rename and renumber storm patches
authorImre Kaloz <kaloz@openwrt.org>
Thu, 5 Jun 2008 17:14:02 +0000 (17:14 +0000)
committerImre Kaloz <kaloz@openwrt.org>
Thu, 5 Jun 2008 17:14:02 +0000 (17:14 +0000)
SVN-Revision: 11368

18 files changed:
target/linux/storm/patches/001-arch.patch [new file with mode: 0644]
target/linux/storm/patches/002-gmac.patch [new file with mode: 0644]
target/linux/storm/patches/003-gmac_one_phy.patch [new file with mode: 0644]
target/linux/storm/patches/004-gmac_enable_napi.patch [new file with mode: 0644]
target/linux/storm/patches/005-gmac_napi_mask_intrs.patch [new file with mode: 0644]
target/linux/storm/patches/006-gmac_napi_tx.patch [new file with mode: 0644]
target/linux/storm/patches/007-mtd.patch [new file with mode: 0644]
target/linux/storm/patches/008-serial.patch [new file with mode: 0644]
target/linux/storm/patches/009-watchdog.patch [new file with mode: 0644]
target/linux/storm/patches/1001-arch.patch [deleted file]
target/linux/storm/patches/1002-gmac.patch [deleted file]
target/linux/storm/patches/1003-gmac_one_phy.patch [deleted file]
target/linux/storm/patches/1004-gmac-enable-napi.patch [deleted file]
target/linux/storm/patches/1005-gmac-napi-mask-intrs.patch [deleted file]
target/linux/storm/patches/1006-gmac-napi-tx.patch [deleted file]
target/linux/storm/patches/1020-mtd.patch [deleted file]
target/linux/storm/patches/1021-serial.patch [deleted file]
target/linux/storm/patches/1022-watchdog.patch [deleted file]

diff --git a/target/linux/storm/patches/001-arch.patch b/target/linux/storm/patches/001-arch.patch
new file mode 100644 (file)
index 0000000..b0461d4
--- /dev/null
@@ -0,0 +1,8864 @@
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -220,6 +220,9 @@
+       help
+         This enables support for the Cirrus EP93xx series of CPUs.
++config ARCH_SL2312
++    bool "SL2312"
++
+ config ARCH_FOOTBRIDGE
+       bool "FootBridge"
+       select FOOTBRIDGE
+@@ -414,6 +417,8 @@
+ source "arch/arm/mach-footbridge/Kconfig"
++source "arch/arm/mach-sl2312/Kconfig"
++
+ source "arch/arm/mach-integrator/Kconfig"
+ source "arch/arm/mach-iop32x/Kconfig"
+@@ -549,6 +554,16 @@
+ config PCI_SYSCALL
+       def_bool PCI
++config SL2312_LPC
++    bool "LPC Host Support"
++    depends on ARCH_SL2312
++    help
++
++config SL2312_LPC_IT8712
++    bool "IT8712 Support"
++    depends on ARCH_SL2312 && SL2312_LPC
++    help
++
+ # Select the host bridge type
+ config PCI_HOST_VIA82C505
+       bool
+@@ -988,6 +1003,10 @@
+ source "drivers/mtd/Kconfig"
+ endif
++if ARCH_SL2312
++source "drivers/telephony/Kconfig"
++endif
++
+ source "drivers/parport/Kconfig"
+ source "drivers/pnp/Kconfig"
+@@ -997,7 +1016,7 @@
+ if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
+       || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
+       || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
+-      || ARCH_IXP23XX
++      || ARCH_IXP23XX || ARCH_SL2312
+ source "drivers/ide/Kconfig"
+ endif
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -72,6 +72,7 @@
+ tune-$(CONFIG_CPU_ARM922T)    :=-mtune=arm9tdmi
+ tune-$(CONFIG_CPU_ARM925T)    :=-mtune=arm9tdmi
+ tune-$(CONFIG_CPU_ARM926T)    :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_FA52X)    :=-mtune=arm9tdmi
+ tune-$(CONFIG_CPU_SA110)      :=-mtune=strongarm110
+ tune-$(CONFIG_CPU_SA1100)     :=-mtune=strongarm1100
+ tune-$(CONFIG_CPU_XSCALE)     :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
+@@ -111,6 +112,7 @@
+  machine-$(CONFIG_ARCH_PXA)      := pxa
+  machine-$(CONFIG_ARCH_L7200)    := l7200
+  machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
++ machine-$(CONFIG_ARCH_SL2312)     := sl2312
+  textofs-$(CONFIG_ARCH_CLPS711X)   := 0x00028000
+  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
+  machine-$(CONFIG_ARCH_IOP32X)           := iop32x
+--- a/arch/arm/boot/compressed/Makefile
++++ b/arch/arm/boot/compressed/Makefile
+@@ -19,6 +19,10 @@
+ OBJS          += head-shark.o ofw-shark.o
+ endif
++ifeq ($(CONFIG_ARCH_SL2312),y)
++OBJS          += head-sl2312.o
++endif
++
+ ifeq ($(CONFIG_ARCH_L7200),y)
+ OBJS          += head-l7200.o
+ endif
+--- /dev/null
++++ b/arch/arm/boot/compressed/head-sl2312.S
+@@ -0,0 +1,6 @@
++#include <asm/mach-types.h>
++#include <asm/arch/sl2312.h>
++
++              .section        ".start", "ax"
++              mov     r7, #MACH_TYPE_SL2312
++
+--- a/arch/arm/boot/compressed/head.S
++++ b/arch/arm/boot/compressed/head.S
+@@ -57,6 +57,17 @@
+               mov     \rb, #0x50000000
+               add     \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
+               .endm
++/*****************************************************
++ *      for Storlink SoC
++ *****************************************************/
++#elif defined(CONFIG_ARCH_SL2312)
++              .macro  loadsp, rb
++              mov     \rb, #0x16000000
++              .endm
++              .macro  writeb, rb
++              strb    \rb, [r3, #0]
++              .endm
++/****************************************************/
+ #else
+               .macro  loadsp, rb
+               addruart \rb
+@@ -116,7 +127,28 @@
+               .rept   8
+               mov     r0, r0
+               .endr
+-
++/*****************************************************************************
++ *  for Storlink Soc -- on chip UART
++ *****************************************************************************/
++#ifndef CONFIG_SERIAL_IT8712          // Jason test
++@                mov     r3, #0x22000000
++                mov     r3, #0x42000000
++                mov     r11, #0x80
++                strb    r11, [r3, #0xc]
++                mov     r11, #0x0
++                strb    r11, [r3, #0x4]
++#ifndef CONFIG_SL3516_ASIC
++                mov     r11, #0x9C            /*0x9c->19200 0x4E->38400 0x34->57600 */
++#else
++              mov     r11, #0x9C              /* 0x61 for 30MHz on GeminiA chip*/
++#endif
++                strb    r11, [r3, #0x0]
++                mov     r11, #0x03
++                strb    r11, [r3, #0xc]
++                      mov     r11, #0xFB
++                strb    r11, [r3, #0x18]
++#endif
++/*****************************************************************************/
+               b       1f
+               .word   0x016f2818              @ Magic numbers to help the loader
+               .word   start                   @ absolute load/run zImage address
+@@ -458,6 +490,39 @@
+               mcr     p15, 0, r0, c7, c5, 4   @ ISB
+               mov     pc, r12
++/*****************************************************************************
++ *  for Storlink Soc -- CPU cache
++ *****************************************************************************/
++__fa526_cache_on:
++                mov     r12, lr
++                bl      __setup_mmu
++                mov     r0, #0
++                mcr     p15, 0, r0, c7, c6, 0   @ Invalidate D cache
++                mcr     p15, 0, r0, c7, c5, 0   @ Invalidate I cache
++                mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
++                mcr     p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
++                mcr     p15, 0, r3, c2, c0, 0   @ load page table pointer
++                mov     r0, #-1
++                mcr     p15, 0, r0, c3, c0, 0   @ load domain access register
++                mrc     p15, 0, r0, c1, c0, 0
++                mov     r0, r0
++                mov     r0, r0
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++        orr     r0, r0, #0x0004                 @ .... .... .... .1..
++#endif
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++        orr     r0, r0, #0x1000                 @ ...1 .... .... ....
++#endif
++
++#ifndef DEBUG
++                orr     r0, r0, #0x0039         @ Write buffer, mmu
++#endif
++                mcr     p15, 0, r0, c1, c0
++                mov     r0, r0
++                mov     r0, r0
++                mov     pc, r12
++/********************************************************************************/
++
+ __arm6_mmu_cache_on:
+               mov     r12, lr
+               bl      __setup_mmu
+@@ -625,6 +690,16 @@
+               @ These match on the architecture ID
++/*****************************************************************************
++ *  for Storlink Soc -- CPU architecture ID
++ *****************************************************************************/
++        .word   0x66015261              @ FA526
++        .word   0xff01fff1
++        b       __fa526_cache_on
++        b       __fa526_cache_off
++        b       __fa526_cache_flush
++/*****************************************************************************/
++
+               .word   0x00020000              @ ARMv4T
+               .word   0x000f0000
+               b       __armv4_mmu_cache_on
+@@ -712,6 +787,23 @@
+               mcr     p15, 0, r0, c8, c7, 0   @ invalidate whole TLB
+               mov     pc, r12
++/*****************************************************************************
++ *  for Storlink Soc -- CPU cache
++ *****************************************************************************/
++__fa526_cache_off:
++        mrc     p15, 0, r0, c1, c0
++        bic     r0, r0, #0x000d
++        mov     r1, #0
++        mcr     p15, 0, r1, c7, c14, 0  @ clean and invalidate D cache
++        mcr     p15, 0, r1, c7, c10, 4  @ drain WB
++        mcr     p15, 0, r0, c1, c0      @ turn MMU and cache off
++        mov     r0, #0
++        mcr     p15, 0, r0, c7, c5, 0   @ invalidate whole cache v4
++        mcr     p15, 0, r0, c8, c7, 0   @ invalidate whole TLB v4
++        mov     pc, lr
++/*****************************************************************************/
++
++
+ __arm6_mmu_cache_off:
+               mov     r0, #0x00000030         @ ARM6 control reg.
+               b       __armv3_mmu_cache_off
+@@ -759,6 +851,17 @@
+               mcr     p15, 0, ip, c7, c10, 4  @ drain WB
+               mov     pc, lr
+               
++/*****************************************************************************
++ *  for Storlink Soc -- CPU cache
++ *****************************************************************************/
++__fa526_cache_flush:
++                mov     r1, #0
++                mcr     p15, 0, r1, c7, c14, 0  @ clean and invalidate D cache
++                mcr     p15, 0, r1, c7, c5, 0   @ flush I cache
++                mcr     p15, 0, r1, c7, c10, 4  @ drain WB
++                mov     pc, lr
++/*****************************************************************************/
++
+ __armv6_mmu_cache_flush:
+               mov     r1, #0
+--- /dev/null
++++ b/arch/arm/boot/compressed/it8712.h
+@@ -0,0 +1,25 @@
++
++#ifndef __IT8712_H__
++#define __IT8712_H__
++
++#include "asm/arch/sl2312.h"
++
++#define IT8712_IO_BASE                        SL2312_LPC_IO_BASE
++//#define IT8712_IO_BASE                      0x27000000
++// Device LDN
++#define LDN_SERIAL1                           0x01
++#define LDN_SERIAL2                           0x02
++#define LDN_PARALLEL                  0x03
++#define LDN_KEYBOARD                  0x05
++#define LDN_MOUSE                             0x06
++#define LDN_GPIO                              0x07
++
++#define IT8712_UART1_PORT             0x3F8
++#define IT8712_UART2_PORT             0x2F8
++
++#define IT8712_GPIO_BASE              0x800   // 0x800-0x804 for GPIO set1-set5
++
++void LPCSetConfig(char LdnNumber, char Index, char data);
++char LPCGetConfig(char LdnNumber, char Index);
++
++#endif
+--- a/arch/arm/boot/compressed/misc.c
++++ b/arch/arm/boot/compressed/misc.c
+@@ -30,7 +30,7 @@
+ #include <asm/arch/uncompress.h>
+ #ifdef CONFIG_DEBUG_ICEDCC
+-
++#include "it8712.h"
+ #ifdef CONFIG_CPU_V6
+ static void icedcc_putc(int ch)
+@@ -69,6 +69,7 @@
+ #define flush()       do { } while (0)
+ #endif
++#if 0
+ static void putstr(const char *ptr)
+ {
+       char c;
+@@ -81,11 +82,36 @@
+       flush();
+ }
++#endif
+ #endif
+ #define __ptr_t void *
++#ifdef CONFIG_SERIAL_IT8712
++unsigned int it8712_uart_base;
++#define UART_RX         0
++#define UART_TX         0
++#define UART_DLL        0
++#define UART_TRG        0
++#define UART_DLM        1
++#define UART_IER        1
++#define UART_FCTR       1
++#define UART_IIR        2
++#define UART_FCR        2
++#define UART_EFR        2
++#define UART_LCR        3
++#define UART_MCR        4
++#define UART_LSR        5
++#define UART_MSR        6
++#define UART_SCR        7
++#define UART_EMSR       7
++void LPCEnterMBPnP(void);
++void LPCExitMBPnP(void);
++int SearchIT8712(void);
++int InitLPCInterface(void);
++#endif
++
+ /*
+  * Optimised C version of memzero for the ARM.
+  */
+@@ -346,6 +372,9 @@
+ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
+                 int arch_id)
+ {
++#ifdef CONFIG_SERIAL_IT8712
++        unsigned char *addr;
++#endif
+       output_data             = (uch *)output_start;  /* Points to kernel start */
+       free_mem_ptr            = free_mem_ptr_p;
+       free_mem_ptr_end        = free_mem_ptr_end_p;
+@@ -353,6 +382,33 @@
+       arch_decomp_setup();
++#ifdef CONFIG_SERIAL_IT8712
++
++        InitLPCInterface();
++        LPCSetConfig(0, 0x02, 0x01);
++        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
++        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
++        it8712_uart_base = IT8712_IO_BASE;
++        it8712_uart_base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
++
++        do {
++        addr = (unsigned char *)(it8712_uart_base + UART_LCR) ;
++        *addr = 0x80;
++        // Set Baud Rate
++        addr = (unsigned char *)(it8712_uart_base+UART_DLL);
++        *addr = 0x06 ;
++        addr = (unsigned char *)(it8712_uart_base+UART_DLM);
++        *addr = 0x00 ;
++
++        addr = (unsigned char *)(it8712_uart_base+UART_LCR);    // LCR
++        *addr = 0x07 ;
++        addr = (unsigned char *)(it8712_uart_base+UART_MCR);    // MCR
++        *addr = 0x08 ;
++        addr = (unsigned char *)(it8712_uart_base+UART_FCR);    // FCR
++        *addr = 0x01 ;
++      } while(0);
++#endif
++
+       makecrc();
+       putstr("Uncompressing Linux...");
+       gunzip();
+@@ -374,4 +430,119 @@
+       return 0;
+ }
+ #endif
++
++#ifdef CONFIG_SERIAL_IT8712
++
++#define LPC_KEY_ADDR    (unsigned char *)(SL2312_LPC_IO_BASE + 0x2e)
++#define LPC_DATA_ADDR   (unsigned char *)(SL2312_LPC_IO_BASE + 0x2f)
++#define LPC_BUS_CTRL                    *( unsigned char*) (SL2312_LPC_HOST_BASE + 0)
++#define LPC_BUS_STATUS                  *( unsigned char*) (SL2312_LPC_HOST_BASE + 2)
++#define LPC_SERIAL_IRQ_CTRL             *( unsigned char*) (SL2312_LPC_HOST_BASE + 4)
++
++char LPCGetConfig(char LdnNumber, char Index)
++{
++        char rtn;
++        unsigned char *addr ;
++
++        LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
++
++        addr = LPC_KEY_ADDR;
++        *addr = 0x07 ;
++
++        addr = LPC_DATA_ADDR;
++        *addr = LdnNumber ;
++
++        addr = LPC_KEY_ADDR;
++        *addr = Index ;
++
++        addr = LPC_DATA_ADDR ;
++        rtn = *addr ;
++
++        LPCExitMBPnP();
++        return rtn;
++
++}
++
++void LPCSetConfig(char LdnNumber, char Index, char data)
++{
++        unsigned char *addr;
++        LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
++        addr = LPC_KEY_ADDR;
++        *addr = 0x07;
++        addr = LPC_DATA_ADDR;
++        *addr = LdnNumber;
++        addr = LPC_KEY_ADDR;
++        *addr = Index;
++        addr = LPC_DATA_ADDR;
++        *addr = data;
++
++        LPCExitMBPnP();
++}
++
++//unsigned char key[4] ;
++void LPCEnterMBPnP(void)
++{
++        unsigned char *addr;
++        addr = LPC_KEY_ADDR;
++        unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
++
++              do {
++              *addr = key[0];
++              *addr = key[1];
++              *addr = key[2];
++              *addr = key[3];
++              }while(0);
++}
++
++void LPCExitMBPnP(void)
++{
++        unsigned char *addr;
++        addr = LPC_KEY_ADDR;
++        *addr = 0x02 ;
++
++        addr = LPC_DATA_ADDR;
++        *addr = 0x02 ;
++}
++
++int InitLPCInterface(void)
++{
++        int i;
++        LPC_BUS_CTRL = 0xc0;
++        LPC_SERIAL_IRQ_CTRL = 0xc0;
++
++        for(i=0;i<0x2000;i++) ;
++
++        LPC_SERIAL_IRQ_CTRL = 0x80;
++        if (!SearchIT8712()) ;
++//                    while(1);
++        return 0;
++}
++
++int SearchIT8712(void)
++{
++        unsigned char Id1, Id2;
++        unsigned short Id;
++        unsigned char *addr;
++
++        LPCEnterMBPnP();
++        addr = LPC_KEY_ADDR;
++        *addr = 0x20 ;
++        addr = LPC_DATA_ADDR;
++        Id1 = *addr ;
++
++        addr = LPC_KEY_ADDR;
++        *addr = 0x21 ;
++        addr = LPC_DATA_ADDR;
++        Id2 = *addr ;
++
++        Id = (Id1 << 8) | Id2;
++        LPCExitMBPnP();
++
++        if (Id == 0x8712)
++                return 1;
++        else
++                return 0;
++}
++
++#endif
+       
+--- a/arch/arm/kernel/entry-armv.S
++++ b/arch/arm/kernel/entry-armv.S
+@@ -18,6 +18,8 @@
+ #include <asm/memory.h>
+ #include <asm/glue.h>
+ #include <asm/vfpmacros.h>
++#include <asm/arch/irqs.h>
++#include <asm/hardware.h>
+ #include <asm/arch/entry-macro.S>
+ #include <asm/thread_notify.h>
+--- a/arch/arm/kernel/irq.c
++++ b/arch/arm/kernel/irq.c
+@@ -40,6 +40,8 @@
+ #include <asm/system.h>
+ #include <asm/mach/time.h>
++extern int fixup_irq(unsigned int irq);
++
+ /*
+  * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
+  */
+@@ -111,8 +113,11 @@
+ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+ {
+       struct pt_regs *old_regs = set_irq_regs(regs);
+-      struct irq_desc *desc = irq_desc + irq;
++//    struct irq_desc *desc = irq_desc + irq;
++      struct irq_desc *desc;
++      irq = fixup_irq(irq);
++      desc = irq_desc + irq;
+       /*
+        * Some hardware gives randomly wrong interrupts.  Rather
+        * than crashing, do something sensible.
+--- a/arch/arm/kernel/process.c
++++ b/arch/arm/kernel/process.c
+@@ -117,7 +117,7 @@
+ void (*pm_idle)(void);
+ EXPORT_SYMBOL(pm_idle);
+-void (*pm_power_off)(void);
++//void (*pm_power_off)(void);
+ EXPORT_SYMBOL(pm_power_off);
+ void (*arm_pm_restart)(char str) = arm_machine_restart;
+@@ -188,13 +188,37 @@
+ void machine_halt(void)
+ {
++      unsigned int reg_v;
++
++      printk("arch_power_off\n");
++
++      reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
++      reg_v &= ~0x00000002;
++      reg_v |= 0x1;
++      mdelay(5);
++      // Power off
++      __raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
++
+ }
+ void machine_power_off(void)
+ {
+-      if (pm_power_off)
++      unsigned int reg_v;
++
++//    if (pm_power_off)
++      if (&pm_power_off!=NULL)
+               pm_power_off();
++
++      printk("arch_power_off\n");
++
++      reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
++      reg_v &= ~0x00000002;
++      reg_v |= 0x1;
++      mdelay(5);
++      // Power off
++      __raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
++
+ }
+ void machine_restart(char * __unused)
+--- a/arch/arm/kernel/time.c
++++ b/arch/arm/kernel/time.c
+@@ -502,8 +502,13 @@
+ device_initcall(timer_init_sysfs);
++extern unsigned int rtc_get_time_second(void);
++
+ void __init time_init(void)
+ {
++#ifdef CONFIG_SL2312_RTC
++      xtime.tv_sec  = rtc_get_time_second() ;
++#endif
+ #ifndef CONFIG_GENERIC_TIME
+       if (system_timer->offset == NULL)
+               system_timer->offset = dummy_gettimeoffset;
+--- /dev/null
++++ b/arch/arm/mach-sl2312/Kconfig
+@@ -0,0 +1,33 @@
++
++menu "SL2312"
++
++config SL3516_ASIC
++      bool "SL3516 ASIC version"
++      depends on ARCH_SL2312
++      help
++        This option to select AISC or FPGA
++config PCI
++       bool "SL2312 PCI"
++       depends on ARCH_SL2312
++       help
++         This option to enable Storlink PCI controller
++
++config SL2312_LPC
++       bool "SL2312 LPC"
++       depends on ARCH_SL2312
++       help
++         This option to enable Low Pin Count controller
++
++config SL2312_USB
++       bool "SL2312 USB"
++       depends on ARCH_SL2312
++       help
++         This option to enable USB OTG host controller
++
++config GEMINI_IPI
++       bool "Gemini IPI test"
++       depends on ARCH_SL2312
++       help
++       Enable this option to test dual cpu Inter-Processor-Interrupt
++endmenu
++
+--- /dev/null
++++ b/arch/arm/mach-sl2312/Makefile
+@@ -0,0 +1,16 @@
++#
++# Makefile for the linux kernel.
++#
++
++# Object file lists.
++
++obj-y                 := arch.o irq.o mm.o time.o sl3516_device.o
++obj-m                 :=
++obj-n                 :=
++
++
++obj-$(CONFIG_PCI) += pci.o
++obj-$(CONFIG_SL2312_LPC) += lpc.o
++obj-$(CONFIG_SL2312_USB) += sl2312-otg.o # sl2312-otg-1.o
++obj-$(CONFIG_GEMINI_XOR_ACCE) += xor.o
++obj-$(CONFIG_GEMINI_IPI)      += gemini_ipi.o
+--- /dev/null
++++ b/arch/arm/mach-sl2312/Makefile.boot
+@@ -0,0 +1,5 @@
++   zreladdr-y := 0x00008000
++params_phys-y := 0x00508100
++#params_phys-y        := 0x00008100
++initrd_phys-y := 0x00800000
++
+--- /dev/null
++++ b/arch/arm/mach-sl2312/arch.c
+@@ -0,0 +1,72 @@
++/*
++ *  linux/arch/arm/mach-epxa10db/arch.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#include <linux/types.h>
++#include <linux/init.h>
++
++#include <asm/hardware.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/mach/time.h>
++#include <asm/mach/arch.h>
++
++extern void sl2312_map_io(void);
++extern void sl2312_init_irq(void);
++extern unsigned long sl2312_gettimeoffset (void);
++extern void __init sl2312_time_init(void);
++
++static struct sys_timer sl2312_timer = {
++      .init           = sl2312_time_init,
++      .offset         = sl2312_gettimeoffset,
++};
++
++static void __init
++sl2312_fixup(struct machine_desc *desc, struct tag *tags,
++                 char **cmdline, struct meminfo *mi)
++{
++        mi->nr_banks      = 1;
++        mi->bank[0].start = 0;
++#ifdef CONFIG_GEMINI_IPI
++        mi->bank[0].size  = (64*1024*1024);  // 128M
++#else
++        mi->bank[0].size  = (128*1024*1024);  // 128M
++#endif
++        mi->bank[0].node  = 0;
++}
++
++/* MACHINE_START(SL2312, "GeminiA")
++      MAINTAINER("Storlink Semi")
++      BOOT_MEM(0x00000000, 0x90000000, 0xf0000000)
++        FIXUP(sl2312_fixup)
++      MAPIO(sl2312_map_io)
++      INITIRQ(sl2312_init_irq)
++      .timer = &sl2312_timer,
++MACHINE_END */
++
++MACHINE_START(SL2312, "GeminiA")
++      /* .phys_ram    = 0x00000000, */
++      .phys_io        = 0x7fffc000,
++      .io_pg_offst    = ((0xffffc000) >> 18) & 0xfffc,
++      .boot_params    = 0x100,
++      .fixup      = sl2312_fixup,
++      .map_io         = sl2312_map_io,
++      .init_irq       = sl2312_init_irq,
++      .timer          = &sl2312_timer,
++MACHINE_END
+--- /dev/null
++++ b/arch/arm/mach-sl2312/gemini_ipi.c
+@@ -0,0 +1,593 @@
++/*
++ * FILE NAME sl_cir.c
++ *
++ * BRIEF MODULE DESCRIPTION
++ *  IPI Driver for CPU1.
++ *
++ *  Author: StorLink, Corp.
++ *          Jason Lee
++ *
++ * Copyright 2002~2006 StorLink, Corp.
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
++ *  WARRANTIES,   INCLUDING, BUT NOT  LIMit8712D  TO, THE IMPLIED WARRANTIES OF
++ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
++ *  NO  EVENT  SHALL   THE AUTHOR  BE LIABLE FOR ANY   DIRECT, INDIRECT,
++ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ *  NOT LIMit8712D   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
++ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
++ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *  You should have received a copy of the  GNU General Public License along
++ *  with this program; if not, writ8712  to the Free Software Foundation, Inc.,
++ *  675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/pagemap.h>
++#include <asm/uaccess.h>
++#include <linux/ioport.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/fs.h>
++#include <linux/interrupt.h>
++#include <asm/io.h>
++#include <asm/delay.h>
++#include <linux/signal.h>
++#include <asm/arch/sl2312.h>
++#include <asm/arch/int_ctrl.h>
++#include <asm/arch/ipi.h>
++#include <linux/dma-mapping.h>
++
++
++#include <linux/mm.h>
++
++#include <linux/bootmem.h>
++
++#include <asm/hardware.h>
++#include <asm/page.h>
++#include <asm/setup.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++
++#include <asm/mach/map.h>
++
++
++static int sl_ipi_debug = 1 ;
++#define DEB(x)  if(sl_ipi_debug>=1) x
++
++#define SRAM_PTR              IO_ADDRESS(SL2312_SRAM_BASE)
++volatile JSCALE_REQ_T *req=(JSCALE_REQ_T*)SRAM_PTR;
++volatile JSCALE_RSP_T *rsp=(JSCALE_RSP_T*)(SRAM_PTR+0x20);
++
++unsigned int jscale_status=0;
++
++#define JSCALE_WAIT   0
++#define XXXXXX_WAIT   1
++#define MAX_WAIT_Q    8
++wait_queue_head_t gemini_ipi_wait[MAX_WAIT_Q];
++
++#define DRAMCTL_DMA_CTL               0X20
++#define DRAMCTL_DMA_SA                0X24
++#define DRAMCTL_DMA_DA                0X28
++#define DRAMCTL_DMA_CNT               0X2C
++#define MEMCPY_UNIT           0x40000
++int hw_memcpy(const void *to, const void *from, unsigned int bytes)
++{
++      unsigned int reg_a,reg_d;
++      int count = bytes,i=0;
++
++      consistent_sync((unsigned int *)to, bytes, DMA_BIDIRECTIONAL);
++      consistent_sync((unsigned int *)from,bytes, DMA_TO_DEVICE);
++
++      DEB(printk("hwmemcpy:count %d\n",count));
++      while(count>0){
++              // SA
++              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_SA;
++              reg_d = (unsigned int )__virt_to_phys(from) + i*MEMCPY_UNIT;
++              DEB(printk("hwmemcpy:from 0x%08x\n",reg_d));
++              writel(reg_d,reg_a);
++              // DA
++              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_DA;
++              reg_d = (unsigned int )__virt_to_phys(to) + i*MEMCPY_UNIT;
++              writel(reg_d,reg_a);
++              DEB(printk("hwmemcpy:to 0x%08x\n",reg_d));
++              // byte count
++              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CNT;
++              reg_d = (count>=MEMCPY_UNIT)?MEMCPY_UNIT:count;
++              writel(reg_d,reg_a);
++              // start DMA
++              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL;
++              writel(0x80000001,reg_a);
++
++              do{
++                      cond_resched();
++//                    msleep(4);
++                      reg_d = readl(IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL);
++              }while(reg_d&0x1);
++
++              count -= MEMCPY_UNIT;
++              i++;
++      }
++
++      return bytes;
++}
++
++static irqreturn_t ipi_interrupt()
++{
++      unsigned int id=getcpuid(),tmp;
++
++      //dmac_inv_range(__phys_to_virt(SL2312_SRAM_BASE),__phys_to_virt(SHAREADDR)+0x2000);
++
++
++      // Clear Interrupt
++      if(id==CPU0) {
++              tmp = readl(CPU1_STATUS);
++              tmp &= ~CPU_IPI_BIT_MASK;
++              writel(tmp,CPU1_STATUS);
++      }
++      else{
++              tmp = readl(CPU0_STATUS);
++              tmp &= ~CPU_IPI_BIT_MASK;
++              writel(tmp,CPU0_STATUS);
++      }
++
++      //
++      DEB(printk("ipi interrupt:0x%x\n",rsp->status));
++      switch(rsp->status){
++              case JSCALE_STATUS_OK:
++
++                      break;
++              case JSCALE_UNKNOWN_MSG_TYPE:
++
++                      break;
++              case JSCALE_FAILED_FILE_SIZE:
++
++                      break;
++              case JSCALE_FAILED_MALLOC:
++
++                      break;
++              case JSCALE_FAILED_FORMAT:
++
++                      break;
++              case JSCALE_DECODE_ERROR:
++
++                      break;
++
++      }
++      jscale_status = rsp->status;
++//    wake_up(&gemini_ipi_wait[JSCALE_WAIT]);
++
++      return IRQ_HANDLED;
++}
++
++static int gemini_ipi_open(struct inode *inode, struct file *file)
++{
++      DEB(printk("ipi open\n"));
++      return 0;
++}
++
++
++static int gemini_ipi_release(struct inode *inode, struct file *file)
++{
++      DEB(printk("ipi release\n"));
++      return 0;
++}
++
++
++static int gemini_ipi_ioctl(struct inode *inode, struct file *file,
++      unsigned int cmd, unsigned long arg)
++{
++      JSCALE_RSP_T tmp;
++
++      switch(cmd) {
++              case GEMINI_IPI_JSCALE_REQ:
++                      DEB(printk("ipi:ioctl jscale request %dX%d Q:%d\n",req->ScaledImageWidth,req->ScaledImageHeight,req->ScaledImageQuality));
++                      if (copy_from_user(req, (JSCALE_REQ_T *)arg, sizeof(JSCALE_REQ_T)))
++                              return -EFAULT;
++                      req->hdr.type = IPC_JSCALE_REQ_MSG;
++                      req->hdr.length = sizeof(JSCALE_REQ_T);
++                      req->input_location  = CPU_1_DATA_OFFSET;
++                      req->output_location = CPU_1_DATA_OFFSET;
++                      break;
++              case GEMINI_IPI_JSCALE_STAT:
++                      DEB(printk("ipi:ioctl jscale stat \n"));
++                      if(jscale_status==JSCALE_BUSY){                                         // not yet
++                              tmp.status = JSCALE_BUSY;
++                              if (copy_to_user((JSCALE_RSP_T *)arg,&tmp, sizeof(JSCALE_RSP_T)))
++                                      return -EFAULT;
++                      }
++                      else{                                                                                           // finish or error
++                              if (copy_to_user((JSCALE_RSP_T *)arg,rsp, sizeof(JSCALE_RSP_T)))
++                                      return -EFAULT;
++                      }
++                      break;
++              default:
++                      printk("IPI: Error IOCTL number\n");
++                      return -ENOIOCTLCMD;
++      }
++
++      return 0;
++}
++
++#define SRAM_SIZE     0x2000
++static ssize_t gemini_ipi_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos)
++{
++      int i=0,tmp=0,j;
++      const char *ptr=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
++      DEB(printk("ipi:write 0x%x to 0x%x length:%d\n",&buf,ptr,count));
++      memcpy(ptr,buf,count);
++      consistent_sync(ptr,count, DMA_TO_DEVICE);
++      //hw_memcpy(ptr,&buf,count);
++
++/*    if(count>SRAM_SIZE){
++              for(i=0;i<(count/SRAM_SIZE);i++)
++                      raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,SRAM_SIZE);
++              if(count%SRAM_SIZE)
++                      raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,count%SRAM_SIZE);
++      }
++      else
++              raid_memcpy(ptr,buf,count);
++*/
++
++/*    for(i=0;i<count;i++){
++              if(buf[i]!=ptr[i])
++                      printk("ipi error:offset %d valud %x[should %x]\n",i,ptr[i],buf[i]);
++      }
++
++      printk("===========input buf===============\n");
++      for(i=0;i<64;i+=16){
++              for(j=0;j<16;j++)
++                      printk("%02x ",buf[i+j]);
++              printk("\n");
++              cond_resched();
++      }
++      printk("===========output buf==============\n");
++      for(i=0;i<64;i+=16){
++              for(j=0;j<16;j++)
++                      printk("%02x ",ptr[i+j]);
++              printk("\n");
++              cond_resched();
++      }
++*/
++      // send irq for CPU1
++      tmp |= CPU_IPI_BIT_MASK;
++      writel(tmp,CPU0_STATUS);
++      jscale_status = JSCALE_BUSY;
++
++      return count;
++}
++
++static ssize_t gemini_ipi_read(struct file * file_p, char *buf, size_t length, loff_t * ppos)
++{
++      int i=0;
++      const char *ptr=(unsigned int )__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
++
++      consistent_sync(ptr,length, DMA_FROM_DEVICE);
++      memcpy(buf,ptr,length);
++      DEB(printk("ipi:read 0x%x to 0x%x length:%d\n",ptr,buf,length));
++
++      //consistent_sync((unsigned int *)ptr,0x2000, DMA_FROM_DEVICE);         // invalid
++      //hw_memcpy(buf,ptr,length);
++
++      // need encoded file size ********
++/*    if(count>SRAM_SIZE){
++              for(i=0;i<(count/SRAM_SIZE);i++)
++                      raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,SRAM_SIZE);
++              if(count%0xFFFF)
++                      raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,length%SRAM_SIZE);
++      }
++      else
++              raid_memcpy(buf,p_mbox->message,length);
++*/
++      return length;
++}
++
++void do_mapping_read(struct address_space *mapping,
++                           struct file_ra_state *_ra,
++                           struct file *filp,
++                           loff_t *ppos,
++                           read_descriptor_t *desc,
++                           read_actor_t actor)
++{
++      struct inode *inode = mapping->host;
++      unsigned long index;
++      unsigned long end_index;
++      unsigned long offset;
++      unsigned long last_index;
++      unsigned long next_index;
++      unsigned long prev_index;
++      loff_t isize;
++      struct page *cached_page;
++      int error;
++      struct file_ra_state ra = *_ra;
++
++      cached_page = NULL;
++      index = *ppos >> PAGE_CACHE_SHIFT;
++      next_index = index;
++      prev_index = ra.prev_page;
++      last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
++      offset = *ppos & ~PAGE_CACHE_MASK;
++
++      isize = i_size_read(inode);
++      if (!isize)
++              goto out;
++
++      end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
++      for (;;) {
++              struct page *page;
++              unsigned long nr, ret;
++
++              /* nr is the maximum number of bytes to copy from this page */
++              nr = PAGE_CACHE_SIZE;
++              if (index >= end_index) {
++                      if (index > end_index)
++                              goto out;
++                      nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
++                      if (nr <= offset) {
++                              goto out;
++                      }
++              }
++              nr = nr - offset;
++
++              cond_resched();
++              if (index == next_index)
++                      next_index = page_cache_readahead(mapping, &ra, filp,
++                                      index, last_index - index);
++
++find_page:
++              page = find_get_page(mapping, index);
++              if (unlikely(page == NULL)) {
++                      handle_ra_miss(mapping, &ra, index);
++                      goto no_cached_page;
++              }
++              if (!PageUptodate(page))
++                      goto page_not_up_to_date;
++page_ok:
++
++              /* If users can be writing to this page using arbitrary
++               * virtual addresses, take care about potential aliasing
++               * before reading the page on the kernel side.
++               */
++              if (mapping_writably_mapped(mapping))
++                      flush_dcache_page(page);
++
++              /*
++               * When (part of) the same page is read multiple times
++               * in succession, only mark it as accessed the first time.
++               */
++              if (prev_index != index)
++                      mark_page_accessed(page);
++              prev_index = index;
++
++              /*
++               * Ok, we have the page, and it's up-to-date, so
++               * now we can copy it to user space...
++               *
++               * The actor routine returns how many bytes were actually used..
++               * NOTE! This may not be the same as how much of a user buffer
++               * we filled up (we may be padding etc), so we can only update
++               * "pos" here (the actor routine has to update the user buffer
++               * pointers and the remaining count).
++               */
++              ret = actor(desc, page, offset, nr);
++              offset += ret;
++              index += offset >> PAGE_CACHE_SHIFT;
++              offset &= ~PAGE_CACHE_MASK;
++
++              page_cache_release(page);
++              if (ret == nr && desc->count)
++                      continue;
++              goto out;
++
++page_not_up_to_date:
++              /* Get exclusive access to the page ... */
++              lock_page(page);
++
++              /* Did it get unhashed before we got the lock? */
++              if (!page->mapping) {
++                      unlock_page(page);
++                      page_cache_release(page);
++                      continue;
++              }
++
++              /* Did somebody else fill it already? */
++              if (PageUptodate(page)) {
++                      unlock_page(page);
++                      goto page_ok;
++              }
++
++readpage:
++              /* Start the actual read. The read will unlock the page. */
++              error = mapping->a_ops->readpage(filp, page);
++
++              if (unlikely(error))
++                      goto readpage_error;
++
++              if (!PageUptodate(page)) {
++                      lock_page(page);
++                      if (!PageUptodate(page)) {
++                              if (page->mapping == NULL) {
++                                      /*
++                                       * invalidate_inode_pages got it
++                                       */
++                                      unlock_page(page);
++                                      page_cache_release(page);
++                                      goto find_page;
++                              }
++                              unlock_page(page);
++                              error = -EIO;
++                              goto readpage_error;
++                      }
++                      unlock_page(page);
++              }
++
++              /*
++               * i_size must be checked after we have done ->readpage.
++               *
++               * Checking i_size after the readpage allows us to calculate
++               * the correct value for "nr", which means the zero-filled
++               * part of the page is not copied back to userspace (unless
++               * another truncate extends the file - this is desired though).
++               */
++              isize = i_size_read(inode);
++              end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
++              if (unlikely(!isize || index > end_index)) {
++                      page_cache_release(page);
++                      goto out;
++              }
++
++              /* nr is the maximum number of bytes to copy from this page */
++              nr = PAGE_CACHE_SIZE;
++              if (index == end_index) {
++                      nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
++                      if (nr <= offset) {
++                              page_cache_release(page);
++                              goto out;
++                      }
++              }
++              nr = nr - offset;
++              goto page_ok;
++
++readpage_error:
++              /* UHHUH! A synchronous read error occurred. Report it */
++              desc->error = error;
++              page_cache_release(page);
++              goto out;
++
++no_cached_page:
++              /*
++               * Ok, it wasn't cached, so we need to create a new
++               * page..
++               */
++              if (!cached_page) {
++                      cached_page = page_cache_alloc_cold(mapping);
++                      if (!cached_page) {
++                              desc->error = -ENOMEM;
++                              goto out;
++                      }
++              }
++              error = add_to_page_cache_lru(cached_page, mapping,
++                                              index, GFP_KERNEL);
++              if (error) {
++                      if (error == -EEXIST)
++                              goto find_page;
++                      desc->error = error;
++                      goto out;
++              }
++              page = cached_page;
++              cached_page = NULL;
++              goto readpage;
++      }
++
++out:
++      *_ra = ra;
++
++      *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
++      if (cached_page)
++              page_cache_release(cached_page);
++      if (filp)
++              file_accessed(filp);
++}
++
++int ipi_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
++{
++      ssize_t written;
++      unsigned long count = desc->count;
++      struct file *file = desc->arg.data;
++      unsigned int *ptr_to=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET) + desc->written;
++      void *ptr_from;
++
++      if (size > count)
++              size = count;
++
++      ptr_from = page_address(page)+offset;
++      written = memcpy(ptr_to,ptr_from,size);
++
++      if (written < 0) {
++              desc->error = written;
++              written = 0;
++      }
++      desc->count = count - written;
++      desc->written += written;
++      return written;
++}
++
++ssize_t gemini_ipi_sendfile(struct file *in_file, loff_t *ppos,
++                       size_t count, read_actor_t actor, void *TARGET)
++{
++      read_descriptor_t desc;
++
++      if (!count)
++              return 0;
++
++      desc.written = 0;
++      desc.count = count;
++      desc.arg.data = TARGET;
++      desc.error = 0;
++
++      do_mapping_read(in_file->f_mapping,&in_file->f_ra,in_file, ppos, &desc, ipi_send_actor);
++
++      if (desc.written)
++              return desc.written;
++      return desc.error;
++}
++static struct file_operations gemini_ipi_fops = {
++      .owner  =       THIS_MODULE,
++      .ioctl  =       gemini_ipi_ioctl,
++      .open   =       gemini_ipi_open,
++      .release=       gemini_ipi_release,
++      .write  =       gemini_ipi_write,
++      .read   =       gemini_ipi_read,
++      .sendfile = gemini_ipi_sendfile,
++};
++
++#ifndef STORLINK_IPI
++#define STORLINK_IPI  242             // Documents/devices.txt suggest to use 240~255 for local driver!!
++#endif
++
++static struct miscdevice gemini_ipi_miscdev =
++{
++      STORLINK_IPI,
++      "slave_ipc",
++      &gemini_ipi_fops
++};
++
++int __init sl_ipi_init(void)
++{
++
++      printk("Gemini IPI Driver Initialization...\n");
++      printk("REQ Head :0x%x(phy:0x%x)\n",(unsigned int)req,(unsigned int)SL2312_SRAM_BASE);
++      printk("RSP Head :0x%x(phy:0x%x)\n",(unsigned int)rsp,(unsigned int)SL2312_SRAM_BASE+0x20);
++      printk("Data buff:0x%x(phy:0x%x)\n",__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET),CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
++
++      misc_register(&gemini_ipi_miscdev);
++
++      if (request_irq(IRQ_CPU0_IP_IRQ_OFFSET, ipi_interrupt, SA_INTERRUPT, "ipi", NULL))
++              printk("Error: Register IRQ for Storlink IPI failed\n");
++
++      return 0;
++}
++
++void __exit sl_ipi_exit(void)
++{
++
++}
++
++module_init(sl_ipi_init);
++module_exit(sl_ipi_exit);
++
++MODULE_AUTHOR("Jason Lee <jason@storlink.com.tw>");
++MODULE_DESCRIPTION("Storlink IPI driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/arch/arm/mach-sl2312/hw_xor.h
+@@ -0,0 +1,573 @@
++/*
++*  linux/include/asm-arm/xor.h
++*
++*  Copyright (C) 2001 Storlink Semi.
++*     Jason Lee <jason@storlink.com.tw>
++*
++*/
++#include <asm/arch/sl2312.h>
++#include <asm/io.h>
++//#include <linux/compatmac.h>
++
++#undef BIG_ENDIAN
++#define CPU           0
++#define DMA           1
++
++#define DESC_NO       8
++#define TX_DESC_NUM           DESC_NO
++#define RX_DESC_NUM           DESC_NO
++
++#define RAID_BASE_ADDR        IO_ADDRESS(SL2312_RAID_BASE)
++
++#define SRAM_PAR_0k           0
++#define SRAM_PAR_4k           1
++#define SRAM_PAR_8k           2
++#define SRAM_PAR_16k          3
++#define SRAM_PAR_SIZE SRAM_PAR_8k
++
++#define RUNNING               0x1
++#define COMPLETE      0x2
++#define ERROR                 0x4
++
++#define CMD_XOR               0x0
++#define CMD_FILL      0x1
++#define CMD_CPY               0x3
++#define CMD_CHK               0x4
++
++enum RAID_DMA_REGISTER {
++      RAID_DMA_DEVICE_ID              = 0xff00,
++      RAID_DMA_STATUS                 = 0xff04,
++      RAID_FCHDMA_CTRL                = 0xff08,
++      RAID_FCHDMA_FIRST_DESC  = 0xff0C,
++      RAID_FCHDMA_CURR_DESC   = 0xff10,
++      RAID_STRDMA_CTRL                = 0xff14,
++      RAID_STRDMA_FIRST_DESC  = 0xff18,
++      RAID_STRDMA_CURR_DESC   = 0xff1C,
++      RAID_TX_FLG_REG                 = 0xff24,
++      RAID_RX_FLG_REG                 = 0xff34,
++      RAID_PCR                                = 0xff50,
++      SMC_CMD_REG                             = 0xff60,
++      SMC_STATUS_REG                  = 0xff64
++      };
++
++enum RAID_FUNC_MODE {
++      RAID_XOR                        = 0,
++      RAID_MIX                        = 2,
++      RAID_SRAM                       = 3,
++      RAID_ENDIAN                     = 4,
++      RAID_MEM_BLK            = 5,
++      RAID_MEM2MEM            = 7,
++      RAID_BUF_SIZE           = 8,
++      RAID_ERR_TEST           = 9,
++      RAID_BURST                      = 10,
++      RAID_BUS                        = 11
++      };
++
++typedef struct reg_info {
++      int mask;
++      char err[32];
++      int offset;
++} REG_INFO;
++
++/********************************************************/
++/*    the definition of RAID DMA Module Register      */
++/********************************************************/
++typedef union
++{
++      unsigned int bit32;
++      struct bits_ff00
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int                            : 8;
++              unsigned int teytPerr           : 4; /* define protocol error under tsPErrI*/
++              unsigned int reytPerr           : 14; /* define protocol error under rsPErrI */
++              unsigned int device_id          : 12;
++              unsigned int revision_id        : 4;
++              #else
++              unsigned int revision_id        : 4;
++              unsigned int device_id          : 12;
++              unsigned int reytPerr           : 14; /* define protocol error under rsPErrI */
++              unsigned int teytPerr           : 4; /* define protocol error under tsPErrI*/
++              unsigned int                            : 8;
++              #endif
++      } bits;
++} RAID_DMA_DEVICE_ID_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff04
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int tsFinishI          : 1; /* owner bit error interrupt */
++              unsigned int tsDErrI            : 1; /* AHB bus error interrupt */
++              unsigned int tsPErrI            : 1; /* RAID XOR fetch descriptor protocol error interrupt */
++              unsigned int tsEODI                     : 1; /* RAID XOR fetch DMA end of descriptor interrupt */
++              unsigned int tsEOFI                     : 1; /* RAID XOR fetch DMA end of frame interrupt */
++              unsigned int rsFinishI          : 1; /* owner bit error interrupt */
++              unsigned int rsDErrI            : 1; /* AHB bus error while RAID XOR store interrupt */
++              unsigned int rsPErrI            : 1; /* RAID XOR store descriptor protocol error interrupt */
++              unsigned int rsEODI                     : 1; /* RAID XOR store DMA end of descriptor interrupt */
++              unsigned int rsEOFI                     : 1; /* RAID XOR store DMA end of frame interrupt */
++              unsigned int inter                      : 8; /* pattern check error interrupt */
++              unsigned int                            : 5;
++              unsigned int Loopback           : 1; /* loopback */
++              unsigned int intEnable          : 8; /*pattern check error interrupt enable */
++              #else
++              unsigned int intEnable          : 8; /*pattern check error interrupt enable */
++              unsigned int Loopback           : 1; /* loopback */
++              unsigned int                            : 5;
++              unsigned int inter                      : 8; /* pattern check error interrupt */
++              unsigned int rsEOFI                     : 1; /* RAID XOR store DMA end of frame interrupt */
++              unsigned int rsEODI                     : 1; /* RAID XOR store DMA end of descriptor interrupt */
++              unsigned int rsPErrI            : 1; /* RAID XOR store descriptor protocol error interrupt */
++              unsigned int rsDErrI            : 1; /* AHB bus error while RAID XOR store interrupt */
++              unsigned int rsFinishI          : 1; /* owner bit error interrupt */
++              unsigned int tsEOFI                     : 1; /* RAID XOR fetch DMA end of frame interrupt */
++              unsigned int tsEODI                     : 1; /* RAID XOR fetch DMA end of descriptor interrupt */
++              unsigned int tsPErrI            : 1; /* RAID XOR fetch descriptor protocol error interrupt */
++              unsigned int tsDErrI            : 1; /* AHB bus error interrupt */
++              unsigned int tsFinishI          : 1; /* owner bit error interrupt */
++              #endif
++      } bits;
++} RAID_DMA_STATUS_T;
++
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff08
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int td_start           :  1;   /* Start DMA transfer */
++              unsigned int td_continue        :  1;   /* Continue DMA operation */
++              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int                            :  1;
++              unsigned int td_prot            :  4;   /* DMA protection control */
++              unsigned int td_burst_size  :  2;       /* DMA max burst size for every AHB request */
++              unsigned int td_bus                 :  2;       /* peripheral bus width */
++              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int                            : 14;
++              #else
++              unsigned int                            : 14;
++              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int td_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
++              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
++              unsigned int td_prot            :  4;   /* TxDMA protection control */
++              unsigned int                            :  1;
++              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int td_continue        :  1;   /* Continue DMA operation */
++              unsigned int td_start           :  1;   /* Start DMA transfer */
++              #endif
++      } bits;
++} RAID_TXDMA_CTRL_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff0c
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
++              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
++              unsigned int                                    :  3;
++              #else
++              unsigned int                                    :  3;
++              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
++              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
++              #endif
++      } bits;
++} RAID_TXDMA_FIRST_DESC_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff10
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int                            :  1;
++              unsigned int sof_eof            :  2;
++              #else
++              unsigned int sof_eof            :  2;
++              unsigned int                            :  1;
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              #endif
++      } bits;
++} RAID_TXDMA_CURR_DESC_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff14
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int rd_start           :  1;   /* Start DMA transfer */
++              unsigned int rd_continue        :  1;   /* Continue DMA operation */
++              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int                            :  1;
++              unsigned int rd_prot            :  4;   /* DMA protection control */
++              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
++              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
++              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int                            : 14;
++              #else
++              unsigned int                            : 14;
++              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
++              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
++              unsigned int rd_prot            :  4;   /* DMA protection control */
++              unsigned int                            :  1;
++              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int rd_continue        :  1;   /* Continue DMA operation */
++              unsigned int rd_start           :  1;   /* Start DMA transfer */
++              #endif
++      } bits;
++} RAID_RXDMA_CTRL_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff18
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
++              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
++              unsigned int                                    :  3;
++              #else
++              unsigned int                                    :  3;
++              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
++              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
++              #endif
++      } bits;
++} RAID_RXDMA_FIRST_DESC_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff1c
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
++              unsigned int sof_eof            :  2;
++              #else
++              unsigned int sof_eof            :  2;
++              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              #endif
++      } bits;
++} RAID_RXDMA_CURR_DESC_T;
++
++typedef union
++{
++      unsigned int bit32;
++      struct bits_ff50
++      {
++              unsigned int pat                        : 32; /* data for pattern check */
++      } bits;
++} RAID_PACR_T;
++
++/******************************************************/
++/*    the definition of DMA Descriptor Register     */
++/******************************************************/
++typedef struct raid_descriptor_t
++{
++      union func_ctrl_t
++      {
++              unsigned int bit32;
++              struct bits_0000
++              {
++                      #ifdef BIG_ENDIAN
++                      unsigned int own                                : 1; /* owner bit */
++                      unsigned int derr                               : 1;    /* data error during processing this descriptor */
++                      unsigned int perr                               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int raid_ctrl_status   : 7; /* pass RAID XOR fetch/store control status to CPU */
++                      unsigned int desc_cnt                   : 6;
++                      unsigned int buffer_size                : 16;   /* transfer buffer size associated with current description*/
++                      #else
++                      unsigned int buffer_size                : 16;   /* transfer buffer size associated with current description*/
++                      unsigned int desc_cnt                   : 6;
++                      unsigned int raid_ctrl_status   : 7; /* pass RAID XOR fetch/store control status to CPU */
++                      unsigned int perr                               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int derr                               : 1;    /* data error during processing this descriptor */
++                      unsigned int own                                : 1; /* owner bit */
++                      #endif
++              } bits;
++      } func_ctrl;
++
++      union flg_status_t
++      {
++              unsigned int bits32;
++              struct bit_004
++              {
++                      #ifdef BIG_ENDIAN
++                      unsigned int bcc                : 16;
++                      unsigned int                    : 13
++                      unsigned int mode               : 3;
++                      #else
++                      unsigned int mode               : 3;
++                      unsigned int                    : 13;
++                      unsigned int bcc                : 16;
++                      #endif
++              } bits_cmd_status;
++      } flg_status;  //Sanders
++
++      unsigned int buf_addr;
++
++      union next_desc_addr_t
++      {
++              unsigned int bits32;
++              struct bits_000c
++              {
++                      #ifdef BIG_ENDIAN
++                      unsigned int ndar               : 28; /* next descriptor address */
++                      unsigned int eofie              : 1; /* end of frame interrupt enable */
++                      unsigned int                    : 1;
++                      unsigned int sof_eof    : 2; /* the position of the descriptor in chain */
++                      #else
++                      unsigned int sof_eof    : 2; /* the position of the descriptor in chain */
++                      unsigned int                    : 1;
++                      unsigned int eofie              : 1; /* end of frame interrupt enable */
++                      unsigned int ndar               : 28; /* next descriptor address */
++                      #endif
++              } bits;
++      } next_desc_addr;
++} RAID_DESCRIPTOR_T;
++
++/******************************************************/
++/*    the offset of RAID SMC register               */
++/******************************************************/
++enum RAID_SMC_REGISTER {
++      RAID_SMC_CMD_REG                = 0xff60,
++      RAID_SMC_STATUS_REG             = 0xff64
++      };
++
++/******************************************************/
++/*    the definition of RAID SMC module register    */
++/******************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff60
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int pat_mode           : 2; /* partition mode selection */
++              unsigned int                            : 14;
++              unsigned int device_id          : 12;
++              unsigned int revision_id        : 4;
++              #else
++              unsigned int revision_id        : 4;
++              unsigned int device_id          : 12;
++              unsigned int                            : 14;
++              unsigned int pat_mode           : 2; /* partition mode selection */
++              #endif
++      } bits;
++} RAID_SMC_CMD;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bits_ff64
++      {
++              #ifdef BIG_ENDIAN
++              unsigned int addr_err1          : 1; /* address is out of range for controller 1 */
++              unsigned int ahb_err1           : 1; /* AHB bus error for controller 1 */
++              unsigned int                            : 14;
++              unsigned int addr_err2          : 1;    /* address is out of range for controller 2 */
++              unsigned int ahb_err2           : 1; /* AHB bus error for controller 2 */
++              unsigned int                            : 14;
++              #else
++              unsigned int                            : 14;
++              unsigned int ahb_err2           : 1; /* AHB bus error for controller 2 */
++              unsigned int addr_err2          : 1;    /* address is out of range for controller 2 */
++              unsigned int                            : 14;
++              unsigned int ahb_err1           : 1; /* AHB bus error for controller 1 */
++              unsigned int addr_err1          : 1; /* address is out of range for controller 1 */
++              #endif
++      } bits;
++} RAID_SMC_STATUS;
++
++typedef struct RAID_S
++{
++      const char *device_name;
++      wait_queue_head_t wait;
++      unsigned int busy;
++      int irq;
++      unsigned int status;
++      RAID_DESCRIPTOR_T *tx_desc;  /*   point to virtual TX descriptor address */
++      RAID_DESCRIPTOR_T *rx_desc;  /* point ot virtual RX descriptor address */
++      RAID_DESCRIPTOR_T *tx_cur_desc; /* current TX descriptor */
++      RAID_DESCRIPTOR_T *rx_cur_desc; /* current RX descriptor */
++      RAID_DESCRIPTOR_T *tx_finished_desc;
++      RAID_DESCRIPTOR_T *rx_finished_desc;
++      RAID_DESCRIPTOR_T *tx_first_desc;
++      RAID_DESCRIPTOR_T *rx_first_desc;
++
++//    unsigned int *tx_buf[TX_DESC_NUM];
++      unsigned int *rx_desc_dma;                      // physical address of rx_descript
++      unsigned int *tx_desc_dma;                      // physical address of tx_descript
++      unsigned int *rx_bufs_dma;
++      unsigned int *tx_bufs_dma;
++
++} RAID_T;
++
++struct reg_ioctl
++{
++      unsigned int reg_addr;
++      unsigned int val_in;
++      unsigned int val_out;
++};
++
++typedef struct dma_ctrl {
++      int sram;
++      int prot;
++      int burst;
++      int bus;
++      int endian;
++      int mode;
++} DMA_CTRL;
++
++
++#ifdef XOR_SW_FILL_IN
++
++#define __XOR(a1, a2) a1 ^= a2
++
++#define GET_BLOCK_2(dst) \
++      __asm__("ldmia  %0, {%1, %2}" \
++              : "=r" (dst), "=r" (a1), "=r" (a2) \
++              : "0" (dst))
++
++#define GET_BLOCK_4(dst) \
++      __asm__("ldmia  %0, {%1, %2, %3, %4}" \
++              : "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \
++              : "0" (dst))
++
++#define XOR_BLOCK_2(src) \
++      __asm__("ldmia  %0!, {%1, %2}" \
++              : "=r" (src), "=r" (b1), "=r" (b2) \
++              : "0" (src)); \
++      __XOR(a1, b1); __XOR(a2, b2);
++
++#define XOR_BLOCK_4(src) \
++      __asm__("ldmia  %0!, {%1, %2, %3, %4}" \
++              : "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \
++              : "0" (src)); \
++      __XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4)
++
++#define PUT_BLOCK_2(dst) \
++      __asm__ __volatile__("stmia     %0!, {%2, %3}" \
++              : "=r" (dst) \
++              : "0" (dst), "r" (a1), "r" (a2))
++
++#define PUT_BLOCK_4(dst) \
++      __asm__ __volatile__("stmia     %0!, {%2, %3, %4, %5}" \
++              : "=r" (dst) \
++              : "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4))
++
++static void
++xor_arm4regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++      unsigned int lines = bytes / sizeof(unsigned long) / 4;
++      register unsigned int a1 __asm__("r4");
++      register unsigned int a2 __asm__("r5");
++      register unsigned int a3 __asm__("r6");
++      register unsigned int a4 __asm__("r7");
++      register unsigned int b1 __asm__("r8");
++      register unsigned int b2 __asm__("r9");
++      register unsigned int b3 __asm__("ip");
++      register unsigned int b4 __asm__("lr");
++
++      do {
++              GET_BLOCK_4(p1);
++              XOR_BLOCK_4(p2);
++              PUT_BLOCK_4(p1);
++      } while (--lines);
++}
++
++static void
++xor_arm4regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++              unsigned long *p3)
++{
++      unsigned int lines = bytes / sizeof(unsigned long) / 4;
++      register unsigned int a1 __asm__("r4");
++      register unsigned int a2 __asm__("r5");
++      register unsigned int a3 __asm__("r6");
++      register unsigned int a4 __asm__("r7");
++      register unsigned int b1 __asm__("r8");
++      register unsigned int b2 __asm__("r9");
++      register unsigned int b3 __asm__("ip");
++      register unsigned int b4 __asm__("lr");
++
++      do {
++              GET_BLOCK_4(p1);
++              XOR_BLOCK_4(p2);
++              XOR_BLOCK_4(p3);
++              PUT_BLOCK_4(p1);
++      } while (--lines);
++}
++
++static void
++xor_arm4regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++              unsigned long *p3, unsigned long *p4)
++{
++      unsigned int lines = bytes / sizeof(unsigned long) / 2;
++      register unsigned int a1 __asm__("r8");
++      register unsigned int a2 __asm__("r9");
++      register unsigned int b1 __asm__("ip");
++      register unsigned int b2 __asm__("lr");
++
++      do {
++              GET_BLOCK_2(p1);
++              XOR_BLOCK_2(p2);
++              XOR_BLOCK_2(p3);
++              XOR_BLOCK_2(p4);
++              PUT_BLOCK_2(p1);
++      } while (--lines);
++}
++
++static void
++xor_arm4regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++              unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++      unsigned int lines = bytes / sizeof(unsigned long) / 2;
++      register unsigned int a1 __asm__("r8");
++      register unsigned int a2 __asm__("r9");
++      register unsigned int b1 __asm__("ip");
++      register unsigned int b2 __asm__("lr");
++
++      do {
++              GET_BLOCK_2(p1);
++              XOR_BLOCK_2(p2);
++              XOR_BLOCK_2(p3);
++              XOR_BLOCK_2(p4);
++              XOR_BLOCK_2(p5);
++              PUT_BLOCK_2(p1);
++      } while (--lines);
++}
++#endif        //XOR_SW_FILL_IN
++
+--- /dev/null
++++ b/arch/arm/mach-sl2312/irq.c
+@@ -0,0 +1,202 @@
++/*
++ *  linux/arch/arm/mach-epxa10db/irq.c
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/stddef.h>
++#include <linux/list.h>
++#include <linux/sched.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/mach/irq.h>
++#include <asm/arch/platform.h>
++#include <asm/arch/int_ctrl.h>
++
++#ifdef CONFIG_PCI
++#include <asm/arch/pci.h>
++#endif
++
++int fixup_irq(unsigned int irq)
++{
++#ifdef CONFIG_PCI
++      if (irq == IRQ_PCI) {
++              return sl2312_pci_get_int_src();
++      }
++#endif
++      return irq;
++}
++
++static void sl2312_ack_irq(unsigned int irq)
++{
++   __raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++}
++
++static void sl2312_mask_irq(unsigned int irq)
++{
++      unsigned int mask;
++
++#ifdef CONFIG_PCI
++      if (irq >= PCI_IRQ_OFFSET)
++      {
++              mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++              mask &= ~IRQ_PCI_MASK ;
++              __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++              sl2312_pci_mask_irq(irq - PCI_IRQ_OFFSET);
++      }
++      else
++#endif
++      if(irq >= FIQ_OFFSET)
++      {
++           mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++           mask &= ~(1 << (irq - FIQ_OFFSET));
++           __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        }
++        else
++        {
++           mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++           mask &= ~(1 << irq);
++           __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        }
++
++}
++
++static void sl2312_unmask_irq(unsigned int irq)
++{
++      unsigned int mask;
++
++#ifdef CONFIG_PCI
++      if (irq >= PCI_IRQ_OFFSET)
++      {
++              mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++              mask |= IRQ_PCI_MASK ;
++              __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++              sl2312_pci_unmask_irq(irq - PCI_IRQ_OFFSET);
++      }
++      else
++#endif
++      if(irq >= FIQ_OFFSET)
++        {
++          mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++          mask |= (1 << (irq - FIQ_OFFSET));
++          __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++      }
++        else
++        {
++          mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++          mask |= (1 << irq);
++          __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        }
++}
++
++static struct irq_chip sl2312_level_irq = {
++        .ack            = sl2312_mask_irq,
++        .mask           = sl2312_mask_irq,
++        .unmask         = sl2312_unmask_irq,
++//            .set_type       = ixp4xx_set_irq_type,
++};
++
++static struct irq_chip sl2312_edge_irq = {
++        .ack            = sl2312_ack_irq,
++        .mask           = sl2312_mask_irq,
++        .unmask         = sl2312_unmask_irq,
++//            .set_type       = ixp4xx_set_irq_type,
++};
++
++static struct resource irq_resource = {
++        .name   = "irq_handler",
++        .start  = IO_ADDRESS(SL2312_INTERRUPT_BASE),
++        .end    = IO_ADDRESS(FIQ_STATUS(SL2312_INTERRUPT_BASE))+4,
++};
++
++void __init sl2312_init_irq(void)
++{
++      unsigned int i, mode, level;
++
++    request_resource(&iomem_resource, &irq_resource);
++
++      for (i = 0; i < NR_IRQS; i++)
++      {
++          if((i>=IRQ_TIMER1 && i<=IRQ_TIMER3)||(i>=IRQ_SERIRQ0 && i<=IRQ_SERIRQ_MAX))
++        {
++              set_irq_chip(i, &sl2312_edge_irq);
++              set_irq_handler(i, handle_edge_irq);
++        }
++          else
++        {
++              set_irq_chip(i, &sl2312_level_irq);
++            set_irq_handler(i,handle_level_irq);
++        }
++        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
++      }
++
++      /* Disable all interrupt */
++      __raw_writel(0,IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++      __raw_writel(0,FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++
++      /* Set interrupt mode */
++    /* emac & ipsec type is level trigger and high active */
++    mode = __raw_readl(IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++    level = __raw_readl(IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++
++      mode &= ~IRQ_GMAC0_MASK;
++      level &= ~IRQ_GMAC0_MASK;
++
++      mode &= ~IRQ_GMAC1_MASK;
++      level &= ~IRQ_GMAC1_MASK;
++
++      mode &= ~IRQ_IPSEC_MASK;
++      level &= ~IRQ_IPSEC_MASK;
++
++      // for IDE0,1, high active and level trigger
++      mode &= ~IRQ_IDE0_MASK;
++      level &= ~IRQ_IDE0_MASK;
++      mode &= ~IRQ_IDE1_MASK;
++      level &= ~IRQ_IDE1_MASK;
++
++
++      // for PCI, high active and level trigger
++      mode &= ~IRQ_PCI_MASK;
++      level &= ~IRQ_PCI_MASK;
++
++      // for USB, high active and level trigger
++      mode &= ~IRQ_USB0_MASK;
++      level &= ~IRQ_USB0_MASK;
++
++      mode &= ~IRQ_USB1_MASK;
++      level &= ~IRQ_USB1_MASK;
++
++      // for LPC, high active and edge trigger
++      mode |= 0xffff0000;
++      level &= 0x0000ffff;
++
++      // for GPIO, high active and level trigger
++      mode &= ~(IRQ_GPIO_MASK);
++      level &= ~(IRQ_GPIO_MASK);
++
++      mode &= ~(IRQ_GPIO1_MASK);
++      level &= ~(IRQ_GPIO1_MASK);
++
++      mode &= ~(IRQ_GPIO2_MASK);
++      level &= ~(IRQ_GPIO2_MASK);
++
++      __raw_writel(mode,IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++      __raw_writel(level,IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++
++}
+--- /dev/null
++++ b/arch/arm/mach-sl2312/lpc.c
+@@ -0,0 +1,125 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ *    ITE Semi IT8712 Super I/O functions.
++ *
++ * Copyright 2001 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc.
++ *            ppopov@mvista.com or source@mvista.com
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
++ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
++ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
++ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
++ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
++ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
++ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *  You should have received a copy of the  GNU General Public License along
++ *  with this program; if not, write  to the Free Software Foundation, Inc.,
++ *  675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/types.h>
++#include <asm/arch/it8712.h>
++#include <linux/init.h>
++#include <asm/arch/hardware.h>
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++
++// MB PnP configuration register
++#define LPC_KEY_ADDR  (IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2e)
++#define LPC_DATA_ADDR (IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2f)
++
++#define LPC_BUS_CTRL                  *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 0)
++#define LPC_BUS_STATUS                        *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 2)
++#define LPC_SERIAL_IRQ_CTRL           *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 4)
++
++int it8712_exist;
++
++static void LPCEnterMBPnP(void)
++{
++      int i;
++      unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
++
++      for (i = 0; i<4; i++)
++              outb(key[i], LPC_KEY_ADDR);
++
++}
++
++static void LPCExitMBPnP(void)
++{
++      outb(0x02, LPC_KEY_ADDR);
++      outb(0x02, LPC_DATA_ADDR);
++}
++
++void LPCSetConfig(char LdnNumber, char Index, char data)
++{
++      LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
++      outb(0x07, LPC_KEY_ADDR);
++      outb(LdnNumber, LPC_DATA_ADDR);
++      outb(Index, LPC_KEY_ADDR);
++      outb(data, LPC_DATA_ADDR);
++      LPCExitMBPnP();
++}
++
++char LPCGetConfig(char LdnNumber, char Index)
++{
++      char rtn;
++
++      LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
++      outb(0x07, LPC_KEY_ADDR);
++      outb(LdnNumber, LPC_DATA_ADDR);
++      outb(Index, LPC_KEY_ADDR);
++      rtn = inb(LPC_DATA_ADDR);
++      LPCExitMBPnP();
++      return rtn;
++}
++
++static int SearchIT8712(void)
++{
++      unsigned char Id1, Id2;
++      unsigned short Id;
++
++      LPCEnterMBPnP();
++      outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */
++      Id1 = inb(LPC_DATA_ADDR);
++      outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */
++      Id2 = inb(LPC_DATA_ADDR);
++      Id = (Id1 << 8) | Id2;
++      LPCExitMBPnP();
++      if (Id == 0x8712)
++              return TRUE;
++      else
++              return FALSE;
++}
++
++int InitLPCInterface(void)
++{
++      LPC_BUS_CTRL = 0xc0;
++      LPC_SERIAL_IRQ_CTRL = 0xc0;
++      mdelay(1);              // wait for 1 serial IRQ cycle
++      LPC_SERIAL_IRQ_CTRL = 0x80;
++      it8712_exist = SearchIT8712();
++      printk("IT8712 %s exist\n", it8712_exist?"":"doesn't");
++      return 0;
++}
++
++//__initcall(InitLPCInterface);
+--- /dev/null
++++ b/arch/arm/mach-sl2312/mm.c
+@@ -0,0 +1,80 @@
++/*
++ *  linux/arch/arm/mach-epxa10db/mm.c
++ *
++ *  MM routines for Altera'a Epxa10db board
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/sizes.h>
++
++#include <asm/mach/map.h>
++
++/* Page table mapping for I/O region */
++static struct map_desc sl2312_io_desc[] __initdata = {
++#ifdef CONFIG_GEMINI_IPI
++{__phys_to_virt(CPU_1_MEM_BASE),         __phys_to_pfn(CPU_1_MEM_BASE),        SZ_64M,  MT_MEMORY},
++#endif
++{IO_ADDRESS(SL2312_SRAM_BASE),         __phys_to_pfn(SL2312_SRAM_BASE),        SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_DRAM_CTRL_BASE),    __phys_to_pfn(SL2312_DRAM_CTRL_BASE),   SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_GLOBAL_BASE),       __phys_to_pfn(SL2312_GLOBAL_BASE),      SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_WAQTCHDOG_BASE),    __phys_to_pfn(SL2312_WAQTCHDOG_BASE),   SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_UART_BASE),         __phys_to_pfn(SL2312_UART_BASE),        SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_TIMER_BASE),        __phys_to_pfn(SL2312_TIMER_BASE),       SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_LCD_BASE),          __phys_to_pfn(SL2312_LCD_BASE),         SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_RTC_BASE),          __phys_to_pfn(SL2312_RTC_BASE),         SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_SATA_BASE),         __phys_to_pfn(SL2312_SATA_BASE),        SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_LPC_HOST_BASE),     __phys_to_pfn(SL2312_LPC_HOST_BASE),    SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_LPC_IO_BASE),       __phys_to_pfn(SL2312_LPC_IO_BASE),      SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_INTERRUPT_BASE),    __phys_to_pfn(SL2312_INTERRUPT_BASE),   SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_INTERRUPT1_BASE),   __phys_to_pfn(SL2312_INTERRUPT1_BASE),  SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_SSP_CTRL_BASE),     __phys_to_pfn(SL2312_SSP_CTRL_BASE),    SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_POWER_CTRL_BASE),   __phys_to_pfn(SL2312_POWER_CTRL_BASE),  SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_CIR_BASE),          __phys_to_pfn(SL2312_CIR_BASE),         SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_GPIO_BASE),         __phys_to_pfn(SL2312_GPIO_BASE),        SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_GPIO_BASE1),        __phys_to_pfn(SL2312_GPIO_BASE1),       SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_GPIO_BASE2),        __phys_to_pfn(SL2312_GPIO_BASE2),       SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_PCI_IO_BASE),         __phys_to_pfn(SL2312_PCI_IO_BASE),      SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_PCI_MEM_BASE),        __phys_to_pfn(SL2312_PCI_MEM_BASE),     SZ_512K,  MT_DEVICE},
++#ifdef CONFIG_NET_SL351X
++{IO_ADDRESS(SL2312_TOE_BASE),         __phys_to_pfn(SL2312_TOE_BASE)       ,   SZ_512K,  MT_DEVICE},
++#endif
++{IO_ADDRESS(SL2312_GMAC0_BASE),              __phys_to_pfn(SL2312_GMAC0_BASE),           SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_GMAC1_BASE),              __phys_to_pfn(SL2312_GMAC1_BASE),           SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_SECURITY_BASE),     __phys_to_pfn(SL2312_SECURITY_BASE),    SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_IDE0_BASE),         __phys_to_pfn(SL2312_IDE0_BASE),        SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_IDE1_BASE),         __phys_to_pfn(SL2312_IDE1_BASE),        SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_RAID_BASE),         __phys_to_pfn(SL2312_RAID_BASE),        SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_FLASH_CTRL_BASE),   __phys_to_pfn(SL2312_FLASH_CTRL_BASE),  SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_DRAM_CTRL_BASE),    __phys_to_pfn(SL2312_DRAM_CTRL_BASE),   SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_GENERAL_DMA_BASE),  __phys_to_pfn(SL2312_GENERAL_DMA_BASE), SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_USB0_BASE),         __phys_to_pfn(SL2312_USB_BASE),         SZ_512K,  MT_DEVICE},
++{IO_ADDRESS(SL2312_USB1_BASE),         __phys_to_pfn(SL2312_USB1_BASE),        SZ_512K,  MT_DEVICE},
++{FLASH_VADDR(SL2312_FLASH_BASE),       __phys_to_pfn(SL2312_FLASH_BASE),       SZ_16M,    MT_DEVICE},
++};
++
++void __init sl2312_map_io(void)
++{
++      iotable_init(sl2312_io_desc, ARRAY_SIZE(sl2312_io_desc));
++}
+--- /dev/null
++++ b/arch/arm/mach-sl2312/pci.c
+@@ -0,0 +1,359 @@
++/*
++ *  linux/arch/arm/mach-sl2312/pci_sl2312.c
++ *
++ *  PCI functions for sl2312 host PCI bridge
++ *
++ *  Copyright (C) 2003 StorLink Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/init.h>
++
++#include <asm/sizes.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/mach/pci.h>
++#include <asm/mach/irq.h>
++#include <asm/mach-types.h>
++
++#include <asm/arch/pci.h>
++
++//#define DEBUG
++
++// sl2312 PCI bridge access routines
++
++#define PCI_IOSIZE_REG        (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE)))
++#define PCI_PROT_REG  (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x04))
++#define PCI_CTRL_REG  (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x08))
++#define PCI_SOFTRST_REG       (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x10))
++#define PCI_CONFIG_REG        (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x28))
++#define PCI_DATA_REG  (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x2C))
++
++static spinlock_t sl2312_pci_lock = SPIN_LOCK_UNLOCKED;
++// for initialize PCI devices
++struct resource pci_ioport_resource = {
++              .name = "PCI I/O Space",
++              .start = IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x100,
++              .end = IO_ADDRESS(SL2312_PCI_IO_BASE) + SZ_512K - 1,
++              .flags = IORESOURCE_IO,
++};
++struct resource pci_iomem_resource = {
++              .name = "PCI Mem Space",
++              .start = SL2312_PCI_MEM_BASE,
++              .end = SL2312_PCI_MEM_BASE + SZ_128M - 1,
++              .flags = IORESOURCE_MEM,
++};
++
++static int sl2312_read_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 *val)
++{
++      unsigned long addr,data;
++      unsigned long flags;
++
++      spin_lock_irqsave(&sl2312_pci_lock, flags);
++    addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3);
++      PCI_CONFIG_REG = addr;
++      data = PCI_DATA_REG;
++
++      switch (size) {
++      case 1:
++          *val = (u8) (data >> ((where & 0x03) * 8));
++              break;
++      case 2:
++          *val = (u16) (data >> ((where & 0x02) * 8));
++              break;
++      case 4:
++          *val = data;
++      if ((where >= 0x10) && (where <= 0x24)) {
++              if ((*val & 0xfff00000) == SL2312_PCI_IO_BASE) {
++                      *val &= 0x000fffff;
++                      *val |= IO_ADDRESS(SL2312_PCI_IO_BASE);
++              }
++      }
++              break;
++      }
++      spin_unlock_irqrestore(&sl2312_pci_lock, flags);
++//    printk("READ==>slot=%d fn=%d where=%d value=%x\n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,*val);
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static int sl2312_write_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 val)
++{
++      unsigned long addr,data;
++      unsigned long flags;
++
++      spin_lock_irqsave(&sl2312_pci_lock, flags);
++    addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3);
++      PCI_CONFIG_REG = addr;
++      data = PCI_DATA_REG;
++
++      switch (size) {
++      case 1:
++      data &= ~(0xff << ((where & 0x03) * 8));
++      data |= (val << ((where & 0x03) * 8));
++      PCI_DATA_REG = data;
++              break;
++      case 2:
++      data &= ~(0xffff << ((where & 0x02) * 8));
++      data |= (val << ((where & 0x02) * 8));
++      PCI_DATA_REG = data;
++              break;
++      case 4:
++      if ((where >= 0x10) && (where <= 0x24)) {
++              if ((val & 0xfff00000) == IO_ADDRESS(SL2312_PCI_IO_BASE)) {
++                      val &= 0x000fffff;
++                      val |= SL2312_PCI_IO_BASE;
++              }
++      }
++          PCI_DATA_REG = val;
++              break;
++      }
++      spin_unlock_irqrestore(&sl2312_pci_lock, flags);
++
++//    printk("WRITE==> slot=%d fn=%d where=%d value=%x \n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,val);
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops sl2312_pci_ops = {
++      .read   = sl2312_read_config,
++      .write  = sl2312_write_config,
++};
++
++
++int __init sl2312_pci_setup_resources(struct resource **resource)
++{
++      PCI_IOSIZE_REG = 0;             // 1M IO size
++      PCI_CTRL_REG = 0x06;
++
++      resource[0] = &pci_ioport_resource;
++      resource[1] = &pci_iomem_resource;
++      resource[2] = NULL;
++
++      return 1;
++}
++
++//static int sl2312_pci_fault(unsigned long addr, struct pt_regs *regs)
++//{
++//    return 1;
++//}
++
++
++/**********************************************************************
++ * MASK(disable) PCI interrupt
++ *    0: PCI INTA, 1: PCI INTB, ...           // for Linux interrupt routing
++ *   16: PERR                                                         // for PCI module internal use
++ *   17: SERR,.. respect to PCI CTRL2 REG
++ **********************************************************************/
++void sl2312_pci_mask_irq(unsigned int irq)
++{
++    struct pci_bus bus;
++      unsigned int tmp;
++
++    bus.number = 0;
++    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
++      if (irq < 16) {                                         // for linux int routing
++              tmp &= ~(1 << (irq + 16 + 6));
++      }
++      else {
++              tmp &= ~(1 << irq);
++      }
++    sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
++}
++
++/* UNMASK(enable) PCI interrupt */
++void sl2312_pci_unmask_irq(unsigned int irq)
++{
++    struct pci_bus bus;
++      unsigned int tmp;
++
++    bus.number = 0;
++    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
++      if (irq < 16) {                                         // for linux int routing
++              tmp |= (1 << (irq + 16 + 6));
++      }
++      else {
++              tmp |= (1 << irq);
++      }
++    sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
++}
++
++/* Get PCI interrupt source */
++int sl2312_pci_get_int_src(void)
++{
++    struct pci_bus bus;
++      unsigned int tmp=0;
++
++    bus.number = 0;
++    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
++      if (tmp & (1 << 28)) {          // PCI INTA
++        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
++              return IRQ_PCI_INTA;
++      }
++      if (tmp & (1 << 29)) {          // PCI INTB
++        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
++              return IRQ_PCI_INTB;
++      }
++      if (tmp & (1 << 30)) {          // PCI INTC
++        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
++              return IRQ_PCI_INTC;
++      }
++      if (tmp & (1 << 31)) {          // PCI INTD
++        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
++              return IRQ_PCI_INTD;
++      }
++      // otherwise, it should be a PCI error
++      return IRQ_PCI;
++}
++
++static irqreturn_t sl2312_pci_irq(int irq, void *devid)
++{
++    struct irq_desc *desc;
++      struct irqaction *action;
++      int retval = 0;
++
++    return 1;
++
++      irq = sl2312_pci_get_int_src();
++      desc = &irq_desc[irq];
++      action = desc->action;
++      do {
++              retval |= action->handler(irq, devid);
++              action = action->next;
++      } while (action);
++
++    return 1;
++}
++
++//extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
++
++void __init sl2312_pci_preinit(void)
++{
++    struct pci_bus bus;
++      unsigned long flags;
++      unsigned int temp;
++      int ret;
++
++      /*
++       * Hook in our fault handler for PCI errors
++       */
++//    external_fault = sl2312_pci_fault;
++
++      spin_lock_irqsave(&sl2312_pci_lock, flags);
++
++      /*
++       * Grab the PCI interrupt.
++       */
++      ret = request_irq(IRQ_PCI, sl2312_pci_irq, 0, "sl2312 pci int", NULL);
++      if (ret)
++              printk(KERN_ERR "PCI: unable to grab PCI error "
++                     "interrupt: %d\n", ret);
++
++      spin_unlock_irqrestore(&sl2312_pci_lock, flags);
++
++      // setup pci bridge
++    bus.number = 0;   /* device 0, function 0 */
++      temp = (SL2312_PCI_DMA_MEM1_BASE & 0xfff00000) | (SL2312_PCI_DMA_MEM1_SIZE << 16);
++    sl2312_write_config(&bus, 0, SL2312_PCI_MEM1_BASE_SIZE, 4, temp);
++}
++
++/*
++ *    No swizzle on SL2312
++ */
++static u8 __init sl2312_pci_swizzle(struct pci_dev *dev, u8 *pinp)
++{
++      return PCI_SLOT(dev->devfn);
++}
++
++/*
++ * map the specified device/slot/pin to an IRQ.  This works out such
++ * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1.
++ */
++static int __init sl2312_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++      int intnr = ((slot  + (pin - 1)) & 3) + 4;  /* the IRQ number of PCI bridge */
++
++      // printk("%s : slot = %d  pin = %d \n",__func__,slot,pin);
++    switch (slot)
++    {
++        case 12:
++              if (pin==1)
++              {
++                      intnr = 3;
++                  }
++                  else
++                  {
++                      intnr = 0;
++                  }
++            break;
++        case 11:
++                  intnr = (2 + (pin - 1)) & 3;
++            break;
++        case 10:
++                  intnr = (1 + (pin - 1)) & 3;
++            break;
++        case  9:
++                  intnr = (pin - 1) & 3;
++            break;
++    }
++//    if (slot == 10)
++//            intnr = (1 + (pin - 1)) & 3;
++//    else if (slot == 9)
++//            intnr = (pin - 1) & 3;
++      return (IRQ_PCI_INTA + intnr);
++}
++
++struct pci_bus * __init sl2312_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
++{
++      return (pci_scan_bus(0, &sl2312_pci_ops, sysdata));
++
++}
++
++int __init sl2312_pci_setup(int nr, struct pci_sys_data *sys)
++{
++      int ret = 0;
++
++      if (nr == 0) {
++              ret = sl2312_pci_setup_resources(sys->resource);
++      }
++
++      return ret;
++}
++
++
++struct hw_pci sl2312_pci __initdata = {
++      .setup          =       sl2312_pci_setup,
++      .preinit                =       sl2312_pci_preinit,
++      .nr_controllers =   1,
++      .swizzle                =       sl2312_pci_swizzle,
++      .map_irq                =       sl2312_pci_map_irq,
++      .scan           =   sl2312_pci_scan_bus,
++};
++
++static int __init sl2312_pci_init(void)
++{
++      if (machine_is_sl2312())
++              pci_common_init(&sl2312_pci);
++      return 0;
++}
++
++subsys_initcall(sl2312_pci_init);
+--- /dev/null
++++ b/arch/arm/mach-sl2312/sl2312-otg-1.c
+@@ -0,0 +1,64 @@
++/*
++ *  linux/arch/arm/mach-pxa/sl2312.c
++ *
++ *  Author:   Nicolas Pitre
++ *  Created:  Nov 05, 2002
++ *  Copyright:        MontaVista Software Inc.
++ *
++ * Code specific to sl2312 aka Bulverde.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/pm.h>
++#include <linux/device.h>
++#include "asm/arch/sl2312.h"
++#include "asm/arch/irqs.h"
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <linux/platform_device.h>
++
++/*
++ * device registration specific to sl2312.
++ */
++
++static u64 sl2312_dmamask_1 = 0xffffffffUL;
++
++static struct resource sl2312_otg_resources_1[] = {
++      [0] = {
++              .start  = 0x69000000,
++              .end    = 0x69000fff,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = IRQ_USB1,
++              .end    = IRQ_USB1,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device ehci_1_device = {
++      .name           = "ehci-hcd-FOTG2XX",
++      .id             = -1,
++      .dev            = {
++              .dma_mask = &sl2312_dmamask_1,
++              .coherent_dma_mask = 0xffffffff,
++      },
++      .num_resources  = ARRAY_SIZE(sl2312_otg_resources_1),
++      .resource       = sl2312_otg_resources_1,
++};
++
++static struct platform_device *devices[] __initdata = {
++      &ehci_1_device,
++};
++
++static int __init sl2312_1_init(void)
++{
++      return platform_add_devices(devices, ARRAY_SIZE(devices));
++}
++
++subsys_initcall(sl2312_1_init);
+--- /dev/null
++++ b/arch/arm/mach-sl2312/sl2312-otg.c
+@@ -0,0 +1,87 @@
++/*
++ *  linux/arch/arm/mach-pxa/sl2312.c
++ *
++ *  Author:   Nicolas Pitre
++ *  Created:  Nov 05, 2002
++ *  Copyright:        MontaVista Software Inc.
++ *
++ * Code specific to sl2312 aka Bulverde.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/pm.h>
++#include <linux/device.h>
++#include "asm/arch/sl2312.h"
++#include "asm/arch/irqs.h"
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <linux/platform_device.h>
++
++/*
++ * device registration specific to sl2312.
++ */
++
++static u64 sl2312_dmamask = 0xffffffffUL;
++
++static struct resource sl2312_otg_resources_1[] = {
++      [0] = {
++              .start  = 0x68000000,
++              .end    = 0x68000fff,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = IRQ_USB0,
++              .end    = IRQ_USB0,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++static struct resource sl2312_otg_resources_2[] = {
++      [2] = {
++              .start  = 0x69000000,
++              .end    = 0x69000fff,
++              .flags  = IORESOURCE_MEM,
++      },
++      [3] = {
++              .start  = IRQ_USB1,
++              .end    = IRQ_USB1,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device ehci_device_1 = {
++      .name           = "ehci-hcd-FOTG2XX",
++      .id             = 1,
++      .dev            = {
++              .dma_mask = &sl2312_dmamask,
++              .coherent_dma_mask = 0xffffffff,
++      },
++      .num_resources  = ARRAY_SIZE(sl2312_otg_resources_1),
++      .resource       = sl2312_otg_resources_1,
++};
++
++static struct platform_device ehci_device_2 = {
++      .name           = "ehci-hcd-FOTG2XX",
++      .id             = 2,
++      .dev            = {
++              .dma_mask = &sl2312_dmamask,
++              .coherent_dma_mask = 0xffffffff,
++      },
++      .num_resources  = ARRAY_SIZE(sl2312_otg_resources_2),
++      .resource       = sl2312_otg_resources_2,
++};
++
++static struct platform_device *devices[] __initdata = {
++      &ehci_device_1, /* &ehci_device_2, */
++};
++
++static int __init sl2312_init(void)
++{
++      return platform_add_devices(devices, ARRAY_SIZE(devices));
++}
++
++subsys_initcall(sl2312_init);
+--- /dev/null
++++ b/arch/arm/mach-sl2312/sl3516_device.c
+@@ -0,0 +1,89 @@
++/*
++ *  linux/arch/arm/mach-2312/sl3516_device.c
++ *
++ *  Author:   Nicolas Pitre
++ *  Created:  Nov 05, 2002
++ *  Copyright:        MontaVista Software Inc.
++ *
++ * Code specific to sl2312 aka Bulverde.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/pm.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include "asm/arch/sl2312.h"
++#include "asm/arch/irqs.h"
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++/*
++ * device registration specific to sl2312.
++ */
++
++static u64 sl3516_dmamask = 0xffffffffUL;
++
++static struct resource sl3516_sata_resources[] = {
++      [0] = {
++              .start  = 0x63400000,
++              .end    = 0x63400040,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = IRQ_IDE1,
++              .end    = IRQ_IDE1,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device sata_device = {
++      .name           = "lepus-sata",
++      .id             = -1,
++      .dev            = {
++              .dma_mask = &sl3516_dmamask,
++              .coherent_dma_mask = 0xffffffff,
++      },
++      .num_resources  = ARRAY_SIZE(sl3516_sata_resources),
++      .resource       = sl3516_sata_resources,
++};
++
++static struct resource sl3516_sata0_resources[] = {
++      [0] = {
++              .start  = 0x63000000,
++              .end    = 0x63000040,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = IRQ_IDE0,
++              .end    = IRQ_IDE0,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device sata0_device = {
++      .name           = "lepus-sata0",
++      .id             = -1,
++      .dev            = {
++              .dma_mask = &sl3516_dmamask,
++              .coherent_dma_mask = 0xffffffff,
++      },
++      .num_resources  = ARRAY_SIZE(sl3516_sata0_resources),
++      .resource       = sl3516_sata0_resources,
++};
++
++static struct platform_device *sata_devices[] __initdata = {
++      &sata_device,
++      &sata0_device,
++};
++
++static int __init sl3516_init(void)
++{
++      return platform_add_devices(sata_devices, ARRAY_SIZE(sata_devices));
++}
++
++subsys_initcall(sl3516_init);
+--- /dev/null
++++ b/arch/arm/mach-sl2312/time.c
+@@ -0,0 +1,134 @@
++/*
++ *  linux/include/asm-arm/arch-epxa10db/time.h
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <asm/leds.h>
++#include <asm/arch/hardware.h>
++#include <asm/mach/time.h>
++#define TIMER_TYPE (volatile unsigned int*)
++#include <asm/arch/timer.h>
++// #define FIQ_PLUS     1
++
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t sl2312_timer_interrupt(int irq, void *dev_id)
++{
++//        unsigned int led;
++      // ...clear the interrupt
++#ifdef FIQ_PLUS
++      *((volatile unsigned int *)FIQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
++#else
++      *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
++#endif
++
++#if 0
++        if(!(jiffies % HZ))
++        {
++            led = jiffies / HZ;
++//            printk("ticks %x \n", led);
++          }
++      do_leds();
++      do_timer(regs);
++      do_profile(regs);
++#endif
++    timer_tick();
++    return IRQ_HANDLED;
++}
++
++static struct irqaction sl2312_timer_irq = {
++      .name           = "SL2312 Timer Tick",
++      .flags          = IRQF_DISABLED | IRQF_TIMER,
++      .handler        = sl2312_timer_interrupt,
++};
++
++unsigned long sl2312_gettimeoffset (void)
++{
++    return 0L;
++}
++
++/*
++ * Set up timer interrupt, and return the current time in seconds.
++ */
++void __init sl2312_time_init(void)
++{
++      // For clock rate adjusting
++      unsigned int tick_rate=0;
++
++#ifdef CONFIG_SL3516_ASIC
++      unsigned int clock_rate_base = 130000000;
++      unsigned int reg_v=0;
++
++      //--> Add by jason for clock adjust
++      reg_v = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_STATUS)));
++      reg_v >>= 15;
++      tick_rate = (clock_rate_base + (reg_v & 0x07)*10000000);
++
++      //  FPGA use AHB bus tick rate
++      printk("Bus: %dMHz",tick_rate/1000000);
++
++      tick_rate /= 6;                         // APB bus run AHB*(1/6)
++
++      switch((reg_v>>3)&3){
++              case 0: printk("(1/1)\n") ;
++                                      break;
++              case 1: printk("(3/2)\n") ;
++                                      break;
++              case 2: printk("(24/13)\n") ;
++                                      break;
++              case 3: printk("(2/1)\n") ;
++                                      break;
++      }
++      //<--
++#else
++      printk("Bus: %dMHz(1/1)\n",CLOCK_TICK_RATE/1000000);            // FPGA use 20MHz
++      tick_rate = CLOCK_TICK_RATE;
++#endif
++
++
++      /*
++       * Make irqs happen for the system timer
++       */
++      // initialize timer interrupt
++      // low active and edge trigger
++#ifdef FIQ_PLUS
++      *((volatile unsigned int *)FIQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
++      *((volatile unsigned int *)FIQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
++      setup_irq(IRQ_TIMER1, &sl2312_timer_irq);
++      /* Start the timer */
++      *TIMER_COUNT(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ);
++      *TIMER_LOAD(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ);
++      *TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_1_CR_ENABLE_MSK|TIMER_1_CR_INT_MSK);
++#else
++      *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
++      *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
++      setup_irq(IRQ_TIMER2, &sl2312_timer_irq);
++      /* Start the timer */
++      *TIMER_COUNT(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ);
++      *TIMER_LOAD(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ);
++      *TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_2_CR_ENABLE_MSK|TIMER_2_CR_INT_MSK);
++#endif
++
++}
++
++
+--- /dev/null
++++ b/arch/arm/mach-sl2312/xor.c
+@@ -0,0 +1,1200 @@
++/*
++ * arch/arm/mach-sl2312/xor.c
++ *
++ * Support functions for the Gemini Soc. This is
++ * a HW XOR unit that is specifically designed for use with RAID5
++ * applications.  This driver provides an interface that is used by
++ * the Linux RAID stack.
++ *
++ * Original Author: Jason Lee<jason@storlink.com.tw>
++ *
++ * Contributors:Sanders<sanders@storlink.com.tw>
++                              Jason Lee<jason@storlink.com.tw>
++ *
++ *
++ * Maintainer: Jason Lee<jason@storlink.com.tw>
++ *
++ * Copyright (C) 2005 Storlink Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *
++ * History:   (06/25/2005, DJ) Initial Creation
++ *
++ *    Versing 1.0.0   Initial version
++ */
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/wait.h>
++#include <linux/list.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/mm.h>
++#include <asm/irq.h>
++#include <asm/delay.h>
++#include <asm/uaccess.h>
++#include <asm/cacheflush.h>
++#include <asm/hardware.h>
++#include <asm/arch/xor.h>
++#include <asm/pci.h>
++#include <linux/version.h>
++
++/*
++ * pick up local definitions
++ */
++#define XOR_SW_FILL_IN
++#include "hw_xor.h"
++
++
++//#define XOR_DEBUG
++//#define XOR_TEST    1
++#ifdef XOR_TEST
++#define TEST_ITERATION 1000
++#define SPIN_WAIT     1
++#endif
++#ifdef XOR_DEBUG
++#define DPRINTK(s, args...) printk("Gemini XOR: " s "\n", ## args)
++#define DENTER() DPRINTK("Entered...\n");
++#define DEXIT() DPRINTK("Exited...\n");
++#else
++#define DPRINTK(s, args...)
++#define DENTER()
++#define DEXIT()
++#endif
++
++//#define SPIN_WAIT
++
++/* globals */
++static RAID_T tp;
++static RAID_TXDMA_CTRL_T      txdma_ctrl;
++RAID_RXDMA_CTRL_T                     rxdma_ctrl;
++
++//#ifndef SPIN_WAIT
++static spinlock_t         raid_lock;
++//#endif
++
++static unsigned int     tx_desc_virtual_base;
++static unsigned int     rx_desc_virtual_base;
++RAID_DESCRIPTOR_T     *tx_desc_ptr;
++RAID_DESCRIPTOR_T     *rx_desc_ptr;
++
++/* static prototypes */
++#define DMA_MALLOC(size,handle)               pci_alloc_consistent(NULL,size,handle)
++#define DMA_MFREE(mem,size,handle)    pci_free_consistent(NULL,size,mem,handle)
++
++static int gemini_xor_init_desc(void);
++
++static unsigned int raid_read_reg(unsigned int offset)
++{
++    unsigned int    reg_val;
++
++    reg_val = readl(RAID_BASE_ADDR + offset);
++      return (reg_val);
++}
++
++static void raid_write_reg(unsigned int offset,unsigned int data,unsigned int bit_mask)
++{
++      unsigned int reg_val;
++    unsigned int *addr;
++
++      reg_val = ( raid_read_reg(offset) & (~bit_mask) ) | (data & bit_mask);
++      addr = (unsigned int *)(RAID_BASE_ADDR + offset);
++    writel(reg_val,addr);
++      return;
++}
++
++#ifndef SPIN_WAIT
++__inline__ void xor_queue_descriptor(void)
++{
++      unsigned int flags,status=1;
++
++      DPRINTK("Going to sleep");
++
++      while(status){
++              yield();
++              //schedule();
++              spin_lock_irqsave(&raid_lock,flags);
++              status = tp.busy;
++              spin_unlock_irqrestore(&raid_lock, flags);
++      }
++//    tp.status = COMPLETE;
++      DPRINTK("woken up!");
++
++}
++#endif
++
++#ifdef SPIN_WAIT
++static void gemini_xor_isr(int d_n)
++#else
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
++static void gemini_xor_isr(int irq, void *dev_id, struct pt_regs *regs)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++static irqreturn_t gemini_xor_isr(int irq, void *dev_instance, struct pt_regs *regs)
++#endif
++#endif
++{
++
++      unsigned int err;
++      RAID_DMA_STATUS_T       dma_status;
++//    RAID_DESCRIPTOR_T *rdesc,*tdesc;
++//    unsigned int *paddr;
++
++      dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
++#ifdef SPIN_WAIT
++      while( (dma_status.bits32& (1<<31) ) ==0 ){
++              udelay(1);
++              dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
++      }
++
++/*    tdesc = tp.tx_first_desc;
++      rdesc = tp.rx_first_desc;
++      for(d_n;d_n>0;d_n--){
++              if( tdesc->func_ctrl.bits.own == DMA ){
++                      paddr = tdesc;
++                      printk("error tx desc:0x%x\n",*paddr++);
++                      printk("error tx desc:0x%x\n",*paddr++);
++                      printk("error tx desc:0s%x\n",*paddr++);
++                      printk("error tx desc:0x%x\n",*paddr);
++                      while(1);
++              }
++              tdesc = (RAID_DESCRIPTOR_T *)((tdesc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++      }
++
++      if( rdesc->func_ctrl.bits.own == DMA ){
++              paddr = rdesc;
++              printk("error rx desc:0x%x\n",*paddr++);
++              printk("error rx desc:0x%x\n",*paddr++);
++              printk("error rx desc:0s%x\n",*paddr++);
++              printk("error rx desc:0x%x\n",*paddr);
++              while(1);
++      }
++*/
++#endif
++
++      if(dma_status.bits32 & ((1<<31)|(1<<26))){
++              // if no bug , we can turn off rx finish interrupt
++              dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
++              err = raid_read_reg(RAID_DMA_DEVICE_ID);
++              tp.busy = 0;
++
++              if(err&0x00FF0000){
++                      tp.status = ERROR;
++                      printk("XOR:<HW>%s error code %x\n",(err&0x00F00000)?"tx":"rx",err);
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
++                      return ;
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#ifndef SPIN_WAIT
++                      return IRQ_RETVAL(IRQ_HANDLED);
++#endif
++#endif
++              }
++              // 16~19 rx error code
++              // 20~23 tx error codd
++
++              dma_status.bits.tsFinishI = 1;
++              dma_status.bits.rsFinishI = 1;
++              raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0x84000000);  // clear INT
++
++//            printk("xor %d\n",d_n);
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
++                      return ;
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#ifndef SPIN_WAIT
++                      return IRQ_RETVAL(IRQ_HANDLED);
++#endif
++#endif
++      }
++
++      #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
++              return ;
++      #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++      #ifndef SPIN_WAIT
++              printk("XOR: DMA status register(0x%8x)\n",dma_status.bits32);
++              return IRQ_RETVAL(IRQ_HANDLED);
++      #endif
++      #endif
++}
++
++void
++xor_gemini_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++      int status=0;
++      unsigned int flags;
++
++      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
++              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
++      }
++
++      spin_lock_irqsave(&raid_lock,flags);
++      while(tp.status != COMPLETE){
++              spin_unlock_irqrestore(&raid_lock, flags);
++              //printk("XOR yield2\n");
++#ifdef XOR_SW_FILL_IN
++              xor_arm4regs_2(bytes,p1,p2);
++              return ;
++#else
++              yield();
++#endif
++      }
++      spin_unlock_irqrestore(&raid_lock, flags);
++      tp.status = RUNNING;
++
++      // flush the cache to memory before H/W XOR touches them
++      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
++      consistent_sync(p2, bytes, DMA_TO_DEVICE);
++
++
++      tp.tx_desc = tp.tx_first_desc;
++      tp.rx_desc = tp.rx_first_desc;
++      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
++              // prepare tx descript
++              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
++              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00020000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++              wmb();
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p2);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00010000;
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);                                                  // keep last descript
++
++      wmb();
++      // prepare rx descript
++      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf);
++      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
++      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
++//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++
++      }
++      else{
++              /* no free tx descriptor */
++              printk("XOR:no free tx descript");
++              return ;
++      }
++
++      // change status
++//    tp.status = RUNNING;
++      status = tp.busy = 1;
++
++      // start tx DMA
++      rxdma_ctrl.bits.rd_start = 1;
++      // start rx DMA
++      txdma_ctrl.bits.td_start = 1;
++
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
++      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
++
++#ifdef SPIN_WAIT
++      gemini_xor_isr(2);
++#else
++      xor_queue_descriptor();
++#endif
++
++      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*2) ;
++      tp.status = COMPLETE;
++//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
++//    tp.rx_desc = tp.rx_first_desc ;
++//    tp.rx_desc->func_ctrl.bits.own = DMA;
++
++}
++
++void
++xor_gemini_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++              unsigned long *p3)
++{
++      int status=0;
++      unsigned int flags;
++
++      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
++              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
++      }
++
++      spin_lock_irqsave(&raid_lock,flags);
++      if(tp.status != COMPLETE){
++              spin_unlock_irqrestore(&raid_lock, flags);
++              //printk("XOR yield3\n");
++#ifdef XOR_SW_FILL_IN
++              xor_arm4regs_3(bytes,p1,p2,p3);
++              return;
++#else
++              yield();
++#endif
++      }
++      spin_unlock_irqrestore(&raid_lock, flags);
++      tp.status = RUNNING;
++
++      // flush the cache to memory before H/W XOR touches them
++      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
++      consistent_sync(p2, bytes, DMA_TO_DEVICE);
++      consistent_sync(p3, bytes, DMA_TO_DEVICE);
++
++      tp.tx_desc = tp.tx_first_desc;
++      tp.rx_desc = tp.rx_first_desc;
++      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
++              // prepare tx descript
++              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
++              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00020000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p2);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x0000000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p3);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00010000;
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);                                                  // keep last descript
++
++      // prepare rx descript
++      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf);
++      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
++      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
++//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++
++      }
++      else{
++              /* no free tx descriptor */
++              printk("XOR:no free tx descript \n");
++              return ;
++      }
++
++      // change status
++//    tp.status = RUNNING;
++      status = tp.busy = 1;
++
++      // start tx DMA
++      rxdma_ctrl.bits.rd_start = 1;
++      // start rx DMA
++      txdma_ctrl.bits.td_start = 1;
++      wmb();
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
++      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
++
++#ifdef SPIN_WAIT
++      gemini_xor_isr(3);
++#else
++      xor_queue_descriptor();
++#endif
++      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*3) | 0x0B;
++      tp.status = COMPLETE;
++//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
++      //tp.rx_desc = tp.rx_first_desc ;
++//    tp.rx_desc->func_ctrl.bits.own = DMA;
++
++}
++
++void
++xor_gemini_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++              unsigned long *p3, unsigned long *p4)
++{
++      int status=0;
++      unsigned int flags;
++
++      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
++              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
++      }
++
++      spin_lock_irqsave(&raid_lock,flags);
++      if(tp.status != COMPLETE){
++              spin_unlock_irqrestore(&raid_lock, flags);
++              //printk("S\n");
++#ifdef XOR_SW_FILL_IN
++              xor_arm4regs_4(bytes,p1,p2,p3,p4);
++              return;
++#else
++              msleep(1);
++              yield();
++#endif
++      }
++      spin_unlock_irqrestore(&raid_lock, flags);
++
++      tp.status = RUNNING;
++
++      // flush the cache to memory before H/W XOR touches them
++      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
++      consistent_sync(p2, bytes, DMA_TO_DEVICE);
++      consistent_sync(p3, bytes, DMA_TO_DEVICE);
++      consistent_sync(p4, bytes, DMA_TO_DEVICE);
++
++      tp.tx_desc = tp.tx_first_desc;
++      tp.rx_desc = tp.rx_first_desc;
++      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
++              // prepare tx descript
++              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
++              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00020000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_cur_desc->buf_addr = (unsigned int)__pa(p2);              // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00000000;
++      tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p3);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00000000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p4);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00010000;
++//            tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);                                                  // keep last descript
++
++      // prepare rx descript
++      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
++      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
++      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
++//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++
++      }
++      else{
++              /* no free tx descriptor */
++              printk("XOR:no free tx descript");
++              return ;
++      }
++
++      // change status
++//    tp.status = RUNNING;
++      status = tp.busy = 1;
++
++      // start tx DMA
++      rxdma_ctrl.bits.rd_start = 1;
++      // start rx DMA
++      txdma_ctrl.bits.td_start = 1;
++      wmb();
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
++      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
++
++#ifdef SPIN_WAIT
++      gemini_xor_isr(4);
++#else
++      xor_queue_descriptor();
++#endif
++
++      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*4) | 0x0B;
++      tp.status = COMPLETE;
++//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
++      //tp.rx_desc = tp.rx_first_desc ;
++//    tp.rx_desc->func_ctrl.bits.own = DMA;
++
++}
++
++void
++xor_gemini_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++              unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++
++      int status=0;
++      unsigned int flags;
++
++
++      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
++              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
++      }
++
++      spin_lock_irqsave(&raid_lock,flags);
++      while(tp.status != COMPLETE){
++              spin_unlock_irqrestore(&raid_lock, flags);
++              //printk("XOR yield5\n");
++#ifdef XOR_SW_FILL_IN
++              xor_arm4regs_5(bytes,p1,p2,p3,p4,p5);
++              return;
++#else
++              msleep(1);
++              yield();
++#endif
++      }
++      spin_unlock_irqrestore(&raid_lock, flags);
++      tp.status = RUNNING;
++
++      // flush the cache to memory before H/W XOR touches them
++      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
++      consistent_sync(p2, bytes, DMA_TO_DEVICE);
++      consistent_sync(p3, bytes, DMA_TO_DEVICE);
++      consistent_sync(p4, bytes, DMA_TO_DEVICE);
++      consistent_sync(p5, bytes, DMA_TO_DEVICE);
++
++      tp.tx_desc = tp.tx_first_desc;
++      tp.rx_desc = tp.rx_first_desc;
++      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
++              // prepare tx descript
++              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
++              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00020000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      wmb();
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p2);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00000000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      wmb();
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p3);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00000000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      wmb();
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++              tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p4);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++              tp.tx_desc->flg_status.bits32 = 0x00000000;
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      wmb();
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++
++
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc->buf_addr = (unsigned int)__pa(p5);          // pysical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
++//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
++//            tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++              tp.tx_desc->flg_status.bits32 = 0x00010000;
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
++      tp.tx_finished_desc = tp.tx_desc;                                                               // keep last descript
++
++      // prepare rx descript
++      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
++      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
++      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
++//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++
++      }
++      else{
++              /* no free tx descriptor */
++              printk("XOR:no free tx descript");
++              return ;
++      }
++
++      // change status
++//    tp.status = RUNNING;
++      status = tp.busy = 1;
++
++      // start tx DMA
++      rxdma_ctrl.bits.rd_start = 1;
++      // start rx DMA
++      txdma_ctrl.bits.td_start = 1;
++      wmb();
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
++      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
++
++#ifdef SPIN_WAIT
++      gemini_xor_isr(5);
++#else
++      xor_queue_descriptor();
++#endif
++
++      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*5) | 0x0B;
++      tp.status = COMPLETE;
++//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
++      //tp.rx_desc = tp.rx_first_desc ;
++//    tp.rx_desc->func_ctrl.bits.own = DMA;
++
++}
++
++#ifdef XOR_TEST
++void
++raid_memset(unsigned int *p1, unsigned int pattern, unsigned int bytes)
++{
++      int status=0,i;
++
++      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
++              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
++      }
++
++      *p1 = pattern;
++
++      // flush the cache to memory before H/W XOR touches them
++      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
++
++      while(tp.status != COMPLETE){
++              DPRINTK("XOR yield\n");
++              //schedule();
++              yield();
++      }
++      tp.status = RUNNING;
++
++      tp.tx_desc = tp.tx_first_desc;
++      tp.rx_desc = tp.rx_first_desc;
++      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
++              // prepare tx descript
++              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
++              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = 4;             /* total frame byte count */
++      tp.tx_desc->flg_status.bits_cmd_status.bcc = bytes;                     // bytes to fill
++      tp.tx_desc->flg_status.bits_cmd_status.mode = CMD_FILL;         // only support memory FILL command
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
++//            tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
++
++      // prepare rx descript
++      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
++      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
++      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
++      tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++//            tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base);
++      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++      tp.rx_finished_desc = tp.rx_desc;
++
++      }
++      else{
++              /* no free tx descriptor */
++              printk("XOR:no free tx descript");
++              return ;
++      }
++
++      // change status
++      //tp.status = RUNNING;
++      status = tp.busy = 1;
++
++      // start tx DMA
++      rxdma_ctrl.bits.rd_start = 1;
++      // start rx DMA
++      txdma_ctrl.bits.td_start = 1;
++
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
++      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
++
++#ifdef SPIN_WAIT
++      gemini_xor_isr(2);
++#else
++      xor_queue_descriptor();
++#endif
++
++      for(i=1; i<(bytes/sizeof(int)); i++) {
++              if(p1[0]!=p1[i]){
++                      printk("pattern set error!\n");
++                      while(1);
++              }
++      }
++
++      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
++      tp.status = COMPLETE;
++//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
++      //tp.rx_desc = tp.rx_first_desc ;
++//    tp.rx_desc->func_ctrl.bits.own = DMA;
++
++}
++#endif
++
++void
++raid_memcpy(unsigned int *to, unsigned int *from, unsigned int bytes)
++{
++      int status=0,i;
++
++      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
++              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
++      }
++
++      // flush the cache to memory before H/W XOR touches them
++      consistent_sync(to, bytes, DMA_BIDIRECTIONAL);
++      consistent_sync(from,bytes, DMA_TO_DEVICE);
++
++      while(tp.status != COMPLETE){
++              DPRINTK("XOR yield\n");
++              //schedule();
++              yield();
++      }
++      tp.status = RUNNING;
++
++      tp.tx_desc = tp.tx_first_desc;
++      tp.rx_desc = tp.rx_first_desc;
++      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
++              // prepare tx descript
++              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
++              tp.tx_desc->buf_addr = (unsigned int)__pa(from);                // physical address
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++      tp.tx_desc->flg_status.bits32 = CMD_CPY;                // only support memory FILL command
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
++//            tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
++
++      // prepare rx descript
++      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
++      tp.rx_desc->buf_addr = (unsigned int)__pa(to);
++      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
++      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
++      tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++//            tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base);
++      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
++
++      }
++      else{
++              /* no free tx descriptor */
++              printk("XOR:no free tx descript");
++              return ;
++      }
++
++      // change status
++      //tp.status = RUNNING;
++      status = tp.busy = 1;
++
++      // start tx DMA
++      rxdma_ctrl.bits.rd_start = 1;
++      // start rx DMA
++      txdma_ctrl.bits.td_start = 1;
++
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
++      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
++
++#ifdef SPIN_WAIT
++      gemini_xor_isr(2);
++#else
++      xor_queue_descriptor();
++#endif
++
++#ifdef XOR_TEST
++      for(i=1; i<(bytes/sizeof(int)); i++) {
++              if(to[i]!=from[i]){
++                      printk("pattern check error!\n");
++                      printk("offset=0x%x p1=%x p2=%x\n",i*4,to[i],from[i]);
++                      while(1);
++              }
++      }
++#endif
++
++      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
++      tp.status = COMPLETE;
++//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
++      //tp.rx_desc = tp.rx_first_desc ;
++//    tp.rx_desc->func_ctrl.bits.own = DMA;
++
++}
++EXPORT_SYMBOL(raid_memcpy);
++
++#ifdef XOR_TEST
++int
++raid_memchk(unsigned int *p1, unsigned int pattern, unsigned int bytes)
++{
++      int status=0;
++      RAID_DMA_STATUS_T       dma_status;
++
++      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
++              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
++      }
++
++      status = ((pattern&0xFFFF)%bytes )/4;
++      p1[status] = pattern;
++
++      while(tp.status != COMPLETE){
++              DPRINTK("XOR yield\n");
++              //schedule();
++              yield();
++      }
++      tp.status = RUNNING;
++
++      // flush the cache to memory before H/W XOR touches them
++      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
++
++      tp.tx_desc = tp.tx_first_desc;
++      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
++              // prepare tx descript
++              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
++              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
++      tp.tx_desc->func_ctrl.bits.raid_ctrl_status = 0;
++      tp.tx_desc->func_ctrl.bits.buffer_size = bytes ;                /* total frame byte count */
++      tp.tx_desc->flg_status.bits32 = CMD_CHK;                // only support memory FILL command
++      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
++      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
++      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
++//            tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
++
++      }
++      else{
++              /* no free tx descriptor */
++              printk("XOR:no free tx descript");
++              return -1;
++      }
++
++      // change status
++      //tp.status = RUNNING;
++      status = tp.busy = 1;
++
++      // start tx DMA
++      txdma_ctrl.bits.td_start = 1;
++
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
++//    raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
++
++#ifdef SPIN_WAIT
++      gemini_xor_isr(2);
++#else
++      xor_queue_descriptor();
++#endif
++
++//    dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
++//    if (dma_status.bits32 & (1<<15))        {
++
++      if((tp.tx_first_desc->func_ctrl.bits.raid_ctrl_status & 0x2)) {
++              status = 1;
++//            raid_write_reg(RAID_DMA_STATUS,0x00008000,0x00080000);
++      }
++      else{
++              status = 0;
++      }
++
++      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
++      tp.status = COMPLETE;
++//    tp.rx_desc->func_ctrl.bits.own = DMA;
++      return status ;
++}
++#endif
++
++int __init gemini_xor_init(void)
++{
++      unsigned int res;
++      unsigned int *paddr1,*paddr2,*paddr3,i;
++      unsigned volatile char  *charact;
++      unsigned volatile short *two_char;
++      unsigned volatile int   *four_char;
++
++      // init descript
++      res = gemini_xor_init_desc();
++      if(res) {
++              printk("Init RAID Descript Fail!!\n");
++              return -res;
++      }
++
++      tp.device_name = "Gemini XOR Acceleration";
++
++      // request irq
++#ifndef SPIN_WAIT
++      res = request_irq(IRQ_RAID, gemini_xor_isr, SA_INTERRUPT, tp.device_name, NULL);
++#endif
++      if(res){
++              printk(KERN_ERR "%s: unable to request IRQ %d for "
++                     "HW XOR %d\n", tp.device_name, IRQ_RAID, res);
++              return -EBUSY;
++      }
++
++#ifdef XOR_TEST
++
++RETEST:
++      paddr1 = kmalloc(0x1000,GFP_KERNEL);
++      paddr2 = kmalloc(0x1000,GFP_KERNEL);
++      paddr3 = kmalloc(0x1000,GFP_KERNEL);
++      for(i=0;i<TEST_ITERATION;i++) {
++              printk("XOR test round %d\n",i);
++              for(res=0;res<(0x1000)/sizeof(int);res++){              // prepare data pattern
++                      paddr1[res]= readl(0xf62000ac);
++                      paddr2[res]= readl(0xf62000ac);
++              }
++              for(res=0;res<0x1000/sizeof(int);res++){                // calculate xor by software
++                      paddr3[res] = paddr1[res]^paddr2[res];
++              }
++              xor_gemini_2(0x1000,paddr1,paddr2);                             // calculate xor by hw
++              for(res=0;res<0x1000/sizeof(int);res++){                // check error
++                      if(paddr1[res]!=paddr3[res]){
++                              printk("XOR ERROR\n");
++                              printk("[%d][0x%x]=0x%x should be %x\n",res,&paddr1[res],paddr1[res],paddr3[res]);
++                              while(1);
++                      }
++              }
++      }
++      kfree(paddr1);
++      kfree(paddr2);
++      kfree(paddr3);
++
++
++      // memcpy test
++      paddr1 = kmalloc(0x4000,GFP_KERNEL);
++      for(i=0;i<TEST_ITERATION;i++) {
++              for(res=0;res<(0x4000)/sizeof(int);res++)
++                      paddr1[res]= readl(0xf62000ac);
++
++              printk("MEMCOPY round %d\n",i);
++              paddr2 = kmalloc(0x4000,GFP_KERNEL);
++              raid_memcpy(paddr2,paddr1,0x4000);
++              kfree(paddr2);
++      }
++      kfree(paddr1);
++
++      // memset test
++      for(i=0;i<TEST_ITERATION;i++) {
++              raid_memset(paddr1,0xFFFFFFFF,0x4000);
++              res = readl(0xf62000ac);
++              printk("MEMFILL fill 0x%x round %d\n",res,i);
++              paddr1 = kmalloc(0x4000,GFP_KERNEL);
++              raid_memset(paddr1,res,0x4000);
++              raid_memset(paddr1,0x0,0x4000);
++              kfree(paddr1);
++      }
++
++      paddr1 = kmalloc(0x4000,GFP_KERNEL);
++      for(i=0;i<TEST_ITERATION;i++){
++              raid_memset(paddr1, i,0x4000);
++              printk("Pattern check same ? ");
++              res = raid_memchk(paddr1, i,0x4000);
++              printk("%s\n",res?"Fail":"OK");
++              if(res) while(1);
++
++              printk("Pattern check diff ? ");
++              res = raid_memchk(paddr1,readl(0xf62000ac),0x4000);
++              printk("%s\n",res?"OK":"Fail");
++              if(!res)        while(1);
++      }
++      kfree(paddr1);
++
++      // SRAM test
++      raid_write_reg(RAID_PCR, 0,0x00000003);
++      for(i=0;i<TEST_ITERATION;i++) {
++              printk("SRAM test %d\n",i);
++              charact = 0xF7000000;
++              two_char = 0xF7000000;
++              four_char = 0xF7000000;
++              for(res=0;res<(16*1024)/sizeof(char);res++) {           // 8-bit access
++                      *charact++ = (unsigned char)res;
++              }
++              charact = 0xF7000000;
++              for(res=0;res<(16*1024)/sizeof(char);res++) {
++                      if(*charact++ != (unsigned char)res){
++                              printk("SRAM data error(8)\n");
++                              while(1);
++                      }
++              }
++
++              for(res=0;res<(16*1024)/sizeof(short);res++) {          // 16-bit access
++                      *two_char++ = (unsigned short)res;
++              }
++              two_char = 0xF7000000;
++              for(res=0;res<(16*1024)/sizeof(short);res++) {
++                      if(*two_char++ != (unsigned short)res){
++                              printk("SRAM data error(16)\n");
++                              while(1);
++                      }
++              }
++
++              for(res=0;res<(16*1024)/sizeof(int);res++) {            // 32-bit access
++                      *four_char++ = (unsigned int)res;
++              }
++              four_char = 0xF7000000;
++              for(res=0;res<(16*1024)/sizeof(int);res++) {
++                      if(*four_char++ != (unsigned int)res){
++                              printk("SRAM data error(32)\n");
++                              while(1);
++                      }
++              }
++      }
++      raid_write_reg(RAID_PCR, SRAM_PAR_SIZE,0x00000003);
++
++#endif
++      return 0;
++}
++
++void __exit gemini_xor_exit(void)
++{
++      DMA_MFREE(tp.tx_desc, TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(unsigned int)tp.tx_desc_dma);
++      DMA_MFREE(tp.rx_desc, RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(unsigned int)tp.rx_desc_dma);
++      free_irq(IRQ_RAID, NULL);
++}
++
++
++static int gemini_xor_init_desc(void)
++{
++      unsigned int i;
++      dma_addr_t          tx_first_desc_dma;
++      dma_addr_t          rx_first_desc_dma;
++      RAID_DMA_STATUS_T       dma_status;
++
++      printk("Initial RAID Descripter...\n");
++
++      tp.tx_desc = (RAID_DESCRIPTOR_T*)DMA_MALLOC(TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t *)&tp.tx_desc_dma);
++    tx_desc_virtual_base = (unsigned int)tp.tx_desc - (unsigned int)tp.tx_desc_dma;
++    memset(tp.tx_desc,0x00,TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T));
++
++      tp.rx_desc = (RAID_DESCRIPTOR_T*)DMA_MALLOC(RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t *)&tp.rx_desc_dma);
++    rx_desc_virtual_base = (unsigned int)tp.rx_desc - (unsigned int)tp.rx_desc_dma;
++    memset(tp.rx_desc,0x00,RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T));
++      printk("XOR:tx_desc = %08x\n",(unsigned int)tp.tx_desc);
++    printk("XOR:rx_desc = %08x\n",(unsigned int)tp.rx_desc);
++      printk("XOR:tx_desc_dma = %08x\n",(unsigned int)tp.tx_desc_dma);
++      printk("XOR:rx_desc_dma = %08x\n",(unsigned int)tp.rx_desc_dma);
++
++      if ((tp.tx_desc == NULL) || (tp.rx_desc == NULL)) {
++              if (tp.tx_desc)
++                      DMA_MFREE(tp.tx_desc, TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t)tp.tx_desc_dma);
++              if (tp.rx_desc)
++                      DMA_MFREE(tp.rx_desc, RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t)tp.rx_desc_dma);
++              return -ENOMEM;
++      }
++
++      tp.tx_cur_desc = tp.tx_desc;  /* virtual address */
++      tp.tx_finished_desc = tp.tx_desc; /* virtual address */
++      tx_first_desc_dma = (dma_addr_t)tp.tx_desc_dma; /* physical address */
++      for (i = 1; i < TX_DESC_NUM; i++) {
++              tp.tx_desc->func_ctrl.bits.own = CPU;
++              tp.tx_desc->func_ctrl.bits.buffer_size = 0;
++              tp.tx_desc_dma = tp.tx_desc_dma + sizeof(RAID_DESCRIPTOR_T);
++//            tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tp.tx_desc_dma | 0x0B;
++              tp.tx_desc->next_desc_addr.bits32 = ((unsigned int)tx_first_desc_dma | 0x0B) + i*0x10;
++              tp.tx_desc = &tp.tx_desc[1];
++      }
++      tp.tx_desc->func_ctrl.bits.own = DMA;
++      tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tx_first_desc_dma|0x0b;
++      tp.tx_desc = tp.tx_cur_desc;
++      tp.tx_desc_dma = (unsigned int*)tx_first_desc_dma;
++      tp.tx_first_desc = tp.tx_desc ;
++
++      tp.rx_cur_desc = tp.rx_desc;  /* virtual address */
++      tp.rx_finished_desc = tp.rx_desc; /* virtual address */
++      rx_first_desc_dma = (dma_addr_t)tp.rx_desc_dma; /* physical address */
++      for (i = 1; i < RX_DESC_NUM; i++) {
++              tp.rx_desc->func_ctrl.bits.own = DMA;
++              tp.rx_desc->func_ctrl.bits.buffer_size = 0;
++              tp.rx_desc_dma = tp.rx_desc_dma + sizeof(RAID_DESCRIPTOR_T);
++//            tp.rx_desc->next_desc_addr.bits32 = (unsigned int)tp.rx_desc_dma | 0x0B;
++              tp.rx_desc->next_desc_addr.bits32 = ((unsigned int)rx_first_desc_dma | 0x0B) + i*0x10;
++              tp.rx_desc = &tp.rx_desc[1];
++      }
++      tp.rx_desc->func_ctrl.bits.own = DMA;
++      tp.rx_desc->next_desc_addr.bits32 = rx_first_desc_dma|0x0b;
++      tp.rx_desc = tp.rx_cur_desc;
++      tp.rx_desc_dma = (unsigned int*)rx_first_desc_dma;
++      tp.rx_first_desc = tp.rx_desc ;
++      tp.busy = 0;
++      tp.status = COMPLETE;
++
++      // Partition SRAM size
++      raid_write_reg(RAID_PCR, SRAM_PAR_SIZE,0x00000003);
++
++      // config tx DMA controler
++      txdma_ctrl.bits32 = 0;
++      txdma_ctrl.bits.td_start = 0;
++      txdma_ctrl.bits.td_continue = 1;
++      txdma_ctrl.bits.td_chain_mode = 1;
++      txdma_ctrl.bits.td_prot = 0;
++      txdma_ctrl.bits.td_burst_size = 1;
++      txdma_ctrl.bits.td_bus = 3;
++      txdma_ctrl.bits.td_endian = 0;
++      txdma_ctrl.bits.td_finish_en = 1;
++      txdma_ctrl.bits.td_fail_en = 1;
++      txdma_ctrl.bits.td_perr_en = 1;
++      txdma_ctrl.bits.td_eod_en = 0;  // enable tx descript
++      txdma_ctrl.bits.td_eof_en = 0;
++      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0xFFFFFFFF);
++
++      // config rx DMA controler
++      rxdma_ctrl.bits32 = 0;
++      rxdma_ctrl.bits.rd_start = 0;
++      rxdma_ctrl.bits.rd_continue = 1;
++      rxdma_ctrl.bits.rd_chain_mode = 1;
++      rxdma_ctrl.bits.rd_prot = 0;
++      rxdma_ctrl.bits.rd_burst_size = 1;
++      rxdma_ctrl.bits.rd_bus = 3;
++      rxdma_ctrl.bits.rd_endian = 0;
++      rxdma_ctrl.bits.rd_finish_en = 0;
++      rxdma_ctrl.bits.rd_fail_en = 1;
++      rxdma_ctrl.bits.rd_perr_en = 1;
++      rxdma_ctrl.bits.rd_eod_en = 0;
++      rxdma_ctrl.bits.rd_eof_en = 0;
++      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0xFFFFFFFF);
++
++      // enable interrupt
++      dma_status.bits32 = 3;  // enable RpInt
++      raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0xFFFFFFFF);
++
++      return 0;
++}
++
++module_init(gemini_xor_init);
++module_exit(gemini_xor_exit);
++
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -187,6 +187,26 @@
+         Say Y if you want support for the ARM926T processor.
+         Otherwise, say N.
++###### for Storlink SoC ######
++config CPU_FA526
++      bool "FA526 processor"
++      depends on ARCH_SL2312
++      default y
++      select CPU_32v4
++      select CPU_ABRT_EV4
++      select CPU_CACHE_FA
++      select CPU_CACHE_VIVT
++      select CPU_CP15_MMU
++      select CPU_COPY_FA
++      select CPU_TLB_FA
++      select CPU_FA_BTB
++      help
++        The FA526 is a version of the ARM9 compatible processor, but with smaller
++        instruction and data caches. It is used in Storlink Sword device family.
++
++        Say Y if you want support for the FA526 processor.
++        Otherwise, say N.
++
+ # ARM940T
+ config CPU_ARM940T
+       bool "Support ARM940T processor" if ARCH_INTEGRATOR
+@@ -461,6 +481,9 @@
+ config CPU_CACHE_VIPT
+       bool
++config CPU_CACHE_FA
++      bool
++
+ if MMU
+ # The copy-page model
+ config CPU_COPY_V3
+@@ -475,6 +498,12 @@
+ config CPU_COPY_V6
+       bool
++config CPU_COPY_FA
++      bool
++
++config CPU_FA_BTB
++      bool
++
+ # This selects the TLB model
+ config CPU_TLB_V3
+       bool
+@@ -534,6 +563,14 @@
+ config IO_36
+       bool
++config CPU_TLB_FA
++      bool
++      help
++        //TODO
++        Faraday ARM FA526 architecture, unified TLB with writeback cache
++        and invalidate instruction cache entry. Branch target buffer is also
++        supported.
++
+ comment "Processor Features"
+ config ARM_THUMB
+@@ -600,7 +637,7 @@
+ config CPU_DCACHE_WRITETHROUGH
+       bool "Force write through D-cache"
+-      depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
++      depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FA526) && !CPU_DCACHE_DISABLE
+       default y if CPU_ARM925T
+       help
+         Say Y here to use the data cache in writethrough mode. Unless you
+--- a/arch/arm/mm/Makefile
++++ b/arch/arm/mm/Makefile
+@@ -32,6 +32,7 @@
+ obj-$(CONFIG_CPU_CACHE_V4WB)  += cache-v4wb.o
+ obj-$(CONFIG_CPU_CACHE_V6)    += cache-v6.o
+ obj-$(CONFIG_CPU_CACHE_V7)    += cache-v7.o
++obj-$(CONFIG_CPU_CACHE_FA)    += cache-fa.o
+ obj-$(CONFIG_CPU_COPY_V3)     += copypage-v3.o
+ obj-$(CONFIG_CPU_COPY_V4WT)   += copypage-v4wt.o
+@@ -40,6 +41,7 @@
+ obj-$(CONFIG_CPU_SA1100)      += copypage-v4mc.o
+ obj-$(CONFIG_CPU_XSCALE)      += copypage-xscale.o
+ obj-$(CONFIG_CPU_XSC3)                += copypage-xsc3.o
++obj-$(CONFIG_CPU_COPY_FA)     += copypage-fa.o
+ obj-$(CONFIG_CPU_TLB_V3)      += tlb-v3.o
+ obj-$(CONFIG_CPU_TLB_V4WT)    += tlb-v4.o
+@@ -47,6 +49,7 @@
+ obj-$(CONFIG_CPU_TLB_V4WBI)   += tlb-v4wbi.o
+ obj-$(CONFIG_CPU_TLB_V6)      += tlb-v6.o
+ obj-$(CONFIG_CPU_TLB_V7)      += tlb-v7.o
++obj-$(CONFIG_CPU_TLB_FA)      += tlb-fa.o
+ obj-$(CONFIG_CPU_ARM610)      += proc-arm6_7.o
+ obj-$(CONFIG_CPU_ARM710)      += proc-arm6_7.o
+@@ -60,6 +63,7 @@
+ obj-$(CONFIG_CPU_ARM926T)     += proc-arm926.o
+ obj-$(CONFIG_CPU_ARM940T)     += proc-arm940.o
+ obj-$(CONFIG_CPU_ARM946E)     += proc-arm946.o
++obj-$(CONFIG_CPU_FA526)               += proc-fa526.o
+ obj-$(CONFIG_CPU_ARM1020)     += proc-arm1020.o
+ obj-$(CONFIG_CPU_ARM1020E)    += proc-arm1020e.o
+ obj-$(CONFIG_CPU_ARM1022)     += proc-arm1022.o
+--- /dev/null
++++ b/arch/arm/mm/cache-fa.S
+@@ -0,0 +1,400 @@
++/*
++ *  linux/arch/arm/mm/cache-fa.S
++ *
++ *  Copyright (C) 2005 Faraday Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  Processors: FA520 FA526 FA626     
++ * 03/31/2005 :       Luke Lee created, modified from cache-v4wb.S
++ * 04/06/2005 :       1. Read CR0-1 and determine the cache size dynamically,
++ *               to suit all Faraday CPU series
++ *            2. Fixed all functions
++ * 04/08/2005 :       insert CONFIG_CPU_ICACHE_DISABLE and CONFIG_CPU_DCACHE_DISABLE
++ * 04/12/2005 :       TODO: make this processor dependent or a self-modifying code to 
++ *            inline cache len/size info into the instructions, as reading cache 
++ *            size and len info in memory could cause another cache miss.
++ * 05/05/2005 :       Modify fa_flush_user_cache_range to comply APCS.
++ * 05/19/2005 :       Adjust for boundary conditions.
++ */
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <asm/hardware.h>
++#include <asm/page.h>
++#include "proc-macros.S"
++
++#define CACHE_DLINESIZE          16
++#ifdef CONFIG_SL3516_ASIC
++#define CACHE_DSIZE      8192
++#else
++#define CACHE_DSIZE      16384 
++#endif 
++#define CACHE_ILINESIZE          16
++#define CACHE_ISIZE      16384
++
++/* Luke Lee 04/06/2005 ins begin */
++/*
++ *    initialize_cache_info()
++ *
++ *    Automatic detection of DSIZE, DLEN, ISIZE, ILEN variables according to 
++ *    system register CR0-1
++ *    Destroyed register: r0, r1, r2, r3, ip
++ */
++      .align
++ENTRY(fa_initialize_cache_info)
++      mov     r3, #1                          @ r3 always = 1
++      adr     ip, __fa_cache_ilen
++      
++      mrc     p15, 0, r0, c0, c0, 1
++      /* ILEN */
++      and     r1, r0, #3                      @ bits [1:0]
++      add     r1, r1, #3                      @ cache line size is at least 8 bytes (2^3)
++      mov     r2, r3, lsl r1                  @ r2 = 1<<r1
++      str     r2, [ip], #4
++      /* ISIZE */
++      mov     r1, r0, lsr #6                  @ bits [8:6]
++      and     r1, r1, #7
++      add     r1, r1, #9                      @ cache size is at least 512 bytes (2^9)
++      mov     r2, r3, lsl r1
++      str     r2, [ip], #4
++      /* DLEN */
++      mov     r1, r0, lsr #12
++      and     r1, r1, #3                      @ bits [13:12]
++      add     r1, r1, #3                      @ cache line size is at least 8 bytes (2^3)
++      mov     r2, r3, lsl r1                  @ r2 = 1<<r1
++      str     r2, [ip], #4
++      /* DSIZE */
++      mov     r1, r0, lsr #18                 @ bits [20:18]
++      and     r1, r1, #7
++      add     r1, r1, #9                      @ cache size is at least 512 bytes (2^9)
++      mov     r2, r3, lsl r1
++      str     r2, [ip]
++      mov     pc, lr
++
++      /* Warning : Do not change the order ! Successive codes depends on this */
++      .align
++      .globl __fa_cache_ilen, __fa_cache_isize, __fa_cache_dlen, __fa_cache_dsize
++__fa_cache_ilen:
++      .word   0                               @ instruction cache line length
++__fa_cache_isize:
++      .word   0                               @ instruction cache size
++__fa_cache_dlen:
++      .word   0                               @ data cahce line length        
++__fa_cache_dsize:
++      .word   0                               @ data cache size
++
++/* Luke Lee 04/06/2005 ins end */
++
++/*
++ *    flush_user_cache_all()
++ *
++ *    Clean and invalidate all cache entries in a particular address
++ *    space.
++ */
++ENTRY(fa_flush_user_cache_all)
++      /* FALLTHROUGH */
++/*
++ *    flush_kern_cache_all()
++ *
++ *    Clean and invalidate the entire cache.
++ */
++ENTRY(fa_flush_kern_cache_all)
++/* Luke Lee 04/06/2005 mod ok */
++      mov     ip, #0
++      
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++      mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
++#endif
++      
++__flush_whole_cache:
++      
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++      mov     ip, #0
++#  ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
++#  else
++      mcr     p15, 0, ip, c7,c14, 0           @ clean/invalidate D cache
++#  endif
++#endif /*CONFIG_CPU_DCACHE_DISABLE*/
++      
++#ifndef CONFIG_CPU_FA_WB_DISABLE      
++      mcr     p15, 0, ip, c7, c10, 4          @ drain write buffer
++#endif
++      
++#ifdef CONFIG_CPU_FA_BTB
++      mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB
++      nop
++      nop
++#endif
++      
++/* Luke Lee 04/06/2005 que todo tofix : should iscratchpad and dscratchpad be invalidated ? */
++      mov     pc, lr
++
++/*
++ *    flush_user_cache_range(start, end, flags)
++ *
++ *    Invalidate a range of cache entries in the specified
++ *    address space.
++ *
++ *    - start - start address (inclusive, page aligned)
++ *    - end   - end address (exclusive, page aligned)
++ *    - flags - vma_area_struct flags describing address space
++ */
++ENTRY(fa_flush_user_cache_range)
++
++/* Luke Lee 04/06/2005 mod ok */
++      /* Luke Lee 04/07/2005 ins 1 */
++      mov     ip, #0
++      sub     r3, r1, r0                      @ calculate total size
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++      tst     r2, #VM_EXEC                    @ executable region?
++      mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
++#endif
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE     
++      /* Luke Lee 04/06/2005 ins 2 mod 1 */
++      cmp     r3, #CACHE_DSIZE                @ total size >= limit?
++      bhs     __flush_whole_cache             @ flush whole D cache
++
++      //debug_Aaron
++        bic     r0, r0, #CACHE_DLINESIZE-1  
++      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate boundary D entry
++        bic     r1, r1, #CACHE_DLINESIZE-1  
++      mcr     p15, 0, r1, c7, c14, 1          @ clean and invalidate boundary D entry
++
++
++1:    /* Luke Lee 04/06/2005 del 2 ins 5 */
++      
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
++#else
++      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
++#endif
++      /* Luke Lee 04/06/2005 mod 1 */
++      add     r0, r0, #CACHE_DLINESIZE
++      cmp     r0, r1
++      bls     1b                              @ Luke Lee 05/19/2005
++#endif        /* CONFIG_CPU_DCACHE_DISABLE */
++      
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      tst     r2, #VM_EXEC
++      /* Luke Lee 04/06/2005 mod 1 tofix todo : ne->eq */
++      mcreq   p15, 0, r4, c7, c10, 4          @ drain write buffer
++#endif
++
++      /* Luke Lee 04/06/2005 ins block */
++#ifdef CONFIG_CPU_FA_BTB
++        tst     r2, #VM_EXEC
++      mov     ip, #0
++      mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
++      nop
++      nop
++#endif
++      mov     pc, lr
++
++/*
++ *    flush_kern_dcache_page(void *page)
++ *
++ *    Ensure no D cache aliasing occurs, either with itself or
++ *    the I cache
++ *
++ *    - addr  - page aligned address
++ */
++ENTRY(fa_flush_kern_dcache_page)
++      add     r1, r0, #PAGE_SZ
++      /* fall through */
++
++/*
++ *    coherent_kern_range(start, end)
++ *
++ *    Ensure coherency between the Icache and the Dcache in the
++ *    region described by start.  If you have non-snooping
++ *    Harvard caches, you need to implement this function.
++ *
++ *    - start  - virtual start address
++ *    - end    - virtual end address
++ */
++ENTRY(fa_coherent_kern_range)
++      /* fall through */
++
++/*
++ *    coherent_user_range(start, end)
++ *
++ *    Ensure coherency between the Icache and the Dcache in the
++ *    region described by start.  If you have non-snooping
++ *    Harvard caches, you need to implement this function.
++ *
++ *    - start  - virtual start address
++ *    - end    - virtual end address
++ */
++ENTRY(fa_coherent_user_range)
++
++/* Luke Lee 04/06/2005 mod ok */
++      /* Luke Lee 04/06/2005 ins 3 mod 1 */
++      bic     r0, r0, #CACHE_DLINESIZE-1
++
++ //debug_Aaron
++        bic     r0, r0, #CACHE_DLINESIZE-1
++        mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate boundary D entry
++        bic     r1, r1, #CACHE_DLINESIZE-1
++        mcr     p15, 0, r1, c7, c14, 1          @ clean and invalidate boundary D entry
++
++#if !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE))
++1:    /* Luke Lee 04/06/2005 del 2 ins 5 mod 1 */
++#ifndef CONFIG_CPU_DCACHE_DISABLE     
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
++#else
++      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
++#endif
++#endif /* CONFIG_CPU_DCACHE_DISABLE */
++      
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++      mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
++#endif
++      add     r0, r0, #CACHE_DLINESIZE
++      cmp     r0, r1
++      bls     1b                              @ Luke Lee 05/19/2005 blo->bls  
++#endif /* !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) */
++
++      mov     ip, #0
++#ifdef CONFIG_CPU_FA_BTB
++      mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB
++      nop
++      nop
++#endif
++
++/* Luke Lee 04/08/2005 ins 1 skp 1 ins 1 */
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mcr     p15, 0, ip, c7, c10, 4          @ drain WB
++#endif
++
++      mov     pc, lr
++
++/*
++ *    dma_inv_range(start, end)
++ *
++ *    Invalidate (discard) the specified virtual address range.
++ *    May not write back any entries.  If 'start' or 'end'
++ *    are not cache line aligned, those lines must be written
++ *    back.
++ *
++ *    - start  - virtual start address
++ *    - end    - virtual end address
++ */
++ENTRY(fa_dma_inv_range)
++
++/* Luke Lee 04/06/2005 mod ok */
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE     
++
++ //debug_Aaron
++        bic     r0, r0, #CACHE_DLINESIZE-1
++        mcr     p15, 0, r0, c7, c6, 1          @ invalidate boundary D entry
++        bic     r1, r1, #CACHE_DLINESIZE-1
++        mcr     p15, 0, r1, c7, c6, 1          @ invalidate boundary D entry
++
++      /* Luke Lee 04/06/2005 ins 4 mod 2 */
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++      tst     r0, #CACHE_DLINESIZE -1
++      bic     r0, r0, #CACHE_DLINESIZE -1
++
++//debug_Aaron
++      //mcrne p15, 0, r0, c7, c10, 1          @ clean boundary D entry
++
++      /* Luke Lee 04/06/2005 mod 1 */
++      /* Luke Lee 05/19/2005 always clean the end-point boundary mcrne->mcr */
++      ////tst r1, #CACHE_DLINESIZE -1
++      //mcr   p15, 0, r1, c7, c10, 1          @ clean boundary D entry
++      /* Luke Lee 04/06/2005 ins 1 */
++#else
++      bic     r0, r0, #CACHE_DLINESIZE -1     
++#endif
++
++//debug_Aaron 
++1:    mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
++//1:  mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
++
++      /* Luke Lee 04/06/2005 mod 1 */ 
++      add     r0, r0, #CACHE_DLINESIZE
++      cmp     r0, r1
++      bls     1b                              @ Luke Lee 05/19/2005 blo->bls
++#endif /* CONFIG_CPU_DCACHE_DISABLE */
++
++      /* Luke Lee 04/06/2005 ins 1 */         
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mov     r0, #0
++      mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
++#endif        
++
++      mov     pc, lr
++
++/*
++ *    dma_clean_range(start, end)
++ *
++ *    Clean (write back) the specified virtual address range.
++ *
++ *    - start  - virtual start address
++ *    - end    - virtual end address
++ */
++ENTRY(fa_dma_clean_range)
++
++/* Luke Lee 04/06/2005 mod ok */
++#ifndef CONFIG_CPU_DCACHE_DISABLE     
++
++ //debug_Aaron
++        bic     r0, r0, #CACHE_DLINESIZE-1
++        mcr     p15, 0, r0, c7, c10, 1          @ clean boundary D entry
++        bic     r1, r1, #CACHE_DLINESIZE-1
++        mcr     p15, 0, r1, c7, c10, 1          @ clean boundary D entry
++
++      /* Luke Lee 04/06/2005 ins 4 mod 2 */
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++      bic     r0, r0, #CACHE_DLINESIZE - 1
++
++//debug_Aaron
++1:    mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
++//1:  mcr     p15, 0, r0, c7, c14, 1          @ clean D entry
++      add     r0, r0, #CACHE_DLINESIZE
++      cmp     r0, r1
++      bls     1b                              @ Luke Lee 05/19/2005 blo->bls
++      /* Luke Lee 04/06/2005 ins 2 */
++#endif
++#endif /* CONFIG_CPU_DCACHE_DISABLE */
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mov     r0, #0  
++      mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
++#endif        
++
++      mov     pc, lr
++
++/*
++ *    dma_flush_range(start, end)
++ *
++ *    Clean and invalidate the specified virtual address range.
++ *
++ *    - start  - virtual start address
++ *    - end    - virtual end address
++ *
++ *    This is actually the same as fa_coherent_kern_range()
++ */
++      .globl  fa_dma_flush_range
++      .set    fa_dma_flush_range, fa_coherent_kern_range
++
++      __INITDATA
++
++      .type   fa_cache_fns, #object
++ENTRY(fa_cache_fns)
++      .long   fa_flush_kern_cache_all
++      .long   fa_flush_user_cache_all
++      .long   fa_flush_user_cache_range
++      .long   fa_coherent_kern_range
++      .long   fa_coherent_user_range
++      .long   fa_flush_kern_dcache_page
++      .long   fa_dma_inv_range
++      .long   fa_dma_clean_range
++      .long   fa_dma_flush_range
++      .size   fa_cache_fns, . - fa_cache_fns
+--- /dev/null
++++ b/arch/arm/mm/copypage-fa.S
+@@ -0,0 +1,106 @@
++/*
++ *  linux/arch/arm/lib/copypage-fa.S
++ *
++ *  Copyright (C) 2005 Faraday Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  ASM optimised string functions
++ * 05/18/2005 :       Luke Lee created, modified from copypage-v4wb.S
++ */
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <asm/asm-offsets.h>
++
++      .text
++/*
++ * ARMv4 optimised copy_user_page for Faraday processors
++ *
++ * We flush the destination cache lines just before we write the data into the
++ * corresponding address.  Since the Dcache is read-allocate, this removes the
++ * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
++ * and merged as appropriate.
++ *
++ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
++ * instruction.  If your processor does not supply this, you have to write your
++ * own copy_user_page that does the right thing.
++ *
++ * copy_user_page(to,from,vaddr)
++ */
++      .align  4
++ENTRY(fa_copy_user_page)
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      /* Write through */
++      stmfd   sp!, {r4, lr}                   @ 2
++      mov     r2, #PAGE_SZ/32                 @ 1
++
++      ldmia   r1!, {r3, r4, ip, lr}           @ 4
++1:    stmia   r0!, {r3, r4, ip, lr}           @ 4
++      ldmia   r1!, {r3, r4, ip, lr}           @ 4+1
++      subs    r2, r2, #1                      @ 1
++      stmia   r0!, {r3, r4, ip, lr}           @ 4
++      ldmneia r1!, {r3, r4, ip, lr}           @ 4
++      bne     1b                              @ 1
++
++      mcr     p15, 0, r2, c7, c7, 0           @ flush ID cache
++      ldmfd   sp!, {r4, pc}                   @ 3
++#else
++      /* Write back */
++      stmfd   sp!, {r4, lr}                   @ 2
++      mov     r2, #PAGE_SZ/32                 @ 1
++
++1:    ldmia   r1!, {r3, r4, ip, lr}           @ 4
++      mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
++      stmia   r0!, {r3, r4, ip, lr}           @ 4
++      ldmia   r1!, {r3, r4, ip, lr}           @ 4
++      mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
++      stmia   r0!, {r3, r4, ip, lr}           @ 4
++      subs    r2, r2, #1                      @ 1
++      bne     1b
++      mcr     p15, 0, r2, c7, c10, 4          @ 1   drain WB
++      ldmfd   sp!, {r4, pc}                   @ 3
++#endif
++
++/*
++ * ARMv4 optimised clear_user_page
++ *
++ * Same story as above.
++ */
++      .align  4
++ENTRY(fa_clear_user_page)
++      str     lr, [sp, #-4]!
++      mov     r1, #PAGE_SZ/32                 @ 1
++      mov     r2, #0                          @ 1
++      mov     r3, #0                          @ 1
++      mov     ip, #0                          @ 1
++      mov     lr, #0                          @ 1
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      /* Write through */
++1:    stmia   r0!, {r2, r3, ip, lr}           @ 4
++      stmia   r0!, {r2, r3, ip, lr}           @ 4
++      subs    r1, r1, #1                      @ 1
++      bne     1b                              @ 1
++
++      mcr     p15, 0, r1, c7, c7, 0           @ flush ID cache
++      ldr     pc, [sp], #4
++#else
++      /* Write back */
++1:    mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
++      stmia   r0!, {r2, r3, ip, lr}           @ 4
++      mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
++      stmia   r0!, {r2, r3, ip, lr}           @ 4
++      subs    r1, r1, #1                      @ 1
++      bne     1b                              @ 1
++      mcr     p15, 0, r1, c7, c10, 4          @ 1   drain WB
++      ldr     pc, [sp], #4
++#endif
++
++      __INITDATA
++
++      .type   fa_user_fns, #object
++ENTRY(fa_user_fns)
++      .long   fa_clear_user_page
++      .long   fa_copy_user_page
++      .size   fa_user_fns, . - fa_user_fns
+--- a/arch/arm/mm/init.c
++++ b/arch/arm/mm/init.c
+@@ -23,6 +23,7 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
++#include <asm/arch/ipi.h>
+ #include "mm.h"
+@@ -252,6 +253,11 @@
+               initrd_end = initrd_start + phys_initrd_size;
+       }
+ #endif
++#ifdef CONFIG_GEMINI_IPI
++      printk("CPU ID:%d\n",getcpuid());
++//    reserve_bootmem_node(NODE_DATA(0), 0x400000, 0x400000);         //CPU0 space
++//    reserve_bootmem_node(NODE_DATA(0), SHAREADDR, SHARE_MEM_SIZE);          //share memory
++#endif
+       /*
+        * Finally, reserve any node zero regions.
+--- /dev/null
++++ b/arch/arm/mm/proc-fa526.S
+@@ -0,0 +1,407 @@
++/*
++ *  linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526
++ *
++ *  Copyright (C) 2005 Faraday Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *
++ * These are the low level assembler for performing cache and TLB
++ * functions on the fa526.
++ *
++ *  Written by : Luke Lee
++ */
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <asm/assembler.h>
++#include <asm/pgtable.h>
++#include <asm/pgtable-hwdef.h>
++#include <asm/elf.h>
++#include <asm/hardware.h>
++#include <asm/page.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++#include "proc-macros.S"
++
++#define CACHE_DLINESIZE          16
++
++      .text
++/*
++ * cpu_fa526_proc_init()
++ */
++ENTRY(cpu_fa526_proc_init)
++      /* MMU is already ON here, ICACHE, DCACHE conditionally disabled */
++
++        mov     r0, #1
++      nop
++      nop
++        mcr     p15, 0, r0, c1, c1, 0         @ turn-on ECR
++      nop
++      nop
++
++      mrc     p15, 0, r0, c1, c0, 0           @ read ctrl register
++
++#ifdef CONFIG_CPU_FA_BTB
++      orr     r0, r0, #CR_Z
++#else
++      bic     r0, r0, #CR_Z
++#endif
++#ifdef CONFIG_CPU_FA_WB_DISABLE
++      mov     r1, #0
++      mcr     p15, 0, r1, c7, c10, 4          @ drain write buffer
++      nop
++      nop
++      bic     r0, r0, #CR_W
++#else
++      orr     r0, r0, #CR_W
++#endif
++#ifdef CONFIG_CPU_DCACHE_DISABLE
++      bic     r0, r0, #CR_C
++#else
++      orr     r0, r0, #CR_C
++#endif
++#ifdef CONFIG_CPU_ICACHE_DISABLE
++      bic     r0, r0, #CR_I
++#else
++      orr     r0, r0, #CR_I
++#endif
++
++      nop
++      nop
++      mcr     p15, 0, r0, c1, c0, 0
++      nop
++      nop
++
++      mov     r5, lr
++      bl      fa_initialize_cache_info        @ destroy r0~r4
++      mov     pc, r5                          @ return
++
++
++/*
++ * cpu_fa526_proc_fin()
++ */
++ENTRY(cpu_fa526_proc_fin)
++      stmfd   sp!, {lr}
++      mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
++      msr     cpsr_c, ip
++
++      bl      fa_flush_kern_cache_all
++      mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
++      bic     r0, r0, #0x1000                 @ ...i............
++      bic     r0, r0, #0x000e                 @ ............wca.
++      mcr     p15, 0, r0, c1, c0, 0           @ disable caches
++
++      nop
++      nop
++      ldmfd   sp!, {pc}
++
++/*
++ * cpu_fa526_reset(loc)
++ *
++ * Perform a soft reset of the system.  Put the CPU into the
++ * same state as it would be if it had been reset, and branch
++ * to what would be the reset vector.
++ *
++ * loc: location to jump to for soft reset
++ */
++      .align  4
++ENTRY(cpu_fa526_reset)
++      mov     ip, #0
++      mcr     p15, 0, ip, c7, c7, 0           @ invalidate I,D caches
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mcr     p15, 0, ip, c7, c10, 4          @ drain WB
++#endif
++      mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
++      mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
++      bic     ip, ip, #0x000f                 @ ............wcam
++      bic     ip, ip, #0x1100                 @ ...i...s........
++
++      bic     ip, ip, #0x0800                 @ BTB off
++      mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
++      nop
++      nop
++      mov     pc, r0
++
++/*
++ * cpu_fa526_do_idle()
++ */
++      .align  4
++ENTRY(cpu_fa526_do_idle)
++
++#ifdef CONFIG_CPU_FA_IDLE
++      nop
++      nop
++      mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt (IDLE mode)
++#endif
++      mov     pc, lr
++
++
++ENTRY(cpu_fa526_dcache_clean_area)
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++1:    mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
++      add     r0, r0, #CACHE_DLINESIZE
++      subs    r1, r1, #CACHE_DLINESIZE
++      bhi     1b
++#endif
++#endif
++      mov     pc, lr
++
++
++/* =============================== PageTable ============================== */
++
++/*
++ * cpu_fa526_switch_mm(pgd)
++ *
++ * Set the translation base pointer to be as described by pgd.
++ *
++ * pgd: new page tables
++ */
++      .align  4
++
++      .globl  fault_address
++fault_address:
++      .long   0
++
++ENTRY(cpu_fa526_switch_mm)
++
++      mov     ip, #0
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
++#else
++      mcr     p15, 0, ip, c7, c14, 0          @ Clean and invalidate whole DCache
++#endif
++#endif /*CONFIG_CPU_DCACHE_DISABLE*/
++
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++      mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
++#endif
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mcr     p15, 0, ip, c7, c10, 4          @ drain WB
++#endif
++
++#ifdef CONFIG_CPU_FA_BTB
++      mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB since mm changed
++      nop
++      nop
++#endif
++      bic     r0, r0, #0xff                   @ clear bits [7:0]
++      bic     r0, r0, #0x3f00                 @ clear bits [13:8]
++      mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
++      mcr     p15, 0, ip, c8, c7, 0           @ invalidate UTLB
++      nop
++      nop
++      mov     pc, lr
++
++/*
++ * cpu_fa526_set_pte_ext(ptep, pte, ext)
++ *
++ * Set a PTE and flush it out
++ */
++      .align  4
++ENTRY(cpu_fa526_set_pte_ext)
++      str     r1, [r0], #-2048                @ linux version
++
++      eor     r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
++
++      bic     r2, r1, #PTE_SMALL_AP_MASK
++      bic     r2, r2, #PTE_TYPE_MASK
++      orr     r2, r2, #PTE_TYPE_SMALL
++
++      tst     r1, #L_PTE_USER                 @ User?
++      orrne   r2, r2, #PTE_SMALL_AP_URO_SRW
++
++      tst     r1, #L_PTE_WRITE | L_PTE_DIRTY  @ Write and Dirty?
++      orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW
++
++      tst     r1, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
++      movne   r2, #0
++
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      eor     r3, r2, #0x0a                   @ C & small page?  1010
++      tst     r3, #0x0b                       @                  1011
++      biceq   r2, r2, #4
++#endif
++      str     r2, [r0]                        @ hardware version
++
++      mov     r2, #0
++      mcr     p15, 0, r2, c7, c10, 0          @ clean D cache all
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mcr     p15, 0, r2, c7, c10, 4          @ drain WB
++#endif
++#ifdef CONFIG_CPU_FA_BTB
++      mcr     p15, 0, r2, c7, c5, 6           @ invalidate BTB
++      nop
++      nop
++#endif
++      mov     pc, lr
++
++      __INIT
++
++      .type   __fa526_setup, #function
++__fa526_setup:
++      /* On return of this routine, r0 must carry correct flags for CFG register */
++      mov     r0, #0
++      mcr     p15, 0, r0, c7, c7              @ invalidate I,D caches on v4
++      mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer on v4
++      mcr     p15, 0, r0, c8, c7              @ invalidate I,D TLBs on v4
++
++      mcr     p15, 0, r0, c7, c5, 5           @ invalidate IScratchpad RAM
++
++        mov     r0, #1
++        mcr     p15, 0, r0, c1, c1, 0         @ turn-on ECR
++
++      mrc     p15, 0, r0, c9, c1, 0           @ DScratchpad
++      bic     r0, r0, #1
++      mcr     p15, 0, r0, c9, c1, 0
++      mrc     p15, 0, r0, c9, c1, 1           @ IScratchpad
++      bic     r0, r0, #1
++      mcr     p15, 0, r0, c9, c1, 1
++
++      mov     r0, #0
++      mcr     p15, 0, r0, c1, c1, 0           @ turn-off ECR
++
++#ifdef CONFIG_CPU_FA_BTB
++      mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB All
++      nop
++      nop
++#endif
++
++      mov     r0, #0x1f                       @ Domains 0, 1 = manager, 2 = client
++      mcr     p15, 0, r0, c3, c0              @ load domain access register
++
++      mrc     p15, 0, r0, c1, c0              @ get control register v4
++      ldr     r5, fa526_cr1_clear
++      bic     r0, r0, r5
++      ldr     r5, fa526_cr1_set
++      orr     r0, r0, r5
++
++#ifdef CONFIG_CPU_FA_BTB
++      orr     r0, r0, #CR_Z
++#else
++      bic     r0, r0, #CR_Z
++#endif
++#ifdef CONFIG_CPU_FA_WB_DISABLE
++      mov     r12, #0
++      mcr     p15, 0, r12, c7, c10, 4         @ drain write buffer
++      nop
++      nop
++      bic     r0, r0, #CR_W                   @ .... .... .... 1...
++#else
++      orr     r0, r0, #CR_W
++#endif
++
++      mov     pc, lr
++      .size   __fa526_setup, . - __fa526_setup
++
++      /*
++       * .RVI ZFRS BLDP WCAM
++       * ..11 0001 .111 1101
++       *
++       */
++      .type   fa526_cr1_clear, #object
++      .type   fa526_cr1_set, #object
++fa526_cr1_clear:
++      .word   0x3f3f
++fa526_cr1_set:
++      .word   0x317D
++
++      __INITDATA
++
++/*
++ * Purpose : Function pointers used to access above functions - all calls
++ *         come through these
++ */
++      .type   fa526_processor_functions, #object
++fa526_processor_functions:
++      .word   v4_early_abort
++      .word   cpu_fa526_proc_init
++      .word   cpu_fa526_proc_fin
++      .word   cpu_fa526_reset
++      .word   cpu_fa526_do_idle
++      .word   cpu_fa526_dcache_clean_area
++      .word   cpu_fa526_switch_mm
++      .word   cpu_fa526_set_pte_ext
++      .size   fa526_processor_functions, . - fa526_processor_functions
++
++      .section ".rodata"
++
++      .type   cpu_arch_name, #object
++cpu_arch_name:
++      .asciz  "armv4"
++      .size   cpu_arch_name, . - cpu_arch_name
++
++      .type   cpu_elf_name, #object
++cpu_elf_name:
++      .asciz  "v4"
++      .size   cpu_elf_name, . - cpu_elf_name
++
++      .type   cpu_fa526_name, #object
++cpu_fa526_name:
++      .ascii  "FA526"
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++      .ascii  "i"
++#endif
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++      .ascii  "d"
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++      .ascii  "(wt)"
++#else
++      .ascii  "(wb)"
++#endif
++#endif
++      .ascii  "\0"
++      .size   cpu_fa526_name, . - cpu_fa526_name
++
++      .align
++
++      .section ".proc.info.init", #alloc, #execinstr
++
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++#define __PMD_SECT_BUFFERABLE 0
++#else
++#define __PMD_SECT_BUFFERABLE PMD_SECT_BUFFERABLE
++#endif
++
++      .type   __fa526_proc_info,#object
++__fa526_proc_info:
++      .long   0x66015261
++      .long   0xff01fff1
++      .long   PMD_TYPE_SECT | \
++              __PMD_SECT_BUFFERABLE | \
++              PMD_SECT_CACHEABLE | \
++              PMD_BIT4 | \
++              PMD_SECT_AP_WRITE | \
++              PMD_SECT_AP_READ
++      .long   PMD_TYPE_SECT | \
++              PMD_BIT4 | \
++              PMD_SECT_AP_WRITE | \
++              PMD_SECT_AP_READ
++      b       __fa526_setup
++      .long   cpu_arch_name
++      .long   cpu_elf_name
++      .long   HWCAP_SWP | HWCAP_HALF
++      .long   cpu_fa526_name
++      .long   fa526_processor_functions
++      .long   fa_tlb_fns
++      .long   fa_user_fns
++      .long   fa_cache_fns
++      .size   __fa526_proc_info, . - __fa526_proc_info
++
++
+--- /dev/null
++++ b/arch/arm/mm/tlb-fa.S
+@@ -0,0 +1,96 @@
++/*
++ *  linux/arch/arm/mm/tlb-fa.S
++ *
++ *  Copyright (C) 2005 Faraday Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  ARM architecture version 4, Faraday variation.
++ *  This assume an unified TLBs, with a write buffer, and branch target buffer (BTB)
++ *
++ *  Processors: FA520 FA526 FA626
++ *  03/31/2005 : Created by Luke Lee, modified from tlb-v4wbi.S
++ *  05/06/2005 : Fixed buggy CPU versions that did not invalidate the associated
++ *               data cache entries when invalidating TLB entries.
++ */
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <asm/asm-offsets.h>
++#include <asm/tlbflush.h>
++#include "proc-macros.S"
++
++
++/*
++ *    flush_user_tlb_range(start, end, mm)
++ *
++ *    Invalidate a range of TLB entries in the specified address space.
++ *
++ *    - start - range start address
++ *    - end   - range end address
++ *    - mm    - mm_struct describing address space
++ */
++      .align  4
++ENTRY(fa_flush_user_tlb_range)
++
++      vma_vm_mm ip, r2
++      act_mm  r3                              @ get current->active_mm
++      eors    r3, ip, r3                      @ == mm ?
++      movne   pc, lr                          @ no, we dont do anything
++      mov     r3, #0
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mcr     p15, 0, r3, c7, c10, 4          @ drain WB
++#endif
++
++      vma_vm_flags r2, r2
++      bic     r0, r0, #0x0ff
++      bic     r0, r0, #0xf00
++
++1:    mcr     p15, 0, r0, c8, c7, 1           @ invalidate UTLB entry
++      add     r0, r0, #PAGE_SZ
++      cmp     r0, r1
++      bls     1b                              @ Luke Lee 05/19/2005 blo -> bls
++
++#ifdef CONFIG_CPU_FA_BTB
++      mcr     p15, 0, r3, c7, c5, 6           @ invalidate BTB
++      nop
++      nop
++#endif
++      mov     pc, lr
++
++
++ENTRY(fa_flush_kern_tlb_range)
++      mov     r3, #0
++
++      mcr     p15, 0, r3, c7, c10, 0          @ clean Dcache all 06/03/2005
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++      mcr     p15, 0, r3, c7, c10, 4          @ drain WB
++#endif
++
++      bic     r0, r0, #0x0ff
++      bic     r0, r0, #0xf00
++1:
++      mcr     p15, 0, r0, c8, c7, 1           @ invalidate UTLB entry
++      add     r0, r0, #PAGE_SZ
++      cmp     r0, r1
++      bls     1b                              @ Luke Lee 05/19/2005 blo -> bls
++
++#ifdef CONFIG_CPU_FA_BTB
++      mcr     p15, 0, r3, c7, c5, 6           @ invalidate BTB
++      nop
++      nop
++#endif
++      mov     pc, lr
++
++
++      __INITDATA
++
++      .type   fa_tlb_fns, #object
++ENTRY(fa_tlb_fns)
++      .long   fa_flush_user_tlb_range
++      .long   fa_flush_kern_tlb_range
++      .long   fa_tlb_flags
++      .size   fa_tlb_fns, . - fa_tlb_fns
+--- a/arch/arm/tools/mach-types
++++ b/arch/arm/tools/mach-types
+@@ -208,7 +208,8 @@
+ fester                        SA1100_FESTER           FESTER                  191
+ gpi                   ARCH_GPI                GPI                     192
+ smdk2410              ARCH_SMDK2410           SMDK2410                193
+-i519                  ARCH_I519               I519                    194
++#i519                 ARCH_I519               I519                    194
++sl2312          ARCH_SL2312         SL2312          194
+ nexio                 SA1100_NEXIO            NEXIO                   195
+ bitbox                        SA1100_BITBOX           BITBOX                  196
+ g200                  SA1100_G200             G200                    197
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/SL_gpio.h
+@@ -0,0 +1,59 @@
++#define GPIO_MINOR_LAST 31
++#define GPIO_MAJOR    120     // Experiemental
++
++#define GPIO_IRQ_NBR  12
++
++#define GPIOBASEADDR          (IO_ADDRESS(0x021000000))
++
++#define GPIODATAOUTOFF                0x00
++#define GPIODATAINOFF         0x04
++#define GPIOPINDIROFF         0x08
++#define GPIOPINBYPASSOFF      0x0C
++#define GPIODATASETOFF                0x10
++#define GPIODATACLEAROFF      0x14
++#define GPIOPINPULLENBOFF     0x18
++#define GPIOPINPULLTPOFF      0x1C
++#define GPIOINTRENBOFF                0x20
++#define GPIOINTRRAWSOFF               0x24
++#define GPIOINTRMASKEDSTATEOFF        0x28
++#define GPIOINTRMASKOFF               0x2C
++#define GPIOINTRCLEAROFF      0x30
++#define GPIOINTRTRIGGEROFF    0x34
++#define GPIOINTRBOTHOFF               0x38
++#define GPIOINTRRISENEGOFF    0x3C
++#define GPIOBNCEENBOFF                0x40
++#define GPIOBNCEPRESOFF               0x44
++
++#define GPIO_IOCTRL_SETDIR    0x20
++#define GPIO_IOCTRL_SET               0x40
++#define GPIO_IOCTRL_CLEAR     0x50
++#define GPIO_IOCTRL_ENBINT    0x60
++#define GPIO_IOCTRL_MASKINT   0x70
++#define GPIO_IOCTRL_LVLTRIG   0x75
++#define GPIO_IOCTRL_EDGINT    0x77
++#define GPIO_IOCTRL_EDGPOLINT 0x78
++#define GPIO_IOCTRL_BYPASS    0x30
++#define GPIO_IOCTRL_PRESCLK   0x80
++#define GPIO_IOCTRL_CLKVAL    0x90
++#define GPIO_IOCTRL_PULLENB   0xA0
++#define GPIO_IOCTRL_PULLTYPE  0xA8
++
++
++#define GPIO_MAJOR    120     /* experimental MAJOR number */
++                              // Minor - 0 : 31 gpio pins
++
++#define GPIO_SET      0x01
++#define GPIO_CLEAR    0x01
++
++#define GPIO_INPUT    0
++#define GPIO_OUTPUT   1
++#define GPIO_EDGEINTR         0
++#define GPIO_EDGESINGL        0
++#define GPIO_EDGEBOTH 1
++#define GPIO_POSITIVE 0
++#define GPIO_ENBINT   1
++#define GPIO_DISABLEMASK      1
++#define GPIO_PULLDOWN 0
++#define GPIO_PULLUP   1
++#define GPIO_ENABLEPULL       1
++#define GPIO_DISABLEPULL      0
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/debug-macro.S
+@@ -0,0 +1,20 @@
++/* linux/include/asm-arm/arch-ebsa110/debug-macro.S
++ *
++ * Debugging macro include header
++ *
++ *  Copyright (C) 1994-1999 Russell King
++ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++**/
++
++              .macro  addruart,rx
++              mov     \rx, #0x42000000
++              .endm
++
++#define UART_SHIFT    2
++#define FLOW_CONTROL
++#include <asm/hardware/debug-8250.S>
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/dma.h
+@@ -0,0 +1,28 @@
++/*
++ *  linux/include/asm-arm/arch-camelot/dma.h
++ *
++ *  Copyright (C) 1997,1998 Russell King
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_DMA_H
++#define __ASM_ARCH_DMA_H
++
++#define MAX_DMA_ADDRESS               0xffffffff
++
++#define MAX_DMA_CHANNELS      0
++
++#endif /* _ASM_ARCH_DMA_H */
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/entry-macro.S
+@@ -0,0 +1,42 @@
++/*
++ * include/asm-arm/arch-arm/entry-macro.S
++ *
++ * Low-level IRQ helper macros for ebsa110 platform.
++ *
++ * This file is licensed under  the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++#include <asm/arch/platform.h>
++#include <asm/arch/int_ctrl.h>
++
++
++                .macro  disable_fiq
++                .endm
++
++                .macro  get_irqnr_preamble, base, tmp
++                .endm
++
++                .macro  arch_ret_to_user, tmp1, tmp2
++                .endm
++
++                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
++                ldr     \irqstat, =IRQ_STATUS(IO_ADDRESS(SL2312_INTERRUPT_BASE))
++                ldr     \irqnr,[\irqstat]
++                cmp     \irqnr,#0
++                beq     2313f
++                mov     \tmp,\irqnr
++                mov     \irqnr,#0
++2312:
++                tst     \tmp, #1
++                bne     2313f
++                add     \irqnr, \irqnr, #1
++                mov     \tmp, \tmp, lsr #1
++                cmp     \irqnr, #31
++                bcc     2312b
++2313:
++                .endm
++
++                .macro  irq_prio_table
++                .endm
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/flash.h
+@@ -0,0 +1,83 @@
++#ifndef __ASM_ARM_ARCH_FLASH_H
++#define __ASM_ARM_ARCH_FLASH_H
++
++#define FLASH_START                                     SL2312_FLASH_BASE
++#define SFLASH_SIZE                                   0x00400000
++#define SPAGE_SIZE                                    0x200
++#define BLOCK_ERASE                                   0x50
++#define BUFFER1_READ                                  0x54
++#define BUFFER2_READ                                  0x56
++#define PAGE_ERASE                                    0x81
++#define MAIN_MEMORY_PAGE_READ                         0x52
++#define MAIN_MEMORY_PROGRAM_BUFFER1                   0x82
++#define MAIN_MEMORY_PROGRAM_BUFFER2                   0x85
++#define BUFFER1_TO_MAIN_MEMORY                        0x83
++#define BUFFER2_TO_MAIN_MEMORY                        0x86
++#define MAIN_MEMORY_TO_BUFFER1                        0x53
++#define MAIN_MEMORY_TO_BUFFER2                        0x55
++#define BUFFER1_WRITE                                 0x84
++#define BUFFER2_WRITE                                 0x87
++#define AUTO_PAGE_REWRITE_BUFFER1                     0x58
++#define AUTO_PAGE_REWRITE_BUFFER2                     0x59
++#define READ_STATUS                                   0x57
++
++#define MAIN_MEMORY_PAGE_READ_SPI                     0xD2
++#define BUFFER1_READ_SPI                              0xD4
++#define BUFFER2_READ_SPI                              0xD6
++#define READ_STATUS_SPI                               0xD7
++
++#define       FLASH_ACCESS_OFFSET                             0x00000010
++#define       FLASH_ADDRESS_OFFSET                            0x00000014
++#define       FLASH_WRITE_DATA_OFFSET                         0x00000018
++#define       FLASH_READ_DATA_OFFSET                          0x00000018
++#define SERIAL_FLASH_CHIP1_EN            0x00010000  // 16th bit = 1
++#define SERIAL_FLASH_CHIP0_EN            0x00000000  // 16th bit = 0
++#define AT45DB321_PAGE_SHIFT                   0xa
++#define AT45DB642_PAGE_SHIFT                   0xb
++#define CONTINUOUS_MODE                        0x00008000
++
++#define FLASH_ACCESS_ACTION_OPCODE                      0x0000
++#define FLASH_ACCESS_ACTION_OPCODE_DATA                 0x0100
++#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS               0x0200
++#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA          0x0300
++#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_X_DATA          0x0400
++#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_2X_DATA         0x0500
++#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_3X_DATA         0x0600
++#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA         0x0700
++//#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_X_DATA        0x0600
++//#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA       0x0700
++
++#define M25P80_PAGE_SIZE  0x100
++#define M25P80_SECTOR_SIZE  0x10000
++
++
++//#define M25P80_BULK_ERASE                                      1
++//#define M25P80_SECTOR_ERASE                                    2
++//#define M25P80_SECTOR_SIZE                                     0x10000
++
++#define M25P80_WRITE_ENABLE                           0x06
++#define M25P80_WRITE_DISABLE                          0x04
++#define M25P80_READ_STATUS                            0x05
++#define M25P80_WRITE_STATUS                           0x01
++#define M25P80_READ                                   0x03
++#define M25P80_FAST_READ                              0x0B
++#define M25P80_PAGE_PROGRAM                           0x02
++#define M25P80_SECTOR_ERASE                           0xD8
++#define M25P80_BULK_ERASE                             0xC7
++#define FLASH_ERR_OK                                                  0x0
++
++extern void address_to_page(__u32, __u16 *, __u16 *);
++extern void main_memory_page_read(__u8, __u16, __u16, __u8 *);
++extern void buffer_to_main_memory(__u8, __u16);
++extern void main_memory_to_buffer(__u8, __u16);
++extern void main_memory_page_program(__u8, __u16, __u16, __u8);
++extern void atmel_flash_read_page(__u32, __u8 *, __u32);
++extern void atmel_erase_page(__u8, __u16);
++extern void atmel_read_status(__u8, __u8 *);
++extern void atmel_flash_program_page(__u32, __u8 *, __u32);
++extern void atmel_buffer_write(__u8, __u16, __u8);
++extern void flash_delay(void);
++
++extern int m25p80_sector_erase(__u32 address, __u32 schip_en);
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/gemini_cir.h
+@@ -0,0 +1,102 @@
++#ifndef _ASM_ARCH_CIR_H
++#define _ASM_ARCH_CIR_H
++#include <linux/ioctl.h>
++
++#define VCR_KEY_POWER         0x613E609F
++#define TV1_KEY_POWER         0x40040100
++#define TV1_KEY_POWER_EXT     0xBCBD
++#define RC5_KER_POWER         0x0CF3
++
++#define VCC_H_ACT_PER         (16-1)
++#define VCC_L_ACT_PER         (8-1)
++#define VCC_DATA_LEN          (32-1)
++#define TV1_H_ACT_PER         (8-1)
++#define TV1_L_ACT_PER         (4-1)
++#define TV1_DATA_LEN          (48-1)
++
++#define VCC_BAUD              540
++#define TV1_BAUD              430
++#ifdef  CONFIG_SL3516_ASIC
++#define       EXT_CLK                 60
++#else
++#define       EXT_CLK                 20
++#endif
++
++#define       NEC_PROTOCOL    0x0
++#define       RC5_PROTOCOL    0x1
++#define VCC_PROTOCOL  0x0
++#define TV1_PROTOCOL  0x01
++
++#ifndef       SL2312_CIR_BASE
++#define       SL2312_CIR_BASE         0x4C000000
++#endif
++#define       CIR_BASE_ADDR           IO_ADDRESS(SL2312_CIR_BASE)
++#define STORLINK_CIR_ID               0x00010400
++
++#define       CIR_IP_ID               *(volatile unsigned int *)(CIR_BASE_ADDR + 0x00)
++#define       CIR_CTR_REG             *(volatile unsigned int *)(CIR_BASE_ADDR + 0x04)
++#define       CIR_STATUS_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x08)
++#define       CIR_RX_REG              *(volatile unsigned int *)(CIR_BASE_ADDR + 0x0C)
++#define       CIR_RX_EXT_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x10)
++#define       CIR_PWR_REG             *(volatile unsigned int *)(CIR_BASE_ADDR + 0x14)
++#define       CIR_PWR_EXT_REG         *(volatile unsigned int *)(CIR_BASE_ADDR + 0x18)
++#define       CIR_TX_CTR_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x1C)
++#define       CIR_TX_FEQ_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x20)
++#define       CIR_TX_REG              *(volatile unsigned int *)(CIR_BASE_ADDR + 0x24)
++#define       CIR_TX_EXT_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x28)
++
++
++#ifndef       SL2312_POWER_CTRL_BASE
++#define       SL2312_POWER_CTRL_BASE          0x4B000000
++#endif
++
++#ifndef PWR_BASE_ADDR
++#define       PWR_BASE_ADDR           IO_ADDRESS(SL2312_POWER_CTRL_BASE)
++#endif
++#define       PWR_CTRL_ID             *(unsigned int*)(PWR_BASE_ADDR+0x00)
++#define       PWR_CTRL_REG            *(unsigned int*)(PWR_BASE_ADDR+0x04)
++#define       PWR_STATUS_REG          *(unsigned int*)(PWR_BASE_ADDR+0x08)
++
++
++#define BIT(x)                        (1<<x)
++#define TX_STATUS             BIT(3)
++
++#define       PWR_STAT_CIR            0x10
++#define       PWR_STAT_RTC            0x20
++#define       PWR_STAT_PUSH           0x40
++#define       PWR_SHUTDOWN            0x01
++
++#define CARR_FREQ             38000
++
++struct cir_ioctl_data {
++      __u32 data;
++};
++struct cir_ioctl_data48 {
++      __u32 timeout;
++      __u32 length;
++      __u8  ret;
++      __u32 data;
++      __u32 data_ext;
++};
++#define OLD_DATA                      0
++#define NEW_RECEIVE                   1
++
++#define       CIR_IOCTL_BASE          ('I'|'R')
++#define CIR_SET_BAUDRATE                      _IOW (CIR_IOCTL_BASE,  0, struct cir_ioctl_data)
++#define CIR_SET_HIGH_PERIOD                   _IOW (CIR_IOCTL_BASE,  1, struct cir_ioctl_data)
++#define CIR_SET_LOW_PERIOD                    _IOW (CIR_IOCTL_BASE,  2, struct cir_ioctl_data)
++#define CIR_SET_PROTOCOL                      _IOW (CIR_IOCTL_BASE,  3, struct cir_ioctl_data)
++#define CIR_SET_ENABLE_COMPARE                _IOW (CIR_IOCTL_BASE,  4, struct cir_ioctl_data)
++#define CIR_SET_ENABLE_DEMOD          _IOW (CIR_IOCTL_BASE,  5, struct cir_ioctl_data)
++#define CIR_SET_POWER_KEY                     _IOW (CIR_IOCTL_BASE,  6, struct cir_ioctl_data)
++#define CIR_GET_BAUDRATE                      _IOR (CIR_IOCTL_BASE,  7, struct cir_ioctl_data)
++#define CIR_GET_HIGH_PERIOD                   _IOR (CIR_IOCTL_BASE,  8 ,struct cir_ioctl_data)
++#define CIR_GET_LOW_PERIOD                    _IOR (CIR_IOCTL_BASE,  9 ,struct cir_ioctl_data)
++#define CIR_GET_PROTOCOL                      _IOR (CIR_IOCTL_BASE, 10, struct cir_ioctl_data)
++#define CIR_GET_ENABLE_COMPARE                _IOR (CIR_IOCTL_BASE, 11, struct cir_ioctl_data)
++#define CIR_GET_ENABLE_DEMOD          _IOR (CIR_IOCTL_BASE, 12, struct cir_ioctl_data)
++#define CIR_GET_POWER_KEY                     _IOR (CIR_IOCTL_BASE, 13, struct cir_ioctl_data)
++#define CIR_GET_DATA                          _IOWR (CIR_IOCTL_BASE, 14, struct cir_ioctl_data48)
++#define CIR_WAIT_INT_DATA                     _IOWR (CIR_IOCTL_BASE, 15, struct cir_ioctl_data48)
++
++#endif //_ASM_ARCH_CIR_H
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/gemini_gpio.h
+@@ -0,0 +1,77 @@
++/*
++ * FILE NAME gemini_gpio.h
++ *
++ * BRIEF MODULE DESCRIPTION
++ *    Generic Gemini GPIO
++ *
++ *  Author: Storlink Software [Device driver]
++ *          Jason Lee <jason@storlink.com.tw>
++ *
++ * Copyright 2005 Storlink Inc.
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
++ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
++ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
++ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
++ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
++ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
++ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *  You should have received a copy of the  GNU General Public License along
++ *  with this program; if not, write  to the Free Software Foundation, Inc.,
++ *  675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __GEMINI_GPIO_H
++#define __GEMINI_GPIO_H
++
++#include <linux/ioctl.h>
++
++#define STATUS_HIGH   1
++#define STATUS_LOW    0
++#define DIRECT_OUT    1
++#define DIRECT_IN     0
++
++#define EDGE_TRIG     0
++#define RISING_EDGE   0
++#define FALL_EDGE     1
++#define SINGLE_EDGE   0
++#define BOTH_EDGE     1
++
++#define LEVEL_TRIG    1
++#define HIGH_ACTIVE   0
++#define LOW_ACTIVE    1
++
++struct gemini_gpio_ioctl_data {
++      __u32 pin;
++      __u8 status;                    // status or pin direction
++                                      // 0: status low or Input
++                                      // 1: status high or Output
++
++      /* these member are used to config GPIO interrupt parameter */
++      __u8    use_default;            // if not sure ,set this argument 1
++      __u8    trig_type;              // 0/1:edge/level triger ?
++      __u8    trig_polar;             // 0/1:rising/falling high/low active ?
++      __u8    trig_both;              // 0/1:single/both detect both ?
++};
++
++#define GEMINI_GPIO_IOCTL_BASE        'Z'
++
++#define GEMINI_SET_GPIO_PIN_DIR               _IOW (GEMINI_GPIO_IOCTL_BASE,16, struct gemini_gpio_ioctl_data)
++#define       GEMINI_SET_GPIO_PIN_STATUS      _IOW (GEMINI_GPIO_IOCTL_BASE,17, struct gemini_gpio_ioctl_data)
++#define       GEMINI_GET_GPIO_PIN_STATUS      _IOWR(GEMINI_GPIO_IOCTL_BASE,18, struct gemini_gpio_ioctl_data)
++#define GEMINI_WAIT_GPIO_PIN_INT      _IOWR(GEMINI_GPIO_IOCTL_BASE,19, struct gemini_gpio_ioctl_data)
++
++
++extern void init_gpio_int(__u32 pin,__u8 trig_type,__u8 trig_polar,__u8 trig_both);
++extern int request_gpio_irq(int bit,void (*handler)(int),char level,char high,char both);
++extern int free_gpio_irq(int bit);
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/gemini_i2s.h
+@@ -0,0 +1,169 @@
++#ifndef __GEMINI_I2S_H__
++#define __GEMINI_I2S_H__
++#include <linux/ioctl.h>
++#include <linux/types.h>
++#include <asm/arch-sl2312/irqs.h>
++
++typedef __u16 UINT16;
++typedef __u32 UINT32;
++typedef __u8 UINT8;
++typedef __u8 BOOL;
++
++/***************************************/
++/* define GPIO module base address     */
++/***************************************/
++#define DMA_CONTROL_PHY_BASE  (IO_ADDRESS(SL2312_GENERAL_DMA_BASE))
++#define DMA_CONTROL_SSP_BASE  (IO_ADDRESS(SL2312_SSP_CTRL_BASE))
++#define SSP_INT                               IRQ_SSP
++#define GPIO_BASE_ADDR      (IO_ADDRESS(SL2312_GPIO_BASE))
++#define GPIO_BASE_ADDR1      (IO_ADDRESS(SL2312_GPIO_BASE1))
++#define GLOBAL_BASE      (IO_ADDRESS(SL2312_GLOBAL_BASE))
++
++/* define read/write register utility */
++#define READ_SSP_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_SSP_BASE))
++#define WRITE_SSP_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_SSP_BASE))
++
++#define READ_GPIO_REG(offset)                 (__raw_readl(offset+GPIO_BASE_ADDR))
++#define WRITE_GPIO_REG(offset,val)    (__raw_writel(val,offset+GPIO_BASE_ADDR))
++
++#define READ_GPIO1_REG(offset)                        (__raw_readl(offset+GPIO_BASE_ADDR1))
++#define WRITE_GPIO1_REG(offset,val)   (__raw_writel(val,offset+GPIO_BASE_ADDR1))
++
++#define READ_DMA_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_PHY_BASE))
++#define WRITE_DMA_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_PHY_BASE))
++
++#define READ_GLOBAL_REG(offset)                       (__raw_readl(offset+GLOBAL_BASE))
++#define WRITE_GLOBAL_REG(offset,val)  (__raw_writel(val,offset+GLOBAL_BASE))
++
++#define SSP_GPIO_INT          IRQ_GPIO
++
++#ifndef CONFIG_SL3516_ASIC
++#define SSP_GPIO_INT_BIT    0x00000400                                //GPIO[10] : SLIC interrupt pin
++
++#define GPIO_EECK          0x00000040         /*   SCK: GPIO[06]   */
++#define GPIO_EECS          0x00000080                 /*   SCS: GPIO[07]   */
++#define GPIO_MISO          0x00000200         /*   SDO: GPIO[09]   receive from 6996*/
++#define GPIO_MOSI          0x00000100         /*   SDI: GPIO[08]   send to 6996*/
++#define GPIO_MISO_BIT  9
++#else
++#define SSP_GPIO_INT_BIT    0x00000001                                //GPIO[0] : SLIC interrupt pin
++
++//#if 0
++//#define GPIO_EECK        0x80000000         /*   SCK: GPIO1[31]   */
++//#define GPIO_EECS        0x40000000                 /*   SCS: GPIO1[30]   */
++//#define GPIO_MISO        0x20000000         /*   SDO: GPIO1[29]   receive from 6996*/
++//#define GPIO_MOSI        0x10000000         /*   SDI: GPIO1[28]   send to 6996*/
++//#define GPIO_MISO_BIT       29
++//#else
++//#define GPIO_EECK        0x00000100         /*   SCK: GPIO1[08]   */
++//#define GPIO_EECS        0x08000000                 /*   SCS: GPIO1[27]   */
++//#define GPIO_MISO        0x00000080         /*   SDO: GPIO1[07]   receive from 6996*/
++//#define GPIO_MOSI        0x00000200         /*   SDI: GPIO1[09]   send to 6996*/
++//#define GPIO_MISO_BIT       7
++//#endif
++#endif
++
++
++enum GPIO_REG
++{
++      GPIO_DATA_OUT           = 0x00,
++      GPIO_DATA_IN            = 0x04,
++      GPIO_PIN_DIR            = 0x08,
++      GPIO_BY_PASS            = 0x0c,
++      GPIO_DATA_SET           = 0x10,
++      GPIO_DATA_CLEAR         = 0x14,
++      GPIO_INT_ENABLE     = 0x20,
++      GPIO_INT_RAWSTATE   = 0x24,
++      GPIO_INT_MASKSTATE  = 0x28,
++      GPIO_INT_MASK       = 0x2C,
++      GPIO_INT_CLEAR      = 0x30,
++      GPIO_INT_TRIGGER    = 0x34,
++      GPIO_INT_BOTH       = 0x38,
++      GPIO_INT_POLARITY   = 0x3C
++};
++
++typedef struct
++{
++      UINT32 src_addr;
++      UINT32 dst_addr;
++      UINT32 llp;
++      UINT32 ctrl_size;
++      UINT32 owner;
++}DMA_LLP_t;
++
++typedef struct
++{
++      UINT32 owner;
++      UINT32 src_addr;
++      UINT32 ctrl_size;
++}IOCTL_LLP_t;
++
++typedef unsigned char byte;
++typedef unsigned short word;
++typedef unsigned long dword;
++
++/* DMA Registers */
++#define       DMA_INT                                 0x00000000
++#define       DMA_INT_TC                              0x00000004
++#define       DMA_CFG                                 0x00000024
++#define       DMA_INT_TC_CLR                          0x00000008
++#define       DMA_TC                                          0x00000014
++#define       DMA_CSR                                         0x00000024
++#define       DMA_SYNC                                        0x00000028
++
++#define       DMA_CH2_CSR                             0x00000140
++#define       DMA_CH2_CFG                             0x00000144
++#define       DMA_CH2_SRC_ADDR                0x00000148
++#define       DMA_CH2_DST_ADDR                0x0000014c
++#define       DMA_CH2_LLP                             0x00000150
++#define       DMA_CH2_SIZE                            0x00000154
++
++#define       DMA_CH3_CSR                             0x00000160
++#define       DMA_CH3_CFG                             0x00000164
++#define       DMA_CH3_SRC_ADDR                0x00000168
++#define       DMA_CH3_DST_ADDR                0x0000016c
++#define       DMA_CH3_LLP                             0x00000170
++#define       DMA_CH3_SIZE                            0x00000174
++
++#define    SSP_DEVICE_ID                      0x00
++#define    SSP_CTRL_STATUS                    0x04
++#define          SSP_FRAME_CTRL           0x08
++#define    SSP_BAUD_RATE            0x0c
++#define    SSP_FRAME_CTRL2          0x10
++#define    SSP_FIFO_CTRL            0x14
++#define    SSP_TX_SLOT_VALID0       0x18
++#define    SSP_TX_SLOT_VALID1       0x1c
++#define    SSP_TX_SLOT_VALID2       0x20
++#define    SSP_TX_SLOT_VALID3       0x24
++#define    SSP_RX_SLOT_VALID0       0x28
++#define    SSP_RX_SLOT_VALID1       0x2c
++#define    SSP_RX_SLOT_VALID2       0x30
++#define    SSP_RX_SLOT_VALID3       0x34
++#define    SSP_SLOT_SIZE0           0x38
++#define    SSP_SLOT_SIZE1           0x3c
++#define    SSP_SLOT_SIZE2           0x40
++#define    SSP_SLOT_SIZE3           0x44
++#define    SSP_READ_PORT            0x48
++#define    SSP_WRITE_PORT           0x4c
++
++
++
++#define SSP_I2S_INIT_BUF                      _IO  ('q', 0x00)
++#define SSP_I2S_STOP_DMA                      _IO  ('q', 0x01)
++#define SSP_I2S_FILE_LEN                      _IOW  ('q', 0x2, int)
++/*
++#define SSP_GET_HOOK_STATUS                   _IOR  ('q', 0xC0, int)
++#define SSP_GET_LINEFEED                      _IOR  ('q', 0xC1, int)
++#define SSP_SET_LINEFEED                      _IOW  ('q', 0xC2, int)
++#define SSP_GET_REG                 _IOWR ('q', 0xC3, struct Ssp_reg *)
++#define SSP_SET_REG                 _IOWR ('q', 0xC4, struct Ssp_reg *)
++#define SSP_GEN_OFFHOOK_TONE          _IO   ('q', 0xC5)
++#define SSP_GEN_BUSY_TONE                     _IO   ('q', 0xC6)
++#define SSP_GEN_RINGBACK_TONE         _IO   ('q', 0xC7)
++#define SSP_GEN_CONGESTION_TONE               _IO   ('q', 0xC8)
++#define SSP_DISABLE_DIALTONE          _IO   ('q', 0xC9)
++#define SSP_PHONE_RING_START          _IO   ('q', 0xCA)
++*/
++
++
++#endif //__GEMINI_I2S_H__
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/gemini_ssp.h
+@@ -0,0 +1,263 @@
++/******************************************************************************
++ *    gemini_ssp.h
++ *
++ *
++ *****************************************************************************/
++
++#include <linux/types.h>
++#include <asm/arch-sl2312/irqs.h>
++#include <linux/phonedev.h>
++#include <linux/telephony.h>
++//#include "proslic.h"
++
++typedef __u16 UINT16;
++typedef __u32 UINT32;
++typedef __u8 UINT8;
++typedef __u8 BOOL;
++
++#define TRUE 1
++#define FALSE 0
++
++/***************************************/
++/* define GPIO module base address     */
++/***************************************/
++#define DMA_CONTROL_PHY_BASE  (IO_ADDRESS(SL2312_GENERAL_DMA_BASE))
++#define DMA_CONTROL_SSP_BASE  (IO_ADDRESS(SL2312_SSP_CTRL_BASE))
++#define SSP_INT                               IRQ_SSP
++#define GPIO_BASE_ADDR      (IO_ADDRESS(SL2312_GPIO_BASE))
++#define GPIO_BASE_ADDR1      (IO_ADDRESS(SL2312_GPIO_BASE1))
++#define GLOBAL_BASE      (IO_ADDRESS(SL2312_GLOBAL_BASE))
++
++/* define read/write register utility */
++#define READ_SSP_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_SSP_BASE))
++#define WRITE_SSP_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_SSP_BASE))
++
++#define READ_GPIO_REG(offset)                 (__raw_readl(offset+GPIO_BASE_ADDR))
++#define WRITE_GPIO_REG(offset,val)    (__raw_writel(val,offset+GPIO_BASE_ADDR))
++
++#define READ_GPIO1_REG(offset)                        (__raw_readl(offset+GPIO_BASE_ADDR1))
++#define WRITE_GPIO1_REG(offset,val)   (__raw_writel(val,offset+GPIO_BASE_ADDR1))
++
++#define READ_DMA_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_PHY_BASE))
++#define WRITE_DMA_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_PHY_BASE))
++
++#define READ_GLOBAL_REG(offset)                       (__raw_readl(offset+GLOBAL_BASE))
++#define WRITE_GLOBAL_REG(offset,val)  (__raw_writel(val,offset+GLOBAL_BASE))
++
++
++#define SSP_GPIO_INT          IRQ_GPIO
++
++#ifndef CONFIG_SL3516_ASIC
++#define SSP_GPIO_INT_BIT    0x00000400                                //GPIO[10] : SLIC interrupt pin
++
++#define GPIO_EECK          0x00000040         /*   SCK: GPIO[06]   */
++#define GPIO_EECS          0x00000080                 /*   SCS: GPIO[07]   */
++#define GPIO_MISO          0x00000200         /*   SDO: GPIO[09]   receive from 6996*/
++#define GPIO_MOSI          0x00000100         /*   SDI: GPIO[08]   send to 6996*/
++#define GPIO_MISO_BIT  9
++#else
++#define SSP_GPIO_INT_BIT    0x00000001                                //GPIO[0] : SLIC interrupt pin
++
++//#if 0
++//#define GPIO_EECK        0x80000000         /*   SCK: GPIO1[31]   */
++//#define GPIO_EECS        0x40000000                 /*   SCS: GPIO1[30]   */
++//#define GPIO_MISO        0x20000000         /*   SDO: GPIO1[29]   receive from 6996*/
++//#define GPIO_MOSI        0x10000000         /*   SDI: GPIO1[28]   send to 6996*/
++//#define GPIO_MISO_BIT       29
++//#else
++//#define GPIO_EECK        0x00000100         /*   SCK: GPIO1[08]   */
++//#define GPIO_EECS        0x08000000                 /*   SCS: GPIO1[27]   */
++//#define GPIO_MISO        0x00000080         /*   SDO: GPIO1[07]   receive from 6996*/
++//#define GPIO_MOSI        0x00000200         /*   SDI: GPIO1[09]   send to 6996*/
++//#define GPIO_MISO_BIT       7
++//#endif
++#endif
++
++
++enum GPIO_REG
++{
++      GPIO_DATA_OUT           = 0x00,
++      GPIO_DATA_IN            = 0x04,
++      GPIO_PIN_DIR            = 0x08,
++      GPIO_BY_PASS            = 0x0c,
++      GPIO_DATA_SET           = 0x10,
++      GPIO_DATA_CLEAR         = 0x14,
++      GPIO_INT_ENABLE     = 0x20,
++      GPIO_INT_RAWSTATE   = 0x24,
++      GPIO_INT_MASKSTATE  = 0x28,
++      GPIO_INT_MASK       = 0x2C,
++      GPIO_INT_CLEAR      = 0x30,
++      GPIO_INT_TRIGGER    = 0x34,
++      GPIO_INT_BOTH       = 0x38,
++      GPIO_INT_POLARITY   = 0x3C
++};
++
++
++#define SPI_ADD_LEN        7                  // bits of Address
++#define SPI_DAT_LEN        8                  // bits of Data
++
++
++
++//#ifdef MIDWAY_DIAG
++#define       DAISY_MODE      1
++#if (DAISY_MODE==1)
++#define NUMBER_OF_CHAN        2
++#else
++#define NUMBER_OF_CHAN        1
++#endif
++#define LLP_SIZE   8
++#define SBUF_SIZE  512 //0xff0 //2560
++#define DBUF_SIZE  SBUF_SIZE*NUMBER_OF_CHAN //0xff0 //2560
++#define TBUF_SIZE  (LLP_SIZE)*DBUF_SIZE
++#define DESC_NUM   1
++#define DTMF_NUM   20
++
++/* define owner bit of SSP */
++//data into SSP and transfer to AP==> SSP_Rx
++//data out of SSP and transfer to SLIC==> SSP_Tx
++#define CPU           0
++#define DMA           1
++
++#define DMA_DEMO   0
++#define DMA_NDEMO  1
++//#define DMA_NONE   2
++
++enum exceptions {
++      PROSLICiNSANE,
++      TIMEoUTpOWERuP,
++      TIMEoUTpOWERdOWN,
++      POWERlEAK,
++      TIPoRrINGgROUNDsHORT,
++      POWERaLARMQ1,
++      POWERaLARMQ2,
++      POWERaLARMQ3,
++      POWERaLARMQ4,
++      POWERaLARMQ5,
++      OWERaLARMQ6,
++      CM_CAL_ERR
++};
++
++typedef struct
++{
++      UINT32 src_addr;
++      UINT32 dst_addr;
++      UINT32 llp;
++      UINT32 ctrl_size;
++}DMA_LLP_t;
++
++typedef struct {
++      unsigned int own ;
++      char  *tbuf;
++      //UINT32 *LinkAddrT;
++      DMA_LLP_t LLPT[LLP_SIZE];
++}DMA_Tx_t;
++
++typedef struct {
++      unsigned int own ;
++      char  *rbuf;
++      //UINT32 *LinkAddrR;
++      DMA_LLP_t LLPR[LLP_SIZE];
++}DMA_Rx_t;
++
++//typedef struct {
++//    //UINT32 init_stat;
++//    struct chipStruct chipData ; /* Represents a proslics state, cached information, and timers */
++//    struct phone_device p;
++//
++//
++//}SSP_SLIC;
++
++
++
++/* DMA Registers */
++#define       DMA_INT                                 0x00000000
++#define       DMA_INT_TC                              0x00000004
++#define       DMA_CFG                                 0x00000024
++#define       DMA_INT_TC_CLR                          0x00000008
++#define       DMA_TC                                          0x00000014
++#define       DMA_CSR                                         0x00000024
++#define       DMA_SYNC                                        0x00000028
++
++#define       DMA_CH2_CSR                             0x00000140
++#define       DMA_CH2_CFG                             0x00000144
++#define       DMA_CH2_SRC_ADDR                0x00000148
++#define       DMA_CH2_DST_ADDR                0x0000014c
++#define       DMA_CH2_LLP                             0x00000150
++#define       DMA_CH2_SIZE                            0x00000154
++
++#define       DMA_CH3_CSR                             0x00000160
++#define       DMA_CH3_CFG                             0x00000164
++#define       DMA_CH3_SRC_ADDR                0x00000168
++#define       DMA_CH3_DST_ADDR                0x0000016c
++#define       DMA_CH3_LLP                             0x00000170
++#define       DMA_CH3_SIZE                            0x00000174
++
++#define    SSP_DEVICE_ID                      0x00
++#define    SSP_CTRL_STATUS                    0x04
++#define          SSP_FRAME_CTRL           0x08
++#define    SSP_BAUD_RATE            0x0c
++#define    SSP_FRAME_CTRL2          0x10
++#define    SSP_FIFO_CTRL            0x14
++#define    SSP_TX_SLOT_VALID0       0x18
++#define    SSP_TX_SLOT_VALID1       0x1c
++#define    SSP_TX_SLOT_VALID2       0x20
++#define    SSP_TX_SLOT_VALID3       0x24
++#define    SSP_RX_SLOT_VALID0       0x28
++#define    SSP_RX_SLOT_VALID1       0x2c
++#define    SSP_RX_SLOT_VALID2       0x30
++#define    SSP_RX_SLOT_VALID3       0x34
++#define    SSP_SLOT_SIZE0           0x38
++#define    SSP_SLOT_SIZE1           0x3c
++#define    SSP_SLOT_SIZE2           0x40
++#define    SSP_SLOT_SIZE3           0x44
++#define    SSP_READ_PORT            0x48
++#define    SSP_WRITE_PORT           0x4c
++
++
++void printFreq_Revision(int num);
++void SLIC_SPI_write(int num, UINT8 ,UINT8);
++UINT8 SLIC_SPI_read(int num, UINT8);
++void SLIC_SPI_write_bit(char);
++void SLIC_SPI_ind_write(int num, UINT8, UINT16);
++UINT16 SLIC_SPI_ind_read(int num, UINT8);
++void SLIC_SPI_CS_enable(UINT8);
++unsigned int SLIC_SPI_read_bit(void);
++void SLIC_SPI_pre_st(void);
++UINT32 ssp_init(void);
++UINT16 SLIC_SPI_get_identifier(int num);
++int selfTest(int num);
++void exception (int num, enum exceptions e);
++int SLIC_init(int num);
++UINT8 version(int num);
++UINT8 chipType (int num);
++void SLIC_init_ind_reg_set(int num);
++UINT8 powerUp(int num);
++UINT8 powerLeakTest(int num);
++void SLIC_init_reg_set(int num);
++int calibrate(int num);
++void goActive(int num);
++void clearInterrupts(int num);
++void setState(int num, int);
++UINT8 loopStatus(int num);
++int verifyIndirectRegisters(int num);
++int verifyIndirectReg(int num, UINT8 , UINT16);
++void sendProSLICID(int num);
++void disableOscillators(int num);
++UINT8 checkSum(int num, char * string );
++void fskInitialization (int num);
++void fskByte(int num, UINT8 c);
++void waitForInterrupt (int num);
++//void findNumber(void);
++UINT8 dtmfAction(int num);
++UINT8 digit(int num);
++void interrupt_init(void);
++//void gemini_slic_isr (int );
++int groundShort(int num);
++void clearAlarmBits(int num);
++void stopRinging(int num);
++void activateRinging(int num);
++void initializeLoopDebounceReg(int num);
++void busyJapan(int num) ;
++void ringBackJapan(int num) ;
++void stateMachine(int num);
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/hardware.h
+@@ -0,0 +1,47 @@
++/*
++ *  linux/include/asm-arm/arch-epxa10/hardware.h
++ *
++ *  This file contains the hardware definitions of the Integrator.
++ *
++ *  Copyright (C) 1999 ARM Limited.
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_HARDWARE_H
++#define __ASM_ARCH_HARDWARE_H
++
++#include <asm/arch/platform.h>
++
++#define pcibios_assign_all_busses()   1
++
++/*
++ * Where in virtual memory the IO devices (timers, system controllers
++ * and so on)
++ *
++ * macro to get at IO space when running virtually
++*/
++
++#define IO_ADDRESS(x)      (((x&0xfff00000)>>4)|(x & 0x000fffff)|0xF0000000)
++#define FLASH_VBASE         0xFE000000
++#define FLASH_SIZE 0x1000000// 8M
++#define FLASH_START         SL2312_FLASH_BASE
++#define FLASH_VADDR(x)      ((x & 0x00ffffff)|0xFE000000)       // flash virtual address
++
++#define PCIBIOS_MIN_IO                                        0x100           // 0x000-0x100 AHB reg and PCI config, data
++#define PCIBIOS_MIN_MEM                                       0
++
++#endif
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/int_ctrl.h
+@@ -0,0 +1,171 @@
++/*
++ *
++ *  This file contains the register definitions for the Excalibur
++ *  Timer TIMER00.
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef __INT_CTRL_H
++#define __INT_CTRL_H
++
++#define PCI_IRQ_OFFSET                          64    /* PCI start IRQ number */
++#define FIQ_OFFSET                32
++
++#define IRQ_SOURCE(base_addr)   (INT_CTRL_TYPE(base_addr  + 0x00))
++#define IRQ_MASK(base_addr)     (INT_CTRL_TYPE (base_addr  + 0x04 ))
++#define IRQ_CLEAR(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x08 ))
++#define IRQ_TMODE(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x0C ))
++#define IRQ_TLEVEL(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x10 ))
++#define IRQ_STATUS(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x14 ))
++#define FIQ_SOURCE(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x20 ))
++#define FIQ_MASK(base_addr)     (INT_CTRL_TYPE (base_addr  + 0x24 ))
++#define FIQ_CLEAR(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x28 ))
++#define FIQ_TMODE(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x2C ))
++#define FIQ_LEVEL(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x30 ))
++#define FIQ_STATUS(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x34 ))
++
++#ifdef CONFIG_SL3516_ASIC
++#define       IRQ_SERIRQ0_OFFSET                      30
++#define       IRQ_PCID_OFFSET                         29
++#define       IRQ_PCIC_OFFSET                         28
++#define       IRQ_PCIB_OFFSET                         27
++#define IRQ_PWR_OFFSET                                        26
++#define IRQ_CIR_OFFSET                                                25
++#define       IRQ_GPIO2_OFFSET                        24
++#define       IRQ_GPIO1_OFFSET                        23
++#define       IRQ_GPIO_OFFSET                         22
++#define       IRQ_SSP_OFFSET                          21
++#define IRQ_LPC_OFFSET                      20
++#define IRQ_LCD_OFFSET                      19
++#define       IRQ_UART_OFFSET                         18
++#define       IRQ_RTC_OFFSET                                  17
++#define       IRQ_TIMER3_OFFSET                       16
++#define       IRQ_TIMER2_OFFSET                       15
++#define       IRQ_TIMER1_OFFSET                       14
++#define IRQ_FLASH_OFFSET                                      12
++#define       IRQ_USB1_OFFSET                         11
++#define IRQ_USB0_OFFSET                                               10
++#define       IRQ_DMA_OFFSET                          9
++#define       IRQ_PCI_OFFSET                          8
++#define       IRQ_IPSEC_OFFSET                        7
++#define       IRQ_RAID_OFFSET                     6
++#define       IRQ_IDE1_OFFSET                         5
++#define       IRQ_IDE0_OFFSET                         4
++#define       IRQ_WATCHDOG_OFFSET                 3
++#define       IRQ_GMAC1_OFFSET                    2
++#define IRQ_GMAC0_OFFSET                                      1
++#define       IRQ_CPU0_IP_IRQ_OFFSET              0
++
++#define       IRQ_SERIRQ0_MASK                        (1<<30)
++#define IRQ_PCID_MASK                                 (1<<29)
++#define IRQ_PCIC_MASK                                 (1<<28)
++#define IRQ_PCIB_MASK                                 (1<<27)
++#define IRQ_PWR_MASK                                  (1<<26)
++#define IRQ_CIR_MASK                                          (1<<25)
++#define       IRQ_GPIO2_MASK                          (1<<24)
++#define       IRQ_GPIO1_MASK                          (1<<23)
++#define       IRQ_GPIO_MASK                       (1<<22)
++#define       IRQ_SSP_MASK                        (1<<21)
++#define IRQ_LPC_MASK                        (1<<20)
++#define IRQ_LCD_MASK                        (1<<19)
++#define       IRQ_UART_MASK                       (1<<18)
++#define       IRQ_RTC_MASK                                (1<<17)
++#define       IRQ_TIMER3_MASK                     (1<<16)
++#define       IRQ_TIMER2_MASK                     (1<<15)
++#define       IRQ_TIMER1_MASK                     (1<<14)
++#define IRQ_FLASH_MASK                                            (1<<12)
++#define       IRQ_USB1_MASK                       (1<<11)
++#define IRQ_USB0_MASK                                     (1<<10)
++#define       IRQ_DMA_MASK                        (1<< 9)
++#define       IRQ_PCI_MASK                        (1<< 8)
++#define       IRQ_IPSEC_MASK                              (1<< 7)
++#define       IRQ_RAID_MASK                       (1<< 6)
++#define       IRQ_IDE1_MASK                       (1<< 5)
++#define       IRQ_IDE0_MASK                       (1<< 4)
++#define       IRQ_WATCHDOG_MASK                   (1<< 3)
++#define       IRQ_GMAC1_MASK                      (1<< 2)
++#define IRQ_GMAC0_MASK                                            (1<< 1)
++#define       IRQ_CPU0_IP_IRQ_MASK                (1<< 0)
++#else
++#define       IRQ_SERIRQ0_OFFSET                      30
++#define       IRQ_PCID_OFFSET                         29
++#define       IRQ_PCIC_OFFSET                         28
++#define       IRQ_PCIB_OFFSET                         27
++#define IRQ_PWR_OFFSET                                        26
++#define IRQ_CIR_OFFSET                                                25
++#define       IRQ_GPIO2_OFFSET                        24
++#define       IRQ_GPIO1_OFFSET                        23
++#define       IRQ_GPIO_OFFSET                         22
++#define       IRQ_SSP_OFFSET                          21
++#define IRQ_LPC_OFFSET                      20
++#define IRQ_LCD_OFFSET                      19
++#define       IRQ_UART_OFFSET                         18
++#define       IRQ_RTC_OFFSET                                  17
++#define       IRQ_TIMER3_OFFSET                       16
++#define       IRQ_TIMER2_OFFSET                       15
++#define       IRQ_TIMER1_OFFSET                       14
++#define IRQ_FLASH_OFFSET                                      12
++#define       IRQ_USB1_OFFSET                         11
++#define IRQ_USB0_OFFSET                                               10
++#define       IRQ_DMA_OFFSET                          9
++#define       IRQ_PCI_OFFSET                          8
++#define       IRQ_IPSEC_OFFSET                        7
++#define       IRQ_RAID_OFFSET                     6
++#define       IRQ_IDE1_OFFSET                         5
++#define       IRQ_IDE0_OFFSET                         4
++#define       IRQ_WATCHDOG_OFFSET                 3
++#define       IRQ_GMAC1_OFFSET                    2
++#define IRQ_GMAC0_OFFSET                                      1
++#define       IRQ_CPU0_IP_IRQ_OFFSET              0
++
++#define       IRQ_SERIRQ0_MASK                        (1<<30)
++#define IRQ_PCID_MASK                                 (1<<29)
++#define IRQ_PCIC_MASK                                 (1<<28)
++#define IRQ_PCIB_MASK                                 (1<<27)
++#define IRQ_PWR_MASK                                  (1<<26)
++#define IRQ_CIR_MASK                                          (1<<25)
++#define       IRQ_GPIO2_MASK                          (1<<24)
++#define       IRQ_GPIO1_MASK                          (1<<23)
++#define       IRQ_GPIO_MASK                       (1<<22)
++#define       IRQ_SSP_MASK                        (1<<21)
++#define IRQ_LPC_MASK                        (1<<20)
++#define IRQ_LCD_MASK                        (1<<19)
++#define       IRQ_UART_MASK                       (1<<18)
++#define       IRQ_RTC_MASK                                (1<<17)
++#define       IRQ_TIMER3_MASK                     (1<<16)
++#define       IRQ_TIMER2_MASK                     (1<<15)
++#define       IRQ_TIMER1_MASK                     (1<<14)
++#define IRQ_FLASH_MASK                                            (1<<12)
++#define       IRQ_USB1_MASK                       (1<<11)
++#define IRQ_USB0_MASK                                     (1<<10)
++#define       IRQ_DMA_MASK                        (1<< 9)
++#define       IRQ_PCI_MASK                        (1<< 8)
++#define       IRQ_IPSEC_MASK                              (1<< 7)
++#define       IRQ_RAID_MASK                       (1<< 6)
++#define       IRQ_IDE1_MASK                       (1<< 5)
++#define       IRQ_IDE0_MASK                       (1<< 4)
++#define       IRQ_WATCHDOG_MASK                   (1<< 3)
++#define       IRQ_GMAC1_MASK                      (1<< 2)
++#define IRQ_GMAC0_MASK                                            (1<< 1)
++#define       IRQ_CPU0_IP_IRQ_MASK                (1<< 0)
++#endif
++
++
++#endif /* __INT_CTRL_H */
++
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/io.h
+@@ -0,0 +1,50 @@
++/*
++ *  linux/include/asm-arm/arch-epxa10db/io.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARM_ARCH_IO_H
++#define __ASM_ARM_ARCH_IO_H
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++
++/*
++ * Generic virtual read/write
++ */
++/*
++#define __arch_getw(a)                (*(volatile unsigned short *)(a))
++#define __arch_putw(v,a)      (*(volatile unsigned short *)(a) = (v))
++*/
++/*#define outsw   __arch_writesw
++#define outsl   __arch_writesl
++#define outsb   __arch_writesb
++#define insb    __arch_readsb
++#define insw    __arch_readsw
++#define insl    __arch_readsl*/
++
++#define __io(a)                       (a)
++#define __mem_pci(a)            (a)
++/*
++#define __arch_getw(a)                        (*(volatile unsigned short  *)(a))
++#define __arch_putw(v,a)              (*(volatile unsigned short *)(a) = (v))
++*/
++#define iomem_valid_addr(off,size) (1)
++#define iomem_to_phys(off) (off)
++
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/ipi.h
+@@ -0,0 +1,189 @@
++/*
++ *  linux/include/asm-arm/arch-sl2312/system.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_IPI_H
++#define __ASM_ARCH_IPI_H
++#include <asm/io.h>
++
++//#define spin_lock(x)        spin_lock_dt(x)
++//#define spin_unlock(x)      spin_unlock_dt(x)
++
++#define SWAP_OFFSET                                                   0x400000
++#define SWAP_SIZE                                                     0x400000
++
++#define SHARE_MEM_ADDR                                                0x2000000
++#define SHARE_MEM_SIZE                                                1024*1024
++
++
++//--> Add by jason for IPI testing
++// memory layout for maste & slave bin
++#define MASTERTEXT      0x8000
++#define SLAVETEXT             0x108000
++#define SHARESIZE             0x4000
++#define SHAREADDR             SHARE_MEM_ADDR // starting 8M
++
++// CPU1 reset release
++#define GLOBAL_BASE           IO_ADDRESS(0x40000000)
++#define GLOBAL_SOFTRESET      (GLOBAL_BASE + 0x0C)
++#define CPU1_RESET_BIT_MASK     0x40000000
++
++// IPI , need to redefine the folliwing,  bug
++#define CPU0_STATUS                   (GLOBAL_BASE + 0x0038)
++#define CPU1_STATUS                   (GLOBAL_BASE + 0x003C)
++#define CPU_IPI_BIT_MASK    0x80000000
++
++/* Your basic SMP spinlocks, allowing only a single CPU anywhere
++*/
++typedef struct {
++       volatile unsigned int lock;
++} spinlock_dt;
++
++
++#define         MASTER_BIT      0x01
++#define         SLAVE_BIT       0x02
++#define         HEART_BIT       0x04
++#define         IPI0_IRQ_BIT    0x08
++#define         IPI0_FIQ_BIT    0x10
++#define         IPI1_IRQ_BIT    0x20
++#define         IPI1_FIQ_BIT    0x40
++
++#define IRQ     0
++#define FIQ     1
++#define DONE    0xff
++
++#define         CPU0            0x0
++#define         CPU1            0x1
++
++#define         MAXCHAR         128*1024
++typedef struct  {
++       int flag;
++       int uart_flag;
++       int cnt;
++       spinlock_dt lk;
++       char message[MAXCHAR];
++}s_mailbox;
++
++// JScale proj definition
++typedef struct {
++      u16             type;                           // message Type
++      u16             length;                         // message length, including message header
++} IPC_MSG_HDR_T;
++
++typedef struct{
++      IPC_MSG_HDR_T   hdr;
++      u32                             input_location;
++      u32                             input_size;
++      u32                             output_location;
++      u16                     ScaledImageWidth;
++      u16                     ScaledImageHeight;
++      u8                      ScaledImageQuality;
++      u8                      MaintainResultionRatio;
++      u8                      TwoStepScaling;
++      u8                      InputFormat;
++      u8                              verbose;
++      u8                              reserved[3];
++} JSCALE_REQ_T;
++
++typedef struct{
++      IPC_MSG_HDR_T   hdr;
++      u32                             status;
++      u32                             code;
++      u32                             output_size;
++} JSCALE_RSP_T;
++
++#define IPC_JSCALE_REQ_MSG                    0       // JScale request from CPU-0 to CPU-1
++#define IPC_JSCALE_RSP_MSG                    1       // JScale response from CPU-1 to CPU-0
++
++enum {
++      JSCALE_STATUS_OK = 0,
++      JSCALE_UNKNOWN_MSG_TYPE,
++      JSCALE_FAILED_FILE_SIZE,
++      JSCALE_FAILED_MALLOC,
++      JSCALE_FAILED_FORMAT,
++      JSCALE_DECODE_ERROR,
++      JSCALE_BUSY,
++};
++// <-- JScale
++
++#define GEMINI_IPI_IOCTL_BASE 'Z'
++#define GEMINI_IPI_JSCALE_REQ         _IOW (GEMINI_IPI_IOCTL_BASE,0,JSCALE_REQ_T)
++#define GEMINI_IPI_JSCALE_STAT                _IOR (GEMINI_IPI_IOCTL_BASE,1,JSCALE_RSP_T)
++
++
++/*
++* Simple spin lock operations.
++*
++*/
++
++#define spin_is_locked_dt(x)((x)->lock != 0)
++
++static inline int test_and_set_dt(spinlock_dt *lock)
++{
++unsigned long tmp;
++__asm__ __volatile__(
++"swp     %0, %2, [%1]\n"
++: "=&r" (tmp)
++: "r" (&lock->lock), "r" (1)
++: "cc", "memory");
++
++return tmp;
++}
++
++static inline void spin_lock_dt(spinlock_dt *lock)
++{
++
++unsigned long tmp;
++__asm__ __volatile__(
++"1:     ldr   %0, [%1]\n"
++"teq     %0, #0\n"
++"swpeq   %0, %2, [%1]\n"
++"       teqeq   %0, #0\n"
++"       bne     1b"
++       : "=&r" (tmp)
++       : "r" (&lock->lock), "r" (1)
++       : "cc", "memory");
++}
++
++static inline void spin_unlock_dt(spinlock_dt *lock)
++{
++       __asm__ __volatile__(
++"       str     %1, [%0]"
++       :
++       : "r" (&lock->lock), "r" (0)
++       : "cc", "memory");
++}
++
++static inline int getcpuid(void)
++{
++       int cpuid;
++
++      __asm__(
++"mrc p8, 0, r0, c0, c0, 0\n"
++"mov %0, r0"
++       :"=r"(cpuid)
++       :
++       :"r0");
++       return (cpuid & 0x07);
++}
++
++
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/irq.h
+@@ -0,0 +1,23 @@
++/*
++ *  linux/include/asm-arm/arch-sl2312/irq.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++ // Since we have PCI interrupt which the interrupt line is pseudo
++ // we need do some fixup
++int fixup_irq(int irq);
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/irqs.h
+@@ -0,0 +1,102 @@
++/*
++ *  linux/include/asm-arm/arch-camelot/irqs.h
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/* Use the Excalibur chip definitions */
++#define INT_CTRL_TYPE
++#include "asm/arch/int_ctrl.h"
++
++#ifdef CONFIG_SL3516_ASIC
++#define       IRQ_SERIRQ_MAX                                  31
++#define       IRQ_SERIRQ1                                             31
++#define       IRQ_SERIRQ0                     30
++#define       IRQ_PCID                                29
++#define       IRQ_PCIC                        28
++#define       IRQ_PCIB                                27
++#define IRQ_PWR                                                       26
++#define IRQ_CIR                                                       25
++#define       IRQ_GPIO2                       24
++#define       IRQ_GPIO1                       23
++#define       IRQ_GPIO                                22
++#define       IRQ_SSP                         21
++#define IRQ_LPC                         20
++#define IRQ_LCD                         19
++#define       IRQ_UART                                18
++#define       IRQ_RTC                                 17
++#define       IRQ_TIMER3                      16
++#define       IRQ_TIMER2                      15
++#define       IRQ_TIMER1                      14
++#define IRQ_FLASH                                             12
++#define       IRQ_USB1                        11
++#define IRQ_USB0                                              10
++#define       IRQ_DMA                         9
++#define       IRQ_PCI                                 8
++#define       IRQ_IPSEC                               7
++#define       IRQ_RAID                        6
++#define       IRQ_IDE1                        5
++#define       IRQ_IDE0                                4
++#define       IRQ_WATCHDOG                    3
++#define       IRQ_GMAC1                       2
++#define IRQ_GMAC0                                             1
++#define       IRQ_CPU0_IP_IRQ                 0
++#else
++#define       IRQ_SERIRQ_MAX                                  31
++#define       IRQ_SERIRQ1                                             31
++#define       IRQ_SERIRQ0                     30
++#define       IRQ_PCID                                29
++#define       IRQ_PCIC                        28
++#define       IRQ_PCIB                                27
++#define IRQ_PWR                                                       26
++#define IRQ_CIR                                                       25
++#define       IRQ_GPIO2                       24
++#define       IRQ_GPIO1                       23
++#define       IRQ_GPIO                                22
++#define       IRQ_SSP                         21
++#define IRQ_LPC                         20
++#define IRQ_LCD                         19
++#define       IRQ_UART                                18
++#define       IRQ_RTC                                 17
++#define       IRQ_TIMER3                      16
++#define       IRQ_TIMER2                      15
++#define       IRQ_TIMER1                      14
++#define IRQ_FLASH                                             12
++#define       IRQ_USB1                        11
++#define IRQ_USB0                                              10
++#define       IRQ_DMA                         9
++#define       IRQ_PCI                                 8
++#define       IRQ_IPSEC                               7
++#define       IRQ_RAID                        6
++#define       IRQ_IDE1                        5
++#define       IRQ_IDE0                                4
++#define       IRQ_WATCHDOG                    3
++#define       IRQ_GMAC1                       2
++#define IRQ_GMAC0                                             1
++#endif
++
++#define ARCH_TIMER_IRQ                               IRQ_TIMER2   /* for MV 4.0 */
++
++#define IRQ_PCI_INTA                                 PCI_IRQ_OFFSET + 0
++#define IRQ_PCI_INTB                                 PCI_IRQ_OFFSET + 1
++#define IRQ_PCI_INTC                                 PCI_IRQ_OFFSET + 2
++#define IRQ_PCI_INTD                                 PCI_IRQ_OFFSET + 3
++
++#define NR_IRQS                           (IRQ_PCI_INTD + 4)
++
++
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/it8712.h
+@@ -0,0 +1,24 @@
++
++#ifndef __IT8712_H__
++#define __IT8712_H__
++
++#include "asm/arch/sl2312.h"
++
++#define IT8712_IO_BASE                        SL2312_LPC_IO_BASE
++// Device LDN
++#define LDN_SERIAL1                           0x01
++#define LDN_SERIAL2                           0x02
++#define LDN_PARALLEL                  0x03
++#define LDN_KEYBOARD                  0x05
++#define LDN_MOUSE                             0x06
++#define LDN_GPIO                              0x07
++
++#define IT8712_UART1_PORT             0x3F8
++#define IT8712_UART2_PORT             0x2F8
++
++#define IT8712_GPIO_BASE              0x800   // 0x800-0x804 for GPIO set1-set5
++
++void LPCSetConfig(char LdnNumber, char Index, char data);
++char LPCGetConfig(char LdnNumber, char Index);
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/memory.h
+@@ -0,0 +1,38 @@
++/*
++ *  linux/include/asm-arm/arch-sl2312/memory.h
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_MMU_H
++#define __ASM_ARCH_MMU_H
++
++/*
++ * Physical DRAM offset.
++ */
++#define PHYS_OFFSET   UL(0x00000000)
++
++/*
++ * Virtual view <-> DMA view memory address translations
++ * virt_to_bus: Used to translate the virtual address to an
++ *              address suitable to be passed to set_dma_addr
++ * bus_to_virt: Used to convert an address for DMA operations
++ *              to an address that the kernel can use.
++ */
++#define __virt_to_bus(x)      (x - PAGE_OFFSET + /*SDRAM_BASE*/0)
++#define __bus_to_virt(x)      (x - /*SDRAM_BASE*/0 + PAGE_OFFSET)
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/param.h
+@@ -0,0 +1,20 @@
++/*
++ *  linux/include/asm-arm/arch-epxa10db/param.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/pci.h
+@@ -0,0 +1,18 @@
++
++#ifndef __SL2312_PCI_H__
++#define __SL2312_PCI_H__
++
++#define SL2312_PCI_PMC                                0x40
++#define SL2312_PCI_PMCSR                      0x44
++#define SL2312_PCI_CTRL1                      0x48
++#define SL2312_PCI_CTRL2                      0x4c
++#define SL2312_PCI_MEM1_BASE_SIZE     0x50
++#define SL2312_PCI_MEM2_BASE_SIZE     0x54
++#define SL2312_PCI_MEM3_BASE_SIZE     0x58
++
++
++void sl2312_pci_mask_irq(unsigned int irq);
++void sl2312_pci_unmask_irq(unsigned int irq);
++int sl2312_pci_get_int_src(void);
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/platform.h
+@@ -0,0 +1,7 @@
++#ifndef PLATFORM_H
++#define PLATFORM_H
++#include "sl2312.h"
++
++#define MAXIRQNUM 68
++#endif
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/preempt.h
+@@ -0,0 +1,63 @@
++/*
++ * include/asm-arm/arch-sl2312/preempt.h
++ *
++ * Timing support for preempt-stats, kfi, ilatency patches
++ *
++ * Author: dsingleton <dsingleton@mvista.com>
++ *
++ * 2001-2004 (c) MontaVista Software, Inc. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++
++#ifndef _ASM_ARCH_PREEMT_H
++#define _ASM_ARCH_PREEMT_H
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/sl2312.h>
++
++static inline unsigned long clock_diff(unsigned long start, unsigned long stop)
++{
++        return (start - stop);
++}
++
++static inline unsigned int readclock(void)
++{
++      unsigned int    x;
++
++      x = readl(IO_ADDRESS(SL2312_TIMER2_BASE));
++      return x;
++}
++
++static inline unsigned __ticks_per_usec(void)
++{
++#ifdef CONFIG_SL3516_ASIC
++      unsigned int ahb_clock_rate_base=130;  /* unit = MHz*/
++      unsigned int reg_v=0;
++      unsigned int ticks_usec;
++
++      reg_v = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+4)));
++      reg_v >>=15;
++      ticks_usec = (ahb_clock_rate_base + (reg_v & 0x07)*10)>>2;
++
++#else
++      unsigned int ticks_usec=20;
++#endif
++
++    return ticks_usec;
++}
++
++/*
++ * timer 1 runs @ 6Mhz  6 ticks = 1 microsecond
++ * and is configed as a count down timer.
++ */
++#define TICKS_PER_USEC                    __ticks_per_usec()
++#define ARCH_PREDEFINES_TICKS_PER_USEC
++
++#define clock_to_usecs(x)         ((x) / TICKS_PER_USEC)
++
++#define INTERRUPTS_ENABLED(x)   (!(x & PSR_I_BIT))
++
++#endif
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/sl2312.h
+@@ -0,0 +1,254 @@
++#ifndef __sl2312_h
++#define __sl2312_h
++
++/****************************************************************************
++ * Copyright  Storlink Corp 2002-2003.  All rights reserved.                *
++ *--------------------------------------------------------------------------*
++ * Name:board.s                                                             *
++ * Description:  SL231x specfic define                                      *
++ * Author: Plus Chen                                                        *
++ * Version: 0.9 Create
++ ****************************************************************************/
++
++/*
++  CPE address map;
++
++               +====================================================
++    0x00000000 | FLASH
++    0x0FFFFFFF |
++               |====================================================
++    0x10000000 | SDRAM
++    0x1FFFFFFF |
++               |====================================================
++    0x20000000 | Global Registers        0x20000000-0x20FFFFFF
++               | EMAC and DMA            0x21000000-0x21FFFFFF
++               | UART Module             0x22000000-0x22FFFFFF
++               | Timer Module            0x23000000-0x23FFFFFF
++               | Interrupt Module        0x24000000-0x24FFFFFF
++               | RTC Module              0x25000000-0x25FFFFFF
++               | LPC Host Controller     0x26000000-0x26FFFFFF
++               | LPC Peripherial IO      0x27000000-0x27FFFFFF
++               | WatchDog Timer          0x28000000-0x28FFFFFF
++    0x2FFFFFFF | Reserved                0x29000000-0x29FFFFFF
++               |=====================================================
++    0x30000000 | PCI IO, Configuration Registers
++    0x3FFFFFFF |
++               |=====================================================
++    0x40000000 | PCI Memory
++    0x4FFFFFFF |
++               |=====================================================
++    0x50000000 | Ethernet MAC and DMA    0x50000000-0x50FFFFFF
++               | Security and DMA        0x51000000-0x51FFFFFF
++               | IDE Channel 0 Register  0x52000000-0x527FFFFF
++               | IDE Channel 1 Register  0x52800000-0x52FFFFFF
++               | USB Register            0x53000000-0x53FFFFFF
++               | Flash Controller        0x54000000-0x54FFFFFF
++               | DRAM Controller         0x55000000-0x55FFFFFF
++    0x5FFFFFFF | Reserved                0x56000000-0x5FFFFFFF
++               |=====================================================
++    0x60000000 | Reserved
++    0x6FFFFFFF |
++               |=====================================================
++    0x70000000 | FLASH shadow Memory
++    0x7FFFFFFF |
++               |=====================================================
++    0x80000000 | Big Endian of memory    0x00000000-0x7FFFFFFF
++    0xFFFFFFFF |
++               +=====================================================
++*/
++
++
++
++/*-------------------------------------------------------------------------------
++ Memory Map definitions
++-------------------------------------------------------------------------------- */
++#define TEST          1
++#if 0
++
++static inline int GETCPUID()
++{
++       int cpuid;
++      __asm__(
++"mrc p8, 0, r0, c0, c0, 0\n"
++"mov %0, r0"
++       :"=r"(cpuid)
++       :
++       :"r0");
++       return (cpuid & 0x07);
++}
++#endif
++#define SL2312_SRAM_BASE                0x70000000       //  SRAM base after remap
++#define SL2312_DRAM_BASE                0x00000000       //  DRAM base after remap
++#define SL2312_RAM_BASE                 0x10000000       //  RAM code base before remap
++#define SL2312_FLASH_BASE                 0x30000000
++#define SL2312_ROM_BASE                 0x30000000
++#define SL2312_GLOBAL_BASE              0x40000000
++#define SL2312_WAQTCHDOG_BASE           0x41000000
++#define SL2312_UART_BASE                0x42000000
++#define SL2312_TIMER_BASE               0x43000000
++#define SL2312_LCD_BASE                 0x44000000
++#define SL2312_RTC_BASE                 0x45000000
++#define SL2312_SATA_BASE                0x46000000
++#define SL2312_LPC_HOST_BASE            0x47000000
++#define SL2312_LPC_IO_BASE              0x47800000
++// #define SL2312_INTERRUPT_BASE           0x48000000
++#define SL2312_INTERRUPT0_BASE          0x48000000
++#define SL2312_INTERRUPT1_BASE          0x49000000
++//#define SL2312_INTERRUPT_BASE               ((getcpuid()==0)?SL2312_INTERRUPT0_BASE:SL2312_INTERRUPT1_BASE)
++#define SL2312_INTERRUPT_BASE             0x48000000
++#define SL2312_SSP_CTRL_BASE            0x4A000000
++#define SL2312_POWER_CTRL_BASE          0x4B000000
++#define SL2312_CIR_BASE                 0x4C000000
++#define SL2312_GPIO_BASE                0x4D000000
++#define SL2312_GPIO_BASE1               0x4E000000
++#define SL2312_GPIO_BASE2               0x4F000000
++#define SL2312_PCI_IO_BASE              0x50000000
++#define SL2312_PCI_MEM_BASE             0x58000000
++#ifdef  CONFIG_NET_SL351X
++#define SL2312_TOE_BASE                 0x60000000
++#define SL2312_GMAC0_BASE               0x6000A000
++#define SL2312_GMAC1_BASE               0x6000E000
++#else
++#define SL2312_GMAC0_BASE               0x60000000
++#define SL2312_GMAC1_BASE               0x61000000
++#endif
++#define SL2312_SECURITY_BASE            0x62000000
++#define SL2312_IDE0_BASE                0x63000000
++#define SL2312_IDE1_BASE                      0x63400000
++#define SL2312_RAID_BASE                0x64000000
++#define SL2312_FLASH_CTRL_BASE          0x65000000
++#define SL2312_DRAM_CTRL_BASE           0x66000000
++#define SL2312_GENERAL_DMA_BASE         0x67000000
++#define SL2312_USB_BASE                 0x68000000
++#define SL2312_USB0_BASE                0x68000000
++#define SL2312_USB1_BASE                0x69000000
++#define SL2312_FLASH_SHADOW             0x30000000
++#define SL2312_BIG_ENDIAN_BASE                        0x80000000
++
++#ifdef CONFIG_GEMINI_IPI
++#define CPU_1_MEM_BASE                        0x4000000                               // 64 MB
++#define CPU_1_DATA_OFFSET             0x4000000-0x300000              // Offset 61 MB
++#endif
++
++#define SL2312_TIMER1_BASE              SL2312_TIMER_BASE
++#define SL2312_TIMER2_BASE              (SL2312_TIMER_BASE + 0x10)
++#define SL2312_TIMER3_BASE              (SL2312_TIMER_BASE + 0x20)
++
++#define SL2312_PCI_DMA_MEM1_BASE              0x00000000
++#define SL2312_PCI_DMA_MEM2_BASE              0x00000000
++#define SL2312_PCI_DMA_MEM3_BASE              0x00000000
++#define SL2312_PCI_DMA_MEM1_SIZE              7
++#define SL2312_PCI_DMA_MEM2_SIZE              6
++#define SL2312_PCI_DMA_MEM3_SIZE              6
++
++/*-------------------------------------------------------------------------------
++ Global Module
++---------------------------------------------------------------------------------*/
++#define GLOBAL_ID                       0x00
++#define GLOBAL_CHIP_ID                  0x002311
++#define GLOBAL_CHIP_REV                 0xA0
++#define GLOBAL_STATUS                   0x04
++#define GLOBAL_CONTROL                  0x1C
++#define GLOBAL_REMAP_BIT                0x01
++#define GLOBAL_RESET_REG              0x0C
++#define GLOBAL_MISC_REG                                       0x30
++#define PFLASH_SHARE_BIT                              0x02
++
++#define GLOBAL_RESET          (1<<31)
++#define RESET_CPU1                    (1<<30)
++#define RESET_SATA1                   (1<<27)
++#define RESET_SATA0                   (1<<26)
++#define RESET_CIR                     (1<<25)
++#define RESET_EXT_DEV         (1<<24)
++#define RESET_WD                      (1<<23)
++#define RESET_GPIO2                   (1<<22)
++#define RESET_GPIO1                   (1<<21)
++#define RESET_GPIO0                   (1<<20)
++#define RESET_SSP                     (1<<19)
++#define RESET_UART                    (1<<18)
++#define RESET_TIMER                   (1<<17)
++#define RESET_RTC                     (1<<16)
++#define RESET_INT0                    (1<<15)
++#define RESET_INT1                    (1<<14)
++#define RESET_LCD                     (1<<13)
++#define RESET_LPC                     (1<<12)
++#define RESET_APB                     (1<<11)
++#define RESET_DMA                     (1<<10)
++#define RESET_USB1                    (1<<9 )
++#define RESET_USB0                    (1<<8 )
++#define RESET_PCI                     (1<<7 )
++#define RESET_GMAC1                   (1<<6 )
++#define RESET_GMAC0                   (1<<5 )
++#define RESET_IPSEC                   (1<<4 )
++#define RESET_RAID                    (1<<3 )
++#define RESET_IDE                     (1<<2 )
++#define RESET_FLASH                   (1<<1 )
++#define RESET_DRAM                    (1<<0 )
++
++
++
++
++
++
++
++
++/*-------------------------------------------------------------------------------
++ DRAM Module
++---------------------------------------------------------------------------------*/
++#define DRAM_SIZE_32M                   0x2000000
++#define DRAM_SIZE_64M                   0x4000000
++#define DRAM_SIZE_128M                  0x8000000
++
++#define DRAM_SIZE                       DRAM_SIZE_128M
++
++#define DRAM_SDRMR                      0x00
++#define SDRMR_DISABLE_DLL               0x80010000
++
++/*------------------------------------------------------------------------------
++ Share Pin Flag
++--------------------------------------------------------------------------------*/
++#ifdef CONFIG_SL2312_SHARE_PIN
++#define FLASH_SHARE_BIT                    0
++#define UART_SHARE_BIT                     1
++#define EMAC_SHARE_BIT                     2
++#define IDE_RW_SHARE_BIT                   3
++#define IDE_CMD_SHARE_BIT                  4
++#endif
++/*-------------------------------------------------------------------------------
++ System Clock
++---------------------------------------------------------------------------------*/
++
++#ifndef SYS_CLK
++#ifdef CONFIG_SL3516_ASIC
++#define SYS_CLK                         150000000
++#else
++#define SYS_CLK                       20000000
++#endif
++#endif
++
++#define AHB_CLK                       SYS_CLK
++#define MAX_TIMER                     3
++#ifndef APB_CLK
++#ifdef CONFIG_SL3516_ASIC
++#define APB_CLK                       (SYS_CLK / 6)
++#else
++#define APB_CLK                               SYS_CLK
++#endif
++#endif
++
++#ifdef CONFIG_SL3516_ASIC
++#define UART_CLK                        48000000      // 30000000 for GeminiA chip, else 48000000
++#else
++#define UART_CLK                      48000000
++#endif
++
++#define SL2312_BAUD_115200              (UART_CLK / 1843200)
++#define SL2312_BAUD_57600               (UART_CLK / 921600)
++#define SL2312_BAUD_38400                     (UART_CLK / 614400)
++#define SL2312_BAUD_19200               (UART_CLK / 307200)
++#define SL2312_BAUD_14400               (UART_CLK / 230400)
++#define SL2312_BAUD_9600                (UART_CLK / 153600)
++
++#endif
++
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/sl2312_ipsec.h
+@@ -0,0 +1,684 @@
++#ifndef _IPSEC_DIAG_H
++#define _IPSEC_DIAG_H
++
++#include <linux/scatterlist.h>
++
++#define BIG_ENDIAN    0
++
++#define IPSEC_TEST    0
++#define ZERO_COPY     1
++
++#define UINT unsigned int
++#define BYTE unsigned char
++
++/* define cipher algorithm */
++enum CIPHER {
++      DES_ECB_E       =20,
++      TDES_ECB_E      =21,
++      AES_ECB_E       =22,
++      DES_CBC_E       =24,
++      TDES_CBC_E      =25,
++      AES_CBC_E       =26,
++
++      DES_ECB_D       =27,
++      TDES_ECB_D      =28,
++      AES_ECB_D       =29,
++      DES_CBC_D       =31,
++      TDES_CBC_D      =32,
++      AES_CBC_D       =33,
++      A_SHA1      =12,
++      A_HMAC_SHA1 =13,
++      A_MD5       =14,
++      A_HMAC_MD5  =15,
++};
++
++// opMode
++#define CIPHER_ENC    0x1
++#define CIPHER_DEC    0x3
++#define AUTH          0x4
++#define ENC_AUTH      0x5
++#define AUTH_DEC      0x7
++
++// cipherAlgorithm
++#define CBC_DES       0x4
++#define CBC_3DES      0x5
++#define CBC_AES       0x6
++#define ECB_DES       0x0
++#define ECB_3DES      0x1
++#define ECB_AES       0x2
++
++// authAlgorithm
++#define SHA1         0
++#define MD5          1
++#define HMAC_SHA1    2
++#define HMAC_MD5     3
++#define FCS          4
++
++//cipher mode
++#define ECB          0
++#define CBC          1
++
++// authMode
++#define AUTH_APPEND  0
++#define AUTH_CHKVAL  1
++
++/******************************************************/
++/*          the offset of IPSEC DMA register          */
++/******************************************************/
++enum IPSEC_DMA_REGISTER {
++      IPSEC_DMA_DEVICE_ID             = 0xff00,
++      IPSEC_DMA_STATUS                = 0xff04,
++      IPSEC_TXDMA_CTRL                = 0xff08,
++      IPSEC_TXDMA_FIRST_DESC  = 0xff0c,
++      IPSEC_TXDMA_CURR_DESC   = 0xff10,
++      IPSEC_RXDMA_CTRL                = 0xff14,
++      IPSEC_RXDMA_FIRST_DESC  = 0xff18,
++      IPSEC_RXDMA_CURR_DESC   = 0xff1c,
++      IPSEC_TXDMA_BUF_ADDR    = 0xff28,
++      IPSEC_RXDMA_BUF_ADDR    = 0xff38,
++      IPSEC_RXDMA_BUF_SIZE            = 0xff30,
++};
++
++#define IPSEC_STATUS_REG    0x00a8
++#define IPSEC_RAND_NUM_REG  0x00ac
++
++/******************************************************/
++/* the field definition of IPSEC DMA Module Register  */
++/******************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff00
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int p_wclk             :  4;   /* DMA_APB write clock period */
++              unsigned int p_rclk             :  4;   /* DMA_APB read clock period */
++              unsigned int                            :  8;
++              unsigned int device_id          : 12;
++              unsigned int revision_id        :  4;
++#else
++              unsigned int revision_id        :  4;
++              unsigned int device_id          : 12;
++              unsigned int                            :  8;
++              unsigned int p_rclk             :  4;   /* DMA_APB read clock period */
++              unsigned int p_wclk             :  4;   /* DMA_APB write clock period */
++#endif
++      } bits;
++} IPSEC_DMA_DEVICE_ID_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff04
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int ts_finish          :  1;   /* finished tx interrupt */
++              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
++              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
++              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
++              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
++              unsigned int rs_finish          :  1;   /* finished rx interrupt */
++              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
++              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
++              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
++              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
++        unsigned int intr           :  8;   /* Peripheral interrupt */
++              unsigned int dma_reset          :  1;   /* write 1 to this bit will cause DMA HClk domain soft reset */
++              unsigned int peri_reset         :  1;   /* write 1 to this bit will cause DMA PClk domain soft reset */
++              unsigned int                            :  3;
++              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
++        unsigned int intr_enable    :  8;   /* Peripheral Interrupt Enable */
++#else
++        unsigned int intr_enable    :  8;   /* Peripheral Interrupt Enable */
++              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
++              unsigned int                            :  3;
++              unsigned int peri_reset         :  1;   /* write 1 to this bit will cause DMA PClk domain soft reset */
++              unsigned int dma_reset          :  1;   /* write 1 to this bit will cause DMA HClk domain soft reset */
++        unsigned int intr           :  8;   /* Peripheral interrupt */
++              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
++              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
++              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
++              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
++              unsigned int rs_finish          :  1;   /* finished rx interrupt */
++              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
++              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
++              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
++              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
++              unsigned int ts_finish          :  1;   /* finished tx interrupt */
++#endif
++      } bits;
++} IPSEC_DMA_STATUS_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff08
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int td_start           :  1;   /* Start DMA transfer */
++              unsigned int td_continue        :  1;   /* Continue DMA operation */
++              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int                            :  1;
++              unsigned int td_prot            :  4;   /* TxDMA protection control */
++              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
++              unsigned int td_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
++              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int                            : 14;
++#else
++              unsigned int                            : 14;
++              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int td_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
++              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
++              unsigned int td_prot            :  4;   /* TxDMA protection control */
++              unsigned int                            :  1;
++              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int td_continue        :  1;   /* Continue DMA operation */
++              unsigned int td_start           :  1;   /* Start DMA transfer */
++#endif
++      } bits;
++} IPSEC_TXDMA_CTRL_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff0c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
++              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
++              unsigned int                                    :  3;
++#else
++              unsigned int                                    :  3;
++              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
++              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
++#endif
++      } bits;
++} IPSEC_TXDMA_FIRST_DESC_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff10
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
++              unsigned int sof_eof            :  2;
++#else
++              unsigned int sof_eof            :  2;
++              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int ndar                       : 28;   /* next descriptor address */
++#endif
++      } bits;
++} IPSEC_TXDMA_CURR_DESC_T;
++
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff14
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rd_start           :  1;   /* Start DMA transfer */
++              unsigned int rd_continue        :  1;   /* Continue DMA operation */
++              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int                            :  1;
++              unsigned int rd_prot            :  4;   /* DMA protection control */
++              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
++              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
++              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int                            : 14;
++#else
++              unsigned int                            : 14;
++              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
++              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
++              unsigned int rd_prot            :  4;   /* DMA protection control */
++              unsigned int                            :  1;
++              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int rd_continue        :  1;   /* Continue DMA operation */
++              unsigned int rd_start           :  1;   /* Start DMA transfer */
++#endif
++      } bits;
++} IPSEC_RXDMA_CTRL_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff18
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
++              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
++              unsigned int                                    :  3;
++#else
++              unsigned int                                    :  3;
++              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
++              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
++#endif
++      } bits;
++} IPSEC_RXDMA_FIRST_DESC_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff1c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
++              unsigned int sof_eof            :  2;
++#else
++              unsigned int sof_eof            :  2;
++              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int ndar                       : 28;   /* next descriptor address */
++#endif
++      } bits;
++} IPSEC_RXDMA_CURR_DESC_T;
++
++
++
++/******************************************************/
++/*    the field definition of IPSEC module Register   */
++/******************************************************/
++typedef union
++{
++      unsigned int id;
++      struct bit_0000
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int device_id          : 28;
++              unsigned int revision_id        :  4;
++#else
++              unsigned int revision_id        :  4;
++              unsigned int device_id          : 28;
++#endif
++      } bits;
++} IPSEC_ID_T;
++
++typedef union
++{
++    unsigned int control;
++    struct bit_0004
++    {
++#if (BIG_ENDIAN==1)
++        unsigned int op_mode            :  4; /* Operation Mode for the IPSec Module */
++        unsigned int                    :  1;
++        unsigned int cipher_algorithm   :  3;
++        unsigned int aesnk              :  4; /* AES Key Size */
++        unsigned int mix_key_sel        :  1; /* 0:use rCipherKey0-3  1:use Key Mixer */
++        unsigned int                    :  2;
++        unsigned int fcs_stream_copy    :  1; /* enable authentication stream copy */
++        unsigned int auth_mode          :  1; /* 0-Append or 1-Check Authentication Result */
++        unsigned int auth_algorithm     :  3;
++        unsigned int                    :  1;
++        unsigned int auth_check_len     :  3; /* Number of 32-bit words to be check or appended */
++                                              /* by the authentication module */
++        unsigned int process_id         :  8; /* Used to identify process.This number will be */
++                                              /* copied to the descriptor status of received packet*/
++#else
++        unsigned int process_id         :  8; /* Used to identify process.This number will be */
++                                              /* copied to the descriptor status of received packet*/
++        unsigned int auth_check_len     :  3; /* Number of 32-bit words to be check or appended */
++                                              /* by the authentication module */
++        unsigned int                    :  1;
++        unsigned int auth_algorithm     :  3;
++        unsigned int auth_mode          :  1; /* 0-Append or 1-Check Authentication Result */
++        unsigned int fcs_stream_copy    :  1; /* enable authentication stream copy */
++        unsigned int                    :  2;
++        unsigned int mix_key_sel        :  1; /* 0:use rCipherKey0-3  1:use Key Mixer */
++        unsigned int aesnk              :  4; /* AES Key Size */
++        unsigned int cipher_algorithm   :  3;
++        unsigned int                    :  1;
++        unsigned int op_mode            :  4; /* Operation Mode for the IPSec Module */
++#endif
++    } bits;
++} IPSEC_CONTROL_T;
++
++
++typedef union
++{
++    unsigned int cipher_packet;
++    struct bit_0008
++    {
++#if (BIG_ENDIAN==1)
++        unsigned int cipher_header_len    : 16; /* The header length to be skipped by the cipher */
++        unsigned int cipher_algorithm_len : 16; /* The length of message body to be encrypted/decrypted */
++#else
++        unsigned int cipher_algorithm_len : 16; /* The length of message body to be encrypted/decrypted */
++        unsigned int cipher_header_len    : 16; /* The header length to be skipped by the cipher */
++#endif
++    } bits;
++} IPSEC_CIPHER_PACKET_T;
++
++typedef union
++{
++    unsigned int auth_packet;
++    struct bit_000c
++    {
++#if (BIG_ENDIAN==1)
++        unsigned int auth_header_len    : 16; /* The header length that is to be skipped by the authenticator */
++        unsigned int auth_algorithm_len : 16; /* The length of message body that is to be authenticated */
++#else
++        unsigned int auth_algorithm_len : 16; /* The length of message body that is to be authenticated */
++        unsigned int auth_header_len    : 16; /* The header length that is to be skipped by the authenticator */
++#endif
++    } bits;
++} IPSEC_AUTH_PACKET_T;
++
++typedef union
++{
++    unsigned int status;
++    struct bit_00a8
++    {
++#if (BIG_ENDIAN==1)
++        unsigned int auth_cmp_rslt  :  1; /* Authentication Compare result */
++        unsigned int wep_crc_ok     :  1; /* WEP ICV compare result */
++        unsigned int tkip_mic_ok    :  1; /* TKIP Mic compare result */
++        unsigned int ccm_mic_ok     :  1; /* CCM Mic compare result */
++        unsigned int                : 16;
++        unsigned int parser_err_code:  4; /* Authentication Compare result */
++        unsigned int auth_err_code  :  4; /* Authentication module error code */
++        unsigned int cipher_err_code:  4; /* Cipher module erroe code */
++#else
++        unsigned int cipher_err_code:  4; /* Cipher module erroe code */
++        unsigned int auth_err_code  :  4; /* Authentication module error code */
++        unsigned int parser_err_code:  4; /* Authentication Compare result */
++        unsigned int                : 16;
++        unsigned int ccm_mic_ok     :  1; /* CCM Mic compare result */
++        unsigned int tkip_mic_ok    :  1; /* TKIP Mic compare result */
++        unsigned int wep_crc_ok     :  1; /* WEP ICV compare result */
++        unsigned int auth_cmp_rslt  :  1; /* Authentication Compare result */
++#endif
++    } bits;
++} IPSEC_STATUS_T;
++
++
++
++/************************************************************************/
++/*              IPSec Descriptor Format                                 */
++/************************************************************************/
++typedef struct descriptor_t
++{
++      union frame_control_t
++      {
++              unsigned int bits32;
++              struct bits_0000
++              {
++#if (BIG_ENDIAN==1)
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int            : 1;    /* authentication compare result */
++                      unsigned int            : 6;    /* checksum[15:8] */
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++#else
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int            : 6;    /* checksum[15:8] */
++                      unsigned int            : 1;    /* authentication compare result */
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++#endif
++              } bits;
++      } frame_ctrl;
++
++      union flag_status_t
++      {
++              unsigned int bits32;
++              struct bits_0004
++              {
++#if (BIG_ENDIAN==1)
++//            unsigned int checksum   : 8; /* checksum[7:0] */
++                      unsigned int            : 4;
++                      unsigned int auth_result: 1;
++                      unsigned int wep_crc_ok : 1;
++                      unsigned int tkip_mic_ok: 1;
++                      unsigned int ccmp_mic_ok: 1;
++                      unsigned int process_id : 8;
++                      unsigned int frame_count:16;
++#else
++                      unsigned int frame_count:16;
++                      unsigned int process_id : 8;
++                      unsigned int ccmp_mic_ok: 1;
++                      unsigned int tkip_mic_ok: 1;
++                      unsigned int wep_crc_ok : 1;
++                      unsigned int auth_result: 1;
++                      unsigned int            : 4;
++//            unsigned int checksum   : 8; /* checksum[7:0] */
++#endif
++              } bits_rx_status;
++
++              struct bits_0005
++              {
++#if (BIG_ENDIAN==1)
++            unsigned int            : 8;
++                      unsigned int process_id : 8;
++                      unsigned int frame_count:16;
++#else
++                      unsigned int frame_count:16;
++                      unsigned int process_id : 8;
++            unsigned int            : 8;
++#endif
++              } bits_tx_status;
++
++              struct bits_0006
++              {
++#if (BIG_ENDIAN==1)
++                      unsigned int            :22;
++                      unsigned int tqflag     :10;
++#else
++                      unsigned int tqflag     :10;
++                      unsigned int            :22;
++#endif
++              } bits_tx_flag;
++      } flag_status;
++
++      unsigned int buf_adr;   /* data buffer address */
++
++      union next_desc_t
++      {
++              unsigned int next_descriptor;
++              struct bits_000c
++              {
++#if (BIG_ENDIAN==1)
++                      unsigned int ndar               :28;    /* next descriptor address */
++                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
++                      unsigned int dec                : 1;    /* AHB bus address. 0-increment; 1-decrement */
++                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
++                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
++#else
++                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
++                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
++                      unsigned int dec                : 1;    /* AHB bus address. 0-increment; 1-decrement */
++                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
++                      unsigned int ndar               :28;    /* next descriptor address */
++#endif
++              } bits;
++      } next_desc;
++} IPSEC_DESCRIPTOR_T;
++
++
++typedef struct IPSEC_S
++{
++    unsigned char       *tx_bufs;
++    unsigned char       *rx_bufs;
++      IPSEC_DESCRIPTOR_T      *tx_desc;           /* point to virtual TX descriptor address*/
++      IPSEC_DESCRIPTOR_T      *rx_desc;           /* point to virtual RX descriptor address*/
++      IPSEC_DESCRIPTOR_T      *tx_cur_desc;   /* point to current TX descriptor */
++      IPSEC_DESCRIPTOR_T      *rx_cur_desc;   /* point to current RX descriptor */
++      IPSEC_DESCRIPTOR_T  *tx_finished_desc;
++      IPSEC_DESCRIPTOR_T  *rx_finished_desc;
++      dma_addr_t          rx_desc_dma;        /* physical RX descriptor address */
++      dma_addr_t          tx_desc_dma;    /* physical TX descriptor address */
++      dma_addr_t          rx_bufs_dma;    /* physical RX descriptor address */
++      dma_addr_t          tx_bufs_dma;    /* physical TX descriptor address */
++} IPSEC_T;
++
++
++/*=====================================================================================================*/
++/*  Data Structure of IPSEC Control Packet  */
++/*=====================================================================================================*/
++typedef struct IPSEC_ECB_AUTH_S
++{
++    IPSEC_CONTROL_T         control; /* control parameter */
++    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
++    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
++    unsigned char           cipher_key[8*4];
++    unsigned char           auth_check_val[5*4];
++} IPSEC_ECB_AUTH_T;
++
++typedef struct IPSEC_CBC_AUTH_S
++{
++    IPSEC_CONTROL_T         control; /* control parameter */
++    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
++    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
++    unsigned char           cipher_iv[4*4];
++    unsigned char           cipher_key[8*4];
++    unsigned char           auth_check_val[5*4];
++} IPSEC_CBC_AUTH_T;
++
++typedef struct IPSEC_ECB_HMAC_AUTH_S
++{
++    IPSEC_CONTROL_T         control; /* control parameter */
++    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
++    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
++    unsigned char           cipher_key[8*4];
++    unsigned char           auth_key[16*4];
++    unsigned char           auth_check_val[5*4];
++} IPSEC_ECB_AUTH_HMAC_T;
++
++typedef struct IPSEC_CBC_HMAC_AUTH_S
++{
++    IPSEC_CONTROL_T         control; /* control parameter */
++    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
++    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
++    unsigned char           cipher_iv[4*4];
++    unsigned char           cipher_key[8*4];
++    unsigned char           auth_key[16*4];
++    unsigned char           auth_check_val[5*4];
++} IPSEC_CBC_AUTH_HMAC_T;
++
++typedef struct IPSEC_HMAC_AUTH_S
++{
++    IPSEC_CONTROL_T         control; /* control parameter */
++    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
++    unsigned char           auth_key[16*4];
++    unsigned char           auth_check_val[5*4];
++} IPSEC_HMAC_AUTH_T;
++
++typedef union
++{
++    unsigned char auth_pkt[28];
++
++    struct IPSEC_AUTH_S
++    {
++        IPSEC_CONTROL_T         control; /* control parameter(4-byte) */
++        IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter(4-byte) */
++        unsigned char           auth_check_val[5*4];
++    } var;
++} IPSEC_AUTH_T;
++
++typedef struct IPSEC_CIPHER_CBC_S
++{
++    IPSEC_CONTROL_T         control; /* control parameter */
++    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
++    unsigned char           cipher_iv[4*4];
++    unsigned char           cipher_key[8*4];
++} IPSEC_CIPHER_CBC_T;
++
++typedef struct IPSEC_CIPHER_ECB_S
++{
++    IPSEC_CONTROL_T         control; /* control parameter */
++    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
++    unsigned char           cipher_key[8*4];
++} IPSEC_CIPHER_ECB_T;
++
++
++/****************************************************************************
++ *                          Structure Definition                            *
++ ****************************************************************************/
++struct IPSEC_PACKET_S
++{
++    unsigned int    op_mode;            /* CIPHER_ENC(1),CIPHER_DEC(3),AUTH(4),ENC_AUTH(5),AUTH_DEC(7) */
++    unsigned int    cipher_algorithm;   /* ECB_DES(0),ECB_3DES(1),ECB_AES(2),CBC_DES(4),CBC_3DES(5),CBC_AES(6) */
++    unsigned int    auth_algorithm;     /* SHA1(0),MD5(1),HMAC_SHA1(2),HMAC_MD5(3),FCS(4) */
++    unsigned int    auth_result_mode;   /* AUTH_APPEND(0),AUTH_CHKVAL(1) */
++    unsigned int    process_id;         /* Used to identify the process */
++    unsigned int    auth_header_len;    /* Header length to be skipped by the authenticator */
++    unsigned int    auth_algorithm_len; /* Length of message body that is to be authenticated */
++    unsigned int    cipher_header_len;  /* Header length to be skipped by the cipher */
++    unsigned int    cipher_algorithm_len;   /* Length of message body to be encrypted or decrypted */
++    unsigned char   iv[16];             /* Initial vector used for DES,3DES,AES */
++    unsigned int    iv_size;            /* Initial vector size */
++    unsigned char   auth_key[64];       /* authentication key */
++    unsigned int    auth_key_size;      /* authentication key size */
++    unsigned char   cipher_key[32];     /* cipher key */
++    unsigned int    cipher_key_size;    /* cipher key size */
++    struct scatterlist *in_packet;         /* input_packet buffer pointer */
++    //unsigned char           *in_packet;         /* input_packet buffer pointer */
++    unsigned int    pkt_len;            /* input total packet length */
++    unsigned char   auth_checkval[20];  /* Authentication check value/FCS check value */
++    struct IPSEC_PACKET_S *next,*prev;        /* pointer to next/previous operation to perform on buffer */
++    void (*callback)(struct IPSEC_PACKET_S *); /* function to call when done authentication/cipher */
++    unsigned char   *out_packet;        /* output_packet buffer pointer */
++    //struct scatterlist *out_packet;        /* output_packet buffer pointer */
++    unsigned int    out_pkt_len;        /* output total packet length */
++    unsigned int    auth_cmp_result;    /* authentication compare result */
++    unsigned int    checksum;           /* checksum value */
++    unsigned int    status;             /* ipsec return status. 0:success, others:fail */
++#if (IPSEC_TEST == 1)
++    unsigned char    *sw_packet;         /* for test only */
++    unsigned int    sw_pkt_len;         /* for test only */
++#endif
++} ;
++
++/*****************************************************************************
++ * Function    : ipsec_crypto_hw_process
++ * Description : This function processes H/W authentication and cipher.
++ *       Input : op_info - the authentication and cipher information for IPSec module.
++ *      Output : none.
++ *      Return : 0 - success, others - failure.
++ *****************************************************************************/
++int ipsec_crypto_hw_process(struct IPSEC_PACKET_S  *op_info);
++
++int ipsec_get_cipher_algorithm(unsigned char *alg_name,unsigned int alg_mode);
++int ipsec_get_auth_algorithm(unsigned char *alg_name,unsigned int alg_mode);
++#if 0
++void ipsec_sw_authentication(char *data,unsigned int data_len,char *authkey,char authAlgorithm,char *auth_result);
++void ipsec_sw_cipher(unsigned char *pt,unsigned int pt_len, unsigned char *cipher_key, unsigned int key_size,
++                            unsigned char *iv,unsigned int cipherAlgorithm,unsigned char *ct);
++void ipsec_sw_auth_cipher(unsigned int op_mode,char *data,unsigned int data_len,
++                                BYTE *auth_key,char authAlgorithm,char *auth_result,
++                                char *pt, unsigned int pt_len,char *cipher_key, int key_size,
++                                char *iv, char cipherAlgorithm,char *ct);
++#endif
++
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/sl_random.h
+@@ -0,0 +1,2 @@
++#define RANDOM_ADD            (IO_ADDRESS (0x051000000) + 0x0AC)
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/system.h
+@@ -0,0 +1,54 @@
++/*
++ *  linux/include/asm-arm/arch-sl2312/system.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_SYSTEM_H
++#define __ASM_ARCH_SYSTEM_H
++
++#include <asm/arch/platform.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/it8712.h>
++#include <asm/io.h>
++
++static void arch_idle(void)
++{
++      /*
++       * This should do all the clock switching
++       * and wait for interrupt tricks
++       */
++      cpu_do_idle();
++}
++
++extern __inline__ void arch_reset(char mode)
++{
++      __raw_writel( (int) GLOBAL_RESET|RESET_CPU1, IO_ADDRESS(SL2312_GLOBAL_BASE) + GLOBAL_RESET_REG);
++}
++
++
++void (*pm_power_off)(void);
++//{
++//    printk("arch_power_off\n");
++
++      // Power off
++//    __raw_writel( (int) 0x00000001, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
++
++//}
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/timer.h
+@@ -0,0 +1,53 @@
++/*
++ *
++ *  This file contains the register definitions for the Excalibur
++ *  Timer TIMER00.
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __TIMER_H
++#define __TIMER_H
++
++/*
++ * Register definitions for the timers
++ */
++
++#define TIMER_COUNT(BASE_ADDR)          (TIMER_TYPE (BASE_ADDR  + 0x00 ))
++#define TIMER_LOAD(BASE_ADDR)           (TIMER_TYPE (BASE_ADDR  + 0x04 ))
++#define TIMER_MATCH1(BASE_ADDR)         (TIMER_TYPE (BASE_ADDR  + 0x08 ))
++#define TIMER_MATCH2(BASE_ADDR)         (TIMER_TYPE (BASE_ADDR  + 0x0C ))
++#define TIMER_CR(BASE_ADDR)             (TIMER_TYPE (BASE_ADDR  + 0x30 ))
++#define TIMER_1_CR_ENABLE_MSK                     (0x00000001)
++#define TIMER_1_CR_ENABLE_OFST                    (0)
++#define TIMER_1_CR_CLOCK_MSK                      (0x00000002)
++#define TIMER_1_CR_CLOCK_OFST                     (1)
++#define TIMER_1_CR_INT_MSK                    (0x00000004)
++#define TIMER_1_CR_INT_OFST               (2)
++#define TIMER_2_CR_ENABLE_MSK                     (0x00000008)
++#define TIMER_2_CR_ENABLE_OFST                    (3)
++#define TIMER_2_CR_CLOCK_MSK                      (0x00000010)
++#define TIMER_2_CR_CLOCK_OFST                     (4)
++#define TIMER_2_CR_INT_MSK                    (0x00000020)
++#define TIMER_2_CR_INT_OFST               (5)
++#define TIMER_3_CR_ENABLE_MSK                     (0x00000040)
++#define TIMER_3_CR_ENABLE_OFST                    (6)
++#define TIMER_3_CR_CLOCK_MSK                      (0x00000080)
++#define TIMER_3_CR_CLOCK_OFST                     (7)
++#define TIMER_3_CR_INT_MSK                    (0x00000100)
++#define TIMER_3_CR_INT_OFST               (8)
++
++#endif /* __TIMER00_H */
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/timex.h
+@@ -0,0 +1,29 @@
++/*
++ *  linux/include/asm-arm/arch-epxa10db/timex.h
++ *
++ *  Excalibur timex specifications
++ *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*
++ * ??
++ */
++#include <asm/arch/sl2312.h>
++
++#define CLOCK_TICK_RATE               APB_CLK
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/uart.h
+@@ -0,0 +1,100 @@
++/* *
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __UART_H
++#define __UART_H
++
++/*
++ * Register definitions for the UART
++ */
++
++#define UART_TX_FIFO_SIZE      (15)
++
++#define UART_RBR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x00))  // read
++#define UART_THR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x00))  // write
++#define UART_IER(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x04))
++#define UART_IER_MS                                 (0x08)
++#define UART_IER_RLS                                (0x04)
++#define UART_IER_TE                                 (0x02)
++#define UART_IER_DR                                 (0x01)
++#define UART_IIR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x08))   // read
++#define UART_IIR_NONE                             (0x01)      /* No interrupt pending */
++#define UART_IIR_RLS                              (0x06)      /* Receive Line Status */
++#define UART_IIR_DR                               (0x04)      /* Receive Data Ready */
++#define UART_IIR_TIMEOUT                          (0x0c)      /* Receive Time Out */
++#define UART_IIR_TE                               (0x02)      /* THR Empty */
++#define UART_IIR_MODEM                            (0x00)      /* Modem Status */
++#define UART_FCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x08))  // write
++#define UART_FCR_FE                               (0x01)      /* FIFO Enable */
++#define UART_FCR_RXFR                             (0x02)      /* Rx FIFO Reset */
++#define UART_FCR_TXFR                             (0x04)      /* Tx FIFO Reset */
++#define UART_FCR_FIFO_1C                            (0x00)
++#define UART_FCR_FIFO_4C                            (0x40)
++#define UART_FCR_FIFO_8C                            (0x80)
++#define UART_FCR_FIFO_14C                           (0xC0)
++#define UART_LCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x0C))
++#define UART_LCR_MSK                                (0x03)
++#define UART_LCR_LEN5                             (0x00)
++#define UART_LCR_LEN6                             (0x01)
++#define UART_LCR_LEN7                             (0x02)
++#define UART_LCR_LEN8                             (0x03)
++#define UART_LCR_STOP                             (0x04)
++#define UART_LCR_EVEN                             (0x18)      /* Even Parity */
++#define UART_LCR_ODD                              (0x08)      /* Odd Parity */
++#define UART_LCR_PE                               (0x08)      /* Parity Enable */
++#define UART_LCR_SETBREAK                         (0x40)      /* Set Break condition */
++#define UART_LCR_STICKPARITY                      (0x20)      /* Stick Parity Enable */
++#define UART_LCR_DLAB                             (0x80)      /* Divisor Latch Access Bit */
++#define UART_MCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x10))
++#define UART_MCR_DTR                              (0x1)       /* Data Terminal Ready */
++#define UART_MCR_RTS                              (0x2)       /* Request to Send */
++#define UART_MCR_OUT1                             (0x4)       /* output       1 */
++#define UART_MCR_OUT2                             (0x8)       /* output2 or global interrupt enable */
++#define UART_MCR_LPBK                             (0x10)      /* loopback mode */
++#define UART_MCR_MASK                               (0xE3)
++#define UART_LSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x14))
++#define UART_LSR_DR                               (0x01)      /* Data Ready */
++#define UART_LSR_OE                               (0x02)      /* Overrun Error */
++#define UART_LSR_PE                               (0x04)      /* Parity Error */
++#define UART_LSR_FE                               (0x08)      /* Framing Error */
++#define UART_LSR_BI                                 (0x10)            /* Break Interrupt */
++#define UART_LSR_THRE                               (0x20)            /* THR Empty */
++#define UART_LSR_TE                                 (0x40)            /* Transmitte Empty */
++#define UART_LSR_DE                                 (0x80)            /* FIFO Data Error */
++#define UART_MSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x18))
++#define UART_MSR_DELTACTS                         (0x01)      /* Delta CTS */
++#define UART_MSR_DELTADSR                         (0x02)      /* Delta DSR */
++#define UART_MSR_TERI                             (0x04)      /* Trailing Edge RI */
++#define UART_MSR_DELTACD                          (0x08)      /* Delta CD */
++#define UART_MSR_CTS                              (0x10)      /* Clear To Send */
++#define UART_MSR_DSR                              (0x20)      /* Data Set Ready */
++#define UART_MSR_RI                               (0x40)      /* Ring Indicator */
++#define UART_MSR_DCD                              (0x80)      /* Data Carrier Detect */
++#define UART_SPR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x1C))
++#define UART_DIV_LO(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x0))
++#define UART_DIV_HI(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x4))
++#define UART_PSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x8))
++#define UART_MDR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x20))
++#define UART_MDR_SERIAL                             (0x0)
++
++#define UART_MSR_DDCD 0x08    /* Delta DCD */
++#define UART_MSR_DDSR 0x02    /* Delta DSR */
++#define UART_MSR_DCTS 0x01    /* Delta CTS */
++#define UART_MSR_ANY_DELTA 0x0F       /* Any of the delta bits! */
++
++
++#endif /* __UART_H */
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/uncompress.h
+@@ -0,0 +1,94 @@
++/*
++ *  linux/include/asm-arm/arch-epxa10db/uncompress.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *  Copyright (C) 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#include "asm/arch/platform.h"
++#include "asm/arch/hardware.h"
++#define UART_TYPE (volatile unsigned int*)
++#ifndef CONFIG_SERIAL_IT8712
++#include "asm/arch/uart.h"
++#endif
++extern unsigned int it8712_uart_base;
++
++/*
++ * This does not append a newline
++ */
++static void putstr(const char *s)
++{
++
++#ifdef CONFIG_SERIAL_IT8712
++
++      unsigned char *base,*status,stat;
++      int i ;
++
++      status = (unsigned char*)it8712_uart_base + 5;
++      base = (unsigned char*)it8712_uart_base ;
++
++      while (*s) {
++
++              stat = *status;
++              while (!(stat&0x20)) {                          // check status
++                      for(i=0;i<0x10;i++)     ;
++                      status = (unsigned char*)it8712_uart_base + 5;
++                      stat = *status ;
++              }
++
++              *base = *s;
++              barrier();
++
++              if (*s == '\n') {
++                      stat = *status;
++                      while (!(stat&0x20)) {                  // check status
++                              for(i=0;i<0x10;i++)     ;
++                              status = (unsigned char*)it8712_uart_base + 5;
++                              stat = *status ;
++              }
++
++                      barrier();
++                      *base = '\r';
++              }
++              s++;
++      }
++
++#else
++      while (*s) {
++              while (!(*UART_LSR(SL2312_UART_BASE) &
++                       UART_LSR_THRE));
++                     barrier();
++
++              *UART_THR(SL2312_UART_BASE) = *s;
++
++              if (*s == '\n') {
++                      while (!(*UART_LSR(SL2312_UART_BASE) &
++                               UART_LSR_THRE));
++                              barrier();
++
++                      *UART_THR(SL2312_UART_BASE) = '\r';
++              }
++              s++;
++      }
++#endif
++}
++
++/*
++ * nothing to do
++ */
++#define arch_decomp_setup()
++
++#define arch_decomp_wdog()
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/vmalloc.h
+@@ -0,0 +1,36 @@
++/*
++ *  linux/include/asm-arm/arch-epxa10db/vmalloc.h
++ *
++ *  Copyright (C) 2000 Russell King.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*
++ * Just any arbitrary offset to the start of the vmalloc VM area: the
++ * current 8MB value just means that there will be a 8MB "hole" after the
++ * physical memory until the kernel virtual memory starts.  That means that
++ * any out-of-bounds memory accesses will hopefully be caught.
++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
++ * area for the same reason. ;)
++ */
++#define VMALLOC_OFFSET          (8*1024*1024)
++#define VMALLOC_START   (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
++#define VMALLOC_VMADDR(x) ((unsigned long)(x))
++#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
++
++//#define MODULE_START    (PAGE_OFFSET - 16*1048576)
++//#define MODULE_END      (PAGE_OFFSET)
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/watchdog.h
+@@ -0,0 +1,58 @@
++#ifndef __WATCHDOG_H
++#define __WATCHDOG_H
++
++#define WATCHDOG_BASE                   (IO_ADDRESS (SL2312_WAQTCHDOG_BASE))
++#define WATCHDOG_COUNTER                  (WATCHDOG_BASE + 0x00)
++#define WATCHDOG_LOAD                     (WATCHDOG_BASE + 0x04)
++#define WATCHDOG_RESTART                  (WATCHDOG_BASE + 0x08)
++#define WATCHDOG_CR                       (WATCHDOG_BASE + 0x0C)
++#define WATCHDOG_STATUS                   (WATCHDOG_BASE + 0x10)
++#define WATCHDOG_CLEAR                    (WATCHDOG_BASE + 0x14)
++#define WATCHDOG_INTRLEN                  (WATCHDOG_BASE + 0x18)
++
++#define WATCHDOG_WDENABLE_MSK                   (0x00000001)
++#define WATCHDOG_WDENABLE_OFST                  (0)
++#define WATCHDOG_WDRST_MSK              (0x00000002)
++#define WATCHDOG_WDRST_OFST             (1)
++#define WATCHDOG_WDINTR_MSK             (0x00000004)
++#define WATCHDOG_WDINTR_OFST            (2)
++#define WATCHDOG_WDEXT_MSK              (0x00000008)
++#define WATCHDOG_WDEXT_OFST             (3)
++#define WATCHDOG_WDCLOCK_MSK            (0x00000010)
++#define WATCHDOG_WDCLOCK_OFST                   (4)
++#define WATCHDOG_CR_MASK                  (0x0000001F)
++
++#define WATCHDOG_CLEAR_STATUS             0x1
++#define WATCHDOG_ENABLE                   1
++#define WATCHDOG_DISABLE                  0
++#define WATCHDOG_RESTART_VALUE            0x5AB9
++
++#define WATCHDOG_MINOR                          130
++
++#define WATCHDOG_IOCTRL_DISABLE                 0x01
++#define WATCHDOG_IOCTRL_SETTIME                 0x02
++#define WATCHDOG_IOCTRL_ENABLE                  0x03
++#define WATCHDOG_IOCTRL_RESTART                 0x04
++
++#define WATCHDOG_TIMEOUT_SCALE            APB_CLK
++#define WATCHDOG_TIMEOUT_MARGIN           30
++#define WATCHDOG_DRIVER_OPEN              1
++#define WATCHDOG_DRIVER_CLOSE             0
++
++
++static void     watchdog_disable(void);
++static void     watchdog_enable(void);
++static int      watchdog_open(struct inode *, struct file *);
++static int      watchdog_release(struct inode *, struct file *);
++static ssize_t  watchdog_read(struct file *, char *, size_t, loff_t *);
++static ssize_t  watchdog_write(struct file *, const char *, size_t, loff_t *);
++static int      watchdog_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
++#ifdef WATCHDOG_TEST
++static void watchdog_fire(int, void *, struct pt_regs *);
++#endif
++
++
++
++
++
++#endif
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/xor.h
+@@ -0,0 +1,29 @@
++/*
++ * include/asm-arm/arch-sl2312/xor.h
++ *
++ * Copyright (C) 2005 Storlink Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _ASM_ARCH_XOR_H
++#define _ASM_ARCH_XOR_H
++
++/*
++ * Function prototypes
++ */
++void xor_gemini_2(unsigned long bytes, unsigned long *p1, unsigned long *p2);
++
++void xor_gemini_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++                           unsigned long *p3);
++
++void xor_gemini_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++                           unsigned long *p3, unsigned long *p4);
++
++void xor_gemini_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++                           unsigned long *p3, unsigned long *p4, unsigned long *p5);
++
++#endif /* _ASM_ARCH_XOR_H */
++
+--- a/include/asm-arm/cacheflush.h
++++ b/include/asm-arm/cacheflush.h
+@@ -46,6 +46,18 @@
+ # define MULTI_CACHE 1
+ #endif
++/***********************************************************************
++ *             Storlink SoC -- Cache
++ ***********************************************************************/
++#if defined(CONFIG_CPU_FA526)
++# ifdef _CACHE
++#  define MULTI_CACHE 1
++# else
++#  define _CACHE fa
++# endif
++#endif
++/***********************************************************************/
++
+ #if defined(CONFIG_CPU_ARM926T)
+ # ifdef _CACHE
+ #  define MULTI_CACHE 1
+--- a/include/asm-arm/page.h
++++ b/include/asm-arm/page.h
+@@ -74,6 +74,18 @@
+ # endif
+ #endif
++/***********************************************************************
++ *             Storlink SoC -- flash
++ ***********************************************************************/
++#ifdef CONFIG_CPU_COPY_FA
++# ifdef _USER
++#  define MULTI_USER 1
++# else
++#  define _USER fa
++# endif
++#endif
++/***********************************************************************/
++
+ #ifdef CONFIG_CPU_SA1100
+ # ifdef _USER
+ #  define MULTI_USER 1
+--- a/include/asm-arm/proc-fns.h
++++ b/include/asm-arm/proc-fns.h
+@@ -89,6 +89,14 @@
+ #   define CPU_NAME cpu_arm922
+ #  endif
+ # endif
++# ifdef CONFIG_CPU_FA526
++#  ifdef CPU_NAME
++#   undef  MULTI_CPU
++#   define MULTI_CPU
++#  else
++#   define CPU_NAME cpu_fa526
++#  endif
++# endif
+ # ifdef CONFIG_CPU_ARM925T
+ #  ifdef CPU_NAME
+ #   undef  MULTI_CPU
+--- a/include/asm-arm/tlbflush.h
++++ b/include/asm-arm/tlbflush.h
+@@ -39,6 +39,8 @@
+ #define TLB_V6_D_ASID (1 << 17)
+ #define TLB_V6_I_ASID (1 << 18)
++#define TLB_DINVAL      (1 << 28)
++#define TLB_BTB         (1 << 29)
+ #define TLB_DCLEAN    (1 << 30)
+ #define TLB_WB                (1 << 31)
+@@ -52,6 +54,7 @@
+  *      v4wb  - ARMv4 with write buffer without I TLB flush entry instruction
+  *      v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
+  *      v6wbi - ARMv6 with write buffer with I TLB flush entry instruction
++ *    fa    - ARMv4 with write buffer with UTLB and branch target buffer (BTB)
+  */
+ #undef _TLB
+ #undef MULTI_TLB
+@@ -86,6 +89,44 @@
+ # define v4_always_flags      (-1UL)
+ #endif
++#ifdef CONFIG_CPU_FA_BTB
++#define __TLB_BTB      TLB_BTB
++#else
++#define __TLB_BTB      0
++#endif
++
++#ifdef CONFIG_CPU_FA_WB_DISABLE
++#define __TLB_WB       0
++#else
++#define __TLB_WB       TLB_WB
++#endif
++
++/* Fix buggy CPU which doesn't invalidate Dcache properly */
++#ifdef CONFIG_CPU_FA520
++#define __TLB_DINVAL   TLB_DINVAL
++#elif defined(CONFIG_CPU_FA526)
++//#define __TLB_DINVAL   TLB_DINVAL
++#define __TLB_DINVAL   0
++#else
++#define __TLB_DINVAL   0
++#endif
++
++#define fa_tlb_flags  (__TLB_WB | __TLB_BTB | __TLB_DINVAL | TLB_DCLEAN | \
++                         TLB_V4_U_FULL | TLB_V4_U_PAGE)
++
++#ifdef CONFIG_CPU_TLB_FA
++# define fa_possible_flags    fa_tlb_flags
++# define fa_always_flags      fa_tlb_flags
++# ifdef _TLB
++#  define MULTI_TLB 1
++# else
++#  define _TLB fa
++# endif
++#else
++# define fa_possible_flags    0
++# define fa_always_flags      (-1UL)
++#endif
++
+ #define v4wbi_tlb_flags       (TLB_WB | TLB_DCLEAN | \
+                        TLB_V4_I_FULL | TLB_V4_D_FULL | \
+                        TLB_V4_I_PAGE | TLB_V4_D_PAGE)
+@@ -246,12 +287,14 @@
+                                v4_possible_flags | \
+                                v4wbi_possible_flags | \
+                                v4wb_possible_flags | \
++                 fa_possible_flags | \
+                                v6wbi_possible_flags)
+ #define always_tlb_flags      (v3_always_flags & \
+                                v4_always_flags & \
+                                v4wbi_always_flags & \
+                                v4wb_always_flags & \
++                 fa_always_flags & \
+                                v6wbi_always_flags)
+ #define tlb_flag(f)   ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
+@@ -261,6 +304,9 @@
+       const int zero = 0;
+       const unsigned int __tlb_flag = __cpu_tlb_flags;
++      if (tlb_flag(TLB_DINVAL))
++              asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
++
+       if (tlb_flag(TLB_WB))
+               dsb();
+@@ -281,6 +327,13 @@
+               dsb();
+               isb();
+       }
++
++      if (tlb_flag(TLB_BTB))
++      {
++        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
++              asm("mov r0, r0" : : );
++              asm("mov r0, r0" : : );
++      }
+ }
+ static inline void local_flush_tlb_mm(struct mm_struct *mm)
+@@ -289,6 +342,9 @@
+       const int asid = ASID(mm);
+       const unsigned int __tlb_flag = __cpu_tlb_flags;
++      if (tlb_flag(TLB_DINVAL))
++              asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
++
+       if (tlb_flag(TLB_WB))
+               dsb();
+@@ -317,6 +373,14 @@
+               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+               dsb();
+       }
++
++      if (tlb_flag(TLB_BTB))
++      {
++        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
++              asm("mov r0, r0" : : );
++              asm("mov r0, r0" : : );
++      }
++
+ }
+ static inline void
+@@ -327,6 +391,9 @@
+       uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
++      if (tlb_flag(TLB_DINVAL))
++        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero)); // clean & invalidate data cache all
++
+       if (tlb_flag(TLB_WB))
+               dsb();
+@@ -357,6 +424,13 @@
+               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+               dsb();
+       }
++
++      if (tlb_flag(TLB_BTB))
++      {
++        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
++              asm("mov r0, r0" : : );
++              asm("mov r0, r0" : : );
++      }
+ }
+ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
+@@ -366,6 +440,9 @@
+       kaddr &= PAGE_MASK;
++      if (tlb_flag(TLB_DINVAL))
++        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
++
+       if (tlb_flag(TLB_WB))
+               dsb();
+@@ -386,6 +463,12 @@
+               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
+       if (tlb_flag(TLB_V6_I_PAGE))
+               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
++      if (tlb_flag(TLB_BTB))
++      {
++        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
++              asm("mov r0, r0" : : );
++              asm("mov r0, r0" : : );
++      }
+       if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+                    TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+@@ -412,6 +495,7 @@
+  */
+ static inline void flush_pmd_entry(pmd_t *pmd)
+ {
++      const unsigned int zero = 0;
+       const unsigned int __tlb_flag = __cpu_tlb_flags;
+       if (tlb_flag(TLB_DCLEAN))
+@@ -419,15 +503,30 @@
+                       : : "r" (pmd) : "cc");
+       if (tlb_flag(TLB_WB))
+               dsb();
++
++      if (tlb_flag(TLB_BTB)) // Luke Lee 05/16/2005
++      {
++        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
++              asm("mov r0, r0" : : );
++              asm("mov r0, r0" : : );
++      }
+ }
+ static inline void clean_pmd_entry(pmd_t *pmd)
+ {
++    const unsigned int zero = 0; // Luke Lee 05/16/2005 ins 1
+       const unsigned int __tlb_flag = __cpu_tlb_flags;
+       if (tlb_flag(TLB_DCLEAN))
+               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
+                       : : "r" (pmd) : "cc");
++
++      if (tlb_flag(TLB_BTB)) // Luke Lee 05/16/2005
++      {
++        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
++              asm("mov r0, r0" : : );
++              asm("mov r0, r0" : : );
++      }
+ }
+ #undef tlb_flag
+--- a/include/asm-arm/xor.h
++++ b/include/asm-arm/xor.h
+@@ -139,3 +139,18 @@
+               xor_speed(&xor_block_8regs);    \
+               xor_speed(&xor_block_32regs);   \
+       } while (0)
++
++#ifdef CONFIG_GEMINI_XOR_ACCE
++#include <asm/arch/xor.h>
++static struct xor_block_template xor_block_gemini = {
++      .name   = "gemini xor acceleration",
++      .do_2   = xor_gemini_2,
++      .do_3   = xor_gemini_3,
++      .do_4   = xor_gemini_4,
++      .do_5   = xor_gemini_5,};
++#undef XOR_TRY_TEMPLATES
++#define XOR_TRY_TEMPLATES                     \
++      do {                                    \
++      xor_speed(&xor_block_gemini); \
++      } while (0)
++#endif
+--- a/include/linux/apm_bios.h
++++ b/include/linux/apm_bios.h
+@@ -217,4 +217,24 @@
+ #define APM_IOC_STANDBY               _IO('A', 1)
+ #define APM_IOC_SUSPEND               _IO('A', 2)
++// add by jason for power control
++struct pwc_ioctl_data {
++      unsigned int action;    // sword struct
++      unsigned int data;      // stand shutdown time for PWC_SET_SHUT_TIME
++                              // stand shutdown source for PWC_WAIT_BTN
++};
++
++#define POWEROFF              0x01
++#define RESTORE_DEFAULT       0x02
++#define SYSTEM_REBOOT 0x04
++
++#define PWR_SRC_CIR           0x10
++#define PWR_SRC_RTC           0x20
++#define PWR_SRC_BTN           0x40
++
++#define       PWC_IOCTL_BASE                  'A'                             // use linux APM ioctl
++#define PWC_SET_SHUT_TIME             _IOW('A', 16, struct pwc_ioctl_data)
++#define PWC_WAIT_BTN                  _IOR('A', 17, struct pwc_ioctl_data)
++#define PWC_SHUTDOWN                  _IO ('A', 18)
++
+ #endif        /* LINUX_APM_H */
+--- a/kernel/time.c
++++ b/kernel/time.c
+@@ -76,6 +76,7 @@
+  * why not move it into the appropriate arch directory (for those
+  * architectures that need it).
+  */
++extern void rtc_set_time_second(unsigned int second);
+  
+ asmlinkage long sys_stime(time_t __user *tptr)
+ {
+@@ -87,6 +88,10 @@
+       tv.tv_nsec = 0;
++#ifdef CONFIG_SL2312_RTC
++    rtc_set_time_second(tv.tv_sec);
++#endif
++
+       err = security_settime(&tv, NULL);
+       if (err)
+               return err;
diff --git a/target/linux/storm/patches/002-gmac.patch b/target/linux/storm/patches/002-gmac.patch
new file mode 100644 (file)
index 0000000..d6632ba
--- /dev/null
@@ -0,0 +1,18615 @@
+--- /dev/null
++++ b/drivers/net/sl2312_emac.c
+@@ -0,0 +1,4604 @@
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/compiler.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/completion.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/arch-sl2312/irqs.h>
++#include <asm/arch/it8712.h>
++#include <asm/arch/sl2312.h>
++#include <linux/mtd/kvctl.h>
++#include <linux/sysctl_storlink.h>
++
++#define BIG_ENDIAN    0
++
++#define GMAC_DEBUG      0
++
++#define GMAC_PHY_IF     2
++
++/* define PHY address */
++#define HPHY_ADDR   0x01
++#define GPHY_ADDR   0x02
++
++#define CONFIG_ADM_6999 1
++/* define chip information */
++#define DRV_NAME                      "SL2312"
++#define DRV_VERSION                   "0.1.1"
++#define SL2312_DRIVER_NAME  DRV_NAME " Fast Ethernet driver " DRV_VERSION
++
++/* define TX/RX descriptor parameter */
++#define MAX_ETH_FRAME_SIZE    1920
++#define TX_BUF_SIZE                   MAX_ETH_FRAME_SIZE
++#define TX_DESC_NUM                   128
++#define TX_BUF_TOT_LEN                (TX_BUF_SIZE * TX_DESC_NUM)
++#define RX_BUF_SIZE                   MAX_ETH_FRAME_SIZE
++#define RX_DESC_NUM                   256
++#define RX_BUF_TOT_LEN                (RX_BUF_SIZE * RX_DESC_NUM)
++#define MAX_ISR_WORK        20
++
++unsigned int int_status = 0;
++
++/* define GMAC base address */
++#define GMAC_PHYSICAL_BASE_ADDR           (SL2312_GMAC_BASE)
++#define GMAC_BASE_ADDR                            (IO_ADDRESS(GMAC_PHYSICAL_BASE_ADDR))
++#define GMAC_GLOBAL_BASE_ADDR       (IO_ADDRESS(SL2312_GLOBAL_BASE))
++
++#define GMAC0_BASE                  (IO_ADDRESS(SL2312_GMAC0_BASE))
++#define GMAC1_BASE                  (IO_ADDRESS(SL2312_GMAC1_BASE))
++
++/* memory management utility */
++#define DMA_MALLOC(size,handle)               pci_alloc_consistent(NULL,size,handle)
++#define DMA_MFREE(mem,size,handle)    pci_free_consistent(NULL,size,mem,handle)
++
++//#define gmac_read_reg(offset)       (readl(GMAC_BASE_ADDR + offset))
++//#define gmac_write_reg(offset,data,mask)  writel( (gmac_read_reg(offset)&~mask) |(data&mask),(GMAC_BASE_ADDR+offset))
++
++/* define owner bit */
++#define CPU           0
++#define DMA           1
++
++#define ACTIVE      1
++#define NONACTIVE   0
++
++#define CONFIG_SL_NAPI
++
++#ifndef CONFIG_SL2312_MPAGE
++#define CONFIG_SL2312_MPAGE
++#endif
++
++#ifdef CONFIG_SL2312_MPAGE
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#endif
++
++#ifndef CONFIG_TXINT_DISABLE
++//#define CONFIG_TXINT_DISABLE
++#endif
++
++enum phy_state
++{
++    LINK_DOWN   = 0,
++    LINK_UP     = 1
++};
++
++
++/* transmit timeout value */
++#define TX_TIMEOUT  (6*HZ)
++
++/***************************************/
++/* the offset address of GMAC register */
++/***************************************/
++enum GMAC_REGISTER {
++      GMAC_STA_ADD0   = 0x0000,
++      GMAC_STA_ADD1   = 0x0004,
++      GMAC_STA_ADD2   = 0x0008,
++      GMAC_RX_FLTR    = 0x000c,
++      GMAC_MCAST_FIL0 = 0x0010,
++      GMAC_MCAST_FIL1 = 0x0014,
++      GMAC_CONFIG0    = 0x0018,
++      GMAC_CONFIG1    = 0x001c,
++      GMAC_CONFIG2    = 0x0020,
++      GMAC_BNCR               = 0x0024,
++      GMAC_RBNR               = 0x0028,
++      GMAC_STATUS             = 0x002c,
++      GMAC_IN_DISCARDS= 0x0030,
++      GMAC_IN_ERRORS  = 0x0034,
++      GMAC_IN_MCAST   = 0x0038,
++      GMAC_IN_BCAST   = 0x003c,
++      GMAC_IN_MAC1    = 0x0040,
++      GMAC_IN_MAC2    = 0x0044
++};
++
++/*******************************************/
++/* the offset address of GMAC DMA register */
++/*******************************************/
++enum GMAC_DMA_REGISTER {
++      GMAC_DMA_DEVICE_ID              = 0xff00,
++      GMAC_DMA_STATUS                 = 0xff04,
++      GMAC_TXDMA_CTRL                 = 0xff08,
++      GMAC_TXDMA_FIRST_DESC   = 0xff0c,
++      GMAC_TXDMA_CURR_DESC    = 0xff10,
++      GMAC_RXDMA_CTRL                 = 0xff14,
++      GMAC_RXDMA_FIRST_DESC   = 0xff18,
++      GMAC_RXDMA_CURR_DESC    = 0xff1c,
++};
++
++/*******************************************/
++/* the register structure of GMAC          */
++/*******************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0004
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int sta_add2_l16       : 16;   /* station MAC address2 bits 15 to 0 */
++              unsigned int sta_add1_h16       : 16;   /* station MAC address1 bits 47 to 32 */
++#else
++              unsigned int sta_add1_h16       : 16;   /* station MAC address1 bits 47 to 32 */
++              unsigned int sta_add2_l16       : 16;   /* station MAC address2 bits 15 to 0 */
++#endif
++      } bits;
++} GMAC_STA_ADD1_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_000c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 27;
++              unsigned int error                      :  1;   /* enable receive of all error frames */
++              unsigned int promiscuous        :  1;   /* enable receive of all frames */
++              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
++              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
++              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
++#else
++              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
++              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
++              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
++              unsigned int promiscuous        :  1;   /* enable receive of all frames */
++              unsigned int error                      :  1;   /* enable receive of all error frames */
++              unsigned int                            : 27;
++#endif
++      } bits;
++} GMAC_RX_FLTR_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0018
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int : 10;
++              unsigned int inv_rx_clk     : 1;        /* Inverse RX Clock */
++              unsigned int rising_latch   : 1;
++        unsigned int rx_tag_remove  :  1;   /* Remove Rx VLAN tag */
++        unsigned int ipv6_tss_rx_en :  1;   /* IPv6 TSS RX enable */
++        unsigned int ipv4_tss_rx_en :  1;   /* IPv4 TSS RX enable */
++        unsigned int rgmii_en       :  1;   /* RGMII in-band status enable */
++              unsigned int tx_fc_en           :  1;   /* TX flow control enable */
++              unsigned int rx_fc_en           :  1;   /* RX flow control enable */
++              unsigned int sim_test           :  1;   /* speed up timers in simulation */
++              unsigned int dis_col            :  1;   /* disable 16 collisions abort function */
++              unsigned int dis_bkoff          :  1;   /* disable back-off function */
++              unsigned int max_len            :  3;   /* maximum receive frame length allowed */
++              unsigned int adj_ifg            :  4;   /* adjust IFG from 96+/-56 */
++        unsigned int                :  1;   /* reserved */
++              unsigned int loop_back          :  1;   /* transmit data loopback enable */
++              unsigned int dis_rx                     :  1;   /* disable receive */
++              unsigned int dis_tx                     :  1;   /* disable transmit */
++#else
++              unsigned int dis_tx                     :  1;   /* disable transmit */
++              unsigned int dis_rx                     :  1;   /* disable receive */
++              unsigned int loop_back          :  1;   /* transmit data loopback enable */
++        unsigned int                :  1;   /* reserved */
++              unsigned int adj_ifg            :  4;   /* adjust IFG from 96+/-56 */
++              unsigned int max_len            :  3;   /* maximum receive frame length allowed */
++              unsigned int dis_bkoff          :  1;   /* disable back-off function */
++              unsigned int dis_col            :  1;   /* disable 16 collisions abort function */
++              unsigned int sim_test           :  1;   /* speed up timers in simulation */
++              unsigned int rx_fc_en           :  1;   /* RX flow control enable */
++              unsigned int tx_fc_en           :  1;   /* TX flow control enable */
++        unsigned int rgmii_en       :  1;   /* RGMII in-band status enable */
++        unsigned int ipv4_tss_rx_en :  1;   /* IPv4 TSS RX enable */
++        unsigned int ipv6_tss_rx_en :  1;   /* IPv6 TSS RX enable */
++        unsigned int rx_tag_remove  :  1;   /* Remove Rx VLAN tag */
++              unsigned int rising_latch   :  1;
++              unsigned int inv_rx_clk : 1;    /* Inverse RX Clock */
++              unsigned int : 10;
++#endif
++      } bits;
++} GMAC_CONFIG0_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_001c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 28;
++              unsigned int buf_size           :  4;   /* per packet buffer size */
++#else
++              unsigned int buf_size           :  4;   /* per packet buffer size */
++              unsigned int                            : 28;
++#endif
++      } bits;
++} GMAC_CONFIG1_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0020
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rel_threshold      : 16;   /* flow control release threshold */
++              unsigned int set_threshold      : 16;   /* flow control set threshold */
++#else
++              unsigned int set_threshold      : 16;   /* flow control set threshold */
++              unsigned int rel_threshold      : 16;   /* flow control release threshold */
++#endif
++      } bits;
++} GMAC_CONFIG2_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0024
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 16;
++              unsigned int buf_num            : 16;   /* return buffer number from software */
++#else
++              unsigned int buf_num            : 16;   /* return buffer number from software */
++              unsigned int                            : 16;
++#endif
++      } bits;
++} GMAC_BNCR_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0028
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 16;
++              unsigned int buf_remain         : 16;   /* remaining buffer number */
++#else
++              unsigned int buf_remain         : 16;   /* remaining buffer number */
++              unsigned int                            : 16;
++#endif
++      } bits;
++} GMAC_RBNR_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_002c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 25;
++              unsigned int mii_rmii           :  2;   /* PHY interface type */
++              unsigned int phy_mode           :  1;   /* PHY interface mode in 10M-bps */
++              unsigned int duplex                     :  1;   /* duplex mode */
++              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
++              unsigned int link                       :  1;   /* link status */
++#else
++              unsigned int link                       :  1;   /* link status */
++              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
++              unsigned int duplex                     :  1;   /* duplex mode */
++              unsigned int phy_mode           :  1;   /* PHY interface mode in 10M-bps */
++              unsigned int mii_rmii           :  2;   /* PHY interface type */
++              unsigned int                            : 25;
++#endif
++      } bits;
++} GMAC_STATUS_T;
++
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_009
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 10;
++              unsigned int tx_fail            :  1;   /* Tx fail interrupt */
++              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
++              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
++              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
++              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
++              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
++              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
++              unsigned int tx_underrun        :  1;   /* GMAC Tx FIFO underrun interrupt */
++              unsigned int                            :  6;
++              unsigned int m_tx_fail          :  1;   /* Tx fail interrupt mask */
++              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
++              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
++              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
++              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
++              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
++              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
++              unsigned int m_tx_underrun      :  1;   /* GMAC Tx FIFO underrun interrupt mask */
++#else
++              unsigned int m_tx_underrun      :  1;   /* GMAC Tx FIFO underrun interrupt mask */
++              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
++              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
++              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
++              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
++              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
++              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
++              unsigned int m_tx_fail          :  1;   /* Tx fail interrupt mask */
++              unsigned int                            :  6;
++              unsigned int tx_underrun        :  1;   /* GMAC Tx FIFO underrun interrupt */
++              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
++              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
++              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
++              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
++              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
++              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
++              unsigned int tx_fail            :  1;   /* Tx fail interrupt */
++              unsigned int                            : 10;
++#endif
++      } bits;
++} GMAC_INT_MASK_T;
++
++
++/*******************************************/
++/* the register structure of GMAC DMA      */
++/*******************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff00
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                :  7;   /* reserved */
++              unsigned int s_ahb_err          :  1;   /* Slave AHB bus error */
++              unsigned int tx_err_code    :  4;   /* TxDMA error code */
++              unsigned int rx_err_code        :  4;   /* RxDMA error code */
++              unsigned int device_id          : 12;
++              unsigned int revision_id        :  4;
++#else
++              unsigned int revision_id        :  4;
++              unsigned int device_id          : 12;
++              unsigned int rx_err_code        :  4;   /* RxDMA error code */
++              unsigned int tx_err_code    :  4;   /* TxDMA error code */
++              unsigned int s_ahb_err          :  1;   /* Slave AHB bus error */
++              unsigned int                :  7;   /* reserved */
++#endif
++      } bits;
++} GMAC_DMA_DEVICE_ID_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff04
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int ts_finish          :  1;   /* finished tx interrupt */
++              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
++              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
++              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
++              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
++              unsigned int rs_finish          :  1;   /* finished rx interrupt */
++              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
++              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
++              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
++              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
++              unsigned int                    :  1;   /* Tx fail interrupt */
++              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
++              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
++              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
++              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
++              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
++              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
++              unsigned int link_change        :  1;   /* GMAC link changed Interrupt for RGMII mode */
++              unsigned int                    :  1;
++              unsigned int                    :  1;
++              unsigned int                            :  3;
++              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
++              unsigned int                    :  1;   /* Tx fail interrupt mask */
++              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
++              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
++              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
++              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
++              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
++              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
++              unsigned int m_link_change      :  1;   /* GMAC link changed Interrupt mask for RGMII mode */
++#else
++              unsigned int m_link_change      :  1;   /* GMAC link changed Interrupt mask for RGMII mode */
++              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
++              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
++              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
++              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
++              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
++              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
++              unsigned int                    :  1;   /* Tx fail interrupt mask */
++              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
++              unsigned int                            :  3;
++              unsigned int                    :  1;
++              unsigned int                    :  1;
++              unsigned int link_change        :  1;   /* GMAC link changed Interrupt for RGMII mode */
++              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
++              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
++              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
++              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
++              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
++              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
++              unsigned int                    :  1;   /* Tx fail interrupt */
++              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
++              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
++              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
++              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
++              unsigned int rs_finish          :  1;   /* finished rx interrupt */
++              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
++              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
++              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
++              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
++              unsigned int ts_finish          :  1;   /* finished tx interrupt */
++#endif
++      } bits;
++} GMAC_DMA_STATUS_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff08
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int td_start           :  1;   /* Start DMA transfer */
++              unsigned int td_continue        :  1;   /* Continue DMA operation */
++              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int                            :  1;
++              unsigned int td_prot            :  4;   /* TxDMA protection control */
++              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
++              unsigned int td_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
++              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int                            : 14;
++#else
++              unsigned int                            : 14;
++              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int td_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
++              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
++              unsigned int td_prot            :  4;   /* TxDMA protection control */
++              unsigned int                            :  1;
++              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int td_continue        :  1;   /* Continue DMA operation */
++              unsigned int td_start           :  1;   /* Start DMA transfer */
++#endif
++      } bits;
++} GMAC_TXDMA_CTRL_T;
++
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff0c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
++              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
++              unsigned int                                    :  3;
++#else
++              unsigned int                                    :  3;
++              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
++              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
++#endif
++      } bits;
++} GMAC_TXDMA_FIRST_DESC_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff10
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int                            :  1;
++              unsigned int sof_eof            :  2;
++#else
++              unsigned int sof_eof            :  2;
++              unsigned int                            :  1;
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int ndar                       : 28;   /* next descriptor address */
++#endif
++      } bits;
++} GMAC_TXDMA_CURR_DESC_T;
++
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff14
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rd_start           :  1;   /* Start DMA transfer */
++              unsigned int rd_continue        :  1;   /* Continue DMA operation */
++              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int                            :  1;
++              unsigned int rd_prot            :  4;   /* DMA protection control */
++              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
++              unsigned int rd_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
++              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int                            : 14;
++#else
++              unsigned int                            : 14;
++              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
++              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
++              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
++              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
++              unsigned int rd_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
++              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
++              unsigned int rd_prot            :  4;   /* DMA protection control */
++              unsigned int                            :  1;
++              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
++              unsigned int rd_continue        :  1;   /* Continue DMA operation */
++              unsigned int rd_start           :  1;   /* Start DMA transfer */
++#endif
++      } bits;
++} GMAC_RXDMA_CTRL_T;
++
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff18
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
++              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
++              unsigned int                                    :  3;
++#else
++              unsigned int                                    :  3;
++              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
++              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
++#endif
++      } bits;
++} GMAC_RXDMA_FIRST_DESC_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit2_ff1c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int ndar                       : 28;   /* next descriptor address */
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int                            :  1;
++              unsigned int sof_eof            :  2;
++#else
++              unsigned int sof_eof            :  2;
++              unsigned int                            :  1;
++              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
++              unsigned int ndar                       : 28;   /* next descriptor address */
++#endif
++      } bits;
++} GMAC_RXDMA_CURR_DESC_T;
++
++
++/********************************************/
++/*          Descriptor Format               */
++/********************************************/
++
++typedef struct descriptor_t
++{
++      union frame_control_t
++      {
++              unsigned int bits32;
++              struct bits_0000
++              {
++#if (BIG_ENDIAN==1)
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int csum_state : 3;    /* checksum error status */
++                      unsigned int vlan_tag   : 1;    /* 802.1q vlan tag packet */
++                      unsigned int frame_state: 3;    /* reference Rx Status1 */
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++#else
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int frame_state: 3;    /* reference Rx Status1 */
++                      unsigned int vlan_tag   : 1;    /* 802.1q vlan tag packet */
++                      unsigned int csum_state : 3;    /* checksum error status */
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++#endif
++              } bits_rx;
++
++              struct bits_0001
++              {
++#if (BIG_ENDIAN==1)
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int            : 6;
++                      unsigned int success_tx : 1;    /* successful transmitted */
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++#else
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int success_tx : 1;    /* successful transmitted */
++                      unsigned int            : 6;
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++#endif
++        } bits_tx_in;
++
++              struct bits_0002
++              {
++#if (BIG_ENDIAN==1)
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int            : 2;
++                      unsigned int udp_csum_en: 1;    /* TSS UDP checksum enable */
++                      unsigned int tcp_csum_en: 1;    /* TSS TCP checksum enable */
++                      unsigned int ipv6_tx_en : 1;    /* TSS IPv6 TX enable */
++                      unsigned int ip_csum_en : 1;    /* TSS IPv4 IP Header checksum enable */
++                      unsigned int vlan_enable: 1;    /* VLAN TIC insertion enable */
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++#else
++                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
++                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
++                      unsigned int vlan_enable: 1;    /* VLAN TIC insertion enable */
++                      unsigned int ip_csum_en : 1;    /* TSS IPv4 IP Header checksum enable */
++                      unsigned int ipv6_tx_en : 1;    /* TSS IPv6 TX enable */
++                      unsigned int tcp_csum_en: 1;    /* TSS TCP checksum enable */
++                      unsigned int udp_csum_en: 1;    /* TSS UDP checksum enable */
++                      unsigned int            : 2;
++                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
++                      unsigned int derr               : 1;    /* data error during processing this descriptor */
++                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
++#endif
++        } bits_tx_out;
++
++      } frame_ctrl;
++
++      union flag_status_t
++      {
++              unsigned int bits32;
++              struct bits_0004
++              {
++#if (BIG_ENDIAN==1)
++            unsigned int priority   : 3;    /* user priority extracted from receiving frame*/
++            unsigned int cfi        : 1;      /* cfi extracted from receiving frame*/
++                      unsigned int vlan_id    :12;    /* VLAN ID extracted from receiving frame */
++                      unsigned int frame_count:16;    /* received frame byte count,include CRC,not include VLAN TIC */
++#else
++                      unsigned int frame_count:16;    /* received frame byte count,include CRC,not include VLAN TIC */
++                      unsigned int vlan_id    :12;    /* VLAN ID extracted from receiving frame */
++            unsigned int cfi        : 1;      /* cfi extracted from receiving frame*/
++            unsigned int priority   : 3;    /* user priority extracted from receiving frame*/
++#endif
++              } bits_rx_status;
++
++              struct bits_0005
++              {
++#if (BIG_ENDIAN==1)
++            unsigned int priority   : 3;    /* user priority to transmit*/
++            unsigned int cfi        : 1;      /* cfi to transmit*/
++                      unsigned int vlan_id    :12;    /* VLAN ID to transmit */
++                      unsigned int frame_count:16;    /* total tx frame byte count */
++#else
++                      unsigned int frame_count:16;    /* total tx frame byte count */
++                      unsigned int vlan_id    :12;    /* VLAN ID to transmit */
++            unsigned int cfi        : 1;      /* cfi to transmit*/
++            unsigned int priority   : 3;    /* user priority to transmit*/
++#endif
++              } bits_tx_flag;
++      } flag_status;
++
++      unsigned int buf_adr;   /* data buffer address */
++
++      union next_desc_t
++      {
++              unsigned int next_descriptor;
++              struct bits_000c
++              {
++#if (BIG_ENDIAN==1)
++                      unsigned int ndar               :28;    /* next descriptor address */
++                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
++                      unsigned int                    : 1;
++                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
++                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
++#else
++                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
++                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
++                      unsigned int                    : 1;
++                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
++                      unsigned int ndar               :28;    /* next descriptor address */
++#endif
++              } bits;
++      } next_desc;
++} GMAC_DESCRIPTOR_T;
++
++typedef struct gmac_conf {
++      struct net_device *dev;
++      int portmap;
++      int vid;
++      int flag;     /* 1: active  0: non-active */
++} sys_gmac_conf;
++
++struct gmac_private {
++      unsigned char       *tx_bufs;   /* Tx bounce buffer region. */
++      unsigned char       *rx_bufs;
++      GMAC_DESCRIPTOR_T       *tx_desc;       /* point to virtual TX descriptor address*/
++      GMAC_DESCRIPTOR_T       *rx_desc;       /* point to virtual RX descriptor address*/
++      GMAC_DESCRIPTOR_T       *tx_cur_desc;   /* point to current TX descriptor */
++      GMAC_DESCRIPTOR_T       *rx_cur_desc;   /* point to current RX descriptor */
++      GMAC_DESCRIPTOR_T   *tx_finished_desc;
++      GMAC_DESCRIPTOR_T   *rx_finished_desc;
++      unsigned long       cur_tx;
++      unsigned int        cur_rx;     /* Index into the Rx buffer of next Rx pkt. */
++      unsigned int        tx_flag;
++      unsigned long       dirty_tx;
++      unsigned char       *tx_buf[TX_DESC_NUM];       /* Tx bounce buffers */
++      dma_addr_t          tx_desc_dma; /* physical TX descriptor address */
++      dma_addr_t          rx_desc_dma;        /* physical RX descriptor address */
++      dma_addr_t          tx_bufs_dma; /* physical TX descriptor address */
++      dma_addr_t          rx_bufs_dma; /* physical RX descriptor address */
++    struct net_device_stats  stats;
++      pid_t               thr_pid;
++      wait_queue_head_t   thr_wait;
++      struct completion   thr_exited;
++    spinlock_t          lock;
++    int                 time_to_die;
++      unsigned int            tx_desc_hdr[GMAC_PHY_IF];       /* the descriptor which sw can fill */
++      unsigned int            tx_desc_tail[GMAC_PHY_IF];      /* the descriptor which is not cleaned yet */
++};
++
++
++struct reg_ioctl_data {
++    unsigned int    reg_addr;   /* the register address */
++    unsigned int    val_in;     /* data write to the register */
++    unsigned int    val_out;    /* data read from the register */
++};
++
++#ifdef CONFIG_SL2312_MPAGE
++typedef struct tx_data_t {
++      int     freeable; // 1 when it's skb. it can be freed in tx interrupt handler
++      struct sk_buff* skb; // skb
++      int     desc_in_use; // 1 when the desc is in use. 0 when desc is available.
++      long end_seq; // to find out packets are in seq.
++      // so this value is the seq of next packet.
++} tx_data;
++#endif
++
++/*************************************************************
++ *         Global Variable
++ *************************************************************/
++struct semaphore        sem_gmac;   /* semaphore for share pins issue */
++
++/*************************************************************
++ *        Static Global Variable
++ *************************************************************/
++// static unsigned int     MAC_BASE_ADDR = GMAC0_BASE;
++static unsigned int     gmac_base_addr[GMAC_PHY_IF] = {GMAC0_BASE,GMAC1_BASE};
++static unsigned int     gmac_irq[GMAC_PHY_IF] = {IRQ_GMAC0,IRQ_GMAC1};
++static struct net_device *gmac_dev[GMAC_PHY_IF];
++
++static unsigned int     FLAG_SWITCH=0;        /* if 1-->switch chip presented. if 0-->switch chip unpresented */
++static unsigned int     flow_control_enable[GMAC_PHY_IF] = {1,1};
++static unsigned int     pre_phy_status[GMAC_PHY_IF] = {LINK_DOWN,LINK_DOWN};
++static unsigned int     tx_desc_virtual_base[GMAC_PHY_IF];
++static unsigned int     rx_desc_virtual_base[GMAC_PHY_IF];
++static unsigned int     full_duplex = 1;
++static unsigned int     speed = 1;
++#ifdef CONFIG_SL2312_MPAGE
++static tx_data                    tx_skb[GMAC_PHY_IF][TX_DESC_NUM];
++#else
++static struct sk_buff   *tx_skb[GMAC_PHY_IF][TX_DESC_NUM];
++#endif
++static struct sk_buff   *rx_skb[GMAC_PHY_IF][RX_DESC_NUM];
++static unsigned int     tx_desc_start_adr[GMAC_PHY_IF];
++static unsigned int     rx_desc_start_adr[GMAC_PHY_IF];
++static unsigned char    eth0_mac[6]= {0x00,0x50,0xc2,0x2b,0xd3,0x25};
++static unsigned char    eth1_mac[6]= {0x00,0x50,0xc2,0x2b,0xdf,0xfe};
++static unsigned int     next_tick = 3 * HZ;
++
++static unsigned int     phy_addr[GMAC_PHY_IF] = {0x01,0x02};  /* define PHY address */
++
++DECLARE_WAIT_QUEUE_HEAD(gmac_queue);
++//static      wait_queue_t    wait;
++
++struct gmac_conf VLAN_conf[] = {
++#ifdef CONFIG_ADM_6999
++      { (struct net_device *)0,0x7F,1 },
++      { (struct net_device *)0,0x80,2 }
++#endif
++#ifdef CONFIG_ADM_6996
++      { (struct net_device *)0,0x0F,1 },
++      { (struct net_device *)0,0x10,2 }
++#endif
++};
++
++#define NUM_VLAN_IF   (sizeof(VLAN_conf)/sizeof(struct gmac_conf))
++
++
++/************************************************/
++/*            GMAC function declare             */
++/************************************************/
++
++unsigned int mii_read(unsigned char phyad,unsigned char regad);
++void mii_write(unsigned char phyad,unsigned char regad,unsigned int value);
++static void gmac_set_phy_status(struct net_device *dev);
++static void gmac_get_phy_status(struct net_device *dev);
++static int gmac_phy_thread (void *data);
++static int gmac_set_mac_address(struct net_device *dev, void *addr);
++static void gmac_tx_timeout(struct net_device *dev);
++static void gmac_tx_packet_complete(struct net_device *dev);
++static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev);
++static void gmac_set_rx_mode(struct net_device *dev);
++static void gmac_rx_packet(struct net_device *dev);
++static int gmac_open (struct net_device *dev);
++static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
++
++static unsigned int gmac_get_dev_index(struct net_device *dev);
++static unsigned int gmac_select_interface(struct net_device *dev);
++
++#ifdef CONFIG_SL2312_MPAGE
++int printk_all(int dev_index, struct gmac_private* tp);
++#endif
++
++/****************************************/
++/*    SPI Function Declare            */
++/****************************************/
++void SPI_write(unsigned char addr,unsigned int value);
++unsigned int SPI_read(unsigned char table,unsigned char addr);
++void SPI_write_bit(char bit_EEDO);
++unsigned int SPI_read_bit(void);
++void SPI_default(void);
++void SPI_reset(unsigned char rstype,unsigned char port_cnt);
++void SPI_pre_st(void);
++void SPI_CS_enable(unsigned char enable);
++void SPI_Set_VLAN(unsigned char LAN,unsigned int port_mask);
++void SPI_Set_tag(unsigned int port,unsigned tag);
++void SPI_Set_PVID(unsigned int PVID,unsigned int port_mask);
++unsigned int SPI_Get_PVID(unsigned int port);
++void SPI_mac_lock(unsigned int port, unsigned char lock);
++void SPI_get_port_state(unsigned int port);
++void SPI_port_enable(unsigned int port,unsigned char enable);
++unsigned int SPI_get_identifier(void);
++void SPI_get_status(unsigned int port);
++
++/****************************************/
++/*    VLAN Function Declare                   */
++/****************************************/
++int getVLANfromdev (struct net_device *dev );
++struct net_device * getdevfromVLAN( int VID);
++
++
++
++/************************************************/
++/*                 function body                */
++/************************************************/
++#if 0
++void hw_memcpy(void *to,const void *from,unsigned long n)
++{
++    writel(from,SL2312_DRAM_CTRL_BASE+0x20);  /* set source address */
++    writel(to,SL2312_DRAM_CTRL_BASE+0x24);    /* set destination address */
++    writel(n,SL2312_DRAM_CTRL_BASE+0x28);     /* set byte count */
++    writel(0x00000001,SL2312_DRAM_CTRL_BASE+0x2c);
++    while (readl(SL2312_DRAM_CTRL_BASE+0x2c));
++}
++#endif
++
++static unsigned int gmac_read_reg(unsigned int addr)
++{
++    unsigned int    reg_val;
++//    unsigned int    flags;
++//    spinlock_t     lock;
++
++//    spin_lock_irqsave(&lock, flags);
++    reg_val = readl(addr);    // Gary Chen
++//    spin_unlock_irqrestore(&lock, flags);
++      return (reg_val);
++}
++
++static void gmac_write_reg(unsigned int addr,unsigned int data,unsigned int bit_mask)
++{
++      unsigned int    reg_val;
++    //unsigned int    *addr;
++//    unsigned int    flags;
++//    spinlock_t     lock;
++
++//    spin_lock_irqsave(&lock, flags);
++      reg_val = ( gmac_read_reg(addr) & (~bit_mask) ) | (data & bit_mask);
++    writel(reg_val,addr);
++//    spin_unlock_irqrestore(&lock, flags);
++      return;
++}
++
++
++static void gmac_sw_reset(struct net_device *dev)
++{
++    unsigned int    index;
++    unsigned int    reg_val;
++
++    index = gmac_get_dev_index(dev);
++    if (index==0)
++        reg_val = readl(GMAC_GLOBAL_BASE_ADDR+0x0c) | 0x00000020;   /* GMAC0 S/W reset */
++    else
++        reg_val = readl(GMAC_GLOBAL_BASE_ADDR+0x0c) | 0x00000040;   /* GMAC1 S/W reset */
++
++    writel(reg_val,GMAC_GLOBAL_BASE_ADDR+0x0c);
++    return;
++}
++
++static void gmac_get_mac_address(void)
++{
++#ifdef CONFIG_MTD
++      extern int get_vlaninfo(vlaninfo* vlan);
++    static vlaninfo    vlan[2];
++
++    if (get_vlaninfo(&vlan[0]))
++    {
++        memcpy(eth0_mac,vlan[0].mac,6);
++        VLAN_conf[0].vid = vlan[0].vlanid;
++        VLAN_conf[0].portmap = vlan[0].vlanmap;
++        memcpy(eth1_mac,vlan[1].mac,6);
++        VLAN_conf[1].vid = vlan[1].vlanid;
++        VLAN_conf[1].portmap = vlan[1].vlanmap;
++    }
++#else
++    unsigned int reg_val;
++
++    reg_val = readl(IO_ADDRESS(SL2312_SECURITY_BASE)+0xac);
++    eth0_mac[4] = (reg_val & 0xff00) >> 8;
++    eth0_mac[5] = reg_val & 0x00ff;
++    reg_val = readl(IO_ADDRESS(SL2312_SECURITY_BASE)+0xac);
++    eth1_mac[4] = (reg_val & 0xff00) >> 8;
++    eth1_mac[5] = reg_val & 0x00ff;
++#endif
++    return;
++}
++
++static unsigned int gmac_get_dev_index(struct net_device *dev)
++{
++    unsigned int    i;
++
++    /* get device index number */
++    for (i=0;i<GMAC_PHY_IF;i++)
++    {
++        if (gmac_dev[i]==dev)
++        {
++            return(i);
++        }
++    }
++    return (0xff);
++}
++
++static unsigned int gmac_select_interface(struct net_device *dev)
++{
++    unsigned int    index;
++
++    index = gmac_get_dev_index(dev);
++    // MAC_BASE_ADDR = gmac_base_addr[index]; // Gary Chen
++    return (index);
++}
++
++
++static void gmac_dump_register(struct net_device *dev)
++{
++#if 0
++    unsigned int   i,val,index;
++
++    index = gmac_select_interface(dev);
++
++    printk("========== GMAC%d ==========\n",index);
++    for (i=0;i<=0x7c;i=i+4)
++    {
++        val = gmac_read_reg(gmac_base_addr[index] + i);
++        printk("offset = %08x   value = %08x\n",i,val);
++    }
++    for (i=0xff00;i<=0xff7c;i=i+4)
++    {
++        val = gmac_read_reg(gmac_base_addr[index] + i);
++        printk("offset = %08x   value = %08x\n",i,val);
++    }
++#endif
++}
++
++static int gmac_init_chip(struct net_device *dev)
++{
++      GMAC_RBNR_T             rbnr_val,rbnr_mask;
++      GMAC_CONFIG2_T  config2_val;
++      GMAC_CONFIG0_T  config0,config0_mask;
++      GMAC_CONFIG1_T  config1;
++      struct sockaddr sock;
++      unsigned int    status;
++      unsigned int    phy_mode;
++      unsigned int    index;
++
++    index = gmac_get_dev_index(dev);
++
++    /* set GMAC RMII mode */
++    if (index==0)
++        phy_mode = 0;   /* 0->MII 1->GMII 2->RGMII(10/100) 3->RGMII(1000) */
++    else
++        phy_mode = 2;   /* 0->MII 1->GMII 2->RGMII(10/100) 3->RGMII(1000) */
++
++    /* set PHY operation mode */
++    status = (phy_mode<<5) | 0x11 | (full_duplex<<3) | (speed<<1);
++    gmac_write_reg(gmac_base_addr[index] + GMAC_STATUS,status ,0x0000007f);
++
++      /* set station MAC address1 and address2 */
++      if (index==0)
++          memcpy(&sock.sa_data[0],&eth0_mac[0],6);
++    else
++          memcpy(&sock.sa_data[0],&eth1_mac[0],6);
++    gmac_set_mac_address(dev,(void *)&sock);
++
++    /* set RX_FLTR register to receive all multicast packet */
++    gmac_write_reg(gmac_base_addr[index] + GMAC_RX_FLTR,0x0000001F,0x0000001f);
++    //gmac_write_reg(gmac_base_addr[index] + GMAC_RX_FLTR,0x00000007,0x0000001f);
++
++      /* set per packet buffer size */
++      config1.bits32 = 0;
++    config1.bits.buf_size = 11; /* buffer size = 2048-byte */
++    gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG1,config1.bits32,0x0000000f);
++
++      /* set flow control threshold */
++      config2_val.bits32 = 0;
++      config2_val.bits.set_threshold = RX_DESC_NUM/4;
++      config2_val.bits.rel_threshold = RX_DESC_NUM*3/4;
++      gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG2,config2_val.bits32,0xffffffff);
++
++      /* init remaining buffer number register */
++      rbnr_val.bits32 = 0;
++      rbnr_val.bits.buf_remain = RX_DESC_NUM;
++      rbnr_mask.bits32 = 0;
++      rbnr_mask.bits.buf_remain = 0xffff;
++      gmac_write_reg(gmac_base_addr[index] + GMAC_RBNR,rbnr_val.bits32,rbnr_mask.bits32);
++
++    /* disable TX/RX and disable internal loop back */
++    config0.bits32 = 0;
++    config0_mask.bits32 = 0;
++    config0.bits.max_len = 2;
++    if (flow_control_enable[index]==1)
++    {
++        config0.bits.tx_fc_en = 1; /* enable tx flow control */
++        config0.bits.rx_fc_en = 1; /* enable rx flow control */
++        printk("Enable MAC Flow Control...\n");
++    }
++    else
++    {
++        config0.bits.tx_fc_en = 0; /* disable tx flow control */
++        config0.bits.rx_fc_en = 0; /* disable rx flow control */
++        printk("Disable MAC Flow Control...\n");
++    }
++    config0.bits.dis_rx = 1;  /* disable rx */
++    config0.bits.dis_tx = 1;  /* disable tx */
++    config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
++      config0.bits.inv_rx_clk = 0;
++      config0.bits.rising_latch = 1;
++      config0.bits.ipv4_tss_rx_en = 1;  /* enable H/W to check ip checksum */
++      config0.bits.ipv6_tss_rx_en = 1;  /* enable H/W to check ip checksum */
++
++    config0_mask.bits.max_len = 7;
++    config0_mask.bits.tx_fc_en = 1;
++    config0_mask.bits.rx_fc_en = 1;
++    config0_mask.bits.dis_rx = 1;
++    config0_mask.bits.dis_tx = 1;
++    config0_mask.bits.loop_back = 1;
++    config0_mask.bits.inv_rx_clk = 1;
++      config0_mask.bits.rising_latch = 1;
++      config0_mask.bits.ipv4_tss_rx_en = 1;
++      config0_mask.bits.ipv6_tss_rx_en = 1;
++    gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++
++      return (0);
++}
++
++static void gmac_enable_tx_rx(struct net_device *dev)
++{
++      GMAC_CONFIG0_T  config0,config0_mask;
++      int                             dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++    /* enable TX/RX */
++    config0.bits32 = 0;
++    config0_mask.bits32 = 0;
++    config0.bits.dis_rx = 0;  /* enable rx */
++    config0.bits.dis_tx = 0;  /* enable tx */
++    config0_mask.bits.dis_rx = 1;
++    config0_mask.bits.dis_tx = 1;
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++}
++
++static void gmac_disable_tx_rx(struct net_device *dev)
++{
++      GMAC_CONFIG0_T  config0,config0_mask;
++      int                             dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++    /* enable TX/RX */
++    config0.bits32 = 0;
++    config0_mask.bits32 = 0;
++    config0.bits.dis_rx = 1;  /* disable rx */
++    config0.bits.dis_tx = 1;  /* disable tx */
++    config0_mask.bits.dis_rx = 1;
++    config0_mask.bits.dis_tx = 1;
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++}
++
++#ifdef CONFIG_SL_NAPI
++static int gmac_rx_poll_ga(struct net_device *dev, int *budget)
++{
++      struct gmac_private *tp = dev->priv;
++      struct sk_buff          *skb;
++    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
++      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
++    GMAC_DESCRIPTOR_T   *rx_desc;
++      unsigned int            pkt_size;
++      unsigned int        desc_count;
++    unsigned int        vid;
++//    unsigned int        priority;
++      unsigned int        own;
++      unsigned int        good_frame = 0;
++      unsigned int        index;
++      unsigned int        dev_index;
++      int                 work = 0;
++      int                 work_done = 0;
++      int                 quota = min(dev->quota, *budget);
++
++    dev_index = gmac_select_interface(dev);
++
++      for (;;)
++      {
++        own = tp->rx_cur_desc->frame_ctrl.bits32 >> 31;
++        if (own == CPU) /* check owner bit */
++        {
++              rx_desc = tp->rx_cur_desc;
++#if (GMAC_DEBUG==1)
++              /* check error interrupt */
++              if ( (rx_desc->frame_ctrl.bits_rx.derr==1)||(rx_desc->frame_ctrl.bits_rx.perr==1) )
++              {
++              printk("%s::Rx Descriptor Processing Error !!!\n",__func__);
++          }
++#endif
++          /* get frame information from the first descriptor of the frame */
++              pkt_size = rx_desc->flag_status.bits_rx_status.frame_count - 4;  /*total byte count in a frame*/
++#if (GMAC_DEBUG==1)
++            priority = rx_desc->flag_status.bits_rx_status.priority;    /* 802.1p priority */
++#endif
++            vid = rx_desc->flag_status.bits_rx_status.vlan_id;          /* 802.1q vlan id */
++            if (vid == 0)
++            {
++                vid = 1;    /* default vlan */
++            }
++              desc_count = rx_desc->frame_ctrl.bits_rx.desc_count; /* get descriptor count per frame */
++
++              if (rx_desc->frame_ctrl.bits_rx.frame_state == 0x000) /* good frame */
++              {
++                      tp->stats.rx_bytes += pkt_size;
++                      tp->stats.rx_packets++;
++                      good_frame = 1;
++              }
++              else
++              {
++                      tp->stats.rx_errors++;
++                      good_frame = 0;
++                      printk("RX status: 0x%x\n",rx_desc->frame_ctrl.bits_rx.frame_state);
++              }
++      }
++      else
++      {
++          work_done = 1;
++          break;  /* Rx process is completed */
++      }
++
++        if (good_frame == 1)
++        {
++            /* get rx skb buffer index */
++            index = ((unsigned int)tp->rx_cur_desc - rx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++            if (rx_skb[dev_index][index])
++            {
++                skb_reserve (rx_skb[dev_index][index], 2);    /* 16 byte align the IP fields. */
++                rx_skb[dev_index][index]->dev = dev;
++                rx_skb[dev_index][index]->ip_summed = CHECKSUM_UNNECESSARY;
++                          skb_put(rx_skb[dev_index][index],pkt_size);
++                          rx_skb[dev_index][index]->protocol = eth_type_trans(rx_skb[dev_index][index],dev); /* set skb protocol */
++                          netif_rx(rx_skb[dev_index][index]);  /* socket rx */
++                          dev->last_rx = jiffies;
++
++                          /* allocate rx skb buffer */
++                if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
++                {
++                    printk("%s::skb buffer allocation fail !\n",__func__);
++                }
++                rx_skb[dev_index][index] = skb;
++                tp->rx_cur_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
++            }
++            else
++            {
++                printk("%s::rx skb index error !\n",__func__);
++            }
++        }
++
++          tp->rx_cur_desc->frame_ctrl.bits_rx.own = DMA; /* release rx descriptor to DMA */
++        /* point to next rx descriptor */
++        tp->rx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->rx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+rx_desc_virtual_base[dev_index]);
++
++        /* release buffer to Remaining Buffer Number Register */
++        if (flow_control_enable[dev_index] ==1)
++        {
++//            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_BNCR,desc_count,0x0000ffff);
++            writel(desc_count,(unsigned int *)(gmac_base_addr[dev_index] + GMAC_BNCR));
++        }
++
++              if (work++ >= quota )
++              {
++                      break;
++              }
++    }
++
++    /* if RX DMA process is stoped , restart it */
++      rxdma_busy.bits.rd_first_des_ptr = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC);
++      if (rxdma_busy.bits.rd_busy == 0)
++      {
++          rxdma_ctrl.bits32 = 0;
++      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
++          rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
++          rxdma_ctrl_mask.bits32 = 0;
++      rxdma_ctrl_mask.bits.rd_start = 1;
++          rxdma_ctrl_mask.bits.rd_continue = 1;
++          gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
++    }
++
++      dev->quota -= work;
++      *budget -= work;
++      if (work_done==1)
++      {
++          /* Receive descriptor is empty now */
++        netif_rx_complete(dev);
++        /* enable receive interrupt */
++        gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,0x0007c000,0x0007c000);   /* enable rx interrupt */
++        return 0;
++    }
++    else
++    {
++        return -1;
++    }
++}
++
++static int gmac_rx_poll_gb(struct net_device *dev, int *budget)
++{
++      struct gmac_private *tp = dev->priv;
++      struct sk_buff          *skb;
++    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
++      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
++    GMAC_DESCRIPTOR_T   *rx_desc;
++      unsigned int            pkt_size;
++      unsigned int        desc_count;
++    unsigned int        vid;
++//    unsigned int        priority;
++      unsigned int        own;
++      unsigned int        good_frame = 0;
++      unsigned int        index;
++      unsigned int        dev_index;
++      int                 work = 0;
++      int                 work_done = 0;
++      int                 quota = min(dev->quota, *budget);
++
++    dev_index = gmac_select_interface(dev);
++
++      for (;;)
++      {
++        own = tp->rx_cur_desc->frame_ctrl.bits32 >> 31;
++        if (own == CPU) /* check owner bit */
++        {
++              rx_desc = tp->rx_cur_desc;
++#if (GMAC_DEBUG==1)
++              /* check error interrupt */
++              if ( (rx_desc->frame_ctrl.bits_rx.derr==1)||(rx_desc->frame_ctrl.bits_rx.perr==1) )
++              {
++              printk("%s::Rx Descriptor Processing Error !!!\n",__func__);
++          }
++#endif
++          /* get frame information from the first descriptor of the frame */
++              pkt_size = rx_desc->flag_status.bits_rx_status.frame_count - 4;  /*total byte count in a frame*/
++#if (GMAC_DEBUG==1)
++            priority = rx_desc->flag_status.bits_rx_status.priority;    /* 802.1p priority */
++#endif
++            vid = rx_desc->flag_status.bits_rx_status.vlan_id;          /* 802.1q vlan id */
++            if (vid == 0)
++            {
++                vid = 1;    /* default vlan */
++            }
++              desc_count = rx_desc->frame_ctrl.bits_rx.desc_count; /* get descriptor count per frame */
++
++              if (rx_desc->frame_ctrl.bits_rx.frame_state == 0x000) /* good frame */
++              {
++                      tp->stats.rx_bytes += pkt_size;
++                      tp->stats.rx_packets++;
++                      good_frame = 1;
++              }
++              else
++              {
++                      tp->stats.rx_errors++;
++                      good_frame = 0;
++                      printk("RX status: 0x%x\n",rx_desc->frame_ctrl.bits_rx.frame_state);
++              }
++      }
++      else
++      {
++          work_done = 1;
++          break;  /* Rx process is completed */
++      }
++
++        if (good_frame == 1)
++        {
++            /* get rx skb buffer index */
++            index = ((unsigned int)tp->rx_cur_desc - rx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++            if (rx_skb[dev_index][index])
++            {
++                skb_reserve (rx_skb[dev_index][index], 2);    /* 16 byte align the IP fields. */
++                rx_skb[dev_index][index]->dev = dev;
++                rx_skb[dev_index][index]->ip_summed = CHECKSUM_UNNECESSARY;
++                          skb_put(rx_skb[dev_index][index],pkt_size);
++                          rx_skb[dev_index][index]->protocol = eth_type_trans(rx_skb[dev_index][index],dev); /* set skb protocol */
++                          netif_rx(rx_skb[dev_index][index]);  /* socket rx */
++                          dev->last_rx = jiffies;
++
++                          /* allocate rx skb buffer */
++                if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
++                {
++                    printk("%s::skb buffer allocation fail !\n",__func__);
++                }
++                rx_skb[dev_index][index] = skb;
++                tp->rx_cur_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
++            }
++            else
++            {
++                printk("%s::rx skb index error !\n",__func__);
++            }
++        }
++
++          tp->rx_cur_desc->frame_ctrl.bits_rx.own = DMA; /* release rx descriptor to DMA */
++        /* point to next rx descriptor */
++        tp->rx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->rx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+rx_desc_virtual_base[dev_index]);
++
++        /* release buffer to Remaining Buffer Number Register */
++        if (flow_control_enable[dev_index] ==1)
++        {
++//            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_BNCR,desc_count,0x0000ffff);
++            writel(desc_count,(unsigned int *)(gmac_base_addr[dev_index] + GMAC_BNCR));
++        }
++
++              if (work++ >= quota )
++              {
++                      break;
++              }
++    }
++
++    /* if RX DMA process is stoped , restart it */
++      rxdma_busy.bits.rd_first_des_ptr = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC);
++      if (rxdma_busy.bits.rd_busy == 0)
++      {
++          rxdma_ctrl.bits32 = 0;
++      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
++          rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
++          rxdma_ctrl_mask.bits32 = 0;
++      rxdma_ctrl_mask.bits.rd_start = 1;
++          rxdma_ctrl_mask.bits.rd_continue = 1;
++          gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
++    }
++
++      dev->quota -= work;
++      *budget -= work;
++      if (work_done==1)
++      {
++          /* Receive descriptor is empty now */
++        netif_rx_complete(dev);
++        /* enable receive interrupt */
++        gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,0x0007c000,0x0007c000);   /* enable rx interrupt */
++        return 0;
++    }
++    else
++    {
++        return -1;
++    }
++}
++
++#endif
++
++static void gmac_rx_packet(struct net_device *dev)
++{
++      struct gmac_private *tp = dev->priv;
++      struct sk_buff          *skb;
++    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
++      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
++    GMAC_DESCRIPTOR_T   *rx_desc;
++      unsigned int            pkt_size;
++      unsigned int        desc_count;
++    unsigned int        vid;
++//    unsigned int        priority;
++      unsigned int        own;
++      unsigned int        good_frame = 0;
++      unsigned int        i,index;
++      unsigned int        dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++      for (i=0;i<256;i++)
++      {
++        own = tp->rx_cur_desc->frame_ctrl.bits32 >> 31;
++        if (own == CPU) /* check owner bit */
++        {
++              rx_desc = tp->rx_cur_desc;
++#if (GMAC_DEBUG==1)
++              /* check error interrupt */
++              if ( (rx_desc->frame_ctrl.bits_rx.derr==1)||(rx_desc->frame_ctrl.bits_rx.perr==1) )
++              {
++              printk("%s::Rx Descriptor Processing Error !!!\n",__func__);
++          }
++#endif
++          /* get frame information from the first descriptor of the frame */
++              pkt_size = rx_desc->flag_status.bits_rx_status.frame_count - 4;  /*total byte count in a frame*/
++#if (GMAC_DEBUG==1)
++            priority = rx_desc->flag_status.bits_rx_status.priority;    /* 802.1p priority */
++#endif
++            vid = rx_desc->flag_status.bits_rx_status.vlan_id;          /* 802.1q vlan id */
++            if (vid == 0)
++            {
++                vid = 1;    /* default vlan */
++            }
++              desc_count = rx_desc->frame_ctrl.bits_rx.desc_count; /* get descriptor count per frame */
++
++              if (rx_desc->frame_ctrl.bits_rx.frame_state == 0x000) /* good frame */
++              {
++                      tp->stats.rx_bytes += pkt_size;
++                      tp->stats.rx_packets++;
++                      good_frame = 1;
++              }
++              else
++              {
++                      tp->stats.rx_errors++;
++                      good_frame = 0;
++                      printk("RX status: 0x%x\n",rx_desc->frame_ctrl.bits_rx.frame_state);
++              }
++      }
++      else
++      {
++          break;  /* Rx process is completed */
++      }
++
++        if (good_frame == 1)
++        {
++            /* get rx skb buffer index */
++            index = ((unsigned int)tp->rx_cur_desc - rx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++            if (rx_skb[dev_index][index])
++            {
++                skb_reserve (rx_skb[dev_index][index], 2);    /* 16 byte align the IP fields. */
++                rx_skb[dev_index][index]->dev = dev;
++                rx_skb[dev_index][index]->ip_summed = CHECKSUM_UNNECESSARY;
++                          skb_put(rx_skb[dev_index][index],pkt_size);
++                          rx_skb[dev_index][index]->protocol = eth_type_trans(rx_skb[dev_index][index],dev); /* set skb protocol */
++                          netif_rx(rx_skb[dev_index][index]);  /* socket rx */
++                          dev->last_rx = jiffies;
++
++                          /* allocate rx skb buffer */
++                if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
++                {
++                    printk("%s::skb buffer allocation fail !\n",__func__);
++                }
++                rx_skb[dev_index][index] = skb;
++                tp->rx_cur_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
++            }
++            else
++            {
++                printk("%s::rx skb index error !\n",__func__);
++            }
++        }
++
++          tp->rx_cur_desc->frame_ctrl.bits_rx.own = DMA; /* release rx descriptor to DMA */
++        /* point to next rx descriptor */
++        tp->rx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->rx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+rx_desc_virtual_base[dev_index]);
++
++        /* release buffer to Remaining Buffer Number Register */
++        if (flow_control_enable[dev_index] ==1)
++        {
++            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_BNCR,desc_count,0x0000ffff);
++        }
++    }
++
++    /* if RX DMA process is stoped , restart it */
++      rxdma_busy.bits.rd_first_des_ptr = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC);
++      if (rxdma_busy.bits.rd_busy == 0)
++      {
++          rxdma_ctrl.bits32 = 0;
++      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
++          rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
++          rxdma_ctrl_mask.bits32 = 0;
++      rxdma_ctrl_mask.bits.rd_start = 1;
++          rxdma_ctrl_mask.bits.rd_continue = 1;
++          gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
++    }
++}
++
++#ifdef CONFIG_SL2312_MPAGE
++static inline void free_tx_buf(int dev_index, int desc_index)
++{
++      if (tx_skb[dev_index][desc_index].freeable &&
++          tx_skb[dev_index][desc_index].skb) {
++              struct sk_buff* skb = tx_skb[dev_index][desc_index].skb;
++              //printk("free_skb %x, len %d\n", skb, skb->len);
++#ifdef CONFIG_TXINT_DISABLE
++              dev_kfree_skb(skb);
++#else
++              dev_kfree_skb_irq(skb);
++#endif
++              tx_skb[dev_index][desc_index].skb = 0;
++      }
++}
++
++#ifdef CONFIG_TXINT_DISABLE
++static void gmac_tx_packet_complete(struct net_device *dev)
++{
++      struct gmac_private     *tp = dev->priv;
++    GMAC_DESCRIPTOR_T     *tx_hw_complete_desc, *next_desc;
++    unsigned int desc_cnt=0;
++    unsigned int i,index,dev_index;
++    unsigned int tx_current_descriptor = 0;
++      // int own_dma = 0;
++
++    dev_index = gmac_select_interface(dev);
++
++      index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++      if (tx_skb[dev_index][index].desc_in_use && tp->tx_finished_desc->frame_ctrl.bits_tx_in.own == CPU) {
++              free_tx_buf(dev_index, index);
++              tx_skb[dev_index][index].desc_in_use = 0;
++      }
++      next_desc = (GMAC_DESCRIPTOR_T*)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
++
++      for (;;) {
++              tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
++              if (next_desc == tx_hw_complete_desc)
++                      break;
++              if (next_desc->frame_ctrl.bits_tx_in.own == CPU) {
++                      if (next_desc->frame_ctrl.bits_tx_in.success_tx == 1) {
++                              tp->stats.tx_bytes += next_desc->flag_status.bits_tx_flag.frame_count;
++                              tp->stats.tx_packets ++;
++                      } else {
++                              tp->stats.tx_errors++;
++                      }
++                      desc_cnt = next_desc->frame_ctrl.bits_tx_in.desc_count;
++                      for (i=1; i<desc_cnt; i++) {
++                              /* get tx skb buffer index */
++                              index = ((unsigned int)next_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++                              next_desc->frame_ctrl.bits_tx_in.own = CPU;
++                              free_tx_buf(dev_index, index);
++                              tx_skb[dev_index][index].desc_in_use = 0;
++                              tp->tx_desc_tail[dev_index] = (tp->tx_desc_tail[dev_index] +1) & (TX_DESC_NUM-1);
++                              /* release Tx descriptor to CPU */
++                              next_desc = (GMAC_DESCRIPTOR_T *)((next_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
++                      }
++                      /* get tx skb buffer index */
++                      index = ((unsigned int)next_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++                      /* free skb buffer */
++                      next_desc->frame_ctrl.bits_tx_in.own = CPU;
++                      free_tx_buf(dev_index, index);
++                      tx_skb[dev_index][index].desc_in_use = 0;
++                      tp->tx_desc_tail[dev_index] = (tp->tx_desc_tail[dev_index] +1) & (TX_DESC_NUM-1);
++                      tp->tx_finished_desc = next_desc;
++//                    printk("finish tx_desc index %d\n", index);
++                      next_desc = (GMAC_DESCRIPTOR_T *)((next_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
++              }
++              else
++                      break;
++      }
++      if (netif_queue_stopped(dev))
++      {
++              netif_wake_queue(dev);
++      }
++
++}
++#else
++static void gmac_tx_packet_complete(struct net_device *dev)
++{
++      struct gmac_private     *tp = dev->priv;
++      GMAC_DESCRIPTOR_T           *tx_hw_complete_desc;
++      unsigned int desc_cnt=0;
++      unsigned int i,index,dev_index;
++      unsigned int tx_current_descriptor = 0;
++      // int own_dma = 0;
++
++      dev_index = gmac_select_interface(dev);
++
++      index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++
++      /* check tx status and accumulate tx statistics */
++      for (;;)
++      {
++
++        for (i=0;i<1000;i++)
++        {
++            tx_current_descriptor = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC);
++            if ( ((tx_current_descriptor & 0x00000003)==0x00000003) ||  /* only one descriptor */
++                 ((tx_current_descriptor & 0x00000003)==0x00000001) )   /* the last descriptor */
++            {
++                break;
++            }
++            udelay(1);
++        }
++        if (i==1000)
++        {
++//            gmac_dump_register(dev);
++//            printk("%s: tx current descriptor = %x \n",__func__,tx_current_descriptor);
++//            printk_all(dev_index, tp);
++            continue;
++        }
++
++          /* get tx H/W completed descriptor virtual address */
++      tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((tx_current_descriptor & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
++//            tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
++          if (tp->tx_finished_desc == tx_hw_complete_desc ) // ||
++                  //tx_skb[dev_index][index].desc_in_use )   /* complete tx processing */
++              {
++                      break;
++              }
++
++        for (;;)
++        {
++              if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.own == CPU)
++              {
++    #if (GMAC_DEBUG==1)
++                      if ( (tp->tx_finished_desc->frame_ctrl.bits_tx_in.derr) ||
++                         (tp->tx_finished_desc->frame_ctrl.bits_tx_in.perr) )
++                      {
++                              printk("%s::Descriptor Processing Error !!!\n",__func__);
++                      }
++    #endif
++                      if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.success_tx == 1)
++                      {
++                              tp->stats.tx_bytes += tp->tx_finished_desc->flag_status.bits_tx_flag.frame_count;
++                              tp->stats.tx_packets ++;
++                      }
++                      else
++                      {
++                              tp->stats.tx_errors++;
++                      }
++                      desc_cnt = tp->tx_finished_desc->frame_ctrl.bits_tx_in.desc_count;
++                      for (i=1; i<desc_cnt; i++)  /* multi-descriptor in one packet */
++                      {
++                              /* get tx skb buffer index */
++                              index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++                              tp->tx_finished_desc->frame_ctrl.bits_tx_in.own = CPU;
++                              free_tx_buf(dev_index, index);
++                              tx_skb[dev_index][index].desc_in_use = 0;
++                              /* release Tx descriptor to CPU */
++                              tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
++                      }
++                      /* get tx skb buffer index */
++                      index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++                      /* free skb buffer */
++                      tp->tx_finished_desc->frame_ctrl.bits_tx_in.own = CPU;
++                      free_tx_buf(dev_index, index);
++                      tx_skb[dev_index][index].desc_in_use = 0;
++                      tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
++
++                  if (tp->tx_finished_desc == tx_hw_complete_desc )
++                      {
++                              break;
++                      }
++            }
++              else
++              {
++                      break;
++                      }
++              }
++      }
++
++      if (netif_queue_stopped(dev))
++      {
++              netif_wake_queue(dev);
++      }
++
++}
++#endif
++#else
++
++static void gmac_tx_packet_complete(struct net_device *dev)
++{
++      struct gmac_private     *tp = dev->priv;
++    GMAC_DESCRIPTOR_T     *tx_hw_complete_desc;
++    unsigned int desc_cnt=0;
++    unsigned int i,index,dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++      /* get tx H/W completed descriptor virtual address */
++      tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
++      /* check tx status and accumulate tx statistics */
++    for (;;)
++    {
++        if (tp->tx_finished_desc == tx_hw_complete_desc)   /* complete tx processing */
++        {
++            break;
++        }
++      if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.own == CPU)
++      {
++#if (GMAC_DEBUG==1)
++          if ( (tp->tx_finished_desc->frame_ctrl.bits_tx_in.derr) ||
++               (tp->tx_finished_desc->frame_ctrl.bits_tx_in.perr) )
++          {
++              printk("%s::Descriptor Processing Error !!!\n",__func__);
++          }
++#endif
++            if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.success_tx == 1)
++            {
++                tp->stats.tx_bytes += tp->tx_finished_desc->flag_status.bits_tx_flag.frame_count;
++                tp->stats.tx_packets ++;
++            }
++            else
++            {
++                tp->stats.tx_errors++;
++            }
++            desc_cnt = tp->tx_finished_desc->frame_ctrl.bits_tx_in.desc_count;
++              for (i=1; i<desc_cnt; i++)  /* multi-descriptor in one packet */
++              {
++                /* get tx skb buffer index */
++                index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++                /* free skb buffer */
++                if (tx_skb[dev_index][index])
++                {
++                          dev_kfree_skb_irq(tx_skb[dev_index][index]);
++                      }
++                  /* release Tx descriptor to CPU */
++                tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
++                tp->tx_finished_desc->frame_ctrl.bits_tx_in.own = CPU;
++              }
++            /* get tx skb buffer index */
++            index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++            /* free skb buffer */
++            if (tx_skb[dev_index][index])
++            {
++                  dev_kfree_skb_irq(tx_skb[dev_index][index]);
++              }
++            tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
++      }
++    }
++
++      if (netif_queue_stopped(dev))
++      {
++          netif_wake_queue(dev);
++      }
++
++}
++
++
++#endif
++
++#if 0
++static void gmac_weird_interrupt(struct net_device *dev)
++{
++    gmac_dump_register(dev);
++}
++#endif
++
++/* The interrupt handler does all of the Rx thread work and cleans up
++   after the Tx thread. */
++static irqreturn_t gmac_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
++{
++      struct net_device       *dev = (struct net_device *)dev_instance;
++      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
++//    GMAC_TXDMA_FIRST_DESC_T txdma_busy;
++//    GMAC_TXDMA_CTRL_T       txdma_ctrl,txdma_ctrl_mask;
++    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
++      GMAC_DMA_STATUS_T           status;
++    unsigned int            i,dev_index;
++      int                     handled = 0;
++
++    dev_index = gmac_select_interface(dev);
++
++      handled = 1;
++
++#ifdef CONFIG_SL_NAPI
++      disable_irq(gmac_irq[dev_index]);   /* disable GMAC interrupt */
++
++    status.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS);        /* read DMA status */
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS,status.bits32,status.bits32);    /* clear DMA status */
++
++    if (status.bits.rx_overrun == 1)
++    {
++              printk("%s::RX Overrun !!!%d\n",__func__,gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RBNR));
++         gmac_dump_register(dev);
++        /* if RX DMA process is stoped , restart it */
++        rxdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC) ;
++        if (rxdma_busy.bits.rd_busy == 0)
++        {
++            /* restart Rx DMA process */
++              rxdma_ctrl.bits32 = 0;
++              rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
++            rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
++            rxdma_ctrl_mask.bits32 = 0;
++              rxdma_ctrl_mask.bits.rd_start = 1;
++            rxdma_ctrl_mask.bits.rd_continue = 1;
++            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
++        }
++    }
++
++    /* process rx packet */
++      if (netif_running(dev) && ((status.bits.rs_eofi==1)||(status.bits.rs_finish==1)))
++      {
++        if (likely(netif_rx_schedule_prep(dev)))
++        {
++            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,0,0x0007c000);   /* disable rx interrupt */
++            __netif_rx_schedule(dev);
++        }
++    }
++#ifndef CONFIG_TXINT_DISABLE
++    /* process tx packet */
++      if (netif_running(dev) && ((status.bits.ts_eofi==1)||(status.bits.ts_finish==1)))
++      {
++              gmac_tx_packet_complete(dev);
++      }
++#endif
++
++      enable_irq(gmac_irq[dev_index]);    /* enable GMAC interrupt */
++    return IRQ_RETVAL(handled);
++#endif
++
++   /* disable GMAC interrupt */
++      disable_irq(gmac_irq[dev_index]);
++    for (i=0;i<MAX_ISR_WORK;i++)
++    {
++        /* read DMA status */
++          status.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS);
++int_status = status.bits32;
++          /* clear DMA status */
++        gmac_write_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS,status.bits32,status.bits32);
++
++        if ((status.bits32 & 0xffffc000)==0)
++        {
++            break;
++        }
++
++          if (status.bits.rx_overrun == 1)
++          {
++                      printk("%s::RX Overrun !!!%d\n",__func__,gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RBNR));
++              gmac_dump_register(dev);
++            /* if RX DMA process is stoped , restart it */
++              rxdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC) ;
++              if (rxdma_busy.bits.rd_busy == 0)
++              {
++                  /* restart Rx DMA process */
++              rxdma_ctrl.bits32 = 0;
++              rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
++                  rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
++                  rxdma_ctrl_mask.bits32 = 0;
++              rxdma_ctrl_mask.bits.rd_start = 1;
++                  rxdma_ctrl_mask.bits.rd_continue = 1;
++                  gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
++            }
++          }
++
++        /* receive rx interrupt */
++      if (netif_running(dev) && ((status.bits.rs_eofi==1)||(status.bits.rs_finish==1)))
++      {
++              gmac_rx_packet(dev);
++//                    gmac_tx_packet_complete(dev);
++        }
++
++        /* receive tx interrupt */
++      // if (netif_running(dev) && (status.bits.ts_finish==1))
++#ifndef CONFIG_TXINT_DISABLE
++      if (netif_running(dev) && ((status.bits.ts_eofi==1)||
++                         (status.bits.ts_finish==1)))
++      {
++              gmac_tx_packet_complete(dev);
++      }
++#endif
++      /* check uncommon events */
++/*        if ((status.bits32 & 0x632fc000)!=0)
++        {
++            printk("%s::DMA Status = %08x \n",__func__,status.bits32);
++            gmac_weird_interrupt(dev);
++        }
++*/
++      }
++
++    /* enable GMAC interrupt */
++      enable_irq(gmac_irq[dev_index]);
++      //printk("gmac_interrupt complete!\n\n");
++      return IRQ_RETVAL(handled);
++}
++
++static void gmac_hw_start(struct net_device *dev)
++{
++      struct gmac_private     *tp = dev->priv;
++      GMAC_TXDMA_CURR_DESC_T  tx_desc;
++      GMAC_RXDMA_CURR_DESC_T  rx_desc;
++    GMAC_TXDMA_CTRL_T       txdma_ctrl,txdma_ctrl_mask;
++    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
++      GMAC_DMA_STATUS_T       dma_status,dma_status_mask;
++      int                                             dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++      /* program TxDMA Current Descriptor Address register for first descriptor */
++      tx_desc.bits32 = (unsigned int)(tp->tx_desc_dma);
++      tx_desc.bits.eofie = 1;
++      tx_desc.bits.sof_eof = 0x03;
++      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC,tx_desc.bits32,0xffffffff);
++      gmac_write_reg(gmac_base_addr[dev_index] + 0xff2c,tx_desc.bits32,0xffffffff);   /* tx next descriptor address */
++
++      /* program RxDMA Current Descriptor Address register for first descriptor */
++      rx_desc.bits32 = (unsigned int)(tp->rx_desc_dma);
++      rx_desc.bits.eofie = 1;
++      rx_desc.bits.sof_eof = 0x03;
++      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CURR_DESC,rx_desc.bits32,0xffffffff);
++      gmac_write_reg(gmac_base_addr[dev_index] + 0xff3c,rx_desc.bits32,0xffffffff);   /* rx next descriptor address */
++
++      /* enable GMAC interrupt & disable loopback */
++      dma_status.bits32 = 0;
++      dma_status.bits.loop_back = 0;  /* disable DMA loop-back mode */
++//    dma_status.bits.m_tx_fail = 1;
++      dma_status.bits.m_cnt_full = 1;
++      dma_status.bits.m_rx_pause_on = 1;
++      dma_status.bits.m_tx_pause_on = 1;
++      dma_status.bits.m_rx_pause_off = 1;
++      dma_status.bits.m_tx_pause_off = 1;
++      dma_status.bits.m_rx_overrun = 1;
++      dma_status.bits.m_link_change = 1;
++      dma_status_mask.bits32 = 0;
++      dma_status_mask.bits.loop_back = 1;
++//    dma_status_mask.bits.m_tx_fail = 1;
++      dma_status_mask.bits.m_cnt_full = 1;
++      dma_status_mask.bits.m_rx_pause_on = 1;
++      dma_status_mask.bits.m_tx_pause_on = 1;
++      dma_status_mask.bits.m_rx_pause_off = 1;
++      dma_status_mask.bits.m_tx_pause_off = 1;
++      dma_status_mask.bits.m_rx_overrun = 1;
++      dma_status_mask.bits.m_link_change = 1;
++      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS,dma_status.bits32,dma_status_mask.bits32);
++
++    /* program tx dma control register */
++      txdma_ctrl.bits32 = 0;
++      txdma_ctrl.bits.td_start = 0;    /* start TX DMA transfer */
++      txdma_ctrl.bits.td_continue = 0; /* continue Tx DMA operation */
++      txdma_ctrl.bits.td_chain_mode = 1;  /* chain mode */
++      txdma_ctrl.bits.td_prot = 0;
++      txdma_ctrl.bits.td_burst_size = 2;  /* DMA burst size for every AHB request */
++      txdma_ctrl.bits.td_bus = 2;         /* peripheral bus width */
++      txdma_ctrl.bits.td_endian = 0;      /* little endian */
++#ifdef CONFIG_TXINT_DISABLE
++      txdma_ctrl.bits.td_finish_en = 0;   /* DMA finish event interrupt disable */
++#else
++      txdma_ctrl.bits.td_finish_en = 1;   /* DMA finish event interrupt enable */
++#endif
++      txdma_ctrl.bits.td_fail_en = 1;     /* DMA fail interrupt enable */
++      txdma_ctrl.bits.td_perr_en = 1;     /* protocol failure interrupt enable */
++      txdma_ctrl.bits.td_eod_en = 0;      /* disable Tx End of Descriptor Interrupt */
++      //txdma_ctrl.bits.td_eod_en = 0;      /* disable Tx End of Descriptor Interrupt */
++#ifdef CONFIG_TXINT_DISABLE
++      txdma_ctrl.bits.td_eof_en = 0;      /* end of frame interrupt disable */
++#else
++      txdma_ctrl.bits.td_eof_en = 1;      /* end of frame interrupt enable */
++#endif
++      txdma_ctrl_mask.bits32 = 0;
++      txdma_ctrl_mask.bits.td_start = 1;
++      txdma_ctrl_mask.bits.td_continue = 1;
++      txdma_ctrl_mask.bits.td_chain_mode = 1;
++      txdma_ctrl_mask.bits.td_prot = 15;
++      txdma_ctrl_mask.bits.td_burst_size = 3;
++      txdma_ctrl_mask.bits.td_bus = 3;
++      txdma_ctrl_mask.bits.td_endian = 1;
++      txdma_ctrl_mask.bits.td_finish_en = 1;
++      txdma_ctrl_mask.bits.td_fail_en = 1;
++      txdma_ctrl_mask.bits.td_perr_en = 1;
++      txdma_ctrl_mask.bits.td_eod_en = 1;
++      //txdma_ctrl_mask.bits.td_eod_en = 1;
++      txdma_ctrl_mask.bits.td_eof_en = 1;
++      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,txdma_ctrl.bits32,txdma_ctrl_mask.bits32);
++
++    /* program rx dma control register */
++      rxdma_ctrl.bits32 = 0;
++      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
++      rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
++      rxdma_ctrl.bits.rd_chain_mode = 1;  /* chain mode */
++      rxdma_ctrl.bits.rd_prot = 0;
++      rxdma_ctrl.bits.rd_burst_size = 2;  /* DMA burst size for every AHB request */
++      rxdma_ctrl.bits.rd_bus = 2;         /* peripheral bus width */
++      rxdma_ctrl.bits.rd_endian = 0;      /* little endian */
++      rxdma_ctrl.bits.rd_finish_en = 1;   /* DMA finish event interrupt enable */
++      rxdma_ctrl.bits.rd_fail_en = 1;     /* DMA fail interrupt enable */
++      rxdma_ctrl.bits.rd_perr_en = 1;     /* protocol failure interrupt enable */
++      rxdma_ctrl.bits.rd_eod_en = 0;      /* disable Rx End of Descriptor Interrupt */
++      rxdma_ctrl.bits.rd_eof_en = 1;      /* end of frame interrupt enable */
++      rxdma_ctrl_mask.bits32 = 0;
++      rxdma_ctrl_mask.bits.rd_start = 1;
++      rxdma_ctrl_mask.bits.rd_continue = 1;
++      rxdma_ctrl_mask.bits.rd_chain_mode = 1;
++      rxdma_ctrl_mask.bits.rd_prot = 15;
++      rxdma_ctrl_mask.bits.rd_burst_size = 3;
++      rxdma_ctrl_mask.bits.rd_bus = 3;
++      rxdma_ctrl_mask.bits.rd_endian = 1;
++      rxdma_ctrl_mask.bits.rd_finish_en = 1;
++      rxdma_ctrl_mask.bits.rd_fail_en = 1;
++      rxdma_ctrl_mask.bits.rd_perr_en = 1;
++      rxdma_ctrl_mask.bits.rd_eod_en = 1;
++      rxdma_ctrl_mask.bits.rd_eof_en = 1;
++      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
++    return;
++}
++
++static void gmac_hw_stop(struct net_device *dev)
++{
++    GMAC_TXDMA_CTRL_T       txdma_ctrl,txdma_ctrl_mask;
++    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
++      int                                     dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++    /* program tx dma control register */
++      txdma_ctrl.bits32 = 0;
++      txdma_ctrl.bits.td_start = 0;
++      txdma_ctrl.bits.td_continue = 0;
++      txdma_ctrl_mask.bits32 = 0;
++      txdma_ctrl_mask.bits.td_start = 1;
++      txdma_ctrl_mask.bits.td_continue = 1;
++      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,txdma_ctrl.bits32,txdma_ctrl_mask.bits32);
++    /* program rx dma control register */
++      rxdma_ctrl.bits32 = 0;
++      rxdma_ctrl.bits.rd_start = 0;    /* stop RX DMA transfer */
++      rxdma_ctrl.bits.rd_continue = 0; /* stop continue RX DMA operation */
++      rxdma_ctrl_mask.bits32 = 0;
++      rxdma_ctrl_mask.bits.rd_start = 1;
++      rxdma_ctrl_mask.bits.rd_continue = 1;
++      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
++}
++
++static int gmac_init_desc_buf(struct net_device *dev)
++{
++      struct gmac_private *tp = dev->priv;
++      struct sk_buff          *skb;
++      dma_addr_t          tx_first_desc_dma=0;
++      dma_addr_t          rx_first_desc_dma=0;
++      dma_addr_t          rx_first_buf_dma=0;
++      unsigned int        i,index;
++
++    printk("Descriptor buffer init......\n");
++
++    /* get device index number */
++    index = gmac_get_dev_index(dev);
++#ifdef CONFIG_SL2312_MPAGE
++      for (i=0; i<TX_DESC_NUM; i++) {
++              tx_skb[index][i].freeable = 0;
++              tx_skb[index][i].skb = 0;
++              tx_skb[index][i].desc_in_use = 0;
++              tx_skb[index][i].end_seq = 0;
++      }
++#else
++    for (i=0;i<TX_DESC_NUM;i++)
++    {
++        tx_skb[index][i] = NULL;
++    }
++#endif
++    for (i=0;i<RX_DESC_NUM;i++)
++    {
++        rx_skb[index][i] = NULL;
++    }
++
++      /* allocates TX/RX descriptors */
++      tp->tx_desc = DMA_MALLOC(TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(dma_addr_t *)&tp->tx_desc_dma);
++    tx_desc_virtual_base[index] = (unsigned int)tp->tx_desc - (unsigned int)tp->tx_desc_dma;
++    memset(tp->tx_desc,0x00,TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T));
++      tp->rx_desc = DMA_MALLOC(RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(dma_addr_t *)&tp->rx_desc_dma);
++    rx_desc_virtual_base[index] = (unsigned int)tp->rx_desc - (unsigned int)tp->rx_desc_dma;
++    memset(tp->rx_desc,0x00,RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T));
++    tx_desc_start_adr[index] = (unsigned int)tp->tx_desc;   /* for tx skb index calculation */
++    rx_desc_start_adr[index] = (unsigned int)tp->rx_desc;   /* for rx skb index calculation */
++    printk("tx_desc = %08x\n",(unsigned int)tp->tx_desc);
++    printk("rx_desc = %08x\n",(unsigned int)tp->rx_desc);
++      printk("tx_desc_dma = %08x\n",tp->tx_desc_dma);
++      printk("rx_desc_dma = %08x\n",tp->rx_desc_dma);
++
++      if (tp->tx_desc==0x00 || tp->rx_desc==0x00)
++      {
++              free_irq(dev->irq, dev);
++
++              if (tp->tx_desc)
++                      DMA_MFREE(tp->tx_desc, TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),tp->tx_desc_dma);
++              if (tp->rx_desc)
++                      DMA_MFREE(tp->rx_desc, RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),tp->rx_desc_dma);
++              return -ENOMEM;
++      }
++
++      /* TX descriptors initial */
++      tp->tx_cur_desc = tp->tx_desc;  /* virtual address */
++      tp->tx_finished_desc = tp->tx_desc; /* virtual address */
++      tx_first_desc_dma = tp->tx_desc_dma; /* physical address */
++      for (i = 1; i < TX_DESC_NUM; i++)
++      {
++              tp->tx_desc->frame_ctrl.bits_tx_out.own = CPU; /* set owner to CPU */
++              tp->tx_desc->frame_ctrl.bits_tx_out.buffer_size = TX_BUF_SIZE;  /* set tx buffer size for descriptor */
++              tp->tx_desc_dma = tp->tx_desc_dma + sizeof(GMAC_DESCRIPTOR_T); /* next tx descriptor DMA address */
++              tp->tx_desc->next_desc.next_descriptor = tp->tx_desc_dma | 0x0000000b;
++              tp->tx_desc = &tp->tx_desc[1] ; /* next tx descriptor virtual address */
++      }
++      /* the last descriptor will point back to first descriptor */
++      tp->tx_desc->frame_ctrl.bits_tx_out.own = CPU;
++      tp->tx_desc->frame_ctrl.bits_tx_out.buffer_size = TX_BUF_SIZE;
++      tp->tx_desc->next_desc.next_descriptor = tx_first_desc_dma | 0x0000000b;
++      tp->tx_desc = tp->tx_cur_desc;
++      tp->tx_desc_dma = tx_first_desc_dma;
++
++      /* RX descriptors initial */
++      tp->rx_cur_desc = tp->rx_desc;  /* virtual address */
++      rx_first_desc_dma = tp->rx_desc_dma; /* physical address */
++      for (i = 1; i < RX_DESC_NUM; i++)
++      {
++        if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
++        {
++            printk("%s::skb buffer allocation fail !\n",__func__);
++        }
++        rx_skb[index][i-1] = skb;
++        tp->rx_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
++              tp->rx_desc->frame_ctrl.bits_rx.own = DMA;  /* set owner bit to DMA */
++              tp->rx_desc->frame_ctrl.bits_rx.buffer_size = RX_BUF_SIZE; /* set rx buffer size for descriptor */
++              tp->rx_bufs_dma = tp->rx_bufs_dma + RX_BUF_SIZE;    /* point to next buffer address */
++              tp->rx_desc_dma = tp->rx_desc_dma + sizeof(GMAC_DESCRIPTOR_T); /* next rx descriptor DMA address */
++              tp->rx_desc->next_desc.next_descriptor = tp->rx_desc_dma | 0x0000000b;
++              tp->rx_desc = &tp->rx_desc[1]; /* next rx descriptor virtual address */
++      }
++      /* the last descriptor will point back to first descriptor */
++    if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
++    {
++        printk("%s::skb buffer allocation fail !\n",__func__);
++    }
++    rx_skb[index][i-1] = skb;
++    tp->rx_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
++      tp->rx_desc->frame_ctrl.bits_rx.own = DMA;
++      tp->rx_desc->frame_ctrl.bits_rx.buffer_size = RX_BUF_SIZE;
++      tp->rx_desc->next_desc.next_descriptor = rx_first_desc_dma | 0x0000000b;
++      tp->rx_desc = tp->rx_cur_desc;
++      tp->rx_desc_dma = rx_first_desc_dma;
++      tp->rx_bufs_dma = rx_first_buf_dma;
++
++      for (i=0; i<GMAC_PHY_IF; i++) {
++              tp->tx_desc_hdr[i] = 0;
++              tp->tx_desc_tail[i] = 0;
++      }
++      return (0);
++}
++
++static int gmac_clear_counter (struct net_device *dev)
++{
++      struct gmac_private *tp = dev->priv;
++      unsigned int    dev_index;
++
++    dev_index = gmac_select_interface(dev);
++//    tp = gmac_dev[index]->priv;
++    /* clear counter */
++    gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_DISCARDS);
++    gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_ERRORS);
++    tp->stats.tx_bytes = 0;
++    tp->stats.tx_packets = 0;
++      tp->stats.tx_errors = 0;
++    tp->stats.rx_bytes = 0;
++      tp->stats.rx_packets = 0;
++      tp->stats.rx_errors = 0;
++    tp->stats.rx_dropped = 0;
++      return (0);
++}
++
++static int gmac_open (struct net_device *dev)
++{
++      struct gmac_private     *tp = dev->priv;
++      int    retval;
++
++    gmac_select_interface(dev);
++
++      /* chip reset */
++      gmac_sw_reset(dev);
++
++    /* allocates tx/rx descriptor and buffer memory */
++    gmac_init_desc_buf(dev);
++
++    /* get mac address from FLASH */
++    gmac_get_mac_address();
++
++    /* set PHY register to start autonegition process */
++    gmac_set_phy_status(dev);
++
++      /* GMAC initialization */
++      if (gmac_init_chip(dev))
++      {
++              printk (KERN_ERR "GMAC init fail\n");
++      }
++
++    /* start DMA process */
++      gmac_hw_start(dev);
++
++    /* enable tx/rx register */
++    gmac_enable_tx_rx(dev);
++
++    /* clear statistic counter */
++    gmac_clear_counter(dev);
++
++      netif_start_queue (dev);
++
++    /* hook ISR */
++      retval = request_irq (dev->irq, gmac_interrupt, SA_INTERRUPT, dev->name, dev);
++      if (retval)
++              return retval;
++
++      if(!FLAG_SWITCH)
++      {
++      init_waitqueue_head (&tp->thr_wait);
++      init_completion(&tp->thr_exited);
++
++      tp->time_to_die = 0;
++      tp->thr_pid = kernel_thread (gmac_phy_thread, dev, CLONE_FS | CLONE_FILES);
++      if (tp->thr_pid < 0)
++      {
++              printk (KERN_WARNING "%s: unable to start kernel thread\n",dev->name);
++      }
++    }
++      return (0);
++}
++
++static int gmac_close(struct net_device *dev)
++{
++    struct gmac_private *tp = dev->priv;
++    unsigned int        i,dev_index;
++    unsigned int        ret;
++
++    dev_index = gmac_get_dev_index(dev);
++
++    /* stop tx/rx packet */
++    gmac_disable_tx_rx(dev);
++
++    /* stop the chip's Tx and Rx DMA processes */
++      gmac_hw_stop(dev);
++
++    netif_stop_queue(dev);
++
++    /* disable interrupts by clearing the interrupt mask */
++    synchronize_irq();
++    free_irq(dev->irq,dev);
++
++      DMA_MFREE(tp->tx_desc, TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(unsigned int)tp->tx_desc_dma);
++      DMA_MFREE(tp->rx_desc, RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(unsigned int)tp->rx_desc_dma);
++
++#ifdef CONFIG_SL2312_MPAGE
++//    kfree(tx_skb);
++#endif
++
++    for (i=0;i<RX_DESC_NUM;i++)
++    {
++        if (rx_skb[dev_index][i])
++        {
++            dev_kfree_skb(rx_skb[dev_index][i]);
++        }
++    }
++      if(!FLAG_SWITCH)
++      {
++      if (tp->thr_pid >= 0)
++      {
++                  tp->time_to_die = 1;
++              wmb();
++              ret = kill_proc (tp->thr_pid, SIGTERM, 1);
++              if (ret)
++              {
++                      printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
++                      return ret;
++              }
++//                    wait_for_completion (&tp->thr_exited);
++      }
++    }
++
++    return (0);
++}
++
++#ifdef CONFIG_SL2312_MPAGE
++int printk_all(int dev_index, struct gmac_private* tp)
++{
++      int i=0;
++    unsigned int tx_current_descriptor = 0;
++    int hw_index;
++    int fi;
++    GMAC_DESCRIPTOR_T* tmp_desc;
++
++      GMAC_DESCRIPTOR_T* cur_desc=tp->tx_cur_desc;
++      fi = ((unsigned int)cur_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++      printk("tmp_desc %x, id %d\n", (int)cur_desc, fi);
++
++      tmp_desc = (GMAC_DESCRIPTOR_T*)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
++      hw_index = ((unsigned int)tmp_desc - tx_desc_start_adr[dev_index])/ sizeof(GMAC_DESCRIPTOR_T);
++      printk("hd_desc %x, ind %d, fin desc %x\n",(int)tmp_desc, hw_index, (int)tp->tx_finished_desc);
++
++      for (i=0; i<TX_DESC_NUM; i++) {
++              printk("**id %4d, hw_index %4d ==> ", fi, hw_index);
++              printk("fc %8x ", tmp_desc->frame_ctrl.bits32);
++              printk("fs %8x ", tmp_desc->flag_status.bits32);
++              printk("fb %8x ", tmp_desc->buf_adr);
++              printk("fd %8x\n",  tmp_desc->next_desc.next_descriptor);
++              tmp_desc = (GMAC_DESCRIPTOR_T*)((tmp_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
++              fi = ((unsigned int)tmp_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++      }
++    tx_current_descriptor = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC);
++    printk("%s: tx current descriptor = %x \n",__func__,tx_current_descriptor);
++    printk("%s: interrupt status = %x \n",__func__,int_status);
++    return 0;
++}
++
++int cleanup_desc(int dev_index, struct gmac_private* tp)
++{
++      int i=0;
++      int index = ((unsigned int)tp->tx_cur_desc - tx_desc_start_adr[dev_index])/sizeof(GMAC_DESCRIPTOR_T);
++      GMAC_DESCRIPTOR_T* fill_desc = tp->tx_cur_desc;
++
++      for (i=0; i< TX_DESC_NUM; i++)
++      {
++              fill_desc->frame_ctrl.bits_tx_out.own = CPU;
++              fill_desc->frame_ctrl.bits_tx_out.buffer_size = TX_BUF_SIZE;
++              tx_skb[dev_index][index].desc_in_use = 0;
++              free_tx_buf(dev_index, index);
++              printk("cleanup di %d\n", index);
++              fill_desc = (GMAC_DESCRIPTOR_T*)((fill_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
++              index++;
++              if (index > TX_DESC_NUM)
++                      index = 0;
++      }
++      return 1;
++}
++
++size_t get_available_tx_desc(struct net_device* dev, int dev_index)
++{
++      struct gmac_private *tp = dev->priv;
++      unsigned int desc_hdr = tp->tx_desc_hdr[dev_index];
++      unsigned int desc_tail = tp->tx_desc_tail[dev_index];
++      int available_desc_num = (TX_DESC_NUM - desc_hdr + desc_tail) & (TX_DESC_NUM-1);
++      if (!available_desc_num) {
++              if (tx_skb[dev_index][desc_hdr].desc_in_use)
++                      return 0;
++              else
++                      return TX_DESC_NUM;
++      }
++      return available_desc_num;
++}
++
++int check_free_tx_desc(int dev_index, int n, GMAC_DESCRIPTOR_T* desc)
++{
++      int i,index;
++      GMAC_DESCRIPTOR_T* tmp_desc = desc;
++
++      if (n > TX_DESC_NUM)
++              return 0;
++
++      index = ((unsigned int)tmp_desc - tx_desc_start_adr[dev_index])/sizeof(GMAC_DESCRIPTOR_T);
++      for (i=0; i<n; i++)
++      {
++              if (tx_skb[dev_index][index].desc_in_use)
++              {
++                      printk("sw desc %d is in use\n", index);
++                      /* cleanup all the descriptors to check if DMA still running */
++                      return 0;
++              }
++              index++;
++              if (index == TX_DESC_NUM)
++                      index = 0;
++      }
++      return 1;
++}
++
++#define TCPHDRLEN(tcp_hdr)  ((ntohs(*((__u16 *)tcp_hdr + 6)) >> 12) & 0x000F)
++
++inline int fill_in_desc(int dev_index, GMAC_DESCRIPTOR_T *desc, char* data, int len, int total_len, int sof, int freeable, int ownership, struct sk_buff* skb)
++{
++      int index = ((unsigned int)desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++
++      if (desc->frame_ctrl.bits_tx_in.own == CPU)
++      {
++              tx_skb[dev_index][index].freeable = freeable;
++              if ((sof & 0x01) && skb) {
++                      tx_skb[dev_index][index].skb = skb;
++              }
++              else
++                      tx_skb[dev_index][index].skb = 0;
++
++              if (sof != 2)
++                      tx_skb[dev_index][index].desc_in_use = 1;
++              else
++                      tx_skb[dev_index][index].desc_in_use = 0;
++
++              consistent_sync(data, len, PCI_DMA_TODEVICE);
++              desc->buf_adr = (unsigned int)__pa(data);
++              desc->frame_ctrl.bits_tx_out.buffer_size = len;
++              desc->flag_status.bits_tx_flag.frame_count = total_len;
++              desc->next_desc.bits.eofie = 1;
++              desc->next_desc.bits.sof_eof = sof;
++              desc->frame_ctrl.bits_tx_out.vlan_enable = 0;
++              desc->frame_ctrl.bits_tx_out.ip_csum_en = 1;     /* TSS IPv4 IP header checksum enable */
++              desc->frame_ctrl.bits_tx_out.ipv6_tx_en = 1;    /* TSS IPv6 tx enable */
++              desc->frame_ctrl.bits_tx_out.tcp_csum_en = 1;    /* TSS TCP checksum enable */
++              desc->frame_ctrl.bits_tx_out.udp_csum_en = 1;    /* TSS UDP checksum enable */
++        wmb();
++              desc->frame_ctrl.bits_tx_out.own = ownership;
++//            consistent_sync(desc, sizeof(GMAC_DESCRIPTOR_T), PCI_DMA_TODEVICE);
++      }
++      return 0;
++}
++#endif
++
++static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++      struct gmac_private     *tp = dev->priv;
++      GMAC_TXDMA_CTRL_T               tx_ctrl,tx_ctrl_mask;
++      GMAC_TXDMA_FIRST_DESC_T txdma_busy;
++      unsigned int            len = skb->len;
++      unsigned int            dev_index;
++      static unsigned int     pcount = 0;
++#ifdef CONFIG_SL2312_MPAGE
++    GMAC_DESCRIPTOR_T *fill_desc;
++      int snd_pages = skb_shinfo(skb)->nr_frags;  /* get number of descriptor */
++      int desc_needed = 1; // for jumbo packet, one descriptor is enough.
++      int header_len = skb->len;
++    struct iphdr      *ip_hdr;
++    struct tcphdr     *tcp_hdr;
++    int             tcp_hdr_len;
++    int             data_len;
++    int             prv_index;
++    long            seq_num;
++    int             first_desc_index;
++    int             ownership, freeable;
++    int             eof;
++      int             i=0;
++#endif
++#ifdef CONFIG_TXINT_DISABLE
++      int                             available_desc_cnt = 0;
++#endif
++
++    dev_index = gmac_select_interface(dev);
++
++#ifdef CONFIG_TXINT_DISABLE
++      available_desc_cnt = get_available_tx_desc(dev, dev_index);
++
++      if (available_desc_cnt < (TX_DESC_NUM >> 2)) {
++              gmac_tx_packet_complete(dev);
++      }
++#endif
++
++#ifdef CONFIG_SL2312_MPAGE
++
++      fill_desc = tp->tx_cur_desc;
++      if(!fill_desc) {
++              printk("cur_desc is NULL!\n");
++              return -1;
++      }
++
++      if (storlink_ctl.recvfile==2)
++      {
++          printk("snd_pages=%d skb->len=%d\n",snd_pages,skb->len);
++      }
++
++      if (snd_pages)
++              desc_needed += snd_pages;   /* decriptors needed for this large packet */
++
++      if (!check_free_tx_desc(dev_index, desc_needed, fill_desc)) {
++              printk("no available desc!\n");
++        gmac_dump_register(dev);
++              printk_all(dev_index, tp);
++              tp->stats.tx_dropped++;
++              if (pcount++ > 10)
++              {
++                  for (;;);
++              }
++              return -1;
++      }
++
++      first_desc_index = ((unsigned int)fill_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++
++      /* check if the tcp packet is in order*/
++      ip_hdr = (struct iphdr*) &(skb->data[14]);
++      tcp_hdr = (struct tcphdr*) &(skb->data[14+ip_hdr->ihl * 4]);
++      tcp_hdr_len = TCPHDRLEN(tcp_hdr) * 4;
++      data_len = skb->len - 14 - ip_hdr->ihl *4 - tcp_hdr_len;
++
++      prv_index = first_desc_index-1;
++      if (prv_index <0)
++          prv_index += TX_DESC_NUM;
++      seq_num = ntohl(tcp_hdr->seq);
++
++      if (snd_pages)
++      {
++              // calculate header length
++              // check fragment total length and header len = skb len - frag len
++              // or parse the header.
++              for (i=0; i<snd_pages; i++) {
++                      skb_frag_t* frag = &skb_shinfo(skb)->frags[i];
++                      header_len -= frag->size;
++              }
++              ownership = CPU;
++              freeable = 0;
++              /* fill header into first descriptor */
++              fill_in_desc(dev_index, fill_desc, skb->data, header_len, len, 2, freeable, ownership, 0);
++              fill_desc = (GMAC_DESCRIPTOR_T*)((fill_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
++              tx_skb[dev_index][first_desc_index].end_seq = seq_num + data_len;
++
++              eof = 0;
++              ownership = DMA;
++              for (i=0; i<snd_pages; i++)
++              {
++                      skb_frag_t* frag = &skb_shinfo(skb)->frags[i];
++                      int start_pos = frag->page_offset;
++                      char* data_buf = page_address(frag->page);
++                      int data_size = frag->size;
++                      int cur_index;
++
++                      if (i == snd_pages-1)
++                      {
++                              eof=1;
++                              freeable = 1;
++                      }
++                      fill_in_desc(dev_index, fill_desc, data_buf+(start_pos), data_size,
++                                   len, eof, freeable, ownership, skb);
++                      cur_index = ((unsigned int)fill_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++
++                      fill_desc = (GMAC_DESCRIPTOR_T*)((fill_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
++              }
++              /* pass the ownership of the first descriptor to hardware */
++//        disable_irq(gmac_irq[dev_index]);
++              tx_skb[dev_index][first_desc_index].desc_in_use = 1;
++        wmb();
++              tp->tx_cur_desc->frame_ctrl.bits_tx_out.own = DMA;
++//            consistent_sync(tp->tx_cur_desc, sizeof(GMAC_DESCRIPTOR_T), PCI_DMA_TODEVICE);
++              tp->tx_cur_desc = fill_desc;
++              dev->trans_start = jiffies;
++//        enable_irq(gmac_irq[dev_index]);
++      }
++      else if ( tp->tx_cur_desc->frame_ctrl.bits_tx_out.own == CPU )
++      {
++//            tx_skb[dev_index][first_desc_index].end_seq = seq_num + data_len;
++//        disable_irq(gmac_irq[dev_index]);
++              fill_in_desc(dev_index, tp->tx_cur_desc, skb->data, skb->len, skb->len, 3, 1, DMA, skb);
++//        enable_irq(gmac_irq[dev_index]);
++              //consistent_sync(tp->tx_cur_desc, sizeof(GMAC_DESCRIPTOR_T), PCI_DMA_TODEVICE);
++              tp->tx_cur_desc = (GMAC_DESCRIPTOR_T*)((tp->tx_cur_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
++              dev->trans_start = jiffies;
++      }
++      else
++      {
++              printk("gmac tx drop!\n");
++              tp->stats.tx_dropped++;
++              return -1;
++      }
++
++#ifdef CONFIG_TXINT_DISABLE
++      tp->tx_desc_hdr[dev_index] = (tp->tx_desc_hdr[dev_index] + desc_needed) & (TX_DESC_NUM-1);
++#endif
++
++#else
++    if ((tp->tx_cur_desc->frame_ctrl.bits_tx_out.own == CPU) && (len < TX_BUF_SIZE))
++      {
++        index = ((unsigned int)tp->tx_cur_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
++        tx_skb[dev_index][index] = skb;
++        consistent_sync(skb->data,skb->len,PCI_DMA_TODEVICE);
++        tp->tx_cur_desc->buf_adr = (unsigned int)__pa(skb->data);
++      tp->tx_cur_desc->flag_status.bits_tx_flag.frame_count = len;    /* total frame byte count */
++      tp->tx_cur_desc->next_desc.bits.sof_eof = 0x03;                 /*only one descriptor*/
++              tp->tx_cur_desc->frame_ctrl.bits_tx_out.buffer_size = len;      /* descriptor byte count */
++        tp->tx_cur_desc->frame_ctrl.bits_tx_out.vlan_enable = 0;
++        tp->tx_cur_desc->frame_ctrl.bits_tx_out.ip_csum_en = 0;     /* TSS IPv4 IP header checksum enable */
++        tp->tx_cur_desc->frame_ctrl.bits_tx_out.ipv6_tx_en = 0 ;    /* TSS IPv6 tx enable */
++        tp->tx_cur_desc->frame_ctrl.bits_tx_out.tcp_csum_en = 0;    /* TSS TCP checksum enable */
++        tp->tx_cur_desc->frame_ctrl.bits_tx_out.udp_csum_en = 0;    /* TSS UDP checksum enable */
++        wmb();
++      tp->tx_cur_desc->frame_ctrl.bits_tx_out.own = DMA;              /* set owner bit */
++      tp->tx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
++      dev->trans_start = jiffies;
++      }
++      else
++      {
++              /* no free tx descriptor */
++              dev_kfree_skb(skb);
++          netif_stop_queue(dev);
++              tp->stats.tx_dropped++;
++              return (-1);
++      }
++#endif
++      /* if TX DMA process is stoped , restart it */
++      txdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_FIRST_DESC);
++      if (txdma_busy.bits.td_busy == 0)
++      {
++              /* restart DMA process */
++              tx_ctrl.bits32 = 0;
++              tx_ctrl.bits.td_start = 1;
++              tx_ctrl.bits.td_continue = 1;
++              tx_ctrl_mask.bits32 = 0;
++              tx_ctrl_mask.bits.td_start = 1;
++              tx_ctrl_mask.bits.td_continue = 1;
++              gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,tx_ctrl.bits32,tx_ctrl_mask.bits32);
++      }
++      return (0);
++}
++
++
++struct net_device_stats * gmac_get_stats(struct net_device *dev)
++{
++    struct gmac_private *tp = dev->priv;
++    unsigned long       flags;
++    unsigned int        pkt_drop;
++    unsigned int        pkt_error;
++    unsigned int        dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++//    if (storlink_ctl.recvfile==3)
++//    {
++//        printk("GMAC_GLOBAL_BASE_ADDR=%x\n", readl(GMAC_GLOBAL_BASE_ADDR+0x30));
++//        gmac_dump_register(dev);
++//        printk_all(0, dev);
++//    }
++
++    if (netif_running(dev))
++    {
++        /* read H/W counter */
++        spin_lock_irqsave(&tp->lock,flags);
++        pkt_drop = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_DISCARDS);
++        pkt_error = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_ERRORS);
++        tp->stats.rx_dropped = tp->stats.rx_dropped + pkt_drop;
++        tp->stats.rx_errors = tp->stats.rx_errors + pkt_error;
++        spin_unlock_irqrestore(&tp->lock,flags);
++    }
++    return &tp->stats;
++}
++
++static unsigned const ethernet_polynomial = 0x04c11db7U;
++static inline u32 ether_crc (int length, unsigned char *data)
++{
++      int crc = -1;
++      unsigned int i;
++      unsigned int crc_val=0;
++
++      while (--length >= 0) {
++              unsigned char current_octet = *data++;
++              int bit;
++              for (bit = 0; bit < 8; bit++, current_octet >>= 1)
++                      crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ?
++                           ethernet_polynomial : 0);
++      }
++      crc = ~crc;
++      for (i=0;i<32;i++)
++      {
++              crc_val = crc_val + (((crc << i) & 0x80000000) >> (31-i));
++      }
++      return crc_val;
++}
++
++static void gmac_set_rx_mode(struct net_device *dev)
++{
++    GMAC_RX_FLTR_T      filter;
++      unsigned int        mc_filter[2];       /* Multicast hash filter */
++    int                 bit_nr;
++      unsigned int        i, dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++//    printk("%s : dev->flags = %x \n",__func__,dev->flags);
++//    dev->flags |= IFF_ALLMULTI;  /* temp */
++    filter.bits32 = 0;
++    filter.bits.error = 0;
++      if (dev->flags & IFF_PROMISC)
++      {
++          filter.bits.error = 1;
++        filter.bits.promiscuous = 1;
++        filter.bits.broadcast = 1;
++        filter.bits.multicast = 1;
++        filter.bits.unicast = 1;
++              mc_filter[1] = mc_filter[0] = 0xffffffff;
++      }
++      else if (dev->flags & IFF_ALLMULTI)
++      {
++        filter.bits.promiscuous = 1;
++        filter.bits.broadcast = 1;
++        filter.bits.multicast = 1;
++        filter.bits.unicast = 1;
++              mc_filter[1] = mc_filter[0] = 0xffffffff;
++      }
++      else
++      {
++              struct dev_mc_list *mclist;
++
++        filter.bits.promiscuous = 1;
++        filter.bits.broadcast = 1;
++        filter.bits.multicast = 1;
++        filter.bits.unicast = 1;
++              mc_filter[1] = mc_filter[0] = 0;
++              for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;i++, mclist = mclist->next)
++              {
++            bit_nr = ether_crc(ETH_ALEN,mclist->dmi_addr) & 0x0000003f;
++            if (bit_nr < 32)
++            {
++                mc_filter[0] = mc_filter[0] | (1<<bit_nr);
++            }
++            else
++            {
++                mc_filter[1] = mc_filter[1] | (1<<(bit_nr-32));
++            }
++              }
++      }
++    filter.bits32 = 0x1f;
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RX_FLTR,filter.bits32,0xffffffff);
++
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_MCAST_FIL0,mc_filter[0],0xffffffff);
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_MCAST_FIL1,mc_filter[1],0xffffffff);
++    return;
++}
++
++static int gmac_set_mac_address(struct net_device *dev, void *addr)
++{
++      struct sockaddr *sock;
++      unsigned int    reg_val;
++      unsigned int    dev_index;
++    unsigned int    i;
++
++    dev_index = gmac_select_interface(dev);
++
++      sock = (struct sockaddr *) addr;
++      for (i = 0; i < 6; i++)
++      {
++              dev->dev_addr[i] = sock->sa_data[i];
++      }
++
++    reg_val = dev->dev_addr[0] + (dev->dev_addr[1]<<8) + (dev->dev_addr[2]<<16) + (dev->dev_addr[3]<<24);
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_STA_ADD0,reg_val,0xffffffff);
++    reg_val = dev->dev_addr[4] + (dev->dev_addr[5]<<8) ;
++    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_STA_ADD1,reg_val,0x0000ffff);
++    memcpy(&eth0_mac[0],&dev->dev_addr[0],6);
++    printk("Storlink %s address = ",dev->name);
++    printk("%02x",dev->dev_addr[0]);
++    printk("%02x",dev->dev_addr[1]);
++    printk("%02x",dev->dev_addr[2]);
++    printk("%02x",dev->dev_addr[3]);
++    printk("%02x",dev->dev_addr[4]);
++    printk("%02x\n",dev->dev_addr[5]);
++
++    return (0);
++}
++
++static void gmac_tx_timeout(struct net_device *dev)
++{
++      GMAC_TXDMA_CTRL_T               tx_ctrl,tx_ctrl_mask;
++    GMAC_TXDMA_FIRST_DESC_T     txdma_busy;
++    int                                                       dev_index;
++
++    dev_index = gmac_select_interface(dev);
++
++    /* if TX DMA process is stoped , restart it */
++      txdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_FIRST_DESC);
++      if (txdma_busy.bits.td_busy == 0)
++      {
++              /* restart DMA process */
++              tx_ctrl.bits32 = 0;
++              tx_ctrl.bits.td_start = 1;
++              tx_ctrl.bits.td_continue = 1;
++              tx_ctrl_mask.bits32 = 0;
++              tx_ctrl_mask.bits.td_start = 1;
++              tx_ctrl_mask.bits.td_continue = 1;
++              gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,tx_ctrl.bits32,tx_ctrl_mask.bits32);
++      }
++      netif_wake_queue(dev);
++    return;
++}
++
++static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++      int rc = 0;
++    unsigned char *hwa = rq->ifr_ifru.ifru_hwaddr.sa_data;
++
++      if (!netif_running(dev))
++      {
++          printk("Before changing the H/W address,please down the device.\n");
++              return -EINVAL;
++    }
++
++      switch (cmd) {
++      case SIOCETHTOOL:
++        break;
++
++    case SIOCSIFHWADDR:
++        gmac_set_mac_address(dev,hwa);
++        break;
++
++      case SIOCGMIIPHY:       /* Get the address of the PHY in use. */
++      case SIOCDEVPRIVATE:    /* binary compat, remove in 2.5 */
++        break;
++
++      case SIOCGMIIREG:       /* Read the specified MII register. */
++      case SIOCDEVPRIVATE+1:
++              break;
++
++      case SIOCSMIIREG:       /* Write the specified MII register */
++      case SIOCDEVPRIVATE+2:
++              break;
++
++      default:
++              rc = -EOPNOTSUPP;
++              break;
++      }
++
++      return rc;
++}
++
++static void gmac_cleanup_module(void)
++{
++    int i;
++
++    for (i=0;i<GMAC_PHY_IF;i++)
++    {
++        unregister_netdev(gmac_dev[i]);
++    }
++      return ;
++}
++
++static int __init gmac_init_module(void)
++{
++      struct gmac_private *tp;
++      struct net_device *dev[GMAC_PHY_IF];
++      unsigned int i;
++
++#ifdef MODULE
++      printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
++#endif
++//    init_waitqueue_entry(&wait, current);
++
++      printk("GMAC Init......\n");
++      for(i = 0; i<GMAC_PHY_IF; i++)
++      {
++              dev[i] = alloc_etherdev(sizeof(struct gmac_private));
++              if (dev[i] == NULL)
++              {
++                      printk (KERN_ERR "Can't allocate ethernet device #%d .\n",i);
++                      return -ENOMEM;
++              }
++        gmac_dev[i] = dev[i];
++
++              SET_MODULE_OWNER(dev[i]);
++
++              tp = dev[i]->priv;
++
++              dev[i]->base_addr = gmac_base_addr[i];
++              dev[i]->irq = gmac_irq[i];
++          dev[i]->open = gmac_open;
++          dev[i]->stop = gmac_close;
++              dev[i]->hard_start_xmit = gmac_start_xmit;
++              dev[i]->get_stats = gmac_get_stats;
++              dev[i]->set_multicast_list = gmac_set_rx_mode;
++              dev[i]->set_mac_address = gmac_set_mac_address;
++              dev[i]->do_ioctl = gmac_netdev_ioctl;
++              dev[i]->tx_timeout = gmac_tx_timeout;
++              dev[i]->watchdog_timeo = TX_TIMEOUT;
++              dev[i]->features |= NETIF_F_SG|NETIF_F_HW_CSUM|NETIF_F_TSO;
++#ifdef CONFIG_SL_NAPI
++        printk("NAPI driver is enabled.\n");
++        if (i==0)
++        {
++              dev[i]->poll = gmac_rx_poll_ga;
++              dev[i]->weight = 64;
++          }
++          else
++          {
++              dev[i]->poll = gmac_rx_poll_gb;
++              dev[i]->weight = 64;
++          }
++#endif
++
++              if (register_netdev(dev[i]))
++              {
++                      gmac_cleanup_module();
++                      return(-1);
++              }
++      }
++
++#ifdef CONFIG_SL3516_ASIC
++{
++    unsigned int    val;
++
++    /* set GMAC global register */
++    val = readl(GMAC_GLOBAL_BASE_ADDR+0x10);
++    val = val | 0x005a0000;
++    writel(val,GMAC_GLOBAL_BASE_ADDR+0x10);
++    writel(0x07f007f0,GMAC_GLOBAL_BASE_ADDR+0x1c);
++    writel(0x77770000,GMAC_GLOBAL_BASE_ADDR+0x20);
++    writel(0x77770000,GMAC_GLOBAL_BASE_ADDR+0x24);
++      val = readl(GMAC_GLOBAL_BASE_ADDR+0x04);
++      if((val&(1<<20))==0){           // GMAC1 enable
++              val = readl(GMAC_GLOBAL_BASE_ADDR+0x30);
++              val = (val & 0xe7ffffff) | 0x08000000;
++              writel(val,GMAC_GLOBAL_BASE_ADDR+0x30);
++      }
++
++}
++#endif
++
++//    printk("%s: dev0=%x  dev1=%x \n",__func__,dev[0],dev[1]);
++//    FLAG_SWITCH = 0 ;
++//    FLAG_SWITCH = SPI_get_identifier();
++//    if(FLAG_SWITCH)
++//    {
++//            printk("Configure ADM699X...\n");
++//            SPI_default();  //Add by jason for ADM699X configuration
++//    }
++      return (0);
++}
++
++
++module_init(gmac_init_module);
++module_exit(gmac_cleanup_module);
++
++static int gmac_phy_thread (void *data)
++{
++      struct net_device   *dev = data;
++      struct gmac_private *tp = dev->priv;
++      unsigned long       timeout;
++
++    daemonize("%s", dev->name);
++      allow_signal(SIGTERM);
++//    reparent_to_init();
++//    spin_lock_irq(&current->sigmask_lock);
++//    sigemptyset(&current->blocked);
++//    recalc_sigpending(current);
++//    spin_unlock_irq(&current->sigmask_lock);
++//    strncpy (current->comm, dev->name, sizeof(current->comm) - 1);
++//    current->comm[sizeof(current->comm) - 1] = '\0';
++
++      while (1)
++      {
++          timeout = next_tick;
++              do
++              {
++                      timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
++              } while (!signal_pending (current) && (timeout > 0));
++
++              if (signal_pending (current))
++              {
++//                    spin_lock_irq(&current->sigmask_lock);
++                      flush_signals(current);
++//                    spin_unlock_irq(&current->sigmask_lock);
++              }
++
++              if (tp->time_to_die)
++                      break;
++
++//        printk("%s : Polling PHY Status...%x\n",__func__,dev);
++              rtnl_lock ();
++        gmac_get_phy_status(dev);
++              rtnl_unlock ();
++      }
++      complete_and_exit (&tp->thr_exited, 0);
++}
++
++static void gmac_set_phy_status(struct net_device *dev)
++{
++    GMAC_STATUS_T   status;
++    unsigned int    reg_val;
++    unsigned int    i = 0;
++    unsigned int    index;
++
++    if (FLAG_SWITCH==1)
++    {
++        return; /* GMAC connects to a switch chip, not PHY */
++    }
++
++    index = gmac_get_dev_index(dev);
++
++    if (index == 0)
++    {
++//            mii_write(phy_addr[index],0x04,0x0461); /* advertisement 10M full duplex, pause capable on */
++//            mii_write(phy_addr[index],0x04,0x0421); /* advertisement 10M half duplex, pause capable on */
++      mii_write(phy_addr[index],0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
++//            mii_write(phy_addr[index],0x04,0x04a1); /* advertisement 100M half duplex, pause capable on */
++#ifdef CONFIG_SL3516_ASIC
++      mii_write(phy_addr[index],0x09,0x0300); /* advertisement 1000M full duplex, pause capable on */
++//            mii_write(phy_addr[index],0x09,0x0000); /* advertisement 1000M full duplex, pause capable on */
++#endif
++    }
++    else
++    {
++//            mii_write(phy_addr[index],0x04,0x0461); /* advertisement 10M full duplex, pause capable on */
++//            mii_write(phy_addr[index],0x04,0x0421); /* advertisement 10M half duplex, pause capable on */
++      mii_write(phy_addr[index],0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
++//            mii_write(phy_addr[index],0x04,0x04a1); /* advertisement 100M half duplex, pause capable on */
++#ifdef CONFIG_SL3516_ASIC
++//            mii_write(phy_addr[index],0x09,0x0000); /* advertisement no 1000M */
++      mii_write(phy_addr[index],0x09,0x0300); /* advertisement 1000M full duplex, pause capable on */
++#endif
++      }
++
++    mii_write(phy_addr[index],0x00,0x1200); /* Enable and Restart Auto-Negotiation */
++    mii_write(phy_addr[index],0x18,0x0041); /* Enable Active led */
++    while (((reg_val=mii_read(phy_addr[index],0x01)) & 0x00000004)!=0x04)
++    {
++        i++;
++        if (i > 30)
++        {
++            break;
++        }
++      msleep(100);
++    }
++    if (i>30)
++    {
++        pre_phy_status[index] = LINK_DOWN;
++              clear_bit(__LINK_STATE_START, &dev->state);
++        netif_stop_queue(dev);
++        storlink_ctl.link = 0;
++        printk("Link Down (%04x) ",reg_val);
++    }
++    else
++    {
++        pre_phy_status[index] = LINK_UP;
++              set_bit(__LINK_STATE_START, &dev->state);
++        netif_wake_queue(dev);
++        storlink_ctl.link = 1;
++        printk("Link Up (%04x) ",reg_val);
++    }
++
++    status.bits32 = 0;
++    reg_val = mii_read(phy_addr[index],10);
++    printk("reg_val0 = %x \n",reg_val);
++    if ((reg_val & 0x0800) == 0x0800)
++    {
++        status.bits.duplex = 1;
++        status.bits.speed = 2;
++        printk(" 1000M/Full \n");
++    }
++    else if ((reg_val & 0x0400) == 0x0400)
++    {
++        status.bits.duplex = 0;
++        status.bits.speed = 2;
++        printk(" 1000M/Half \n");
++    }
++    else
++    {
++        reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
++        printk("reg_val1 = %x \n",reg_val);
++        if ((reg_val & 0x08)==0x08) /* 100M full duplex */
++        {
++                status.bits.duplex = 1;
++                status.bits.speed = 1;
++                printk(" 100M/Full \n");
++        }
++        else if ((reg_val & 0x04)==0x04) /* 100M half duplex */
++        {
++                status.bits.duplex = 0;
++                status.bits.speed = 1;
++                printk(" 100M/Half \n");
++        }
++        else if ((reg_val & 0x02)==0x02) /* 10M full duplex */
++        {
++                status.bits.duplex = 1;
++                status.bits.speed = 0;
++                printk(" 10M/Full \n");
++        }
++        else if ((reg_val & 0x01)==0x01) /* 10M half duplex */
++        {
++                status.bits.duplex = 0;
++                status.bits.speed = 0;
++                printk(" 100M/Half \n");
++        }
++    }
++
++    reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
++    if ((reg_val & 0x20)==0x20)
++    {
++        flow_control_enable[index] = 1;
++        printk("Flow Control Enable. \n");
++    }
++    else
++    {
++        flow_control_enable[index] = 0;
++        printk("Flow Control Disable. \n");
++    }
++    full_duplex = status.bits.duplex;
++    speed = status.bits.speed;
++}
++
++static void gmac_get_phy_status(struct net_device *dev)
++{
++      GMAC_CONFIG0_T  config0,config0_mask;
++    GMAC_STATUS_T   status;
++    unsigned int    reg_val;
++    unsigned int    index;
++
++    index = gmac_select_interface(dev);
++
++    status.bits32 = 0;
++    status.bits.phy_mode = 1;
++
++#ifdef CONFIG_SL3516_ASIC
++    status.bits.mii_rmii = 2;   /* default value for ASIC version */
++//    status.bits.speed = 1;
++#else
++    if (index==0)
++        status.bits.mii_rmii = 0;
++    else
++        status.bits.mii_rmii = 2;
++#endif
++
++    /* read PHY status register */
++    reg_val = mii_read(phy_addr[index],0x01);
++    if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */
++    {
++        /* read PHY Auto-Negotiation Link Partner Ability Register */
++        reg_val = mii_read(phy_addr[index],10);
++        if ((reg_val & 0x0800) == 0x0800)
++        {
++            status.bits.mii_rmii = 3;  /* RGMII 1000Mbps mode */
++            status.bits.duplex = 1;
++            status.bits.speed = 2;
++        }
++        else if ((reg_val & 0x0400) == 0x0400)
++        {
++            status.bits.mii_rmii = 3;  /* RGMII 1000Mbps mode */
++            status.bits.duplex = 0;
++            status.bits.speed = 2;
++        }
++        else
++        {
++            reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
++            if ((reg_val & 0x08)==0x08) /* 100M full duplex */
++            {
++                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
++                    status.bits.duplex = 1;
++                    status.bits.speed = 1;
++            }
++            else if ((reg_val & 0x04)==0x04) /* 100M half duplex */
++            {
++                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
++                    status.bits.duplex = 0;
++                    status.bits.speed = 1;
++            }
++            else if ((reg_val & 0x02)==0x02) /* 10M full duplex */
++            {
++                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
++                    status.bits.duplex = 1;
++                    status.bits.speed = 0;
++            }
++            else if ((reg_val & 0x01)==0x01) /* 10M half duplex */
++            {
++                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
++                    status.bits.duplex = 0;
++                    status.bits.speed = 0;
++            }
++        }
++        status.bits.link = LINK_UP; /* link up */
++        netif_wake_queue(dev);
++
++        reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
++        if ((reg_val & 0x20)==0x20)
++        {
++            if (flow_control_enable[index] == 0)
++            {
++                config0.bits32 = 0;
++                config0_mask.bits32 = 0;
++                config0.bits.tx_fc_en = 1; /* enable tx flow control */
++                config0.bits.rx_fc_en = 1; /* enable rx flow control */
++                config0_mask.bits.tx_fc_en = 1;
++                config0_mask.bits.rx_fc_en = 1;
++                gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++//                printk("eth%d Flow Control Enable. \n",index);
++            }
++            flow_control_enable[index] = 1;
++        }
++        else
++        {
++            if (flow_control_enable[index] == 1)
++            {
++                config0.bits32 = 0;
++                config0_mask.bits32 = 0;
++                config0.bits.tx_fc_en = 0; /* disable tx flow control */
++                config0.bits.rx_fc_en = 0; /* disable rx flow control */
++                config0_mask.bits.tx_fc_en = 1;
++                config0_mask.bits.rx_fc_en = 1;
++                gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++//                printk("eth%d Flow Control Disable. \n",index);
++            }
++            flow_control_enable[index] = 0;
++        }
++
++        if (pre_phy_status[index] == LINK_DOWN)
++        {
++            gmac_enable_tx_rx(dev);
++            pre_phy_status[index] = LINK_UP;
++                      set_bit(__LINK_STATE_START, &dev->state);
++                      storlink_ctl.link = 1;
++//                    printk("eth%d Link Up ...\n",index);
++        }
++    }
++    else
++    {
++        status.bits.link = LINK_DOWN; /* link down */
++        netif_stop_queue(dev);
++        flow_control_enable[index] = 0;
++        storlink_ctl.link = 0;
++        if (pre_phy_status[index] == LINK_UP)
++        {
++            gmac_disable_tx_rx(dev);
++            pre_phy_status[index] = LINK_DOWN;
++                      clear_bit(__LINK_STATE_START, &dev->state);
++//                    printk("eth%d Link Down ...\n",index);
++      }
++
++    }
++
++    reg_val = gmac_read_reg(gmac_base_addr[index] + GMAC_STATUS);
++    if (reg_val != status.bits32)
++    {
++        gmac_write_reg(gmac_base_addr[index] + GMAC_STATUS,status.bits32,0x0000007f);
++    }
++}
++
++/***************************************/
++/* define GPIO module base address     */
++/***************************************/
++#define GPIO_BASE_ADDR  (IO_ADDRESS(SL2312_GPIO_BASE))
++
++/* define GPIO pin for MDC/MDIO */
++
++// for gemini ASIC
++#ifdef CONFIG_SL3516_ASIC
++#define H_MDC_PIN           22
++#define H_MDIO_PIN          21
++#define G_MDC_PIN           22
++#define G_MDIO_PIN          21
++#else
++#define H_MDC_PIN           3
++#define H_MDIO_PIN          2
++#define G_MDC_PIN           0
++#define G_MDIO_PIN          1
++#endif
++
++//#define GPIO_MDC             0x80000000
++//#define GPIO_MDIO            0x00400000
++
++static unsigned int GPIO_MDC = 0;
++static unsigned int GPIO_MDIO = 0;
++static unsigned int GPIO_MDC_PIN = 0;
++static unsigned int GPIO_MDIO_PIN = 0;
++
++// For PHY test definition!!
++#define LPC_EECK              0x02
++#define LPC_EDIO              0x04
++#define LPC_GPIO_SET          3
++#define LPC_BASE_ADDR         IO_ADDRESS(IT8712_IO_BASE)
++#define inb_gpio(x)           inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
++#define outb_gpio(x, y)               outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
++
++enum GPIO_REG
++{
++    GPIO_DATA_OUT   = 0x00,
++    GPIO_DATA_IN    = 0x04,
++    GPIO_PIN_DIR    = 0x08,
++    GPIO_BY_PASS    = 0x0c,
++    GPIO_DATA_SET   = 0x10,
++    GPIO_DATA_CLEAR = 0x14,
++};
++/***********************/
++/*    MDC : GPIO[31]   */
++/*    MDIO: GPIO[22]   */
++/***********************/
++
++/***************************************************
++* All the commands should have the frame structure:
++*<PRE><ST><OP><PHYAD><REGAD><TA><DATA><IDLE>
++****************************************************/
++
++/*****************************************************************
++* Inject a bit to NWay register through CSR9_MDC,MDIO
++*******************************************************************/
++void mii_serial_write(char bit_MDO) // write data into mii PHY
++{
++#if 0 //def CONFIG_SL2312_LPC_IT8712
++      unsigned char iomode,status;
++
++      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
++      iomode |= (LPC_EECK|LPC_EDIO) ;                         // Set EECK,EDIO,EECS output
++      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
++
++      if(bit_MDO)
++      {
++              status = inb_gpio( LPC_GPIO_SET);
++              status |= LPC_EDIO ;            //EDIO high
++              outb_gpio(LPC_GPIO_SET, status);
++      }
++      else
++      {
++              status = inb_gpio( LPC_GPIO_SET);
++              status &= ~(LPC_EDIO) ;         //EDIO low
++              outb_gpio(LPC_GPIO_SET, status);
++      }
++
++      status |= LPC_EECK ;            //EECK high
++      outb_gpio(LPC_GPIO_SET, status);
++
++      status &= ~(LPC_EECK) ;         //EECK low
++      outb_gpio(LPC_GPIO_SET, status);
++
++#else
++    unsigned int addr;
++    unsigned int value;
++
++    addr = GPIO_BASE_ADDR + GPIO_PIN_DIR;
++    value = readl(addr) | GPIO_MDC | GPIO_MDIO; /* set MDC/MDIO Pin to output */
++    writel(value,addr);
++    if(bit_MDO)
++    {
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++        writel(GPIO_MDIO,addr); /* set MDIO to 1 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++        writel(GPIO_MDC,addr); /* set MDC to 1 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++        writel(GPIO_MDC,addr); /* set MDC to 0 */
++    }
++    else
++    {
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++        writel(GPIO_MDIO,addr); /* set MDIO to 0 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++        writel(GPIO_MDC,addr); /* set MDC to 1 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++        writel(GPIO_MDC,addr); /* set MDC to 0 */
++    }
++
++#endif
++}
++
++/**********************************************************************
++* read a bit from NWay register through CSR9_MDC,MDIO
++***********************************************************************/
++unsigned int mii_serial_read(void) // read data from mii PHY
++{
++#if 0 //def CONFIG_SL2312_LPC_IT8712
++      unsigned char iomode,status;
++      unsigned int value ;
++
++      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
++      iomode &= ~(LPC_EDIO) ;         // Set EDIO input
++      iomode |= (LPC_EECK) ;          // Set EECK,EECS output
++      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
++
++      status = inb_gpio( LPC_GPIO_SET);
++      status |= LPC_EECK ;            //EECK high
++      outb_gpio(LPC_GPIO_SET, status);
++
++      status &= ~(LPC_EECK) ;         //EECK low
++      outb_gpio(LPC_GPIO_SET, status);
++
++      value = inb_gpio( LPC_GPIO_SET);
++
++      value = value>>2 ;
++      value &= 0x01;
++
++      return value ;
++
++#else
++    unsigned int *addr;
++    unsigned int value;
++
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_PIN_DIR);
++    value = readl(addr) & ~GPIO_MDIO; //0xffbfffff;   /* set MDC to output and MDIO to input */
++    writel(value,addr);
++
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);
++    writel(GPIO_MDC,addr); /* set MDC to 1 */
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++    writel(GPIO_MDC,addr); /* set MDC to 0 */
++
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_IN);
++    value = readl(addr);
++    value = (value & (1<<GPIO_MDIO_PIN)) >> GPIO_MDIO_PIN;
++    return(value);
++
++#endif
++}
++
++/***************************************
++* preamble + ST
++***************************************/
++void mii_pre_st(void)
++{
++    unsigned char i;
++
++    for(i=0;i<32;i++) // PREAMBLE
++        mii_serial_write(1);
++    mii_serial_write(0); // ST
++    mii_serial_write(1);
++}
++
++
++/******************************************
++* Read MII register
++* phyad -> physical address
++* regad -> register address
++***************************************** */
++unsigned int mii_read(unsigned char phyad,unsigned char regad)
++{
++    unsigned int i,value;
++    unsigned int bit;
++
++    if (phyad == GPHY_ADDR)
++    {
++        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
++        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
++    }
++    else
++    {
++        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
++        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
++    }
++    GPIO_MDC = (1<<GPIO_MDC_PIN);
++    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
++
++    mii_pre_st(); // PRE+ST
++    mii_serial_write(1); // OP
++    mii_serial_write(0);
++
++    for (i=0;i<5;i++) { // PHYAD
++        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++
++    for (i=0;i<5;i++) { // REGAD
++        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++
++    mii_serial_read(); // TA_Z
++//    if((bit=mii_serial_read()) !=0 ) // TA_0
++//    {
++//        return(0);
++//    }
++    value=0;
++    for (i=0;i<16;i++) { // READ DATA
++        bit=mii_serial_read();
++        value += (bit<<(15-i)) ;
++    }
++
++    mii_serial_write(0); // dumy clock
++    mii_serial_write(0); // dumy clock
++//printk("%s: phy_addr=%x reg_addr=%x value=%x \n",__func__,phyad,regad,value);
++    return(value);
++}
++
++/******************************************
++* Write MII register
++* phyad -> physical address
++* regad -> register address
++* value -> value to be write
++***************************************** */
++void mii_write(unsigned char phyad,unsigned char regad,unsigned int value)
++{
++    unsigned int i;
++    char bit;
++
++printk("%s: phy_addr=%x reg_addr=%x value=%x \n",__func__,phyad,regad,value);
++    if (phyad == GPHY_ADDR)
++    {
++        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
++        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
++    }
++    else
++    {
++        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
++        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
++    }
++    GPIO_MDC = (1<<GPIO_MDC_PIN);
++    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
++
++    mii_pre_st(); // PRE+ST
++    mii_serial_write(0); // OP
++    mii_serial_write(1);
++    for (i=0;i<5;i++) { // PHYAD
++        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++
++    for (i=0;i<5;i++) { // REGAD
++        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++    mii_serial_write(1); // TA_1
++    mii_serial_write(0); // TA_0
++
++    for (i=0;i<16;i++) { // OUT DATA
++        bit= ((value>>(15-i)) & 0x01) ? 1 : 0 ;
++        mii_serial_write(bit);
++    }
++    mii_serial_write(0); // dumy clock
++    mii_serial_write(0); // dumy clock
++}
++
++
++
++
++
++
++
++
++
++/*                            NOTES
++ *   The instruction set of the 93C66/56/46/26/06 chips are as follows:
++ *
++ *               Start  OP        *
++ *     Function   Bit  Code  Address**  Data     Description
++ *     -------------------------------------------------------------------
++ *     READ        1    10   A7 - A0             Reads data stored in memory,
++ *                                               starting at specified address
++ *     EWEN        1    00   11XXXXXX            Write enable must precede
++ *                                               all programming modes
++ *     ERASE       1    11   A7 - A0             Erase register A7A6A5A4A3A2A1A0
++ *     WRITE       1    01   A7 - A0   D15 - D0  Writes register
++ *     ERAL        1    00   10XXXXXX            Erase all registers
++ *     WRAL        1    00   01XXXXXX  D15 - D0  Writes to all registers
++ *     EWDS        1    00   00XXXXXX            Disables all programming
++ *                                               instructions
++ *    *Note: A value of X for address is a don't care condition.
++ *    **Note: There are 8 address bits for the 93C56/66 chips unlike
++ *          the 93C46/26/06 chips which have 6 address bits.
++ *
++ *   The 93Cx6 has a four wire interface: clock, chip select, data in, and
++ *   data out.While the ADM6996 uning three interface: clock, chip select,and data line.
++ *   The input and output are the same pin. ADM6996 can only recognize the write cmd.
++ *   In order to perform above functions, you need
++ *   1. to enable the chip select .
++ *   2. send one clock of dummy clock
++ *   3. send start bit and opcode
++ *   4. send 8 bits address and 16 bits data
++ *   5. to disable the chip select.
++ *                                                    Jason Lee 2003/07/30
++ */
++
++/***************************************/
++/* define GPIO module base address     */
++/***************************************/
++#define GPIO_EECS          0x00400000         /*   EECS: GPIO[22]   */
++//#define GPIO_MOSI        0x20000000         /*   EEDO: GPIO[29]   send to 6996*/
++#define GPIO_MISO          0x40000000         /*   EEDI: GPIO[30]   receive from 6996*/
++#define GPIO_EECK          0x80000000         /*   EECK: GPIO[31]   */
++
++#define ADM_EECS              0x01
++#define ADM_EECK              0x02
++#define ADM_EDIO              0x04
++/*************************************************************
++* SPI protocol for ADM6996 control
++**************************************************************/
++#define SPI_OP_LEN         0x03               // the length of start bit and opcode
++#define SPI_OPWRITE        0X05               // write
++#define SPI_OPREAD         0X06               // read
++#define SPI_OPERASE        0X07               // erase
++#define SPI_OPWTEN         0X04               // write enable
++#define SPI_OPWTDIS        0X04               // write disable
++#define SPI_OPERSALL       0X04               // erase all
++#define SPI_OPWTALL        0X04               // write all
++
++#define SPI_ADD_LEN        8                  // bits of Address
++#define SPI_DAT_LEN        16                 // bits of Data
++#define ADM6996_PORT_NO            6                  // the port number of ADM6996
++#define ADM6999_PORT_NO            9                  // the port number of ADM6999
++#ifdef CONFIG_ADM_6996
++      #define ADM699X_PORT_NO         ADM6996_PORT_NO
++#endif
++#ifdef CONFIG_ADM_6999
++      #define ADM699X_PORT_NO         ADM6999_PORT_NO
++#endif
++#define LPC_GPIO_SET          3
++#define LPC_BASE_ADDR                 IO_ADDRESS(IT8712_IO_BASE)
++
++extern int it8712_exist;
++
++#define inb_gpio(x)                   inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
++#define outb_gpio(x, y)               outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
++
++/****************************************/
++/*    Function Declare                */
++/****************************************/
++/*
++void SPI_write(unsigned char addr,unsigned int value);
++unsigned int SPI_read(unsigned char table,unsigned char addr);
++void SPI_write_bit(char bit_EEDO);
++unsigned int SPI_read_bit(void);
++void SPI_default(void);
++void SPI_reset(unsigned char rstype,unsigned char port_cnt);
++void SPI_pre_st(void);
++void SPI_CS_enable(unsigned char enable);
++void SPI_Set_VLAN(unsigned char LAN,unsigned int port_mask);
++void SPI_Set_tag(unsigned int port,unsigned tag);
++void SPI_Set_PVID(unsigned int PVID,unsigned int port_mask);
++void SPI_mac_lock(unsigned int port, unsigned char lock);
++void SPI_get_port_state(unsigned int port);
++void SPI_port_enable(unsigned int port,unsigned char enable);
++
++void SPI_get_status(unsigned int port);
++*/
++
++struct PORT_CONFIG
++{
++      unsigned char auto_negotiation; // 0:Disable    1:Enable
++      unsigned char speed;            // 0:10M        1:100M
++      unsigned char duplex;           // 0:Half       1:Full duplex
++      unsigned char Tag;              // 0:Untag      1:Tag
++      unsigned char port_disable;     // 0:port enable        1:disable
++      unsigned char pvid;             // port VLAN ID 0001
++      unsigned char mdix;             // Crossover judgement. 0:Disable 1:Enable
++      unsigned char mac_lock;         // MAC address Lock 0:Disable 1:Enable
++};
++
++struct PORT_STATUS
++{
++      unsigned char link;             // 0:not link   1:link established
++      unsigned char speed;            // 0:10M        1:100M
++      unsigned char duplex;           // 0:Half       1:Full duplex
++      unsigned char flow_ctl;         // 0:flow control disable 1:enable
++      unsigned char mac_lock;         // MAC address Lock 0:Disable 1:Enable
++      unsigned char port_disable;     // 0:port enable        1:disable
++
++      // Serial Management
++      unsigned long rx_pac_count;             //receive packet count
++      unsigned long rx_pac_byte;              //receive packet byte count
++      unsigned long tx_pac_count;             //transmit packet count
++      unsigned long tx_pac_byte;              //transmit packet byte count
++      unsigned long collision_count;          //error count
++      unsigned long error_count ;
++
++      unsigned long rx_pac_count_overflow;            //overflow flag
++      unsigned long rx_pac_byte_overflow;
++      unsigned long tx_pac_count_overflow;
++      unsigned long tx_pac_byte_overflow;
++      unsigned long collision_count_overflow;
++      unsigned long error_count_overflow;
++};
++
++struct PORT_CONFIG port_config[ADM699X_PORT_NO];      // 0~3:LAN , 4:WAN , 5:MII
++static struct PORT_STATUS port_state[ADM699X_PORT_NO];
++
++/******************************************
++* SPI_write
++* addr -> Write Address
++* value -> value to be write
++***************************************** */
++void SPI_write(unsigned char addr,unsigned int value)
++{
++      int     i;
++      char    bit;
++#ifdef CONFIG_IT8712_GPIO
++      char    status;
++#else
++    int     ad1;
++#endif
++
++#ifdef CONFIG_IT8712_GPIO
++      status = inb_gpio(LPC_GPIO_SET);
++      status &= ~(ADM_EDIO) ;         //EDIO low
++      outb_gpio(LPC_GPIO_SET, status);
++#else
++      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++      writel(GPIO_MISO,ad1); /* set MISO to 0 */
++#endif
++      SPI_CS_enable(1);
++
++      SPI_write_bit(0);       //dummy clock
++
++      //send write command (0x05)
++      for(i=SPI_OP_LEN-1;i>=0;i--)
++      {
++              bit = (SPI_OPWRITE>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++      // send 8 bits address (MSB first, LSB last)
++      for(i=SPI_ADD_LEN-1;i>=0;i--)
++      {
++              bit = (addr>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++      // send 16 bits data (MSB first, LSB last)
++      for(i=SPI_DAT_LEN-1;i>=0;i--)
++      {
++              bit = (value>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++
++      SPI_CS_enable(0);       // CS low
++
++      for(i=0;i<0xFFF;i++) ;
++#ifdef CONFIG_IT8712_GPIO
++      status = inb_gpio(LPC_GPIO_SET);
++      status &= ~(ADM_EDIO) ;         //EDIO low
++      outb_gpio(LPC_GPIO_SET, status);
++#else
++      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++      writel(GPIO_MISO,ad1); /* set MISO to 0 */
++#endif
++}
++
++
++/************************************
++* SPI_write_bit
++* bit_EEDO -> 1 or 0 to be written
++************************************/
++void SPI_write_bit(char bit_EEDO)
++{
++#ifdef CONFIG_IT8712_GPIO
++      unsigned char iomode,status;
++
++      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
++      iomode |= (ADM_EECK|ADM_EDIO|ADM_EECS) ;                                // Set EECK,EDIO,EECS output
++      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
++
++      if(bit_EEDO)
++      {
++              status = inb_gpio( LPC_GPIO_SET);
++              status |= ADM_EDIO ;            //EDIO high
++              outb_gpio(LPC_GPIO_SET, status);
++      }
++      else
++      {
++              status = inb_gpio( LPC_GPIO_SET);
++              status &= ~(ADM_EDIO) ;         //EDIO low
++              outb_gpio(LPC_GPIO_SET, status);
++      }
++
++      status |= ADM_EECK ;            //EECK high
++      outb_gpio(LPC_GPIO_SET, status);
++
++      status &= ~(ADM_EECK) ;         //EECK low
++      outb_gpio(LPC_GPIO_SET, status);
++
++#else
++      unsigned int addr;
++      unsigned int value;
++
++      addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);
++      value = readl(addr) |GPIO_EECK |GPIO_MISO ;   /* set EECK/MISO Pin to output */
++      writel(value,addr);
++      if(bit_EEDO)
++      {
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++              writel(GPIO_MISO,addr); /* set MISO to 1 */
++              writel(GPIO_EECK,addr); /* set EECK to 1 */
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++              writel(GPIO_EECK,addr); /* set EECK to 0 */
++      }
++      else
++      {
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++              writel(GPIO_MISO,addr); /* set MISO to 0 */
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++              writel(GPIO_EECK,addr); /* set EECK to 1 */
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++              writel(GPIO_EECK,addr); /* set EECK to 0 */
++      }
++
++      return ;
++#endif
++}
++
++/**********************************************************************
++* read a bit from ADM6996 register
++***********************************************************************/
++unsigned int SPI_read_bit(void) // read data from
++{
++#ifdef CONFIG_IT8712_GPIO
++      unsigned char iomode,status;
++      unsigned int value ;
++
++      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
++      iomode &= ~(ADM_EDIO) ;         // Set EDIO input
++      iomode |= (ADM_EECS|ADM_EECK) ;         // Set EECK,EECS output
++      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
++
++      status = inb_gpio( LPC_GPIO_SET);
++      status |= ADM_EECK ;            //EECK high
++      outb_gpio(LPC_GPIO_SET, status);
++
++      status &= ~(ADM_EECK) ;         //EECK low
++      outb_gpio(LPC_GPIO_SET, status);
++
++      value = inb_gpio( LPC_GPIO_SET);
++
++      value = value>>2 ;
++      value &= 0x01;
++
++      return value ;
++#else
++      unsigned int addr;
++      unsigned int value;
++
++      addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);
++      value = readl(addr) & (~GPIO_MISO);   // set EECK to output and MISO to input
++      writel(value,addr);
++
++      addr =(GPIO_BASE_ADDR + GPIO_DATA_SET);
++      writel(GPIO_EECK,addr); // set EECK to 1
++      addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++      writel(GPIO_EECK,addr); // set EECK to 0
++
++      addr = (GPIO_BASE_ADDR + GPIO_DATA_IN);
++      value = readl(addr) ;
++      value = value >> 30;
++      return value ;
++#endif
++}
++
++/******************************************
++* SPI_default
++* EEPROM content default value
++*******************************************/
++void SPI_default(void)
++{
++      int i;
++#ifdef CONFIG_ADM_6999
++      SPI_write(0x11,0xFF30);
++      for(i=1;i<8;i++)
++              SPI_write(i,0x840F);
++
++      SPI_write(0x08,0x880F);                 //port 8 Untag, PVID=2
++      SPI_write(0x09,0x881D);                 //port 9 Tag, PVID=2 ,10M
++      SPI_write(0x14,0x017F);                 //Group 0~6,8 as VLAN 1
++      SPI_write(0x15,0x0180);                 //Group 7,8 as VLAN 2
++#endif
++
++#ifdef CONFIG_ADM_6996
++      SPI_write(0x11,0xFF30);
++      SPI_write(0x01,0x840F);                 //port 0~3 Untag ,PVID=1 ,100M ,duplex
++      SPI_write(0x03,0x840F);
++      SPI_write(0x05,0x840F);
++      SPI_write(0x07,0x840F);
++      SPI_write(0x08,0x880F);                 //port 4 Untag, PVID=2
++      SPI_write(0x09,0x881D);                 //port 5 Tag, PVID=2 ,10M
++      SPI_write(0x14,0x0155);                 //Group 0~3,5 as VLAN 1
++      SPI_write(0x15,0x0180);                 //Group 4,5 as VLAN 2
++
++#endif
++
++      for(i=0x16;i<=0x22;i++)
++              SPI_write((unsigned char)i,0x0000);             // clean VLAN¡@map 3~15
++
++      for (i=0;i<NUM_VLAN_IF;i++)                             // Set VLAN ID map 1,2
++              SPI_Set_PVID( VLAN_conf[i].vid,  VLAN_conf[i].portmap);
++
++      for(i=0;i<ADM699X_PORT_NO;i++)                          // reset count
++              SPI_reset(0,i);
++}
++
++/*************************************************
++* SPI_reset
++* rstype -> reset type
++*         0:reset all count for 'port_cnt' port
++*         1:reset specified count 'port_cnt'
++* port_cnt   ->  port number or counter index
++***************************************************/
++void SPI_reset(unsigned char rstype,unsigned char port_cnt)
++{
++
++      int i;
++#ifdef CONFIG_IT8712_GPIO
++    char status;
++#else
++      int ad1;
++#endif
++      char bit;
++
++#ifdef CONFIG_IT8712_GPIO
++      status = inb_gpio(LPC_GPIO_SET);
++      status &= ~(ADM_EDIO) ;         //EDIO low
++      outb_gpio(LPC_GPIO_SET, status);
++#else
++      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++      writel(GPIO_MISO,ad1); /* set MISO to 0 */
++#endif
++
++      SPI_CS_enable(0);       // CS low
++
++      SPI_pre_st(); // PRE+ST
++      SPI_write_bit(0); // OP
++      SPI_write_bit(1);
++
++      SPI_write_bit(1);               // Table select, must be 1 -> reset Counter
++
++      SPI_write_bit(0);               // Device Address
++      SPI_write_bit(0);
++
++      rstype &= 0x01;
++      SPI_write_bit(rstype);          // Reset type 0:clear dedicate port's all counters 1:clear dedicate counter
++
++      for (i=5;i>=0;i--)              // port or cnt index
++      {
++              bit = port_cnt >> i ;
++              bit &= 0x01 ;
++              SPI_write_bit(bit);
++      }
++
++      SPI_write_bit(0);               // dumy clock
++      SPI_write_bit(0);               // dumy clock
++
++#ifdef CONFIG_IT8712_GPIO
++      status = inb_gpio(LPC_GPIO_SET);
++      status &= ~(ADM_EDIO) ;         //EDIO low
++      outb_gpio(LPC_GPIO_SET, status);
++#else
++      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++      writel(GPIO_MISO,ad1); /* set MISO to 0 */
++#endif
++}
++
++/*****************************************************
++* SPI_pre_st
++* preambler: 32 bits '1'   start bit: '01'
++*****************************************************/
++void SPI_pre_st(void)
++{
++      int i;
++
++      for(i=0;i<32;i++) // PREAMBLE
++              SPI_write_bit(1);
++      SPI_write_bit(0); // ST
++      SPI_write_bit(1);
++}
++
++
++/***********************************************************
++* SPI_CS_enable
++* before access ,you have to enable Chip Select. (pull high)
++* When fisish, you should pull low !!
++*************************************************************/
++void SPI_CS_enable(unsigned char enable)
++{
++#ifdef CONFIG_IT8712_GPIO
++
++      unsigned char iomode,status;
++
++      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
++      iomode |= (ADM_EECK|ADM_EDIO|ADM_EECS) ;                                // Set EECK,EDIO,EECS output
++      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
++
++
++      status = inb_gpio( LPC_GPIO_SET);
++      if(enable)
++              status |= ADM_EECS ;            //EECS high
++      else
++              status &= ~(ADM_EECS) ; //EECS low
++
++      outb_gpio(LPC_GPIO_SET, status);
++
++
++      status |= ADM_EECK ;            //EECK high
++      outb_gpio(LPC_GPIO_SET, status);
++
++      status &= ~(ADM_EECK) ;         //EECK low
++      outb_gpio(LPC_GPIO_SET, status);
++
++#else
++      unsigned int addr,value;
++
++      addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);
++      value = readl(addr) |GPIO_EECS |GPIO_EECK;   /* set EECS/EECK Pin to output */
++      writel(value,addr);
++
++      if(enable)
++      {
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++              writel(GPIO_EECS,addr); /* set EECS to 1 */
++
++      }
++      else
++      {
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++              writel(GPIO_EECS,addr); /* set EECS to 0 */
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++              writel(GPIO_EECK,addr); /* set EECK to 1 */     // at least one clock after CS low
++              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++              writel(GPIO_EECK,addr); /* set EECK to 0 */
++      }
++#endif
++}
++
++/*********************************************************
++* SPI_Set_VLAN: group ports as VLAN
++* LAN  -> VLAN number : 0~16
++* port_mask -> ports which would group as LAN
++*            ex. 0x03 = 0000 0011
++*                     port 0 and port 1
++*********************************************************/
++void SPI_Set_VLAN(unsigned char LAN,unsigned int port_mask)
++{
++      unsigned int i,value=0;
++      unsigned reg_add = 0x13 + LAN ;
++
++      for(i=0;i<ADM6996_PORT_NO;i++)
++      {       if(port_mask&0x01)
++              {
++                      switch(i)
++                      {
++                              case 0: value|=0x0001;  break;  //port0:bit[0]
++                              case 1: value|=0x0004;  break;  //port1:bit[2]
++                              case 2: value|=0x0010;  break;  //port2:bit[4]
++                              case 3: value|=0x0040;  break;  //port3:bit[6]
++                              case 4: value|=0x0080;  break;  //port4:bit[7]
++                              case 5: value|=0x0100;  break;  //port5:bit[8]
++                      }
++              }
++              port_mask >>= 1;
++      }
++
++      SPI_write(reg_add,value);
++}
++
++
++/*******************************************
++* SPI_Set_tag
++* port -> port number to set tag or untag
++* tag  -> 0/set untag,  1/set tag
++* In general, tag is for MII port. LAN and
++* WAN port is configed as untag!!
++********************************************/
++void SPI_Set_tag(unsigned int port,unsigned tag)
++{
++      unsigned int regadd,value;
++
++      // mapping port's register !! (0,1,2,3,4,5) ==> (1,3,5,7,8,9)
++      if(port<=3)
++              regadd=2*port+1;
++      else if(port==4) regadd = 8 ;
++      else regadd = 9 ;
++
++
++      value = SPI_read(0,regadd);             //read original setting
++
++      if(tag)
++              value |= 0x0010 ;               // set tag
++      else
++              value &= 0xFFEF ;               // set untag
++
++      SPI_write(regadd,value);                // write back!!
++}
++
++/************************************************
++* SPI_Set_PVID
++* PVID -> PVID number :
++* port_mask -> ports which would group as LAN
++*            ex. 0x0F = 0000 1111 ==> port 0~3
++************************************************/
++void SPI_Set_PVID(unsigned int PVID,unsigned int port_mask)
++{
++      unsigned int i,value=0;
++
++      PVID &= 0x000F ;
++
++      for(i=0;i<ADM699X_PORT_NO;i++)
++      {       if(port_mask&0x01)
++              {
++#ifdef CONFIG_ADM_6996
++                      switch(i)
++                      {
++                              case 0:
++                                      value = SPI_read(0,0x01);       // read original value
++                                      value &= 0xC3FF ;                       //set PVIC column as 0 first
++                                      value |= PVID << 10 ;           //Set PVID column as PVID
++                                      SPI_write(0x01,value);          //write back
++                                      break;
++                              case 1:
++                                      value = SPI_read(0,0x03);
++                                      value &= 0xC3FF ;
++                                      value |= PVID << 10 ;
++                                      SPI_write(0x03,value);
++                                      break;
++                              case 2:
++                                      value = SPI_read(0,0x05);
++                                      value &= 0xC3FF ;
++                                      value |= PVID << 10 ;
++                                      SPI_write(0x05,value);
++                                      break;
++                              case 3:
++                                      value = SPI_read(0,0x07);
++                                      value &= 0xC3FF ;
++                                      value |= PVID << 10 ;
++                                      SPI_write(0x07,value);
++                                      break;
++                              case 4:
++                                      value = SPI_read(0,0x08);
++                                      value &= 0xC3FF ;
++                                      value |= PVID << 10 ;
++                                      SPI_write(0x08,value);
++                                      break;
++                              case 5:
++                                      value = SPI_read(0,0x09);
++                                      value &= 0xC3FF ;
++                                      value |= PVID << 10 ;
++                                      SPI_write(0x09,value);
++                                      break;
++                      }
++#endif
++#ifdef CONFIG_ADM_6999
++                      value = SPI_read(0,(unsigned char)i+1);
++                      value &= 0xC3FF ;
++                      value |= PVID << 10 ;
++                      SPI_write((unsigned char)i+1,value);
++#endif
++              }
++              port_mask >>= 1;
++      }
++}
++
++
++/************************************************
++* SPI_get_PVID
++* port -> which ports to VID
++************************************************/
++unsigned int SPI_Get_PVID(unsigned int port)
++{
++      unsigned int value=0;
++
++      if (port>=ADM6996_PORT_NO)
++              return 0;
++
++      switch(port)
++      {
++              case 0:
++                      value = SPI_read(0,0x01);       // read original value
++                      value &= 0x3C00 ;               // get VID
++                      value = value >> 10 ;           // Shift
++                      break;
++              case 1:
++                      value = SPI_read(0,0x03);
++                      value &= 0x3C00 ;
++                      value = value >> 10 ;
++                      break;
++              case 2:
++                      value = SPI_read(0,0x05);
++                      value &= 0x3C00 ;
++                      value = value >> 10 ;
++                      break;
++              case 3:
++                      value = SPI_read(0,0x07);
++                      value &= 0x3C00 ;
++                      value = value >> 10 ;
++                      break;
++              case 4:
++                      value = SPI_read(0,0x08);
++                      value &= 0x3C00 ;
++                      value = value >> 10 ;
++                      break;
++              case 5:
++                      value = SPI_read(0,0x09);
++                      value &= 0x3C00 ;
++                      value = value >> 10 ;
++                      break;
++      }
++      return value ;
++}
++
++
++/**********************************************
++* SPI_mac_clone
++* port -> the port which will lock or unlock
++* lock -> 0/the port will be unlock
++*       1/the port will be locked
++**********************************************/
++void SPI_mac_lock(unsigned int port, unsigned char lock)
++{
++      unsigned int i,value=0;
++
++      value = SPI_read(0,0x12);               // read original
++
++      for(i=0;i<ADM6996_PORT_NO;i++)
++      {       if(lock)                                // lock port
++              {
++                      switch(port)
++                      {
++                              case 0: value|=0x0001;  break;  //port0:bit[0]
++                              case 1: value|=0x0004;  break;  //port1:bit[2]
++                              case 2: value|=0x0010;  break;  //port2:bit[4]
++                              case 3: value|=0x0040;  break;  //port3:bit[6]
++                              case 4: value|=0x0080;  break;  //port4:bit[7]
++                              case 5: value|=0x0100;  break;  //port5:bit[8]
++                      }
++              }
++              else
++              {
++                      switch(i)                       // unlock port
++                      {
++                              case 0: value&=0xFFFE;  break;
++                              case 1: value&=0xFFFB;  break;
++                              case 2: value&=0xFFEF;  break;
++                              case 3: value&=0xFFBF;  break;
++                              case 4: value&=0xFF7F;  break;
++                              case 5: value&=0xFEFF;  break;
++                      }
++              }
++      }
++
++      SPI_write(0x12,value);
++}
++
++
++/***************************************************
++* SPI_learn_pause
++* pause = 01-80-c2-00-00-01
++* DA=distination address
++* forward -> 0: if DA == pause then drop and stop mac learning
++*          1: if DA == pause ,then forward it
++***************************************************/
++void SPI_pause_cmd_forward(unsigned char forward)
++{
++      unsigned int value=0;
++
++      value = SPI_read(0,0x2C);               // read original setting
++      if(forward)
++              value |= 0x2000;                // set bit[13] '1'
++      else
++              value &= 0xDFFF;                // set bit[13] '0'
++
++      SPI_write(0x2C,value);
++
++}
++
++
++/************************************************
++* SPI_read
++* table -> which table to be read: 1/count  0/EEPROM
++* addr  -> Address to be read
++* return : Value of the register
++*************************************************/
++unsigned int SPI_read(unsigned char table,unsigned char addr)
++{
++      int i ;
++      unsigned int value=0;
++      unsigned int bit;
++#ifdef CONFIG_IT8712_GPIO
++      unsigned char status;
++#else
++    unsigned int ad1;
++#endif
++
++#ifdef CONFIG_IT8712_GPIO
++      status = inb_gpio(LPC_GPIO_SET);
++      status &= ~(ADM_EDIO) ;         //EDIO low
++      outb_gpio(LPC_GPIO_SET, status);
++#else
++      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++      writel(GPIO_MISO,ad1); /* set MISO to 0 */
++#endif
++
++      SPI_CS_enable(0);
++
++      SPI_pre_st(); // PRE+ST
++      SPI_write_bit(1); // OPCODE '10' for read
++      SPI_write_bit(0);
++
++      (table==1) ? SPI_write_bit(1) : SPI_write_bit(0) ;      // table select
++
++      SPI_write_bit(0);               // Device Address
++      SPI_write_bit(0);
++
++
++      // send 7 bits address to be read
++      for (i=6;i>=0;i--) {
++              bit= ((addr>>i) & 0x01) ? 1 :0 ;
++              SPI_write_bit(bit);
++      }
++
++
++      // turn around
++      SPI_read_bit(); // TA_Z
++
++      value=0;
++      for (i=31;i>=0;i--) { // READ DATA
++              bit=SPI_read_bit();
++              value |= bit << i ;
++      }
++
++      SPI_read_bit(); // dumy clock
++      SPI_read_bit(); // dumy clock
++
++      if(!table)                                      // EEPROM, only fetch 16 bits data
++      {
++          if(addr&0x01)                               // odd number content (register,register-1)
++                  value >>= 16 ;                      // so we remove the rear 16bits
++          else                                        // even number content (register+1,register),
++                  value &= 0x0000FFFF ;               // so we keep the rear 16 bits
++      }
++
++
++      SPI_CS_enable(0);
++
++#ifdef CONFIG_IT8712_GPIO
++      status = inb_gpio(LPC_GPIO_SET);
++      status &= ~(ADM_EDIO) ;         //EDIO low
++      outb_gpio(LPC_GPIO_SET, status);
++#else
++      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++      writel(GPIO_MISO,ad1); /* set MISO to 0 */
++#endif
++
++      return(value);
++
++}
++
++
++
++/**************************************************
++* SPI_port_en
++* port -> Number of port to config
++* enable -> 1/ enable this port
++*         0/ disable this port
++**************************************************/
++void SPI_port_enable(unsigned int port,unsigned char enable)
++{
++      unsigned int reg_val ;
++      unsigned char reg_add ;
++
++      if(port<=3)
++              reg_add=2*port+1;
++      else if(port==4) reg_add = 8 ;
++      else reg_add = 9 ;
++
++      reg_val = SPI_read(0,reg_add);
++      if(enable)
++      {
++              reg_val &= 0xFFDF ;
++              SPI_write(reg_add,reg_val);
++      }
++      else
++      {
++              reg_val |= 0x0020 ;
++              SPI_write(reg_add,reg_val);
++      }
++}
++
++/********************************************************
++* get port status
++* port -> specify the port number to get configuration
++*********************************************************/
++void SPI_get_status(unsigned int port)
++{
++/*    unsigned int reg_val,add_offset[6];
++      struct PORT_STATUS *status;
++      status = &port_state[port];
++
++      if(port>(ADM6996_PORT_NO-1))
++              return ;
++
++      // Link estabilish , speed, deplex, flow control ?
++      if(port < 5 )
++      {
++              reg_val = SPI_read(1, 1) ;
++              if(port < 4)
++                      reg_val >>= port*8 ;
++              else
++                      reg_val >>=28 ;
++              status->link = reg_val & 0x00000001 ;
++              status->speed = reg_val  & 0x00000002 ;
++              status->duplex = reg_val & 0x00000004 ;
++              status->flow_ctl = reg_val & 0x00000008 ;
++      }
++      else if(port ==5 )
++      {
++              reg_val = SPI_read(1, 2) ;
++              status->link = reg_val & 0x00000001 ;
++              status->speed = reg_val  & 0x00000002 ;
++              status->duplex = reg_val & 0x00000008 ;
++              status->flow_ctl = reg_val & 0x00000010 ;
++      }
++
++      //   Mac Lock ?
++      reg_val = SPI_read(0,0x12);
++      switch(port)
++      {
++              case 0: status->mac_lock = reg_val & 0x00000001;
++              case 1: status->mac_lock = reg_val & 0x00000004;
++              case 2: status->mac_lock = reg_val & 0x00000010;
++              case 3: status->mac_lock = reg_val & 0x00000040;
++              case 4: status->mac_lock = reg_val & 0x00000080;
++              case 5: status->mac_lock = reg_val & 0x00000100;
++      }
++
++      // port enable ?
++      add_offset[0] = 0x01 ;          add_offset[1] = 0x03 ;
++      add_offset[2] = 0x05 ;          add_offset[3] = 0x07 ;
++      add_offset[4] = 0x08 ;          add_offset[5] = 0x09 ;
++      reg_val = SPI_read(0,add_offset[port]);
++      status->port_disable = reg_val & 0x0020;
++
++
++      //  Packet Count ...
++      add_offset[0] = 0x04 ;          add_offset[1] = 0x06 ;
++      add_offset[2] = 0x08 ;          add_offset[3] = 0x0a ;
++      add_offset[4] = 0x0b ;          add_offset[5] = 0x0c ;
++
++      reg_val = SPI_read(1,add_offset[port]);
++      status->rx_pac_count = reg_val ;
++      reg_val = SPI_read(1,add_offset[port]+9);
++      status->rx_pac_byte = reg_val ;
++      reg_val = SPI_read(1,add_offset[port]+18);
++      status->tx_pac_count = reg_val ;
++      reg_val = SPI_read(1,add_offset[port]+27);
++      status->tx_pac_byte = reg_val ;
++      reg_val = SPI_read(1,add_offset[port]+36);
++      status->collision_count = reg_val ;
++      reg_val = SPI_read(1,add_offset[port]+45);
++      status->error_count = reg_val ;
++      reg_val = SPI_read(1, 0x3A);
++      switch(port)
++      {
++              case 0: status->rx_pac_count_overflow = reg_val & 0x00000001;
++                      status->rx_pac_byte_overflow = reg_val & 0x00000200 ;
++              case 1: status->rx_pac_count_overflow = reg_val & 0x00000004;
++                      status->rx_pac_byte_overflow = reg_val & 0x00000800 ;
++              case 2: status->rx_pac_count_overflow = reg_val & 0x00000010;
++                      status->rx_pac_byte_overflow = reg_val & 0x00002000 ;
++              case 3: status->rx_pac_count_overflow = reg_val & 0x00000040;;
++                      status->rx_pac_byte_overflow = reg_val & 0x00008000 ;
++              case 4: status->rx_pac_count_overflow = reg_val & 0x00000080;
++                      status->rx_pac_byte_overflow = reg_val & 0x00010000 ;
++              case 5: status->rx_pac_count_overflow = reg_val & 0x00000100;
++                      status->rx_pac_byte_overflow = reg_val & 0x00020000 ;
++      }
++
++      reg_val = SPI_read(1, 0x3B);
++      switch(port)
++      {
++              case 0: status->tx_pac_count_overflow = reg_val & 0x00000001;
++                      status->tx_pac_byte_overflow  = reg_val & 0x00000200 ;
++              case 1: status->tx_pac_count_overflow  = reg_val & 0x00000004;
++                      status->tx_pac_byte_overflow  = reg_val & 0x00000800 ;
++              case 2: status->tx_pac_count_overflow  = reg_val & 0x00000010;
++                      status->tx_pac_byte_overflow  = reg_val & 0x00002000 ;
++              case 3: status->tx_pac_count_overflow  = reg_val & 0x00000040;;
++                      status->tx_pac_byte_overflow  = reg_val & 0x00008000 ;
++              case 4: status->tx_pac_count_overflow  = reg_val & 0x00000080;
++                      status->tx_pac_byte_overflow  = reg_val & 0x00010000 ;
++              case 5: status->tx_pac_count_overflow  = reg_val & 0x00000100;
++                      status->tx_pac_byte_overflow  = reg_val & 0x00020000 ;
++      }
++*/
++
++      unsigned int reg_val;
++      struct PORT_STATUS *status;
++      status = &port_state[port];
++
++      if(port>=ADM6999_PORT_NO)
++              return ;
++
++      // Link estabilish , speed, deplex, flow control ?
++      if(port < ADM6999_PORT_NO-1 )
++      {
++              reg_val = SPI_read(1, 0x01) ;
++              reg_val = reg_val >> port*4 ;
++              status->link = reg_val & 0x00000001 ;
++              status->speed = reg_val  & 0x00000002 ;
++              status->duplex = reg_val & 0x00000004 ;
++              status->flow_ctl = reg_val & 0x00000008 ;
++      }
++      else if(port == (ADM6999_PORT_NO-1) )
++      {
++              reg_val = SPI_read(1, 0x02) ;
++              status->link = reg_val & 0x00000001 ;
++              status->speed = reg_val  & 0x00000002 ;
++              status->duplex = reg_val & 0x00000008 ;
++              status->flow_ctl = reg_val & 0x00000010 ;
++      }
++
++      // Mac Lock ?
++      reg_val = SPI_read(0,0x12);
++      reg_val = reg_val >> port ;
++      reg_val = reg_val & 0x01 ;
++      status->mac_lock = reg_val ? 0x01:0x00 ;
++
++      // port enable ?
++      reg_val = SPI_read(0,(unsigned char)port+1);
++      status->port_disable = reg_val & 0x0020;
++
++      //  Packet Count ...
++      reg_val = SPI_read(1,(unsigned char)port+0x04);
++      status->rx_pac_count = reg_val ;
++      reg_val = SPI_read(1,(unsigned char)port+0x0D);
++      status->rx_pac_byte = reg_val ;
++      reg_val = SPI_read(1,(unsigned char)port+0x16);
++      status->tx_pac_count = reg_val ;
++      reg_val = SPI_read(1,(unsigned char)port+0x1F);
++      status->tx_pac_byte = reg_val ;
++      reg_val = SPI_read(1,(unsigned char)port+0x28);
++      status->collision_count = reg_val ;
++      reg_val = SPI_read(1,(unsigned char)port+0x31);
++      status->error_count = reg_val ;
++      reg_val = SPI_read(1, 0x3A);
++      reg_val = reg_val >> port ;
++      status->rx_pac_count_overflow = reg_val & 0x00000001;
++      reg_val = reg_val >> 0x09 ;
++      status->rx_pac_byte_overflow = reg_val & 0x00000001 ;
++
++      reg_val = SPI_read(1, 0x3B);
++      reg_val = reg_val >> port ;
++      status->tx_pac_count_overflow = reg_val & 0x00000001;
++      reg_val = reg_val >> 0x09 ;
++      status->tx_pac_byte_overflow  = reg_val & 0x00000001 ;
++
++      reg_val = SPI_read(1, 0x3C);
++      reg_val = reg_val >> port ;
++      status->collision_count_overflow = reg_val & 0x00000001;
++      reg_val = reg_val >> 0x09 ;
++      status->error_count_overflow  = reg_val & 0x00000001 ;
++
++}
++
++unsigned int SPI_get_identifier(void)
++{
++      unsigned int flag=0;
++
++#ifdef CONFIG_IT8712_GPIO
++
++      if (!it8712_exist) {
++              return -ENODEV;
++      }
++      printk("it8712_gpio init\n");
++
++      /* initialize registers */
++      // switch all multi-function pins to GPIO
++      LPCSetConfig(LDN_GPIO, 0x28, 0xff);
++
++      // set simple I/O base address
++      LPCSetConfig(LDN_GPIO, 0x62, IT8712_GPIO_BASE >> 8);
++      LPCSetConfig(LDN_GPIO, 0x63, (unsigned char) IT8712_GPIO_BASE >> 8);
++
++      // select GPIO to simple I/O
++      LPCSetConfig(LDN_GPIO, 0xc3, 0xff);
++
++      // enable internal pull-up
++      LPCSetConfig(LDN_GPIO, 0xbb, 0xff);
++
++#endif
++
++      flag = SPI_read(1,0x00);
++      printk("Get ADM identifier %6x\n",flag);
++      if ((flag & 0xFFFF0) == 0x21120) {
++              printk("ADM699X Found\n");
++              return 1;
++      }
++      else {
++              printk("ADM699X not Found\n");
++              return 0;
++      }
++}
++
+--- /dev/null
++++ b/drivers/net/sl351x_crc16.c
+@@ -0,0 +1,93 @@
++/****************************************************************************
++* Name                        : sl351x_crc16.c
++* Description :
++*             Implement CRC16
++*             refer to RFC1662
++* History
++*
++*     Date            Writer          Description
++*     -----------     -----------     -------------------------------------------------
++*     09/14/2005      Gary Chen       Create
++*
++****************************************************************************/
++
++#define INITFCS16             0xffff  /* Initial FCS value */
++#define GOODFCS16             0xf0b8  /* Good final FCS value */
++#define SWAP_WORD(x)  (unsigned short)((((unsigned short)x & 0x00FF) << 8) |  \
++                                                                               (((unsigned short)x & 0xFF00) >> 8))
++
++/*----------------------------------------------------------------------
++*     x**0 + x**5 + x**12 + x**16
++*----------------------------------------------------------------------*/
++static const unsigned short crc16_tbl[256] = {
++      0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
++      0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
++      0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
++      0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
++      0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
++      0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
++      0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
++      0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
++      0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
++      0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
++      0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
++      0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
++      0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
++      0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
++      0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
++      0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
++      0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
++      0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
++      0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
++      0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
++      0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
++      0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
++      0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
++      0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
++      0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
++      0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
++      0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
++      0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
++      0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
++      0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
++      0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
++      0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
++};
++
++/*----------------------------------------------------------------------
++* hash_crc16
++*----------------------------------------------------------------------*/
++unsigned short hash_crc16(unsigned short crc, unsigned char *datap, unsigned long len)
++{
++    while (len--)
++    {
++        crc = (crc >> 8) ^ crc16_tbl[(crc ^ (*datap++)) & 0xff];
++    }
++
++    return (crc);
++
++}
++
++/*----------------------------------------------------------------------
++* hash_check_crc16
++*----------------------------------------------------------------------*/
++unsigned long hash_check_crc16(unsigned char *datap, unsigned long len)
++{
++    unsigned short crc;
++
++    crc = hash_crc16(INITFCS16, datap, len );
++    return (crc == GOODFCS16) ?  0 : 1;
++}
++
++/*----------------------------------------------------------------------
++* hash_gen_crc16
++*----------------------------------------------------------------------*/
++unsigned short hash_gen_crc16(unsigned char *datap, unsigned long len)
++{
++    unsigned short crc;
++
++    crc = hash_crc16(INITFCS16, datap, len);
++    crc ^= 0xffff;
++
++    return(SWAP_WORD(crc));
++}
+--- /dev/null
++++ b/drivers/net/sl351x_gmac.c
+@@ -0,0 +1,5622 @@
++/**************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
++*--------------------------------------------------------------------------
++* Name                        : sl351x_gmac.c
++* Description :
++*             Ethernet device driver for Storlink SL351x FPGA
++*
++* History
++*
++*     Date            Writer          Description
++*     -----------     -----------     -------------------------------------------------
++*     08/22/2005      Gary Chen       Create and implement
++*   27/10/2005  CH Hsu      Porting to Linux
++*
++****************************************************************************/
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/compiler.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/completion.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/it8712.h>
++#include <linux/mtd/kvctl.h>
++#include <linux/skbuff.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++
++#include <linux/mtd/kvctl.h>
++
++#define        MIDWAY
++#define        SL_LEPUS
++#define VITESSE_G5SWITCH      1
++
++#ifndef CONFIG_SL351x_RXTOE
++//#define CONFIG_SL351x_RXTOE 1
++#endif
++#undef CONFIG_SL351x_RXTOE
++
++#include <asm/arch/sl2312.h>
++#include <asm/arch/sl351x_gmac.h>
++#include <asm/arch/sl351x_hash_cfg.h>
++#include <asm/arch/sl351x_nat_cfg.h>
++
++#ifdef CONFIG_SL351x_SYSCTL
++#include <linux/sysctl_storlink.h>
++#endif
++
++#ifdef CONFIG_SL351x_RXTOE
++#include <asm/arch/sl351x_toe.h>
++#include <net/tcp.h>
++#include <linux/tcp.h>
++#include <linux/ip.h>
++#endif
++
++// #define SL351x_TEST_WORKAROUND
++#ifdef CONFIG_SL351x_NAT
++#define CONFIG_SL_NAPI                                        1
++#endif
++#define GMAX_TX_INTR_DISABLED                 1
++#define DO_HW_CHKSUM                                  1
++#define ENABLE_TSO                                            1
++#define GMAC_USE_TXQ0                                 1
++// #define NAT_WORKAROUND_BY_RESET_GMAC       1
++// #define HW_RXBUF_BY_KMALLOC                        1
++//#define _DUMP_TX_TCP_CONTENT        1
++#define       br_if_ioctl                                             1
++#define GMAC_LEN_1_2_ISSUE                            1
++
++#define GMAC_EXISTED_FLAG                     0x5566abcd
++#define CONFIG_MAC_NUM                                GMAC_NUM
++#define GMAC0_BASE                                    TOE_GMAC0_BASE
++#define GMAC1_BASE                                    TOE_GMAC1_BASE
++#define PAUSE_SET_HW_FREEQ                    (TOE_HW_FREEQ_DESC_NUM / 2)
++#define PAUSE_REL_HW_FREEQ                    ((TOE_HW_FREEQ_DESC_NUM / 2) + 10)
++#define DEFAULT_RXQ_MAX_CNT                   256
++#ifdef        L2_jumbo_frame
++#define TCPHDRLEN(tcp_hdr)  ((ntohs(*((__u16 *)tcp_hdr + 6)) >> 12) & 0x000F)
++#endif
++
++/* define chip information */
++#define DRV_NAME                                      "SL351x"
++#define DRV_VERSION                                   "0.1.4"
++#define SL351x_DRIVER_NAME            DRV_NAME " Giga Ethernet driver " DRV_VERSION
++
++#define toe_gmac_enable_interrupt(irq)        enable_irq(irq)
++#define toe_gmac_disable_interrupt(irq)       disable_irq(irq)
++
++#ifdef SL351x_GMAC_WORKAROUND
++#define GMAC_SHORT_FRAME_THRESHOLD            10
++static struct timer_list gmac_workround_timer_obj;
++void sl351x_poll_gmac_hanged_status(u32 data);
++#ifdef CONFIG_SL351x_NAT
++//#define IxscriptMate_1518                           1
++      void sl351x_nat_workaround_init(void);
++      #ifndef NAT_WORKAROUND_BY_RESET_GMAC
++              static void sl351x_nat_workaround_handler(void);
++      #endif
++#endif
++#endif
++
++#ifdef GMAC_LEN_1_2_ISSUE
++      #define _DEBUG_PREFETCH_NUM     256
++static        int     _debug_prefetch_cnt;
++static        char _debug_prefetch_buf[_DEBUG_PREFETCH_NUM][4] __attribute__((aligned(4)));
++#endif
++/*************************************************************
++ *         Global Variable
++ *************************************************************/
++static int    gmac_initialized = 0;
++TOE_INFO_T toe_private_data;
++//static int          do_again = 0;
++spinlock_t gmac_fq_lock;
++unsigned int FLAG_SWITCH;
++
++static unsigned int           next_tick = 3 * HZ;
++static unsigned char          eth_mac[CONFIG_MAC_NUM][6]= {{0x00,0x11,0x11,0x87,0x87,0x87}, {0x00,0x22,0x22,0xab,0xab,0xab}};
++
++#undef CONFIG_SL351x_RXTOE
++extern NAT_CFG_T nat_cfg;
++
++/************************************************/
++/*                 function declare             */
++/************************************************/
++static int gmac_set_mac_address(struct net_device *dev, void *addr);
++static unsigned int gmac_get_phy_vendor(int phy_addr);
++static void gmac_set_phy_status(struct net_device *dev);
++void gmac_get_phy_status(struct net_device *dev);
++static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
++static void gmac_tx_timeout(struct net_device *dev);
++static int gmac_phy_thread (void *data);
++struct net_device_stats * gmac_get_stats(struct net_device *dev);
++static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev);
++static void gmac_set_rx_mode(struct net_device *dev);
++static irqreturn_t toe_gmac_interrupt (int irq, void *dev_instance);
++static void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp);
++unsigned int mii_read(unsigned char phyad,unsigned char regad);
++void mii_write(unsigned char phyad,unsigned char regad,unsigned int value);
++void mac_init_drv(void);
++
++static void toe_init_free_queue(void);
++static void toe_init_swtx_queue(void);
++static void toe_init_default_queue(void);
++#ifdef CONFIG_SL351x_RXTOE
++static void toe_init_interrupt_queue(void);
++#endif
++static void toe_init_interrupt_config(void);
++static void toe_gmac_sw_reset(void);
++static int toe_gmac_init_chip(struct net_device *dev);
++static void toe_gmac_enable_tx_rx(struct net_device* dev);
++static void toe_gmac_disable_tx_rx(struct net_device *dev);
++static void toe_gmac_hw_start(struct net_device *dev);
++static void toe_gmac_hw_stop(struct net_device *dev);
++static int toe_gmac_clear_counter(struct net_device *dev);
++static void toe_init_gmac(struct net_device *dev);
++static  void toe_gmac_tx_complete(GMAC_INFO_T *tp, unsigned int tx_qid, struct net_device *dev, int interrupt);
++#ifdef CONFIG_SL_NAPI
++static int gmac_rx_poll(struct net_device *dev, int *budget);
++// static void toe_gmac_disable_rx(struct net_device *dev);
++// static void toe_gmac_enable_rx(struct net_device *dev);
++#endif
++
++u32 mac_read_dma_reg(int mac, unsigned int offset);
++void mac_write_dma_reg(int mac, unsigned int offset, u32 data);
++void mac_stop_txdma(struct net_device *dev);
++void mac_get_sw_tx_weight(struct net_device *dev, char *weight);
++void mac_set_sw_tx_weight(struct net_device *dev, char *weight);
++void mac_get_hw_tx_weight(struct net_device *dev, char *weight);
++void mac_set_hw_tx_weight(struct net_device *dev, char *weight);
++static inline void toe_gmac_fill_free_q(void);
++
++#ifdef VITESSE_G5SWITCH
++extern int Get_Set_port_status(void);
++extern int SPI_default(void);
++extern unsigned int SPI_get_identifier(void);
++void gmac_get_switch_status(struct net_device *dev);
++unsigned int Giga_switch=0;
++unsigned int switch_port_no=0;
++unsigned int ever_dwon=0;
++#endif
++
++/************************************************/
++/*            GMAC function declare             */
++/************************************************/
++static int gmac_open (struct net_device *dev);
++static int gmac_close (struct net_device *dev);
++static void gmac_cleanup_module(void);
++static void gmac_get_mac_address(void);
++
++#ifdef CONFIG_SL351x_NAT
++static void toe_init_hwtx_queue(void);
++extern void sl351x_nat_init(void);
++extern void sl351x_nat_input(struct sk_buff *skb, int port, void *l3off, void *l4off);
++extern int sl351x_nat_output(struct sk_buff *skb, int port);
++extern int sl351x_nat_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
++#endif
++
++#ifdef CONFIG_SL351x_RXTOE
++extern void set_toeq_hdr(struct toe_conn* connection, TOE_INFO_T* toe, struct net_device *dev);
++extern void sl351x_toe_init(void);
++extern void toe_gmac_handle_toeq(struct net_device *dev, GMAC_INFO_T* tp, __u32 status);
++extern struct toe_conn* init_toeq(int ipver, void* iph, struct tcphdr* tcp_hdr, TOE_INFO_T* toe, unsigned char* l2hdr);
++#endif
++
++int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2);
++void mac_set_rule_enable_bit(int mac, int rule, int data);
++int mac_set_rule_action(int mac, int rule, int data);
++int mac_get_MRxCRx(int mac, int rule, int ctrlreg);
++void mac_set_MRxCRx(int mac, int rule, int ctrlreg, u32 data);
++
++/*----------------------------------------------------------------------
++*     Ethernet Driver init
++*----------------------------------------------------------------------*/
++
++static int __init gmac_init_module(void)
++{
++      GMAC_INFO_T             *tp;
++      struct net_device       *dev;
++      int             i,j;
++      unsigned int    chip_id;
++//    unsigned int chip_version;
++
++#ifdef CONFIG_SL3516_ASIC
++{
++    unsigned int    val;
++    /* set GMAC global register */
++    val = readl(GMAC_GLOBAL_BASE_ADDR+0x10);
++    val = val | 0x005f0000;
++    writel(val,GMAC_GLOBAL_BASE_ADDR+0x10);
++//    writel(0xb737b737,GMAC_GLOBAL_BASE_ADDR+0x1c); //For Socket Board
++    writel(0x77777777,GMAC_GLOBAL_BASE_ADDR+0x20);
++//    writel(0xa737b747,GMAC_GLOBAL_BASE_ADDR+0x1c);//For Mounting Board
++
++      //debug_Aaron
++    //writel(0xa7f0a7f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For Mounting Board
++    writel(0xa7f0b7f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For Mounting Board
++
++    writel(0x77777777,GMAC_GLOBAL_BASE_ADDR+0x24);
++      writel(0x09200030,GMAC_GLOBAL_BASE_ADDR+0x2C);
++      val = readl(GMAC_GLOBAL_BASE_ADDR+0x04);
++      if((val&(1<<20))==0){           // GMAC1 enable
++              val = readl(GMAC_GLOBAL_BASE_ADDR+0x30);
++              val = (val & 0xe7ffffff) | 0x08000000;
++              writel(val,GMAC_GLOBAL_BASE_ADDR+0x30);
++      }
++}
++#endif
++
++#ifdef VITESSE_G5SWITCH
++      Giga_switch = SPI_get_identifier();
++      if(Giga_switch)
++              switch_port_no = SPI_default();
++#endif
++
++      chip_id = readl(GMAC_GLOBAL_BASE_ADDR+0x0);
++      if (chip_id == 0x3512C1)
++      {
++              writel(0x5787a5f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For 3512 Switch Board
++              writel(0x55557777,GMAC_GLOBAL_BASE_ADDR+0x20);//For 3512 Switch Board
++      }
++//#endif
++
++      mac_init_drv();
++
++      printk (KERN_INFO SL351x_DRIVER_NAME " built at %s %s\n", __DATE__, __TIME__);
++
++//    init_waitqueue_entry(&wait, current);
++
++      // printk("GMAC Init......\n");
++
++      i = 0;
++      for(j = 0; i<CONFIG_MAC_NUM; j++)
++      {
++              i=j;
++              if(Giga_switch){                // if gswitch present, swap eth0/1
++                      if(j==0)
++                              i=1;
++                      else if(j==1)
++                              i=0;
++              }
++
++              tp = (GMAC_INFO_T *)&toe_private_data.gmac[i];
++              tp->dev = NULL;
++              if (tp->existed != GMAC_EXISTED_FLAG) continue;
++
++              dev = alloc_etherdev(0);
++              if (dev == NULL)
++              {
++                      printk (KERN_ERR "Can't allocate ethernet device #%d .\n",i);
++                      return -ENOMEM;
++              }
++
++              dev->priv=tp;
++              tp->dev = dev;
++
++              SET_MODULE_OWNER(dev);
++
++              // spin_lock_init(&tp->lock);
++              spin_lock_init(&gmac_fq_lock);
++              dev->base_addr = tp->base_addr;
++              dev->irq = tp->irq;
++          dev->open = gmac_open;
++          dev->stop = gmac_close;
++              dev->hard_start_xmit = gmac_start_xmit;
++              dev->get_stats = gmac_get_stats;
++              dev->set_multicast_list = gmac_set_rx_mode;
++              dev->set_mac_address = gmac_set_mac_address;
++              dev->do_ioctl = gmac_netdev_ioctl;
++              dev->tx_timeout = gmac_tx_timeout;
++              dev->watchdog_timeo = GMAC_DEV_TX_TIMEOUT;
++#ifdef        L2_jumbo_frame
++              dev->mtu = 2018; //2002  ,2018
++#endif
++              if (tp->port_id == 0)
++                      dev->tx_queue_len = TOE_GMAC0_SWTXQ_DESC_NUM;
++              else
++                      dev->tx_queue_len = TOE_GMAC1_SWTXQ_DESC_NUM;
++
++#ifdef DO_HW_CHKSUM
++              dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
++#ifdef ENABLE_TSO
++              dev->features |= NETIF_F_TSO;
++#endif
++#endif
++#ifdef CONFIG_SL_NAPI
++        dev->poll = gmac_rx_poll;
++        dev->weight = 64;
++#endif
++
++              if (register_netdev(dev))
++              {
++                      gmac_cleanup_module();
++                      return(-1);
++              }
++      }
++
++
++//    FLAG_SWITCH = 0 ;
++//    FLAG_SWITCH = SPI_get_identifier();
++//    if(FLAG_SWITCH)
++//    {
++//            printk("Configure ADM699X...\n");
++//            SPI_default();  //Add by jason for ADM699X configuration
++//    }
++      return (0);
++}
++
++/*----------------------------------------------------------------------
++*     gmac_cleanup_module
++*----------------------------------------------------------------------*/
++
++static void gmac_cleanup_module(void)
++{
++    int i;
++
++#ifdef SL351x_GMAC_WORKAROUND
++      del_timer(&gmac_workround_timer_obj);
++#endif
++
++    for (i=0;i<CONFIG_MAC_NUM;i++)
++    {
++      if (toe_private_data.gmac[i].dev)
++      {
++              unregister_netdev(toe_private_data.gmac[i].dev);
++              toe_private_data.gmac[i].dev = NULL;
++        }
++    }
++      return ;
++}
++
++module_init(gmac_init_module);
++module_exit(gmac_cleanup_module);
++
++
++/*----------------------------------------------------------------------
++*     gmac_read_reg
++*----------------------------------------------------------------------*/
++static inline unsigned int gmac_read_reg(unsigned int base, unsigned int offset)
++//static unsigned int gmac_read_reg(unsigned int base, unsigned int offset)
++{
++    volatile unsigned int reg_val;
++
++    reg_val = readl(base + offset);
++      return (reg_val);
++}
++
++/*----------------------------------------------------------------------
++*     gmac_write_reg
++*----------------------------------------------------------------------*/
++static inline void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask)
++//static void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask)
++{
++      volatile unsigned int reg_val;
++    unsigned int *addr;
++
++      reg_val = ( gmac_read_reg(base, offset) & (~bit_mask) ) | (data & bit_mask);
++      addr = (unsigned int *)(base + offset);
++    writel(reg_val,addr);
++      return;
++}
++
++/*----------------------------------------------------------------------
++*     mac_init_drv
++*----------------------------------------------------------------------*/
++void mac_init_drv(void)
++{
++      TOE_INFO_T                      *toe;
++      int                                     i;
++      QUEUE_THRESHOLD_T       threshold;
++      u32                                     *destp;
++      unsigned int            chip_id,chip_version;
++
++      chip_id = readl(GMAC_GLOBAL_BASE_ADDR+0x0);
++      chip_version = chip_id & 0x1 ;
++
++      if (!gmac_initialized)
++      {
++              gmac_initialized = 1;
++
++              // clear non TOE Queue Header Area
++              destp = (u32 *)TOE_NONTOE_QUE_HDR_BASE;
++              for (; destp < (u32 *)NONTOE_Q_HDR_AREA_END; destp++)
++                      *destp = 0x00;
++
++              // clear TOE Queue Header Area
++              destp = (u32 *)TOE_TOE_QUE_HDR_BASE;
++              for (; destp < (u32 *)TOE_Q_HDR_AREA_END; destp++)
++                      *destp = 0x00;
++
++              // init private data
++              toe = (TOE_INFO_T *)&toe_private_data;
++              memset((void *)toe, 0, sizeof(TOE_INFO_T));
++              toe->gmac[0].base_addr = GMAC0_BASE;
++              toe->gmac[1].base_addr = GMAC1_BASE;
++              toe->gmac[0].dma_base_addr = TOE_GMAC0_DMA_BASE;
++              toe->gmac[1].dma_base_addr = TOE_GMAC1_DMA_BASE;
++        toe->gmac[0].auto_nego_cfg = 1;
++        toe->gmac[1].auto_nego_cfg = 1;
++#ifdef CONFIG_SL3516_ASIC
++        toe->gmac[0].speed_cfg = GMAC_SPEED_1000;
++        toe->gmac[1].speed_cfg = GMAC_SPEED_1000;
++#else
++              toe->gmac[0].speed_cfg = GMAC_SPEED_100;
++        toe->gmac[1].speed_cfg = GMAC_SPEED_100;
++#endif
++        toe->gmac[0].full_duplex_cfg = 1;
++        toe->gmac[1].full_duplex_cfg = 1;
++#ifdef CONFIG_SL3516_ASIC
++        toe->gmac[0].phy_mode = GMAC_PHY_RGMII_1000;
++        toe->gmac[1].phy_mode = GMAC_PHY_RGMII_1000;
++#else
++              toe->gmac[0].phy_mode = GMAC_PHY_RGMII_100;
++        toe->gmac[1].phy_mode = GMAC_PHY_RGMII_100;
++#endif
++        toe->gmac[0].port_id = GMAC_PORT0;
++        toe->gmac[1].port_id = GMAC_PORT1;
++        toe->gmac[0].phy_addr = 0x1;
++        toe->gmac[1].phy_addr = 2;
++//      toe->gmac[0].irq = SL2312_INTERRUPT_GMAC0;
++              toe->gmac[0].irq =1;
++//      toe->gmac[1].irq = SL2312_INTERRUPT_GMAC1;
++              toe->gmac[1].irq =2;
++        toe->gmac[0].mac_addr1 = &eth_mac[0][0];
++        toe->gmac[1].mac_addr1 = &eth_mac[1][0];
++
++              for (i=0; i<CONFIG_MAC_NUM; i++)
++              {
++                      unsigned int data, phy_vendor;
++                      gmac_write_reg(toe->gmac[i].base_addr, GMAC_STA_ADD2, 0x55aa55aa, 0xffffffff);
++                      data = gmac_read_reg(toe->gmac[i].base_addr, GMAC_STA_ADD2);
++                      if (data == 0x55aa55aa)
++                      {
++#ifdef VITESSE_G5SWITCH
++                              if(Giga_switch && (i==1)){
++                                      toe->gmac[i].existed = GMAC_EXISTED_FLAG;
++                                      break;
++                              }
++#endif
++                              phy_vendor = gmac_get_phy_vendor(toe->gmac[i].phy_addr);
++                              if (phy_vendor != 0 && phy_vendor != 0xffffffff)
++                                      toe->gmac[i].existed = GMAC_EXISTED_FLAG;
++                      }
++              }
++
++              // Write GLOBAL_QUEUE_THRESHOLD_REG
++              threshold.bits32 = 0;
++              threshold.bits.swfq_empty = (TOE_SW_FREEQ_DESC_NUM > 256) ? 255 :
++                                                      TOE_SW_FREEQ_DESC_NUM/2;
++              threshold.bits.hwfq_empty = (TOE_HW_FREEQ_DESC_NUM > 256) ? 256/4 :
++                                                      TOE_HW_FREEQ_DESC_NUM/4;
++              threshold.bits.toe_class = (TOE_TOE_DESC_NUM > 256) ? 256/4 :
++                                                      TOE_TOE_DESC_NUM/4;
++              threshold.bits.intrq = (TOE_INTR_DESC_NUM > 256) ? 256/4 :
++                                                      TOE_INTR_DESC_NUM/4;
++              writel(threshold.bits32, TOE_GLOBAL_BASE + GLOBAL_QUEUE_THRESHOLD_REG);
++
++              FLAG_SWITCH = 0;
++              toe_gmac_sw_reset();
++              toe_init_free_queue();
++              toe_init_swtx_queue();
++#ifdef CONFIG_SL351x_NAT
++              toe_init_hwtx_queue();
++#endif
++              toe_init_default_queue();
++#ifdef CONFIG_SL351x_RXTOE
++              toe_init_interrupt_queue();
++#endif
++              toe_init_interrupt_config();
++
++#if defined(CONFIG_SL351x_NAT) || defined(CONFIG_SL351x_RXTOE)
++              sl351x_hash_init();
++#else
++      {
++              volatile u32 *dp1, *dp2, dword;
++
++              dp1 = (volatile u32 *) TOE_V_BIT_BASE;
++              dp2 = (volatile u32 *) TOE_A_BIT_BASE;
++
++              for (i=0; i<HASH_TOTAL_ENTRIES/32; i++)
++              {
++                      *dp1++ = 0;
++                      dword = *dp2++; // read-clear
++              }
++      }
++#endif
++      }
++
++#ifdef SL351x_GMAC_WORKAROUND
++#ifdef CONFIG_SL351x_NAT
++      sl351x_nat_workaround_init();
++#endif
++      init_timer(&gmac_workround_timer_obj);
++      if (chip_version == 1)
++      {
++              gmac_workround_timer_obj.expires = jiffies * 50;
++      }
++      else
++      {
++              gmac_workround_timer_obj.expires = jiffies + 2;
++      }
++      gmac_workround_timer_obj.data = (unsigned long)&gmac_workround_timer_obj;
++      gmac_workround_timer_obj.function = (void *)&sl351x_poll_gmac_hanged_status;
++      add_timer(&gmac_workround_timer_obj);
++#endif
++}
++
++/*----------------------------------------------------------------------
++*     toe_init_free_queue
++*     (1) Initialize the Free Queue Descriptor Base Address & size
++*             Register: TOE_GLOBAL_BASE + 0x0004
++*     (2) Initialize DMA Read/Write pointer for
++*             SW Free Queue and HW Free Queue
++*     (3)     Initialize DMA Descriptors for
++*             SW Free Queue and HW Free Queue,
++*----------------------------------------------------------------------*/
++static void toe_init_free_queue(void)
++{
++      int                             i;
++      TOE_INFO_T                      *toe;
++      DMA_RWPTR_T                     rwptr_reg;
++//    unsigned int            rwptr_addr;
++      unsigned int            desc_buf;
++      GMAC_RXDESC_T           *sw_desc_ptr;
++      struct sk_buff          *skb;
++#ifdef CONFIG_SL351x_NAT
++      GMAC_RXDESC_T           *desc_ptr;
++      unsigned int            buf_ptr;
++#endif
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      desc_buf = (unsigned int)DMA_MALLOC((TOE_SW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T)),
++                                              (dma_addr_t *)&toe->sw_freeq_desc_base_dma) ;
++      sw_desc_ptr = (GMAC_RXDESC_T *)desc_buf;
++      if (!desc_buf)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return;
++      }
++      memset((void *)desc_buf, 0, TOE_SW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T));
++
++      // DMA Queue Base & Size
++      writel((toe->sw_freeq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_SW_FREEQ_DESC_POWER,
++                      TOE_GLOBAL_BASE + GLOBAL_SW_FREEQ_BASE_SIZE_REG);
++
++      // init descriptor base
++      toe->swfq_desc_base = desc_buf;
++
++      // SW Free Queue Read/Write Pointer
++      rwptr_reg.bits.wptr = TOE_SW_FREEQ_DESC_NUM - 1;
++      rwptr_reg.bits.rptr = 0;
++      toe->fq_rx_rwptr.bits32 = rwptr_reg.bits32;
++      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++
++      // SW Free Queue Descriptors
++      for (i=0; i<TOE_SW_FREEQ_DESC_NUM; i++)
++      {
++              sw_desc_ptr->word0.bits.buffer_size = SW_RX_BUF_SIZE;
++              sw_desc_ptr->word1.bits.sw_id = i;      // used to locate skb
++              if ( (skb = dev_alloc_skb(SW_RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
++              {
++                      printk("%s::skb buffer allocation fail !\n",__func__); while(1);
++              }
++              REG32(skb->data) = (unsigned int)skb;
++              skb_reserve(skb, SKB_RESERVE_BYTES);
++              // toe->rx_skb[i] = skb;
++              sw_desc_ptr->word2.buf_adr = (unsigned int)__pa(skb->data);
++//            consistent_sync((unsigned int)desc_ptr, sizeof(GMAC_RXDESC_T), PCI_DMA_TODEVICE);
++              sw_desc_ptr++;
++      }
++
++#ifdef CONFIG_SL351x_NAT
++      if (sizeof(skb->cb) < 64)
++      {
++                      printk("==> %s:: sk structure is incorrect -->Change to cb[64] !\n",__func__); while(1);
++      }
++      // init hardware free queues
++      desc_buf = (unsigned int)DMA_MALLOC((TOE_HW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T)),
++                                              (dma_addr_t *)&toe->hw_freeq_desc_base_dma) ;
++      desc_ptr = (GMAC_RXDESC_T *)desc_buf;
++      if (!desc_buf)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return;
++      }
++      memset((void *)desc_buf, 0, TOE_HW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T));
++
++      // DMA Queue Base & Size
++      writel((toe->hw_freeq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_HW_FREEQ_DESC_POWER,
++                      TOE_GLOBAL_BASE + GLOBAL_HW_FREEQ_BASE_SIZE_REG);
++
++      // init descriptor base
++      toe->hwfq_desc_base = desc_buf;
++
++      // HW Free Queue Read/Write Pointer
++      rwptr_reg.bits.wptr = TOE_HW_FREEQ_DESC_NUM - 1;
++      rwptr_reg.bits.rptr = 0;
++      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
++#ifndef HW_RXBUF_BY_KMALLOC
++      buf_ptr = (unsigned int)DMA_MALLOC(TOE_HW_FREEQ_DESC_NUM * HW_RX_BUF_SIZE,
++                                              (dma_addr_t *)&toe->hwfq_buf_base_dma);
++#else
++      buf_ptr = (unsigned int)kmalloc(TOE_HW_FREEQ_DESC_NUM * HW_RX_BUF_SIZE, GFP_KERNEL);
++      toe->hwfq_buf_base_dma = __pa(buf_ptr);
++#endif
++      if (!buf_ptr)
++      {
++              printk("===> %s::Failed to allocate HW TxQ Buffers!\n",__func__);
++              while(1);       // could not be happened, if happened, adjust the buffer descriptor number
++              return;
++      }
++
++      toe->hwfq_buf_base = buf_ptr;
++      toe->hwfq_buf_end_dma = toe->hwfq_buf_base_dma + (TOE_HW_FREEQ_DESC_NUM * HW_RX_BUF_SIZE);
++      buf_ptr = (unsigned int)toe->hwfq_buf_base_dma;
++      for (i=0; i<TOE_HW_FREEQ_DESC_NUM; i++)
++      {
++              desc_ptr->word0.bits.buffer_size = HW_RX_BUF_SIZE;
++              desc_ptr->word1.bits.sw_id = i;
++              desc_ptr->word2.buf_adr = (unsigned int)buf_ptr;
++//            consistent_sync((unsigned int)desc_ptr, sizeof(GMAC_RXDESC_T), PCI_DMA_TODEVICE);
++              // consistent_sync((unsigned int)buf_ptr, HW_RX_BUF_SIZE, PCI_DMA_TODEVICE);
++              desc_ptr++;
++              buf_ptr += HW_RX_BUF_SIZE;
++      }
++#else
++      // DMA Queue Base & Size
++      writel((0) | TOE_SW_FREEQ_DESC_POWER,
++                      TOE_GLOBAL_BASE + GLOBAL_HW_FREEQ_BASE_SIZE_REG);
++      rwptr_reg.bits.wptr = TOE_HW_FREEQ_DESC_NUM - 1;
++      rwptr_reg.bits.rptr = 0;
++      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
++
++#endif
++}
++/*----------------------------------------------------------------------
++*     toe_init_swtx_queue
++*     (2) Initialize the GMAC 0/1 SW TXQ Queue Descriptor Base Address & sizeup
++*             GMAC_SW_TX_QUEUE_BASE_REG(0x0050)
++*     (2) Initialize DMA Read/Write pointer for
++*             GMAC 0/1 SW TX Q0-5
++*----------------------------------------------------------------------*/
++static void toe_init_swtx_queue(void)
++{
++      int                             i;
++      TOE_INFO_T                      *toe;
++      DMA_RWPTR_T                     rwptr_reg;
++      unsigned int            rwptr_addr;
++      unsigned int            desc_buf;
++
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++
++      // GMAC-0, SW-TXQ
++      // The GMAC-0 and GMAC-0 maybe have different descriptor number
++      // so, not use for instruction
++      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
++                                              (dma_addr_t *)&toe->gmac[0].swtxq_desc_base_dma) ;
++      toe->gmac[0].swtxq_desc_base = desc_buf;
++      if (!desc_buf)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return  ;
++      }
++      memset((void *)desc_buf, 0,     TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
++      writel((toe->gmac[0].swtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC0_SWTXQ_DESC_POWER,
++                      TOE_GMAC0_DMA_BASE+ GMAC_SW_TX_QUEUE_BASE_REG);
++
++      // GMAC0 SW TX Q0-Q5
++      rwptr_reg.bits.wptr = 0;
++      rwptr_reg.bits.rptr = 0;
++      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_SW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_SW_TXQ_NUM; i++)
++      {
++              toe->gmac[0].swtxq[i].rwptr_reg = rwptr_addr;
++              toe->gmac[0].swtxq[i].desc_base = desc_buf;
++              toe->gmac[0].swtxq[i].total_desc_num = TOE_GMAC0_SWTXQ_DESC_NUM;
++              desc_buf += TOE_GMAC0_SWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
++              writel(rwptr_reg.bits32, rwptr_addr);
++              rwptr_addr+=4;
++      }
++
++      // GMAC-1, SW-TXQ
++      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC1_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
++                                              (dma_addr_t *)&toe->gmac[1].swtxq_desc_base_dma) ;
++      toe->gmac[1].swtxq_desc_base = desc_buf;
++      if (!desc_buf)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return  ;
++      }
++      memset((void *)desc_buf, 0,     TOE_GMAC1_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
++      writel((toe->gmac[1].swtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC1_SWTXQ_DESC_POWER,
++                      TOE_GMAC1_DMA_BASE+ GMAC_SW_TX_QUEUE_BASE_REG);
++
++
++      // GMAC1 SW TX Q0-Q5
++      rwptr_reg.bits.wptr = 0;
++      rwptr_reg.bits.rptr = 0;
++      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_SW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_SW_TXQ_NUM; i++)
++      {
++              toe->gmac[1].swtxq[i].rwptr_reg = rwptr_addr;
++              toe->gmac[1].swtxq[i].desc_base = desc_buf;
++              toe->gmac[1].swtxq[i].total_desc_num = TOE_GMAC1_SWTXQ_DESC_NUM;
++              desc_buf += TOE_GMAC1_SWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
++              writel(rwptr_reg.bits32, rwptr_addr);
++              rwptr_addr+=4;
++      }
++}
++
++/*----------------------------------------------------------------------
++*     toe_init_hwtx_queue
++*     (2) Initialize the GMAC 0/1 HW TXQ Queue Descriptor Base Address & size
++*             GMAC_HW_TX_QUEUE_BASE_REG(0x0054)
++*     (2) Initialize DMA Read/Write pointer for
++*             GMAC 0/1 HW TX Q0-5
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static void toe_init_hwtx_queue(void)
++{
++      int                             i;
++      TOE_INFO_T                      *toe;
++      DMA_RWPTR_T                     rwptr_reg;
++      unsigned int            rwptr_addr;
++      unsigned int            desc_buf;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      // GMAC-0, HW-TXQ
++      // The GMAC-0 and GMAC-0 maybe have different descriptor number
++      // so, not use for instruction
++      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC0_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
++                                              (dma_addr_t *)&toe->gmac[0].hwtxq_desc_base_dma) ;
++      toe->gmac[0].hwtxq_desc_base = desc_buf;
++      if (!desc_buf)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return  ;
++      }
++      memset((void *)desc_buf, 0,     TOE_GMAC0_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
++      writel((toe->gmac[0].hwtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC0_HWTXQ_DESC_POWER,
++                      TOE_GMAC0_DMA_BASE+ GMAC_HW_TX_QUEUE_BASE_REG);
++
++      // GMAC0 HW TX Q0-Q5
++      rwptr_reg.bits.wptr = 0;
++      rwptr_reg.bits.rptr = 0;
++      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              toe->gmac[0].hwtxq[i].desc_base = desc_buf;
++              desc_buf += TOE_GMAC0_HWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
++              writel(rwptr_reg.bits32, rwptr_addr);
++              rwptr_addr+=4;
++      }
++
++      // GMAC-1, HW-TXQ
++      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC1_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
++                                              (dma_addr_t *)&toe->gmac[1].hwtxq_desc_base_dma) ;
++      toe->gmac[1].hwtxq_desc_base = desc_buf;
++      if (!desc_buf)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return  ;
++      }
++      memset((void *)desc_buf, 0,     TOE_GMAC1_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
++      writel((toe->gmac[1].hwtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC1_HWTXQ_DESC_POWER,
++                      TOE_GMAC1_DMA_BASE+ GMAC_HW_TX_QUEUE_BASE_REG);
++
++      // GMAC1 HW TX Q0-Q5
++      rwptr_reg.bits.wptr = 0;
++      rwptr_reg.bits.rptr = 0;
++      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              toe->gmac[1].hwtxq[i].desc_base = desc_buf;
++              desc_buf += TOE_GMAC1_HWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
++              writel(rwptr_reg.bits32, rwptr_addr);
++              rwptr_addr+=4;
++      }
++}
++#endif
++
++/*----------------------------------------------------------------------
++*     toe_init_default_queue
++*     (1) Initialize the default 0/1 Queue Header
++*             Register: TOE_DEFAULT_Q0_HDR_BASE (0x60002000)
++*                               TOE_DEFAULT_Q1_HDR_BASE (0x60002008)
++*     (2)     Initialize Descriptors of Default Queue 0/1
++*----------------------------------------------------------------------*/
++static void toe_init_default_queue(void)
++{
++      TOE_INFO_T                              *toe;
++      volatile NONTOE_QHDR_T  *qhdr;
++      GMAC_RXDESC_T                   *desc_ptr;
++      DMA_SKB_SIZE_T                  skb_size;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T)),
++                                                                                      (dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
++      if (!desc_ptr)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return  ;
++      }
++      memset((void *)desc_ptr, 0, TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T));
++      toe->gmac[0].default_desc_base = (unsigned int)desc_ptr;
++      toe->gmac[0].default_desc_num = TOE_DEFAULT_Q0_DESC_NUM;
++      qhdr = (volatile NONTOE_QHDR_T *)TOE_DEFAULT_Q0_HDR_BASE;
++      qhdr->word0.base_size = ((unsigned int)toe->gmac[0].default_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_DEFAULT_Q0_DESC_POWER;
++      qhdr->word1.bits32 = 0;
++      toe->gmac[0].rx_rwptr.bits32 = 0;
++      toe->gmac[0].default_qhdr = (NONTOE_QHDR_T *)qhdr;
++      desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q1_DESC_NUM * sizeof(GMAC_RXDESC_T)),
++                                                                                      (dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
++      if (!desc_ptr)
++      {
++              printk("%s::DMA_MALLOC fail !\n",__func__);
++              return  ;
++      }
++      memset((void *)desc_ptr, 0, TOE_DEFAULT_Q1_DESC_NUM * sizeof(GMAC_RXDESC_T));
++      toe->gmac[1].default_desc_base = (unsigned int)desc_ptr;
++      toe->gmac[1].default_desc_num = TOE_DEFAULT_Q1_DESC_NUM;
++      qhdr = (volatile NONTOE_QHDR_T *)TOE_DEFAULT_Q1_HDR_BASE;
++      qhdr->word0.base_size = ((unsigned int)toe->gmac[1].default_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_DEFAULT_Q1_DESC_POWER;
++      qhdr->word1.bits32 = 0;
++      toe->gmac[1].rx_rwptr.bits32 = 0;
++      toe->gmac[1].default_qhdr = (NONTOE_QHDR_T *)qhdr;
++
++      skb_size.bits.hw_skb_size = HW_RX_BUF_SIZE;
++      skb_size.bits.sw_skb_size = SW_RX_BUF_SIZE;
++      writel(skb_size.bits32, TOE_GLOBAL_BASE + GLOBAL_DMA_SKB_SIZE_REG);
++}
++
++/*----------------------------------------------------------------------
++*     toe_init_interrupt_queue
++*     (1) Initialize the Interrupt Queue Header
++*             Register: TOE_INTR_Q_HDR_BASE (0x60002080)
++*     (2)     Initialize Descriptors of Interrupt Queues
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_RXTOE
++static void toe_init_interrupt_queue(void)
++{
++      TOE_INFO_T                              *toe;
++      volatile NONTOE_QHDR_T  *qhdr;
++      INTR_QHDR_T                             *desc_ptr;
++      // unsigned int                 desc_buf_addr;
++      int                                             i;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      desc_ptr = (INTR_QHDR_T *)DMA_MALLOC((TOE_INTR_QUEUE_NUM * TOE_INTR_DESC_NUM * sizeof(INTR_QHDR_T)),
++                                                                                      (dma_addr_t *)&toe->intr_desc_base_dma);
++      if (!desc_ptr)
++      {
++              printk("%s::DMA_MALLOC interrupt queue fail !\n",__func__);
++              return  ;
++      }
++      /*
++      desc_buf_addr = (unsigned int)DMA_MALLOC((TOE_INTR_DESC_NUM * sizeof(TOE_QHDR_T)),
++                                                                                              (dma_addr_t *)&toe->intr_buf_base_dma);
++      if (!desc_buf_addr)
++      {
++              printk("%s::DMA_MALLOC interrupt desc fail !\n",__func__);
++              return  ;
++      }*/
++      printk("#### %s::Intr Q desc %x\n", __func__, (u32)desc_ptr);
++
++      memset((void *)desc_ptr, 0, TOE_INTR_QUEUE_NUM * TOE_INTR_DESC_NUM * sizeof(INTR_QHDR_T));
++//    memset((void *)desc_buf_addr, 0, TOE_INTR_DESC_NUM * sizeof(TOE_QHDR_T));
++      toe->intr_desc_base = (unsigned int)desc_ptr;
++      toe->intr_desc_num = TOE_INTR_DESC_NUM;
++
++      qhdr = (volatile NONTOE_QHDR_T *)TOE_INTR_Q_HDR_BASE;
++//    intrq = (INTRQ_INFO_T*) &toe->intrq[0];
++      for (i=0; i<TOE_INTR_QUEUE_NUM; i++, qhdr++)
++      {
++              qhdr->word0.base_size = ((unsigned int)toe->intr_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_INTR_DESC_POWER;
++              qhdr->word1.bits32 = 0;
++              desc_ptr += TOE_INTR_DESC_NUM;
++      }
++}
++
++#endif
++
++/*----------------------------------------------------------------------
++*     toe_init_interrupt_config
++*     Interrupt Select Registers are used to map interrupt to int0 or int1
++*     Int0 and int1 are wired to CPU 0/1 GMAC 0/1
++*     Interrupt Device Inteface data are used to pass device info to
++*             upper device deiver or store status/statistics
++*     ISR handler
++*             (1) If status bit ON but masked, the prinf error message (bug issue)
++*             (2) If select bits are for me, handle it, else skip to let
++*                     the other ISR handles it.
++*  Notes:
++*             GMACx init routine (for eCOS) or open routine (for Linux)
++*       enable the interrupt bits only which are selected for him.
++*
++*     Default Setting:
++*             GMAC0 intr bits ------> int0 ----> eth0
++*             GMAC1 intr bits ------> int1 ----> eth1
++*             TOE intr -------------> int0 ----> eth0
++*             Classification Intr --> int0 ----> eth0
++*             Default Q0 -----------> int0 ----> eth0
++*             Default Q1 -----------> int1 ----> eth1
++*----------------------------------------------------------------------*/
++static void toe_init_interrupt_config(void)
++{
++      // clear all status bits
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++
++      // Init select registers
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++
++      // disable all interrupt
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_0_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_2_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_3_REG);
++      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++}
++
++/*----------------------------------------------------------------------
++*     toe_init_gmac
++*----------------------------------------------------------------------*/
++static void toe_init_gmac(struct net_device *dev)
++{
++      GMAC_INFO_T             *tp = dev->priv;
++      TOE_INFO_T              *toe;
++      u32                     data;
++
++      if (!gmac_initialized)
++              return ;
++
++      if (!tp->existed)
++              return;
++
++      tp->dev = dev;
++      tp->flow_control_enable = 1;
++      tp->pre_phy_status = LINK_DOWN;
++      tp->full_duplex_status = tp->full_duplex_cfg;
++      tp->speed_status = tp->speed_status;
++
++#if 0
++   /* get mac address from FLASH */
++    gmac_get_mac_address();
++#endif
++
++    /* set PHY register to start autonegition process */
++    gmac_set_phy_status(dev);
++
++      /* GMAC initialization */
++      if ( toe_gmac_init_chip(dev) )
++      {
++              printk ("GMAC %d init fail\n", tp->port_id);
++      }
++
++    /* clear statistic counter */
++    toe_gmac_clear_counter(dev);
++
++      memset((void *)&tp->ifStatics, 0, sizeof(struct net_device_stats));
++
++      /* -----------------------------------------------------------
++      Enable GMAC interrupt & disable loopback
++      Notes:
++              GMACx init routine (for eCOS) or open routine (for Linux)
++              enable the interrupt bits only which are selected for him.
++      --------------------------------------------------------------*/
++      toe = (TOE_INFO_T *)&toe_private_data;
++
++      // Enable Interrupt Bits
++      if (tp->port_id == 0)
++      {
++              tp->intr0_selected =    GMAC0_TXDERR_INT_BIT     | GMAC0_TXPERR_INT_BIT         |
++                                      GMAC0_RXDERR_INT_BIT     | GMAC0_RXPERR_INT_BIT         |
++                                  GMAC0_SWTQ05_FIN_INT_BIT | GMAC0_SWTQ05_EOF_INT_BIT |
++                                  GMAC0_SWTQ04_FIN_INT_BIT | GMAC0_SWTQ04_EOF_INT_BIT |
++                                  GMAC0_SWTQ03_FIN_INT_BIT | GMAC0_SWTQ03_EOF_INT_BIT |
++                                  GMAC0_SWTQ02_FIN_INT_BIT | GMAC0_SWTQ02_EOF_INT_BIT |
++                                  GMAC0_SWTQ01_FIN_INT_BIT | GMAC0_SWTQ01_EOF_INT_BIT |
++                                  GMAC0_SWTQ00_FIN_INT_BIT | GMAC0_SWTQ00_EOF_INT_BIT;
++
++#ifdef GMAX_TX_INTR_DISABLED
++          tp->intr0_enabled =         0;
++#else
++          tp->intr0_enabled =         GMAC0_SWTQ00_FIN_INT_BIT | GMAC0_SWTQ00_EOF_INT_BIT;
++#endif
++
++          tp->intr1_selected =        TOE_IQ_ALL_BITS                  | TOE_CLASS_RX_INT_BITS        |
++                                                      GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT |
++                                                      GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT |
++                                                      DEFAULT_Q0_INT_BIT;
++          tp->intr1_enabled =         DEFAULT_Q0_INT_BIT | TOE_IQ_ALL_BITS;
++          tp->intr2_selected =        0xffffffff;      // TOE Queue 32-63 FUUL Intr
++          tp->intr2_enabled =         0xffffffff;
++          tp->intr3_selected =        0xffffffff;      // TOE Queue 0-31 FUUL Intr
++          tp->intr3_enabled =         0xffffffff;
++          tp->intr4_selected =        GMAC0_INT_BITS | CLASS_RX_FULL_INT_BITS |
++                                                      HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
++          tp->intr4_enabled =         GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT;
++
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) & ~tp->intr0_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG) & ~tp->intr1_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG) & ~tp->intr2_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG) & ~tp->intr3_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG) & ~tp->intr4_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++      }
++      else
++      {
++              tp->intr0_selected =    GMAC1_TXDERR_INT_BIT     | GMAC1_TXPERR_INT_BIT         |
++                                      GMAC1_RXDERR_INT_BIT     | GMAC1_RXPERR_INT_BIT         |
++                                  GMAC1_SWTQ15_FIN_INT_BIT | GMAC1_SWTQ15_EOF_INT_BIT |
++                                  GMAC1_SWTQ14_FIN_INT_BIT | GMAC1_SWTQ14_EOF_INT_BIT |
++                                  GMAC1_SWTQ13_FIN_INT_BIT | GMAC1_SWTQ13_EOF_INT_BIT |
++                                  GMAC1_SWTQ12_FIN_INT_BIT | GMAC1_SWTQ12_EOF_INT_BIT |
++                                  GMAC1_SWTQ11_FIN_INT_BIT | GMAC1_SWTQ11_EOF_INT_BIT |
++                                  GMAC1_SWTQ10_FIN_INT_BIT | GMAC1_SWTQ10_EOF_INT_BIT;
++#ifdef GMAX_TX_INTR_DISABLED
++          tp->intr0_enabled =         0;
++#else
++          tp->intr0_enabled =         GMAC1_SWTQ10_FIN_INT_BIT | GMAC1_SWTQ10_EOF_INT_BIT;
++#endif
++
++          tp->intr1_selected =        DEFAULT_Q1_INT_BIT;
++          tp->intr1_enabled =         DEFAULT_Q1_INT_BIT | TOE_IQ_ALL_BITS;
++          tp->intr2_selected =        0;       // TOE Queue 32-63 FUUL Intr
++          tp->intr2_enabled =         0;
++          tp->intr3_selected =        0;       // TOE Queue 0-31 FUUL Intr
++          tp->intr3_enabled =         0;
++          tp->intr4_selected =        GMAC1_INT_BITS;
++          tp->intr4_enabled =         GMAC1_INT_BITS;
++
++          if (toe->gmac[0].existed != GMAC_EXISTED_FLAG)
++          {
++              tp->intr1_selected      |=      TOE_IQ_ALL_BITS | TOE_CLASS_RX_INT_BITS |
++                                                              GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT |
++                                                              GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT;
++              tp->intr1_enabled       |=      TOE_IQ_ALL_BITS;
++              tp->intr2_selected      |=      0xffffffff;      // TOE Queue 32-63 FUUL Intr
++              tp->intr2_enabled       |=      0xffffffff;
++              tp->intr3_selected      |=      0xffffffff;      // TOE Queue 0-31 FUUL Intr
++              tp->intr3_enabled       |=      0xffffffff;
++              tp->intr4_selected      |=      CLASS_RX_FULL_INT_BITS |
++                                                              HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
++              tp->intr4_enabled       |=      SWFQ_EMPTY_INT_BIT;
++              }
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) | tp->intr0_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG) | tp->intr1_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG) | tp->intr2_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG) | tp->intr3_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
++          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG) | tp->intr4_selected;
++          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++      }
++
++      // enable only selected bits
++      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_0_REG,
++                                      tp->intr0_enabled, tp->intr0_selected);
++      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_1_REG,
++                                      tp->intr1_enabled, tp->intr1_selected);
++      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_2_REG,
++                                      tp->intr2_enabled, tp->intr2_selected);
++      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_3_REG,
++                                      tp->intr3_enabled, tp->intr3_selected);
++      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
++                                      tp->intr4_enabled, tp->intr4_selected);
++
++    /* start DMA process */
++      toe_gmac_hw_start(dev);
++
++    /* enable tx/rx register */
++    toe_gmac_enable_tx_rx(dev);
++
++//    toe_gmac_enable_interrupt(tp->irq);
++
++    return ;
++}
++
++
++/*----------------------------------------------------------------------
++* toe_gmac_sw_reset
++*----------------------------------------------------------------------*/
++static void toe_gmac_sw_reset(void)
++{
++      unsigned int    reg_val;
++      reg_val = readl(GMAC_GLOBAL_BASE_ADDR+GLOBAL_RESET_REG) | 0x00000060;   /* GMAC0 S/W reset */
++    writel(reg_val,GMAC_GLOBAL_BASE_ADDR+GLOBAL_RESET_REG);
++    udelay(100);
++    return;
++}
++
++/*----------------------------------------------------------------------
++*     toe_gmac_init_chip
++*----------------------------------------------------------------------*/
++static int toe_gmac_init_chip(struct net_device *dev)
++{
++      GMAC_INFO_T     *tp = dev->priv;
++      GMAC_CONFIG2_T  config2_val;
++      GMAC_CONFIG0_T  config0,config0_mask;
++      GMAC_CONFIG1_T  config1;
++      #ifdef CONFIG_SL351x_NAT
++      GMAC_CONFIG3_T  config3_val;
++      #endif
++      GMAC_TX_WCR0_T  hw_weigh;
++      GMAC_TX_WCR1_T  sw_weigh;
++//    GMAC_HASH_ENABLE_REG0_T hash_ctrl;
++//
++#if 0 /* mac address will be set in late_initcall */
++      struct sockaddr sock;
++      // GMAC_AHB_WEIGHT_T    ahb_weight, ahb_weight_mask;
++
++
++      /* set station MAC address1 and address2 */
++      memcpy(&sock.sa_data[0],&eth_mac[tp->port_id][0],6);
++      gmac_set_mac_address(dev,(void *)&sock);
++#endif
++
++      /* set RX_FLTR register to receive all multicast packet */
++      gmac_write_reg(tp->base_addr, GMAC_RX_FLTR, 0x00000007,0x0000001f);
++      //    gmac_write_reg(tp->base_addr, GMAC_RX_FLTR, 0x00000007,0x0000001f);
++      //gmac_write_reg(tp->base_addr, GMAC_RX_FLTR,0x00000007,0x0000001f);
++
++      /* set per packet buffer size */
++      //      config1.bits32 = 0x002004;      //next version
++      /* set flow control threshold */
++      config1.bits32 = 0;
++      config1.bits.set_threshold = 32 / 2;
++      config1.bits.rel_threshold = 32 / 4 * 3;
++      gmac_write_reg(tp->base_addr, GMAC_CONFIG1, config1.bits32, 0xffffffff);
++
++      /* set flow control threshold */
++      config2_val.bits32 = 0;
++      config2_val.bits.set_threshold = TOE_SW_FREEQ_DESC_NUM/2;
++      config2_val.bits.rel_threshold = TOE_SW_FREEQ_DESC_NUM*3/4;
++      gmac_write_reg(tp->base_addr, GMAC_CONFIG2, config2_val.bits32,0xffffffff);
++
++      #ifdef CONFIG_SL351x_NAT
++      /* set HW free queue flow control threshold */
++      config3_val.bits32 = 0;
++      config3_val.bits.set_threshold = PAUSE_SET_HW_FREEQ;
++      config3_val.bits.rel_threshold = PAUSE_REL_HW_FREEQ;
++      gmac_write_reg(tp->base_addr, GMAC_CONFIG3, config3_val.bits32,0xffffffff);
++      #endif
++      /* set_mcast_filter mask*/
++      //      gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL0,0x0,0xffffffff);
++      //  gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL1,0x0,0xffffffff);
++
++      /* disable TX/RX and disable internal loop back */
++      config0.bits32 = 0;
++      config0_mask.bits32 = 0;
++
++      //debug_Aaron
++#ifdef        L2_jumbo_frame
++      config0.bits.max_len = 5;
++#else
++      config0.bits.max_len = 2;
++#endif
++
++      if (tp->flow_control_enable==1)
++      {
++              config0.bits.tx_fc_en = 1; /* enable tx flow control */
++              config0.bits.rx_fc_en = 1; /* enable rx flow control */
++              printk("Enable MAC Flow Control...\n");
++      }
++      else
++      {
++              config0.bits.tx_fc_en = 0; /* disable tx flow control */
++              config0.bits.rx_fc_en = 0; /* disable rx flow control */
++              printk("Disable MAC Flow Control...\n");
++      }
++      config0.bits.dis_rx = 1;  /* disable rx */
++      config0.bits.dis_tx = 1;  /* disable tx */
++      config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
++      config0.bits.rx_err_detect = 1;
++      config0.bits.rgmii_en = 0;
++      config0.bits.rgmm_edge = 1;
++      config0.bits.rxc_inv = 0;
++      config0.bits.ipv4_rx_chksum = 1;  /* enable H/W to check ip checksum */
++      config0.bits.ipv6_rx_chksum = 1;  /* enable H/W to check ip checksum */
++      config0.bits.port0_chk_hwq = 1; // GaryChen 3/24/2006 2:26PM
++      config0.bits.port1_chk_hwq = 1; // GaryChen 3/24/2006 2:26PM
++      config0.bits.port0_chk_toeq = 1;
++      config0.bits.port1_chk_toeq = 1;
++      config0.bits.port0_chk_classq = 1;
++      config0.bits.port1_chk_classq = 1;
++
++      config0_mask.bits.max_len = 7;
++      config0_mask.bits.tx_fc_en = 1;
++      config0_mask.bits.rx_fc_en = 1;
++      config0_mask.bits.dis_rx = 1;
++      config0_mask.bits.dis_tx = 1;
++      config0_mask.bits.loop_back = 1;
++      config0_mask.bits.rgmii_en = 1;
++      config0_mask.bits.rgmm_edge = 1;
++      config0_mask.bits.rxc_inv = 1;
++      config0_mask.bits.ipv4_rx_chksum = 1;
++      config0_mask.bits.ipv6_rx_chksum = 1;
++      config0_mask.bits.port0_chk_hwq = 1;
++      config0_mask.bits.port1_chk_hwq = 1;
++      config0_mask.bits.port0_chk_toeq = 1;
++      config0_mask.bits.port1_chk_toeq = 1;
++      config0_mask.bits.port0_chk_classq = 1;
++      config0_mask.bits.port1_chk_classq = 1;
++      config0_mask.bits.rx_err_detect = 1;
++
++      #if 0
++      config0.bits.dis_rx = 1;  /* disable rx */
++      config0.bits.dis_tx = 1;  /* disable tx */
++      config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
++      config0.bits.txc_inv = 0;
++      config0.bits.rgmii_en = 0;
++      config0.bits.rgmm_edge = 1;
++      config0.bits.rxc_inv = 1;
++      config0.bits.ipv4_tss_rx_en = 1;  /* enable H/W to check ip checksum */
++      config0.bits.ipv6_tss_rx_en = 1;  /* enable H/W to check ip checksum */
++
++      config0_mask.bits.max_len = 3;
++      config0_mask.bits.tx_fc_en = 1;
++      config0_mask.bits.rx_fc_en = 1;
++      config0_mask.bits.dis_rx = 1;
++      config0_mask.bits.dis_tx = 1;
++      config0_mask.bits.loop_back = 1;
++      config0_mask.bits.rgmii_en = 1;
++      config0_mask.bits.rgmm_edge = 1;
++      config0_mask.bits.txc_inv = 1;
++      config0_mask.bits.rxc_inv = 1;
++      config0_mask.bits.ipv4_tss_rx_en = 1;
++      config0_mask.bits.ipv6_tss_rx_en = 1;
++      #endif
++
++      gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
++
++      #if 1
++      hw_weigh.bits32 = 0;
++      hw_weigh.bits.hw_tq3 = 1;
++      hw_weigh.bits.hw_tq2 = 1;
++      hw_weigh.bits.hw_tq1 = 1;
++      hw_weigh.bits.hw_tq0 = 1;
++      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_0_REG, hw_weigh.bits32, 0xffffffff);
++
++      sw_weigh.bits32 = 0;
++      sw_weigh.bits.sw_tq5 = 1;
++      sw_weigh.bits.sw_tq4 = 1;
++      sw_weigh.bits.sw_tq3 = 1;
++      sw_weigh.bits.sw_tq2 = 1;
++      sw_weigh.bits.sw_tq1 = 1;
++      sw_weigh.bits.sw_tq0 = 1;
++      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_1_REG, sw_weigh.bits32, 0xffffffff);
++      #endif
++
++      #if 0
++      ahb_weight.bits32 = 0;
++      ahb_weight_mask.bits32 = 0;
++      ahb_weight.bits.rx_weight = 1;
++      ahb_weight.bits.tx_weight = 1;
++      ahb_weight.bits.hash_weight = 1;
++      ahb_weight.bits.pre_req = 0x1f;
++      ahb_weight.bits.tqDV_threshold = 0;
++      ahb_weight_mask.bits.rx_weight = 0x1f;
++      ahb_weight_mask.bits.tx_weight = 0x1f;
++      ahb_weight_mask.bits.hash_weight = 0x1f;
++      ahb_weight_mask.bits.pre_req = 0x1f;
++      ahb_weight_mask.bits.tqDV_threshold = 0x1f;
++      gmac_write_reg(tp->dma_base_addr, GMAC_AHB_WEIGHT_REG, ahb_weight.bits32, ahb_weight_mask.bits32);
++      #endif
++
++      #if defined(CONFIG_SL351x_NAT) || defined(CONFIG_SL351x_RXTOE)
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR0, IPPROTO_TCP, 0xffffffff);
++      #endif
++      #ifdef CONFIG_SL351x_NAT
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR1, IPPROTO_UDP, 0xffffffff);
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR2, IPPROTO_GRE, 0xffffffff);
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR3, 0xff, 0xffffffff);
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR4, 0xff, 0xffffffff);
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR5, 0xff, 0xffffffff);
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR6, 0xff, 0xffffffff);
++      gmac_write_reg(tp->dma_base_addr, GMAC_SPR7, 0xff, 0xffffffff);
++
++      sl351x_nat_init();
++      #endif
++
++      #ifdef CONFIG_SL351x_RXTOE
++      /* setup matching rule to TOE */
++      sl351x_toe_init();
++      #endif
++
++      // for A1 ASIC version
++//    hash_ctrl.bits32 = 0;
++//    hash_ctrl.bits.timing = 6;
++//    gmac_write_reg(tp->dma_base_addr, GMAC_HASH_ENGINE_REG0, hash_ctrl.bits32, 0xffffffff);
++
++      return (0);
++}
++
++/*----------------------------------------------------------------------
++*     toe_gmac_enable_tx_rx
++*----------------------------------------------------------------------*/
++static void toe_gmac_enable_tx_rx(struct net_device *dev)
++{
++      GMAC_INFO_T             *tp = dev->priv;
++      GMAC_CONFIG0_T  config0,config0_mask;
++
++    /* enable TX/RX */
++    config0.bits32 = 0;
++    config0_mask.bits32 = 0;
++    config0.bits.dis_rx = 0;  /* enable rx */
++    config0.bits.dis_tx = 0;  /* enable tx */
++    config0_mask.bits.dis_rx = 1;
++    config0_mask.bits.dis_tx = 1;
++    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
++}
++/*----------------------------------------------------------------------
++*     toe_gmac_disable_rx
++*----------------------------------------------------------------------*/
++#if 0
++static void toe_gmac_disable_rx(struct net_device *dev)
++{
++      GMAC_INFO_T             *tp = dev->priv;
++      GMAC_CONFIG0_T  config0,config0_mask;
++
++    /* enable TX/RX */
++    config0.bits32 = 0;
++    config0_mask.bits32 = 0;
++    config0.bits.dis_rx = 1;  /* disable rx */
++//    config0.bits.dis_tx = 1;  /* disable tx */
++    config0_mask.bits.dis_rx = 1;
++//     config0_mask.bits.dis_tx = 1;
++    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
++}
++#endif
++/*----------------------------------------------------------------------
++*     toe_gmac_enable_rx
++*----------------------------------------------------------------------*/
++#if 0
++static void toe_gmac_enable_rx(struct net_device *dev)
++{
++      GMAC_INFO_T             *tp = dev->priv;
++      GMAC_CONFIG0_T  config0,config0_mask;
++
++    /* enable TX/RX */
++    config0.bits32 = 0;
++    config0_mask.bits32 = 0;
++    config0.bits.dis_rx = 0;  /* enable rx */
++//    config0.bits.dis_tx = 0;  /* enable tx */
++    config0_mask.bits.dis_rx = 1;
++//    config0_mask.bits.dis_tx = 1;
++    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
++}
++#endif
++/*----------------------------------------------------------------------
++*     toe_gmac_disable_tx_rx
++*----------------------------------------------------------------------*/
++static void toe_gmac_disable_tx_rx(struct net_device *dev)
++{
++      GMAC_INFO_T             *tp = dev->priv;
++      GMAC_CONFIG0_T  config0,config0_mask;
++
++    /* enable TX/RX */
++    config0.bits32 = 0;
++    config0_mask.bits32 = 0;
++    config0.bits.dis_rx = 1;  /* disable rx */
++    config0.bits.dis_tx = 1;  /* disable tx */
++    config0_mask.bits.dis_rx = 1;
++    config0_mask.bits.dis_tx = 1;
++    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
++}
++
++/*----------------------------------------------------------------------
++*     toe_gmac_hw_start
++*----------------------------------------------------------------------*/
++static void toe_gmac_hw_start(struct net_device *dev)
++{
++      GMAC_INFO_T                             *tp = (GMAC_INFO_T *)dev->priv;
++      GMAC_DMA_CTRL_T                 dma_ctrl, dma_ctrl_mask;
++
++
++    /* program dma control register */
++      dma_ctrl.bits32 = 0;
++      dma_ctrl.bits.rd_enable = 1;
++      dma_ctrl.bits.td_enable = 1;
++      dma_ctrl.bits.loopback = 0;
++      dma_ctrl.bits.drop_small_ack = 0;
++      dma_ctrl.bits.rd_prot = 0;
++      dma_ctrl.bits.rd_burst_size = 3;
++      dma_ctrl.bits.rd_insert_bytes = RX_INSERT_BYTES;
++      dma_ctrl.bits.rd_bus = 3;
++      dma_ctrl.bits.td_prot = 0;
++      dma_ctrl.bits.td_burst_size = 3;
++      dma_ctrl.bits.td_bus = 3;
++
++      dma_ctrl_mask.bits32 = 0;
++      dma_ctrl_mask.bits.rd_enable = 1;
++      dma_ctrl_mask.bits.td_enable = 1;
++      dma_ctrl_mask.bits.loopback = 1;
++      dma_ctrl_mask.bits.drop_small_ack = 1;
++      dma_ctrl_mask.bits.rd_prot = 3;
++      dma_ctrl_mask.bits.rd_burst_size = 3;
++      dma_ctrl_mask.bits.rd_insert_bytes = 3;
++      dma_ctrl_mask.bits.rd_bus = 3;
++      dma_ctrl_mask.bits.td_prot = 0x0f;
++      dma_ctrl_mask.bits.td_burst_size = 3;
++      dma_ctrl_mask.bits.td_bus = 3;
++
++      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++
++    return;
++}
++
++/*----------------------------------------------------------------------
++*     toe_gmac_hw_stop
++*----------------------------------------------------------------------*/
++static void toe_gmac_hw_stop(struct net_device *dev)
++{
++      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
++      GMAC_DMA_CTRL_T         dma_ctrl, dma_ctrl_mask;
++
++    /* program dma control register */
++      dma_ctrl.bits32 = 0;
++      dma_ctrl.bits.rd_enable = 0;
++      dma_ctrl.bits.td_enable = 0;
++
++      dma_ctrl_mask.bits32 = 0;
++      dma_ctrl_mask.bits.rd_enable = 1;
++      dma_ctrl_mask.bits.td_enable = 1;
++
++      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++}
++
++/*----------------------------------------------------------------------
++*     toe_gmac_clear_counter
++*----------------------------------------------------------------------*/
++static int toe_gmac_clear_counter (struct net_device *dev)
++{
++      GMAC_INFO_T     *tp = (GMAC_INFO_T *)dev->priv;
++
++    /* clear counter */
++    gmac_read_reg(tp->base_addr, GMAC_IN_DISCARDS);
++    gmac_read_reg(tp->base_addr, GMAC_IN_ERRORS);
++    gmac_read_reg(tp->base_addr, GMAC_IN_MCAST);
++    gmac_read_reg(tp->base_addr, GMAC_IN_BCAST);
++    gmac_read_reg(tp->base_addr, GMAC_IN_MAC1);
++    gmac_read_reg(tp->base_addr, GMAC_IN_MAC2);
++              tp->ifStatics.tx_bytes = 0;
++              tp->ifStatics.tx_packets = 0;
++              tp->ifStatics.tx_errors = 0;
++              tp->ifStatics.rx_bytes = 0;
++              tp->ifStatics.rx_packets = 0;
++              tp->ifStatics.rx_errors = 0;
++              tp->ifStatics.rx_dropped = 0;
++      return (0);
++}
++
++
++/*----------------------------------------------------------------------
++*     toe_gmac_tx_complete
++*----------------------------------------------------------------------*/
++static  void toe_gmac_tx_complete(GMAC_INFO_T *tp, unsigned int tx_qid,
++                                                                              struct net_device *dev, int interrupt)
++{
++      volatile GMAC_TXDESC_T  *curr_desc;
++      GMAC_TXDESC_0_T                 word0;
++      GMAC_TXDESC_1_T                 word1;
++      unsigned int                    desc_count;
++//    struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
++      GMAC_SWTXQ_T                    *swtxq;
++      DMA_RWPTR_T                             rwptr;
++
++      /* get tx H/W completed descriptor virtual address */
++      /* check tx status and accumulate tx statistics */
++      swtxq = &tp->swtxq[tx_qid];
++      swtxq->intr_cnt++;
++      for (;;)
++      {
++              rwptr.bits32 = readl(swtxq->rwptr_reg);
++              if (rwptr.bits.rptr == swtxq->finished_idx)
++                      break;
++      curr_desc = (volatile GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
++//            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_FROMDEVICE);
++              word0.bits32 = curr_desc->word0.bits32;
++              word1.bits32 = curr_desc->word1.bits32;
++
++              if (word0.bits.status_tx_ok)
++              {
++                      tp->ifStatics.tx_bytes += word1.bits.byte_count;
++                      desc_count = word0.bits.desc_count;
++                      if (desc_count==0)
++                      {
++                              printk("%s::Desc 0x%x = 0x%x, desc_count=%d\n",__func__, (u32)curr_desc, word0.bits32, desc_count);
++                              while(1);
++                      }
++                      while (--desc_count)
++                      {
++                              word0.bits.status_tx_ok = 0;
++                              curr_desc->word0.bits32 = word0.bits32;
++                              swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
++                              curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
++                              word0.bits32 = curr_desc->word0.bits32;
++#ifdef _DUMP_TX_TCP_CONTENT
++                              if (curr_desc->word0.bits.buffer_size < 16)
++                              {
++                                      int a;
++                                      char *datap;
++                                      printk("\t Tx Finished Desc 0x%x Len %d Addr 0x%08x: ", (u32)curr_desc, curr_desc->word0.bits.buffer_size, curr_desc->word2.buf_adr);
++                                      datap = (char *)__va(curr_desc->word2.buf_adr);
++                                      for (a=0; a<8 && a<curr_desc->word0.bits.buffer_size; a++, datap++)
++                                      {
++                                              printk("0x%02x ", *datap);
++                                      }
++                                      printk("\n");
++                              }
++#endif
++                      }
++
++                      word0.bits.status_tx_ok = 0;
++                      if (swtxq->tx_skb[swtxq->finished_idx])
++                      {
++                              if (interrupt)
++                                      dev_kfree_skb_irq(swtxq->tx_skb[swtxq->finished_idx]);
++                              else
++                                      dev_kfree_skb(swtxq->tx_skb[swtxq->finished_idx]);
++                              swtxq->tx_skb[swtxq->finished_idx] = NULL;
++                      }
++                      curr_desc->word0.bits32 = word0.bits32;
++                      swtxq->curr_finished_desc = (GMAC_TXDESC_T *)curr_desc;
++                      swtxq->total_finished++;
++                      tp->ifStatics.tx_packets++;
++                      swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
++              }
++              else
++              {
++                      // tp->ifStatics.tx_errors++;
++                      // printk("%s::Tx Descriptor is !!!\n",__func__);
++                      // wait ready by breaking
++                      break;
++              }
++      }
++
++      if (netif_queue_stopped(dev))
++      {
++              netif_wake_queue(dev);
++      }
++}
++
++/*----------------------------------------------------------------------
++*     gmac_start_xmit
++*----------------------------------------------------------------------*/
++static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++      GMAC_INFO_T                     *tp= dev->priv;
++//    static unsigned int     pcount = 0;
++//    unsigned int                    tx_qid;
++    DMA_RWPTR_T                               rwptr;
++      volatile GMAC_TXDESC_T  *curr_desc;
++      int                                     snd_pages = skb_shinfo(skb)->nr_frags + 1;  /* get number of descriptor */
++      int                                     frag_id = 0;
++      int                                     len, total_len = skb->len;
++      struct net_device_stats *isPtr;
++      unsigned int                    free_desc;
++      GMAC_SWTXQ_T                    *swtxq;
++      register unsigned long  word0, word1, word2, word3;
++      unsigned short                  wptr, rptr;
++#ifdef        L2_jumbo_frame
++      int header_len = skb->len;
++      struct iphdr    *ip_hdr;
++    struct tcphdr     *tcp_hdr;
++    int             tcp_hdr_len;
++    unsigned char     *ptr;
++    int             data_len,a;
++    unsigned int    val;
++#endif
++
++#ifdef GMAC_LEN_1_2_ISSUE
++      int                                             total_pages;
++      total_pages = snd_pages;
++#endif
++
++      isPtr = (struct net_device_stats *)&tp->ifStatics;
++#if 1
++      if (skb->len >= 0x10000)
++      {
++//            spin_unlock(&tp->tx_mutex);
++              isPtr->tx_dropped++;
++              printk("%s::[GMAC %d] skb->len %d >= 64K\n", __func__, tp->port_id, skb->len);
++              netif_stop_queue(dev);
++              return 1;
++    }
++#endif
++
++#if 0
++      if (storlink_ctl.recvfile==2)
++      {
++          printk("snd_pages=%d skb->len=%d\n",snd_pages,skb->len);
++      }
++#endif
++
++#ifdef GMAC_USE_TXQ0
++      #define tx_qid  0
++#endif
++
++      swtxq = &tp->swtxq[tx_qid];
++
++//    spin_lock(&tp->tx_mutex);
++    rwptr.bits32 = readl(swtxq->rwptr_reg);
++      wptr = rwptr.bits.wptr;
++      rptr = rwptr.bits.rptr;
++
++      // check finished desc or empty BD
++      // cannot check by read ptr of RW PTR register,
++      // because the HW complete to send but the SW may NOT handle it
++#ifndef       GMAX_TX_INTR_DISABLED
++      if (wptr >= swtxq->finished_idx)
++              free_desc = swtxq->total_desc_num - wptr - 1 + swtxq->finished_idx;
++      else
++              free_desc = swtxq->finished_idx - wptr - 1;
++
++      if (free_desc < snd_pages)
++      {
++//            spin_unlock(&tp->tx_mutex);
++              isPtr->tx_dropped++;
++//            printk("GMAC %d No available descriptor!\n", tp->port_id);
++              netif_stop_queue(dev);
++              return 1;
++    }
++#else
++      toe_gmac_tx_complete(tp, tx_qid, dev, 0);
++
++      if (wptr >= swtxq->finished_idx)
++              free_desc = swtxq->total_desc_num - wptr - 1 + swtxq->finished_idx;
++      else
++              free_desc = swtxq->finished_idx - wptr - 1;
++      if (free_desc < snd_pages)
++      {
++//            spin_unlock(&tp->tx_mutex);
++              isPtr->tx_dropped++;
++//            printk("GMAC %d No available descriptor!\n", tp->port_id);
++              netif_stop_queue(dev);
++              return 1;
++    }
++
++#if 0
++      printk("1: free_desc=%d, wptr=%d, finished_idx=%d\n", free_desc, wptr, swtxq->finished_idx);
++      if ((free_desc < (snd_pages << 2)) ||
++          (free_desc < (swtxq->total_desc_num >> 2)))
++      {
++              printk("2: free_desc = %d\n", free_desc);
++              toe_gmac_tx_complete(tp, tx_qid, dev, 0);
++              rwptr.bits32 = readl(swtxq->rwptr_reg);
++              wptr = rwptr.bits.wptr;
++              if (wptr>= swtxq->finished_idx)
++                      free_desc = swtxq->total_desc_num - wptr -1 + swtxq->finished_idx;
++              else
++                      free_desc = swtxq->finished_idx - wptr - 1;
++      }
++#endif
++#endif
++
++#ifdef        L2_jumbo_frame
++//            data_len = skb->len - 14 - ip_hdr->ihl *4 - tcp_hdr_len;
++//            if ((skb->nh.iph->protocol == __constant_htons(ETH_P_IP)) && ((skb->nh.iph->protocol & 0x00ff)  == IPPROTO_TCP))
++//            if (skb->nh.iph->protocol == 0x006 && (skb->nh.iph->protocol == __constant_htons(ETH_P_IP)))
++              if (((skb->nh.iph->protocol & 0x00ff)  == IPPROTO_TCP))
++              {
++                              ip_hdr = (struct iphdr*)(skb->nh.iph);
++                              tcp_hdr = (struct tcphdr*)(skb->h.th);
++                              tcp_hdr_len = TCPHDRLEN(tcp_hdr) * 4;
++                              tcp_hdr_len = TCPHDRLEN(tcp_hdr) * 4;
++
++                              if ((skb->h.th->syn) && (tcp_hdr_len > 20))
++                              {
++                                      ptr = (unsigned char *)(tcp_hdr+1);
++                                      if ((ptr[0] == 0x02) && (ptr[1] == 0x04) && (ptr[2] == 0x07) && (ptr[3] == 0xba)) // 0x07 aa=2016-54=1962  ,0x07ba=2032-54=1978
++                                      {
++                                              ptr[2]=0x20;    //23
++                                              ptr[3]=0x00;    //00
++                                              printk("-----> Change MSS to 8K \n" );
++                                      }
++                              }
++              }
++//            if ((ip_hdr->protocol & 0x00ff) != IPPROTO_TCP)
++//            if ((tcp_hdr_len > 20) && (skb->h.th->syn))
++#endif
++
++
++#if 0
++      if (snd_pages > 1)
++              printk("-----> snd_pages=%d\n", snd_pages);
++      if (total_len > 1514)
++      {
++              printk("-----> total_len=%d\n", total_len);
++      }
++#endif
++
++    while (snd_pages)
++    {
++      char *pkt_datap;
++
++      curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + wptr;
++//            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_FROMDEVICE);
++#if 0
++//#if (GMAC_DEBUG==1)
++      // if curr_desc->word2.buf_adr !=0 means that the ISR does NOT handle it
++      // if (curr_desc->word2.buf_adr)
++      if (swtxq->tx_skb[wptr])
++      {
++              printk("Error! Stop due to TX descriptor's buffer is not freed!\n");
++              while(1);
++              dev_kfree_skb(swtxq->tx_skb[wptr]);
++              swtxq->tx_skb[wptr] = NULL;
++              }
++#endif
++
++              if (frag_id == 0)
++              {
++#if 0
++                      int i;
++                      pkt_datap = skb->data;
++                      len = total_len;
++                      for (i=0; i<skb_shinfo(skb)->nr_frags; i++)
++                      {
++                              skb_frag_t* frag = &skb_shinfo(skb)->frags[i];
++                              len -= frag->size;
++                      }
++#else
++                      pkt_datap = skb->data;
++                      len = total_len - skb->data_len;
++#endif
++              }
++              else
++              {
++                      skb_frag_t* frag = &skb_shinfo(skb)->frags[frag_id-1];
++                      pkt_datap = page_address(frag->page) + frag->page_offset;
++                      len = frag->size;
++                      if (len > total_len)
++                      {
++                              printk("===> Fatal Error! Send Frag size %d > Total Size %d!!!!!\n",
++                                      len, total_len);
++                      }
++              }
++
++              /* set TX descriptor */
++              /* copy packet to descriptor buffer address */
++              // curr_desc->word0.bits32 = len;    /* total frame byte count */
++              word0 = len;
++#ifdef        L2_jumbo_frame
++              word3 = (dev->mtu+14) | EOFIE_BIT;  //2016 ,2032
++#else
++              word3 = 1514 | EOFIE_BIT;
++#endif
++
++#ifdef DO_HW_CHKSUM
++#ifdef        L2_jumbo_frame
++              if (total_len >= (dev->mtu+14) && (skb->nh.iph->protocol == 0x011) && skb->nh.iph && (skb->nh.iph->frag_off & __constant_htons(0x3fff)))
++#else
++              if (total_len <= 1514 && ip_hdr(skb) && (ip_hdr(skb)->frag_off & __constant_htons(0x3fff)))
++#endif
++                      word1  = total_len |
++                                      TSS_IP_CHKSUM_BIT  |
++                                      TSS_IPV6_ENABLE_BIT |
++                                      TSS_MTU_ENABLE_BIT;
++              else
++                      word1 = total_len |
++                                      TSS_UDP_CHKSUM_BIT |
++                                      TSS_TCP_CHKSUM_BIT |
++                                      TSS_IP_CHKSUM_BIT  |
++                                      TSS_IPV6_ENABLE_BIT |
++                                      TSS_MTU_ENABLE_BIT;
++#else
++              word1 = total_len | TSS_MTU_ENABLE_BIT;
++#endif
++              word2 = (unsigned long)__pa(pkt_datap);
++
++              if (frag_id == 0)
++              {
++                      word3 |= SOF_BIT;       // SOF
++              }
++
++              if (snd_pages == 1)
++              {
++                      word3 |= EOF_BIT;       // EOF
++                      swtxq->tx_skb[wptr] = skb;
++#ifdef CONFIG_SL351x_NAT
++                      if (nat_cfg.enabled && sl351x_nat_output(skb, tp->port_id))
++                              word1 |= TSS_IP_FIXED_LEN_BIT;
++#endif
++              }
++              else
++                      swtxq->tx_skb[wptr] = NULL;
++              // word1 |= TSS_IP_FIXED_LEN_BIT;
++#if 1
++#ifdef CONFIG_SL351x_RXTOE
++              // check if this frame has the mission to enable toe hash entry..
++              // if rx_max_pktsize ==0, do not enable RXTOE
++              if (TCP_SKB_CB(skb)->connection && storlink_ctl.rx_max_pktsize) {
++                      set_toeq_hdr(TCP_SKB_CB(skb)->connection, &toe_private_data, dev);
++              }
++#endif
++#endif
++#ifdef _DUMP_TX_TCP_CONTENT
++              if (len < 16 && frag_id && skb->h.th && (skb->h.th->source == __constant_htons(445) || skb->h.th->source == __constant_htons(139)))
++              {
++                      int a;
++                      char *datap;
++                      printk("Tx Desc 0x%x Frag %d Len %d [IP-ID 0x%x] 0x%08x: ", (u32)curr_desc, frag_id, len, htons(skb->nh.iph->id), (u32)pkt_datap);
++                      datap = (char *)pkt_datap;
++                      for (a=0; a<8 && a<len; a++, datap++)
++                      {
++                              printk("0x%02x ", *datap);
++                      }
++                      printk("\n");
++              }
++#endif
++
++#ifdef GMAC_LEN_1_2_ISSUE
++              if ((total_pages!=snd_pages) && (len == 1 || len == 2 ) && ((u32)pkt_datap & 0x03))
++              {
++                      memcpy((void *)&_debug_prefetch_buf[_debug_prefetch_cnt][0], pkt_datap, len);
++                      pkt_datap = (char *)&_debug_prefetch_buf[_debug_prefetch_cnt][0];
++                      word2 = (unsigned long)__pa(pkt_datap);
++                      _debug_prefetch_cnt++;
++                      if (_debug_prefetch_cnt >= _DEBUG_PREFETCH_NUM)
++                              _debug_prefetch_cnt = 0;
++              }
++#endif
++
++              consistent_sync((void *)pkt_datap, len, PCI_DMA_TODEVICE);
++              wmb();
++              curr_desc->word0.bits32 = word0;
++              curr_desc->word1.bits32 = word1;
++              curr_desc->word2.bits32 = word2;
++              curr_desc->word3.bits32 = word3;
++              swtxq->curr_tx_desc = (GMAC_TXDESC_T *)curr_desc;
++//            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_TODEVICE);
++#ifdef _DUMP_TX_TCP_CONTENT
++              if (len < 16 && frag_id && skb->h.th && (skb->h.th->source == __constant_htons(445) || skb->h.th->source == __constant_htons(139)))
++              {
++                      int a;
++                      char *datap;
++                      printk("\t 0x%08x: ", (u32)pkt_datap);
++                      datap = (char *)pkt_datap;
++                      for (a=0; a<8 && a<len; a++, datap++)
++                      {
++                              printk("0x%02x ", *datap);
++                      }
++                      printk("\n");
++              }
++#endif
++              free_desc--;
++              wmb();
++              wptr = RWPTR_ADVANCE_ONE(wptr, swtxq->total_desc_num);
++              frag_id++;
++              snd_pages--;
++      }
++
++    swtxq->total_sent++;
++      SET_WPTR(swtxq->rwptr_reg, wptr);
++      dev->trans_start = jiffies;
++
++
++      // printk("MAC %d Qid %d rwptr = 0x%x, curr_desc=0x%x\n", skb->tx_port_id, tx_qid, rwptr.bits32, curr_desc);
++//#ifdef      GMAX_TX_INTR_DISABLED
++//            toe_gmac_tx_complete(tp, tx_qid, dev, 0);
++//#endif
++      return (0);
++}
++
++/*----------------------------------------------------------------------
++* gmac_set_mac_address
++*----------------------------------------------------------------------*/
++
++static int gmac_set_mac_address(struct net_device *dev, void *addr)
++{
++      GMAC_INFO_T             *tp= dev->priv;
++      struct sockaddr *sock;
++      unsigned int    reg_val;
++    unsigned int    i;
++
++      sock = (struct sockaddr *) addr;
++      for (i = 0; i < 6; i++)
++      {
++              dev->dev_addr[i] = sock->sa_data[i];
++      }
++
++    reg_val = dev->dev_addr[0] + (dev->dev_addr[1]<<8) + (dev->dev_addr[2]<<16) + (dev->dev_addr[3]<<24);
++    gmac_write_reg(tp->base_addr,GMAC_STA_ADD0,reg_val,0xffffffff);
++    reg_val = dev->dev_addr[4] + (dev->dev_addr[5]<<8);
++    gmac_write_reg(tp->base_addr,GMAC_STA_ADD1,reg_val,0x0000ffff);
++      memcpy(&eth_mac[tp->port_id][0],&dev->dev_addr[0],6);
++
++    printk("Storlink %s address = ",dev->name);
++    printk("%02x",dev->dev_addr[0]);
++    printk("%02x",dev->dev_addr[1]);
++    printk("%02x",dev->dev_addr[2]);
++    printk("%02x",dev->dev_addr[3]);
++    printk("%02x",dev->dev_addr[4]);
++    printk("%02x\n",dev->dev_addr[5]);
++
++    return (0);
++}
++
++/*----------------------------------------------------------------------
++* gmac_get_mac_address
++*     get mac address from FLASH
++*----------------------------------------------------------------------*/
++static void gmac_get_mac_address(void)
++{
++#ifdef CONFIG_MTD
++      extern int get_vlaninfo(vlaninfo* vlan);
++    static vlaninfo    vlan[2];
++
++    if (get_vlaninfo(&vlan[0]))
++    {
++        memcpy((void *)&eth_mac[0][0],vlan[0].mac,6);
++        // VLAN_conf[0].vid = vlan[0].vlanid;
++        // VLAN_conf[0].portmap = vlan[0].vlanmap;
++        memcpy((void *)&eth_mac[1][0],vlan[1].mac,6);
++        // VLAN_conf[1].vid = vlan[1].vlanid;
++        // VLAN_conf[1].portmap = vlan[1].vlanmap;
++    }
++#else
++    unsigned int reg_val;
++
++    reg_val = readl(IO_ADDRESS(TOE_GMAC0_BASE)+0xac);
++    eth_mac[0][4] = (reg_val & 0xff00) >> 8;
++    eth_mac[0][5] = reg_val & 0x00ff;
++    reg_val = readl(IO_ADDRESS(SL2312_SECURITY_BASE)+0xac);
++    eth_mac[1][4] = (reg_val & 0xff00) >> 8;
++    eth_mac[1][5] = reg_val & 0x00ff;
++#endif
++    return;
++}
++
++
++/*----------------------------------------------------------------------
++* mac_stop_txdma
++*----------------------------------------------------------------------*/
++void mac_stop_txdma(struct net_device *dev)
++{
++      GMAC_INFO_T                             *tp = (GMAC_INFO_T *)dev->priv;
++      GMAC_DMA_CTRL_T                 dma_ctrl, dma_ctrl_mask;
++      GMAC_TXDMA_FIRST_DESC_T txdma_busy;
++
++      // wait idle
++      do
++      {
++              txdma_busy.bits32 = gmac_read_reg(tp->dma_base_addr, GMAC_DMA_TX_FIRST_DESC_REG);
++      } while (txdma_busy.bits.td_busy);
++
++    /* program dma control register */
++      dma_ctrl.bits32 = 0;
++      dma_ctrl.bits.rd_enable = 0;
++      dma_ctrl.bits.td_enable = 0;
++
++      dma_ctrl_mask.bits32 = 0;
++      dma_ctrl_mask.bits.rd_enable = 1;
++      dma_ctrl_mask.bits.td_enable = 1;
++
++      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++}
++
++/*----------------------------------------------------------------------
++* mac_start_txdma
++*----------------------------------------------------------------------*/
++void mac_start_txdma(struct net_device *dev)
++{
++      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
++      GMAC_DMA_CTRL_T         dma_ctrl, dma_ctrl_mask;
++
++    /* program dma control register */
++      dma_ctrl.bits32 = 0;
++      dma_ctrl.bits.rd_enable = 1;
++      dma_ctrl.bits.td_enable = 1;
++
++      dma_ctrl_mask.bits32 = 0;
++      dma_ctrl_mask.bits.rd_enable = 1;
++      dma_ctrl_mask.bits.td_enable = 1;
++
++      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++}
++
++
++/*----------------------------------------------------------------------
++* gmac_get_stats
++*----------------------------------------------------------------------*/
++
++struct net_device_stats * gmac_get_stats(struct net_device *dev)
++{
++    GMAC_INFO_T *tp = (GMAC_INFO_T *)dev->priv;
++    // unsigned int        flags;
++    unsigned int        pkt_drop;
++    unsigned int        pkt_error;
++
++    if (netif_running(dev))
++    {
++        /* read H/W counter */
++        // spin_lock_irqsave(&tp->lock,flags);
++        pkt_drop = gmac_read_reg(tp->base_addr,GMAC_IN_DISCARDS);
++        pkt_error = gmac_read_reg(tp->base_addr,GMAC_IN_ERRORS);
++        tp->ifStatics.rx_dropped = tp->ifStatics.rx_dropped + pkt_drop;
++        tp->ifStatics.rx_errors = tp->ifStatics.rx_errors + pkt_error;
++        // spin_unlock_irqrestore(&tp->lock,flags);
++    }
++    return &tp->ifStatics;
++}
++
++
++
++/*----------------------------------------------------------------------
++* mac_get_sw_tx_weight
++*----------------------------------------------------------------------*/
++void mac_get_sw_tx_weight(struct net_device *dev, char *weight)
++{
++      GMAC_TX_WCR1_T  sw_weigh;
++    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
++
++      sw_weigh.bits32 = gmac_read_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_1_REG);
++
++      weight[0] = sw_weigh.bits.sw_tq0;
++      weight[1] = sw_weigh.bits.sw_tq1;
++      weight[2] = sw_weigh.bits.sw_tq2;
++      weight[3] = sw_weigh.bits.sw_tq3;
++      weight[4] = sw_weigh.bits.sw_tq4;
++      weight[5] = sw_weigh.bits.sw_tq5;
++}
++
++/*----------------------------------------------------------------------
++* mac_set_sw_tx_weight
++*----------------------------------------------------------------------*/
++void mac_set_sw_tx_weight(struct net_device *dev, char *weight)
++{
++      GMAC_TX_WCR1_T  sw_weigh;
++    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
++
++      sw_weigh.bits32 = 0;
++      sw_weigh.bits.sw_tq0 = weight[0];
++      sw_weigh.bits.sw_tq1 = weight[1];
++      sw_weigh.bits.sw_tq2 = weight[2];
++      sw_weigh.bits.sw_tq3 = weight[3];
++      sw_weigh.bits.sw_tq4 = weight[4];
++      sw_weigh.bits.sw_tq5 = weight[5];
++
++      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_1_REG, sw_weigh.bits32, 0xffffffff);
++}
++
++/*----------------------------------------------------------------------
++* mac_get_hw_tx_weight
++*----------------------------------------------------------------------*/
++void mac_get_hw_tx_weight(struct net_device *dev, char *weight)
++{
++      GMAC_TX_WCR0_T  hw_weigh;
++    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
++
++      hw_weigh.bits32 = gmac_read_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_0_REG);
++
++      weight[0] = hw_weigh.bits.hw_tq0;
++      weight[1] = hw_weigh.bits.hw_tq1;
++      weight[2] = hw_weigh.bits.hw_tq2;
++      weight[3] = hw_weigh.bits.hw_tq3;
++}
++
++/*----------------------------------------------------------------------
++* mac_set_hw_tx_weight
++*----------------------------------------------------------------------*/
++void mac_set_hw_tx_weight(struct net_device *dev, char *weight)
++{
++      GMAC_TX_WCR0_T  hw_weigh;
++    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
++
++      hw_weigh.bits32 = 0;
++      hw_weigh.bits.hw_tq0 = weight[0];
++      hw_weigh.bits.hw_tq1 = weight[1];
++      hw_weigh.bits.hw_tq2 = weight[2];
++      hw_weigh.bits.hw_tq3 = weight[3];
++
++      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_0_REG, hw_weigh.bits32, 0xffffffff);
++}
++
++/*----------------------------------------------------------------------
++* mac_start_tx_dma
++*----------------------------------------------------------------------*/
++int mac_start_tx_dma(int mac)
++{
++      GMAC_DMA_CTRL_T dma_ctrl, dma_ctrl_mask;
++
++      dma_ctrl.bits32 = 0;
++      dma_ctrl.bits.td_enable = 1;
++
++      dma_ctrl_mask.bits32 = 0;
++      dma_ctrl_mask.bits.td_enable = 1;
++
++      if (mac == 0)
++      gmac_write_reg(TOE_GMAC0_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++      else
++      gmac_write_reg(TOE_GMAC1_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++      return  1;
++}
++
++/*----------------------------------------------------------------------
++* mac_stop_tx_dma
++*----------------------------------------------------------------------*/
++int mac_stop_tx_dma(int mac)
++{
++      GMAC_DMA_CTRL_T dma_ctrl, dma_ctrl_mask;
++
++      dma_ctrl.bits32 = 0;
++      dma_ctrl.bits.td_enable = 0;
++
++      dma_ctrl_mask.bits32 = 0;
++      dma_ctrl_mask.bits.td_enable = 1;
++
++      if (mac == 0)
++      gmac_write_reg(TOE_GMAC0_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++      else
++      gmac_write_reg(TOE_GMAC1_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
++      return  1;
++}
++
++/*----------------------------------------------------------------------
++* mac_read_reg(int mac, unsigned int offset)
++*----------------------------------------------------------------------*/
++unsigned int mac_read_reg(int mac, unsigned int offset)
++{
++      switch (mac)
++      {
++              case 0:
++                      return gmac_read_reg(TOE_GMAC0_BASE, offset);
++              case 1:
++                      return gmac_read_reg(TOE_GMAC1_BASE, offset);
++              default:
++                      return 0;
++      }
++}
++
++/*----------------------------------------------------------------------
++* mac_write_reg
++*----------------------------------------------------------------------*/
++void mac_write_reg(int mac, unsigned int offset, unsigned data)
++{
++      switch (mac)
++      {
++              case 0:
++                      gmac_write_reg(GMAC0_BASE, offset, data, 0xffffffff);
++                      break;
++              case 1:
++                      gmac_write_reg(GMAC1_BASE, offset, data, 0xffffffff);
++                      break;
++      }
++}
++
++/*----------------------------------------------------------------------
++* mac_read_dma_reg(int mac, unsigned int offset)
++*----------------------------------------------------------------------*/
++u32 mac_read_dma_reg(int mac, unsigned int offset)
++{
++      switch (mac)
++      {
++              case 0:
++                      return gmac_read_reg(TOE_GMAC0_DMA_BASE, offset);
++              case 1:
++                      return gmac_read_reg(TOE_GMAC1_DMA_BASE, offset);
++              default:
++                      return 0;
++      }
++}
++
++/*----------------------------------------------------------------------
++* mac_write_dma_reg
++*----------------------------------------------------------------------*/
++void mac_write_dma_reg(int mac, unsigned int offset, u32 data)
++{
++      switch (mac)
++      {
++              case 0:
++                      gmac_write_reg(TOE_GMAC0_DMA_BASE, offset, data, 0xffffffff);
++                      break;
++              case 1:
++                      gmac_write_reg(TOE_GMAC1_DMA_BASE, offset, data, 0xffffffff);
++                      break;
++      }
++}
++
++/*----------------------------------------------------------------------
++* ether_crc
++*----------------------------------------------------------------------*/
++static unsigned const ethernet_polynomial = 0x04c11db7U;
++static unsigned int ether_crc (int length, unsigned char *data)
++{
++      int crc = -1;
++      unsigned int i;
++      unsigned int crc_val=0;
++
++      while (--length >= 0) {
++              unsigned char current_octet = *data++;
++              int bit;
++              for (bit = 0; bit < 8; bit++, current_octet >>= 1)
++                      crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ?
++                           ethernet_polynomial : 0);
++      }
++      crc = ~crc;
++      for (i=0;i<32;i++)
++      {
++              crc_val = crc_val + (((crc << i) & 0x80000000) >> (31-i));
++      }
++      return crc_val;
++}
++
++
++
++/*----------------------------------------------------------------------
++* mac_set_rx_mode
++*----------------------------------------------------------------------*/
++void mac_set_rx_mode(int pid, unsigned int data)
++{
++      unsigned int    base;
++
++      base = (pid == 0) ? GMAC0_BASE : GMAC1_BASE;
++
++    gmac_write_reg(base, GMAC_RX_FLTR, data, 0x0000001f);
++    return;
++}
++
++
++/*----------------------------------------------------------------------
++* gmac_open
++*----------------------------------------------------------------------*/
++
++static int gmac_open (struct net_device *dev)
++{
++      GMAC_INFO_T  *tp = (GMAC_INFO_T *)dev->priv;
++      int                                     retval;
++      TOE_INFO_T                              *toe;
++      toe = (TOE_INFO_T *)&toe_private_data;
++
++    /* hook ISR */
++      retval = request_irq (dev->irq, toe_gmac_interrupt, IRQF_DISABLED, dev->name, dev);
++      if (retval)
++              return retval;
++
++      toe_init_gmac(dev);
++
++      if(!FLAG_SWITCH)
++      {
++      init_waitqueue_head (&tp->thr_wait);
++      init_completion(&tp->thr_exited);
++
++      tp->time_to_die = 0;
++      tp->thr_pid = kernel_thread (gmac_phy_thread, dev, CLONE_FS | CLONE_FILES);
++      if (tp->thr_pid < 0)
++      {
++              printk (KERN_WARNING "%s: unable to start kernel thread\n",dev->name);
++      }
++    }
++
++      tp->operation = 1;
++
++      netif_start_queue (dev);
++
++      return (0);
++}
++
++/*----------------------------------------------------------------------
++* gmac_close
++*----------------------------------------------------------------------*/
++static int gmac_close(struct net_device *dev)
++{
++    TOE_INFO_T                        *toe;
++//    GMAC_RXDESC_T           *sw_desc_ptr,*desc_ptr;
++//    unsigned int            buf_ptr;
++      GMAC_INFO_T     *tp = dev->priv;
++      unsigned int            ret;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++
++      tp->operation = 0;
++
++    netif_stop_queue(dev);
++    mdelay(20);
++
++    /* stop tx/rx packet */
++    toe_gmac_disable_tx_rx(dev);
++    mdelay(20);
++
++    /* stop the chip's Tx and Rx DMA processes */
++      toe_gmac_hw_stop(dev);
++
++      toe_gmac_disable_interrupt(tp->irq);
++
++    /* disable interrupts by clearing the interrupt mask */
++    synchronize_irq();
++    free_irq(dev->irq,dev);
++
++//    DMA_MFREE(sw_desc_ptr, (TOE_SW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T),(dma_addr_t *)&toe->sw_freeq_desc_base_dma);
++//    DMA_MFREE(desc_ptr, TOE_HW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T),(dma_addr_t *)&toe->hw_freeq_desc_base_dma);
++//    DMA_MFREE(buf_ptr, TOE_HW_FREEQ_DESC_NUM) * HW_RX_BUF_SIZE),(dma_addr_t *)&toe->hwfq_buf_base_dma);
++//    DMA_MFREE(toe->gmac[0].swtxq_desc_base , TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[0].swtxq_desc_base_dma);
++//    DMA_MFREE(toe->gmac[1].swtxq_desc_base , TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[1].swtxq_desc_base_dma);
++//    DMA_MFREE(toe->gmac[0].hwtxq_desc_base_dma , TOE_GMAC0_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[0].hwtxq_desc_base_dma);
++//    DMA_MFREE(toe->gmac[1].hwtxq_desc_base_dma , TOE_GMAC0_SWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[1].hwtxq_desc_base_dma);
++//    DMA_MFREE(toe->gmac[0].default_desc_base_dma ,TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
++//    DMA_MFREE(toe->gmac[1].default_desc_base_dma , TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
++//    DMA_MFREE(toe->intr_desc_base_dma , TOE_INTR_QUEUE_NUM * TOE_INTR_DESC_NUM * sizeof(GMAC_RXDESC_T),(dma_addr_t *)&toe->intr_desc_base_dma);
++//    DMA_MFREE(toe->intr_buf_base_dma , TOE_INTR_DESC_NUM * sizeof(TOE_QHDR_T),(dma_addr_t *)&toe->intr_buf_base_dma);
++
++      if(!FLAG_SWITCH)
++      {
++      if (tp->thr_pid >= 0)
++      {
++                  tp->time_to_die = 1;
++              wmb();
++              ret = kill_proc (tp->thr_pid, SIGTERM, 1);
++              if (ret)
++              {
++                      printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
++                      return ret;
++              }
++//                    wait_for_completion (&tp->thr_exited);
++      }
++    }
++
++    return (0);
++}
++
++/*----------------------------------------------------------------------
++* toe_gmac_fill_free_q
++* allocate buffers for free queue.
++*----------------------------------------------------------------------*/
++static inline void toe_gmac_fill_free_q(void)
++{
++      struct sk_buff  *skb;
++      volatile DMA_RWPTR_T    fq_rwptr;
++      volatile GMAC_RXDESC_T  *fq_desc;
++      unsigned long   flags;
++      // unsigned short max_cnt=TOE_SW_FREEQ_DESC_NUM>>1;
++
++      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++      spin_lock_irqsave(&gmac_fq_lock, flags);
++      //while ((max_cnt--) && (unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
++      //                              TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
++      while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
++                                      TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
++              if ((skb = dev_alloc_skb(SW_RX_BUF_SIZE)) == NULL) {
++                      printk("%s::skb allocation fail!\n", __func__);
++                      //while(1);
++                      break;
++              }
++              REG32(skb->data) = (unsigned int)skb;
++              skb_reserve(skb, SKB_RESERVE_BYTES);
++              // fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
++                      TOE_SW_FREEQ_DESC_NUM);
++              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base+fq_rwptr.bits.wptr;
++              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
++              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
++              toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
++      }
++      spin_unlock_irqrestore(&gmac_fq_lock, flags);
++}
++// EXPORT_SYMBOL(toe_gmac_fill_free_q);
++
++/*----------------------------------------------------------------------
++* toe_gmac_interrupt
++*----------------------------------------------------------------------*/
++static irqreturn_t toe_gmac_interrupt (int irq, void *dev_instance)
++{
++      struct net_device   *dev = (struct net_device *)dev_instance;
++      TOE_INFO_T                      *toe;
++      GMAC_INFO_T             *tp = (GMAC_INFO_T *)dev->priv;
++      unsigned int            status0;
++      unsigned int            status1;
++      unsigned int            status2;
++      unsigned int            status3;
++      unsigned int            status4;
++
++//    struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
++      toe = (TOE_INFO_T *)&toe_private_data;
++//    handle NAPI
++#ifdef CONFIG_SL_NAPI
++if (storlink_ctl.pauseoff == 1)
++{
++/* disable GMAC interrupt */
++    //toe_gmac_disable_interrupt(tp->irq);
++
++//    isPtr->interrupts++;
++      /* read Interrupt status */
++      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
++      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
++      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
++      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++      // prompt warning if status bit ON but not enabled
++#if 0
++      if (status0 & ~tp->intr0_enabled)
++              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
++                              status0, tp->intr0_enabled);
++      if (status1 & ~tp->intr1_enabled)
++              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
++                              status1, tp->intr1_enabled);
++      if (status2 & ~tp->intr2_enabled)
++              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
++                              status2, tp->intr2_enabled);
++      if (status3 & ~tp->intr3_enabled)
++              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
++                              status3, tp->intr3_enabled);
++      if (status4 & ~tp->intr4_enabled)
++              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
++                              status4, tp->intr4_enabled);
++#endif
++
++      if (status0)
++              writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
++      if (status1)
++              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
++      if (status2)
++              writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
++      if (status3)
++              writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
++      if (status4)
++              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
++#if 0
++      /* handle freeq interrupt first */
++      if (status4 & tp->intr4_enabled) {
++              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
++              {
++                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
++                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
++
++                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
++                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
++                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
++                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
++                      printk("\nfreeq int\n");
++                      toe_gmac_fill_free_q();
++                      tp->sw_fq_empty_cnt++;
++
++              }
++      }
++#endif
++      // Interrupt Status 1
++      if (status1 & tp->intr1_enabled)
++      {
++              #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
++              #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
++              // Handle GMAC 0/1 HW Tx queue 0-3 EOF events
++              // Only count
++              // TOE, Classification, and default queues interrupts are handled by ISR
++              // because they should pass packets to upper layer
++              if (tp->port_id == 0)
++              {
++                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
++                      {
++                              if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
++                                      tp->hwtxq[3].eof_cnt++;
++                              if (status1 & GMAC0_HWTQ02_EOF_INT_BIT)
++                                      tp->hwtxq[2].eof_cnt++;
++                              if (status1 & GMAC0_HWTQ01_EOF_INT_BIT)
++                                      tp->hwtxq[1].eof_cnt++;
++                              if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
++                                      tp->hwtxq[0].eof_cnt++;
++                      }
++                              if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
++                              {
++                                      if (likely(netif_rx_schedule_prep(dev)))
++                              {
++                                      unsigned int data32;
++                                      // disable GMAC-0 rx interrupt
++                                      // class-Q & TOE-Q are implemented in future
++                                      //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                      //data32 &= ~DEFAULT_Q0_INT_BIT;
++                                              //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                              //printk("\%s: DEFAULT_Q0_INT_BIT===================>>>>>>>>>>>>\n",__func__);
++                                              writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                              //tp->total_q_cnt_napi=0;
++                                              //rx_time = jiffies;
++                                              //rx_old_bytes = isPtr->rx_bytes;
++                              __netif_rx_schedule(dev);
++                              }
++                      }
++              }
++              else if (tp->port_id == 1)
++              {
++                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
++                      {
++                              if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
++                                      tp->hwtxq[3].eof_cnt++;
++                              if (status1 & GMAC1_HWTQ12_EOF_INT_BIT)
++                                      tp->hwtxq[2].eof_cnt++;
++                              if (status1 & GMAC1_HWTQ11_EOF_INT_BIT)
++                                      tp->hwtxq[1].eof_cnt++;
++                              if (status1 & GMAC1_HWTQ10_EOF_INT_BIT)
++                                      tp->hwtxq[0].eof_cnt++;
++                      }
++
++                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
++                      {
++                              if (likely(netif_rx_schedule_prep(dev)))
++                      {
++                              unsigned int data32;
++                              // disable GMAC-0 rx interrupt
++                              // class-Q & TOE-Q are implemented in future
++                              //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                              //data32 &= ~DEFAULT_Q1_INT_BIT;
++                                      //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                      //printk("\%s: 1111111111--->DEFAULT_Q1_INT_BIT===================>>>>>>>>>>>>\n",__func__);
++                                      writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                      //tp->total_q_cnt_napi=0;
++                                      //rx_time = jiffies;
++                                      //rx_old_bytes = isPtr->rx_bytes;
++                              __netif_rx_schedule(dev);
++                      }
++                      }
++              }
++      }
++
++      // Interrupt Status 0
++      if (status0 & tp->intr0_enabled)
++      {
++              #define ERR_INTR_BITS   (GMAC0_TXDERR_INT_BIT | GMAC0_TXPERR_INT_BIT |  \
++                                                               GMAC1_TXDERR_INT_BIT | GMAC1_TXPERR_INT_BIT |  \
++                                                               GMAC0_RXDERR_INT_BIT | GMAC0_RXPERR_INT_BIT |  \
++                                                               GMAC1_RXDERR_INT_BIT | GMAC1_RXPERR_INT_BIT)
++
++              if (status0 &  ERR_INTR_BITS)
++              {
++                      if ((status0 & GMAC0_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXDERR_INT_BIT))
++                      {
++                              tp->txDerr_cnt[0]++;
++                              printk("GMAC0 TX AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC0_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXPERR_INT_BIT))
++                      {
++                              tp->txPerr_cnt[0]++;
++                              printk("GMAC0 Tx Descriptor Protocol Error!\n");
++                      }
++                      if ((status0 & GMAC1_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXDERR_INT_BIT))
++                      {
++                              tp->txDerr_cnt[1]++;
++                              printk("GMAC1 Tx AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC1_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXPERR_INT_BIT))
++                      {
++                              tp->txPerr_cnt[1]++;
++                              printk("GMAC1 Tx Descriptor Protocol Error!\n");
++                      }
++
++                      if ((status0 & GMAC0_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXDERR_INT_BIT))
++                      {
++                              tp->RxDerr_cnt[0]++;
++                              printk("GMAC0 Rx AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC0_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXPERR_INT_BIT))
++                      {
++                              tp->RxPerr_cnt[0]++;
++                              printk("GMAC0 Rx Descriptor Protocol Error!\n");
++                      }
++                      if ((status0 & GMAC1_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXDERR_INT_BIT))
++                      {
++                              tp->RxDerr_cnt[1]++;
++                              printk("GMAC1 Rx AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC1_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXPERR_INT_BIT))
++                      {
++                              tp->RxPerr_cnt[1]++;
++                              printk("GMAC1 Rx Descriptor Protocol Error!\n");
++                      }
++              }
++
++#ifndef       GMAX_TX_INTR_DISABLED
++              if (tp->port_id == 1 && netif_running(dev) &&
++                      (((status0 & GMAC1_SWTQ10_FIN_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_FIN_INT_BIT))
++                      ||
++                      ((status0 & GMAC1_SWTQ10_EOF_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_EOF_INT_BIT))))
++              {
++                      toe_gmac_tx_complete(&toe_private_data.gmac[1], 0, dev, 1);
++              }
++
++              if (tp->port_id == 0 && netif_running(dev) &&
++                      (((status0 & GMAC0_SWTQ00_FIN_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_FIN_INT_BIT))
++                      ||
++                      ((status0 & GMAC0_SWTQ00_EOF_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_EOF_INT_BIT))))
++              {
++                      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
++              }
++#endif
++      }
++      // Interrupt Status 4
++      if (status4 & tp->intr4_enabled)
++      {
++              #define G1_INTR4_BITS           (0xff000000)
++              #define G0_INTR4_BITS           (0x00ff0000)
++
++              if (tp->port_id == 0)
++              {
++                      if ((status4 & G0_INTR4_BITS) && (tp->intr4_enabled & G0_INTR4_BITS))
++                      {
++                              if (status4 & GMAC0_RESERVED_INT_BIT)
++                                      printk("GMAC0_RESERVED_INT_BIT is ON\n");
++                              if (status4 & GMAC0_MIB_INT_BIT)
++                                      tp->mib_full_cnt++;
++                              if (status4 & GMAC0_RX_PAUSE_ON_INT_BIT)
++                                      tp->rx_pause_on_cnt++;
++                              if (status4 & GMAC0_TX_PAUSE_ON_INT_BIT)
++                                      tp->tx_pause_on_cnt++;
++                              if (status4 & GMAC0_RX_PAUSE_OFF_INT_BIT)
++                                      tp->rx_pause_off_cnt++;
++                              if (status4 & GMAC0_TX_PAUSE_OFF_INT_BIT)
++                                      tp->rx_pause_off_cnt++;
++                              if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
++                                      tp->rx_overrun_cnt++;
++                              if (status4 & GMAC0_STATUS_CHANGE_INT_BIT)
++                                      tp->status_changed_cnt++;
++                      }
++              }
++              else if (tp->port_id == 1)
++              {
++                      if ((status4 & G1_INTR4_BITS) && (tp->intr4_enabled & G1_INTR4_BITS))
++                      {
++                              if (status4 & GMAC1_RESERVED_INT_BIT)
++                                      printk("GMAC1_RESERVED_INT_BIT is ON\n");
++                              if (status4 & GMAC1_MIB_INT_BIT)
++                                      tp->mib_full_cnt++;
++                              if (status4 & GMAC1_RX_PAUSE_ON_INT_BIT)
++                              {
++                                      printk("Gmac pause on\n");
++                                      tp->rx_pause_on_cnt++;
++                              }
++                              if (status4 & GMAC1_TX_PAUSE_ON_INT_BIT)
++                              {
++                                      printk("Gmac pause on\n");
++                                      tp->tx_pause_on_cnt++;
++                              }
++                              if (status4 & GMAC1_RX_PAUSE_OFF_INT_BIT)
++                              {
++                                      printk("Gmac pause off\n");
++                                      tp->rx_pause_off_cnt++;
++                              }
++                              if (status4 & GMAC1_TX_PAUSE_OFF_INT_BIT)
++                              {
++                                      printk("Gmac pause off\n");
++                                      tp->rx_pause_off_cnt++;
++                              }
++                              if (status4 & GMAC1_RX_OVERRUN_INT_BIT)
++                              {
++                                      //printk("Gmac Rx Overrun \n");
++                                      tp->rx_overrun_cnt++;
++                              }
++                              if (status4 & GMAC1_STATUS_CHANGE_INT_BIT)
++                                      tp->status_changed_cnt++;
++                      }
++              }
++      }
++
++      //toe_gmac_enable_interrupt(tp->irq);
++#ifdef IxscriptMate_1518
++      if (storlink_ctl.pauseoff == 1)
++      {
++              GMAC_CONFIG0_T config0;
++              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++              config0.bits.dis_rx = 0;
++              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++              config0.bits.dis_rx = 0;
++              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++      }
++#endif
++//     enable_irq(gmac_irq[dev_index]);
++      //printk("gmac_interrupt complete!\n\n");
++//    return IRQ_RETVAL(handled);
++      return  IRQ_RETVAL(1);
++}
++else
++{
++#endif        //endif NAPI
++
++
++      /* disable GMAC interrupt */
++    toe_gmac_disable_interrupt(tp->irq);
++
++//    isPtr->interrupts++;
++      /* read Interrupt status */
++      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
++      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
++      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
++      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++      // prompt warning if status bit ON but not enabled
++#if 0
++      if (status0 & ~tp->intr0_enabled)
++              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
++                              status0, tp->intr0_enabled);
++      if (status1 & ~tp->intr1_enabled)
++              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
++                              status1, tp->intr1_enabled);
++      if (status2 & ~tp->intr2_enabled)
++              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
++                              status2, tp->intr2_enabled);
++      if (status3 & ~tp->intr3_enabled)
++              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
++                              status3, tp->intr3_enabled);
++      if (status4 & ~tp->intr4_enabled)
++              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
++                              status4, tp->intr4_enabled);
++#endif
++#define       INTERRUPT_SELECT                        1
++      if (status0)
++              writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
++      if (status1)
++              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
++      if (status2)
++              writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
++      if (status3)
++              writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
++      if (status4)
++              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
++
++      /* handle freeq interrupt first */
++      if (status4 & tp->intr4_enabled) {
++              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
++              {
++                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
++                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
++
++                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
++                      //      SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
++                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
++                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
++                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
++                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
++                      printk("\nfreeq int\n");
++                      toe_gmac_fill_free_q();
++                      tp->sw_fq_empty_cnt++;
++
++                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
++                              SWFQ_EMPTY_INT_BIT);
++              }
++      }
++
++      // Interrupt Status 1
++      if (status1 & tp->intr1_enabled)
++      {
++              #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
++              #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
++              // Handle GMAC 0/1 HW Tx queue 0-3 EOF events
++              // Only count
++              // TOE, Classification, and default queues interrupts are handled by ISR
++              // because they should pass packets to upper layer
++              if (tp->port_id == 0)
++              {
++#ifndef       INTERRUPT_SELECT
++                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
++                      {
++                              if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
++                                      tp->hwtxq[3].eof_cnt++;
++                              if (status1 & GMAC0_HWTQ02_EOF_INT_BIT)
++                                      tp->hwtxq[2].eof_cnt++;
++                              if (status1 & GMAC0_HWTQ01_EOF_INT_BIT)
++                                      tp->hwtxq[1].eof_cnt++;
++                              if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
++                                      tp->hwtxq[0].eof_cnt++;
++#endif        //INTERRUPT_SELECT
++#ifndef       INTERRUPT_SELECT
++                      }
++#endif        //INTERRUPT_SELECT
++                      if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
++                      {
++                              tp->default_q_intr_cnt++;
++                              toe_gmac_handle_default_rxq(dev, tp);
++                      }
++#ifdef CONFIG_SL351x_RXTOE
++                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
++                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
++                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
++                              toe_gmac_handle_toeq(dev, tp, status1);
++                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
++                      }
++#endif
++              }
++              else if (tp->port_id == 1)
++              {
++#ifndef       INTERRUPT_SELECT
++                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
++                      {
++                              if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
++                                      tp->hwtxq[3].eof_cnt++;
++                              if (status1 & GMAC1_HWTQ12_EOF_INT_BIT)
++                                      tp->hwtxq[2].eof_cnt++;
++                              if (status1 & GMAC1_HWTQ11_EOF_INT_BIT)
++                                      tp->hwtxq[1].eof_cnt++;
++                              if (status1 & GMAC1_HWTQ10_EOF_INT_BIT)
++                                      tp->hwtxq[0].eof_cnt++;
++#endif        //INTERRUPT_SELECT
++#ifndef       INTERRUPT_SELECT
++                      }
++#endif        //INTERRUPT_SELECT
++                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
++                      {
++                              tp->default_q_intr_cnt++;
++                              toe_gmac_handle_default_rxq(dev, tp);
++                      }
++#ifdef CONFIG_SL351x_RXTOE
++                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
++                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
++                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
++                              toe_gmac_handle_toeq(dev, tp, status1);
++                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
++                      }
++#endif
++              }
++      }
++
++
++      // Interrupt Status 0
++      if (status0 & tp->intr0_enabled)
++      {
++
++              #define ERR_INTR_BITS   (GMAC0_TXDERR_INT_BIT | GMAC0_TXPERR_INT_BIT |  \
++                                                               GMAC1_TXDERR_INT_BIT | GMAC1_TXPERR_INT_BIT |  \
++                                                               GMAC0_RXDERR_INT_BIT | GMAC0_RXPERR_INT_BIT |  \
++                                                               GMAC1_RXDERR_INT_BIT | GMAC1_RXPERR_INT_BIT)
++#ifndef       INTERRUPT_SELECT
++              if (status0 &  ERR_INTR_BITS)
++              {
++                      if ((status0 & GMAC0_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXDERR_INT_BIT))
++                      {
++                              tp->txDerr_cnt[0]++;
++                              printk("GMAC0 TX AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC0_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXPERR_INT_BIT))
++                      {
++                              tp->txPerr_cnt[0]++;
++                              printk("GMAC0 Tx Descriptor Protocol Error!\n");
++                      }
++                      if ((status0 & GMAC1_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXDERR_INT_BIT))
++                      {
++                              tp->txDerr_cnt[1]++;
++                              printk("GMAC1 Tx AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC1_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXPERR_INT_BIT))
++                      {
++                              tp->txPerr_cnt[1]++;
++                              printk("GMAC1 Tx Descriptor Protocol Error!\n");
++                      }
++
++                      if ((status0 & GMAC0_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXDERR_INT_BIT))
++                      {
++                              tp->RxDerr_cnt[0]++;
++                              printk("GMAC0 Rx AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC0_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXPERR_INT_BIT))
++                      {
++                              tp->RxPerr_cnt[0]++;
++                              printk("GMAC0 Rx Descriptor Protocol Error!\n");
++                      }
++                      if ((status0 & GMAC1_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXDERR_INT_BIT))
++                      {
++                              tp->RxDerr_cnt[1]++;
++                              printk("GMAC1 Rx AHB Bus Error!\n");
++                      }
++                      if ((status0 & GMAC1_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXPERR_INT_BIT))
++                      {
++                              tp->RxPerr_cnt[1]++;
++                              printk("GMAC1 Rx Descriptor Protocol Error!\n");
++                      }
++              }
++#endif        //INTERRUPT_SELECT
++#ifndef       GMAX_TX_INTR_DISABLED
++              if (tp->port_id == 1 && netif_running(dev) &&
++                      (((status0 & GMAC1_SWTQ10_FIN_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_FIN_INT_BIT))
++                      ||
++                      ((status0 & GMAC1_SWTQ10_EOF_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_EOF_INT_BIT))))
++              {
++                      toe_gmac_tx_complete(&toe_private_data.gmac[1], 0, dev, 1);
++              }
++
++              if (tp->port_id == 0 && netif_running(dev) &&
++                      (((status0 & GMAC0_SWTQ00_FIN_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_FIN_INT_BIT))
++                      ||
++                      ((status0 & GMAC0_SWTQ00_EOF_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_EOF_INT_BIT))))
++              {
++                      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
++              }
++#endif
++              // clear enabled status bits
++      }
++      // Interrupt Status 4
++#ifndef       INTERRUPT_SELECT
++      if (status4 & tp->intr4_enabled)
++      {
++              #define G1_INTR4_BITS           (0xff000000)
++              #define G0_INTR4_BITS           (0x00ff0000)
++
++              if (tp->port_id == 0)
++              {
++                      if ((status4 & G0_INTR4_BITS) && (tp->intr4_enabled & G0_INTR4_BITS))
++                      {
++                              if (status4 & GMAC0_RESERVED_INT_BIT)
++                                      printk("GMAC0_RESERVED_INT_BIT is ON\n");
++                              if (status4 & GMAC0_MIB_INT_BIT)
++                                      tp->mib_full_cnt++;
++                              if (status4 & GMAC0_RX_PAUSE_ON_INT_BIT)
++                                      tp->rx_pause_on_cnt++;
++                              if (status4 & GMAC0_TX_PAUSE_ON_INT_BIT)
++                                      tp->tx_pause_on_cnt++;
++                              if (status4 & GMAC0_RX_PAUSE_OFF_INT_BIT)
++                                      tp->rx_pause_off_cnt++;
++                              if (status4 & GMAC0_TX_PAUSE_OFF_INT_BIT)
++                                      tp->rx_pause_off_cnt++;
++                              if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
++                                      tp->rx_overrun_cnt++;
++                              if (status4 & GMAC0_STATUS_CHANGE_INT_BIT)
++                                      tp->status_changed_cnt++;
++                      }
++              }
++              else if (tp->port_id == 1)
++              {
++                      if ((status4 & G1_INTR4_BITS) && (tp->intr4_enabled & G1_INTR4_BITS))
++                      {
++                              if (status4 & GMAC1_RESERVED_INT_BIT)
++                                      printk("GMAC1_RESERVED_INT_BIT is ON\n");
++                              if (status4 & GMAC1_MIB_INT_BIT)
++                                      tp->mib_full_cnt++;
++                              if (status4 & GMAC1_RX_PAUSE_ON_INT_BIT)
++                              {
++                                      //printk("Gmac pause on\n");
++                                      tp->rx_pause_on_cnt++;
++                              }
++                              if (status4 & GMAC1_TX_PAUSE_ON_INT_BIT)
++                              {
++                                      //printk("Gmac pause on\n");
++                                      tp->tx_pause_on_cnt++;
++                              }
++                              if (status4 & GMAC1_RX_PAUSE_OFF_INT_BIT)
++                              {
++                                      //printk("Gmac pause off\n");
++                                      tp->rx_pause_off_cnt++;
++                              }
++                              if (status4 & GMAC1_TX_PAUSE_OFF_INT_BIT)
++                              {
++                                      //printk("Gmac pause off\n");
++                                      tp->rx_pause_off_cnt++;
++                              }
++                              if (status4 & GMAC1_RX_OVERRUN_INT_BIT)
++                              {
++                                      //printk("Gmac Rx Overrun \n");
++                                      tp->rx_overrun_cnt++;
++                              }
++                              if (status4 & GMAC1_STATUS_CHANGE_INT_BIT)
++                                      tp->status_changed_cnt++;
++                      }
++              }
++#if 0
++              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
++              {
++                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++//                    mac_stop_rxdma(tp->sc);
++                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
++                              tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
++
++                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
++                              SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
++                      toe_gmac_fill_free_q();
++                      tp->sw_fq_empty_cnt++;
++
++                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
++                              SWFQ_EMPTY_INT_BIT);
++//#if 0
++/*                    if (netif_running(dev))
++                              toe_gmac_handle_default_rxq(dev, tp);
++                      printk("SWFQ_EMPTY_INT_BIT is ON!\n");  // should not be happened */
++//#endif
++              }
++#endif
++      }
++#endif        //INTERRUPT_SELECT
++      toe_gmac_enable_interrupt(tp->irq);
++//enable gmac rx function when do RFC 2544
++#ifdef IxscriptMate_1518
++      if (storlink_ctl.pauseoff == 1)
++      {
++              GMAC_CONFIG0_T config0;
++              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++              config0.bits.dis_rx = 0;
++              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++              config0.bits.dis_rx = 0;
++              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++      }
++#endif
++      //printk("gmac_interrupt complete!\n\n");
++//    return IRQ_RETVAL(handled);
++      return  IRQ_RETVAL(1);
++#ifdef CONFIG_SL_NAPI
++}
++#endif
++}
++
++/*----------------------------------------------------------------------
++*     toe_gmac_handle_default_rxq
++*     (1) Get rx Buffer for default Rx queue
++*     (2) notify or call upper-routine to handle it
++*     (3) get a new buffer and insert it into SW free queue
++*     (4) Note: The SW free queue Read-Write Pointer should be locked when accessing
++*----------------------------------------------------------------------*/
++//static inline void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
++static void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
++{
++      TOE_INFO_T                      *toe;
++    GMAC_RXDESC_T     *curr_desc;
++      struct sk_buff          *skb;
++    DMA_RWPTR_T                       rwptr;
++      unsigned int            pkt_size;
++      int                                     max_cnt;
++      unsigned int        desc_count;
++      unsigned int        good_frame, chksum_status, rx_status;
++      struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
++
++//when do ixia RFC 2544 test and packet size is select 1518 bytes,disable gmace rx function immediately after one interrupt come in.
++#ifdef IxscriptMate_1518
++      if (storlink_ctl.pauseoff == 1)
++      {
++              GMAC_CONFIG0_T config0;
++              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++              config0.bits.dis_rx = 1;
++              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++              config0.bits.dis_rx = 1;
++              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++      }
++#endif
++      rwptr.bits32 = readl(&tp->default_qhdr->word1);
++#if 0
++      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
++      {
++              mac_stop_txdma((struct net_device *)tp->dev);
++              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
++                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
++              while(1);
++      }
++#endif
++      toe = (TOE_INFO_T *)&toe_private_data;
++      max_cnt = DEFAULT_RXQ_MAX_CNT;
++      while ((--max_cnt) && rwptr.bits.rptr != rwptr.bits.wptr)
++//    while (rwptr.bits.rptr != rwptr.bits.wptr)
++      {
++//if packet size is not 1518 for RFC 2544,enable gmac rx function.The other packet size have RX workaround.
++#ifdef IxscriptMate_1518
++      if (storlink_ctl.pauseoff == 1)
++              {
++                      if (pkt_size != 1514)
++                      {
++                                              GMAC_CONFIG0_T config0;
++                                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++                                              config0.bits.dis_rx = 0;
++                                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++                                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++                                              config0.bits.dis_rx = 0;
++                                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++                      }
++              }
++#endif
++      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
++//            consistent_sync(curr_desc, sizeof(GMAC_RXDESC_T), PCI_DMA_FROMDEVICE);
++              tp->default_q_cnt++;
++      tp->rx_curr_desc = (unsigned int)curr_desc;
++      rx_status = curr_desc->word0.bits.status;
++      chksum_status = curr_desc->word0.bits.chksum_status;
++      tp->rx_status_cnt[rx_status]++;
++      tp->rx_chksum_cnt[chksum_status]++;
++        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
++              desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
++              good_frame=1;
++              if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
++                      || (pkt_size < 60)
++                  || (chksum_status & 0x4)
++                      || rx_status)
++              {
++                      good_frame = 0;
++                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
++                              printk("%s::derr (GMAC-%d)!!!\n", __func__, tp->port_id);
++                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_perr)
++                              printk("%s::perr (GMAC-%d)!!!\n", __func__, tp->port_id);
++                      if (rx_status)
++                      {
++                              if (rx_status == 4 || rx_status == 7)
++                                      isPtr->rx_crc_errors++;
++//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
++                      }
++#ifdef SL351x_GMAC_WORKAROUND
++                      else if (pkt_size < 60)
++                      {
++                              if (tp->short_frames_cnt < GMAC_SHORT_FRAME_THRESHOLD)
++                                      tp->short_frames_cnt++;
++                              if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
++                              {
++                                      GMAC_CONFIG0_T config0;
++                                      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++                                      config0.bits.dis_rx = 1;
++                                      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++                                      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++                                      config0.bits.dis_rx = 1;
++                                      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++                              }
++                      }
++#endif
++//                    if (chksum_status)
++//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
++                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
++                      dev_kfree_skb_irq(skb);
++              }
++              if (good_frame)
++              {
++                      if (curr_desc->word0.bits.drop)
++                              printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
++//                    if (chksum_status)
++//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
++
++              /* get frame information from the first descriptor of the frame */
++#ifdef SL351x_GMAC_WORKAROUND
++                      if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
++                      {
++                              GMAC_CONFIG0_T config0;
++                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++                              config0.bits.dis_rx = 0;
++                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++                              config0.bits.dis_rx = 0;
++                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++                      }
++                      tp->short_frames_cnt = 0;
++#endif
++                      isPtr->rx_packets++;
++                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr - SKB_RESERVE_BYTES)));
++                      if (!skb)
++                      {
++                              printk("Fatal Error!!skb==NULL\n");
++                              goto next_rx;
++                      }
++                      tp->curr_rx_skb = skb;
++                      // consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
++
++      //              curr_desc->word2.buf_adr = 0;
++
++                      skb_reserve (skb, RX_INSERT_BYTES);     /* 16 byte align the IP fields. */
++                      skb_put(skb, pkt_size);
++                      skb->dev = dev;
++                      if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
++                      {
++                              skb->ip_summed = CHECKSUM_UNNECESSARY;
++#ifdef CONFIG_SL351x_NAT
++                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
++                              {
++                                      struct iphdr    *ip_hdr;
++                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
++                                      sl351x_nat_input(skb,
++                                                                      tp->port_id,
++                                                                      (void *)curr_desc->word3.bits.l3_offset,
++                                                                      (void *)curr_desc->word3.bits.l4_offset);
++                              }
++#endif
++                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
++#if 0
++#ifdef CONFIG_SL351x_RXTOE
++                              if (storlink_ctl.rx_max_pktsize) {
++                                      struct iphdr    *ip_hdr;
++                                      struct tcphdr   *tcp_hdr;
++                                      int ip_hdrlen;
++
++                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
++                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
++                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
++                                              ip_hdrlen = ip_hdr->ihl << 2;
++                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
++                                              if (tcp_hdr->syn) {
++                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
++                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
++                                                      TCP_SKB_CB(skb)->connection = connection;
++                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
++                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
++                                                      //                      __func__, skb->data, connection, connection->mode);
++                                              }
++                                      }
++                              }
++#endif
++#endif
++                      }
++                      else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
++                      {
++                              skb->ip_summed = CHECKSUM_UNNECESSARY;
++#ifdef CONFIG_SL351x_NAT
++                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
++                              {
++                                      struct iphdr            *ip_hdr;
++                                      //struct tcphdr         *tcp_hdr;
++                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
++                                      //tcp_hdr = (struct tcphdr *)&(skb->data[curr_desc->word3.bits.l4_offset]);
++                                      if (ip_hdr->protocol == IPPROTO_UDP)
++                                      {
++                                              sl351x_nat_input(skb,
++                                                                              tp->port_id,
++                                                                              (void *)curr_desc->word3.bits.l3_offset,
++                                                                              (void *)curr_desc->word3.bits.l4_offset);
++                                      }
++                                      else if (ip_hdr->protocol == IPPROTO_GRE)
++                                      {
++                                              sl351x_nat_input(skb,
++                                                                      tp->port_id,
++                                                                      (void *)curr_desc->word3.bits.l3_offset,
++                                                                      (void *)curr_desc->word3.bits.l4_offset);
++                                      }
++                              }
++#endif
++                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
++                      }
++                      else
++                      {
++                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
++                      }
++
++                      netif_rx(skb);  /* socket rx */
++                      dev->last_rx = jiffies;
++
++                      isPtr->rx_bytes += pkt_size;
++
++        }
++
++next_rx:
++              // advance one for Rx default Q 0/1
++              rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
++              SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
++      tp->rx_rwptr.bits32 = rwptr.bits32;
++
++              toe_gmac_fill_free_q();
++      }
++}
++
++/*----------------------------------------------------------------------
++* gmac_get_phy_vendor
++*----------------------------------------------------------------------*/
++static unsigned int gmac_get_phy_vendor(int phy_addr)
++{
++    unsigned int      reg_val;
++    reg_val=(mii_read(phy_addr,0x02) << 16) + mii_read(phy_addr,0x03);
++    return reg_val;
++}
++
++/*----------------------------------------------------------------------
++* gmac_set_phy_status
++*----------------------------------------------------------------------*/
++void gmac_set_phy_status(struct net_device *dev)
++{
++      GMAC_INFO_T *tp = dev->priv;
++      GMAC_STATUS_T   status;
++      unsigned int    reg_val, ability,wan_port_id;
++      unsigned int    i = 0;
++
++#ifdef VITESSE_G5SWITCH
++      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1)){
++#if 0
++              rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
++              rcv_mask |= 0x4F;
++              for(i=0;i<4;i++){
++                      reg_val = BIT(26)|(i<<21)|(10<<16);
++                      SPI_write(3,0,1,reg_val);
++                      msleep(10);
++                      reg_val = SPI_read(3,0,2);
++                      if(reg_val & 0x0c00){
++                              printk("Port%d:Giga mode\n",i);
++                              SPI_write(1,i,0x00,0x300701B1);
++                              SPI_write(1,i,0x00,0x10070181);
++                              switch_pre_link[i]=LINK_UP;
++                              switch_pre_speed[i]=GMAC_SPEED_1000;
++                      }
++                      else{
++                              reg_val = BIT(26)|(i<<21)|(5<<16);
++                              SPI_write(3,0,1,reg_val);
++                              msleep(10);
++                              ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5;
++                              if ((ability & 0x0C)) /* 100M full duplex */
++                              {
++                                      SPI_write(1,i,0x00,0x30050472);
++                                      SPI_write(1,i,0x00,0x10050442);
++                                      printk("Port%d:100M\n",i);
++                                      switch_pre_link[i]=LINK_UP;
++                              switch_pre_speed[i]=GMAC_SPEED_100;
++                              }
++                              else if((ability & 0x03)) /* 10M full duplex */
++                              {
++                                      SPI_write(1,i,0x00,0x30050473);
++                                      SPI_write(1,i,0x00,0x10050443);
++                                      printk("Port%d:10M\n",i);
++                                      switch_pre_link[i]=LINK_UP;
++                                      switch_pre_speed[i]=GMAC_SPEED_10;
++                              }
++                              else{
++                                      SPI_write(1,i,0x00,BIT(16));                    // disable RX
++                                      SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
++                                      while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
++                                              msleep(1);
++
++                                      SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
++                                      switch_pre_link[i]=LINK_DOWN;
++                                      switch_pre_speed[i]=GMAC_SPEED_10;
++                                      rcv_mask &= ~BIT(i);
++                                      SPI_write(2,0,0x10,rcv_mask);                   // Disable Receive
++                              }
++                      }
++              }
++#endif
++              gmac_get_switch_status(dev);
++              gmac_write_reg(tp->base_addr, GMAC_STATUS, 0x7d, 0x0000007f);
++//            SPI_write(2,0,0x10,rcv_mask);                   // Enable Receive
++              return ;
++      }
++#endif
++
++      reg_val = gmac_get_phy_vendor(tp->phy_addr);
++      printk("GMAC-%d Addr %d Vendor ID: 0x%08x\n", tp->port_id, tp->phy_addr, reg_val);
++
++      switch (tp->phy_mode)
++      {
++              case GMAC_PHY_GMII:
++              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
++              #ifdef CONFIG_SL3516_ASIC
++              mii_write(tp->phy_addr,0x09,0x0300); /* advertise 1000M full/half duplex */
++              #else
++              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M full/half duplex */
++              #endif
++              break;
++              case GMAC_PHY_RGMII_100:
++              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
++              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M */
++              break;
++              case GMAC_PHY_RGMII_1000:
++              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
++              #ifdef CONFIG_SL3516_ASIC
++              mii_write(tp->phy_addr,0x09,0x0300); /* advertise 1000M full/half duplex */
++              #else
++              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M full/half duplex */
++              #endif
++              break;
++              case GMAC_PHY_MII:
++              default:
++              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
++              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M */
++              break;
++      }
++
++      mii_write(tp->phy_addr,0x18,0x0041);    // Phy active led
++      if (tp->auto_nego_cfg)
++      {
++              reg_val = 0x1200 | (1 << 15);
++              mii_write(tp->phy_addr,0x00,reg_val); /* Enable and Restart Auto-Negotiation */
++              mdelay(500);
++              reg_val &= ~(1 << 15);
++              mii_write(tp->phy_addr, 0x00, reg_val);
++      }
++      else
++      {
++              reg_val = 0;
++              reg_val |= (tp->full_duplex_cfg) ? (1 << 8) : 0;
++              reg_val |= (tp->speed_cfg == GMAC_SPEED_1000) ? (1 << 6) : 0;
++              reg_val |= (tp->speed_cfg == GMAC_SPEED_100) ? (1 << 13) : 0;
++              mii_write(tp->phy_addr, 0x00, reg_val);
++              mdelay(100);
++
++              reg_val |= (1 << 15);   // Reset PHY;
++              mii_write(tp->phy_addr, 0x00, reg_val);
++      }
++
++      status.bits32 = 0;
++      /* set PHY operation mode */
++      status.bits.mii_rmii = tp->phy_mode;
++      status.bits.reserved = 1;
++      mdelay(100);
++      while (((reg_val=mii_read(tp->phy_addr,0x01)) & 0x00000004)!=0x04)
++      {
++              msleep(100);
++              i++;
++              if (i > 30)
++              break;
++      }
++      if (i>30)
++      {
++              tp->pre_phy_status = LINK_DOWN;
++              status.bits.link = LINK_DOWN;
++              //              clear_bit(__LINK_STATE_START, &dev->state);
++              printk("Link Down (0x%04x) ", reg_val);
++              if(Giga_switch == 1)
++              {
++                              wan_port_id = 1;
++#ifdef CONFIG_SL351x_SYSCTL
++                              storlink_ctl.link[ wan_port_id] = 0;
++#endif
++              }
++              else
++              {
++#ifdef CONFIG_SL351x_SYSCTL
++                              storlink_ctl.link[ tp->port_id] = 0;
++#endif
++              }
++      }
++      else
++      {
++              tp->pre_phy_status = LINK_UP;
++              status.bits.link = LINK_UP;
++              //              set_bit(__LINK_STATE_START, &dev->state);
++              printk("Link Up (0x%04x) ",reg_val);
++              if(Giga_switch == 1)
++              {
++                              wan_port_id = 1;
++#ifdef CONFIG_SL351x_SYSCTL
++                              storlink_ctl.link[ wan_port_id] = 1;
++#endif
++              }
++              else
++              {
++#ifdef CONFIG_SL351x_SYSCTL
++                              storlink_ctl.link[ tp->port_id] = 1;
++#endif
++              }
++      }
++      //    value = mii_read(PHY_ADDR,0x05);
++
++      ability = (mii_read(tp->phy_addr,0x05) & 0x05E0) >> 5;
++
++      //#ifdef CONFIG_SL3516_ASIC
++      reg_val = mii_read(tp->phy_addr,10);
++      printk("MII REG 10 = 0x%x\n",reg_val);
++
++      if ((reg_val & 0x0800) == 0x0800)
++      {
++              status.bits.duplex = 1;
++              status.bits.speed = 2;
++              if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
++              status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
++
++              printk(" 1000M/Full \n");
++      }
++      else if ((reg_val & 0x0400) == 0x0400)
++      {
++              status.bits.duplex = 0;
++              status.bits.speed = 2;
++              if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
++              status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
++
++              printk(" 1000M/Half \n");
++      }
++      //#endif
++      else
++      {
++              #ifdef CONFIG_SL3516_ASIC
++              if (status.bits.mii_rmii == GMAC_PHY_RGMII_1000)
++              status.bits.mii_rmii = GMAC_PHY_RGMII_100;
++              #endif
++              printk("MII REG 5 (bit 5:15) = 0x%x\n", ability);
++              if ((ability & 0x08)==0x08) /* 100M full duplex */
++              {
++                      status.bits.duplex = 1;
++                      status.bits.speed = 1;
++                      printk(" 100M/Full\n");
++
++              }
++              else if ((ability & 0x04)==0x04) /* 100M half duplex */
++              {
++                      status.bits.duplex = 0;
++                      status.bits.speed = 1;
++                      printk(" 100M/Half\n");
++
++              }
++              else if ((ability & 0x02)==0x02) /* 10M full duplex */
++              {
++                      status.bits.duplex = 1;
++                      status.bits.speed = 0;
++                      printk(" 10M/Full\n");
++
++              }
++              else if ((ability & 0x01)==0x01) /* 10M half duplex */
++              {
++                      status.bits.duplex = 0;
++                      status.bits.speed = 0;
++                      printk(" 10M/Half\n");
++
++              }
++      }
++      if ((ability & 0x20)==0x20)
++      {
++              tp->flow_control_enable = 1;
++              printk("Flow Control Enable.\n");
++      }
++      else
++      {
++              tp->flow_control_enable = 0;
++              printk("Flow Control Disable.\n");
++      }
++      tp->full_duplex_status = status.bits.duplex;
++      tp->speed_status = status.bits.speed;
++      if (!tp->auto_nego_cfg)
++      {
++              status.bits.duplex = tp->full_duplex_cfg;
++              status.bits.speed = tp->speed_cfg;
++      }
++      toe_gmac_disable_tx_rx(dev);
++      mdelay(10);
++      gmac_write_reg(tp->base_addr, GMAC_STATUS, status.bits32, 0x0000007f);
++      toe_gmac_enable_tx_rx(dev);
++}
++
++/*----------------------------------------------------------------------
++* gmac_phy_thread
++*----------------------------------------------------------------------*/
++static int gmac_phy_thread (void *data)
++{
++      struct net_device   *dev = data;
++      GMAC_INFO_T *tp = dev->priv;
++      unsigned long       timeout;
++
++    daemonize("%s", dev->name);
++      allow_signal(SIGTERM);
++//    reparent_to_init();
++//    spin_lock_irq(&current->sigmask_lock);
++//    sigemptyset(&current->blocked);
++//    recalc_sigpending(current);
++//    spin_unlock_irq(&current->sigmask_lock);
++//    strncpy (current->comm, dev->name, sizeof(current->comm) - 1);
++//    current->comm[sizeof(current->comm) - 1] = '\0';
++
++      while (1)
++      {
++          timeout = next_tick;
++              do
++              {
++                      timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
++              } while (!signal_pending (current) && (timeout > 0));
++
++              if (signal_pending (current))
++              {
++//                    spin_lock_irq(&current->sigmask_lock);
++                      flush_signals(current);
++//                    spin_unlock_irq(&current->sigmask_lock);
++              }
++
++              if (tp->time_to_die)
++                      break;
++
++              // printk("%s : Polling MAC %d PHY Status...\n",__func__, tp->port_id);
++              rtnl_lock ();
++              if (tp->auto_nego_cfg){
++#ifdef VITESSE_G5SWITCH
++                      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1))
++                              gmac_get_switch_status(dev);
++                      else
++#endif
++                              gmac_get_phy_status(dev); //temp remove
++              }
++              rtnl_unlock ();
++      }
++      complete_and_exit (&tp->thr_exited, 0);
++}
++
++/*----------------------------------------------------------------------
++* gmac_get_switch_status
++*----------------------------------------------------------------------*/
++#ifdef VITESSE_G5SWITCH
++void gmac_get_switch_status(struct net_device *dev)
++{
++      GMAC_INFO_T *tp = dev->priv;
++      GMAC_CONFIG0_T  config0,config0_mask;
++      unsigned int    switch_port_id;
++      int get_link=0;
++
++      get_link = Get_Set_port_status();
++      if(get_link){                           // link
++              if(ever_dwon){
++                      ever_dwon = 0;
++                      toe_gmac_enable_tx_rx(dev);
++                      netif_wake_queue(dev);
++                      set_bit(__LINK_STATE_START, &dev->state);
++              }
++      }
++      else{                                   // all down
++              //printk("All link down\n");
++              ever_dwon=1;
++              netif_stop_queue(dev);
++              toe_gmac_disable_tx_rx(dev);
++              clear_bit(__LINK_STATE_START, &dev->state);
++      }
++
++      if ( tp->port_id == 1 )
++              switch_port_id = 0;
++#ifdef CONFIG_SL351x_SYSCTL
++      if (get_link)
++      {
++              storlink_ctl.link[switch_port_id] = 1;
++      }
++      else
++      {
++              storlink_ctl.link[switch_port_id] = 0;
++      }
++      if (storlink_ctl.pauseoff == 1)
++              {
++                      if (tp->flow_control_enable == 1)
++                      {
++                              config0.bits32 = 0;
++                              config0_mask.bits32 = 0;
++                              config0.bits.tx_fc_en = 0; /* disable tx flow control */
++                              config0.bits.rx_fc_en = 0; /* disable rx flow control */
++                              config0_mask.bits.tx_fc_en = 1;
++                              config0_mask.bits.rx_fc_en = 1;
++                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++                              printk("Disable SWITCH Flow Control...\n");
++                      }
++                              tp->flow_control_enable = 0;
++              }
++              else
++#endif
++              {
++                      if (tp->flow_control_enable == 0)
++                      {
++                              config0.bits32 = 0;
++                              config0_mask.bits32 = 0;
++                              config0.bits.tx_fc_en = 1; /* enable tx flow control */
++                              config0.bits.rx_fc_en = 1; /* enable rx flow control */
++                              config0_mask.bits.tx_fc_en = 1;
++                              config0_mask.bits.rx_fc_en = 1;
++                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++                              printk("Enable SWITCH Flow Control...\n");
++                      }
++                      tp->flow_control_enable = 1;
++              }
++      return ;
++
++}
++#endif
++
++/*----------------------------------------------------------------------
++* gmac_get_phy_status
++*----------------------------------------------------------------------*/
++void gmac_get_phy_status(struct net_device *dev)
++{
++      GMAC_INFO_T *tp = dev->priv;
++      GMAC_CONFIG0_T  config0,config0_mask;
++      GMAC_STATUS_T   status, old_status;
++      unsigned int    reg_val,ability,wan_port_id;
++
++      old_status.bits32 = status.bits32 = gmac_read_reg(tp->base_addr, GMAC_STATUS);
++
++
++      /* read PHY status register */
++      reg_val = mii_read(tp->phy_addr,0x01);
++      if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */
++      {
++              ability = (mii_read(tp->phy_addr,0x05) & 0x05E0) >> 5;
++              /* read PHY Auto-Negotiation Link Partner Ability Register */
++              #ifdef CONFIG_SL3516_ASIC
++              reg_val = mii_read(tp->phy_addr,10);
++              if ((reg_val & 0x0800) == 0x0800)
++              {
++                      status.bits.duplex = 1;
++                      status.bits.speed = 2;
++                      if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
++                      status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
++              }
++              else if ((reg_val & 0x0400) == 0x0400)
++              {
++                      status.bits.duplex = 0;
++                      status.bits.speed = 2;
++                      if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
++                      status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
++              }
++              else
++              #endif
++              {
++                      #ifdef CONFIG_SL3516_ASIC
++                      if (status.bits.mii_rmii == GMAC_PHY_RGMII_1000)
++                      status.bits.mii_rmii = GMAC_PHY_RGMII_100;
++                      #endif
++                      if ((ability & 0x08)==0x08) /* 100M full duplex */
++                      {
++                              status.bits.duplex = 1;
++                              status.bits.speed = 1;
++                      }
++                      else if ((ability & 0x04)==0x04) /* 100M half duplex */
++                      {
++                              status.bits.duplex = 0;
++                              status.bits.speed = 1;
++                      }
++                      else if ((ability & 0x02)==0x02) /* 10M full duplex */
++                      {
++                              status.bits.duplex = 1;
++                              status.bits.speed = 0;
++                      }
++                      else if ((ability & 0x01)==0x01) /* 10M half duplex */
++                      {
++                              status.bits.duplex = 0;
++                              status.bits.speed = 0;
++                      }
++              }
++              status.bits.link = LINK_UP; /* link up */
++              if(Giga_switch==1)
++              {
++                              wan_port_id = 1;
++#ifdef CONFIG_SL351x_SYSCTL
++                              storlink_ctl.link[ wan_port_id] = 1;
++              }
++              else
++              {
++                              storlink_ctl.link[ tp->port_id] = 1;
++#endif
++              }
++              if ((ability & 0x20)==0x20)
++              {
++                      if (tp->flow_control_enable == 0)
++                      {
++                              config0.bits32 = 0;
++                              config0_mask.bits32 = 0;
++                              config0.bits.tx_fc_en = 1; /* enable tx flow control */
++                              config0.bits.rx_fc_en = 1; /* enable rx flow control */
++                              config0_mask.bits.tx_fc_en = 1;
++                              config0_mask.bits.rx_fc_en = 1;
++                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++                              printk("GMAC-%d Flow Control Enable.\n", tp->port_id);
++                      }
++                      tp->flow_control_enable = 1;
++              }
++              else
++              {
++                      if (tp->flow_control_enable == 1)
++                      {
++                              config0.bits32 = 0;
++                              config0_mask.bits32 = 0;
++                              config0.bits.tx_fc_en = 0; /* disable tx flow control */
++                              config0.bits.rx_fc_en = 0; /* disable rx flow control */
++                              config0_mask.bits.tx_fc_en = 1;
++                              config0_mask.bits.rx_fc_en = 1;
++                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
++                              printk("GMAC-%d Flow Control Disable.\n", tp->port_id);
++                      }
++                      tp->flow_control_enable = 0;
++              }
++
++              if (tp->pre_phy_status == LINK_DOWN)
++              {
++                      printk("GMAC-%d LINK_UP......\n",tp->port_id);
++                      tp->pre_phy_status = LINK_UP;
++              }
++      }
++      else
++      {
++              status.bits.link = LINK_DOWN; /* link down */
++              if(Giga_switch == 1)
++              {
++                              wan_port_id = 1;
++#ifdef CONFIG_SL351x_SYSCTL
++                              storlink_ctl.link[ wan_port_id] = 0;
++              }
++              else
++              {
++                              storlink_ctl.link[ tp->port_id] = 0;
++#endif
++              }
++              if (tp->pre_phy_status == LINK_UP)
++              {
++                      printk("GMAC-%d LINK_Down......\n",tp->port_id);
++                      tp->pre_phy_status = LINK_DOWN;
++              }
++      }
++
++      tp->full_duplex_status = status.bits.duplex;
++      tp->speed_status = status.bits.speed;
++      if (!tp->auto_nego_cfg)
++      {
++              status.bits.duplex = tp->full_duplex_cfg;
++              status.bits.speed = tp->speed_cfg;
++      }
++
++      if (old_status.bits32 != status.bits32)
++      {
++              netif_stop_queue(dev);
++              toe_gmac_disable_tx_rx(dev);
++              clear_bit(__LINK_STATE_START, &dev->state);
++              printk("GMAC-%d Change Status Bits 0x%x-->0x%x\n",tp->port_id, old_status.bits32, status.bits32);
++              mdelay(10); // let GMAC consume packet
++              gmac_write_reg(tp->base_addr, GMAC_STATUS, status.bits32, 0x0000007f);
++              if (status.bits.link == LINK_UP)
++              {
++                      toe_gmac_enable_tx_rx(dev);
++                      netif_wake_queue(dev);
++                      set_bit(__LINK_STATE_START, &dev->state);
++              }
++      }
++}
++
++/***************************************/
++/* define GPIO module base address     */
++/***************************************/
++#define GPIO_BASE_ADDR  (IO_ADDRESS(SL2312_GPIO_BASE))
++#define GPIO_BASE_ADDR1  (IO_ADDRESS(SL2312_GPIO_BASE1))
++
++/* define GPIO pin for MDC/MDIO */
++#ifdef CONFIG_SL3516_ASIC
++#define H_MDC_PIN           22
++#define H_MDIO_PIN          21
++#define G_MDC_PIN           22
++#define G_MDIO_PIN          21
++#else
++#define H_MDC_PIN           3
++#define H_MDIO_PIN          2
++#define G_MDC_PIN           0
++#define G_MDIO_PIN          1
++#endif
++
++//#define GPIO_MDC             0x80000000
++//#define GPIO_MDIO            0x00400000
++
++static unsigned int GPIO_MDC = 0;
++static unsigned int GPIO_MDIO = 0;
++static unsigned int GPIO_MDC_PIN = 0;
++static unsigned int GPIO_MDIO_PIN = 0;
++
++// For PHY test definition!!
++#define LPC_EECK              0x02
++#define LPC_EDIO              0x04
++#define LPC_GPIO_SET          3
++#define LPC_BASE_ADDR         IO_ADDRESS(IT8712_IO_BASE)
++#define inb_gpio(x)           inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
++#define outb_gpio(x, y)               outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
++
++enum GPIO_REG
++{
++    GPIO_DATA_OUT   = 0x00,
++    GPIO_DATA_IN    = 0x04,
++    GPIO_PIN_DIR    = 0x08,
++    GPIO_BY_PASS    = 0x0c,
++    GPIO_DATA_SET   = 0x10,
++    GPIO_DATA_CLEAR = 0x14,
++};
++/***********************/
++/*    MDC : GPIO[31]   */
++/*    MDIO: GPIO[22]   */
++/***********************/
++
++/***************************************************
++* All the commands should have the frame structure:
++*<PRE><ST><OP><PHYAD><REGAD><TA><DATA><IDLE>
++****************************************************/
++
++/*****************************************************************
++* Inject a bit to NWay register through CSR9_MDC,MDIO
++*******************************************************************/
++void mii_serial_write(char bit_MDO) // write data into mii PHY
++{
++#ifdef CONFIG_SL2312_LPC_IT8712
++      unsigned char iomode,status;
++
++      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
++      iomode |= (LPC_EECK|LPC_EDIO) ;                         // Set EECK,EDIO,EECS output
++      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
++
++      if(bit_MDO)
++      {
++              status = inb_gpio( LPC_GPIO_SET);
++              status |= LPC_EDIO ;            //EDIO high
++              outb_gpio(LPC_GPIO_SET, status);
++      }
++      else
++      {
++              status = inb_gpio( LPC_GPIO_SET);
++              status &= ~(LPC_EDIO) ;         //EDIO low
++              outb_gpio(LPC_GPIO_SET, status);
++      }
++
++      status |= LPC_EECK ;            //EECK high
++      outb_gpio(LPC_GPIO_SET, status);
++
++      status &= ~(LPC_EECK) ;         //EECK low
++      outb_gpio(LPC_GPIO_SET, status);
++
++#else
++    unsigned int addr;
++    unsigned int value;
++
++    addr = GPIO_BASE_ADDR + GPIO_PIN_DIR;
++    value = readl(addr) | GPIO_MDC | GPIO_MDIO; /* set MDC/MDIO Pin to output */
++    writel(value,addr);
++    if(bit_MDO)
++    {
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++        writel(GPIO_MDIO,addr); /* set MDIO to 1 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++        writel(GPIO_MDC,addr); /* set MDC to 1 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++        writel(GPIO_MDC,addr); /* set MDC to 0 */
++    }
++    else
++    {
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++        writel(GPIO_MDIO,addr); /* set MDIO to 0 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
++        writel(GPIO_MDC,addr); /* set MDC to 1 */
++        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++        writel(GPIO_MDC,addr); /* set MDC to 0 */
++    }
++
++#endif
++}
++
++/**********************************************************************
++* read a bit from NWay register through CSR9_MDC,MDIO
++***********************************************************************/
++unsigned int mii_serial_read(void) // read data from mii PHY
++{
++#ifdef CONFIG_SL2312_LPC_IT8712
++      unsigned char iomode,status;
++      unsigned int value ;
++
++      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
++      iomode &= ~(LPC_EDIO) ;         // Set EDIO input
++      iomode |= (LPC_EECK) ;          // Set EECK,EECS output
++      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
++
++      status = inb_gpio( LPC_GPIO_SET);
++      status |= LPC_EECK ;            //EECK high
++      outb_gpio(LPC_GPIO_SET, status);
++
++      status &= ~(LPC_EECK) ;         //EECK low
++      outb_gpio(LPC_GPIO_SET, status);
++
++      value = inb_gpio( LPC_GPIO_SET);
++
++      value = value>>2 ;
++      value &= 0x01;
++
++      return value ;
++
++#else
++    unsigned int *addr;
++    unsigned int value;
++
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_PIN_DIR);
++    value = readl(addr) & ~GPIO_MDIO; //0xffbfffff;   /* set MDC to output and MDIO to input */
++    writel(value,addr);
++
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);
++    writel(GPIO_MDC,addr); /* set MDC to 1 */
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
++    writel(GPIO_MDC,addr); /* set MDC to 0 */
++
++    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_IN);
++    value = readl(addr);
++    value = (value & (1<<GPIO_MDIO_PIN)) >> GPIO_MDIO_PIN;
++    return(value);
++
++#endif
++}
++
++/***************************************
++* preamble + ST
++***************************************/
++void mii_pre_st(void)
++{
++    unsigned char i;
++
++    for(i=0;i<32;i++) // PREAMBLE
++        mii_serial_write(1);
++    mii_serial_write(0); // ST
++    mii_serial_write(1);
++}
++
++
++/******************************************
++* Read MII register
++* phyad -> physical address
++* regad -> register address
++***************************************** */
++unsigned int mii_read(unsigned char phyad,unsigned char regad)
++{
++    unsigned int i,value;
++    unsigned int bit;
++
++    if (phyad == GPHY_ADDR)
++    {
++        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
++        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
++    }
++    else
++    {
++        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
++        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
++    }
++    GPIO_MDC = (1<<GPIO_MDC_PIN);
++    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
++
++    mii_pre_st(); // PRE+ST
++    mii_serial_write(1); // OP
++    mii_serial_write(0);
++
++    for (i=0;i<5;i++) { // PHYAD
++        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++
++    for (i=0;i<5;i++) { // REGAD
++        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++
++    mii_serial_read(); // TA_Z
++//    if((bit=mii_serial_read()) !=0 ) // TA_0
++//    {
++//        return(0);
++//    }
++    value=0;
++    for (i=0;i<16;i++) { // READ DATA
++        bit=mii_serial_read();
++        value += (bit<<(15-i)) ;
++    }
++
++    mii_serial_write(0); // dumy clock
++    mii_serial_write(0); // dumy clock
++
++      //printk("%s: phy_addr=0x%x reg_addr=0x%x value=0x%x \n",__func__,phyad,regad,value);
++    return(value);
++}
++
++/******************************************
++* Write MII register
++* phyad -> physical address
++* regad -> register address
++* value -> value to be write
++***************************************** */
++void mii_write(unsigned char phyad,unsigned char regad,unsigned int value)
++{
++    unsigned int i;
++    char bit;
++
++      printk("%s: phy_addr=0x%x reg_addr=0x%x value=0x%x \n",__func__,phyad,regad,value);
++    if (phyad == GPHY_ADDR)
++    {
++        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
++        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
++    }
++    else
++    {
++        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
++        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
++    }
++    GPIO_MDC = (1<<GPIO_MDC_PIN);
++    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
++
++    mii_pre_st(); // PRE+ST
++    mii_serial_write(0); // OP
++    mii_serial_write(1);
++    for (i=0;i<5;i++) { // PHYAD
++        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++
++    for (i=0;i<5;i++) { // REGAD
++        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
++        mii_serial_write(bit);
++    }
++    mii_serial_write(1); // TA_1
++    mii_serial_write(0); // TA_0
++
++    for (i=0;i<16;i++) { // OUT DATA
++        bit= ((value>>(15-i)) & 0x01) ? 1 : 0 ;
++        mii_serial_write(bit);
++    }
++    mii_serial_write(0); // dumy clock
++    mii_serial_write(0); // dumy clock
++}
++
++/*----------------------------------------------------------------------
++* gmac_set_rx_mode
++*----------------------------------------------------------------------*/
++static void gmac_set_rx_mode(struct net_device *dev)
++{
++    GMAC_RX_FLTR_T      filter;
++      unsigned int        mc_filter[2];       /* Multicast hash filter */
++    int                 bit_nr;
++      unsigned int        i;
++      GMAC_INFO_T             *tp = dev->priv;
++
++//    printk("%s : dev->flags = %x \n",__func__,dev->flags);
++//    dev->flags |= IFF_ALLMULTI;  /* temp */
++    filter.bits32 = 0;
++    filter.bits.error = 0;
++      if (dev->flags & IFF_PROMISC)
++      {
++          filter.bits.error = 1;
++        filter.bits.promiscuous = 1;
++        filter.bits.broadcast = 1;
++        filter.bits.multicast = 1;
++        filter.bits.unicast = 1;
++              mc_filter[1] = mc_filter[0] = 0xffffffff;
++      }
++      else if (dev->flags & IFF_ALLMULTI)
++      {
++//        filter.bits.promiscuous = 1;
++        filter.bits.broadcast = 1;
++        filter.bits.multicast = 1;
++        filter.bits.unicast = 1;
++              mc_filter[1] = mc_filter[0] = 0xffffffff;
++      }
++      else
++      {
++              struct dev_mc_list *mclist;
++
++//        filter.bits.promiscuous = 1;
++        filter.bits.broadcast = 1;
++        filter.bits.multicast = 1;
++        filter.bits.unicast = 1;
++              mc_filter[1] = mc_filter[0] = 0;
++              for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;i++, mclist = mclist->next)
++              {
++            bit_nr = ether_crc(ETH_ALEN,mclist->dmi_addr) & 0x0000003f;
++            if (bit_nr < 32)
++            {
++                mc_filter[0] = mc_filter[0] | (1<<bit_nr);
++            }
++            else
++            {
++                mc_filter[1] = mc_filter[1] | (1<<(bit_nr-32));
++            }
++              }
++      }
++    gmac_write_reg(tp->base_addr,GMAC_RX_FLTR,filter.bits32,0xffffffff);  //chech base address!!!
++    gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL0,mc_filter[0],0xffffffff);
++    gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL1,mc_filter[1],0xffffffff);
++    return;
++}
++
++#ifdef CONFIG_SL_NAPI
++/*----------------------------------------------------------------------
++* gmac_rx_poll
++*----------------------------------------------------------------------*/
++static int gmac_rx_poll(struct net_device *dev, int *budget)
++{
++      TOE_INFO_T                      *toe;
++    GMAC_RXDESC_T     *curr_desc;
++      struct sk_buff          *skb;
++    DMA_RWPTR_T                       rwptr;
++      unsigned int            pkt_size;
++      unsigned int        desc_count;
++      unsigned int        good_frame, chksum_status, rx_status;
++      int                 rx_pkts_num = 0;
++      int                 quota = min(dev->quota, *budget);
++      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
++      unsigned int            status4;
++      volatile DMA_RWPTR_T    fq_rwptr;
++      int                                     max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
++      //unsigned long         rx_old_bytes;
++      struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
++      //unsigned long long    rx_time;
++
++
++
++#if 1
++      if (do_again)
++      {
++                      toe_gmac_fill_free_q();
++                      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++                      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                      //printk("\n%s:: do_again toe_gmac_fill_free_q =======>status4=0x%x =====fq_rwptr =0x%8x======>JKJKJKJKJKJKJKJKJ \n", __func__,status4,fq_rwptr.bits32);
++                      if (fq_rwptr.bits.wptr != fq_rwptr.bits.rptr)
++                      {
++                                              //status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++                                              do_again =0;
++                                              //netif_rx_complete(dev);
++                                              gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4, 0x1);
++                                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                                              rwptr.bits32 = readl(&tp->default_qhdr->word1);
++                      }
++                      else
++                              return 1;
++      }
++#endif
++      rwptr.bits32 = readl(&tp->default_qhdr->word1);
++#if 0
++      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
++      {
++              mac_stop_txdma((struct net_device *)tp->dev);
++              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
++                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
++              while(1);
++      }
++#endif
++      toe = (TOE_INFO_T *)&toe_private_data;
++
++      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++      //printk("%s:---Before-------------->Default Queue HW RW ptr (0x%8x),   fq_rwptr =0x%8x \n",__func__,rwptr.bits32,fq_rwptr.bits32 );
++      //printk("%s:---Before while   rx_pkts_num=%d------rx_finished_idx=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rx_finished_idx,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
++//    while ((--max_cnt) && (rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
++
++      while ((rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
++      {
++
++      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
++              tp->default_q_cnt++;
++      tp->rx_curr_desc = (unsigned int)curr_desc;
++      rx_status = curr_desc->word0.bits.status;
++      chksum_status = curr_desc->word0.bits.chksum_status;
++      tp->rx_status_cnt[rx_status]++;
++      tp->rx_chksum_cnt[chksum_status]++;
++        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
++              desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
++              good_frame=1;
++              if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
++                      || (pkt_size < 60)
++                  || (chksum_status & 0x4)
++                  || rx_status )
++//                    || rx_status || (rwptr.bits.rptr > rwptr.bits.wptr ))
++              {
++                      good_frame = 0;
++                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
++                              printk("%s::derr (GMAC-%d)!!!\n", __func__, tp->port_id);
++                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_perr)
++                              printk("%s::perr (GMAC-%d)!!!\n", __func__, tp->port_id);
++                      if (rx_status)
++                      {
++                              if (rx_status == 4 || rx_status == 7)
++                                      isPtr->rx_crc_errors++;
++//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
++                      }
++#ifdef SL351x_GMAC_WORKAROUND
++                      else if (pkt_size < 60)
++                      {
++                              if (tp->short_frames_cnt < GMAC_SHORT_FRAME_THRESHOLD)
++                                      tp->short_frames_cnt++;
++                              if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
++                              {
++                                      GMAC_CONFIG0_T config0;
++                                      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++                                      config0.bits.dis_rx = 1;
++                                      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++                                      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++                                      config0.bits.dis_rx = 1;
++                                      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++                              }
++                      }
++#endif
++//                    if (chksum_status)
++//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
++                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
++                      dev_kfree_skb_irq(skb);
++              }
++              if (good_frame)
++              {
++                      if (curr_desc->word0.bits.drop)
++                              printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
++//                    if (chksum_status)
++//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
++
++#ifdef SL351x_GMAC_WORKAROUND
++                      if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
++                      {
++                              GMAC_CONFIG0_T config0;
++                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++                              config0.bits.dis_rx = 0;
++                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++                              config0.bits.dis_rx = 0;
++                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++                      }
++                      tp->short_frames_cnt = 0;
++#endif
++              /* get frame information from the first descriptor of the frame */
++                      isPtr->rx_packets++;
++                      //consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
++                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
++                      tp->curr_rx_skb = skb;
++      //              curr_desc->word2.buf_adr = 0;
++
++                  //skb_reserve (skb, SKB_RESERVE_BYTES);
++                      skb_reserve (skb, RX_INSERT_BYTES);     /* 2 byte align the IP fields. */
++                      //if ((skb->tail+pkt_size) > skb->end )
++                      //printk("%s::------------->Here skb->len=%d,pkt_size= %d,skb->head=0x%x,skb->tail= 0x%x, skb->end= 0x%x\n", __func__, skb->len, pkt_size,skb->head,skb->tail,skb->end);
++                      skb_put(skb, pkt_size);
++
++
++                      skb->dev = dev;
++                      if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
++                      {
++                              skb->ip_summed = CHECKSUM_UNNECESSARY;
++#ifdef CONFIG_SL351x_NAT
++                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
++                              {
++                                      struct iphdr    *ip_hdr;
++                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
++                                      sl351x_nat_input(skb,
++                                                                      tp->port_id,
++                                                                      (void *)curr_desc->word3.bits.l3_offset,
++                                                                      (void *)curr_desc->word3.bits.l4_offset);
++                              }
++#endif
++                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
++#if 0
++#ifdef CONFIG_SL351x_RXTOE
++                              if (storlink_ctl.rx_max_pktsize) {
++                                      struct iphdr    *ip_hdr;
++                                      struct tcphdr   *tcp_hdr;
++                                      int ip_hdrlen;
++
++                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
++                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
++                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
++                                              ip_hdrlen = ip_hdr->ihl << 2;
++                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
++                                              if (tcp_hdr->syn) {
++                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
++                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
++                                                      TCP_SKB_CB(skb)->connection = connection;
++                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
++                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
++                                                      //                      __func__, skb->data, connection, connection->mode);
++                                              }
++                                      }
++                              }
++#endif
++#endif
++                      }
++                      else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
++                      {
++                              skb->ip_summed = CHECKSUM_UNNECESSARY;
++#ifdef CONFIG_SL351x_NAT
++                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
++                              {
++                                      struct iphdr    *ip_hdr;
++                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
++                                      if (ip_hdr->protocol == IPPROTO_UDP)
++                                      {
++                                              sl351x_nat_input(skb,
++                                                                              tp->port_id,
++                                                                              (void *)curr_desc->word3.bits.l3_offset,
++                                                                              (void *)curr_desc->word3.bits.l4_offset);
++                                      }
++                                      else if (ip_hdr->protocol == IPPROTO_GRE)
++                                      {
++                                              sl351x_nat_input(skb,
++                                                                      tp->port_id,
++                                                                      (void *)curr_desc->word3.bits.l3_offset,
++                                                                      (void *)curr_desc->word3.bits.l4_offset);
++                                      }
++                              }
++#endif
++                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
++                      }
++                      else
++                      {
++                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
++                      }
++                      //netif_rx(skb);  /* socket rx */
++                      netif_receive_skb(skb); //For NAPI
++                      dev->last_rx = jiffies;
++
++                      isPtr->rx_bytes += pkt_size;
++                      //printk("------------------->isPtr->rx_bytes = %d\n",isPtr->rx_bytes);
++
++
++        }
++              // advance one for Rx default Q 0/1
++              rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
++              SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
++      tp->rx_rwptr.bits32 = rwptr.bits32;
++              rx_pkts_num++;
++              //rwptr.bits32 = readl(&tp->default_qhdr->word1);//try read default_qhdr again
++              //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++              //printk("%s:---Loop  -------->rx_pkts_num=%d------------>Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits32,fq_rwptr.bits32 );
++#if 0
++              if ((status4 & 0x1) == 0)
++              {
++                      //if (!((dev->last_rx <= (rx_time + 2)) &&  (isPtr->rx_bytes > (rx_old_bytes + 1000000 ))))
++                      if (tp->total_q_cnt_napi < 1024)
++                      {
++                              tp->total_q_cnt_napi++;
++                              toe_gmac_fill_free_q();  //for iperf test disable
++                      }
++                      //else
++                              //printk("%s:---isPtr->rx_bytes =%u , rx_old_bytes =%u\n",__func__,isPtr->rx_bytes,rx_old_bytes );
++
++              }
++#endif
++              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
++              //printk("%s:---Loop  -------->rx_pkts_num=%d----rwptr.bits.rptr=0x%x-------->Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits32,fq_rwptr.bits32 );
++              //printk("%s:---Loop  rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
++      }
++      // advance one for Rx default Q 0/1
++
++              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
++              //SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
++      //tp->rx_rwptr.bits32 = rwptr.bits32;
++      //rwptr.bits.rptr = rwptr.bits.rptr;
++
++      dev->quota -= rx_pkts_num;
++      *budget -= rx_pkts_num;
++
++      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);//try read SWFQ empty again
++      //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++      rwptr.bits32 = readl(&tp->default_qhdr->word1); //try read default_qhdr again
++      //printk("%s:---After    rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
++//    if (rwptr.bits.rptr > rwptr.bits.wptr )
++//                    {
++                              //toe_gmac_disable_rx(dev);
++                              //wait_event_interruptible_timeout(freeq_wait,
++                                      //(rx_pkts_num == 100), CMTP_INTEROP_TIMEOUT);
++                              //printk("\n%s:: return 22222=======> rx_pkts_num =%d,   rwptr.bits.rptr=%d,   rwptr.bits.wptr = %d ====---------=======>JKJKJKJKJK\n",
++                                      //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
++//                            return 1;
++//                    }
++
++      if (rwptr.bits.rptr == rwptr.bits.wptr)
++      {
++              unsigned int data32;
++                      //printk("%s:---[rwptr.bits.rptr == rwptr.bits.wptr]   rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
++
++          /* Receive descriptor is empty now */
++#if 1
++     if (status4 & 0x1)
++                      {
++                              do_again =1;
++                              //writel(0x40400000, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_4_REG); //disable SWFQ empty interrupt
++                              //toe_gmac_disable_interrupt(tp->irq);
++                              tp->sw_fq_empty_cnt++;
++                              //toe_gmac_disable_rx(dev);
++                              writel(0x07960202, TOE_GMAC0_BASE+GMAC_CONFIG0);
++                              writel(0x07960202, TOE_GMAC1_BASE+GMAC_CONFIG0);
++                              //printk("\n%s ::  freeq int-----tp->sw_fq_empty_cnt  =%d---------====================----------------->\n",__func__,tp->sw_fq_empty_cnt);
++                              //while ((fq_rwptr.bits.wptr >= (fq_rwptr.bits.rptr+256)) || (fq_rwptr.bits.wptr <= (fq_rwptr.bits.rptr+256)))
++                              //{
++                                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
++                                      //0x1);
++                              //printk("\n%s::fq_rwptr.wrptr = %x =======> ===========>here \n", __func__,fq_rwptr.bits32);
++                              //if ((status4 & 0x1) == 0)
++                                      //break;
++                               return 1;
++                              //}
++
++                      }
++#endif
++        //toe_gmac_fill_free_q();
++        netif_rx_complete(dev);
++        // enable GMAC-0 rx interrupt
++        // class-Q & TOE-Q are implemented in future
++        //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++        //if (tp->port_id == 0)
++              //data32 |= DEFAULT_Q0_INT_BIT;
++        //else
++              //data32 |= DEFAULT_Q1_INT_BIT;
++        //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++              writel(0x3, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
++              //printk("\n%s::netif_rx_complete-->  rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x ====---------=======>JKJKJKJKJK\n",
++              //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
++        writel(0x07960200, TOE_GMAC0_BASE+GMAC_CONFIG0);
++              writel(0x07960200, TOE_GMAC1_BASE+GMAC_CONFIG0);
++        return 0;
++    }
++    else
++    {
++        //printk("\n%s:: return 1 -->status4= 0x%x,rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x  ======> \n", __func__,status4,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
++        return 1;
++    }
++}
++#endif
++
++/*----------------------------------------------------------------------
++* gmac_tx_timeout
++*----------------------------------------------------------------------*/
++void gmac_tx_timeout(struct net_device *dev)
++{
++      GMAC_INFO_T                             *tp = (GMAC_INFO_T *)dev->priv;
++
++#ifdef CONFIG_SL351x_SYSCTL
++      if (tp->operation && storlink_ctl.link[tp->port_id])
++#else
++      if (tp->operation)
++#endif
++      {
++              netif_wake_queue(dev);
++      }
++}
++
++
++
++/*----------------------------------------------------------------------
++* mac_set_rule_reg
++*----------------------------------------------------------------------*/
++int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2)
++{
++      int             total_key_dwords;
++
++      total_key_dwords = 1;
++
++      if (reg0 & MR_L2_BIT)
++      {
++              if (reg0 & MR_DA_BIT) total_key_dwords += 2;
++              if (reg0 & MR_SA_BIT) total_key_dwords += 2;
++              if ((reg0 & MR_DA_BIT) && ( reg0 & MR_SA_BIT)) total_key_dwords--;
++              if (reg0 & (MR_PPPOE_BIT | MR_VLAN_BIT)) total_key_dwords++;
++      }
++      if (reg0 & MR_L3_BIT)
++      {
++              if (reg0 & (MR_IP_HDR_LEN_BIT | MR_TOS_TRAFFIC_BIT | MR_SPR_BITS))
++                      total_key_dwords++;
++              if (reg0 & MR_FLOW_LABLE_BIT) total_key_dwords++;
++              if ((reg0 & MR_IP_VER_BIT) == 0) // IPv4
++              {
++                      if (reg1 & 0xff000000) total_key_dwords += 1;
++                      if (reg1 & 0x00ff0000) total_key_dwords += 1;
++              }
++              else
++              {
++                      if (reg1 & 0xff000000) total_key_dwords += 4;
++                      if (reg1 & 0x00ff0000) total_key_dwords += 4;
++              }
++      }
++      if (reg0 & MR_L4_BIT)
++      {
++              if (reg1 & 0x0000f000) total_key_dwords += 1;
++              if (reg1 & 0x00000f00) total_key_dwords += 1;
++              if (reg1 & 0x000000f0) total_key_dwords += 1;
++              if (reg1 & 0x0000000f) total_key_dwords += 1;
++              if (reg2 & 0xf0000000) total_key_dwords += 1;
++              if (reg2 & 0x0f000000) total_key_dwords += 1;
++      }
++      if (reg0 & MR_L7_BIT)
++      {
++              if (reg2 & 0x00f00000) total_key_dwords += 1;
++              if (reg2 & 0x000f0000) total_key_dwords += 1;
++              if (reg2 & 0x0000f000) total_key_dwords += 1;
++              if (reg2 & 0x00000f00) total_key_dwords += 1;
++              if (reg2 & 0x000000f0) total_key_dwords += 1;
++              if (reg2 & 0x0000000f) total_key_dwords += 1;
++      }
++
++      if (total_key_dwords > HASH_MAX_KEY_DWORD)
++              return -1;
++
++      if (total_key_dwords == 0 && enabled)
++              return -2;
++
++      mac_set_rule_enable_bit(mac, rule, 0);
++      if (enabled)
++      {
++              mac_set_MRxCRx(mac, rule, 0, reg0);
++              mac_set_MRxCRx(mac, rule, 1, reg1);
++              mac_set_MRxCRx(mac, rule, 2, reg2);
++              mac_set_rule_action(mac, rule, total_key_dwords);
++              mac_set_rule_enable_bit(mac, rule, enabled);
++      }
++      else
++      {
++              mac_set_rule_action(mac, rule, 0);
++      }
++      return total_key_dwords;
++}
++
++/*----------------------------------------------------------------------
++* mac_get_rule_enable_bit
++*----------------------------------------------------------------------*/
++int mac_get_rule_enable_bit(int mac, int rule)
++{
++      switch (rule)
++      {
++              case 0: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) >> 15) & 1);
++              case 1: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) >> 31) & 1);
++              case 2: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) >> 15) & 1);
++              case 3: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) >> 31) & 1);
++              default: return 0;
++      }
++}
++
++/*----------------------------------------------------------------------
++* mac_set_rule_enable_bit
++*----------------------------------------------------------------------*/
++void mac_set_rule_enable_bit(int mac, int rule, int data)
++{
++      u32 reg;
++
++      if (data & ~1)
++              return;
++
++      switch (rule)
++      {
++              case 0:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(1<<15)) | (data << 15);
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg);
++                      break;
++              case 1:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(1<<31)) | (data << 31);
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg);
++                      break;
++              case 2:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(1<<15)) | (data << 15);
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1, reg);
++                      break;
++              case 3:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(1<<31)) | (data << 31);
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1, reg);
++      }
++}
++
++/*----------------------------------------------------------------------
++* mac_set_rule_action
++*----------------------------------------------------------------------*/
++int mac_set_rule_action(int mac, int rule, int data)
++{
++      u32 reg;
++
++      if (data > 32)
++              return -1;
++
++      if (data)
++              data = (data << 6) | (data + HASH_ACTION_DWORDS);
++      switch (rule)
++      {
++              case 0:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(0x7ff));
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg | data);
++                      break;
++              case 1:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(0x7ff<<16));
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg | (data << 16));
++                      break;
++              case 2:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(0x7ff));
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1,  reg | data);
++                      break;
++              case 3:
++                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(0x7ff<<16));
++                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1, reg | (data << 16));
++                      break;
++              default:
++                      return -1;
++      }
++
++      return 0;
++}
++/*----------------------------------------------------------------------
++* mac_get_MRxCRx
++*----------------------------------------------------------------------*/
++int mac_get_MRxCRx(int mac, int rule, int ctrlreg)
++{
++      int reg;
++
++      switch (rule)
++      {
++              case 0: reg = GMAC_MR0CR0 + ctrlreg * 4; break;
++              case 1: reg = GMAC_MR1CR0 + ctrlreg * 4; break;
++              case 2: reg = GMAC_MR2CR0 + ctrlreg * 4; break;
++              case 3: reg = GMAC_MR3CR0 + ctrlreg * 4; break;
++              default: return 0;
++      }
++      return mac_read_dma_reg(mac, reg);
++}
++
++/*----------------------------------------------------------------------
++* mac_set_MRxCRx
++*----------------------------------------------------------------------*/
++void mac_set_MRxCRx(int mac, int rule, int ctrlreg, u32 data)
++{
++      int reg;
++
++      switch (rule)
++      {
++              case 0: reg = GMAC_MR0CR0 + ctrlreg * 4; break;
++              case 1: reg = GMAC_MR1CR0 + ctrlreg * 4; break;
++              case 2: reg = GMAC_MR2CR0 + ctrlreg * 4; break;
++              case 3: reg = GMAC_MR3CR0 + ctrlreg * 4; break;
++              default: return;
++      }
++      mac_write_dma_reg(mac, reg, data);
++}
++
++/*----------------------------------------------------------------------
++* mac_set_rule_priority
++*----------------------------------------------------------------------*/
++void mac_set_rule_priority(int mac, int p0, int p1, int p2, int p3)
++{
++      int                     i;
++      GMAC_MRxCR0_T   reg[4];
++
++      for (i=0; i<4; i++)
++              reg[i].bits32 = mac_get_MRxCRx(mac, i, 0);
++
++      reg[0].bits.priority = p0;
++      reg[1].bits.priority = p1;
++      reg[2].bits.priority = p2;
++      reg[3].bits.priority = p3;
++
++      for (i=0; i<4; i++)
++              mac_set_MRxCRx(mac, i, 0, reg[i].bits32);
++}
++
++/*----------------------------------------------------------------------
++* gmac_netdev_ioctl
++*----------------------------------------------------------------------*/
++static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++      int                             rc = 0;
++    unsigned char             *hwa = rq->ifr_ifru.ifru_hwaddr.sa_data;
++
++#ifdef br_if_ioctl
++    struct                            ethtool_cmd ecmd;       //br_if.c will call this ioctl
++      GMAC_INFO_T             *tp = dev->priv;
++#endif
++
++#ifdef        CONFIG_SL351x_NAT
++      if (cmd == SIOCDEVPRIVATE)
++              return sl351x_nat_ioctl(dev, rq, cmd);
++#endif
++
++      switch (cmd) {
++      case SIOCETHTOOL:
++#ifdef br_if_ioctl    //br_if.c will call this ioctl
++              if (!netif_running(dev))
++              {
++                      printk("Before changing the H/W address,please down the device.\n");
++                      return -EINVAL;
++              }
++              memset((void *) &ecmd, 0, sizeof (ecmd));
++                  ecmd.supported =
++                      SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
++                    SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
++                    SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
++                          ecmd.port = PORT_TP;
++                  ecmd.transceiver = XCVR_EXTERNAL;
++                  ecmd.phy_address = tp->phy_addr;
++                  switch (tp->speed_status)
++                  {
++                  case GMAC_SPEED_10: ecmd.speed = SPEED_10; break;
++                  case GMAC_SPEED_100: ecmd.speed = SPEED_100; break;
++                  case GMAC_SPEED_1000: ecmd.speed = SPEED_1000; break;
++                  default: ecmd.speed = SPEED_10; break;
++                 }
++                  ecmd.duplex = tp->full_duplex_status ? DUPLEX_FULL : DUPLEX_HALF;
++                  ecmd.advertising = ADVERTISED_TP;
++                  ecmd.advertising |= ADVERTISED_Autoneg;
++                  ecmd.autoneg = AUTONEG_ENABLE;
++                    if (copy_to_user(rq->ifr_data, &ecmd, sizeof (ecmd)))
++                      return -EFAULT;
++#endif
++
++        break;
++
++    case SIOCSIFHWADDR:
++              if (!netif_running(dev))
++              {
++                      printk("Before changing the H/W address,please down the device.\n");
++                      return -EINVAL;
++              }
++        gmac_set_mac_address(dev,hwa);
++        break;
++
++      case SIOCGMIIPHY:       /* Get the address of the PHY in use. */
++        break;
++
++      case SIOCGMIIREG:       /* Read the specified MII register. */
++              break;
++
++      case SIOCSMIIREG:       /* Write the specified MII register */
++              break;
++
++      default:
++              rc = -EOPNOTSUPP;
++              break;
++      }
++
++      return rc;
++}
++
++#ifdef SL351x_GMAC_WORKAROUND
++
++#define GMAC_TX_STATE_OFFSET  0x60
++#define GMAC_RX_STATE_OFFSET  0x64
++#define GMAC_POLL_HANGED_NUM  200
++#define GMAC_RX_HANGED_STATE  0x4b2000
++#define GMAC_RX_HANGED_MASK           0xdff000
++#define GMAC_TX_HANGED_STATE  0x34012
++#define GMAC_TX_HANGED_MASK           0xfffff
++#define TOE_GLOBAL_REG_SIZE           (0x78/sizeof(u32))
++#define TOE_DMA_REG_SIZE              (0xd0/sizeof(u32))
++#define TOE_GMAC_REG_SIZE             (0x30/sizeof(u32))
++#define GMAC0_RX_HANG_BIT             (1 << 0)
++#define GMAC0_TX_HANG_BIT             (1 << 1)
++#define GMAC1_RX_HANG_BIT             (1 << 2)
++#define GMAC1_TX_HANG_BIT             (1 << 3)
++
++int           gmac_in_do_workaround;
++#if 0
++int           debug_cnt, poll_max_cnt;
++#endif
++u32           gmac_workaround_cnt[4];
++u32           toe_global_reg[TOE_GLOBAL_REG_SIZE];
++u32           toe_dma_reg[GMAC_NUM][TOE_DMA_REG_SIZE];
++u32           toe_gmac_reg[GMAC_NUM][TOE_GMAC_REG_SIZE];
++u32           gmac_short_frame_workaround_cnt[2];
++
++static void sl351x_gmac_release_buffers(void);
++static void sl351x_gmac_release_swtx_q(void);
++static void sl351x_gmac_release_rx_q(void);
++#ifdef _TOEQ_CLASSQ_READY_
++static void sl351x_gmac_release_class_q(void);
++static void sl351x_gmac_release_toe_q(void);
++static void sl351x_gmac_release_intr_q(void);
++#endif
++static void sl351x_gmac_release_sw_free_q(void);
++static void sl351x_gmac_release_hw_free_q(void);
++#ifdef CONFIG_SL351x_NAT
++static int get_free_desc_cnt(unsigned long rwptr, int total);
++static void sl351x_gmac_release_hwtx_q(void);
++u32     sl351x_nat_workaround_cnt;
++#endif
++void sl351x_gmac_save_reg(void);
++void sl351x_gmac_restore_reg(void);
++
++
++/*----------------------------------------------------------------------
++*     sl351x_poll_gmac_hanged_status
++*     - Called by timer routine, period 10ms
++*     - If (state != 0 && state == prev state && )
++*----------------------------------------------------------------------*/
++void sl351x_poll_gmac_hanged_status(u32 data)
++{
++      int                     i;
++      u32                     state;
++      TOE_INFO_T              *toe;
++      GMAC_INFO_T             *tp;
++      u32                             hanged_state;
++      // int                          old_operation[GMAC_NUM];
++#ifdef CONFIG_SL351x_NAT
++      u32                             hw_free_cnt;
++#endif
++
++      if (gmac_in_do_workaround)
++              return;
++
++      gmac_in_do_workaround = 1;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      hanged_state = 0;
++
++#ifdef SL351x_TEST_WORKAROUND
++      if (toe->gmac[0].operation || toe->gmac[1].operation)
++      {
++              debug_cnt++;
++              if (debug_cnt == (30 * HZ))
++              {
++                      debug_cnt = 0;
++                      hanged_state = GMAC0_RX_HANG_BIT;
++                      goto do_workaround;
++              }
++      }
++#endif
++      if (toe->gmac[0].operation)
++              hanged_state |= GMAC0_RX_HANG_BIT | GMAC0_TX_HANG_BIT;
++
++#if (GMAC_NUM > 1)
++      if (toe->gmac[1].operation)
++              hanged_state |= GMAC1_RX_HANG_BIT | GMAC1_TX_HANG_BIT;
++#endif
++
++      for (i=0; i<GMAC_POLL_HANGED_NUM; i++)
++      {
++              if (hanged_state & GMAC0_RX_HANG_BIT)
++              {
++                      state = readl(TOE_GMAC0_BASE + GMAC_RX_STATE_OFFSET) & GMAC_RX_HANGED_MASK;
++                      if (state != GMAC_RX_HANGED_STATE)
++                              hanged_state &= ~GMAC0_RX_HANG_BIT;
++              }
++              if (hanged_state & GMAC0_TX_HANG_BIT)
++              {
++                      state = readl(TOE_GMAC0_BASE + GMAC_TX_STATE_OFFSET) & GMAC_TX_HANGED_MASK;
++                      if (state != GMAC_TX_HANGED_STATE)
++                              hanged_state &= ~GMAC0_TX_HANG_BIT;
++              }
++#if (GMAC_NUM > 1)
++              if (hanged_state & GMAC1_RX_HANG_BIT)
++              {
++                      state = readl(TOE_GMAC1_BASE + GMAC_RX_STATE_OFFSET) & GMAC_RX_HANGED_MASK;
++                      if (state != GMAC_RX_HANGED_STATE)
++                              hanged_state &= ~GMAC1_RX_HANG_BIT;
++              }
++              if (hanged_state & GMAC1_TX_HANG_BIT)
++              {
++                      state = readl(TOE_GMAC1_BASE + GMAC_TX_STATE_OFFSET) & GMAC_TX_HANGED_MASK;
++                      if (state != GMAC_TX_HANGED_STATE)
++                              hanged_state &= ~GMAC1_TX_HANG_BIT;
++              }
++#endif
++              if (!hanged_state)
++              {
++#if 0
++                      if (i < poll_max_cnt)
++                              poll_max_cnt = i;
++#endif
++                      if (toe->gmac[0].short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
++                      {
++                              gmac_short_frame_workaround_cnt[0]++;
++                              toe->gmac[0].short_frames_cnt = 0;
++                              goto do_workaround;
++                      }
++#if (GMAC_NUM > 1)
++                      if (toe->gmac[1].short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
++                      {
++                              gmac_short_frame_workaround_cnt[1]++;
++                              toe->gmac[1].short_frames_cnt = 0;
++                              goto do_workaround;
++                      }
++#endif
++
++#ifdef CONFIG_SL351x_NAT
++                      hw_free_cnt = readl(TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
++                      hw_free_cnt = get_free_desc_cnt(hw_free_cnt, TOE_HW_FREEQ_DESC_NUM);
++#ifdef NAT_WORKAROUND_BY_RESET_GMAC
++                      if (readl(TOE_GLOBAL_BASE + 0x4084) && (hw_free_cnt <= PAUSE_SET_HW_FREEQ))
++                      {
++                              sl351x_nat_workaround_cnt++;
++                              goto do_workaround;
++                      }
++#else
++                      if (readl(TOE_GLOBAL_BASE + 0x4084) && (hw_free_cnt <= (PAUSE_SET_HW_FREEQ*2)))
++                      {
++                              sl351x_nat_workaround_cnt++;
++                              sl351x_nat_workaround_handler();
++                      }
++#endif
++#endif
++                      gmac_in_do_workaround = 0;
++                      add_timer(&gmac_workround_timer_obj);
++                      return;
++              }
++      }
++
++do_workaround:
++
++      gmac_initialized = 0;
++      if (hanged_state)
++      {
++              if (hanged_state & GMAC0_RX_HANG_BIT) gmac_workaround_cnt[0]++;
++              if (hanged_state & GMAC0_TX_HANG_BIT) gmac_workaround_cnt[1]++;
++              if (hanged_state & GMAC1_RX_HANG_BIT) gmac_workaround_cnt[2]++;
++              if (hanged_state & GMAC1_TX_HANG_BIT) gmac_workaround_cnt[3]++;
++      }
++
++      for (i=0; i<GMAC_NUM; i++)
++      {
++              tp=(GMAC_INFO_T *)&toe->gmac[i];
++              // old_operation[i] = tp->operation;
++              if (tp->operation)
++              {
++                      netif_stop_queue(tp->dev);
++                      clear_bit(__LINK_STATE_START, &tp->dev->state);
++                      toe_gmac_disable_interrupt(tp->irq);
++                      toe_gmac_disable_tx_rx(tp->dev);
++                      toe_gmac_hw_stop(tp->dev);
++              }
++      }
++
++      // clear all status bits
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
++      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++
++#if 0
++      if ((hanged_state & GMAC0_RX_HANG_BIT) &&
++              (readl(TOE_GMAC0_DMA_BASE + 0xdc) & 0xf0))
++      {
++              struct sk_buff *skb;
++              unsigned int buf;
++              buf = readl(TOE_GMAC0_DMA_BASE + 0x68) & ~3;
++#ifdef CONFIG_SL351x_NAT
++              if (buf < toe->hwfq_buf_base_dma || buf > toe->hwfq_buf_end_dma)
++#endif
++              {
++                      skb = (struct sk_buff *)(REG32(buf - SKB_RESERVE_BYTES));
++                      printk("GMAC-0 free a loss SKB 0x%x\n", (u32)skb);
++                      dev_kfree_skb(skb);
++              }
++      }
++      if ((hanged_state & GMAC1_RX_HANG_BIT)  &&
++              (readl(TOE_GMAC1_DMA_BASE + 0xdc) & 0xf0))
++      {
++              struct sk_buff *skb;
++              unsigned int buf;
++              buf = readl(TOE_GMAC1_DMA_BASE + 0x68) & ~3;
++#ifdef CONFIG_SL351x_NAT
++              if (buf < toe->hwfq_buf_base_dma || buf > toe->hwfq_buf_end_dma)
++#endif
++              {
++                      skb = (struct sk_buff *)(REG32(buf - SKB_RESERVE_BYTES));
++                      printk("GMAC-1 free a loss SKB 0x%x\n", (u32)skb);
++                      dev_kfree_skb(skb);
++              }
++      }
++#endif
++
++      sl351x_gmac_release_buffers();
++      sl351x_gmac_save_reg();
++      toe_gmac_sw_reset();
++      sl351x_gmac_restore_reg();
++
++      if (toe->gmac[0].default_qhdr->word1.bits32)
++      {
++              // printk("===> toe->gmac[0].default_qhdr->word1 = 0x%x\n", toe->gmac[0].default_qhdr->word1);
++              sl351x_gmac_release_rx_q();
++              writel(0, &toe->gmac[0].default_qhdr->word1);
++      }
++      if (toe->gmac[1].default_qhdr->word1.bits32)
++      {
++              // printk("===> toe->gmac[1].default_qhdr->word1 = 0x%x\n", toe->gmac[1].default_qhdr->word1);
++              sl351x_gmac_release_rx_q();
++              writel(0, &toe->gmac[1].default_qhdr->word1);
++      }
++
++      gmac_initialized = 1;
++
++#ifdef        CONFIG_SL351x_NAT
++      writel(0, TOE_GLOBAL_BASE + 0x4084);
++#endif
++
++      for (i=0; i<GMAC_NUM; i++)
++      {
++              tp=(GMAC_INFO_T *)&toe->gmac[i];
++              if (tp->operation)
++              {
++                      toe_gmac_enable_interrupt(tp->irq);
++                      toe_gmac_hw_start(tp->dev);
++                      toe_gmac_enable_tx_rx(tp->dev);
++                      netif_wake_queue(tp->dev);
++                      set_bit(__LINK_STATE_START, &tp->dev->state);
++              }
++      }
++
++      gmac_in_do_workaround = 0;
++      add_timer(&gmac_workround_timer_obj);
++}
++
++/*----------------------------------------------------------------------
++*     get_free_desc_cnt
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static int get_free_desc_cnt(unsigned long rwptr, int total)
++{
++      unsigned short wptr = rwptr & 0xffff;
++      unsigned short rptr = rwptr >> 16;
++
++      if (wptr >= rptr)
++              return (total - wptr + rptr);
++      else
++              return (rptr - wptr);
++}
++#endif
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_buffers
++*----------------------------------------------------------------------*/
++static void sl351x_gmac_release_buffers(void)
++{
++      // Free buffers & Descriptors in all SW Tx Queues
++      sl351x_gmac_release_swtx_q();
++
++      // Free buffers in Default Rx Queues
++      sl351x_gmac_release_rx_q();
++
++#ifdef _TOEQ_CLASSQ_READY_
++      // Free buffers in Classification Queues
++      sl351x_gmac_release_class_q();
++
++      // Free buffers in TOE Queues
++      sl351x_gmac_release_toe_q();
++
++      // Free buffers in Interrupt Queues
++      sl351x_gmac_release_intr_q();
++#endif
++
++      // Free buffers & descriptors in SW free queue
++      sl351x_gmac_release_sw_free_q();
++
++      // Free buffers & descriptors in HW free queue
++      sl351x_gmac_release_hw_free_q();
++
++#ifdef CONFIG_SL351x_NAT
++      // Free buffers & descriptors in HW free queue
++      sl351x_gmac_release_hwtx_q();
++#endif
++}
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_swtx_q
++*----------------------------------------------------------------------*/
++static void sl351x_gmac_release_swtx_q(void)
++{
++      int                             i, j;
++      GMAC_TXDESC_T   *curr_desc;
++      unsigned int    desc_count;
++      TOE_INFO_T              *toe;
++      GMAC_INFO_T             *tp;
++      GMAC_SWTXQ_T    *swtxq;
++      DMA_RWPTR_T             rwptr;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      tp = (GMAC_INFO_T *)&toe->gmac[0];
++      for (i=0; i<GMAC_NUM; i++, tp++)
++      {
++              if (!tp->existed) continue;
++              swtxq = (GMAC_SWTXQ_T *)&tp->swtxq[0];
++              for (j=0; j<TOE_SW_TXQ_NUM; j++, swtxq++)
++              {
++                      for (;;)
++                      {
++                              rwptr.bits32 = readl(swtxq->rwptr_reg);
++                              if (rwptr.bits.rptr == swtxq->finished_idx)
++                              break;
++                              curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
++                              // if (curr_desc->word0.bits.status_tx_ok)
++                              {
++                                      desc_count = curr_desc->word0.bits.desc_count;
++                                      while (--desc_count)
++                                      {
++                                              curr_desc->word0.bits.status_tx_ok = 0;
++                                              swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
++                                              curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
++                                      }
++
++                                      curr_desc->word0.bits.status_tx_ok = 0;
++                                      if (swtxq->tx_skb[swtxq->finished_idx])
++                                      {
++                                              dev_kfree_skb_irq(swtxq->tx_skb[swtxq->finished_idx]);
++                                              swtxq->tx_skb[swtxq->finished_idx] = NULL;
++                                      }
++                              }
++                              swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
++                      }
++                      writel(0, swtxq->rwptr_reg);
++                      swtxq->finished_idx = 0;
++              }
++      }
++
++}
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_rx_q
++*----------------------------------------------------------------------*/
++static void sl351x_gmac_release_rx_q(void)
++{
++      int                             i;
++      TOE_INFO_T              *toe;
++      GMAC_INFO_T             *tp;
++      DMA_RWPTR_T             rwptr;
++      volatile GMAC_RXDESC_T  *curr_desc;
++      struct sk_buff                  *skb;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      tp = (GMAC_INFO_T *)&toe->gmac[0];
++      for (i=0; i<GMAC_NUM; i++, tp++)
++      {
++              if (!tp->existed) continue;
++              rwptr.bits32 = readl(&tp->default_qhdr->word1);
++              while (rwptr.bits.rptr != rwptr.bits.wptr)
++              {
++                      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
++                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
++                      dev_kfree_skb_irq(skb);
++                      rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
++                      SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
++                      rwptr.bits32 = readl(&tp->default_qhdr->word1);
++              }  // while
++              writel(0, &tp->default_qhdr->word1);
++              tp->rx_rwptr.bits32 = 0;
++      } // for
++
++}
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_class_q
++*----------------------------------------------------------------------*/
++#ifdef _TOEQ_CLASSQ_READY_
++static void sl351x_gmac_release_class_q(void)
++{
++      int                             i;
++      TOE_INFO_T              *toe;
++      CLASSQ_INFO_T   *classq;
++      DMA_RWPTR_T             rwptr;
++      volatile GMAC_RXDESC_T  *curr_desc;
++      struct sk_buff                  *skb;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      classq = (CLASSQ_INFO_T *)&toe->classq[0];
++      for (i=0; i<TOE_CLASS_QUEUE_NUM; i++, classq++)
++      {
++              rwptr.bits32 = readl(&classq->qhdr->word1);
++              while (rwptr.bits.rptr != rwptr.bits.wptr)
++              {
++                      curr_desc = (GMAC_RXDESC_T *)classq->desc_base + rwptr.bits.rptr;
++                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
++                      dev_kfree_skb_irq(skb);
++                      rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, classq->desc_num);
++                      SET_RPTR(&classq->qhdr->word1, rwptr.bits.rptr);
++                      rwptr.bits32 = readl(&classq->qhdr->word1);
++              }  // while
++              writel(0, &classq->qhdr->word1);
++              classq->rwptr.bits32 = 0;
++      } // for
++
++}
++#endif
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_toe_q
++*----------------------------------------------------------------------*/
++#ifdef _TOEQ_CLASSQ_READY_
++static void sl351x_gmac_release_toe_q(void)
++{
++      int                             i;
++      TOE_INFO_T              *toe;
++      TOEQ_INFO_T             *toeq_info;
++      TOE_QHDR_T              *toe_qhdr;
++      DMA_RWPTR_T             rwptr;
++      volatile GMAC_RXDESC_T  *curr_desc;
++      unsigned int    rptr, wptr;
++      GMAC_RXDESC_T   *toe_curr_desc;
++      struct sk_buff                  *skb;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      toe_qhdr = (TOE_QHDR_T *)TOE_TOE_QUE_HDR_BASE;
++      for (i=0; i<TOE_TOE_QUEUE_NUM; i++, toe_qhdr++)
++      {
++              toeq_info = (TOEQ_INFO_T *)&toe->toeq[i];
++              wptr = toe_qhdr->word1.bits.wptr;
++              rptr = toe_qhdr->word1.bits.rptr;
++              while (rptr != wptr)
++              {
++                      toe_curr_desc = (GMAC_RXDESC_T *)toeq_info->desc_base + rptr;
++                      skb = (struct sk_buff *)(REG32(__va(toe_curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
++                      dev_kfree_skb_irq(skb);
++                      rptr = RWPTR_ADVANCE_ONE(rptr, toeq_info->desc_num);
++                      SET_RPTR(&toe_qhdr->word1.bits32, rptr);
++                      wptr = toe_qhdr->word1.bits.wptr;
++                      rptr = toe_qhdr->word1.bits.rptr;
++              }
++              toe_qhdr->word1.bits32 = 0;
++              toeq_info->rwptr.bits32 = 0;
++      }
++}
++#endif
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_intr_q
++*----------------------------------------------------------------------*/
++#ifdef _TOEQ_CLASSQ_READY_
++static void sl351x_gmac_release_intr_q(void)
++{
++}
++#endif
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_sw_free_q
++*----------------------------------------------------------------------*/
++static void sl351x_gmac_release_sw_free_q(void)
++{
++      TOE_INFO_T                              *toe;
++      volatile DMA_RWPTR_T    fq_rwptr;
++      volatile GMAC_RXDESC_T  *fq_desc;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++
++      while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr)
++      {
++              struct sk_buff *skb;
++              if ((skb = dev_alloc_skb(SW_RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
++              {
++                      printk("%s::skb buffer allocation fail !\n",__func__); while(1);
++              }
++              // *(unsigned int *)(skb->data) = (unsigned int)skb;
++              REG32(skb->data) = (unsigned long)skb;
++              skb_reserve(skb, SKB_RESERVE_BYTES);
++
++              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
++              fq_desc = (volatile GMAC_RXDESC_T *)toe->swfq_desc_base + fq_rwptr.bits.wptr;
++              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
++              SET_WPTR(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
++              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++      }
++
++      toe->fq_rx_rwptr.bits.wptr = TOE_SW_FREEQ_DESC_NUM - 1;
++      toe->fq_rx_rwptr.bits.rptr = 0;
++      writel(toe->fq_rx_rwptr.bits32, TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++
++}
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_hw_free_q
++*----------------------------------------------------------------------*/
++static void sl351x_gmac_release_hw_free_q(void)
++{
++      DMA_RWPTR_T                     rwptr_reg;
++
++#ifdef CONFIG_SL351x_NAT
++      int                                     i;
++      TOE_INFO_T                      *toe;
++      GMAC_RXDESC_T           *desc_ptr;
++      unsigned int            buf_ptr;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++      desc_ptr = (GMAC_RXDESC_T *)toe->hwfq_desc_base;
++      buf_ptr = (unsigned int)toe->hwfq_buf_base_dma;
++      for (i=0; i<TOE_HW_FREEQ_DESC_NUM; i++)
++      {
++              desc_ptr->word0.bits.buffer_size = HW_RX_BUF_SIZE;
++              desc_ptr->word1.bits.sw_id = i;
++              desc_ptr->word2.buf_adr = (unsigned int)buf_ptr;
++              desc_ptr++;
++              buf_ptr += HW_RX_BUF_SIZE;
++      }
++#endif
++      rwptr_reg.bits.wptr = TOE_HW_FREEQ_DESC_NUM - 1;
++      rwptr_reg.bits.rptr = 0;
++      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
++}
++
++/*----------------------------------------------------------------------
++*     sl351x_gmac_release_hw_free_q
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static void sl351x_gmac_release_hwtx_q(void)
++{
++      int                             i;
++      unsigned int    rwptr_addr;
++
++      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              writel(0, rwptr_addr);
++              rwptr_addr+=4;
++      }
++      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              writel(0, rwptr_addr);
++              rwptr_addr+=4;
++      }
++}
++#endif
++
++/*----------------------------------------------------------------------
++*     sl351x_gmac_save_reg
++*----------------------------------------------------------------------*/
++void sl351x_gmac_save_reg(void)
++{
++      int     i;
++      volatile u32    *destp;
++      unsigned int    srce_addr;
++
++      srce_addr = TOE_GLOBAL_BASE;
++      destp = (volatile u32 *)toe_global_reg;
++      for (i=0; i<TOE_GLOBAL_REG_SIZE; i++, destp++, srce_addr+=4)
++              *destp = readl(srce_addr);
++
++      srce_addr = TOE_GMAC0_DMA_BASE;
++      destp = (volatile u32 *)&toe_dma_reg[0][0];
++      for (i=0; i<TOE_DMA_REG_SIZE; i++, destp++, srce_addr+=4)
++      {
++              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x38))
++                      srce_addr = (TOE_GMAC0_DMA_BASE+0x50);
++              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x58))
++                      srce_addr = (TOE_GMAC0_DMA_BASE+0x70);
++
++              *destp = readl(srce_addr);
++      }
++      srce_addr = TOE_GMAC1_DMA_BASE;
++      destp = (volatile u32 *)&toe_dma_reg[1][0];
++      for (i=0; i<TOE_DMA_REG_SIZE; i++, destp++, srce_addr+=4)
++      {
++              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x38))
++                      srce_addr = (TOE_GMAC0_DMA_BASE+0x50);
++              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x58))
++                      srce_addr = (TOE_GMAC0_DMA_BASE+0x70);
++
++              *destp = readl(srce_addr);
++      }
++
++      srce_addr = TOE_GMAC0_BASE;
++      destp = (volatile u32 *)&toe_gmac_reg[0][0];
++      for (i=0; i<TOE_GMAC_REG_SIZE; i++, destp++, srce_addr+=4)
++              *destp = readl(srce_addr);
++
++      srce_addr = TOE_GMAC1_BASE;
++      destp = (volatile u32 *)&toe_gmac_reg[1][0];
++      for (i=0; i<TOE_GMAC_REG_SIZE; i++, destp++, srce_addr+=4)
++              *destp = readl(srce_addr);
++}
++
++/*----------------------------------------------------------------------
++*     sl351x_gmac_restore_reg
++*----------------------------------------------------------------------*/
++void sl351x_gmac_restore_reg(void)
++{
++      int     i;
++      volatile u32    *srcep;
++      unsigned int    dest_addr;
++
++      srcep = (volatile u32 *)&toe_dma_reg[0][0];
++      dest_addr = TOE_GMAC0_DMA_BASE;
++      for (i=0; i<TOE_DMA_REG_SIZE; i++, dest_addr+=4, srcep++)
++      {
++              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x38))
++                      dest_addr = (TOE_GMAC0_DMA_BASE+0x50);
++              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x58))
++                      dest_addr = (TOE_GMAC0_DMA_BASE+0x70);
++
++              writel(*srcep, dest_addr);
++              // gmac_write_reg(dest_addr, 0, *srcep, 0xffffffff);
++      }
++      srcep = (volatile u32 *)&toe_dma_reg[1][0];
++      dest_addr = TOE_GMAC1_DMA_BASE;
++      for (i=0; i<TOE_DMA_REG_SIZE; i++, dest_addr+=4, srcep++)
++      {
++              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x38))
++                      dest_addr = (TOE_GMAC0_DMA_BASE+0x50);
++              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x58))
++                      dest_addr = (TOE_GMAC0_DMA_BASE+0x70);
++
++              writel(*srcep, dest_addr);
++              // gmac_write_reg(dest_addr, 0, *srcep, 0xffffffff);
++      }
++
++      srcep = (volatile u32 *)&toe_gmac_reg[0][0];
++      dest_addr = TOE_GMAC0_BASE;
++      for (i=0; i<TOE_GMAC_REG_SIZE; i++, dest_addr+=4, srcep++)
++              writel(*srcep, dest_addr);
++
++      srcep = (volatile u32 *)&toe_gmac_reg[1][0];
++      dest_addr = TOE_GMAC1_BASE;
++      for (i=0; i<TOE_GMAC_REG_SIZE; i++, dest_addr+=4, srcep++)
++              writel(*srcep, dest_addr);
++
++      srcep = (volatile u32 *)toe_global_reg;
++      dest_addr = TOE_GLOBAL_BASE;
++      for (i=0; i<TOE_GLOBAL_REG_SIZE; i++, dest_addr+=4, srcep++)
++              writel(*srcep, dest_addr);
++
++}
++
++#ifdef CONFIG_SL351x_NAT
++/*----------------------------------------------------------------------
++*     sl351x_nat_workaround_init
++*----------------------------------------------------------------------*/
++#define NAT_WORAROUND_DESC_POWER      (6)
++#define NAT_WORAROUND_DESC_NUM                (2 << NAT_WORAROUND_DESC_POWER)
++dma_addr_t sl351x_nat_workaround_desc_dma;
++void sl351x_nat_workaround_init(void)
++{
++      unsigned int    desc_buf;
++
++      desc_buf = (unsigned int)DMA_MALLOC((NAT_WORAROUND_DESC_NUM * sizeof(GMAC_RXDESC_T)),
++                                              (dma_addr_t *)&sl351x_nat_workaround_desc_dma) ;
++      memset((void *)desc_buf, 0, NAT_WORAROUND_DESC_NUM * sizeof(GMAC_RXDESC_T));
++
++      // DMA Queue Base & Size
++      writel((sl351x_nat_workaround_desc_dma & DMA_Q_BASE_MASK) | NAT_WORAROUND_DESC_POWER,
++                      TOE_GLOBAL_BASE + 0x4080);
++      writel(0, TOE_GLOBAL_BASE + 0x4084);
++}
++
++/*----------------------------------------------------------------------
++*     sl351x_nat_workaround_handler
++*----------------------------------------------------------------------*/
++#ifndef NAT_WORKAROUND_BY_RESET_GMAC
++static void sl351x_nat_workaround_handler(void)
++{
++      int                                     i;
++      DMA_RWPTR_T                     rwptr;
++      GMAC_RXDESC_T           *desc_ptr;
++      unsigned int            buf_ptr;
++      TOE_INFO_T                      *toe;
++      GMAC_CONFIG0_T          config0;
++      unsigned int            rwptr_addr;
++
++      toe = (TOE_INFO_T *)&toe_private_data;
++
++      // disable Rx of GMAC-0 & 1
++      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++      config0.bits.dis_rx = 1;
++      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++      config0.bits.dis_rx = 1;
++      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++
++      // wait GMAC-0 HW Tx finished
++      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              rwptr.bits32 = readl(rwptr_addr);
++              if (rwptr.bits.rptr != rwptr.bits.wptr)
++                      return; // wait the HW to send packets and release buffers
++              rwptr_addr+=4;
++      }
++      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              rwptr.bits32 = readl(rwptr_addr);
++              if (rwptr.bits.rptr != rwptr.bits.wptr)
++                      return; // wait the HW to send packets and release buffers
++              rwptr_addr+=4;
++      }
++
++      // printk("sl351x_nat_workaround_handler %d\n", sl351x_nat_workaround_cnt);
++      desc_ptr = (GMAC_RXDESC_T *)toe->hwfq_desc_base;
++      buf_ptr = (unsigned int)toe->hwfq_buf_base_dma;
++      for (i=0; i<TOE_HW_FREEQ_DESC_NUM; i++)
++      {
++              desc_ptr->word0.bits.buffer_size = HW_RX_BUF_SIZE;
++              desc_ptr->word1.bits.sw_id = i;
++              desc_ptr->word2.buf_adr = (unsigned int)buf_ptr;
++              desc_ptr++;
++              buf_ptr += HW_RX_BUF_SIZE;
++      }
++      rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
++      rwptr.bits.wptr = RWPTR_RECEDE_ONE(rwptr.bits.rptr, TOE_HW_FREEQ_DESC_NUM);
++      writel(rwptr.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
++      writel(0, TOE_GLOBAL_BASE + 0x4084);
++
++      // Enable Rx of GMAC-0 & 1
++      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
++      config0.bits.dis_rx = 0;
++      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
++      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
++      config0.bits.dis_rx = 0;
++      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
++}
++#endif
++#endif // CONFIG_SL351x_NAT
++
++#endif // SL351x_GMAC_WORKAROUND
++
++/* get the mac addresses from flash
++ *can't do this in module_init because mtd driver is initialized after ethernet
++ */
++static __init int sl351x_mac_address_init(void)
++{
++      GMAC_INFO_T             *tp;
++      struct sockaddr sock;
++      int i;
++
++      /* get mac address from FLASH */
++      gmac_get_mac_address();
++
++      for (i = 0; i < GMAC_NUM; i++) {
++              tp = (GMAC_INFO_T *)&toe_private_data.gmac[i];
++              memcpy(&sock.sa_data[0],&eth_mac[tp->port_id][0],6);
++              gmac_set_mac_address(tp->dev,(void *)&sock);
++      }
++
++        return 0;
++}
++late_initcall(sl351x_mac_address_init);
++
++
+--- /dev/null
++++ b/drivers/net/sl351x_hash.c
+@@ -0,0 +1,713 @@
++/**************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
++*--------------------------------------------------------------------------
++* Name                        : sl351x_hash.c
++* Description :
++*             Handle Storlink SL351x Hash Functions
++*
++* History
++*
++*     Date            Writer          Description
++*----------------------------------------------------------------------------
++*     03/13/2006      Gary Chen       Create and implement
++*
++****************************************************************************/
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/compiler.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/completion.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/it8712.h>
++#include <linux/mtd/kvctl.h>
++#include <linux/skbuff.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/list.h>
++#define        MIDWAY
++#define        SL_LEPUS
++
++#include <asm/arch/sl2312.h>
++#include <asm/arch/sl351x_gmac.h>
++#include <asm/arch/sl351x_hash_cfg.h>
++
++#ifndef RXTOE_DEBUG
++#define RXTOE_DEBUG
++#endif
++#undef RXTOE_DEBUG
++
++/*----------------------------------------------------------------------
++* Definition
++*----------------------------------------------------------------------*/
++#define       hash_printf                             printk
++
++#define HASH_TIMER_PERIOD             (30)    // seconds
++#define HASH_ILLEGAL_INDEX            0xffff
++
++/*----------------------------------------------------------------------
++* Variables
++*----------------------------------------------------------------------*/
++u32                                   hash_nat_owner_bits[HASH_TOTAL_ENTRIES/32];
++char                          hash_tables[HASH_TOTAL_ENTRIES][HASH_MAX_BYTES] __attribute__ ((aligned(16)));
++static struct timer_list hash_timer_obj;
++LIST_HEAD(hash_timeout_list);
++
++/*----------------------------------------------------------------------
++* Functions
++*----------------------------------------------------------------------*/
++void dm_long(u32 location, int length);
++static void hash_timer_func(u32 data);
++
++/*----------------------------------------------------------------------
++* hash_init
++*----------------------------------------------------------------------*/
++void sl351x_hash_init(void)
++{
++      int i;
++      volatile u32 *dp1, *dp2, dword;
++
++      dp1 = (volatile u32 *) TOE_V_BIT_BASE;
++      dp2 = (volatile u32 *) TOE_A_BIT_BASE;
++
++      for (i=0; i<HASH_TOTAL_ENTRIES/32; i++)
++      {
++              *dp1++ = 0;
++              dword = *dp2++; // read-clear
++      }
++      memset((void *)&hash_nat_owner_bits, 0, sizeof(hash_nat_owner_bits));
++      memset((void *)&hash_tables, 0, sizeof(hash_tables));
++
++      init_timer(&hash_timer_obj);
++      hash_timer_obj.expires = jiffies + (HASH_TIMER_PERIOD * HZ);
++      hash_timer_obj.data = (unsigned long)&hash_timer_obj;
++      hash_timer_obj.function = (void *)&hash_timer_func;
++      add_timer(&hash_timer_obj);
++
++#if (HASH_MAX_BYTES == 128)
++      writel((unsigned long)__pa(&hash_tables) | 3,   // 32 words
++                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
++#elif (HASH_MAX_BYTES == 64)
++      writel((unsigned long)__pa(&hash_tables) | 2,   // 16 words
++                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
++#else
++      #error Incorrect setting for HASH_MAX_BYTES
++#endif
++
++}
++/*----------------------------------------------------------------------
++* hash_add_entry
++*----------------------------------------------------------------------*/
++int hash_add_entry(HASH_ENTRY_T *entry)
++{
++      int     rc;
++      u32     key[HASH_MAX_DWORDS];
++      rc = hash_build_keys((u32 *)&key, entry);
++      if (rc < 0)
++              return -1;
++      hash_write_entry(entry, (unsigned char*) &key[0]);
++//    hash_set_valid_flag(entry->index, 1);
++//    printk("Dump hash key!\n");
++//    dump_hash_key(entry);
++      return entry->index;
++}
++
++/*----------------------------------------------------------------------
++* hash_set_valid_flag
++*----------------------------------------------------------------------*/
++void hash_set_valid_flag(int index, int valid)
++{
++      register u32 reg32;
++
++      reg32 = TOE_V_BIT_BASE + (index/32) * 4;
++
++      if (valid)
++      {
++              writel(readl(reg32) | (1 << (index%32)), reg32);
++      }
++      else
++      {
++              writel(readl(reg32) & ~(1 << (index%32)), reg32);
++      }
++}
++
++/*----------------------------------------------------------------------
++* hash_set_nat_owner_flag
++*----------------------------------------------------------------------*/
++void hash_set_nat_owner_flag(int index, int valid)
++{
++      if (valid)
++      {
++              hash_nat_owner_bits[index/32] |= (1 << (index % 32));
++      }
++      else
++      {
++              hash_nat_owner_bits[index/32] &= ~(1 << (index % 32));
++      }
++}
++
++
++/*----------------------------------------------------------------------
++* hash_build_keys
++*----------------------------------------------------------------------*/
++int hash_build_keys(u32 *destp, HASH_ENTRY_T *entry)
++{
++      u32     data;
++      unsigned char   *cp;
++      int                             i, j;
++      unsigned short  index;
++      int                     total;
++
++      memset((void *)destp, 0, HASH_MAX_BYTES);
++      cp = (unsigned char *)destp;
++
++      if (entry->key_present.port || entry->key_present.Ethertype)
++      {
++              HASH_PUSH_WORD(cp, entry->key.Ethertype);               // word 0
++              HASH_PUSH_BYTE(cp, entry->key.port);                    // Byte 2
++              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
++      }
++      else
++      {
++              HASH_PUSH_DWORD(cp, 0);
++      }
++
++      if (entry->key_present.da || entry->key_present.sa)
++      {
++              unsigned char mac[4];
++              if (entry->key_present.da)
++              {
++                      for (i=0; i<4; i++)
++                              HASH_PUSH_BYTE(cp, entry->key.da[i]);
++              }
++              mac[0] = (entry->key_present.da) ? entry->key.da[4] : 0;
++              mac[1] = (entry->key_present.da) ? entry->key.da[5] : 0;
++              mac[2] = (entry->key_present.sa) ? entry->key.sa[0] : 0;
++              mac[3] = (entry->key_present.sa) ? entry->key.sa[1] : 0;
++              data = mac[0] + (mac[1]<<8) + (mac[2]<<16) + (mac[3]<<24);
++              HASH_PUSH_DWORD(cp, data);
++              if (entry->key_present.sa)
++              {
++                      for (i=2; i<6; i++)
++                              HASH_PUSH_BYTE(cp, entry->key.sa[i]);
++              }
++      }
++
++      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
++      {
++              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
++              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
++      }
++      if (entry->key_present.ipv4_hdrlen || entry->key_present.ip_tos || entry->key_present.ip_protocol)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.ip_protocol);             // Byte 0
++              HASH_PUSH_BYTE(cp, entry->key.ip_tos);                  // Byte 1
++              HASH_PUSH_BYTE(cp, entry->key.ipv4_hdrlen);             // Byte 2
++              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
++      }
++
++      if (entry->key_present.ipv6_flow_label)
++      {
++              HASH_PUSH_DWORD(cp, entry->key.ipv6_flow_label);        // low word
++      }
++      if (entry->key_present.sip)
++      {
++              // input (entry->key.sip[i]) is network-oriented
++              // output (hash key) is host-oriented
++              for (i=3; i>=0; i--)
++                      HASH_PUSH_BYTE(cp, entry->key.sip[i]);
++              if (entry->key.ipv6)
++              {
++                      for (i=4; i<16; i+=4)
++                      {
++                              for (j=i+3; j>=i; j--)
++                                      HASH_PUSH_BYTE(cp, entry->key.sip[j]);
++                      }
++              }
++      }
++      if (entry->key_present.dip)
++      {
++              // input (entry->key.sip[i]) is network-oriented
++              // output (hash key) is host-oriented
++              for (i=3; i>=0; i--)
++                      HASH_PUSH_BYTE(cp, entry->key.dip[i]);
++              if (entry->key.ipv6)
++              {
++                      for (i=4; i<16; i+=4)
++                      {
++                              for (j=i+3; j>=i; j--)
++                                      HASH_PUSH_BYTE(cp, entry->key.dip[j]);
++                      }
++              }
++      }
++
++      if (entry->key_present.l4_bytes_0_3)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
++      }
++      if (entry->key_present.l4_bytes_4_7)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[4]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[5]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[6]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[7]);
++      }
++      if (entry->key_present.l4_bytes_8_11)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[8]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[9]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[10]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[11]);
++      }
++      if (entry->key_present.l4_bytes_12_15)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[12]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[13]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[14]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[15]);
++      }
++      if (entry->key_present.l4_bytes_16_19)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[16]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[17]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[18]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[19]);
++      }
++      if (entry->key_present.l4_bytes_20_23)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[20]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[21]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[22]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[23]);
++      }
++      if (entry->key_present.l7_bytes_0_3)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[0]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[1]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[2]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[3]);
++      }
++      if (entry->key_present.l7_bytes_4_7)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[4]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[5]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[6]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[7]);
++      }
++      if (entry->key_present.l7_bytes_8_11)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[8]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[9]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[10]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[11]);
++      }
++      if (entry->key_present.l7_bytes_12_15)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[12]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[13]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[14]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[15]);
++      }
++      if (entry->key_present.l7_bytes_16_19)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[16]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[17]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[18]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[19]);
++      }
++      if (entry->key_present.l7_bytes_20_23)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[20]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[21]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[22]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[23]);
++      }
++
++      // get hash index
++      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
++
++      if (total > HASH_MAX_KEY_DWORD)
++      {
++              //hash_printf("Total key words (%d) is too large (> %d)!\n",
++              //                              total, HASH_MAX_KEY_DWORD);
++              return -1;
++      }
++
++      if (entry->key_present.port || entry->key_present.Ethertype)
++              index = hash_gen_crc16((unsigned char *)destp, total * 4);
++      else
++      {
++              if (total == 1)
++              {
++                      hash_printf("No key is assigned!\n");
++                      return -1;
++              }
++
++              index = hash_gen_crc16((unsigned char *)(destp+1), (total-1) * 4);
++      }
++
++      entry->index = index & HASH_BITS_MASK;
++
++      //hash_printf("Total key words = %d, Hash Index= %d\n",
++      //                              total, entry->index);
++
++      cp = (unsigned char *)destp;
++      cp+=3;
++      HASH_PUSH_BYTE(cp, entry->rule);        // rule
++
++      entry->total_dwords = total;
++
++      return total;
++}
++
++/*----------------------------------------------------------------------
++* hash_build_nat_keys
++*----------------------------------------------------------------------*/
++void hash_build_nat_keys(u32 *destp, HASH_ENTRY_T *entry)
++{
++      unsigned char   *cp;
++      int                             i;
++      unsigned short  index;
++      int                     total;
++
++      memset((void *)destp, 0, HASH_MAX_BYTES);
++
++      cp = (unsigned char *)destp + 2;
++      HASH_PUSH_BYTE(cp, entry->key.port);
++      cp++;
++
++      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
++      {
++              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
++              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
++      }
++
++      HASH_PUSH_BYTE(cp, entry->key.ip_protocol);
++      cp+=3;
++
++      // input (entry->key.sip[i]) is network-oriented
++      // output (hash key) is host-oriented
++      for (i=3; i>=0; i--)
++              HASH_PUSH_BYTE(cp, entry->key.sip[i]);
++
++      // input (entry->key.sip[i]) is network-oriented
++      // output (hash key) is host-oriented
++      for (i=3; i>=0; i--)
++              HASH_PUSH_BYTE(cp, entry->key.dip[i]);
++
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
++
++      // get hash index
++      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
++
++      index = hash_gen_crc16((unsigned char *)destp, total * 4);
++      entry->index = index & ((1 << HASH_BITS) - 1);
++
++      cp = (unsigned char *)destp;
++      cp+=3;
++      HASH_PUSH_BYTE(cp, entry->rule);        // rule
++
++      entry->total_dwords = total;
++}
++
++/*----------------------------------------------------------------------
++* hash_build_toe_keys
++*----------------------------------------------------------------------*/
++int hash_build_toe_keys(u32 *destp, HASH_ENTRY_T *entry)
++{
++      unsigned long   data;
++      unsigned char   *cp;
++      unsigned short  index;
++      int     i;
++      int total;
++      //printk("%s\n", __func__);
++      memset((void*)destp, 0, HASH_MAX_BYTES);
++      cp = (unsigned char*)destp;
++
++      if(entry->key_present.port || entry->key_present.Ethertype) {
++              data = (entry->key.port << 16) + entry->key.Ethertype;
++              HASH_PUSH_DWORD(cp, data);
++      } else
++              HASH_PUSH_DWORD(cp, 0);
++
++      if (entry->key_present.da || entry->key_present.sa) {
++              unsigned char   mac[4];
++              if (entry->key_present.da) {
++                      data = (entry->key.da[0]) + (entry->key.da[1] << 8) +
++                                 (entry->key.da[2] << 16) + (entry->key.da[3] <<24);
++                      HASH_PUSH_DWORD(cp, data);
++              }
++              mac[0] = (entry->key_present.da) ? entry->key.da[4] : 0;
++              mac[1] = (entry->key_present.da) ? entry->key.da[5] : 0;
++              mac[2] = (entry->key_present.sa) ? entry->key.sa[0] : 0;
++              mac[3] = (entry->key_present.sa) ? entry->key.sa[1] : 0;
++              data = mac[0] + (mac[1]<<8) + (mac[2]<<16) + (mac[3]<<24);
++              HASH_PUSH_DWORD(cp, data);
++              if (entry->key_present.sa) {
++                      data = (entry->key.sa[2]) + (entry->key.sa[3] << 8) +
++                                 (entry->key.sa[4] << 16) + (entry->key.sa[5] <<24);
++                      HASH_PUSH_DWORD(cp, data);
++              }
++      }
++
++      if (entry->key_present.ip_protocol) {
++              unsigned char ip_protocol;
++              ip_protocol = entry->key.ip_protocol;
++              data = ip_protocol;
++              HASH_PUSH_DWORD(cp, data);
++      }
++
++      if (entry->key_present.ipv6_flow_label) {
++              unsigned long flow_label;
++              flow_label  = entry->key.ipv6_flow_label;
++              data = flow_label & 0xfffff;
++              HASH_PUSH_DWORD(cp, data);
++      }
++
++      if (entry->key_present.sip)     {
++              {
++                      data = IPIV(entry->key.sip[0], entry->key.sip[1],
++                                      entry->key.sip[2], entry->key.sip[3]);
++                      HASH_PUSH_DWORD(cp, data);
++                      if (entry->key.ipv6) {
++                              for (i=4; i<16; i+=4) {
++                                      data = IPIV(entry->key.sip[i+0], entry->key.sip[i+1],
++                                                      entry->key.sip[i+2], entry->key.sip[i+3]);
++                                      HASH_PUSH_DWORD(cp, data);
++                              }
++                      }
++              }
++      }
++
++      if (entry->key_present.dip)     {
++              {
++                      data = IPIV(entry->key.dip[0], entry->key.dip[1],
++                                              entry->key.dip[2], entry->key.dip[3]);
++                      HASH_PUSH_DWORD(cp, data);
++                      if (entry->key.ipv6) {
++                              for (i=4; i<16; i+=4) {
++                                      data = IPIV(entry->key.dip[i+0], entry->key.dip[i+1],
++                                                              entry->key.dip[i+2], entry->key.dip[i+3]);
++                                      HASH_PUSH_DWORD(cp, data);
++                              }
++                      }
++              }
++      }
++      if (entry->key_present.l4_bytes_0_3)
++      {
++              unsigned char *datap;
++              datap = &entry->key.l4_bytes[0];
++              data =  datap[0] +      (datap[1] << 8) + (datap[2] << 16) + (datap[3] << 24);
++              HASH_PUSH_DWORD(cp, data);
++      }
++      if (entry->key_present.l7_bytes_0_3)
++      {
++              unsigned char *datap;
++              datap = &entry->key.l7_bytes[0];
++              data =  datap[0] +      (datap[1] << 8) + (datap[2] << 16) + (datap[3] << 24);
++              HASH_PUSH_DWORD(cp, data);
++      }
++      if (entry->key_present.l7_bytes_4_7)
++      {
++              unsigned char *datap;
++              datap = &entry->key.l7_bytes[4];
++              data =  datap[0] +      (datap[1] << 8) + (datap[2] << 16) + (datap[3] << 24);
++              HASH_PUSH_DWORD(cp, data);
++      }
++
++      total = (unsigned long)((unsigned long)cp - (unsigned long)destp) / (sizeof(u32));
++      if (total > HASH_MAX_KEY_DWORD) {
++              //printf("Total key words (%d) is too large (> %d)!\n",
++              //              total, HASH_MAX_KEY_DWORD);
++              return -1;
++      }
++      index = hash_gen_crc16((unsigned char*)(destp + 1), (total-1)*4);
++      entry->index = index & ((1 << HASH_BITS)-1);
++
++      cp = (unsigned char*) destp;
++      cp += 3;
++      HASH_PUSH_BYTE(cp, entry->rule);
++      entry->total_dwords = total;
++      return total;
++}
++
++/*----------------------------------------------------------------------
++* hash_add_toe_entry
++*----------------------------------------------------------------------*/
++int hash_add_toe_entry(HASH_ENTRY_T *entry)
++{
++      int     rc;
++      u32     key[HASH_MAX_DWORDS];
++
++      rc = hash_build_toe_keys((u32 *)&key, entry);
++      if (rc < 0)
++              return -1;
++      hash_write_entry(entry, (unsigned char*) &key[0]);
++      //hash_dump_entry(entry->index);
++//    hash_set_valid_flag(entry->index, 1);
++//    printk("Dump hash key!\n");
++//    dump_hash_key(entry);
++      return entry->index;
++}
++
++
++/*----------------------------------------------------------------------
++* hash_write_entry
++*----------------------------------------------------------------------*/
++int hash_write_entry(HASH_ENTRY_T *entry, unsigned char *key)
++{
++      int             i;
++      u32             *srcep, *destp, *destp2;
++
++      srcep = (u32 *)key;
++      destp2 = destp = (u32 *)&hash_tables[entry->index][0];
++
++      for (i=0; i<(entry->total_dwords); i++, srcep++, destp++)
++              *destp = *srcep;
++
++      srcep = (u32 *)&entry->action;
++      *destp++ = *srcep;
++
++      srcep = (u32 *)&entry->param;
++      for (i=0; i<(sizeof(ENTRY_PARAM_T)/sizeof(*destp)); i++, srcep++, destp++)
++              *destp = *srcep;
++
++      memset(destp, 0, (HASH_MAX_DWORDS-entry->total_dwords-HASH_ACTION_DWORDS) * sizeof(u32));
++
++      consistent_sync(destp2, (entry->total_dwords+HASH_ACTION_DWORDS) * 4, PCI_DMA_TODEVICE);
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++* hash_timer_func
++*----------------------------------------------------------------------*/
++static void hash_timer_func(u32 data)
++{
++      int                                     i, j, idx;
++      volatile u32            *own_p, *valid_p;
++      u32                                     own_bits, a_bits;
++      int                                     period = HASH_TIMER_PERIOD;
++
++      valid_p = (volatile u32 *)TOE_V_BIT_BASE;
++      own_p = (volatile u32 *)hash_nat_owner_bits;
++      for (i=0, idx=0; i<(HASH_TOTAL_ENTRIES/32); i++, own_p++, valid_p++, idx+=32)
++      {
++              a_bits = readl(TOE_A_BIT_BASE + (i*4));
++              own_bits = *own_p;
++              if (own_bits)
++              {
++                      for (j=0; own_bits && j<32; j++)
++                      {
++                              if (own_bits & 1)
++                              {
++                                      short *counter_p, *interval_p;
++                                      NAT_HASH_ENTRY_T        *nat_entry;
++                                      GRE_HASH_ENTRY_T        *gre_entry;
++                                      nat_entry = (NAT_HASH_ENTRY_T *)hash_get_entry(idx+j);
++                                      gre_entry = (GRE_HASH_ENTRY_T *)nat_entry;
++                                      if (nat_entry->key.ip_protocol == IPPROTO_GRE)
++                                      {
++                                              counter_p = (short *)&gre_entry->tmo.counter;
++                                              interval_p = (short *)&gre_entry->tmo.interval;
++                                      }
++                                      else
++                                      {
++                                              counter_p = (short *)&nat_entry->tmo.counter;
++                                              interval_p = (short *)&nat_entry->tmo.interval;
++                                      }
++                                      if (a_bits & 1)
++                                      {
++                                              *counter_p = *interval_p;
++                                      }
++                                      else
++                                      {
++                                              *counter_p -= HASH_TIMER_PERIOD;
++                                              if (*counter_p <= 0)
++                                              {
++                                                      *valid_p &= ~(1 << j);          // invalidate it
++                                                      *own_p &= ~(1 << j);            // release ownership for NAT
++                                                      *counter_p = 0;
++                                                      // hash_printf("%lu %s: Clear hash index: %d\n", jiffies/HZ, __func__, i*32+j);
++                                              }
++                                              else if (period > *counter_p)
++                                              {
++                                                      period = *counter_p;
++                                              }
++                                      }
++                              }
++                              a_bits >>= 1;
++                              own_bits >>=1;
++                      }
++              }
++      }
++
++      hash_timer_obj.expires = jiffies + (period * HZ);
++      add_timer((struct timer_list *)data);
++}
++
++/*----------------------------------------------------------------------
++* dm_long
++*----------------------------------------------------------------------*/
++void dm_long(u32 location, int length)
++{
++      u32             *start_p, *curr_p, *end_p;
++      u32             *datap, data;
++      int             i;
++
++      //if (length > 1024)
++      //      length = 1024;
++
++      start_p = (u32 *)location;
++      end_p = (u32 *)location + length;
++      curr_p = (u32 *)((u32)location & 0xfffffff0);
++      datap = (u32 *)location;
++      while (curr_p < end_p)
++      {
++              hash_printf("0x%08x: ",(u32)curr_p & 0xfffffff0);
++              for (i=0; i<4; i++)
++              {
++                      if (curr_p < start_p || curr_p >= end_p)
++               hash_printf("         ");
++                      else
++                      {
++                              data = *datap;
++                              hash_printf("%08X ", data);
++                      }
++                      if (i==1)
++              hash_printf("- ");
++
++                      curr_p++;
++                      datap++;
++              }
++        hash_printf("\n");
++      }
++}
++
++/*----------------------------------------------------------------------
++* hash_dump_entry
++*----------------------------------------------------------------------*/
++void hash_dump_entry(int index)
++{
++      hash_printf("Hash Index %d:\n", index);
++      dm_long((u32)&hash_tables[index][0], HASH_MAX_DWORDS);
++}
++
++
+--- /dev/null
++++ b/drivers/net/sl351x_nat.c
+@@ -0,0 +1,1736 @@
++/****************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
++*----------------------------------------------------------------------------
++* Name                        : sl351x_nat.c
++* Description :
++*             Handle Storlink SL351x NAT Functions
++*
++*
++* Packet Flow:
++*
++*            (xmit)+<--- SW NAT -->+(xmit)
++*                  |       ^^      |
++*                  |       ||      |
++*                  |       ||      |
++*   Client <---> GMAC-x  HW-NAT  GMAC-y  <---> Server
++*
++*
++* History
++*
++*     Date            Writer          Description
++*----------------------------------------------------------------------------
++*     03/13/2006      Gary Chen       Create and implement
++*
++*
++****************************************************************************/
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/compiler.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/completion.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/it8712.h>
++#include <linux/mtd/kvctl.h>
++#include <linux/skbuff.h>
++#include <linux/if_ether.h>
++#include <linux/if_pppox.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <linux/ppp_defs.h>
++
++#define        MIDWAY
++#define        SL_LEPUS
++
++#include <asm/arch/sl2312.h>
++#include <asm/arch/sl351x_gmac.h>
++#include <asm/arch/sl351x_hash_cfg.h>
++#include <asm/arch/sl351x_nat_cfg.h>
++#ifdef CONFIG_NETFILTER
++// #include <linux/netfilter/nf_conntrack.h>
++#include <linux/netfilter/nf_conntrack_tcp.h>
++#endif
++
++//#define NAT_DEBUG_MSG               1
++#define _NOT_CHECK_SIP_DIP
++//#define     SL351x_NAT_TEST_BY_SMARTBITS            1       // Initialize 32 hash entries and test by SmartBITS
++#define VITESSE_G5SWITCH      1
++
++#ifdef CONFIG_SL351x_NAT
++
++/*----------------------------------------------------------------------
++* Definition
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL3516_ASIC
++#define CONFIG_SL351x_NAT_TCP_UDP
++#define CONFIG_SL351x_NAT_GRE
++#define CONFIG_SL351x_TCP_UDP_RULE_ID 0
++#define CONFIG_SL351x_GRE_RULE_ID             1
++#else
++#define CONFIG_SL351x_NAT_TCP_UDP
++//#define CONFIG_SL351x_NAT_GRE
++#define CONFIG_SL351x_TCP_UDP_RULE_ID 0
++#define CONFIG_SL351x_GRE_RULE_ID             0
++#endif
++
++#define       nat_printf                                      printk
++#define NAT_FTP_CTRL_PORT                     (21)    // TCP
++#define NAT_H323_PORT                         (1720)  // TCP
++#define NAT_T120_PORT                         (1503)  // TCP
++#define NAT_PPTP_PORT                         (1723)  // TCP
++#define NAT_TFTP_PORT                                 (69)    // UDP
++#define NAT_DNS_PORT                          (53)    // UDP
++#define NAT_NTP_PORT                          (123)   // UDP
++#define NAT_RAS_PORT                          (1719)  // UDP
++#define NAT_BOOTP67_PORT                      (67)    // UDP
++#define NAT_BOOTP68_PORT                      (68)    // UDP
++
++#define NAT_TCP_PORT_MAX                      64
++#define NAT_UDP_PORT_MAX                      64
++
++#define GRE_PROTOCOL                          (0x880b)
++#define GRE_PROTOCOL_SWAP                     __constant_htons(0x880b)
++
++#ifdef VITESSE_G5SWITCH
++extern int Giga_switch;
++#endif
++
++typedef struct
++{
++      u16             flags_ver;
++      u16             protocol;
++      u16             payload_length;
++      u16             call_id;
++      u32             seq;
++      u32             ack;
++} GRE_PKTHDR_T;
++
++/*----------------------------------------------------------------------
++* NAT Configuration
++*
++* Note: Any change for network setting, the NAT configuration should
++*       be changed also.
++*     cfg->lan_port   0 if GMAC-0, 1: if GMAC-1
++*     cfg->wan_port   0 if GMAC-0, 1: if GMAC-1
++*     cfg->lan_ipaddr, cfg->lan_gateway, cfg->lan_netmask
++*     cfg->wan_ipaddr, cfg->wan_gateway, cfg->wan_netmask
++*
++*----------------------------------------------------------------------*/
++NAT_CFG_T             nat_cfg;
++static int            nat_initialized;
++u32                   nat_collision;
++
++#ifdef CONFIG_SL351x_NAT_TCP_UDP
++static u16            fixed_tcp_port_list[]={NAT_FTP_CTRL_PORT,
++                                                                              NAT_H323_PORT,
++                                                                              // NAT_T120_PORT,
++                                                                              NAT_PPTP_PORT,
++                                                                              0};
++static u16            fixed_udp_port_list[]={NAT_DNS_PORT,
++                                                                              NAT_NTP_PORT,
++                                                                              NAT_TFTP_PORT,
++                                                                              NAT_RAS_PORT,
++                                                                              NAT_BOOTP67_PORT,
++                                                                              NAT_BOOTP68_PORT,
++                                                                              0};
++#endif
++
++// #define _HAVE_DYNAMIC_PORT_LIST
++#ifdef _HAVE_DYNAMIC_PORT_LIST
++static u16            dynamic_tcp_port_list[NAT_TCP_PORT_MAX+1];
++static u16            dynamic_udp_port_list[NAT_UDP_PORT_MAX+1]};
++#endif
++
++/*----------------------------------------------------------------------
++* Functions
++*----------------------------------------------------------------------*/
++int sl351x_nat_tcp_udp_output(struct sk_buff *skb, int port);
++int sl351x_nat_udp_output(struct sk_buff *skb, int port);
++int sl351x_nat_gre_output(struct sk_buff *skb, int port);
++
++extern int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2);
++extern void hash_dump_entry(int index);
++extern void mac_get_hw_tx_weight(struct net_device *dev, char *weight);
++extern void mac_set_hw_tx_weight(struct net_device *dev, char *weight);
++
++#ifdef SL351x_NAT_TEST_BY_SMARTBITS
++static void nat_init_test_entry(void);
++#endif
++/*----------------------------------------------------------------------
++* sl351x_nat_init
++*     initialize a NAT matching rule
++*     Called by SL351x Driver
++*             key             : port, protocol, Sip, Dip, Sport, Dport
++*             Action  : Srce Q: HW Free Queue,
++*                               Dest Q: HW TxQ
++*                               Change DA
++*                               Change SA
++*                 Change Sip or Dip
++*                       Change Sport or Dport
++*----------------------------------------------------------------------*/
++void sl351x_nat_init(void)
++{
++      int                                     rc;
++      GMAC_MRxCR0_T           mrxcr0;
++      GMAC_MRxCR1_T           mrxcr1;
++      GMAC_MRxCR2_T           mrxcr2;
++      NAT_CFG_T                       *cfg;
++
++      if (nat_initialized)
++              return;
++
++      nat_initialized = 1;
++
++      if ((sizeof(NAT_HASH_ENTRY_T) > HASH_MAX_BYTES) ||
++              (sizeof(GRE_HASH_ENTRY_T) > HASH_MAX_BYTES))
++      {
++              nat_printf("NAT_HASH_ENTRY_T structure Size is too larger!\n");
++              while(1);
++      }
++
++      cfg = (NAT_CFG_T *)&nat_cfg;
++      memset((void *)cfg, 0, sizeof(NAT_CFG_T));
++#ifdef _HAVE_DYNAMIC_PORT_LIST
++      memset((void *)dynamic_tcp_port_list, 0, sizeof(dynamic_tcp_port_list));
++      memset((void *)dynamic_udp_port_list, 0, sizeof(dynamic_udp_port_list));
++#endif
++
++#ifdef VITESSE_G5SWITCH
++      if(Giga_switch)
++      {
++              cfg->enabled                    = 1;
++              cfg->tcp_udp_rule_id    = CONFIG_SL351x_TCP_UDP_RULE_ID;
++              cfg->gre_rule_id                = CONFIG_SL351x_GRE_RULE_ID;
++              cfg->lan_port                   = 1;
++              cfg->wan_port                   = 0;
++              cfg->default_hw_txq     = 3;
++              cfg->tcp_tmo_interval   = 60;
++              cfg->udp_tmo_interval   = 180;
++              cfg->gre_tmo_interval   = 60;
++      }
++      else
++      {
++              cfg->enabled                    = 1;
++              cfg->tcp_udp_rule_id    = CONFIG_SL351x_TCP_UDP_RULE_ID;
++              cfg->gre_rule_id                = CONFIG_SL351x_GRE_RULE_ID;
++              cfg->lan_port                   = 0;
++              cfg->wan_port                   = 1;
++              cfg->default_hw_txq     = 3;
++              cfg->tcp_tmo_interval   = 60;
++              cfg->udp_tmo_interval   = 180;
++              cfg->gre_tmo_interval   = 60;
++
++      }
++#endif
++
++#if 1 //      debug purpose
++      cfg->ipcfg[0].total                             = 1;
++      cfg->ipcfg[0].entry[0].ipaddr   = IPIV(192,168,2,92);
++      cfg->ipcfg[0].entry[0].netmask  = IPIV(255,255,255,0);
++      cfg->ipcfg[1].total                             = 1;
++      cfg->ipcfg[1].entry[0].ipaddr   = IPIV(192,168,1,200);
++      cfg->ipcfg[1].entry[0].netmask  = IPIV(255,255,255,0);
++#endif
++
++#if 1
++      cfg->xport.total = 0;
++#else
++      cfg->xport.total = 4;
++
++      // H.323/H.225 Call setup
++      cfg->xport.entry[0].protocol = IPPROTO_TCP;
++      cfg->xport.entry[0].sport_start = 0;
++      cfg->xport.entry[0].sport_end = 0;
++      cfg->xport.entry[0].dport_start = 1720;
++      cfg->xport.entry[0].dport_end = 1720;
++      cfg->xport.entry[1].protocol = IPPROTO_TCP;
++      cfg->xport.entry[1].sport_start = 1720;
++      cfg->xport.entry[1].sport_end = 1720;
++      cfg->xport.entry[1].dport_start = 0;
++      cfg->xport.entry[1].dport_end = 0;
++
++      // RAS Setup
++      cfg->xport.entry[2].protocol = IPPROTO_UDP;
++      cfg->xport.entry[2].sport_start = 0;
++      cfg->xport.entry[2].sport_end = 0;
++      cfg->xport.entry[2].dport_start = 1719;
++      cfg->xport.entry[2].dport_end = 1719;
++      cfg->xport.entry[3].protocol = IPPROTO_UDP;
++      cfg->xport.entry[3].sport_start = 1719;
++      cfg->xport.entry[3].sport_end = 1719;
++      cfg->xport.entry[3].dport_start = 0;
++      cfg->xport.entry[3].dport_end = 0;
++#endif
++
++#ifdef CONFIG_SL351x_NAT_TCP_UDP
++      mrxcr0.bits32 = 0;
++      mrxcr1.bits32 = 0;
++      mrxcr2.bits32 = 0;
++      mrxcr0.bits.port = 1;
++      mrxcr0.bits.l3 = 1;
++      mrxcr0.bits.l4 = 1;
++      mrxcr1.bits.sip = 1;
++      mrxcr1.bits.dip = 1;
++      mrxcr1.bits.l4_byte0_15 = 0x0f; // Byte 0-3
++      mrxcr0.bits.sprx = 3;
++
++      rc = mac_set_rule_reg(cfg->lan_port, cfg->tcp_udp_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
++      if (rc < 0)
++      {
++              nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->lan_port, cfg->tcp_udp_rule_id);
++      }
++
++      if (cfg->lan_port != cfg->wan_port)
++      {
++              rc = mac_set_rule_reg(cfg->wan_port, cfg->tcp_udp_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
++              if (rc < 0)
++              {
++                      nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->wan_port, cfg->tcp_udp_rule_id);
++              }
++      }
++#endif
++
++#ifdef CONFIG_SL351x_NAT_GRE
++      mrxcr0.bits32 = 0;
++      mrxcr1.bits32 = 0;
++      mrxcr2.bits32 = 0;
++      mrxcr0.bits.port = 1;
++      mrxcr0.bits.l3 = 1;
++      mrxcr0.bits.l4 = 1;
++      mrxcr1.bits.sip = 1;
++      mrxcr1.bits.dip = 1;
++      mrxcr1.bits.l4_byte0_15 = 0xcc; // Byte 2, 3, 6, 7
++      mrxcr0.bits.sprx = 4;                   // see GMAC driver about SPR
++
++      rc = mac_set_rule_reg(cfg->lan_port, cfg->gre_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
++      if (rc < 0)
++      {
++              nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->lan_port, cfg->gre_rule_id);
++      }
++
++      if (cfg->lan_port != cfg->wan_port)
++      {
++              rc = mac_set_rule_reg(cfg->wan_port, cfg->gre_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
++              if (rc < 0)
++              {
++                      nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->wan_port, cfg->gre_rule_id);
++              }
++      }
++#endif
++
++#ifdef SL351x_NAT_TEST_BY_SMARTBITS
++      nat_init_test_entry();
++#endif
++}
++
++/*----------------------------------------------------------------------
++* nat_build_keys
++*     Note: To call this routine, the key->rule_id MUST be zero
++*----------------------------------------------------------------------*/
++static inline int nat_build_keys(NAT_KEY_T *key)
++{
++      return hash_gen_crc16((unsigned char *)key, NAT_KEY_SIZE) & HASH_BITS_MASK;
++}
++
++/*----------------------------------------------------------------------
++* gre_build_keys
++*     Note: To call this routine, the key->rule_id MUST be zero
++*----------------------------------------------------------------------*/
++static inline int gre_build_keys(GRE_KEY_T *key)
++{
++      return hash_gen_crc16((unsigned char *)key, GRE_KEY_SIZE) & HASH_BITS_MASK;
++}
++
++/*----------------------------------------------------------------------
++* nat_write_hash_entry
++*----------------------------------------------------------------------*/
++static inline int nat_write_hash_entry(int index, void *hash_entry)
++{
++      int             i;
++      u32             *srcep, *destp, *destp2;
++
++      srcep = (u32 *)hash_entry;
++      destp = destp2 = (u32 *)&hash_tables[index][0];
++
++      for (i=0; i<(NAT_HASH_ENTRY_SIZE/sizeof(u32)); i++)
++              *destp++ = *srcep++;
++
++      consistent_sync(destp2, NAT_HASH_ENTRY_SIZE, PCI_DMA_TODEVICE);
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++* gre_write_hash_entry
++*----------------------------------------------------------------------*/
++static inline int gre_write_hash_entry(int index, void *hash_entry)
++{
++      int             i;
++      u32             *srcep, *destp, *destp2;
++
++      srcep = (u32 *)hash_entry;
++      destp = destp2 = (u32 *)&hash_tables[index][0];
++
++      for (i=0; i<(GRE_HASH_ENTRY_SIZE/sizeof(u32)); i++)
++              *destp++ = *srcep++;
++
++      consistent_sync(destp2, GRE_HASH_ENTRY_SIZE, PCI_DMA_TODEVICE);
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++* sl351x_nat_find_ipcfg
++*     return NULL if not found
++*----------------------------------------------------------------------*/
++static NAT_IP_ENTRY_T *sl351x_nat_find_ipcfg(u32 ipaddr, int port)
++{
++      int                             i;
++      NAT_IP_ENTRY_T  *ipcfg;
++
++      ipcfg = (NAT_IP_ENTRY_T *)&nat_cfg.ipcfg[port].entry[0];
++      for (i=0; i<nat_cfg.ipcfg[port].total; i++, ipcfg++)
++      {
++              if (ipaddr == ipcfg->ipaddr)
++              {
++                      return ipcfg;
++              }
++      }
++      return NULL;
++}
++
++/*----------------------------------------------------------------------
++* sl351x_nat_assign_qid
++*----------------------------------------------------------------------*/
++static int sl351x_nat_assign_qid(u8 proto, u32 sip, u32 dip, u16 sport, u16 dport)
++{
++      int                             i, total, qid;
++      NAT_WRULE_ENTRY_T       *entry;
++
++      for (qid = 0; qid<CONFIG_NAT_TXQ_NUM; qid++)
++      {
++              if (qid == nat_cfg.default_hw_txq)
++                      continue;
++
++              entry = (NAT_WRULE_ENTRY_T *)&nat_cfg.wrule[qid].entry[0];
++              total = nat_cfg.wrule[qid].total;
++              for (i=0; i<total; i++, entry++)
++              {
++                      if (!entry->protocol || entry->protocol==proto)
++                      {
++                              //if (!entry->sip_start && !entry->dip_start && !entry->sport_start && !entry->dport_start)
++                              //      continue; // UI take care
++                              if (entry->sip_start && !((sip >= entry->sip_start) &&
++                                                                         (sip <= entry->sip_end)))
++                                      continue;
++                              if (entry->dip_start && !((dip >= entry->dip_start) &&
++                                                                         (dip <= entry->dip_end)))
++                                      continue;
++                              if (entry->sport_start && !((sport >= entry->sport_start) &&
++                                                                         (sport <= entry->sport_end)))
++                                      continue;
++                              if (entry->dport_start && !((dport >= entry->dport_start)
++                                                                     && (dport <= entry->dport_end)))
++                                      continue;
++                              return qid;
++                      }
++              }
++      }
++      return nat_cfg.default_hw_txq;
++}
++
++/*----------------------------------------------------------------------
++* sl351x_nat_input
++*     Handle NAT input frames
++*     Called by SL351x Driver - Handle Default Rx Queue
++*     Notes: The caller must make sure that the l3off & l4offset should not be zero.
++*     SL351x NAT Frames should meet the following conditions:
++*     1. TCP or UDP frame
++*     2. Cannot be special ALGs ports which TCP/UDP data is updated
++*     3. LAN-IN Frames:
++*             Source IP is in the LAN subnet and Destination is not in the LAN subnet
++*     4. WAN-IN Frames
++*             Destination IP is in the WAN port IP
++*
++*     Example Ports
++*     1. TCP/UDP data is updated
++*             (a) FTP Control Packet
++*             (b) VoIP Packets
++*             (c) etc. (add in future)
++*     2. UDP Low packet rate, not worth
++*             (b) TFTP Destination Port is 69
++*             (b) DNS  53
++*             (c) NTP  123
++*             (d) etc. (add in future)
++*----------------------------------------------------------------------*/
++void sl351x_nat_input(struct sk_buff *skb, int port, void *l3off, void *l4off)
++{
++      int                             i, found;
++      u32                                     sip, dip;
++      u16                                     sport, dport;
++      struct ethhdr           *ether_hdr;
++      struct iphdr            *ip_hdr;
++      struct tcphdr           *tcp_hdr;
++      struct pppoe_hdr        *pppoe_hdr;
++      NAT_CB_T                        *nat_cb;
++      u8                                      proto, pppoe_frame=0;
++      NAT_CFG_T                       *cfg;
++      u16                                     ppp_proto;
++      NAT_IP_ENTRY_T          *ipcfg;
++      NAT_XPORT_ENTRY_T       *xentry;
++      GRE_PKTHDR_T            *gre_hdr;
++#ifdef CONFIG_SL351x_NAT_TCP_UDP
++      u16                             *port_ptr;
++#endif
++
++      cfg = (NAT_CFG_T *)&nat_cfg;
++      if (!cfg->enabled || !cfg->ipcfg[port].total)
++              return;
++
++      ip_hdr = (struct iphdr *)&(skb->data[(u32)l3off]);
++      proto = ip_hdr->protocol;
++
++      tcp_hdr = (struct tcphdr *)&(skb->data[(u32)l4off]);
++      gre_hdr = (GRE_PKTHDR_T *)tcp_hdr;
++      sport = ntohs(tcp_hdr->source);
++      dport = ntohs(tcp_hdr->dest);
++
++      sip = ntohl(ip_hdr->saddr);
++      dip = ntohl(ip_hdr->daddr);
++
++      if (dip == IPIV(255,255,255,255))
++              return;
++
++      if (port == cfg->lan_port)
++      {
++              ipcfg = (NAT_IP_ENTRY_T *)&cfg->ipcfg[port].entry[0];
++              for (i=0, found=0; i<cfg->ipcfg[port].total; i++, ipcfg++)
++              {
++                      u32 subnet = ipcfg->ipaddr & ipcfg->netmask;
++                      if (((sip & ipcfg->netmask) == subnet) &&
++                              ((dip & ipcfg->netmask) != subnet))
++                      {
++                              found = 1;
++                              break;
++                      }
++              }
++              if (!found)
++                      return;
++      }
++      else
++      {
++#ifndef _NOT_CHECK_SIP_DIP    // enable it if know and get the wan ip address
++              if (!sl351x_nat_find_ipcfg(dip, port))
++              {
++                      printk("WAN->LAN Incorrect Dip %d.%d.%d.%d\n", HIPQUAD(dip));
++                      return;
++              }
++#endif
++              ether_hdr = (struct ethhdr *)skb->data;
++              pppoe_hdr = (struct pppoe_hdr *)(ether_hdr + 1);
++              ppp_proto = *(u16 *)&pppoe_hdr->tag[0];
++              if (ether_hdr->h_proto == __constant_htons(ETH_P_PPP_SES)       // 0x8864
++                      && ppp_proto == __constant_htons(PPP_IP) )                              // 0x21
++              {
++                      pppoe_frame = 1;
++              }
++      }
++
++#ifdef CONFIG_SL351x_NAT_TCP_UDP
++      if (proto == IPPROTO_TCP)
++      {
++#ifdef        NAT_DEBUG_MSG
++              nat_printf("From   GMAC-%d: 0x%-4X TCP %d.%d.%d.%d [%d] --> %d.%d.%d.%d [%d]",
++                              port, ntohs(ip_hdr->id),
++                              NIPQUAD(ip_hdr->saddr), sport,
++                              NIPQUAD(ip_hdr->daddr), dport);
++              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_SYN) nat_printf(" SYN");
++              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_FIN) nat_printf(" FIN");
++              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_RST) nat_printf(" RST");
++              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_ACK) nat_printf(" ACK");
++              nat_printf("\n");
++#endif
++              // if (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN | TCP_FLAG_FIN | TCP_FLAG_RST))
++              if (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN))
++              {
++                      return;
++              }
++              port_ptr = fixed_tcp_port_list;
++              for (i=0; *port_ptr; i++, port_ptr++)
++              {
++                      if (sport == *port_ptr || dport == *port_ptr)
++                              return;
++              }
++#ifdef _HAVE_DYNAMIC_PORT_LIST
++              port_ptr = dynamic_tcp_port_list;
++              for (i=0; *port_ptr; i++, port_ptr++)
++              {
++                      if (sport == *port_ptr || dport == *port_ptr)
++                              return;
++              }
++#endif
++      }
++      else if (proto == IPPROTO_UDP)
++      {
++#ifdef        NAT_DEBUG_MSG
++              nat_printf("From   GMAC-%d: 0x%-4X UDP %d.%d.%d.%d [%d] --> %d.%d.%d.%d [%d]",
++                              port, ntohs(ip_hdr->id),
++                              NIPQUAD(ip_hdr->saddr), sport,
++                              NIPQUAD(ip_hdr->daddr), dport);
++              nat_printf("\n");
++#endif
++              port_ptr = fixed_udp_port_list;
++              for (i=0; *port_ptr; i++, port_ptr++)
++              {
++                      if (sport == *port_ptr || dport == *port_ptr)
++                              return;
++              }
++#ifdef _HAVE_DYNAMIC_PORT_LIST
++              port_ptr = dynamic_udp_port_list;
++              for (i=0; *port_ptr; i++, port_ptr++)
++              {
++                      if (sport == *port_ptr || dport == *port_ptr)
++                              return;
++              }
++#endif
++      }
++      else
++#endif        // CONFIG_SL351x_NAT_TCP_UDP
++#ifdef CONFIG_SL351x_NAT_GRE
++      if (proto == IPPROTO_GRE)
++      {
++              if (gre_hdr->protocol != GRE_PROTOCOL_SWAP)
++                      return;
++#ifdef        NAT_DEBUG_MSG
++              nat_printf("From   GMAC-%d: 0x%-4X GRE %d.%d.%d.%d [%d] --> %d.%d.%d.%d",
++                              port, ntohs(ip_hdr->id),
++                              NIPQUAD(ip_hdr->saddr), ntohs(gre_hdr->call_id),
++                              NIPQUAD(ip_hdr->daddr));
++              nat_printf("\n");
++#endif
++      }
++      else
++#endif
++              return;
++
++
++      // check xport list
++      xentry = (NAT_XPORT_ENTRY_T *)&cfg->xport.entry[0];
++      for (i=0; i<cfg->xport.total; i++, xentry++)
++      {
++              if (!xentry->protocol || xentry->protocol == proto)
++              {
++                      //if (!xentry->sport_start && !xentry->dport_start) // UI take care
++                      //      continue;
++                      if (xentry->sport_start && !((sport >= xentry->sport_start) &&
++                                                                         (sport <= xentry->sport_end)))
++                              continue;
++                      if (xentry->dport_start && !((dport >= xentry->dport_start)
++                                                                     && (dport <= xentry->dport_end)))
++                              continue;
++                      return;
++              }
++      }
++
++      nat_cb = NAT_SKB_CB(skb);
++      if (((u32)nat_cb & 3))
++      {
++              nat_printf("%s ERROR! nat_cb is not alignment!!!!!!\n", __func__);
++              return;
++      }
++      nat_cb->tag = NAT_CB_TAG;
++      memcpy(nat_cb->sa, skb->data+6, 6);
++      nat_cb->sip = ip_hdr->saddr;
++      nat_cb->dip = ip_hdr->daddr;
++      if (proto == IPPROTO_GRE)
++      {
++              nat_cb->sport = gre_hdr->protocol;
++              nat_cb->dport = gre_hdr->call_id;
++      }
++      else
++      {
++              nat_cb->sport = tcp_hdr->source;
++              nat_cb->dport = tcp_hdr->dest;
++      }
++      nat_cb->pppoe_frame = pppoe_frame;
++}
++
++/*----------------------------------------------------------------------
++* sl351x_nat_output
++*     Handle NAT output frames
++*     Called by SL351x Driver - Transmit
++*
++*     1. If not SL351x NAT frames, return FALSE
++*     2. LAN-to-WAN frames
++*             (1) Sip must be WAN IP
++*     3. If TCP SY/RST/FIN frame, return
++*     4. Build the hash key and get the hash index
++*     5. If V-Bit is ON, return.
++*     6. Write hash entry and validate it
++*
++*----------------------------------------------------------------------*/
++int sl351x_nat_output(struct sk_buff *skb, int port)
++{
++      struct iphdr            *ip_hdr;
++      u8                                      proto;
++      NAT_CB_T                        *nat_cb;
++
++      nat_cb = NAT_SKB_CB(skb);
++      if (nat_cb->tag != NAT_CB_TAG)
++              return 0;
++
++      if (((u32)nat_cb & 3))
++      {
++              nat_printf("%s ERROR! nat_cb is not alignment!!!!!!\n", __func__);
++              return 0;
++      }
++      ip_hdr = (struct iphdr *)skb->h.ipiph;
++      proto = ip_hdr->protocol;
++
++      switch (proto)
++      {
++              case IPPROTO_TCP:
++              case IPPROTO_UDP:
++                      return sl351x_nat_tcp_udp_output(skb, port);
++              case IPPROTO_GRE:
++                      return sl351x_nat_gre_output(skb, port);
++      }
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++* sl351x_nat_tcp_udp_output
++*     Handle NAT TCP/UDP output frames
++*----------------------------------------------------------------------*/
++int sl351x_nat_tcp_udp_output(struct sk_buff *skb, int port)
++{
++      u32                                     sip, dip;
++      struct ethhdr           *ether_hdr;
++      struct iphdr            *ip_hdr;
++      struct tcphdr           *tcp_hdr;
++      struct pppoe_hdr        *pppoe_hdr;
++      NAT_CB_T                        *nat_cb;
++      NAT_CFG_T                       *cfg;
++      u8                                      proto;
++      u16                                     sport, dport, ppp_proto;
++      u32                                     hash_data[HASH_MAX_DWORDS];
++      NAT_HASH_ENTRY_T        *hash_entry;
++      int                                     hash_index;
++      struct ip_conntrack *nat_ip_conntrack;
++      enum ip_conntrack_info ctinfo;
++
++      nat_cb = NAT_SKB_CB(skb);
++      cfg = (NAT_CFG_T *)&nat_cfg;
++
++      ether_hdr = (struct ethhdr *)skb->data;
++      ip_hdr = (struct iphdr *)skb->h.ipiph;
++      tcp_hdr = (struct tcphdr *)((u32)ip_hdr + (ip_hdr->ihl<<2));
++      sip = ntohl(ip_hdr->saddr);
++      dip = ntohl(ip_hdr->daddr);
++      proto = ip_hdr->protocol;
++      sport = ntohs(tcp_hdr->source);
++      dport = ntohs(tcp_hdr->dest);
++
++#ifdef        NAT_DEBUG_MSG
++      {
++              nat_printf("To   GMAC-%d: 0x%-4X [%d] %d.%d.%d.%d [%d] --> %d.%d.%d.%d [%d]",
++                              port, ntohs(ip_hdr->id), proto,
++                              NIPQUAD(ip_hdr->saddr), sport,
++                              NIPQUAD(ip_hdr->daddr), dport);
++              if (proto == IPPROTO_TCP)
++              {
++                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_SYN) nat_printf(" SYN");
++                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_FIN) nat_printf(" FIN");
++                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_RST) nat_printf(" RST");
++                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_ACK) nat_printf(" ACK");
++              }
++              nat_printf("\n");
++      }
++#endif
++      nat_ip_conntrack = ip_conntrack_get(skb, &ctinfo);
++      if (!nat_ip_conntrack)
++      {
++              nat_printf("IP conntrack info is not found!\n");
++              return 0;
++      }
++      // nat_printf("nat_ip_conntrack = 0x%x, status=0x%lx, ctinfo=%d\n", (u32)nat_ip_conntrack, nat_ip_conntrack->status, ctinfo);
++      // if (nat_ip_conntrack->master || nat_ip_conntrack->helper)
++      if (nat_ip_conntrack->helper)
++      {
++              nat_printf("Sport=%d Dport=%d master=0x%x, helper=0x%x\n", sport, dport, (u32)nat_ip_conntrack->master, (u32)nat_ip_conntrack->helper);
++              return 0;
++      }
++
++      //if (proto == IPPROTO_TCP && !(nat_ip_conntrack->status & IPS_ASSURED))
++      //      return 0;
++
++#ifdef        NAT_DEBUG_MSG
++      nat_printf("nat_ip_conntrack=0x%x, nat_cb->state=%d\n", (u32)nat_ip_conntrack, nat_cb->state);
++      nat_printf("lan2wan_hash_index=%d,  wan2lan_hash_index=%d\n", nat_ip_conntrack->lan2wan_hash_index, nat_ip_conntrack->wan2lan_hash_index);
++      nat_printf("lan2wan_collision=%d, wan2lan_collision=%d\n", nat_ip_conntrack->lan2wan_collision, nat_ip_conntrack->wan2lan_collision);
++#endif
++      if (proto == IPPROTO_TCP)
++      {
++              if (nat_cb->state >= TCP_CONNTRACK_FIN_WAIT && nat_cb->state <= TCP_CONNTRACK_CLOSE)
++              {
++                      if      (nat_ip_conntrack->lan2wan_hash_index)
++                      {
++#ifdef        NAT_DEBUG_MSG
++                              nat_printf("Invalidate LAN->WAN hash entry %d\n", nat_ip_conntrack->lan2wan_hash_index - 1);
++#endif
++                              hash_nat_disable_owner(nat_ip_conntrack->lan2wan_hash_index - 1);
++                              hash_invalidate_entry(nat_ip_conntrack->lan2wan_hash_index - 1);
++                              nat_ip_conntrack->lan2wan_hash_index = 0;
++                      }
++                      if      (nat_ip_conntrack->wan2lan_hash_index)
++                      {
++#ifdef        NAT_DEBUG_MSG
++                              nat_printf("Invalidate WAN->LAN hash entry %d\n", nat_ip_conntrack->wan2lan_hash_index - 1);
++#endif
++                              hash_nat_disable_owner(nat_ip_conntrack->wan2lan_hash_index - 1);
++                              hash_invalidate_entry(nat_ip_conntrack->wan2lan_hash_index - 1);
++                              nat_ip_conntrack->wan2lan_hash_index = 0;
++                      }
++                      return 0;
++
++              }
++              else if (nat_cb->state != TCP_CONNTRACK_ESTABLISHED)
++              {
++                      return 0;
++              }
++      }
++      if (proto == IPPROTO_TCP && (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN | TCP_FLAG_FIN | TCP_FLAG_RST)))
++      // if (proto == IPPROTO_TCP &&  (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN)))
++              return 0;
++
++      hash_entry = (NAT_HASH_ENTRY_T *)&hash_data;
++      if (port == cfg->wan_port)      // LAN-to-WAN
++      {
++              if (nat_ip_conntrack->lan2wan_hash_index || nat_ip_conntrack->lan2wan_collision)
++                      return 0;
++#ifndef _NOT_CHECK_SIP_DIP    // enable it if know and get the wan ip address
++              if (!sl351x_nat_find_ipcfg(sip, port))
++              {
++                      printk("LAN->WAN Incorrect Sip %d.%d.%d.%d\n", HIPQUAD(sip));
++                      return 0;
++              }
++#endif
++              // Note: unused fields (including rule_id) MUST be zero
++              hash_entry->key.Ethertype       = 0;
++              hash_entry->key.port_id         = cfg->lan_port;
++              hash_entry->key.rule_id         = 0;
++              hash_entry->key.ip_protocol = proto;
++              hash_entry->key.reserved1       = 0;
++              hash_entry->key.reserved2       = 0;
++              hash_entry->key.sip             = ntohl(nat_cb->sip);
++              hash_entry->key.dip             = ntohl(nat_cb->dip);
++              hash_entry->key.sport           = nat_cb->sport;
++              hash_entry->key.dport           = nat_cb->dport;
++
++              hash_index = nat_build_keys(&hash_entry->key);
++
++#ifdef NAT_DEBUG_LAN_HASH_TIMEOUT
++              if (hash_get_nat_owner_flag(hash_index))
++                      return 0;
++#endif
++              if (hash_get_valid_flag(hash_index))
++              {
++                      nat_ip_conntrack->lan2wan_collision = 1;
++                      nat_collision++;
++#if 0
++                      if (proto == IPPROTO_TCP && (tcp_flag_word(tcp_hdr) & (TCP_FLAG_FIN | TCP_FLAG_RST)))
++                      {
++                              if (memcmp((void *)&hash_entry->key, hash_get_entry(hash_index), sizeof(NAT_KEY_T)) == 0)
++                              {
++                                      hash_nat_disable_owner(hash_index);
++                                      hash_invalidate_entry(hash_index); // Must last one, else HW Tx fast SW
++                                      // nat_printf("Invalidate nat hash entry %d\n", hash_index);
++                              }
++                      }
++#endif
++                      return 0;
++              }
++
++              // write hash entry
++              hash_entry->key.rule_id = cfg->tcp_udp_rule_id;
++              memcpy(hash_entry->param.da, skb->data, 6);
++              memcpy(hash_entry->param.sa, skb->data+6, 6);
++              hash_entry->param.Sip = sip;
++              hash_entry->param.Dip = dip;
++              hash_entry->param.Sport = sport;
++              hash_entry->param.Dport = dport;
++              hash_entry->param.vlan = 0;
++              hash_entry->param.sw_id = 0;
++              hash_entry->param.mtu = 0;
++              // check PPPoE
++              pppoe_hdr = (struct pppoe_hdr *)(ether_hdr + 1);
++              ppp_proto = *(u16 *)&pppoe_hdr->tag[0];
++              if (ether_hdr->h_proto == __constant_htons(ETH_P_PPP_SES)       // 0x8864
++                      && ppp_proto == __constant_htons(PPP_IP) )                              // 0x21
++              {
++                      hash_entry->action.dword = NAT_PPPOE_LAN2WAN_ACTIONS;
++                      hash_entry->param.pppoe = htons(pppoe_hdr->sid);
++              }
++              else
++              {
++                      hash_entry->action.dword = NAT_LAN2WAN_ACTIONS;
++                      hash_entry->param.pppoe = 0;
++              }
++              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(proto, sip, dip, sport, dport);
++              hash_entry->action.bits.dest_qid +=     (cfg->wan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
++              hash_entry->tmo.counter = hash_entry->tmo.interval =
++                                              (proto == IPPROTO_TCP) ? cfg->tcp_tmo_interval : cfg->udp_tmo_interval;
++              nat_write_hash_entry(hash_index, hash_entry);
++              // nat_printf("%lu Validate a LAN hash entry %d\n", jiffies/HZ, hash_index);
++              // hash_dump_entry(hash_index);
++              hash_nat_enable_owner(hash_index);
++              hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
++              nat_ip_conntrack->lan2wan_hash_index = hash_index + 1;
++              nat_ip_conntrack->hw_nat |= 1;
++              return 0;
++      }
++      else // WAN-to-LAN
++      {
++              if (nat_ip_conntrack->wan2lan_hash_index || nat_ip_conntrack->wan2lan_collision)
++                      return 0;
++
++              // Note: unused fields (including rule_id) MUST be zero
++              hash_entry->key.Ethertype       = 0;
++              hash_entry->key.port_id         = cfg->wan_port;
++              hash_entry->key.rule_id         = 0;
++              hash_entry->key.ip_protocol = proto;
++              hash_entry->key.reserved1       = 0;
++              hash_entry->key.reserved2       = 0;
++              hash_entry->key.sip             = ntohl(nat_cb->sip);
++              hash_entry->key.dip             = ntohl(nat_cb->dip);
++              hash_entry->key.sport           = nat_cb->sport;
++              hash_entry->key.dport           = nat_cb->dport;
++
++              hash_index = nat_build_keys(&hash_entry->key);
++
++#ifdef NAT_DEBUG_WAN_HASH_TIMEOUT
++              if (hash_get_nat_owner_flag(hash_index))
++                      return 0;
++#endif
++              if (hash_get_valid_flag(hash_index))
++              {
++                      nat_ip_conntrack->wan2lan_collision = 1;
++                      nat_collision++;
++#if 0
++                      if (proto == IPPROTO_TCP && (tcp_flag_word(tcp_hdr) & (TCP_FLAG_FIN | TCP_FLAG_RST)))
++                      {
++                              if (memcmp((void *)&hash_entry->key, hash_get_entry(hash_index), sizeof(NAT_KEY_T)) == 0)
++                              {
++                                      hash_nat_disable_owner(hash_index);
++                                      hash_invalidate_entry(hash_index); // Must last one, else HW Tx fast SW
++                                      // nat_printf("Invalidate nat hash entry %d\n", hash_index);
++                              }
++                      }
++#endif
++                      return 0;
++              }
++
++              // write hash entry
++              hash_entry->key.rule_id = cfg->tcp_udp_rule_id;
++              memcpy(hash_entry->param.da, skb->data, 6);
++              memcpy(hash_entry->param.sa, skb->data+6, 6);
++              hash_entry->param.Sip = sip;
++              hash_entry->param.Dip = dip;
++              hash_entry->param.Sport = sport;
++              hash_entry->param.Dport = dport;
++              hash_entry->param.vlan = 0;
++              hash_entry->param.pppoe = 0;
++              hash_entry->param.sw_id = 0;
++              hash_entry->param.mtu = 0;
++              hash_entry->action.dword = (nat_cb->pppoe_frame) ? NAT_PPPOE_WAN2LAN_ACTIONS : NAT_WAN2LAN_ACTIONS;
++              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(proto, sip, dip, sport, dport);
++              hash_entry->action.bits.dest_qid += (cfg->lan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;;
++              hash_entry->tmo.counter = hash_entry->tmo.interval =
++                                              (proto == IPPROTO_TCP) ? cfg->tcp_tmo_interval : cfg->udp_tmo_interval;
++              nat_write_hash_entry(hash_index, hash_entry);
++
++              // nat_printf("%lu Validate a WAN hash entry %d\n", jiffies/HZ, hash_index);
++              // hash_dump_entry(hash_index);
++              hash_nat_enable_owner(hash_index);
++              hash_validate_entry(hash_index); // Must last one, else HW Tx fast SW
++              nat_ip_conntrack->wan2lan_hash_index = hash_index + 1;
++              nat_ip_conntrack->hw_nat |= 2;
++              return 0;
++      }
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++* sl351x_nat_gre_output
++*     Handle NAT GRE output frames
++*----------------------------------------------------------------------*/
++int sl351x_nat_gre_output(struct sk_buff *skb, int port)
++{
++      u32                                     sip, dip;
++      struct ethhdr           *ether_hdr;
++      struct iphdr            *ip_hdr;
++      struct pppoe_hdr        *pppoe_hdr;
++      GRE_PKTHDR_T            *gre_hdr;
++      NAT_CB_T                        *nat_cb;
++      NAT_CFG_T                       *cfg;
++      u16                                     ppp_proto;
++      u32                                     hash_data[HASH_MAX_DWORDS];
++      GRE_HASH_ENTRY_T        *hash_entry;
++      int                                     hash_index;
++      struct ip_conntrack *nat_ip_conntrack;
++      enum ip_conntrack_info ctinfo;
++
++      nat_cb = NAT_SKB_CB(skb);
++      cfg = (NAT_CFG_T *)&nat_cfg;
++
++      ether_hdr = (struct ethhdr *)skb->data;
++      ip_hdr = (struct iphdr *)skb->h.ipiph;
++      gre_hdr = (GRE_PKTHDR_T *)((u32)ip_hdr + (ip_hdr->ihl<<2));
++      sip = ntohl(ip_hdr->saddr);
++      dip = ntohl(ip_hdr->daddr);
++
++#ifdef        NAT_DEBUG_MSG
++      {
++              nat_printf("To   GMAC-%d: 0x%-4X GRE %d.%d.%d.%d [%d] --> %d.%d.%d.%d",
++                              port, ntohs(ip_hdr->id),
++                              NIPQUAD(ip_hdr->saddr), ntohs(gre_hdr->call_id),
++                              NIPQUAD(ip_hdr->daddr));
++              nat_printf("\n");
++      }
++#endif
++      nat_ip_conntrack = ip_conntrack_get(skb, &ctinfo);
++      if (nat_ip_conntrack)
++      {
++              // if (nat_ip_conntrack->master || nat_ip_conntrack->helper)
++              if (nat_ip_conntrack->helper)
++              {
++                      nat_printf("GRE Call-ID=%d, master=0x%x, helper=0x%x\n", ntohs(gre_hdr->call_id), (u32)nat_ip_conntrack->master, (u32)nat_ip_conntrack->helper);
++                      return 0;
++              }
++              if (!(nat_ip_conntrack->status & IPS_ASSURED))
++                      return 0;
++      }
++
++      hash_entry = (GRE_HASH_ENTRY_T *)&hash_data;
++      if (port == cfg->wan_port)      // LAN-to-WAN
++      {
++#ifdef _NOT_CHECK_SIP_DIP     // enable it if know and get the wan ip address
++              if (!sl351x_nat_find_ipcfg(sip, port))
++              {
++                      printk("LAN->WAN Incorrect Sip %d.%d.%d.%d\n", HIPQUAD(sip));
++                      return 0;
++              }
++#endif
++              // Note: unused fields (including rule_id) MUST be zero
++              hash_entry->key.Ethertype       = 0;
++              hash_entry->key.port_id         = cfg->lan_port;
++              hash_entry->key.rule_id         = 0;
++              hash_entry->key.ip_protocol = IPPROTO_GRE;
++              hash_entry->key.reserved1       = 0;
++              hash_entry->key.reserved2       = 0;
++              hash_entry->key.reserved3       = 0;
++              hash_entry->key.reserved4       = 0;
++              hash_entry->key.sip             = ntohl(nat_cb->sip);
++              hash_entry->key.dip             = ntohl(nat_cb->dip);
++              hash_entry->key.protocol        = nat_cb->sport;
++              hash_entry->key.call_id         = nat_cb->dport;
++
++              hash_index = gre_build_keys(&hash_entry->key);
++
++#ifdef NAT_DEBUG_LAN_HASH_TIMEOUT
++              if (hash_get_nat_owner_flag(hash_index))
++                      return 0;
++#endif
++              if (hash_get_valid_flag(hash_index))
++              {
++                      return 0;
++              }
++
++              // write hash entry
++              hash_entry->key.rule_id = cfg->gre_rule_id;
++              memcpy(hash_entry->param.da, skb->data, 6);
++              memcpy(hash_entry->param.sa, skb->data+6, 6);
++              hash_entry->param.Sip = sip;
++              hash_entry->param.Dip = dip;
++              hash_entry->param.Sport = 0;
++              hash_entry->param.Dport = ntohs(gre_hdr->call_id);
++              hash_entry->param.vlan = 0;
++              hash_entry->param.sw_id = 0;
++              hash_entry->param.mtu = 0;
++              // check PPPoE
++              pppoe_hdr = (struct pppoe_hdr *)(ether_hdr + 1);
++              ppp_proto = *(u16 *)&pppoe_hdr->tag[0];
++              if (ether_hdr->h_proto == __constant_htons(ETH_P_PPP_SES)       // 0x8864
++                      && ppp_proto == __constant_htons(PPP_IP) )                              // 0x21
++              {
++                      hash_entry->action.dword = NAT_PPPOE_PPTP_LAN2WAN_ACTIONS;
++                      hash_entry->param.pppoe = htons(pppoe_hdr->sid);
++              }
++              else
++              {
++                      hash_entry->action.dword = NAT_PPTP_LAN2WAN_ACTIONS;
++                      hash_entry->param.pppoe = 0;
++              }
++              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(IPPROTO_GRE, sip, dip, 0, ntohs(gre_hdr->call_id));
++              hash_entry->action.bits.dest_qid +=     (cfg->wan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
++              hash_entry->tmo.counter = hash_entry->tmo.interval = cfg->gre_tmo_interval;
++              gre_write_hash_entry(hash_index, hash_entry);
++              // nat_printf("%lu Validate a LAN hash entry %d\n", jiffies/HZ, hash_index);
++              // hash_dump_entry(hash_index);
++              hash_nat_enable_owner(hash_index);
++              hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
++              return 0;
++      }
++      else // WAN-to-LAN
++      {
++              // Note: unused fields (including rule_id) MUST be zero
++              hash_entry->key.Ethertype       = 0;
++              hash_entry->key.port_id         = cfg->wan_port;
++              hash_entry->key.rule_id         = 0;
++              hash_entry->key.ip_protocol = IPPROTO_GRE;
++              hash_entry->key.reserved1       = 0;
++              hash_entry->key.reserved2       = 0;
++              hash_entry->key.reserved3       = 0;
++              hash_entry->key.reserved4       = 0;
++              hash_entry->key.sip             = ntohl(nat_cb->sip);
++              hash_entry->key.dip             = ntohl(nat_cb->dip);
++              hash_entry->key.protocol        = nat_cb->sport;
++              hash_entry->key.call_id         = nat_cb->dport;
++
++              hash_index = gre_build_keys(&hash_entry->key);
++
++#ifdef NAT_DEBUG_WAN_HASH_TIMEOUT
++              if (hash_get_nat_owner_flag(hash_index))
++                      return 0;
++#endif
++              if (hash_get_valid_flag(hash_index))
++              {
++                      return 0;
++              }
++
++              // write hash entry
++              hash_entry->key.rule_id = cfg->gre_rule_id;
++              memcpy(hash_entry->param.da, skb->data, 6);
++              memcpy(hash_entry->param.sa, skb->data+6, 6);
++              hash_entry->param.Sip = sip;
++              hash_entry->param.Dip = dip;
++              hash_entry->param.Sport = 0;
++              hash_entry->param.Dport = ntohs(gre_hdr->call_id);
++              hash_entry->param.vlan = 0;
++              hash_entry->param.pppoe = 0;
++              hash_entry->param.sw_id = 0;
++              hash_entry->param.mtu = 0;
++              hash_entry->action.dword = (nat_cb->pppoe_frame) ? NAT_PPPOE_PPTP_WAN2LAN_ACTIONS : NAT_PPTP_WAN2LAN_ACTIONS;
++              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(IPPROTO_GRE, sip, dip, 0, ntohs(gre_hdr->call_id));
++              hash_entry->action.bits.dest_qid += (cfg->lan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;;
++              hash_entry->tmo.counter = hash_entry->tmo.interval = cfg->gre_tmo_interval;
++              gre_write_hash_entry(hash_index, hash_entry);
++
++              // nat_printf("%lu Validate a WAN hash entry %d\n", jiffies/HZ, hash_index);
++              // hash_dump_entry(hash_index);
++              hash_nat_enable_owner(hash_index);
++              hash_validate_entry(hash_index); // Must last one, else HW Tx fast SW
++              return 0;
++      }
++      return 0;
++}
++
++
++#ifdef _HAVE_DYNAMIC_PORT_LIST
++/*----------------------------------------------------------------------
++* sl_nat_add_port
++*----------------------------------------------------------------------*/
++void sl_nat_add_port(u8 protocol, u16 port)
++{
++      int     i;
++      u16             *port_ptr;
++
++      if (protocol == IPPROTO_TCP)
++              port_ptr = dynamic_tcp_port_list;
++      else if (protocol == IPPROTO_UDP)
++              port_ptr = dynamic_udp_port_list;
++      else
++              return;
++
++      for (i=0; *port_ptr; i++)
++      {
++              if (port == *port_ptr)
++                      return;
++              port_ptr++;
++      }
++      port_ptr++;
++      *port_ptr = port;
++}
++
++/*----------------------------------------------------------------------
++* sl_nat_remove_port
++*----------------------------------------------------------------------*/
++void sl_nat_remove_port(u8 protocol, u16 port)
++{
++      int     i, j;
++      u16             *port_ptr, *next;
++
++      if (protocol == IPPROTO_TCP)
++              port_ptr = dynamic_tcp_port_list;
++      else if (protocol == IPPROTO_UDP)
++              port_ptr = dynamic_udp_port_list;
++      else
++              return;
++
++      for (i=0; *port_ptr; i++, port_ptr++)
++      {
++              if (port == *port_ptr)
++              {
++                      port_next = port_ptr + 1;
++                      for (j=i+1; *port_next; i++, j++)
++                              *port_ptr++ = *port_next++;
++                      *port_ptr = 0;
++                      return;
++              }
++      }
++}
++#endif
++
++/*----------------------------------------------------------------------
++* sl351x_nat_ioctl
++*----------------------------------------------------------------------*/
++int sl351x_nat_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++      GMAC_INFO_T             *tp = (GMAC_INFO_T *)dev->priv;
++      int                             i, j, port_id;
++    NATCMD_HDR_T              nat_hdr;
++    NAT_REQ_E                 ctrl;
++      unsigned char           *req_datap;
++      NAT_IP_ENTRY_T          *ipcfg;
++      NAT_XPORT_ENTRY_T       *xport_entry;
++      NAT_WRULE_ENTRY_T       *wrule_entry;
++      unsigned int            qid;
++
++      if (copy_from_user((void *)&nat_hdr, rq->ifr_data, sizeof(nat_hdr)))
++              return -EFAULT;
++      req_datap = (unsigned char *)rq->ifr_data + sizeof(nat_hdr);
++      port_id = tp->port_id;
++      switch (nat_hdr.cmd) {
++      case NATSSTATUS:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_STATUS_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&ctrl.status, req_datap, sizeof(ctrl.status)))
++                      return -EFAULT;
++              if (ctrl.status.enable != 0 && ctrl.status.enable != 1)
++                      return -EPERM;
++              // sl351x_nat_set_enabled_flag(ctrl.status.enable);
++              if (nat_cfg.enabled && (ctrl.status.enable == 0))
++              {
++                      for (i=0; i<HASH_TOTAL_ENTRIES; i++)
++                      {
++                              if (hash_get_nat_owner_flag(i))
++                              {
++                                      hash_nat_disable_owner(i);
++                                      hash_invalidate_entry(i);
++                              }
++                      }
++              }
++              nat_cfg.enabled = ctrl.status.enable;
++              break;
++      case NATGSTATUS:
++              if (nat_hdr.len != sizeof(NAT_STATUS_T))
++                      return -EPERM;
++              ctrl.status.enable = nat_cfg.enabled;
++              if (copy_to_user(req_datap, (void *)&ctrl.status, sizeof(ctrl.status)))
++                      return -EFAULT;
++              break;
++      case NATSETPORT:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_PORTCFG_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&ctrl.portcfg, req_datap, sizeof(ctrl.portcfg)))
++                      return -EFAULT;
++              if (ctrl.portcfg.portmap == 0)
++                      nat_cfg.lan_port = port_id;
++              else if (ctrl.portcfg.portmap == 1)
++                      nat_cfg.wan_port = port_id;
++              else
++                      return -EPERM;
++              break;
++      case NATGETPORT:
++              if (nat_hdr.len != sizeof(NAT_PORTCFG_T))
++                      return -EPERM;
++              if (nat_cfg.lan_port == port_id)
++                      ctrl.portcfg.portmap = 0;
++              else if (nat_cfg.wan_port == port_id)
++                      ctrl.portcfg.portmap = 1;
++              else
++                      return -EPERM;
++              if (copy_to_user(req_datap, (void *)&ctrl.portcfg, sizeof(ctrl.portcfg)))
++                      return -EFAULT;
++              break;
++      case NATADDIP:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_IPCFG_T))
++                      return -EPERM;
++              i = nat_cfg.ipcfg[port_id].total;
++              if (i >= CONFIG_NAT_MAX_IP_NUM)
++                      return -E2BIG;
++              if (copy_from_user((void *)&nat_cfg.ipcfg[port_id].entry[i], req_datap, sizeof(NAT_IPCFG_T)))
++                      return -EFAULT;
++              nat_cfg.ipcfg[port_id].total++;
++              break;
++      case NATDELIP:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_IPCFG_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&ctrl.ipcfg, req_datap, sizeof(ctrl.ipcfg)))
++                      return -EFAULT;
++              ipcfg = (NAT_IP_ENTRY_T *)&nat_cfg.ipcfg[port_id].entry[0];
++              for (i=0; i<nat_cfg.ipcfg[port_id].total; i++, ipcfg++)
++              {
++                      if (ipcfg->ipaddr == ctrl.ipcfg.entry.ipaddr)
++                      {
++                              NAT_IP_ENTRY_T *ipcfg_next;
++                              ipcfg_next = ipcfg + 1;
++                              for (j=i+1; j < nat_cfg.ipcfg[port_id].total; i++, j++)
++                              {
++                                      memcpy((void *)ipcfg, (void *)ipcfg_next, sizeof(NAT_IP_ENTRY_T));
++                                      ipcfg++;
++                                      ipcfg_next++;
++                              }
++                              ipcfg->ipaddr = 0;
++                              ipcfg->netmask = 0;
++                              nat_cfg.ipcfg[port_id].total--;
++                              return 0;
++                      }
++              }
++              return -ENOENT;
++      case NATGETIP:
++              if (nat_hdr.len != sizeof(NAT_IPCFG_ALL_T))
++                      return -EPERM;
++              if (copy_to_user(req_datap, (void *)&nat_cfg.ipcfg[port_id], sizeof(NAT_IPCFG_ALL_T)))
++                      return -EFAULT;
++              break;
++      case NATAXPORT:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_XPORT_T))
++                      return -EPERM;
++              i = nat_cfg.xport.total;
++              if (i >= CONFIG_NAT_MAX_XPORT)
++                      return -E2BIG;
++              if (copy_from_user((void *)&nat_cfg.xport.entry[i], req_datap, sizeof(NAT_XPORT_T)))
++                      return -EFAULT;
++              nat_cfg.xport.total++;
++              break;
++      case NATDXPORT:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_XPORT_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&ctrl.xport, req_datap, sizeof(NAT_XPORT_T)))
++                      return -EFAULT;
++              xport_entry = (NAT_XPORT_ENTRY_T *)&nat_cfg.xport.entry[0];
++              for (i=0; i<nat_cfg.xport.total; i++, xport_entry++)
++              {
++                      if (memcmp((void *)xport_entry, (void *)&ctrl.xport, sizeof(NAT_XPORT_ENTRY_T)) == 0)
++                      {
++                              NAT_XPORT_ENTRY_T *xport_next;
++                              xport_next = xport_entry + 1;
++                              for (j=i+1; j < nat_cfg.xport.total; i++, j++)
++                              {
++                                      memcpy((void *)xport_entry, (void *)xport_next, sizeof(NAT_XPORT_ENTRY_T));
++                                      xport_entry++;
++                                      xport_next++;
++                              }
++                              memset((void *)xport_entry, 0, sizeof(NAT_XPORT_ENTRY_T));
++                              nat_cfg.xport.total--;
++                              return 0;
++                      }
++              }
++              return -ENOENT;
++      case NATGXPORT:
++              if (nat_hdr.len != sizeof(NAT_XPORT_ALL_T))
++                      return -EPERM;
++              if (copy_to_user(req_datap, (void *)&nat_cfg.xport, sizeof(NAT_XPORT_ALL_T)))
++                      return -EFAULT;
++              break;
++      case NATSWEIGHT:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_WEIGHT_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&nat_cfg.weight, req_datap, sizeof(NAT_WEIGHT_T)))
++                      return -EFAULT;
++              mac_set_hw_tx_weight(dev, (char *)&nat_cfg.weight);
++              break;
++      case NATGWEIGHT:
++              if (nat_hdr.len != sizeof(NAT_WEIGHT_T))
++                      return -EPERM;
++              mac_get_hw_tx_weight(dev, (char *)&nat_cfg.weight);
++              if (copy_to_user(req_datap, (void *)&nat_cfg.weight, sizeof(NAT_WEIGHT_T)))
++                      return -EFAULT;
++              break;
++      case NATAWRULE:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_WRULE_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&qid, req_datap, sizeof(qid)))
++                      return -EFAULT;
++              if (qid > CONFIG_NAT_TXQ_NUM)
++                      return -EPERM;
++              i = nat_cfg.wrule[qid].total;
++              if (i >= CONFIG_NAT_MAX_WRULE)
++                      return -E2BIG;
++              if (copy_from_user((void *)&nat_cfg.wrule[qid].entry[i], req_datap+sizeof(qid), sizeof(NAT_WRULE_T)))
++                      return -EFAULT;
++              nat_cfg.wrule[qid].total++;
++              break;
++      case NATDWRULE:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_WRULE_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&ctrl.wrule, req_datap, sizeof(NAT_WRULE_T)))
++                      return -EFAULT;
++              qid = ctrl.wrule.qid;
++              if (qid >= CONFIG_NAT_TXQ_NUM)
++                      return -EPERM;
++              wrule_entry = (NAT_WRULE_ENTRY_T *)&nat_cfg.wrule[qid].entry[0];
++              for (i=0; i<nat_cfg.wrule[qid].total; i++, wrule_entry++)
++              {
++                      if (memcmp((void *)wrule_entry, (void *)&ctrl.wrule.entry, sizeof(NAT_WRULE_ENTRY_T)) == 0)
++                      {
++                              NAT_WRULE_ENTRY_T *wrule_next;
++                              wrule_next = wrule_entry + 1;
++                              for (j=i+1; j < nat_cfg.wrule[qid].total; i++, j++)
++                              {
++                                      memcpy((void *)wrule_entry, (void *)wrule_next, sizeof(NAT_WRULE_ENTRY_T));
++                                      wrule_entry++;
++                                      wrule_next++;
++                              }
++                              memset((void *)wrule_entry, 0, sizeof(NAT_WRULE_ENTRY_T));
++                              nat_cfg.wrule[qid].total--;
++                              return 0;
++                      }
++              }
++              return -ENOENT;
++      case NATGWRULE:
++              if (nat_hdr.len != sizeof(NAT_WRULE_ALL_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&qid, req_datap, sizeof(qid)))
++                      return -EFAULT;
++              if (qid >= CONFIG_NAT_TXQ_NUM)
++                      return -EPERM;
++              if (copy_to_user(req_datap, (void *)&nat_cfg.wrule[qid], sizeof(NAT_WRULE_ALL_T)))
++                      return -EFAULT;
++              break;
++      case NATSDEFQ:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_QUEUE_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&nat_cfg.default_hw_txq, req_datap, sizeof(u32)))
++                      return -EFAULT;
++              break;
++      case NATGDEFQ:
++              if (nat_hdr.len != sizeof(NAT_QUEUE_T))
++                      return -EPERM;
++              if (copy_to_user(req_datap, (void *)&nat_cfg.default_hw_txq, sizeof(u32)))
++                      return -EFAULT;
++      case NATRMIPCFG:
++              nat_cfg.ipcfg[port_id].total = 0;
++              break;
++      case NATTESTENTRY:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++              if (nat_hdr.len != sizeof(NAT_TESTENTRY_T))
++                      return -EPERM;
++              if (copy_from_user((void *)&ctrl.init_entry, req_datap, sizeof(ctrl.init_entry)))
++                      return -EFAULT;
++              if (ctrl.init_entry.init_enable != 0 && ctrl.init_entry.init_enable != 1)
++                      return -EPERM;
++              nat_cfg.init_enabled = ctrl.init_entry.init_enable;
++              break;
++
++      default:
++              return -EPERM;
++      }
++
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++*     nat_init_test_entry
++*     Initialize NAT test hash entries
++*
++*     SmartBits P1  -----> Lepus GMAC 0 --------------+
++*                                                                                                     |
++*                                                                                                     |
++*             P3  <----- Lepus GMAC 1 -- HW TxQ0 <--+
++*                                                                       -- HW TxQ1 <--+
++*                                                                       -- HW TxQ2 <--+
++*                                                                       -- HW TxQ3 <--+
++*
++*     SmartBits P1  <----- Lepus GMAC 0 -- HW TxQ0 <--+
++*                                                                       -- HW TxQ1 <--+
++*                                     -- HW TxQ2 <--+
++*                                                                       -- HW TxQ3 <--+
++*                                                                                                     |
++*                                                                                                     |
++*             P3  -----> Lepus GMAC 1 --------------+
++*
++*   LAN GMAC0 <--------------------------------------------> GMAC1 WAN
++*     192.168.[x].[y]:50 --> 168.95.[x].[y]:80 ---TXQ[y-1]---> 192.168.2.254:200[y] --> 168.95.[x].[y]:80
++*     192.168.[x].[y]:50 <-- 168.95.[x].[y]:80 <--TXQ[y-1]---- 192.168.2.254:200[y] <-- 168.95.[x].[y]:80
++*   where:
++*             [x] : Packet Type
++*             [y] : Tx Queue, 1 for TxQ0, 2 for TxQ1, 3 for TxQ2, 4 for TxQ3,
++*
++*
++* Packet Type:
++* 1. TCP Frames <---> TCP Frames
++*   LAN GMAC0 <--------------------------------> GMAC1 WAN
++*     192.168.1.1:50 --> 168.95.1.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.1.1:80
++*     192.168.1.1:50 <-- 168.95.1.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.1.1:80
++*
++*     192.168.1.2:50 --> 168.95.1.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.1.2:80
++*     192.168.1.2:50 <-- 168.95.1.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.1.2:80
++*
++*     192.168.1.3:50 --> 168.95.1.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.1.3:80
++*     192.168.1.3:50 <-- 168.95.1.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.1.3:80
++*
++*     192.168.1.4:50 --> 168.95.1.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.1.4:80
++*     192.168.1.4:50 <-- 168.95.1.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.1.4:80
++*
++* 2 TCP Frames <----> PPPoE + TCP Frames
++*   LAN GMAC0 <--------------------------------> GMAC1 WAN
++*     192.168.2.1:50 --> 168.95.2.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.2.1:80
++*     192.168.2.1:50 <-- 168.95.2.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.2.1:80
++*
++*     192.168.2.2:50 --> 168.95.2.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.2.2:80
++*     192.168.2.2:50 <-- 168.95.2.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.2.2:80
++*
++*     192.168.2.3:50 --> 168.95.2.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.2.3:80
++*     192.168.2.3:50 <-- 168.95.2.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.2.3:80
++*
++*     192.168.2.4:50 --> 168.95.2.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.2.4:80
++*     192.168.2.4:50 <-- 168.95.2.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.2.4:80
++*
++* 3 TCP Frames <----> VLAN + PPPoE + TCP Frames
++*   LAN GMAC0 <--------------------------------> GMAC1 WAN
++*     192.168.3.1:50 --> 168.95.3.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.3.1:80
++*     192.168.3.1:50 <-- 168.95.3.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.3.1:80
++*
++*     192.168.3.2:50 --> 168.95.3.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.3.2:80
++*     192.168.3.2:50 <-- 168.95.3.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.3.2:80
++*
++*     192.168.3.3:50 --> 168.95.3.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.3.3:80
++*     192.168.3.3:50 <-- 168.95.3.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.3.3:80
++*
++*     192.168.3.4:50 --> 168.95.3.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.3.4:80
++*     192.168.3.4:50 <-- 168.95.3.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.3.4:80
++*
++* 4 VLAN-A + TCP Frames <----> VLAN-B + PPPoE + TCP Frames
++*   LAN GMAC0 <--------------------------------> GMAC1 WAN
++*     192.168.4.1:50 --> 168.95.4.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.4.1:80
++*     192.168.4.1:50 <-- 168.95.4.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.4.1:80
++*
++*     192.168.4.2:50 --> 168.95.4.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.4.2:80
++*     192.168.4.2:50 <-- 168.95.4.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.4.2:80
++*
++*     192.168.4.3:50 --> 168.95.4.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.4.3:80
++*     192.168.4.3:50 <-- 168.95.4.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.4.3:80
++*
++*     192.168.4.4:50 --> 168.95.4.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.4.4:80
++*     192.168.4.4:50 <-- 168.95.4.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.4.4:80
++*
++*
++*
++*----------------------------------------------------------------------*/
++#ifdef SL351x_NAT_TEST_BY_SMARTBITS
++#define       NAT_IPIV(a,b,c,d)                       ((a<<24)+(b<<16)+(c<<8)+d)
++#define     NAT_TEST_CLIENT_IP                        NAT_IPIV(192,168,1,1)
++#define     NAT_TEST_SERVER_IP                        NAT_IPIV(168,95,1,1)
++#define               NAT_TEST_LAN_IP                         NAT_IPIV(192,168,1,254)
++#define               NAT_TEST_WAN_IP                         NAT_IPIV(192,168,2,254)
++#define     NAT_TEST_MAP_PORT_BASE            2001
++#define     NAT_TEST_SPORT                            50
++#define     NAT_TEST_DPORT                            80
++#define     NAT_TEST_PROTOCOL                 6
++u8                    nat_test_lan_target_da[6]={0x00,0x11,0x22,0x33,0x44,0x55};
++u8                    nat_test_wan_target_da[6]={0x00,0xaa,0xbb,0xcc,0xdd,0xee};
++u8                    nat_test_lan_my_da[6]={0x00,0x11,0x11,0x11,0x11,0x11};
++u8                    nat_test_wan_my_da[6]={0x00,0x22,0x22,0x22,0x22,0x22};
++static void nat_init_test_entry(void)
++{
++      int                             i, j ;
++      NAT_HASH_ENTRY_T        *hash_entry;
++      u32                                     sip, dip;
++      u32                                     hash_data[HASH_MAX_DWORDS];
++      NAT_CFG_T                       *cfg;
++      int                                     hash_index;
++
++      cfg = (NAT_CFG_T *)&nat_cfg;
++      hash_entry = (NAT_HASH_ENTRY_T *)&hash_data;
++      hash_entry->key.Ethertype       = 0;
++      hash_entry->key.rule_id         = 0;
++      hash_entry->key.ip_protocol = IPPROTO_TCP;
++      hash_entry->key.reserved1       = 0;
++      hash_entry->key.reserved2       = 0;
++      // hash_entry->key.sip          = NAT_TEST_CLIENT_IP;
++      // hash_entry->key.dip          = NAT_TEST_SERVER_IP;
++      hash_entry->key.sport           = htons(NAT_TEST_SPORT);
++      hash_entry->key.dport           = htons(NAT_TEST_DPORT);
++      hash_entry->key.rule_id = cfg->tcp_udp_rule_id;
++      hash_entry->action.dword = NAT_LAN2WAN_ACTIONS;
++
++      sip = NAT_TEST_CLIENT_IP;
++      dip = NAT_TEST_SERVER_IP;
++
++      // Init TCP <------> TCP hash entries
++      // LAN --> WAN
++      // (1) TCP --> TCP
++      // (2) TCP --> PPPoE + TCP
++      // (3) TCP --> VLAN-B + PPPoE + TCP
++      // (4) TCP + VLAN-A --> VLAN-B + PPPoE + TCP
++      memcpy(hash_entry->param.da, nat_test_wan_target_da, 6);
++      memcpy(hash_entry->param.sa, nat_test_wan_my_da, 6);
++      hash_entry->key.port_id = cfg->lan_port;
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              if (i < 2)
++              {
++                      hash_entry->action.bits.dest_qid = i+2;
++              }
++              else
++              {
++                      hash_entry->action.bits.dest_qid = i;
++              }
++              hash_entry->action.bits.dest_qid += (cfg->wan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
++              hash_entry->param.Sport = NAT_TEST_MAP_PORT_BASE+i;
++              hash_entry->param.Dport = NAT_TEST_DPORT;
++              for (j=0; j<4; j++)
++              {
++                      hash_entry->key.sip = sip + i + j*0x100;
++                      hash_entry->key.dip = dip + i + j*0x100;
++                      hash_entry->param.Dip = hash_entry->key.dip;
++                      hash_entry->param.Sip = NAT_TEST_WAN_IP;
++                      switch (j)
++                      {
++                      case 0:
++                              hash_entry->action.bits.pppoe = 0;
++                              hash_entry->param.pppoe = 0;
++                              hash_entry->action.bits.vlan = 0;
++                              hash_entry->param.vlan = 0;
++                              break;
++                      case 1:
++                              hash_entry->action.bits.pppoe = 1;
++                              hash_entry->param.pppoe = i+1;
++                              hash_entry->action.bits.vlan = 0;
++                              hash_entry->param.vlan = 0;
++                              break;
++                      case 2:
++                              hash_entry->action.bits.pppoe = 1;
++                              hash_entry->param.pppoe = i+1;
++                              hash_entry->action.bits.vlan = 1;
++                              hash_entry->param.vlan = i+10;
++                              break;
++                      case 3:
++                              hash_entry->action.bits.pppoe = 1;
++                              hash_entry->param.pppoe = i+1;
++                              hash_entry->action.bits.vlan = 1;
++                              hash_entry->param.vlan = i+10;
++                              break;
++                      }
++                      hash_entry->tmo.counter = hash_entry->tmo.interval = 0x7fff;
++                      hash_index = nat_build_keys(&hash_entry->key);
++                      nat_write_hash_entry(hash_index, hash_entry);
++                      hash_nat_enable_owner(hash_index);
++                      hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
++              }
++      }
++
++
++      // WAN --> LAN
++      hash_entry->key.port_id         = cfg->wan_port;
++      hash_entry->key.sport           = htons(NAT_TEST_DPORT);
++      hash_entry->key.dport           = htons(NAT_TEST_DPORT);
++      hash_entry->key.rule_id         = cfg->tcp_udp_rule_id;
++      hash_entry->action.dword        = NAT_WAN2LAN_ACTIONS;
++      hash_entry->key.sport           = htons(NAT_TEST_DPORT);
++      memcpy(hash_entry->param.da, nat_test_lan_target_da, 6);
++      memcpy(hash_entry->param.sa, nat_test_lan_my_da, 6);
++      for (i=0; i<TOE_HW_TXQ_NUM; i++)
++      {
++              hash_entry->key.dport = htons(NAT_TEST_MAP_PORT_BASE + i);
++              if (i < 2)
++              {
++                      hash_entry->action.bits.dest_qid = i+2;
++              }
++              else
++              {
++                      hash_entry->action.bits.dest_qid = i;
++              }
++              hash_entry->action.bits.dest_qid += (cfg->lan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
++              hash_entry->param.Dport = NAT_TEST_SPORT;
++              hash_entry->param.Sport = NAT_TEST_DPORT;
++              hash_entry->param.da[5] = i;
++              for (j=0; j<4; j++)
++              {
++                      hash_entry->key.sip = (dip + i + j*0x100);
++                      hash_entry->key.dip = (NAT_TEST_WAN_IP);
++                      hash_entry->param.Sip = hash_entry->key.sip;
++                      hash_entry->param.Dip = sip + i + j*0x100;
++                      switch (j)
++                      {
++                      case 0:
++                              hash_entry->action.bits.pppoe = 0;
++                              hash_entry->param.pppoe = 0;
++                              hash_entry->action.bits.vlan = 0;
++                              hash_entry->param.vlan = 0;
++                              break;
++                      case 1:
++                              hash_entry->action.bits.pppoe = 2;
++                              hash_entry->param.pppoe = i+1;
++                              hash_entry->action.bits.vlan = 0;
++                              hash_entry->param.vlan = 0;
++                              break;
++                      case 2:
++                              hash_entry->action.bits.pppoe = 2;
++                              hash_entry->param.pppoe = i+1;
++                              hash_entry->action.bits.vlan = 2;
++                              hash_entry->param.vlan = i+5;
++                              break;
++                      case 3:
++                              hash_entry->action.bits.pppoe = 1;
++                              hash_entry->param.pppoe = i+1;
++                              hash_entry->action.bits.vlan = 1;
++                              hash_entry->param.vlan = i+5;
++                              break;
++                      }
++                      hash_entry->tmo.counter = hash_entry->tmo.interval = 0x7fff;
++                      hash_index = nat_build_keys(&hash_entry->key);
++                      nat_write_hash_entry(hash_index, hash_entry);
++                      hash_nat_enable_owner(hash_index);
++                      hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
++              }
++      }
++}
++#endif        // SL351x_NAT_TEST_BY_SMARTBITS
++
++#endif // CONFIG_SL351x_NAT
++
+--- /dev/null
++++ b/drivers/net/sl351x_proc.c
+@@ -0,0 +1,578 @@
++/****************************************************************************
++* Copyright 2006 Storlink Corp.  All rights reserved.
++*----------------------------------------------------------------------------
++* Name                        : sl351x_proc.c
++* Description :
++*             Handle Proc Routines for Storlink SL351x Platform
++*
++* History
++*
++*     Date            Writer          Description
++*----------------------------------------------------------------------------
++*     04/13/2006      Gary Chen       Create and implement
++*
++*
++****************************************************************************/
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/compiler.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/completion.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/it8712.h>
++#include <linux/mtd/kvctl.h>
++#include <linux/skbuff.h>
++#include <linux/if_ether.h>
++#include <linux/if_pppox.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/ppp_defs.h>
++#ifdef CONFIG_NETFILTER
++// #include <linux/netfilter_ipv4/ip_conntrack.h>
++#endif
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/percpu.h>
++#ifdef CONFIG_SYSCTL
++#include <linux/sysctl.h>
++#endif
++
++#define        MIDWAY
++#define        SL_LEPUS
++
++// #define PROC_DEBUG_MSG     1
++
++#include <asm/arch/sl2312.h>
++#include <asm/arch/sl351x_gmac.h>
++#include <asm/arch/sl351x_hash_cfg.h>
++#include <asm/arch/sl351x_nat_cfg.h>
++#include <asm/arch/sl351x_toe.h>
++
++#ifdef CONFIG_PROC_FS
++/*----------------------------------------------------------------------
++* Definition
++*----------------------------------------------------------------------*/
++#define       proc_printf                                     printk
++#define SL351x_GMAC_PROC_NAME         "sl351x_gmac"
++#define SL351x_NAT_PROC_NAME          "sl351x_nat"
++#define SL351x_TOE_PROC_NAME          "sl351x_toe"
++
++/*----------------------------------------------------------------------
++* Function Definition
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static int nat_ct_open(struct inode *inode, struct file *file);
++static void *nat_ct_seq_start(struct seq_file *s, loff_t *pos);
++static void nat_ct_seq_stop(struct seq_file *s, void *v);
++static void *nat_ct_seq_next(struct seq_file *s, void *v, loff_t *pos);
++static int nat_ct_seq_show(struct seq_file *s, void *v);
++#endif
++
++#ifdef CONFIG_SL351x_RXTOE
++static int toe_ct_open(struct inode *inode, struct file *file);
++static void *toe_ct_seq_start(struct seq_file *s, loff_t *pos);
++static void toe_ct_seq_stop(struct seq_file *s, void *v);
++static void *toe_ct_seq_next(struct seq_file *s, void *v, loff_t *pos);
++static int toe_ct_seq_show(struct seq_file *s, void *v);
++extern int sl351x_get_toe_conn_flag(int index);
++extern struct toe_conn * sl351x_get_toe_conn_info(int index);
++#endif
++
++static int gmac_ct_open(struct inode *inode, struct file *file);
++static void *gmac_ct_seq_start(struct seq_file *s, loff_t *pos);
++static void gmac_ct_seq_stop(struct seq_file *s, void *v);
++static void *gmac_ct_seq_next(struct seq_file *s, void *v, loff_t *pos);
++static int gmac_ct_seq_show(struct seq_file *s, void *v);
++
++
++/*----------------------------------------------------------------------
++* Data
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SYSCTL
++// static struct ctl_table_header *nat_ct_sysctl_header;
++#endif
++
++#ifdef CONFIG_SL351x_NAT
++static struct seq_operations nat_ct_seq_ops = {
++      .start = nat_ct_seq_start,
++      .next  = nat_ct_seq_next,
++      .stop  = nat_ct_seq_stop,
++      .show  = nat_ct_seq_show
++};
++
++static struct file_operations nat_file_ops= {
++      .owner   = THIS_MODULE,
++      .open    = nat_ct_open,
++      .read    = seq_read,
++      .llseek  = seq_lseek,
++      .release = seq_release
++};
++#endif // CONFIG_SL351x_NAT
++
++#ifdef CONFIG_SL351x_RXTOE
++static struct seq_operations toe_ct_seq_ops = {
++      .start = toe_ct_seq_start,
++      .next  = toe_ct_seq_next,
++      .stop  = toe_ct_seq_stop,
++      .show  = toe_ct_seq_show
++};
++
++static struct file_operations toe_file_ops= {
++      .owner   = THIS_MODULE,
++      .open    = toe_ct_open,
++      .read    = seq_read,
++      .llseek  = seq_lseek,
++      .release = seq_release
++};
++#endif
++
++static struct seq_operations gmac_ct_seq_ops = {
++      .start = gmac_ct_seq_start,
++      .next  = gmac_ct_seq_next,
++      .stop  = gmac_ct_seq_stop,
++      .show  = gmac_ct_seq_show
++};
++
++static struct file_operations gmac_file_ops= {
++      .owner   = THIS_MODULE,
++      .open    = gmac_ct_open,
++      .read    = seq_read,
++      .llseek  = seq_lseek,
++      .release = seq_release
++};
++
++#ifdef SL351x_GMAC_WORKAROUND
++extern u32 gmac_workaround_cnt[4];
++extern u32 gmac_short_frame_workaround_cnt[2];
++#ifdef CONFIG_SL351x_NAT
++      extern u32 sl351x_nat_workaround_cnt;
++#endif
++#endif
++/*----------------------------------------------------------------------
++* nat_ct_open
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static int nat_ct_open(struct inode *inode, struct file *file)
++{
++      return seq_open(file, &nat_ct_seq_ops);
++}
++#endif // CONFIG_SL351x_NAT
++/*----------------------------------------------------------------------
++* nat_ct_seq_start
++* find the first
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static void *nat_ct_seq_start(struct seq_file *s, loff_t *pos)
++{
++      int i;
++
++      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
++      for (i=*pos; i<HASH_TOTAL_ENTRIES; i++)
++      {
++              if (hash_get_nat_owner_flag(i))
++              {
++                      *pos = i;
++                      return (void *)(i+1);
++              }
++      }
++      return NULL;
++}
++#endif // CONFIG_SL351x_NAT
++/*----------------------------------------------------------------------
++* nat_ct_seq_stop
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static void nat_ct_seq_stop(struct seq_file *s, void *v)
++{
++}
++#endif // CONFIG_SL351x_NAT
++/*----------------------------------------------------------------------
++* nat_ct_seq_next
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static void *nat_ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
++{
++      int i;
++
++      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
++      (*pos)++;
++      for (i=*pos; i<HASH_TOTAL_ENTRIES; i++)
++      {
++              if (hash_get_nat_owner_flag(i))
++              {
++                      *pos = i;
++                      return (void *)(i+1);
++              }
++      }
++      return NULL;
++}
++#endif // CONFIG_SL351x_NAT
++/*----------------------------------------------------------------------
++* nat_ct_seq_show
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_NAT
++static int nat_ct_seq_show(struct seq_file *s, void *v)
++{
++      int                             idx;
++      NAT_HASH_ENTRY_T        *nat_entry;
++      GRE_HASH_ENTRY_T        *gre_entry;
++
++      idx = (int)v;
++      if (idx<=0 || idx >HASH_TOTAL_ENTRIES)
++              return -ENOSPC;
++
++      idx--;
++      nat_entry = (NAT_HASH_ENTRY_T *)&hash_tables[idx];
++      gre_entry = (GRE_HASH_ENTRY_T *)nat_entry;
++      if (nat_entry->key.ip_protocol == IPPROTO_GRE)
++      {
++              if (seq_printf(s, "%4d: KEY MAC-%d [%d] %u.%u.%u.%u [%u]-->%u.%u.%u.%u\n",
++                                      idx, gre_entry->key.port_id, gre_entry->key.ip_protocol,
++                                      HIPQUAD(gre_entry->key.sip), ntohs(gre_entry->key.call_id),
++                                      HIPQUAD(gre_entry->key.dip)))
++                      return -ENOSPC;
++              if (seq_printf(s, "      PARAMETER: %u.%u.%u.%u -->%u.%u.%u.%u [%u] Timeout:%ds\n",
++                                      HIPQUAD(gre_entry->param.Sip),
++                                      HIPQUAD(gre_entry->param.Dip), gre_entry->param.Dport,
++                                      gre_entry->tmo.counter))
++                      return -ENOSPC;
++      }
++      else
++      {
++              if (seq_printf(s, "%4d: KEY MAC-%d [%d] %u.%u.%u.%u [%u]-->%u.%u.%u.%u [%u]\n",
++                                      idx, nat_entry->key.port_id, nat_entry->key.ip_protocol,
++                                      HIPQUAD(nat_entry->key.sip), ntohs(nat_entry->key.sport),
++                                      HIPQUAD(nat_entry->key.dip), ntohs(nat_entry->key.dport)))
++                      return -ENOSPC;
++              if (seq_printf(s, "      PARAMETER: %u.%u.%u.%u [%u]-->%u.%u.%u.%u [%u] Timeout:%ds\n",
++                                      HIPQUAD(nat_entry->param.Sip), nat_entry->param.Sport,
++                                      HIPQUAD(nat_entry->param.Dip), nat_entry->param.Dport,
++                                      nat_entry->tmo.counter))
++                      return -ENOSPC;
++      }
++      return 0;
++}
++#endif // CONFIG_SL351x_NAT
++
++/*----------------------------------------------------------------------
++* toe_ct_open
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_RXTOE
++static int toe_ct_open(struct inode *inode, struct file *file)
++{
++      return seq_open(file, &toe_ct_seq_ops);
++}
++#endif
++/*----------------------------------------------------------------------
++* toe_ct_seq_start
++* find the first
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_RXTOE
++static void *toe_ct_seq_start(struct seq_file *s, loff_t *pos)
++{
++      int i;
++
++      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
++      for (i=*pos; i<TOE_TOE_QUEUE_NUM; i++)
++      {
++              if (sl351x_get_toe_conn_flag(i))
++              {
++                      *pos = i;
++                      return (void *)(i+1);
++              }
++      }
++      return NULL;
++}
++#endif
++/*----------------------------------------------------------------------
++* toe_ct_seq_stop
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_RXTOE
++static void toe_ct_seq_stop(struct seq_file *s, void *v)
++{
++}
++#endif
++/*----------------------------------------------------------------------
++* toe_ct_seq_next
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_RXTOE
++static void *toe_ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
++{
++      int i;
++
++      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
++      (*pos)++;
++      for (i=*pos; i<TOE_TOE_QUEUE_NUM; i++)
++      {
++              if (sl351x_get_toe_conn_flag(i))
++              {
++                      *pos = i;
++                      return (void *)(i+1);
++              }
++      }
++      return NULL;
++}
++#endif
++/*----------------------------------------------------------------------
++* toe_ct_seq_show
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_SL351x_RXTOE
++static int toe_ct_seq_show(struct seq_file *s, void *v)
++{
++      int                             idx;
++      struct toe_conn         *toe_entry;
++
++      idx = (int)v;
++      if (idx<=0 || idx >TOE_TOE_QUEUE_NUM)
++              return -ENOSPC;
++
++      idx--;
++      toe_entry = (struct toe_conn *)sl351x_get_toe_conn_info(idx);
++      if (!toe_entry)
++              return -ENOSPC;
++
++      if (seq_printf(s, "%4d: Qid %d MAC-%d TCP %u.%u.%u.%u [%u]-->%u.%u.%u.%u [%u]\n",
++                              idx, toe_entry->qid, toe_entry->gmac->port_id,
++                              NIPQUAD(toe_entry->saddr[0]), ntohs(toe_entry->source),
++                              NIPQUAD(toe_entry->daddr[0]), ntohs(toe_entry->dest)))
++                      return -ENOSPC;
++      return 0;
++}
++#endif
++/*----------------------------------------------------------------------
++* gmac_ct_open
++*----------------------------------------------------------------------*/
++static int gmac_ct_open(struct inode *inode, struct file *file)
++{
++      return seq_open(file, &gmac_ct_seq_ops);
++}
++
++/*----------------------------------------------------------------------
++* gmac_ct_seq_start
++* find the first
++*----------------------------------------------------------------------*/
++static void *gmac_ct_seq_start(struct seq_file *s, loff_t *pos)
++{
++      int i;
++      i = (int)*pos + 1;;
++
++      if (i > 9)
++              return NULL;
++      else
++              return (void *)i;
++}
++
++/*----------------------------------------------------------------------
++* gmac_ct_seq_stop
++*----------------------------------------------------------------------*/
++static void gmac_ct_seq_stop(struct seq_file *s, void *v)
++{
++}
++
++/*----------------------------------------------------------------------
++* gmac_ct_seq_next
++*----------------------------------------------------------------------*/
++static void *gmac_ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
++{
++      int i;
++
++      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
++
++      (*pos)++;
++      i = (int)*pos + 1;;
++
++      if (i > 9)
++              return NULL;
++      else
++              return (void *)i;
++}
++
++/*----------------------------------------------------------------------
++* seq_dm_long
++*----------------------------------------------------------------------*/
++static void seq_dm_long(struct seq_file *s, u32 location, int length)
++{
++      u32             *start_p, *curr_p, *end_p;
++      u32             *datap, data;
++      int             i;
++
++      //if (length > 1024)
++      //      length = 1024;
++
++      start_p = (u32 *)location;
++      end_p = (u32 *)location + length;
++      curr_p = (u32 *)((u32)location & 0xfffffff0);
++      datap = (u32 *)location;
++      while (curr_p < end_p)
++      {
++              cond_resched();
++              seq_printf(s, "0x%08x: ",(u32)curr_p & 0xfffffff0);
++              for (i=0; i<4; i++)
++              {
++                      if (curr_p < start_p || curr_p >= end_p)
++               seq_printf(s, "         ");
++                      else
++                      {
++                              data = *datap;
++                              seq_printf(s, "%08X ", data);
++                      }
++                      if (i==1)
++              seq_printf(s, "- ");
++
++                      curr_p++;
++                      datap++;
++              }
++        seq_printf(s, "\n");
++      }
++}
++
++/*----------------------------------------------------------------------
++* gmac_ct_seq_show
++*----------------------------------------------------------------------*/
++static int gmac_ct_seq_show(struct seq_file *s, void *v)
++{
++      switch ((int)v)
++      {
++              case 1:
++                      seq_printf(s, "\nGMAC Global Registers\n");
++                      seq_dm_long(s, TOE_GLOBAL_BASE, 32);
++                      break;
++              case 2:
++                      seq_printf(s, "\nGMAC Non-TOE Queue Header\n");
++                      seq_dm_long(s, TOE_NONTOE_QUE_HDR_BASE, 12);
++                      break;
++              case 3:
++                      seq_printf(s, "\nGMAC TOE Queue Header\n");
++                      seq_dm_long(s, TOE_TOE_QUE_HDR_BASE, 12);
++                      break;
++              case 4:
++                      seq_printf(s, "\nGMAC-0 DMA Registers\n");
++                      seq_dm_long(s, TOE_GMAC0_DMA_BASE, 52);
++                      break;
++              case 5:
++                      seq_printf(s, "\nGMAC-0 Registers\n");
++                      seq_dm_long(s, TOE_GMAC0_BASE, 32);
++                      break;
++              case 6:
++                      seq_printf(s, "\nGMAC-1 DMA Registers\n");
++                      seq_dm_long(s, TOE_GMAC1_DMA_BASE, 52);
++                      break;
++              case 7:
++                      seq_printf(s, "\nGMAC-1 Registers\n");
++                      seq_dm_long(s, TOE_GMAC1_BASE, 32);
++                      break;
++              case 8:
++                      seq_printf(s, "\nGLOBAL Registers\n");
++                      seq_dm_long(s, GMAC_GLOBAL_BASE_ADDR, 16);
++                      break;
++              case 9:
++#ifdef SL351x_GMAC_WORKAROUND
++                      seq_printf(s, "\nGMAC-0 Rx/Tx/Short Workaround: %u, %u, %u\n", gmac_workaround_cnt[0], gmac_workaround_cnt[1], gmac_short_frame_workaround_cnt[0]);
++                      seq_printf(s, "GMAC-1 Rx/Tx/Short Workaround: %u, %u, %u\n", gmac_workaround_cnt[2], gmac_workaround_cnt[3], gmac_short_frame_workaround_cnt[1]);
++#ifdef CONFIG_SL351x_NAT
++                      seq_printf(s, "NAT Workaround: %u\n", sl351x_nat_workaround_cnt);
++#endif
++#endif
++                      break;
++              default:
++                      return -ENOSPC;
++      }
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++* init
++*----------------------------------------------------------------------*/
++static int __init init(void)
++{
++      struct proc_dir_entry *proc_gmac=NULL;
++
++#ifdef CONFIG_SL351x_NAT
++      struct proc_dir_entry *proc_nat=NULL;
++#endif
++
++#ifdef CONFIG_SL351x_RXTOE
++      struct proc_dir_entry *proc_toe=NULL;
++#endif
++
++#ifdef CONFIG_SYSCTL
++      // nat_ct_sysctl_header = NULL;
++#endif
++      proc_gmac = proc_net_fops_create(SL351x_GMAC_PROC_NAME, 0440, &gmac_file_ops);
++      if (!proc_gmac) goto init_bad;
++
++#ifdef CONFIG_SL351x_NAT
++      proc_nat = proc_net_fops_create(SL351x_NAT_PROC_NAME, 0440, &nat_file_ops);
++      if (!proc_nat) goto init_bad;
++#endif // CONFIG_SL351x_NAT
++
++#ifdef CONFIG_SL351x_RXTOE
++      proc_toe = proc_net_fops_create(SL351x_TOE_PROC_NAME, 0440, &toe_file_ops);
++      if (!proc_toe) goto init_bad;
++#endif
++
++#ifdef CONFIG_SYSCTL
++      // nat_ct_sysctl_header = register_sysctl_table(nat_ct_net_table, 0);
++      // if (!nat_ct_sysctl_header) goto init_bad;
++#endif
++
++      return 0;
++
++init_bad:
++      if (proc_gmac) proc_net_remove(SL351x_GMAC_PROC_NAME);
++
++#ifdef CONFIG_SL351x_NAT
++      if (proc_nat) proc_net_remove(SL351x_NAT_PROC_NAME);
++#endif
++
++#ifdef CONFIG_SL351x_RXTOE
++      if (proc_toe) proc_net_remove(SL351x_NAT_PROC_NAME);
++#endif
++
++#ifdef CONFIG_SYSCTL
++      // if (nat_ct_sysctl_header) unregister_sysctl_table(nat_ct_sysctl_header);
++#endif
++      proc_printf("SL351x NAT Proc: can't create proc or register sysctl.\n");
++      return -ENOMEM;
++}
++
++/*----------------------------------------------------------------------
++* fini
++*----------------------------------------------------------------------*/
++static void __exit fini(void)
++{
++      proc_net_remove(SL351x_GMAC_PROC_NAME);
++
++#ifdef CONFIG_SL351x_NAT
++      proc_net_remove(SL351x_NAT_PROC_NAME);
++#endif
++
++#ifdef CONFIG_SL351x_RXTOE
++      proc_net_remove(SL351x_TOE_PROC_NAME);
++#endif
++
++#ifdef CONFIG_SYSCTL
++      // unregister_sysctl_table(nat_ct_sysctl_header);
++#endif
++}
++
++/*----------------------------------------------------------------------
++* module
++*----------------------------------------------------------------------*/
++module_init(init);
++module_exit(fini);
++
++#endif        // CONFIG_PROC_FS
+--- /dev/null
++++ b/drivers/net/sl351x_toe.c
+@@ -0,0 +1,1083 @@
++/**************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
++*--------------------------------------------------------------------------
++* Name                        : sl351x_toe.c
++* Description :
++*             Provide TOE routines for SL351x
++*
++* History
++*
++*     Date            Writer          Description
++*----------------------------------------------------------------------------
++*                             Xiaochong
++*
++****************************************************************************/
++
++#include <linux/pci.h>
++#include <linux/ip.h>
++#include <linux/ipv6.h>
++#include <linux/tcp.h>
++#include <linux/slab.h>
++#include <linux/etherdevice.h>
++#include <asm/io.h>
++#include <linux/sysctl_storlink.h>
++#include <net/tcp.h>
++#include <linux/if_ether.h>
++#include <asm/arch/sl351x_gmac.h>
++#include <asm/arch/sl351x_toe.h>
++#include <asm/arch/sl351x_hash_cfg.h>
++#include <asm/arch/sl351x_nat_cfg.h>
++
++static int in_toe_isr;
++static int toe_initialized=0;
++
++static struct toe_conn        toe_connections[TOE_TOE_QUEUE_NUM];
++EXPORT_SYMBOL(toe_connections);
++static __u32 toe_connection_bits[TOE_TOE_QUEUE_NUM/32] __attribute__ ((aligned(16)));
++struct sk_buff* gen_pure_ack(struct toe_conn* connection, TOE_QHDR_T* toe_qhdr, INTR_QHDR_T *intr_curr_desc);
++
++extern struct storlink_sysctl storlink_ctl;
++extern TOE_INFO_T toe_private_data;
++extern spinlock_t gmac_fq_lock;
++extern void mac_write_dma_reg(int mac, unsigned int offset, u32 data);
++extern int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2);
++extern int hash_add_toe_entry(HASH_ENTRY_T *entry);
++extern void toe_gmac_fill_free_q(void);
++
++#define _DEBUG_SKB_           1
++#ifdef _DEBUG_SKB_
++/*---------------------------------------------------------------------------
++ * _debug_skb
++ *-------------------------------------------------------------------------*/
++static inline void _debug_skb(struct sk_buff *skb, GMAC_RXDESC_T *toe_curr_desc, u32 data)
++{
++      if ((u32)skb < 0x1000)
++      {
++              printk("%s skb=%x\n", __func__, (u32)skb);
++              while(1);
++      }
++      REG32(__va(toe_curr_desc->word2.buf_adr)-SKB_RESERVE_BYTES) = data;
++}
++#else
++#define _debug_skb(x, y, z)
++#endif
++
++/*---------------------------------------------------------------------------
++ * get_connection_seq_num
++ *-------------------------------------------------------------------------*/
++u32 get_connection_seq_num(unsigned short qid)
++{
++      TOE_QHDR_T      *toe_qhdr;
++
++      toe_qhdr = (TOE_QHDR_T*)TOE_TOE_QUE_HDR_BASE;
++      toe_qhdr += qid;
++      return (u32)toe_qhdr->word3.seq_num;
++}
++EXPORT_SYMBOL(get_connection_seq_num);
++
++/*---------------------------------------------------------------------------
++ * get_connection_ack_num
++ *-------------------------------------------------------------------------*/
++u32 get_connection_ack_num(unsigned short qid)
++{
++      TOE_QHDR_T      *toe_qhdr;
++
++      toe_qhdr = (TOE_QHDR_T*)TOE_TOE_QUE_HDR_BASE;
++      toe_qhdr += qid;
++      return (u32)toe_qhdr->word4.ack_num;
++}
++EXPORT_SYMBOL(get_connection_ack_num);
++
++/*---------------------------------------------------------------------------
++ * dump_toe_qhdr
++ *-------------------------------------------------------------------------*/
++void dump_toe_qhdr(TOE_QHDR_T *toe_qhdr)
++{
++      printk("TOE w1 %x, w2 %x, w3 %x\n", toe_qhdr->word1.bits32,
++              toe_qhdr->word2.bits32, toe_qhdr->word3.bits32);
++      printk("w4 %x, w5 %x, w6 %x\n", toe_qhdr->word4.bits32,
++              toe_qhdr->word5.bits32, toe_qhdr->word6.bits32);
++}
++
++/*---------------------------------------------------------------------------
++ * dump_intrq_desc
++ *-------------------------------------------------------------------------*/
++void dump_intrq_desc(INTR_QHDR_T *intr_curr_desc)
++{
++      printk("INTR w0 %x, w1 %x, seq %x\n", intr_curr_desc->word0.bits32,
++              intr_curr_desc->word1.bits32, intr_curr_desc->word2.bits32);
++      printk("ack %x, w4 %x\n", intr_curr_desc->word3.bits32,
++              intr_curr_desc->word4.bits32);
++}
++
++/*---------------------------------------------------------------------------
++ * This routine will initialize a TOE matching rule
++ * called by SL351x GMAC driver.
++ *-------------------------------------------------------------------------*/
++void sl351x_toe_init(void)
++{
++      GMAC_MRxCR0_T   mrxcr0;
++      GMAC_MRxCR1_T   mrxcr1;
++      GMAC_MRxCR2_T   mrxcr2;
++      int     rule, rc;
++
++      if (toe_initialized)
++              return;
++
++      toe_initialized = 1;
++
++#ifndef CONFIG_SL351x_NAT
++      mrxcr0.bits32 = 0;
++      mrxcr1.bits32 = 0;
++      mrxcr2.bits32 = 0;
++      mrxcr0.bits.l3 = 1;
++      mrxcr0.bits.l4 = 1;
++      mrxcr1.bits.sip = 1;
++      mrxcr1.bits.dip = 1;
++      mrxcr1.bits.l4_byte0_15 = 0x0f;
++      mrxcr0.bits.sprx = 1;
++      rule = 0;
++      rc = mac_set_rule_reg(0, rule, 1, mrxcr0.bits32, mrxcr1.bits32,
++                                              mrxcr2.bits32);
++      if (rc<0) {
++              printk("%s::Set MAC 0 rule fail!\n", __func__);
++      }
++      rc = mac_set_rule_reg(1, rule, 1, mrxcr0.bits32, mrxcr1.bits32,
++                                              mrxcr2.bits32);
++      if (rc<0) {
++              printk("%s::Set MAC 1 rule fail!\n", __func__);
++      }
++#endif // CONFIG_SL351x_NAT
++}
++
++/*---------------------------------------------------------------------------
++ * dump_intrq_desc
++ * assign an interrupt queue number to a give tcp queue
++ *-------------------------------------------------------------------------*/
++int get_interrupt_queue_id(int tcp_qid)
++{
++      return (int)(tcp_qid & 0x0003);
++}
++
++/*---------------------------------------------------------------------------
++ * reset_connection_index
++ * reset the connection bit by given index
++ *-------------------------------------------------------------------------*/
++void reset_connection_index(__u8 index)
++{
++      __u32 mask = ~(0xffffffff & (1<< (index&0x1f)));
++      toe_connection_bits[index>>5] = toe_connection_bits[index>>5] & mask;
++}
++
++/*---------------------------------------------------------------------------
++ * update_timer
++ *-------------------------------------------------------------------------*/
++void update_timer(struct toe_conn* connection)
++{
++//    if (time_before(jiffies, connection->last_rx_jiffies+3))
++//    if ((jiffies + 0xffffffff - connection->last_rx_jiffies) & 0x3)
++//    if (connection->last_rx_jiffies > jiffies)
++//            printk("%s::jif %g, last_rx_jif %g\n", __func__, jiffies, connection->last_rx_jiffies);
++/*    if ((long)(jiffies + 2)< 3) { // overflow...
++              printk("%s::jiffies %x\n", __func__, jiffies);
++      } */
++//    if ((long)(jiffies - connection->last_rx_jiffies)< 2)
++//            return;
++      connection->last_rx_jiffies = jiffies;
++      // gary chen mod_timer(&connection->rx_timer, jiffies+2);
++      connection->rx_timer.expires = jiffies + 2;
++      add_timer(&connection->rx_timer);
++//    printk("%s::nt %x, lj %x\n", __func__, (jiffies+2), connection->last_rx_jiffies);
++}
++
++/*---------------------------------------------------------------------------
++ * gen_pure_ack
++ *-------------------------------------------------------------------------*/
++struct sk_buff* gen_pure_ack(struct toe_conn* connection, TOE_QHDR_T* toe_qhdr,
++INTR_QHDR_T *intr_curr_desc)
++{
++      struct sk_buff  *skb;
++      struct iphdr    *ip_hdr;
++      struct tcphdr   *tcp_hdr;
++      struct ethhdr   *eth_hdr;
++
++      if ((skb= dev_alloc_skb(RX_BUF_SIZE))==NULL) {
++              printk("%s::alloc pure ack fail!\n", __func__);
++              return NULL;
++      }
++      skb_reserve(skb, RX_INSERT_BYTES);
++      memset(skb->data, 0, 60);
++
++      eth_hdr = (struct ethhdr*)&(skb->data[0]);
++      memcpy(eth_hdr, &connection->l2_hdr, sizeof(struct ethhdr));
++
++      ip_hdr = (struct iphdr*)&(skb->data[14]);
++      ip_hdr->version = connection->ip_ver;
++      ip_hdr->ihl = 20>>2;
++      ip_hdr->tot_len = ntohs(40);
++      ip_hdr->frag_off = htons(IP_DF);
++      ip_hdr->ttl = 128;
++      ip_hdr->protocol = 0x06;
++      ip_hdr->saddr = connection->saddr[0];
++      ip_hdr->daddr = connection->daddr[0];
++//    printk("%s ip sa %x, da %x\n",
++//            __func__, ntohl(ip_hdr->saddr), ntohl(ip_hdr->daddr));
++
++      tcp_hdr = (struct tcphdr*)&(skb->data[34]);
++      tcp_hdr->source = connection->source;
++      tcp_hdr->dest = connection->dest;
++      if (intr_curr_desc) {
++              tcp_hdr->seq = htonl(intr_curr_desc->word2.seq_num);
++              tcp_hdr->ack_seq = htonl(intr_curr_desc->word3.ack_num);
++              tcp_hdr->window = htons(intr_curr_desc->word0.bits.win_size);
++      } else {
++              tcp_hdr->seq = htonl(toe_qhdr->word3.seq_num);
++              tcp_hdr->ack_seq = htonl(toe_qhdr->word4.ack_num);
++              tcp_hdr->window = htons(toe_qhdr->word6.bits.WinSize);
++      }
++      tcp_hdr->ack = 1;
++      tcp_hdr->doff = 20 >> 2;
++#if 0
++      if (!intr_curr_desc) {
++              unsigned char byte;
++              for (i=0; i<20; i++) {
++                      byte = skb->data[34+i];
++                      printk("%x ", byte);
++              }
++              printk("\n");
++      }
++#endif
++      TCP_SKB_CB(skb)->connection = connection;
++      return skb;
++}
++
++/*---------------------------------------------------------------------------
++ * connection_rx_timer
++ *-------------------------------------------------------------------------*/
++void connection_rx_timer(unsigned long *data)
++{
++      struct toe_conn *connection = (struct toe_conn*)data;
++      unsigned int    tcp_qid, toeq_wptr;
++      unsigned int    pkt_size, desc_count;
++      struct sk_buff  *skb;
++      GMAC_RXDESC_T   *toe_curr_desc;
++      TOE_QHDR_T      *toe_qhdr;
++      struct net_device       *dev;
++      unsigned long   conn_flags;
++      DMA_RWPTR_T             toeq_rwptr;
++      unsigned short  timeout_descs;
++
++      if (in_toe_isr)
++              printk("%s::in_toe_isr=%d!\n", __func__, in_toe_isr);
++
++      if (connection) {
++              /* should we disable gmac interrupt first? */
++              if (!connection->gmac)
++                      printk("%s::conn gmac %x!\n", __func__, (u32)connection->gmac);
++              local_irq_save(conn_flags);
++              if (!spin_trylock(&connection->conn_lock)) {
++                      local_irq_restore(conn_flags);
++                      // timer should be updated by the toeq isr. So no need to update here.
++                      printk("%s::conn_lock is held by ISR!\n", __func__);
++                      return;
++              }
++              disable_irq(connection->gmac->irq);
++
++              /* disable hash entry and get toeq desc. */
++              hash_set_valid_flag(connection->hash_entry_index, 0);
++              do{} while(0);  /* wait until HW finish */
++
++              dev = connection->dev;
++              if (!dev)
++                      printk("%s::conn dev NULL!\n", __func__);
++              tcp_qid = connection->qid;
++              toe_qhdr = (TOE_QHDR_T *)(TOE_TOE_QUE_HDR_BASE +
++                            tcp_qid * sizeof(TOE_QHDR_T));
++              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
++              toeq_wptr = toe_qhdr->word1.bits.wptr;
++              timeout_descs = toeq_wptr - toeq_rwptr.bits.rptr;
++
++              if (toeq_rwptr.bits.rptr == toeq_wptr) {
++                      if (toe_qhdr->word5.bits32) {
++                              // shall we check toe_qhdr->word2.bits?
++                              skb = gen_pure_ack(connection, toe_qhdr, (INTR_QHDR_T *)NULL);
++                              skb_put(skb, 54);
++                              skb->dev = connection->dev;
++                              skb->ip_summed = CHECKSUM_UNNECESSARY;
++                              skb->protocol = eth_type_trans(skb, connection->dev);
++                              netif_rx(skb);
++                              connection->dev->last_rx = jiffies;
++                      }
++              } else {
++                      while (toeq_rwptr.bits.rptr != toeq_rwptr.bits.wptr) {
++                              /* we just simply send those packets to tcp? */
++                              toe_curr_desc = (GMAC_RXDESC_T*)(toe_private_data.toe_desc_base[tcp_qid]
++                                      + toeq_rwptr.bits.rptr * sizeof(GMAC_RXDESC_T));
++                              connection->curr_desc = toe_curr_desc;
++                              if (toe_curr_desc->word3.bits.ctrl_flag) {
++                                      printk("%s::ctrl flag! %x, conn rptr %d, to %d, jif %x, conn_jif %x\n",
++                                              __func__, toe_curr_desc->word3.bits32,
++                                              connection->toeq_rwptr.bits.rptr, timeout_descs,
++                                              (u32)jiffies, (u32)connection->last_rx_jiffies);
++                              }
++                              desc_count = toe_curr_desc->word0.bits.desc_count;
++                              pkt_size = toe_curr_desc->word1.bits.byte_count;
++                              consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
++                                      PCI_DMA_FROMDEVICE);
++                              skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr)-
++                                      SKB_RESERVE_BYTES));
++                              _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x02);
++                              connection->curr_rx_skb = skb;
++                              skb_reserve(skb, RX_INSERT_BYTES);
++                              skb_put(skb, pkt_size);
++                              skb->dev = dev;
++                              skb->protocol = eth_type_trans(skb, dev);
++                              {
++                                      struct iphdr* ip_hdr = (struct iphdr*)&(skb->data[0]);
++                                      if (toe_curr_desc->word3.bits.ctrl_flag)
++                                              printk("%s::ip id %x\n", __func__, ntohs(ip_hdr->id));
++                              }
++                              skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++                              netif_rx(skb);
++                              dev->last_rx = jiffies;
++#if 0
++                              if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
++                                      printk("%s::alloc buf fail!\n", __func__);
++                              }
++                              *(unsigned int*)(skb->data) = (unsigned int)skb;
++                              connection->curr_rx_skb = skb;
++                              skb_reserve(skb, SKB_RESERVE_BYTES);
++                              spin_lock_irqsave(&connection->gmac->rx_mutex, flags);
++                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                              if (toe_private_data.fq_rx_rwptr.bits.wptr != fq_rwptr.bits.wptr) {
++                                      mac_stop_txdma((struct net_device*)connection->dev);
++                                      spin_unlock_irqrestore(&connection->gmac->rx_mutex, flags);
++                                      while(1);
++                              }
++                              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base + fq_rwptr.bits.wptr;
++                              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
++                              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
++                              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
++                              toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
++                              spin_unlock_irqrestore(&connection->gmac->rx_mutex, flags);
++#endif
++//                            spin_lock_irqsave(&connection->gmac->rx_mutex, flags);
++                              toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
++                              SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
++//                            spin_unlock_irqrestore(&connection->gmac->rx_mutex, flags);
++                              connection->toeq_rwptr.bits32 = toeq_rwptr.bits32;
++                      }
++                      toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
++//                    toe_gmac_fill_free_q();
++              }
++              connection->last_rx_jiffies = jiffies;
++              if (connection->status != TCP_CONN_CLOSED)
++                      mod_timer(&connection->rx_timer, jiffies+2);
++              if (connection->status != TCP_CONN_ESTABLISHED)
++                      printk("%s::conn status %x\n", __func__, connection->status);
++              hash_set_valid_flag(connection->hash_entry_index, 1);
++              enable_irq(connection->gmac->irq);
++              // Gary Chen spin_unlock_irqrestore(&connection->conn_lock, conn_flags);
++      }
++}
++
++/*---------------------------------------------------------------------------
++ * free_toeq_descs
++ *-------------------------------------------------------------------------*/
++void free_toeq_descs(int qid, TOE_INFO_T *toe)
++{
++      void    *desc_ptr;
++
++      desc_ptr = (void*)toe->toe_desc_base[qid];
++      pci_free_consistent(NULL, TOE_TOE_DESC_NUM*sizeof(GMAC_RXDESC_T), desc_ptr,
++         (dma_addr_t)toe->toe_desc_base_dma[qid]);
++      toe->toe_desc_base[qid] = 0;
++}
++
++/*---------------------------------------------------------------------------
++ * set_toeq_hdr
++ *-------------------------------------------------------------------------*/
++void set_toeq_hdr(struct toe_conn*    connection, TOE_INFO_T* toe, struct net_device *dev)
++{
++      volatile TOE_QHDR_T     *toe_qhdr;
++      volatile unsigned int   toeq_wptr; // toeq_rptr
++      volatile GMAC_RXDESC_T  *toe_curr_desc;
++      struct sk_buff  *skb;
++      unsigned int    pkt_size;
++      DMA_RWPTR_T     toeq_rwptr;
++
++      if (connection->status == TCP_CONN_CLOSING) {
++              connection->status = TCP_CONN_CLOSED;
++              hash_set_valid_flag(connection->hash_entry_index, 0);
++              // remove timer first.
++              // del_timer_sync(&(connection->rx_timer));
++              // check if any queued frames last time.
++              toe_qhdr = (volatile TOE_QHDR_T*)TOE_TOE_QUE_HDR_BASE;
++              toe_qhdr += connection->qid;
++              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
++
++              //toeq_rptr = toe_qhdr->word1.bits.rptr;
++              toeq_wptr = toe_qhdr->word1.bits.wptr;
++              while (toeq_rwptr.bits.rptr != toeq_wptr) {
++                      printk("%s::pending frames in TOE Queue before closing!\n", __func__);
++                      toe_curr_desc = (GMAC_RXDESC_T*)(toe->toe_desc_base[connection->qid] +
++                              toe_qhdr->word1.bits.rptr*sizeof(GMAC_RXDESC_T));
++                      connection->curr_desc = (GMAC_RXDESC_T *)toe_curr_desc;
++                      pkt_size = toe_curr_desc->word1.bits.byte_count;
++                      consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
++                              PCI_DMA_FROMDEVICE);
++                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr) -
++                              SKB_RESERVE_BYTES));
++                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x03);
++                      connection->curr_rx_skb = skb;
++                      skb_reserve(skb, RX_INSERT_BYTES);
++                      skb_put(skb, pkt_size);
++                      skb->dev = connection->dev;
++                      skb->protocol = eth_type_trans(skb, connection->dev);
++                      skb->ip_summed = CHECKSUM_UNNECESSARY;
++                      netif_rx(skb);
++                      connection->dev->last_rx = jiffies;
++
++                      toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
++                      SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
++              }
++              free_toeq_descs(connection->qid, toe);
++              // shall we re-fill free queue?
++
++              reset_connection_index(connection->qid);
++              //memset(connection, 0, sizeof(struct toe_conn));
++              printk(" del timer and close connection %x, qid %d\n", (u32)connection, connection->qid);
++              return;
++      }
++      /* enable or setup toe queue header */
++      if (connection->status == TCP_CONN_CONNECTING && storlink_ctl.rx_max_pktsize) {
++              volatile TOE_QHDR_T     *qhdr;
++              int iq_id;
++              connection->status = TCP_CONN_ESTABLISHED;
++              qhdr = (volatile TOE_QHDR_T*)((unsigned int)TOE_TOE_QUE_HDR_BASE +
++                             connection->qid * sizeof(TOE_QHDR_T));
++
++              iq_id = get_interrupt_queue_id(connection->qid);
++              connection->dev = dev;
++              connection->gmac = dev->priv;
++              connection->toeq_rwptr.bits32 = 0;
++
++//            qhdr->word6.bits.iq_num = iq_id;
++              qhdr->word6.bits.MaxPktSize = (connection->max_pktsize)>>2; // in word.
++              qhdr->word7.bits.AckThreshold = connection->ack_threshold;
++              qhdr->word7.bits.SeqThreshold = connection->seq_threshold;
++
++              // init timer.
++#if 1
++              init_timer(&connection->rx_timer);
++              connection->rx_timer.expires = jiffies + 5;
++              connection->rx_timer.data = (unsigned long)connection;
++              connection->rx_timer.function = (void *)&connection_rx_timer;
++              add_timer(&connection->rx_timer);
++              connection->last_rx_jiffies = jiffies;
++              printk("init_timer %x\n", (u32)jiffies);
++#endif
++              hash_set_valid_flag(connection->hash_entry_index, 1);
++              return;
++      } else {
++              printk("%s::conn status %x, rx_pktsize %d\n",
++                      __func__, connection->status, storlink_ctl.rx_max_pktsize);
++      }
++}
++
++/*---------------------------------------------------------------------------
++ * get_connection_index
++ * get_connection_index will find an available index for the connection,
++ * when allocate a new connection is needed.
++ * we find available Qid from AV bits and write to hash_table, so that when RxTOE
++ * packet is received, sw_id from ToeQ descriptor is also the Qid of conneciton Q.
++ *-------------------------------------------------------------------------*/
++int get_connection_index(void)
++{
++      int i=0, j=0, index=-1;
++      __u32   connection_bits;
++
++      for (i = 0; i< TOE_TOE_QUEUE_NUM/32; i++) {
++              connection_bits = ~(toe_connection_bits[i]);
++              if (connection_bits == 0)
++                      // all 32 bits are used.
++                      continue;
++
++              for (j=0; j<32; j++) {
++                      if (connection_bits & 0x01) {
++                              index = i*32 + j;
++                              return index;
++                      }
++                      connection_bits = connection_bits >> 1;
++              }
++      }
++      return index;
++}
++
++/*---------------------------------------------------------------------------
++ * set_toe_connection
++ *-------------------------------------------------------------------------*/
++void set_toe_connection(int index, int val)
++{
++      if (val) {
++              toe_connection_bits[index/32] |= (1<<(index%32));
++      } else {
++              toe_connection_bits[index/32] &= (~(1<<(index%32)));
++      }
++}
++
++/*---------------------------------------------------------------------------
++ * sl351x_get_toe_conn_flag
++ *-------------------------------------------------------------------------*/
++int sl351x_get_toe_conn_flag(int index)
++{
++      if (index < TOE_TOE_QUEUE_NUM)
++              return (toe_connection_bits[index/32] & (1 << (index %32)));
++      else
++              return 0;
++}
++
++/*---------------------------------------------------------------------------
++ * sl351x_get_toe_conn_info
++ *-------------------------------------------------------------------------*/
++struct toe_conn * sl351x_get_toe_conn_info(int index)
++{
++      if (index < TOE_TOE_QUEUE_NUM)
++              return (struct toe_conn *)&toe_connections[index];
++      else
++              return NULL;
++}
++
++/*---------------------------------------------------------------------------
++ * create_sw_toe_connection
++ *-------------------------------------------------------------------------*/
++struct toe_conn* create_sw_toe_connection(int qid, int ip_ver, void* ip_hdr,
++      struct tcphdr* tcp_hdr)
++{
++      struct toe_conn*        connection =  &(toe_connections[qid]);
++
++      connection->ip_ver = (__u8)ip_ver;
++      connection->qid = (__u8)qid;
++      connection->source = (__u16)tcp_hdr->source;
++      connection->dest = (__u16)tcp_hdr->dest;
++      if (ip_ver == 4) {
++              struct iphdr* iph = (struct iphdr*) ip_hdr;
++              connection->saddr[0] = (__u32)iph->saddr;
++              connection->daddr[0] = (__u32)iph->daddr;
++//            printk("%s::saddr %x, daddr %x\n", __func__,
++//                    ntohl(connection->saddr[0]), ntohl(connection->daddr[0]));
++      } else if (ip_ver == 6) {
++              struct ipv6hdr *iph = (struct ipv6hdr*)ip_hdr;
++              int i=0;
++              for (i=0; i<4; i++) {
++                      connection->saddr[i] = (__u32)iph->saddr.in6_u.u6_addr32[i];
++                      connection->daddr[i] = (__u32)iph->daddr.in6_u.u6_addr32[i];
++              }
++      }
++      connection->status = TCP_CONN_CREATION;
++      return connection;
++}
++
++/*---------------------------------------------------------------------------
++ * fill_toeq_buf
++ *-------------------------------------------------------------------------*/
++int fill_toeq_buf(int index, TOE_INFO_T* toe)
++{
++      volatile TOE_QHDR_T     *qhdr;
++      //struct toe_conn* connection;
++      GMAC_RXDESC_T   *desc_ptr;
++
++      if (!toe->toe_desc_base[index]) {
++              // first time. init.
++              desc_ptr = (GMAC_RXDESC_T*)(pci_alloc_consistent(NULL, TOE_TOE_DESC_NUM
++                          *sizeof(GMAC_RXDESC_T), (dma_addr_t*)&toe->toe_desc_base_dma[index]));
++
++              toe->toe_desc_num = TOE_TOE_DESC_NUM;
++              toe->toe_desc_base[index] = (unsigned int)desc_ptr;
++      }
++      qhdr = (volatile TOE_QHDR_T*)((unsigned int)TOE_TOE_QUE_HDR_BASE +
++                                                                      index*sizeof(TOE_QHDR_T));
++      //connection = (struct toe_conn*)&(toe_connections[index]);
++
++      qhdr->word0.base_size = ((unsigned int)toe->toe_desc_base_dma[index]&TOE_QHDR0_BASE_MASK)
++                                      | TOE_TOE_DESC_POWER;
++      qhdr->word1.bits32 = 0;
++      qhdr->word2.bits32 = 0;
++      qhdr->word3.bits32 = 0;
++      qhdr->word4.bits32 = 0;
++      qhdr->word5.bits32 = 0;
++      return 1;
++}
++
++/*---------------------------------------------------------------------------
++ * create_toe_hash_entry_smb
++ * add SMB header in hash entry.
++ *-------------------------------------------------------------------------*/
++int create_toe_hash_entry_smb(int ip_ver, void* ip_hdr, struct tcphdr* tcp_hdr,
++      int sw_id)
++{
++      HASH_ENTRY_T    hash_entry, *entry;
++      int     hash_entry_index;
++      int i;
++
++      entry = (HASH_ENTRY_T*)&hash_entry;
++      memset((void*)entry, 0, sizeof(HASH_ENTRY_T));
++      entry->rule = 0;
++
++      /* enable fields of hash key */
++      entry->key_present.ip_protocol = 1;
++      entry->key_present.sip = 1;
++      entry->key_present.dip = 1;
++      entry->key_present.l4_bytes_0_3 = 1;    // src port and dest port
++      entry->key_present.l7_bytes_0_3 = 0;    // do we need to enable NETBIOS? how?
++      entry->key_present.l7_bytes_4_7 = 1;    // "SMB" header
++
++      /* hash key */
++      entry->key.ip_protocol = IPPROTO_TCP;
++      if (ip_ver == 4) {
++              struct iphdr *iph = (struct iphdr*)ip_hdr;
++              memcpy(entry->key.sip, &iph->saddr, 4);
++              memcpy(entry->key.dip, &iph->daddr, 4);
++      } else if (ip_ver == 6) {
++              struct ipv6hdr *iph = (struct ipv6hdr*)ip_hdr;
++              for (i=0; i<4; i++) {
++                      memcpy(&(entry->key.sip[i*4]), &(iph->saddr.in6_u.u6_addr32[i]), 4);
++                      memcpy(&(entry->key.dip[i*4]), &(iph->daddr.in6_u.u6_addr32[i]), 4);
++              }
++      }
++      *(__u16*)&entry->key.l4_bytes[0] = tcp_hdr->source;
++      *(__u16*)&entry->key.l4_bytes[2] = tcp_hdr->dest;
++
++      entry->key.l7_bytes[4] = 0xff;
++      entry->key.l7_bytes[5] = 0x53;
++      entry->key.l7_bytes[6] = 0x4d;
++      entry->key.l7_bytes[7] = 0x42;
++
++      /* action of hash entry match */
++      entry->action.sw_id = 1;
++      entry->action.dest_qid = (__u8)TOE_TOE_QID(sw_id);
++      entry->action.srce_qid = 0;
++      hash_entry_index = hash_add_toe_entry(entry);
++
++      return hash_entry_index;
++}
++
++// best performance of tcp streaming.
++/*---------------------------------------------------------------------------
++ * create_toe_hash_entry_smb
++ * add SMB header in hash entry.
++ *-------------------------------------------------------------------------*/
++int create_toe_hash_entry_ftp(int ip_ver, void* ip_hdr, struct tcphdr* tcphdr)
++{
++      return 0;
++}
++
++// is hash entry for nfs needed?
++
++/*
++ * Create a TOE hash entry by given ip addresses and tcp port numbers.
++ * hash entry index will be saved in sw connection.
++ */
++/*---------------------------------------------------------------------------
++ * create_toe_hash_entry
++ *-------------------------------------------------------------------------*/
++int create_toe_hash_entry(int ip_ver, void* ip_hdr, struct tcphdr* tcp_hdr, int sw_id)
++{
++      HASH_ENTRY_T    hash_entry, *entry;
++//    unsigned long   hash_key[HASH_MAX_DWORDS];
++      int     hash_entry_index;
++
++      entry = (HASH_ENTRY_T*) &hash_entry;
++      memset((void*)entry, 0, sizeof(HASH_ENTRY_T));
++      entry->rule = 0;
++      /* enable fields of hash key */
++      entry->key_present.ip_protocol = 1;
++      entry->key_present.sip = 1;
++      entry->key_present.dip = 1;
++      entry->key_present.l4_bytes_0_3 = 1;    // src port and dest port
++
++      /* hash key */
++      entry->key.ip_protocol = IPPROTO_TCP;
++      if (ip_ver == 4) {
++              // key of ipv4
++              struct iphdr* iph = (struct iphdr*)ip_hdr;
++              memcpy(entry->key.sip, &iph->saddr, 4);
++              memcpy(entry->key.dip, &iph->daddr, 4);
++      } else if (ip_ver == 6) {
++              // key of ipv6
++              int i=0;
++              struct ipv6hdr *iph = (struct ipv6hdr*)ip_hdr;
++              for (i=0; i<4; i++) {
++                      memcpy(&(entry->key.sip[i*4]), &(iph->saddr.in6_u.u6_addr32[i]), 4);
++                      memcpy(&(entry->key.dip[i*4]), &(iph->daddr.in6_u.u6_addr32[i]), 4);
++              }
++      }
++      *(__u16*)&entry->key.l4_bytes[0] = tcp_hdr->source;
++      *(__u16*)&entry->key.l4_bytes[2] = tcp_hdr->dest;
++      // is it necessary to write ip version to hash key?
++
++      /* action of hash entry match */
++      entry->action.sw_id = 1;
++      entry->action.dest_qid = (__u8)TOE_TOE_QID(sw_id);
++      entry->action.srce_qid = 0;     // 0 for SW FreeQ. 1 for HW FreeQ.
++      hash_entry_index = hash_add_toe_entry(entry);
++//    printk("\n%s. sw_id %d, hash_entry index %x\n",
++//            __func__, TOE_TOE_QID(sw_id), hash_entry_index);
++      return hash_entry_index;
++}
++
++/*---------------------------------------------------------------------------
++ * init_toeq
++ * 1. Reserve a TOE Queue id first, to get the sw toe_connection.
++ * 2. Setup the hash entry with given iphdr and tcphdr, save hash entry index
++ *    in sw toe_connection.
++ * 3. Prepare sw toe_connection and allocate buffers.
++ * 4. Validate hash entry.
++ *-------------------------------------------------------------------------*/
++struct toe_conn* init_toeq(int ipver, void* iph, struct tcphdr* tcp_hdr,
++      TOE_INFO_T* toe, unsigned char* l2hdr)
++{
++//    printk("\t*** %s, ipver %d\n", __func__, ipver);
++      int qid=-1;
++      struct toe_conn* connection;
++      int hash_entry_index;
++      // int i=0;
++      unsigned short  dest_port = ntohs(tcp_hdr->dest);
++
++      if (dest_port == 445) {
++              printk("%s::SMB/CIFS connection\n", __func__);
++      } else if (dest_port == 20) {
++              printk("%s::ftp-data connection\n", __func__);
++      } else if (dest_port == 2049) {
++              printk("%s::nfs daemon connection\n", __func__);
++      }
++      qid = get_connection_index();
++      if (qid<0)
++              return 0;       // setup toeq failure
++      set_toe_connection(qid, 1); // reserve this sw toeq.
++
++      //connection = (struct toe_conn*)&(toe_connections[qid]);
++      hash_entry_index = create_toe_hash_entry(ipver, iph, tcp_hdr, qid);
++      if (hash_entry_index <0) {
++              printk("%s::release toe hash entry!\n", __func__);
++              set_toe_connection(qid, 0); // release this sw toeq.
++              return 0;
++      }
++      connection = create_sw_toe_connection(qid, ipver, iph, tcp_hdr);
++      connection->hash_entry_index = (__u16) hash_entry_index;
++
++      fill_toeq_buf(qid, toe);
++      memcpy(&connection->l2_hdr, l2hdr, sizeof(struct ethhdr));
++      spin_lock_init(&connection->conn_lock);
++
++      return connection;
++}
++
++#if 0
++/*----------------------------------------------------------------------
++*   toe_init_toe_queue
++*   (1) Initialize the TOE Queue Header
++*       Register: TOE_TOE_QUE_HDR_BASE (0x60003000)
++*   (2) Initialize Descriptors of TOE Queues
++*----------------------------------------------------------------------*/
++void toe_init_toe_queue(TOE_INFO_T* toe)
++{
++}
++EXPORT_SYMBOL(toe_init_toe_queue);
++#endif
++
++/*---------------------------------------------------------------------------
++ * dump_jumbo_skb
++ *-------------------------------------------------------------------------*/
++void dump_jumbo_skb(struct jumbo_frame *jumbo_skb)
++{
++      if (jumbo_skb->skb0) {
++//            printk("%s. jumbo skb %x, len %d\n",
++//                    __func__, jumbo_skb->skb0->data, jumbo_skb->skb0->len);
++              netif_rx(jumbo_skb->skb0);
++      }
++      jumbo_skb->skb0 = 0;
++      jumbo_skb->tail = 0;
++      jumbo_skb->iphdr0 = 0;
++      jumbo_skb->tcphdr0 = 0;
++}
++
++/* ---------------------------------------------------------------------
++ * Append skb to skb0. skb0 is the jumbo frame that will be passed to
++ * kernel tcp.
++ * --------------------------------------------------------------------*/
++void rx_append_skb(struct jumbo_frame *jumbo_skb, struct sk_buff* skb, int payload_len)
++{
++      struct iphdr* iphdr0 = (struct iphdr*)&(skb->data[0]);
++      int ip_hdrlen = iphdr0->ihl << 2;
++      struct tcphdr* tcphdr0 = (struct tcphdr*)&(skb->data[ip_hdrlen]);
++
++      if (!jumbo_skb->skb0) {
++              // head of the jumbo frame.
++              jumbo_skb->skb0 = skb;
++              jumbo_skb->tail = 0;
++              jumbo_skb->iphdr0 = iphdr0;
++              jumbo_skb->tcphdr0 = tcphdr0;
++      } else {
++              if (!jumbo_skb->tail)
++                      skb_shinfo(jumbo_skb->skb0)->frag_list = skb;
++              else
++                      (jumbo_skb->tail)->next = skb;
++              jumbo_skb->tail = skb;
++
++              // do we need to change truesize as well?
++              jumbo_skb->skb0->len += payload_len;
++              jumbo_skb->skb0->data_len += payload_len;
++
++              jumbo_skb->iphdr0->tot_len = htons(ntohs(jumbo_skb->iphdr0->tot_len)+payload_len);
++              jumbo_skb->tcphdr0->ack_seq = tcphdr0->ack_seq;
++              jumbo_skb->tcphdr0->window = tcphdr0->window;
++
++              skb->len += payload_len;
++              skb->data_len = 0;
++              skb->data += ntohs(iphdr0->tot_len) - payload_len;
++      }
++}
++
++/*----------------------------------------------------------------------
++* toe_gmac_handle_toeq
++* (1) read interrupt Queue to get TOE Q.
++* (2) get packet fro TOE Q and send to upper layer handler.
++* (3) allocate new buffers and put to TOE Q. Intr Q buffer is recycled.
++*----------------------------------------------------------------------*/
++void toe_gmac_handle_toeq(struct net_device *dev, GMAC_INFO_T* tp, __u32 status)
++{
++      //volatile INTRQ_INFO_T *intrq_info;
++      //TOEQ_INFO_T           *toeq_info;
++      volatile NONTOE_QHDR_T  *intr_qhdr;
++      volatile TOE_QHDR_T             *toe_qhdr;
++      volatile INTR_QHDR_T    *intr_curr_desc;
++      TOE_INFO_T      *toe = &toe_private_data;
++
++      volatile GMAC_RXDESC_T  *toe_curr_desc; // , *fq_desc;// *tmp_desc;
++      volatile DMA_RWPTR_T    intr_rwptr, toeq_rwptr;  // fq_rwptr;
++
++      unsigned int    pkt_size, desc_count, tcp_qid;
++      volatile unsigned int   toeq_wptr;
++      struct toe_conn*                connection;
++      int             i, frag_id = 0;
++      // unsigned long        toeq_flags;
++      struct jumbo_frame      jumbo_skb;
++      struct sk_buff  *skb;
++      __u32   interrupt_status;
++
++      in_toe_isr++;
++
++      interrupt_status = status >> 24;
++      // get interrupt queue header
++      intr_qhdr = (volatile NONTOE_QHDR_T*)TOE_INTR_Q_HDR_BASE;
++      memset(&jumbo_skb, 0, sizeof(struct jumbo_frame));
++
++      for (i=0; i<TOE_INTR_QUEUE_NUM; i++, intr_qhdr++) {
++              if (!(interrupt_status & 0x0001)) {
++                      // no interrupt of this IntQ
++                      interrupt_status = interrupt_status >> 1;
++                      continue;
++              }
++              interrupt_status = interrupt_status >> 1;
++              intr_rwptr.bits32 = readl(&intr_qhdr->word1);
++
++              while ( intr_rwptr.bits.rptr != intr_rwptr.bits.wptr) {
++                      int max_pktsize = 1;
++                      // get interrupt queue descriptor.
++                      intr_curr_desc = (INTR_QHDR_T*)toe->intr_desc_base +
++                              i* TOE_INTR_DESC_NUM + intr_rwptr.bits.rptr;
++//                    printk("%s::int %x\n", __func__, intr_curr_desc->word1.bits32);
++                      // get toeq id
++                      tcp_qid = (u8)intr_curr_desc->word1.bits.tcp_qid - (u8)TOE_TOE_QID(0);
++                      // get toeq queue header
++                      toe_qhdr = (volatile TOE_QHDR_T*) TOE_TOE_QUE_HDR_BASE;
++                      toe_qhdr += tcp_qid;
++                      connection = &toe_connections[tcp_qid];
++                      del_timer(&connection->rx_timer);
++                      // Gary Chen spin_lock_irqsave(&connection->conn_lock, toeq_flags);
++                      // handling interrupts of this TOE Q.
++                      if (intr_curr_desc->word1.bits.ctl || intr_curr_desc->word1.bits.osq ||
++                              intr_curr_desc->word1.bits.abn)
++                              max_pktsize = 0;
++                      if (!max_pktsize || intr_curr_desc->word1.bits.TotalPktSize) {
++                              desc_count=0;
++                              // wptr in intl queue is where this TOE interrupt should stop.
++                              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
++                              toeq_wptr = intr_curr_desc->word0.bits.wptr;
++                              if (connection->toeq_rwptr.bits.rptr != toeq_rwptr.bits.rptr)
++                                      printk("conn rptr %d, hw rptr %d\n",
++                                              connection->toeq_rwptr.bits.rptr, toeq_rwptr.bits.rptr);
++
++                              if (intr_curr_desc->word1.bits.ctl &&
++                                      (toeq_rwptr.bits.rptr == toeq_wptr)) {
++                                      printk("\nctrl frame, but not in TOE queue! conn rptr %d, hw wptr %d\n",
++                                              connection->toeq_rwptr.bits.rptr, toeq_wptr);
++//                                    dump_toe_qhdr(toe_qhdr);
++//                                    dump_intrq_desc(intr_curr_desc);
++                              }
++                              // while (toeq_rwptr.bits.rptr != intr_curr_desc->word0.bits.wptr) {
++                              while (toe_qhdr->word1.bits.rptr != intr_curr_desc->word0.bits.wptr) {
++                                      frag_id++;
++                                      toe_curr_desc = (volatile GMAC_RXDESC_T *)(toe->toe_desc_base[tcp_qid]
++                                              + toe_qhdr->word1.bits.rptr *sizeof(GMAC_RXDESC_T));
++                                      connection->curr_desc = (GMAC_RXDESC_T *)toe_curr_desc;
++                                      desc_count = toe_curr_desc->word0.bits.desc_count;
++                                      pkt_size = toe_curr_desc->word1.bits.byte_count;
++                                      consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
++                                              PCI_DMA_FROMDEVICE);
++                                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr)-
++                                              SKB_RESERVE_BYTES));
++                                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x01);
++                                      connection->curr_rx_skb = skb;
++                                      skb_reserve(skb, RX_INSERT_BYTES);
++                                      if ((skb->len + pkt_size) > (1514+16))
++                                      {
++                                              printk("skb->len=%d, pkt_size=%d\n",skb->len, pkt_size);
++                                              while(1);
++                                      }
++
++                                      skb_put(skb, pkt_size);
++                                      skb->dev = dev;
++                                      skb->protocol = eth_type_trans(skb, dev);
++                                      skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++                                      if (toe_curr_desc->word3.bits32 & 0x1b000000)
++                                              dump_jumbo_skb(&jumbo_skb);
++
++                                      rx_append_skb(&jumbo_skb, skb, pkt_size-toe_curr_desc->word3.bits.l7_offset);
++//                                    spin_lock_irqsave(&gmac_fq_lock, flags);
++                                      toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
++                                      SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
++//                                    spin_unlock_irqrestore(&gmac_fq_lock, flags);
++                                      if (storlink_ctl.fqint_threshold)
++                                              continue;
++#if 0
++//#if (HANDLE_FREEQ_METHOD == HANDLE_FREEQ_INDIVIDUAL)
++                                      if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
++                                              printk("%s::toe queue alloc buffer ", __func__);
++                                      }
++                                      *(unsigned int*)(skb->data) = (unsigned int)skb;
++                                      connection->curr_rx_skb = skb;
++                                      skb_reserve(skb, SKB_RESERVE_BYTES);
++
++                                      spin_lock_irqsave(&gmac_fq_lock, flags);
++                                      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                                      if (toe->fq_rx_rwptr.bits.wptr != fq_rwptr.bits.wptr) {
++                                              printk("%s::fq_rx_rwptr %x\n", __func__, toe->fq_rx_rwptr.bits32);
++                                              mac_stop_txdma((struct net_device*) tp->dev);
++                                              spin_unlock_irqrestore(&gmac_fq_lock, flags);
++                                              while(1);
++                                      }
++                                      fq_desc = (GMAC_RXDESC_T*)toe->swfq_desc_base + fq_rwptr.bits.wptr;
++                                      fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
++
++                                      fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
++                                      SET_WPTR(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
++                                      toe->fq_rx_rwptr.bits32 = fq_rwptr.bits32;
++                                      spin_unlock_irqrestore(&gmac_fq_lock, flags);
++#endif
++                              } // end of this multi-desc.
++                              dump_jumbo_skb(&jumbo_skb);
++                              dev->last_rx = jiffies;
++                              connection->toeq_rwptr.bits32 = toeq_rwptr.bits32;
++                      } else if (intr_curr_desc->word1.bits.sat) {
++                              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
++                              toeq_wptr = intr_curr_desc->word0.bits.wptr;
++                              if (connection->toeq_rwptr.bits.rptr != toeq_rwptr.bits.rptr)
++                                      printk("SAT. conn rptr %d, hw rptr %d\n",
++                                              connection->toeq_rwptr.bits.rptr, toeq_rwptr.bits.rptr);
++/*
++                                      printk("%s::SAT int!, ackcnt %x, seqcnt %x, rptr %d, wptr %d, ack %x, qhack %x\n",
++                                              __func__, intr_curr_desc->word4.bits.AckCnt, intr_curr_desc->word4.bits.SeqCnt,
++                                              toeq_rptr, toeq_wptr, intr_curr_desc->word3.ack_num, toe_qhdr->word4.ack_num);*/
++                              /* pure ack */
++                              if (toeq_rwptr.bits.rptr == toeq_wptr) {
++                                      if (intr_curr_desc->word4.bits32) {
++                                              skb = gen_pure_ack(connection, (TOE_QHDR_T *)toe_qhdr, (INTR_QHDR_T *)intr_curr_desc);
++                                              skb_put(skb, 60);
++                                              skb->dev = connection->dev;
++                                              skb->ip_summed = CHECKSUM_UNNECESSARY;
++                                              skb->protocol = eth_type_trans(skb, connection->dev);
++                                              netif_rx(skb);
++                                      } else
++                                              printk("%s::SAT Interrupt!. But cnt is 0!\n", __func__);
++                              } else {
++                                      // while (toeq_rwptr.bits.rptr != toeq_wptr) {
++                                      while (toe_qhdr->word1.bits.rptr != intr_curr_desc->word0.bits.wptr) {
++                                              toe_curr_desc = (volatile GMAC_RXDESC_T*)(toe->toe_desc_base[tcp_qid]
++                                                      + toe_qhdr->word1.bits.rptr * sizeof(GMAC_RXDESC_T));
++                                              connection->curr_desc = (GMAC_RXDESC_T *)toe_curr_desc;
++                                              desc_count = toe_curr_desc->word0.bits.desc_count;
++                                              pkt_size = toe_curr_desc->word1.bits.byte_count;
++                                              consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
++                                                      PCI_DMA_FROMDEVICE);
++                                              // if ( ((toeq_rwptr.bits.rptr +1)&(TOE_TOE_DESC_NUM-1)) == toeq_wptr) {
++                                              if ( RWPTR_ADVANCE_ONE(toe_qhdr->word1.bits.rptr, TOE_TOE_DESC_NUM) == toeq_wptr) {
++                                                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr) -
++                                                              SKB_RESERVE_BYTES));
++                                                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x04);
++                                                      connection->curr_rx_skb = skb;
++                                                      skb_reserve(skb, RX_INSERT_BYTES);
++                                                      skb_put(skb, pkt_size);
++                                                      skb->dev = dev;
++                                                      skb->protocol = eth_type_trans(skb, dev);
++                                                      skb->ip_summed = CHECKSUM_UNNECESSARY;
++                                                      // printk("toeq_rptr %d, wptr %d\n", toeq_rptr, toeq_wptr);
++                                                      netif_rx(skb);
++                                                      dev->last_rx = jiffies;
++/*
++                                                      if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
++
++                                                      }
++                                                      *(unsigned int*)(skb->data) = (unsigned int) skb;
++                                                      skb_reserve(skb, SKB_RESERVE_BYTES); */
++                                              } else {
++                                                      // reuse this skb, append to free queue..
++                                                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr)-
++                                                              SKB_RESERVE_BYTES));
++                                                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x05);
++                                                      connection->curr_rx_skb = skb;
++                                                      dev_kfree_skb_irq(skb);
++                                              }
++#if 0
++                                              spin_lock_irqsave(&gmac_fq_lock, flags);
++                                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++/*                                            if (toe->fq_rx_rwptr.bits.wptr != fq_rwptr.bits.wptr) {
++                                                      printk("%s::fq_rx_rwptr %x\n", __func__, toe->fq_rx_rwptr.bits32);
++                                                      mac_stop_txdma((struct net_device*) tp->dev);
++                                                      spin_unlock_irqrestore(&gmac_fq_lock, flags);
++                                                      while(1);
++                                              } */
++                                              fq_desc = (GMAC_RXDESC_T*)toe->swfq_desc_base + fq_rwptr.bits.wptr;
++                                              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
++
++                                              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
++                                              SET_WPTR(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
++                                              toe->fq_rx_rwptr.bits32 = fq_rwptr.bits32;
++      //                                      spin_unlock_irqrestore(&gmac_fq_lock, flags);
++#endif
++//                                            spin_lock_irqsave(&gmac_fq_lock, flags);
++                                              toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
++                                              SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
++//                                            spin_unlock_irqrestore(&gmac_fq_lock, flags);
++                                      }
++                              } // end of ACK with options.
++                              connection->toeq_rwptr.bits32 = toeq_rwptr.bits32;
++                              // Gary Chen spin_unlock_irqrestore(&connection->conn_lock, toeq_flags);
++//                            }
++                      };
++                      update_timer(connection);
++                      // any protection against interrupt queue header?
++                      intr_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(intr_rwptr.bits.rptr, TOE_INTR_DESC_NUM);
++                      SET_RPTR(&intr_qhdr->word1, intr_rwptr.bits.rptr);
++                      intr_rwptr.bits32 = readl(&intr_qhdr->word1);
++                      toe_gmac_fill_free_q();
++              } // end of this interrupt Queue processing.
++      } // end of all interrupt Queues.
++
++      in_toe_isr = 0;
++}
++
++
+--- /dev/null
++++ b/drivers/net/sl_lepus_hash.c
+@@ -0,0 +1,553 @@
++/**************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
++*--------------------------------------------------------------------------
++* Name                        : sl_lepus_hash.c
++* Description :
++*             Handle Storlink Lepus Hash Functions
++*
++* History
++*
++*     Date            Writer          Description
++*----------------------------------------------------------------------------
++*     03/13/2006      Gary Chen       Create and implement
++*
++****************************************************************************/
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/compiler.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/completion.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/it8712.h>
++#include <linux/mtd/kvctl.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/list.h>
++#define        MIDWAY
++#define        SL_LEPUS
++
++#include <asm/arch/sl2312.h>
++#include <asm/arch/sl_lepus_gmac.h>
++#include <asm/arch/sl_hash_cfg.h>
++
++#ifndef RXTOE_DEBUG
++#define RXTOE_DEBUG
++#endif
++#undef RXTOE_DEBUG
++
++/*----------------------------------------------------------------------
++* Definition
++*----------------------------------------------------------------------*/
++#define       hash_printf                             printk
++
++#define HASH_TIMER_PERIOD             (60*HZ) // seconds
++#define HASH_ILLEGAL_INDEX            0xffff
++
++/*----------------------------------------------------------------------
++* Variables
++*----------------------------------------------------------------------*/
++u32                                   hash_activate_bits[HASH_TOTAL_ENTRIES/32];
++u32                                   hash_nat_owner_bits[HASH_TOTAL_ENTRIES/32];
++char                          hash_tables[HASH_TOTAL_ENTRIES][HASH_MAX_BYTES] __attribute__ ((aligned(16)));
++static struct timer_list hash_timer_obj;
++LIST_HEAD(hash_timeout_list);
++
++/*----------------------------------------------------------------------
++* Functions
++*----------------------------------------------------------------------*/
++void dm_long(u32 location, int length);
++static void hash_timer_func(u32 data);
++
++/*----------------------------------------------------------------------
++* hash_init
++*----------------------------------------------------------------------*/
++void hash_init(void)
++{
++      int i;
++      volatile u32 *dp1, *dp2, dword;
++
++      dp1 = (volatile u32 *) TOE_V_BIT_BASE;
++      dp2 = (volatile u32 *) TOE_A_BIT_BASE;
++
++      for (i=0; i<HASH_TOTAL_ENTRIES/32; i++)
++      {
++              *dp1++ = 0;
++              dword = *dp2++; // read-clear
++      }
++      memset((void *)&hash_nat_owner_bits, 0, sizeof(hash_nat_owner_bits));
++      memset((void *)&hash_tables, 0, sizeof(hash_tables));
++
++      init_timer(&hash_timer_obj);
++      hash_timer_obj.expires = jiffies + HASH_TIMER_PERIOD;
++      hash_timer_obj.data = (unsigned long)&hash_timer_obj;
++      hash_timer_obj.function = (void *)&hash_timer_func;
++      add_timer(&hash_timer_obj);
++
++#if (HASH_MAX_BYTES == 128)
++      writel((unsigned long)__pa(&hash_tables) | 3,   // 32 words
++                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
++#elif (HASH_MAX_BYTES == 64)
++      writel((unsigned long)__pa(&hash_tables) | 2,   // 16 words
++                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
++#else
++      #error Incorrect setting for HASH_MAX_BYTES
++#endif
++
++}
++/*----------------------------------------------------------------------
++* hash_add_entry
++*----------------------------------------------------------------------*/
++int hash_add_entry(HASH_ENTRY_T *entry)
++{
++      int     rc;
++      u32     key[HASH_MAX_DWORDS];
++      rc = hash_build_keys((u32 *)&key, entry);
++      if (rc < 0)
++              return -1;
++      hash_write_entry(entry, (unsigned char*) &key[0]);
++//    hash_set_valid_flag(entry->index, 1);
++//    printk("Dump hash key!\n");
++//    dump_hash_key(entry);
++      return entry->index;
++}
++
++/*----------------------------------------------------------------------
++* hash_set_valid_flag
++*----------------------------------------------------------------------*/
++void hash_set_valid_flag(int index, int valid)
++{
++      register u32 reg32;
++
++      reg32 = TOE_V_BIT_BASE + (index/32) * 4;
++
++      if (valid)
++      {
++              writel(readl(reg32) | (1 << (index%32)), reg32);
++      }
++      else
++      {
++              writel(readl(reg32) & ~(1 << (index%32)), reg32);
++      }
++}
++
++/*----------------------------------------------------------------------
++* hash_set_nat_owner_flag
++*----------------------------------------------------------------------*/
++void hash_set_nat_owner_flag(int index, int valid)
++{
++      if (valid)
++      {
++              hash_nat_owner_bits[index/32] |= (1 << (index % 32));
++      }
++      else
++      {
++              hash_nat_owner_bits[index/32] &= ~(1 << (index % 32));
++      }
++}
++
++
++/*----------------------------------------------------------------------
++* hash_build_keys
++*----------------------------------------------------------------------*/
++int hash_build_keys(u32 *destp, HASH_ENTRY_T *entry)
++{
++      u32     data;
++      unsigned char   *cp;
++      int                             i, j;
++      unsigned short  index;
++      int                     total;
++
++      memset((void *)destp, 0, HASH_MAX_BYTES);
++      cp = (unsigned char *)destp;
++
++      if (entry->key_present.port || entry->key_present.Ethertype)
++      {
++              HASH_PUSH_WORD(cp, entry->key.Ethertype);               // word 0
++              HASH_PUSH_BYTE(cp, entry->key.port);                    // Byte 2
++              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
++      }
++      else
++      {
++              HASH_PUSH_DWORD(cp, 0);
++      }
++
++      if (entry->key_present.da || entry->key_present.sa)
++      {
++              unsigned char mac[4];
++              if (entry->key_present.da)
++              {
++                      for (i=0; i<4; i++)
++                              HASH_PUSH_BYTE(cp, entry->key.da[i]);
++              }
++              mac[0] = (entry->key_present.da) ? entry->key.da[4] : 0;
++              mac[1] = (entry->key_present.da) ? entry->key.da[5] : 0;
++              mac[2] = (entry->key_present.sa) ? entry->key.sa[0] : 0;
++              mac[3] = (entry->key_present.sa) ? entry->key.sa[1] : 0;
++              data = mac[0] + (mac[1]<<8) + (mac[2]<<16) + (mac[3]<<24);
++              HASH_PUSH_DWORD(cp, data);
++              if (entry->key_present.sa)
++              {
++                      for (i=2; i<6; i++)
++                              HASH_PUSH_BYTE(cp, entry->key.sa[i]);
++              }
++      }
++
++      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
++      {
++              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
++              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
++      }
++      if (entry->key_present.ipv4_hdrlen || entry->key_present.ip_tos || entry->key_present.ip_protocol)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.ip_protocol);             // Byte 0
++              HASH_PUSH_BYTE(cp, entry->key.ip_tos);                  // Byte 1
++              HASH_PUSH_BYTE(cp, entry->key.ipv4_hdrlen);             // Byte 2
++              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
++      }
++
++      if (entry->key_present.ipv6_flow_label)
++      {
++              HASH_PUSH_DWORD(cp, entry->key.ipv6_flow_label);        // low word
++      }
++      if (entry->key_present.sip)
++      {
++              // input (entry->key.sip[i]) is network-oriented
++              // output (hash key) is host-oriented
++              for (i=3; i>=0; i--)
++                      HASH_PUSH_BYTE(cp, entry->key.sip[i]);
++              if (entry->key.ipv6)
++              {
++                      for (i=4; i<16; i+=4)
++                      {
++                              for (j=i+3; j>=i; j--)
++                                      HASH_PUSH_BYTE(cp, entry->key.sip[j]);
++                      }
++              }
++      }
++      if (entry->key_present.dip)
++      {
++              // input (entry->key.sip[i]) is network-oriented
++              // output (hash key) is host-oriented
++              for (i=3; i>=0; i--)
++                      HASH_PUSH_BYTE(cp, entry->key.dip[i]);
++              if (entry->key.ipv6)
++              {
++                      for (i=4; i<16; i+=4)
++                      {
++                              for (j=i+3; j>=i; j--)
++                                      HASH_PUSH_BYTE(cp, entry->key.dip[j]);
++                      }
++              }
++      }
++
++      if (entry->key_present.l4_bytes_0_3)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
++      }
++      if (entry->key_present.l4_bytes_4_7)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[4]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[5]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[6]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[7]);
++      }
++      if (entry->key_present.l4_bytes_8_11)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[8]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[9]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[10]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[11]);
++      }
++      if (entry->key_present.l4_bytes_12_15)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[12]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[13]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[14]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[15]);
++      }
++      if (entry->key_present.l4_bytes_16_19)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[16]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[17]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[18]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[19]);
++      }
++      if (entry->key_present.l4_bytes_20_23)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[20]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[21]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[22]);
++              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[23]);
++      }
++      if (entry->key_present.l7_bytes_0_3)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[0]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[1]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[2]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[3]);
++      }
++      if (entry->key_present.l7_bytes_4_7)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[4]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[5]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[6]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[7]);
++      }
++      if (entry->key_present.l7_bytes_8_11)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[8]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[9]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[10]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[11]);
++      }
++      if (entry->key_present.l7_bytes_12_15)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[12]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[13]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[14]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[15]);
++      }
++      if (entry->key_present.l7_bytes_16_19)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[16]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[17]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[18]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[19]);
++      }
++      if (entry->key_present.l7_bytes_20_23)
++      {
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[20]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[21]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[22]);
++              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[23]);
++      }
++
++      // get hash index
++      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
++
++      if (total > HASH_MAX_KEY_DWORD)
++      {
++              //hash_printf("Total key words (%d) is too large (> %d)!\n",
++              //                              total, HASH_MAX_KEY_DWORD);
++              return -1;
++      }
++
++      if (entry->key_present.port || entry->key_present.Ethertype)
++              index = hash_gen_crc16((unsigned char *)destp, total * 4);
++      else
++      {
++              if (total == 1)
++              {
++                      hash_printf("No key is assigned!\n");
++                      return -1;
++              }
++
++              index = hash_gen_crc16((unsigned char *)(destp+1), (total-1) * 4);
++      }
++
++      entry->index = index & HASH_BITS_MASK;
++
++      //hash_printf("Total key words = %d, Hash Index= %d\n",
++      //                              total, entry->index);
++
++      cp = (unsigned char *)destp;
++      cp+=3;
++      HASH_PUSH_BYTE(cp, entry->rule);        // rule
++
++      entry->total_dwords = total;
++
++      return total;
++}
++
++/*----------------------------------------------------------------------
++* hash_build_nat_keys
++*----------------------------------------------------------------------*/
++void hash_build_nat_keys(u32 *destp, HASH_ENTRY_T *entry)
++{
++      unsigned char   *cp;
++      int                             i;
++      unsigned short  index;
++      int                     total;
++
++      memset((void *)destp, 0, HASH_MAX_BYTES);
++
++      cp = (unsigned char *)destp + 2;
++      HASH_PUSH_BYTE(cp, entry->key.port);
++      cp++;
++
++      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
++      {
++              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
++              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
++      }
++
++      HASH_PUSH_BYTE(cp, entry->key.ip_protocol);
++      cp+=3;
++
++      // input (entry->key.sip[i]) is network-oriented
++      // output (hash key) is host-oriented
++      for (i=3; i>=0; i--)
++              HASH_PUSH_BYTE(cp, entry->key.sip[i]);
++
++      // input (entry->key.sip[i]) is network-oriented
++      // output (hash key) is host-oriented
++      for (i=3; i>=0; i--)
++              HASH_PUSH_BYTE(cp, entry->key.dip[i]);
++
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
++      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
++
++      // get hash index
++      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
++
++      index = hash_gen_crc16((unsigned char *)destp, total * 4);
++      entry->index = index & ((1 << HASH_BITS) - 1);
++
++      cp = (unsigned char *)destp;
++      cp+=3;
++      HASH_PUSH_BYTE(cp, entry->rule);        // rule
++
++      entry->total_dwords = total;
++}
++
++
++/*----------------------------------------------------------------------
++* hash_write_entry
++*----------------------------------------------------------------------*/
++int hash_write_entry(HASH_ENTRY_T *entry, unsigned char *key)
++{
++      int             i;
++      u32             *srcep, *destp, *destp2;
++
++      srcep = (u32 *)key;
++      destp2 = destp = (u32 *)&hash_tables[entry->index][0];
++
++      for (i=0; i<(entry->total_dwords); i++, srcep++, destp++)
++              *destp = *srcep;
++
++      srcep = (u32 *)&entry->action;
++      *destp++ = *srcep;
++
++      srcep = (u32 *)&entry->param;
++      for (i=0; i<(sizeof(ENTRY_PARAM_T)/sizeof(*destp)); i++, srcep++, destp++)
++              *destp = *srcep;
++
++      memset(destp, 0, (HASH_MAX_DWORDS-entry->total_dwords-HASH_ACTION_DWORDS) * sizeof(u32));
++
++      consistent_sync(destp2, (entry->total_dwords+HASH_ACTION_DWORDS) * 4, PCI_DMA_TODEVICE);
++      return 0;
++}
++
++/*----------------------------------------------------------------------
++* hash_timer_func
++*----------------------------------------------------------------------*/
++static void hash_timer_func(u32 data)
++{
++      int                             i, j;
++      volatile u32    *active_p, *own_p, *valid_p;
++      u32                             a_bits, own_bits;
++
++      valid_p = (volatile u32 *)TOE_V_BIT_BASE;
++      active_p = (volatile u32 *)hash_activate_bits;
++      own_p = (volatile u32 *)hash_nat_owner_bits;
++      for (i=0; i<(HASH_TOTAL_ENTRIES/32); i++, own_p++, active_p++, valid_p++)
++      {
++              *active_p |= readl(TOE_A_BIT_BASE + (i*4));
++              a_bits = *active_p;
++              own_bits = *own_p;
++              if (own_bits)
++              {
++#ifndef DEBUG_NAT_MIXED_HW_SW_TX
++                      a_bits = own_bits & ~a_bits;
++#else
++                      a_bits = own_bits & a_bits;
++#endif
++                      for (j=0; a_bits && j<32; j++)
++                      {
++                              if (a_bits & 1)
++                              {
++                                      *valid_p &= ~(1 << j);          // invalidate it
++#if !(defined(NAT_DEBUG_LAN_HASH_TIMEOUT) || defined(NAT_DEBUG_WAN_HASH_TIMEOUT))
++                                      *own_p &= ~(1 << j);            // release ownership for NAT
++#endif
++// #ifdef DEBUG_NAT_MIXED_HW_SW_TX
++#if 0
++                                      hash_printf("%lu %s: Clear hash index: %d\n", jiffies/HZ, __func__, i*32+j);
++#endif
++                              }
++                              a_bits >>= 1;
++                      }
++                      *active_p &= ~own_bits;         // deactivate it for next polling
++              }
++      }
++
++      hash_timer_obj.expires = jiffies + HASH_TIMER_PERIOD;
++      add_timer((struct timer_list *)data);
++}
++
++/*----------------------------------------------------------------------
++* dm_long
++*----------------------------------------------------------------------*/
++void dm_long(u32 location, int length)
++{
++      u32             *start_p, *curr_p, *end_p;
++      u32             *datap, data;
++      int             i;
++
++      //if (length > 1024)
++      //      length = 1024;
++
++      start_p = (u32 *)location;
++      end_p = (u32 *)location + length;
++      curr_p = (u32 *)((u32)location & 0xfffffff0);
++      datap = (u32 *)location;
++      while (curr_p < end_p)
++      {
++              hash_printf("0x%08x: ",(u32)curr_p & 0xfffffff0);
++              for (i=0; i<4; i++)
++              {
++                      if (curr_p < start_p || curr_p >= end_p)
++               hash_printf("         ");
++                      else
++                      {
++                              data = *datap;
++                              hash_printf("%08X ", data);
++                      }
++                      if (i==1)
++              hash_printf("- ");
++
++                      curr_p++;
++                      datap++;
++              }
++        hash_printf("\n");
++      }
++}
++
++/*----------------------------------------------------------------------
++* hash_dump_entry
++*----------------------------------------------------------------------*/
++void hash_dump_entry(int index)
++{
++      hash_printf("Hash Index %d:\n", index);
++      dm_long((u32)&hash_tables[index][0], HASH_MAX_DWORDS);
++}
++
++
+--- /dev/null
++++ b/drivers/net/sl_switch.c
+@@ -0,0 +1,650 @@
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++#define GMAC_GLOBAL_BASE_ADDR       (IO_ADDRESS(SL2312_GLOBAL_BASE))
++#define GPIO_BASE_ADDR1  (IO_ADDRESS(SL2312_GPIO_BASE1))
++enum GPIO_REG
++{
++    GPIO_DATA_OUT   = 0x00,
++    GPIO_DATA_IN    = 0x04,
++    GPIO_PIN_DIR    = 0x08,
++    GPIO_BY_PASS    = 0x0c,
++    GPIO_DATA_SET   = 0x10,
++    GPIO_DATA_CLEAR = 0x14,
++};
++
++#define GMAC_SPEED_10                 0
++#define GMAC_SPEED_100                        1
++#define GMAC_SPEED_1000                       2
++
++enum phy_state
++{
++    LINK_DOWN   = 0,
++    LINK_UP     = 1
++};
++
++#ifndef BIT
++#define BIT(x)                                                (1 << (x))
++#endif
++
++//int Get_Set_port_status();
++unsigned int SPI_read_bit(void);
++void SPI_write_bit(char bit_EEDO);
++void SPI_write(unsigned char block,unsigned char subblock,unsigned char addr,unsigned int value);
++unsigned int SPI_read(unsigned char block,unsigned char subblock,unsigned char addr);
++int SPI_default(void);
++void SPI_CS_enable(unsigned char enable);
++unsigned int SPI_get_identifier(void);
++void phy_write(unsigned char port_no,unsigned char reg,unsigned int val);
++unsigned int phy_read(unsigned char port_no,unsigned char reg);
++void phy_write_masked(unsigned char port_no,unsigned char reg,unsigned int val,unsigned int mask);
++void init_seq_7385(unsigned char port_no) ;
++void phy_receiver_init (unsigned char port_no);
++
++#define PORT_NO               4
++int switch_pre_speed[PORT_NO]={0,0,0,0};
++int switch_pre_link[PORT_NO]={0,0,0,0};
++
++
++
++
++
++/*                            NOTES
++ *   The Protocol of the SPI are as follows:
++ *
++ *                       Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
++ *    byte0     |   Block id  | r/w | sub-block        |
++ *    byte1     |             Address                  |
++ *    byte2     |             Data                     |
++ *    byte3     |             Data                     |
++ *    byte4     |             Data                     |
++ *    byte5     |             Data                     |
++ */
++
++
++
++
++/***************************************/
++/* define GPIO module base address     */
++/***************************************/
++#define GPIO_EECS          0x80000000         /*   EECS: GPIO[22]   */
++#define GPIO_MOSI          0x20000000         /*   EEDO: GPIO[29]   send to 6996*/
++#define GPIO_MISO          0x40000000         /*   EEDI: GPIO[30]   receive from 6996*/
++#define GPIO_EECK          0x10000000         /*   EECK: GPIO[31]   */
++
++/*************************************************************
++* SPI protocol for ADM6996 control
++**************************************************************/
++#define SPI_OP_LEN         0x08               // the length of start bit and opcode
++#define SPI_OPWRITE        0X05               // write
++#define SPI_OPREAD         0X06               // read
++#define SPI_OPERASE        0X07               // erase
++#define SPI_OPWTEN         0X04               // write enable
++#define SPI_OPWTDIS        0X04               // write disable
++#define SPI_OPERSALL       0X04               // erase all
++#define SPI_OPWTALL        0X04               // write all
++
++#define SPI_ADD_LEN        8                  // bits of Address
++#define SPI_DAT_LEN        32                 // bits of Data
++
++
++/****************************************/
++/*    Function Declare                */
++/****************************************/
++
++//unsigned int SPI_read_bit(void);
++//void SPI_write_bit(char bit_EEDO);
++//unsigned int SPI_read_bit(void);
++/******************************************
++* SPI_write
++* addr -> Write Address
++* value -> value to be write
++***************************************** */
++void phy_receiver_init (unsigned char port_no)
++{
++    phy_write(port_no,31,0x2a30);
++    phy_write_masked(port_no, 12, 0x0200, 0x0300);
++    phy_write(port_no,31,0);
++}
++
++void phy_write(unsigned char port_no,unsigned char reg,unsigned int val)
++{
++      unsigned int cmd;
++
++      cmd = (port_no<<21)|(reg<<16)|val;
++      SPI_write(3,0,1,cmd);
++}
++
++unsigned int phy_read(unsigned char port_no,unsigned char reg)
++{
++      unsigned int cmd,reg_val;
++
++      cmd = BIT(26)|(port_no<<21)|(reg<<16);
++      SPI_write(3,0,1,cmd);
++      msleep(2);
++      reg_val = SPI_read(3,0,2);
++      return reg_val;
++}
++
++void phy_write_masked(unsigned char port_no,unsigned char reg,unsigned int val,unsigned int mask)
++{
++      unsigned int cmd,reg_val;
++
++      cmd = BIT(26)|(port_no<<21)|(reg<<16);  // Read reg_val
++      SPI_write(3,0,1,cmd);
++      mdelay(2);
++      reg_val = SPI_read(3,0,2);
++      reg_val &= ~mask;                       // Clear masked bit
++      reg_val |= (val&mask) ;                 // set masked bit ,if true
++      cmd = (port_no<<21)|(reg<<16)|reg_val;
++      SPI_write(3,0,1,cmd);
++}
++
++void init_seq_7385(unsigned char port_no)
++{
++      unsigned char rev;
++
++      phy_write(port_no, 31, 0x2a30);
++      phy_write_masked(port_no, 8, 0x0200, 0x0200);
++      phy_write(port_no, 31, 0x52b5);
++      phy_write(port_no, 16, 0xb68a);
++      phy_write_masked(port_no, 18, 0x0003, 0xff07);
++      phy_write_masked(port_no, 17, 0x00a2, 0x00ff);
++      phy_write(port_no, 16, 0x968a);
++      phy_write(port_no, 31, 0x2a30);
++      phy_write_masked(port_no, 8, 0x0000, 0x0200);
++      phy_write(port_no, 31, 0x0000); /* Read revision */
++      rev = phy_read(port_no, 3) & 0x000f;
++      if (rev == 0)
++      {
++              phy_write(port_no, 31, 0x2a30);
++              phy_write_masked(port_no, 8, 0x0200, 0x0200);
++              phy_write(port_no, 31, 0x52b5);
++              phy_write(port_no, 18, 0x0000);
++              phy_write(port_no, 17, 0x0689);
++              phy_write(port_no, 16, 0x8f92);
++              phy_write(port_no, 31, 0x52B5);
++              phy_write(port_no, 18, 0x0000);
++              phy_write(port_no, 17, 0x0E35);
++              phy_write(port_no, 16, 0x9786);
++              phy_write(port_no, 31, 0x2a30);
++              phy_write_masked(port_no, 8, 0x0000, 0x0200);
++              phy_write(port_no, 23, 0xFF80);
++              phy_write(port_no, 23, 0x0000);
++      }
++      phy_write(port_no, 31, 0x0000);
++      phy_write(port_no, 18, 0x0048);
++      if (rev == 0)
++      {
++              phy_write(port_no, 31, 0x2a30);
++              phy_write(port_no, 20, 0x6600);
++              phy_write(port_no, 31, 0x0000);
++              phy_write(port_no, 24, 0xa24e);
++      }
++      else
++      {
++              phy_write(port_no, 31, 0x2a30);
++              phy_write_masked(port_no, 22, 0x0240, 0x0fc0);
++              phy_write_masked(port_no, 20, 0x4000, 0x6000);
++              phy_write(port_no, 31, 1);
++              phy_write_masked(port_no, 20, 0x6000, 0xe000);
++              phy_write(port_no, 31, 0x0000);
++      }
++}
++
++int Get_Set_port_status()
++{
++      unsigned int    reg_val,ability,rcv_mask,mac_config;
++      int is_link=0;
++      int i;
++
++      rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
++
++      for(i=0;i<4;i++){
++              reg_val = phy_read(i,1);
++              if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */
++              {
++                      is_link=1;
++                      if(switch_pre_link[i]==LINK_DOWN){              // Link Down ==> Link up
++
++                              rcv_mask |= BIT(i);                     // Enable receive
++
++                              reg_val = phy_read(i,10);
++                              if(reg_val & 0x0c00){
++                                      printk("Port%d:Giga mode\n",i);
++//                                    SPI_write(1,i,0x00,0x300701B1);
++                                      mac_config = 0x00060004|(6<<6);
++
++                                      SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030);       // reset port
++                                      mac_config |= (( BIT(i) << 19) | 0x08000000);
++                                      SPI_write(1,i,0x00,mac_config);
++                                      SPI_write(1,i,0x04,0x000300ff);         // flow control
++
++                                      reg_val = SPI_read(5,0,0x12);
++                                      reg_val &= ~BIT(i);
++                                      SPI_write(5,0,0x12,reg_val);
++
++                                      reg_val = SPI_read(1,i,0x00);
++                                      reg_val |= 0x10010000;
++                                      SPI_write(1,i,0x00,reg_val);
++//                                    SPI_write(1,i,0x00,0x10070181);
++                                      switch_pre_link[i]=LINK_UP;
++                                      switch_pre_speed[i]=GMAC_SPEED_1000;
++                              }
++                              else{
++                                      reg_val = phy_read(i,5);
++                                      ability = (reg_val&0x5e0) >>5;
++                                      if ((ability & 0x0C)) /* 100M */
++                                      {
++//                                            SPI_write(1,i,0x00,0x30050472);
++                                              if((ability&0x08)==0)           // Half
++                                                      mac_config = 0x00040004 |(17<<6);
++                                              else                            // Full
++                                                      mac_config = 0x00040004 |(17<<6);
++
++                                              SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030);       // reset port
++                                              mac_config |= (( BIT(i) << 19) | 0x08000000);
++                                              SPI_write(1,i,0x00,mac_config);
++                                              SPI_write(1,i,0x04,0x000300ff);         // flow control
++
++                                              reg_val = SPI_read(5,0,0x12);
++                                              reg_val &= ~BIT(i);
++                                              SPI_write(5,0,0x12,reg_val);
++
++                                              reg_val = SPI_read(1,i,0x00);
++                                              reg_val &= ~0x08000000;
++                                              reg_val |= 0x10010000;
++                                              SPI_write(1,i,0x00,reg_val);
++//                                            SPI_write(1,i,0x00,0x10050442);
++                                              printk("Port%d:100M\n",i);
++                                              switch_pre_link[i]=LINK_UP;
++                                              switch_pre_speed[i]=GMAC_SPEED_100;
++                                      }
++                                      else if((ability & 0x03)) /* 10M */
++                                      {
++//                                            SPI_write(1,i,0x00,0x30050473);
++                                              if((ability&0x2)==0)            // Half
++                                                      mac_config = 0x00040004 |(17<<6);
++                                              else                            // Full
++                                                      mac_config = 0x00040004 |(17<<6);
++
++                                              SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030);       // reset port
++                                              mac_config |= (( BIT(i) << 19) | 0x08000000);
++                                              SPI_write(1,i,0x00,mac_config);
++                                              SPI_write(1,i,0x04,0x000300ff);         // flow control
++
++                                              reg_val = SPI_read(5,0,0x12);
++                                              reg_val &= ~BIT(i);
++                                              SPI_write(5,0,0x12,reg_val);
++
++                                              reg_val = SPI_read(1,i,0x00);
++                                              reg_val &= ~0x08000000;
++                                              reg_val |= 0x10010000;
++                                              SPI_write(1,i,0x00,reg_val);
++//                                            SPI_write(1,i,0x00,0x10050443);
++                                              printk("Port%d:10M\n",i);
++                                              switch_pre_link[i]=LINK_UP;
++                                              switch_pre_speed[i]=GMAC_SPEED_10;
++                                      }
++                                      else{
++                                              SPI_write(1,i,0x00,0x20000030);
++                                              printk("Port%d:Unknown mode\n",i);
++                                              switch_pre_link[i]=LINK_DOWN;
++                                              switch_pre_speed[i]=GMAC_SPEED_10;
++                                      }
++                              }
++                      }
++                      else{                                           // Link up ==> Link UP
++
++                      }
++              }
++              else{                                                   // Link Down
++                      if(switch_pre_link[i]==LINK_UP){
++                              printk("Port%d:Link Down\n",i);
++                              //phy_receiver_init(i);
++                              reg_val = SPI_read(1,i,0);
++                              reg_val &= ~BIT(16);
++                              SPI_write(1,i,0x00,reg_val);                    // disable RX
++                              SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
++                              while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
++                                      msleep(1);
++                              SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
++                              SPI_write(5,0,0x0E,SPI_read(5,0,0x0E) & ~BIT(i));// accept packet
++
++                              reg_val = SPI_read(5,0,0x12);
++                              reg_val |= BIT(i);
++                              SPI_write(5,0,0x12,reg_val);
++                      }
++                      switch_pre_link[i]=LINK_DOWN;
++                      rcv_mask &= ~BIT(i);                    // disable receive
++              }
++      }
++
++      SPI_write(2,0,0x10,rcv_mask);                   // Receive mask
++      return is_link;
++
++}
++EXPORT_SYMBOL(Get_Set_port_status);
++
++void SPI_write(unsigned char block,unsigned char subblock,unsigned char addr,unsigned int value)
++{
++      int     i;
++      char    bit;
++      unsigned int data;
++
++      SPI_CS_enable(1);
++
++      data = (block<<5) | 0x10 | subblock;
++
++      //send write command
++      for(i=SPI_OP_LEN-1;i>=0;i--)
++      {
++              bit = (data>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++
++      // send 8 bits address (MSB first, LSB last)
++      for(i=SPI_ADD_LEN-1;i>=0;i--)
++      {
++              bit = (addr>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++      // send 32 bits data (MSB first, LSB last)
++      for(i=SPI_DAT_LEN-1;i>=0;i--)
++      {
++              bit = (value>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++
++      SPI_CS_enable(0);       // CS low
++
++}
++
++
++/************************************
++* SPI_write_bit
++* bit_EEDO -> 1 or 0 to be written
++************************************/
++void SPI_write_bit(char bit_EEDO)
++{
++      unsigned int addr;
++      unsigned int value;
++
++      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
++      value = readl(addr) |GPIO_EECK |GPIO_MOSI ;   /* set EECK/MISO Pin to output */
++      writel(value,addr);
++      if(bit_EEDO)
++      {
++              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_SET);
++              writel(GPIO_MOSI,addr); /* set MISO to 1 */
++
++      }
++      else
++      {
++              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
++              writel(GPIO_MOSI,addr); /* set MISO to 0 */
++      }
++      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_SET);
++      writel(GPIO_EECK,addr); /* set EECK to 1 */
++      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
++      writel(GPIO_EECK,addr); /* set EECK to 0 */
++
++      //return ;
++}
++
++/**********************************************************************
++* read a bit from ADM6996 register
++***********************************************************************/
++unsigned int SPI_read_bit(void) // read data from
++{
++      unsigned int addr;
++      unsigned int value;
++
++      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
++      value = readl(addr) & (~GPIO_MISO);   // set EECK to output and MISO to input
++      writel(value,addr);
++
++      addr =(GPIO_BASE_ADDR1 + GPIO_DATA_SET);
++      writel(GPIO_EECK,addr); // set EECK to 1
++
++
++      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_IN);
++      value = readl(addr) ;
++
++      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
++      writel(GPIO_EECK,addr); // set EECK to 0
++
++
++      value = value >> 30;
++      return value ;
++}
++
++/******************************************
++* SPI_default
++* EEPROM content default value
++*******************************************/
++int SPI_default(void)
++{
++      int i;
++      unsigned reg_val,cmd;
++
++#if 0
++      SPI_write(7,0,0x1C,0x01);                               // map code space to 0
++
++      reg_val = SPI_read(7,0,0x10);
++      reg_val |= 0x0146;
++      reg_val &= ~0x0001;
++      SPI_write(7,0,0x10,reg_val);                            // reset iCPU and enable ext_access
++      SPI_write(7,0,0x11,0x0000);                             // start address
++      for(i=0;i<sizeof(vts_img);i++){
++              SPI_write(7,0,0x12,vts_img[i]);                 // fill in ROM data
++      }
++      reg_val |= BIT(0)|BIT(3);
++      SPI_write(7,0,0x10,reg_val);                            // release iCPU
++      SPI_write(7,0,0x10,SPI_read(7,0,0x10)&~BIT(7));                         // release iCPU
++      return ;
++#endif
++
++
++      for(i=0;i<15;i++){
++              if(i!=6 && i!=7)
++                      SPI_write(3,2,0,0x1010400+i);           // Initial memory
++              mdelay(1);
++      }
++
++      mdelay(30);
++
++      SPI_write(2,0,0xB0,0x05);                       // Clear MAC table
++      SPI_write(2,0,0xD0,0x03);                       // Clear VLAN
++
++      //for(i=0;i<5;i++)
++      SPI_write(1,6,0x19,0x2C);                       // Double Data rate
++
++      for(i=0;i<4;i++){
++              SPI_write(1,i,0x00,0x30050472);         // MAC configure
++              SPI_write(1,i,0x00,0x10050442);         // MAC configure
++              SPI_write(1,i,0x10,0x5F4);              // Max length
++              SPI_write(1,i,0x04,0x00030000);         // Flow control
++              SPI_write(1,i,0xDF,0x00000001);         // Flow control
++              SPI_write(1,i,0x08,0x000050c2);         // Flow control mac high
++              SPI_write(1,i,0x0C,0x002b00f1);         // Flow control mac low
++              SPI_write(1,i,0x6E,BIT(3));             // forward pause frame
++      }
++      SPI_write(1,i,0x00,0x20000030);                 // set port 4 as reset
++
++      SPI_write(1,6,0x00,0x300701B1);                 // MAC configure
++      SPI_write(1,6,0x00,0x10070181);                 // MAC configure
++      SPI_write(1,6,0x10,0x5F4);                      // Max length
++      SPI_write(1,6,0x04,0x00030000);         // Flow control
++      SPI_write(1,6,0xDF,0x00000002);         // Flow control
++      SPI_write(1,6,0x08,0x000050c2);         // Flow control mac high
++      SPI_write(1,6,0x0C,0x002b00f1);         // Flow control mac low
++      SPI_write(1,6,0x6E,BIT(3));             // forward pause frame
++
++
++      //SPI_write(7,0,0x05,0x31);                     // MII delay for loader
++      //SPI_write(7,0,0x05,0x01);                     // MII delay for kernel
++      SPI_write(7,0,0x05,0x33);
++
++      SPI_write(2,0,0x10,0x4F);                       // Receive mask
++
++      mdelay(50);
++
++      SPI_write(7,0,0x14,0x02);                       // Release Reset
++
++      mdelay(3);
++
++      for(i=0;i<4;i++){
++              init_seq_7385(i);
++              phy_receiver_init(i);
++              cmd = BIT(26)|(i<<21)|(0x1B<<16);       // Config LED
++              SPI_write(3,0,1,cmd);
++              mdelay(10);
++              reg_val = SPI_read(3,0,2);
++              reg_val &= 0xFF00;
++              reg_val |= 0x61;
++              cmd = (i<<21)|(0x1B<<16)|reg_val;
++              SPI_write(3,0,1,cmd);
++
++              cmd = BIT(26)|(i<<21)|(0x04<<16);       // Pause enable
++              SPI_write(3,0,1,cmd);
++              mdelay(10);
++              reg_val = SPI_read(3,0,2);
++              reg_val |= BIT(10)|BIT(11);
++              cmd = (i<<21)|(0x04<<16)|reg_val;
++              SPI_write(3,0,1,cmd);
++
++              cmd = BIT(26)|(i<<21)|(0x0<<16);        // collision test and re-negotiation
++              SPI_write(3,0,1,cmd);
++              mdelay(10);
++              reg_val = SPI_read(3,0,2);
++              reg_val |= BIT(7)|BIT(8)|BIT(9);
++              cmd = (i<<21)|(0x0<<16)|reg_val;
++              SPI_write(3,0,1,cmd);
++      }
++      init_seq_7385(i);
++      writel(0x5787a7f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For switch timing
++      return 4;               // return port_no
++}
++EXPORT_SYMBOL(SPI_default);
++
++/***********************************************************
++* SPI_CS_enable
++* before access ,you have to enable Chip Select. (pull high)
++* When fisish, you should pull low !!
++*************************************************************/
++void SPI_CS_enable(unsigned char enable)
++{
++
++      unsigned int addr,value;
++
++      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
++      value = readl(addr) |GPIO_EECS |GPIO_EECK;   /* set EECS/EECK Pin to output */
++      writel(value,addr);
++
++      if(enable)
++      {
++              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
++              writel(GPIO_EECK,addr); /* set EECK to 0 */     // pull low clk first
++              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
++              writel(GPIO_EECS,addr); /* set EECS to 0 */
++
++      }
++      else
++      {
++              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_SET);
++              writel(GPIO_EECK,addr); /* set EECK to 1 */     // pull high clk before disable
++              writel(GPIO_EECS,addr); /* set EECS to 1 */
++      }
++}
++
++
++/************************************************
++* SPI_read
++* table -> which table to be read: 1/count  0/EEPROM
++* addr  -> Address to be read
++* return : Value of the register
++*************************************************/
++unsigned int SPI_read(unsigned char block,unsigned char subblock,unsigned char addr)
++{
++      int     i;
++      char    bit;
++      unsigned int data,value=0;
++
++      SPI_CS_enable(1);
++
++      data = (block<<5) | subblock;
++
++      //send write command
++      for(i=SPI_OP_LEN-1;i>=0;i--)
++      {
++              bit = (data>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++
++      // send 8 bits address (MSB first, LSB last)
++      for(i=SPI_ADD_LEN-1;i>=0;i--)
++      {
++              bit = (addr>>i)& 0x01;
++              SPI_write_bit(bit);
++      }
++
++      // dummy read for chip ready
++      for(i=0;i<8;i++)
++              SPI_read_bit();
++
++
++      // read 32 bits data (MSB first, LSB last)
++      for(i=SPI_DAT_LEN-1;i>=0;i--)
++      {
++              bit = SPI_read_bit();
++              value |= bit<<i;
++      }
++
++      SPI_CS_enable(0);       // CS low
++      return(value);
++
++}
++
++void pull_low_gpio(unsigned int val)
++{
++
++      unsigned int addr,value;
++
++      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
++      writel(val,addr); /* set pin low to save power*/
++
++      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
++      value = readl(addr) & ~ val;   /* set Pin to input */
++      writel(value,addr);
++
++//    value = readl(GMAC_GLOBAL_BASE_ADDR+0x0C);      // reset GPIO1 module(self clear)
++//    value |= BIT(21);
++//    writel(value,GMAC_GLOBAL_BASE_ADDR+0x0C);
++}
++
++unsigned int SPI_get_identifier(void)
++{
++      unsigned int flag=0;
++
++      SPI_write(7,0,0x01,0x01);
++      flag = SPI_read(7,0,0x18);  // chip id
++      if((flag & 0x0ffff000)==0x07385000){
++              printk("Get VSC-switch ID 0x%08x\n",flag);
++              //Giga_switch = 1;;
++              return 1;
++      }
++      else{
++              printk("VSC-switch not found\n");
++              //Giga_switch = 0;
++              pull_low_gpio(GPIO_EECK|GPIO_MOSI|GPIO_MISO|GPIO_EECS); // reduce power consume
++              return 0;
++      }
++}
++EXPORT_SYMBOL(SPI_get_identifier);
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/sl351x_gmac.h
+@@ -0,0 +1,2223 @@
++/****************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
++*--------------------------------------------------------------------------
++* Name                        : sl351x_gmac.h
++* Description :
++*             Define for device driver of Storlink SL351x network Engine
++*
++* Historych
++*
++*     Date            Writer          Description
++*     -----------     -----------     -------------------------------------------------
++*     08/22/2005      Gary Chen       Create and implement
++*
++****************************************************************************/
++#ifndef _GMAC_SL351x_H
++#define _GMAC_SL351x_H
++#include <linux/skbuff.h>
++
++#define SL351x_GMAC_WORKAROUND                1
++
++#undef BIG_ENDIAN
++#define BIG_ENDIAN                            0
++#define GMAC_DEBUG                            1
++#define GMAC_NUM                                      2
++//#define     L2_jumbo_frame                          1
++
++#define _PACKED_                                      __attribute__ ((aligned(1), packed))
++
++#ifndef BIT
++#define BIT(x)                                                (1 << (x))
++#endif
++
++#define REG32(addr)                           (*(volatile unsigned long  * const)(addr))
++
++#define DMA_MALLOC(size,handle)               pci_alloc_consistent(NULL,size,handle)
++#define DMA_MFREE(mem,size,handle)    pci_free_consistent(NULL,size,mem,handle)
++
++// Define frame size
++#define ETHER_ADDR_LEN                                6
++#define GMAC_MAX_ETH_FRAME_SIZE               1514
++#define GMAC_TX_BUF_SIZE                      ((GMAC_MAX_ETH_FRAME_SIZE + 31) & (~31))
++#define MAX_ISR_WORK                  20
++
++#ifdef        L2_jumbo_frame
++#define SW_RX_BUF_SIZE                                9234    // 2048 ,9234
++#else
++#define SW_RX_BUF_SIZE                                1536    // 2048
++#endif
++
++#define HW_RX_BUF_SIZE                                1536    // 2048
++
++#define GMAC_DEV_TX_TIMEOUT           (10*HZ)                 //add by CH
++#define       SKB_RESERVE_BYTES                       16
++
++/**********************************************************************
++ * Base Register
++ **********************************************************************/
++#define TOE_BASE                                      (IO_ADDRESS(SL2312_TOE_BASE))
++#define GMAC_GLOBAL_BASE_ADDR       (IO_ADDRESS(SL2312_GLOBAL_BASE))
++
++#define TOE_GLOBAL_BASE                               (TOE_BASE + 0x0000)
++#define TOE_NONTOE_QUE_HDR_BASE               (TOE_BASE + 0x2000)
++#define TOE_TOE_QUE_HDR_BASE          (TOE_BASE + 0x3000)
++#define TOE_V_BIT_BASE                                (TOE_BASE + 0x4000)
++#define TOE_A_BIT_BASE                                (TOE_BASE + 0x6000)
++#define TOE_GMAC0_DMA_BASE                    (TOE_BASE + 0x8000)
++#define TOE_GMAC0_BASE                                (TOE_BASE + 0xA000)
++#define TOE_GMAC1_DMA_BASE                    (TOE_BASE + 0xC000)
++#define TOE_GMAC1_BASE                                (TOE_BASE + 0xE000)
++
++/**********************************************************************
++ * Queue ID
++ **********************************************************************/
++#define TOE_SW_FREE_QID                               0x00
++#define TOE_HW_FREE_QID                               0x01
++#define TOE_GMAC0_SW_TXQ0_QID         0x02
++#define TOE_GMAC0_SW_TXQ1_QID         0x03
++#define TOE_GMAC0_SW_TXQ2_QID         0x04
++#define TOE_GMAC0_SW_TXQ3_QID         0x05
++#define TOE_GMAC0_SW_TXQ4_QID         0x06
++#define TOE_GMAC0_SW_TXQ5_QID         0x07
++#define TOE_GMAC0_HW_TXQ0_QID         0x08
++#define TOE_GMAC0_HW_TXQ1_QID         0x09
++#define TOE_GMAC0_HW_TXQ2_QID         0x0A
++#define TOE_GMAC0_HW_TXQ3_QID         0x0B
++#define TOE_GMAC1_SW_TXQ0_QID         0x12
++#define TOE_GMAC1_SW_TXQ1_QID         0x13
++#define TOE_GMAC1_SW_TXQ2_QID         0x14
++#define TOE_GMAC1_SW_TXQ3_QID         0x15
++#define TOE_GMAC1_SW_TXQ4_QID         0x16
++#define TOE_GMAC1_SW_TXQ5_QID         0x17
++#define TOE_GMAC1_HW_TXQ0_QID         0x18
++#define TOE_GMAC1_HW_TXQ1_QID         0x19
++#define TOE_GMAC1_HW_TXQ2_QID         0x1A
++#define TOE_GMAC1_HW_TXQ3_QID         0x1B
++#define TOE_GMAC0_DEFAULT_QID         0x20
++#define TOE_GMAC1_DEFAULT_QID         0x21
++#define TOE_CLASSIFICATION_QID(x)     (0x22 + x)      // 0x22 ~ 0x2F
++#define TOE_TOE_QID(x)                                (0x40 + x)      // 0x40 ~ 0x7F
++
++/**********************************************************************
++ * TOE DMA Queue Number should be 2^n, n = 6...12
++ * TOE DMA Queues are the following queue types:
++ *            SW Free Queue, HW Free Queue,
++ *            GMAC 0/1 SW TX Q0-5, and GMAC 0/1 HW TX Q0-5
++ * They have same descriptor numbers.
++ * The base address and descriptor number are configured at
++ * DMA Queues Descriptor Ring Base Address/Size Register (offset 0x0004)
++ **********************************************************************/
++#define TOE_SW_FREEQ_DESC_POWER               10
++#define TOE_SW_FREEQ_DESC_NUM         (1<<TOE_SW_FREEQ_DESC_POWER)
++#define TOE_HW_FREEQ_DESC_POWER               8
++#define TOE_HW_FREEQ_DESC_NUM         (1<<TOE_HW_FREEQ_DESC_POWER)
++#define TOE_GMAC0_SWTXQ_DESC_POWER    8
++#define TOE_GMAC0_SWTXQ_DESC_NUM      (1<<TOE_GMAC0_SWTXQ_DESC_POWER)
++#define TOE_GMAC0_HWTXQ_DESC_POWER    8
++#define TOE_GMAC0_HWTXQ_DESC_NUM      (1<<TOE_GMAC0_HWTXQ_DESC_POWER)
++#define TOE_GMAC1_SWTXQ_DESC_POWER    8
++#define TOE_GMAC1_SWTXQ_DESC_NUM      (1<<TOE_GMAC1_SWTXQ_DESC_POWER)
++#define TOE_GMAC1_HWTXQ_DESC_POWER    8
++#define TOE_GMAC1_HWTXQ_DESC_NUM      (1<<TOE_GMAC1_HWTXQ_DESC_POWER)
++#define TOE_DEFAULT_Q0_DESC_POWER     8
++#define TOE_DEFAULT_Q0_DESC_NUM               (1<<TOE_DEFAULT_Q0_DESC_POWER)
++#define TOE_DEFAULT_Q1_DESC_POWER     8
++#define TOE_DEFAULT_Q1_DESC_NUM               (1<<TOE_DEFAULT_Q1_DESC_POWER)
++#define TOE_TOE_DESC_POWER                    8
++#define TOE_TOE_DESC_NUM                      (1<<TOE_TOE_DESC_POWER)
++#define TOE_CLASS_DESC_POWER          8
++#define TOE_CLASS_DESC_NUM                    (1<<TOE_CLASS_DESC_POWER)
++#define TOE_INTR_DESC_POWER                   8
++#define TOE_INTR_DESC_NUM                     (1<<TOE_INTR_DESC_POWER)
++
++#define TOE_TOE_QUEUE_MAX                     64
++#define TOE_TOE_QUEUE_NUM                     64
++#define TOE_CLASS_QUEUE_MAX                   14
++#define TOE_CLASS_QUEUE_NUM                   14
++#define TOE_INTR_QUEUE_MAX                    4
++#define TOE_INTR_QUEUE_NUM                    4
++#define TOE_SW_TXQ_MAX                                6
++#define TOE_SW_TXQ_NUM                                1
++#define TOE_HW_TXQ_MAX                                4
++#define TOE_HW_TXQ_NUM                                4
++#define _max(x,y)                                     ((x>y) ? x :y)
++#define TX_DESC_NUM                                   _max(TOE_GMAC0_SWTXQ_DESC_NUM, TOE_GMAC1_SWTXQ_DESC_NUM)
++
++#define RWPTR_ADVANCE_ONE(x, max)     ((x == (max -1)) ? 0 : x+1)
++#define RWPTR_RECEDE_ONE(x, max)      ((x == 0) ? (max -1) : x-1)
++#define SET_WPTR(addr, data)          (*(volatile u16 * const)((u32)(addr)+2) = (u16)data)
++#define SET_RPTR(addr, data)          (*(volatile u16 * const)((u32)(addr)) = (u16)data)
++
++/**********************************************************************
++ * Global registers
++ * #define TOE_GLOBAL_BASE                    (TOE_BASE + 0x0000)
++ * Base 0x60000000
++ **********************************************************************/
++#define GLOBAL_TOE_VERSION_REG                        0x0000
++#define GLOBAL_SW_FREEQ_BASE_SIZE_REG 0x0004
++#define GLOBAL_HW_FREEQ_BASE_SIZE_REG 0x0008
++#define GLOBAL_DMA_SKB_SIZE_REG                       0x0010
++#define GLOBAL_SWFQ_RWPTR_REG                 0x0014
++#define GLOBAL_HWFQ_RWPTR_REG                 0x0018
++#define GLOBAL_INTERRUPT_STATUS_0_REG 0x0020
++#define GLOBAL_INTERRUPT_ENABLE_0_REG 0x0024
++#define GLOBAL_INTERRUPT_SELECT_0_REG 0x0028
++#define GLOBAL_INTERRUPT_STATUS_1_REG 0x0030
++#define GLOBAL_INTERRUPT_ENABLE_1_REG 0x0034
++#define GLOBAL_INTERRUPT_SELECT_1_REG 0x0038
++#define GLOBAL_INTERRUPT_STATUS_2_REG 0x0040
++#define GLOBAL_INTERRUPT_ENABLE_2_REG 0x0044
++#define GLOBAL_INTERRUPT_SELECT_2_REG 0x0048
++#define GLOBAL_INTERRUPT_STATUS_3_REG 0x0050
++#define GLOBAL_INTERRUPT_ENABLE_3_REG 0x0054
++#define GLOBAL_INTERRUPT_SELECT_3_REG 0x0058
++#define GLOBAL_INTERRUPT_STATUS_4_REG 0x0060
++#define GLOBAL_INTERRUPT_ENABLE_4_REG 0x0064
++#define GLOBAL_INTERRUPT_SELECT_4_REG 0x0068
++#define GLOBAL_HASH_TABLE_BASE_REG            0x006C
++#define GLOBAL_QUEUE_THRESHOLD_REG            0x0070
++
++/**********************************************************************
++ * GMAC 0/1 DMA/TOE register
++ * #define TOE_GMAC0_DMA_BASE         (TOE_BASE + 0x8000)
++ * #define TOE_GMAC1_DMA_BASE         (TOE_BASE + 0xC000)
++ * Base 0x60008000 or 0x6000C000
++ **********************************************************************/
++#define GMAC_DMA_CTRL_REG                             0x0000
++#define GMAC_TX_WEIGHTING_CTRL_0_REG  0x0004
++#define GMAC_TX_WEIGHTING_CTRL_1_REG  0x0008
++#define GMAC_SW_TX_QUEUE0_PTR_REG             0x000C
++#define GMAC_SW_TX_QUEUE1_PTR_REG             0x0010
++#define GMAC_SW_TX_QUEUE2_PTR_REG             0x0014
++#define GMAC_SW_TX_QUEUE3_PTR_REG             0x0018
++#define GMAC_SW_TX_QUEUE4_PTR_REG             0x001C
++#define GMAC_SW_TX_QUEUE5_PTR_REG             0x0020
++#define GMAC_HW_TX_QUEUE0_PTR_REG             0x0024
++#define GMAC_HW_TX_QUEUE1_PTR_REG             0x0028
++#define GMAC_HW_TX_QUEUE2_PTR_REG             0x002C
++#define GMAC_HW_TX_QUEUE3_PTR_REG             0x0030
++#define GMAC_DMA_TX_FIRST_DESC_REG            0x0038
++#define GMAC_DMA_TX_CURR_DESC_REG             0x003C
++#define GMAC_DMA_TX_DESC_WORD0_REG            0x0040
++#define GMAC_DMA_TX_DESC_WORD1_REG            0x0044
++#define GMAC_DMA_TX_DESC_WORD2_REG            0x0048
++#define GMAC_DMA_TX_DESC_WORD3_REG            0x004C
++#define GMAC_SW_TX_QUEUE_BASE_REG             0x0050
++#define GMAC_HW_TX_QUEUE_BASE_REG             0x0054
++#define GMAC_DMA_RX_FIRST_DESC_REG            0x0058
++#define GMAC_DMA_RX_CURR_DESC_REG             0x005C
++#define GMAC_DMA_RX_DESC_WORD0_REG            0x0060
++#define GMAC_DMA_RX_DESC_WORD1_REG            0x0064
++#define GMAC_DMA_RX_DESC_WORD2_REG            0x0068
++#define GMAC_DMA_RX_DESC_WORD3_REG            0x006C
++#define GMAC_HASH_ENGINE_REG0                 0x0070
++#define GMAC_HASH_ENGINE_REG1                 0x0074
++#define GMAC_MR0CR0                                           0x0078  // matching rule 0 Control register 0
++#define GMAC_MR0CR1                                           0x007C  // matching rule 0 Control register 1
++#define GMAC_MR0CR2                                           0x0080  // matching rule 0 Control register 2
++#define GMAC_MR1CR0                                           0x0084  // matching rule 1 Control register 0
++#define GMAC_MR1CR1                                           0x0088  // matching rule 1 Control register 1
++#define GMAC_MR1CR2                                           0x008C  // matching rule 1 Control register 2
++#define GMAC_MR2CR0                                           0x0090  // matching rule 2 Control register 0
++#define GMAC_MR2CR1                                           0x0094  // matching rule 2 Control register 1
++#define GMAC_MR2CR2                                           0x0098  // matching rule 2 Control register 2
++#define GMAC_MR3CR0                                           0x009C  // matching rule 3 Control register 0
++#define GMAC_MR3CR1                                           0x00A0  // matching rule 3 Control register 1
++#define GMAC_MR3CR2                                           0x00A4  // matching rule 3 Control register 2
++#define GMAC_SPR0                                             0x00A8  // Support Protocol Regsister 0
++#define GMAC_SPR1                                             0x00AC  // Support Protocol Regsister 1
++#define GMAC_SPR2                                             0x00B0  // Support Protocol Regsister 2
++#define GMAC_SPR3                                             0x00B4  // Support Protocol Regsister 3
++#define GMAC_SPR4                                             0x00B8  // Support Protocol Regsister 4
++#define GMAC_SPR5                                             0x00BC  // Support Protocol Regsister 5
++#define GMAC_SPR6                                             0x00C0  // Support Protocol Regsister 6
++#define GMAC_SPR7                                             0x00C4  // Support Protocol Regsister 7
++#define GMAC_AHB_WEIGHT_REG                           0x00C8  // GMAC Hash/Rx/Tx AHB Weighting register
++
++/**********************************************************************
++ * TOE GMAC 0/1 register
++ * #define TOE_GMAC0_BASE                             (TOE_BASE + 0xA000)
++ * #define TOE_GMAC1_BASE                             (TOE_BASE + 0xE000)
++ * Base 0x6000A000 or 0x6000E000
++ **********************************************************************/
++enum GMAC_REGISTER {
++      GMAC_STA_ADD0   = 0x0000,
++      GMAC_STA_ADD1   = 0x0004,
++      GMAC_STA_ADD2   = 0x0008,
++      GMAC_RX_FLTR    = 0x000c,
++      GMAC_MCAST_FIL0 = 0x0010,
++      GMAC_MCAST_FIL1 = 0x0014,
++      GMAC_CONFIG0    = 0x0018,
++      GMAC_CONFIG1    = 0x001c,
++      GMAC_CONFIG2    = 0x0020,
++      GMAC_CONFIG3    = 0x0024,
++      GMAC_RESERVED   = 0x0028,
++      GMAC_STATUS             = 0x002c,
++      GMAC_IN_DISCARDS= 0x0030,
++      GMAC_IN_ERRORS  = 0x0034,
++      GMAC_IN_MCAST   = 0x0038,
++      GMAC_IN_BCAST   = 0x003c,
++      GMAC_IN_MAC1    = 0x0040,       // for STA 1 MAC Address
++      GMAC_IN_MAC2    = 0x0044        // for STA 2 MAC Address
++};
++/**********************************************************************
++ * TOE version Register (offset 0x0000)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int reserved           : 15;   // bit 31:17
++              unsigned int v_bit_mode         : 1;    // bit 16               1: 128-entry
++              unsigned int device_id          : 12;   // bit 15:4     Device ID
++              unsigned int revision_id        : 4;    // bit  3:0     Revision ID
++#else
++              unsigned int revision_id        : 4;    // bit  3:0     Revision ID
++              unsigned int device_id          : 12;   // bit 15:4     Device ID
++              unsigned int v_bit_mode         : 1;    // bit 16               1: 128-entry
++              unsigned int reserved           : 15;   // bit 31:17
++#endif
++      } bits;
++} TOE_VERSION_T;
++
++
++/**********************************************************************
++ * DMA Queues description Ring Base Address/Size Register (offset 0x0004)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      unsigned int base_size;
++} DMA_Q_BASE_SIZE_T;
++#define DMA_Q_BASE_MASK       (~0x0f)
++
++/**********************************************************************
++ * DMA SKB Buffer register (offset 0x0008)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_0008
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int hw_skb_size        : 16;   // bit 31:16    HW Free poll SKB Size
++              unsigned int sw_skb_size        : 16;   // bit 15:0     SW Free poll SKB Size
++#else
++              unsigned int sw_skb_size        : 16;   // bit 15:0     SW Free poll SKB Size
++              unsigned int hw_skb_size        : 16;   // bit 31:16    HW Free poll SKB Size
++#endif
++      } bits;
++} DMA_SKB_SIZE_T;
++
++/**********************************************************************
++ * DMA SW Free Queue Read/Write Pointer Register (offset 0x000C)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_000c
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int wptr                       : 16;   // bit 31:16    Write Ptr, RW
++              unsigned int rptr                       : 16;   // bit 15:0             Read Ptr, RO
++#else
++              unsigned int rptr                       : 16;   // bit 15:0             Read Ptr, RO
++              unsigned int wptr                       : 16;   // bit 31:16    Write Ptr, RW
++#endif
++      } bits;
++} DMA_RWPTR_T;
++
++/**********************************************************************
++ * DMA HW Free Queue Read/Write Pointer Register (offset 0x0010)
++ **********************************************************************/
++// see DMA_RWPTR_T structure
++
++/**********************************************************************
++ * Interrupt Status Register 0        (offset 0x0020)
++ * Interrupt Mask Register 0  (offset 0x0024)
++ * Interrupt Select Register 0        (offset 0x0028)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_0020
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int txDerr1            : 1;    // bit 31       GMAC1 AHB Bus Error while Tx
++              unsigned int txPerr1            : 1;    // bit 30       GMAC1 Tx Descriptor Protocol Error
++              unsigned int txDerr0            : 1;    // bit 29       GMAC0 AHB Bus Error while Tx
++              unsigned int txPerr0            : 1;    // bit 28       GMAC0 Tx Descriptor Protocol Error
++              unsigned int rxDerr1            : 1;    // bit 27       GMAC1 AHB Bus Error while Rx
++              unsigned int rxPerr1            : 1;    // bit 26       GMAC1 Rx Descriptor Protocol Error
++              unsigned int rxDerr0            : 1;    // bit 25       GMAC0 AHB Bus Error while Rx
++              unsigned int rxPerr0            : 1;    // bit 24       GMAC0 Rx Descriptor Protocol Error
++              unsigned int swtq15_fin         : 1;    // bit 23       GMAC1 SW Tx Queue 5 Finish Interrupt
++              unsigned int swtq14_fin         : 1;    // bit 22       GMAC1 SW Tx Queue 4 Finish Interrupt
++              unsigned int swtq13_fin         : 1;    // bit 21       GMAC1 SW Tx Queue 3 Finish Interrupt
++              unsigned int swtq12_fin         : 1;    // bit 20       GMAC1 SW Tx Queue 2 Finish Interrupt
++              unsigned int swtq11_fin         : 1;    // bit 19       GMAC1 SW Tx Queue 1 Finish Interrupt
++              unsigned int swtq10_fin         : 1;    // bit 18       GMAC1 SW Tx Queue 0 Finish Interrupt
++              unsigned int swtq05_fin         : 1;    // bit 17       GMAC0 SW Tx Queue 5 Finish Interrupt
++              unsigned int swtq04_fin         : 1;    // bit 16       GMAC0 SW Tx Queue 4 Finish Interrupt
++              unsigned int swtq03_fin         : 1;    // bit 15       GMAC0 SW Tx Queue 3 Finish Interrupt
++              unsigned int swtq02_fin         : 1;    // bit 14       GMAC0 SW Tx Queue 2 Finish Interrupt
++              unsigned int swtq01_fin         : 1;    // bit 13       GMAC0 SW Tx Queue 1 Finish Interrupt
++              unsigned int swtq00_fin         : 1;    // bit 12       GMAC0 SW Tx Queue 0 Finish Interrupt
++              unsigned int swtq15_eof         : 1;    // bit 11       GMAC1 SW Tx Queue 5 EOF Interrupt
++              unsigned int swtq14_eof         : 1;    // bit 10       GMAC1 SW Tx Queue 4 EOF Interrupt
++              unsigned int swtq13_eof         : 1;    // bit 9        GMAC1 SW Tx Queue 3 EOF Interrupt
++              unsigned int swtq12_eof         : 1;    // bit 8        GMAC1 SW Tx Queue 2 EOF Interrupt
++              unsigned int swtq11_eof         : 1;    // bit 7        GMAC1 SW Tx Queue 1 EOF Interrupt
++              unsigned int swtq10_eof         : 1;    // bit 6        GMAC1 SW Tx Queue 0 EOF Interrupt
++              unsigned int swtq05_eof         : 1;    // bit 5        GMAC0 SW Tx Queue 5 EOF Interrupt
++              unsigned int swtq04_eof         : 1;    // bit 4        GMAC0 SW Tx Queue 4 EOF Interrupt
++              unsigned int swtq03_eof         : 1;    // bit 3        GMAC0 SW Tx Queue 3 EOF Interrupt
++              unsigned int swtq02_eof         : 1;    // bit 2        GMAC0 SW Tx Queue 2 EOF Interrupt
++              unsigned int swtq01_eof         : 1;    // bit 1        GMAC0 SW Tx Queue 1 EOF Interrupt
++              unsigned int swtq00_eof         : 1;    // bit 0        GMAC0 SW Tx Queue 0 EOF Interrupt
++#else
++              unsigned int swtq00_eof         : 1;    // bit 0        GMAC0 SW Tx Queue 0 EOF Interrupt
++              unsigned int swtq01_eof         : 1;    // bit 1        GMAC0 SW Tx Queue 1 EOF Interrupt
++              unsigned int swtq02_eof         : 1;    // bit 2        GMAC0 SW Tx Queue 2 EOF Interrupt
++              unsigned int swtq03_eof         : 1;    // bit 3        GMAC0 SW Tx Queue 3 EOF Interrupt
++              unsigned int swtq04_eof         : 1;    // bit 4        GMAC0 SW Tx Queue 4 EOF Interrupt
++              unsigned int swtq05_eof         : 1;    // bit 5        GMAC0 SW Tx Queue 5 EOF Interrupt
++              unsigned int swtq10_eof         : 1;    // bit 6        GMAC1 SW Tx Queue 0 EOF Interrupt
++              unsigned int swtq11_eof         : 1;    // bit 7        GMAC1 SW Tx Queue 1 EOF Interrupt
++              unsigned int swtq12_eof         : 1;    // bit 8        GMAC1 SW Tx Queue 2 EOF Interrupt
++              unsigned int swtq13_eof         : 1;    // bit 9        GMAC1 SW Tx Queue 3 EOF Interrupt
++              unsigned int swtq14_eof         : 1;    // bit 10       GMAC1 SW Tx Queue 4 EOF Interrupt
++              unsigned int swtq15_eof         : 1;    // bit 11       GMAC1 SW Tx Queue 5 EOF Interrupt
++              unsigned int swtq00_fin         : 1;    // bit 12       GMAC0 SW Tx Queue 0 Finish Interrupt
++              unsigned int swtq01_fin         : 1;    // bit 13       GMAC0 SW Tx Queue 1 Finish Interrupt
++              unsigned int swtq02_fin         : 1;    // bit 14       GMAC0 SW Tx Queue 2 Finish Interrupt
++              unsigned int swtq03_fin         : 1;    // bit 15       GMAC0 SW Tx Queue 3 Finish Interrupt
++              unsigned int swtq04_fin         : 1;    // bit 16       GMAC0 SW Tx Queue 4 Finish Interrupt
++              unsigned int swtq05_fin         : 1;    // bit 17       GMAC0 SW Tx Queue 5 Finish Interrupt
++              unsigned int swtq10_fin         : 1;    // bit 18       GMAC1 SW Tx Queue 0 Finish Interrupt
++              unsigned int swtq11_fin         : 1;    // bit 19       GMAC1 SW Tx Queue 1 Finish Interrupt
++              unsigned int swtq12_fin         : 1;    // bit 20       GMAC1 SW Tx Queue 2 Finish Interrupt
++              unsigned int swtq13_fin         : 1;    // bit 21       GMAC1 SW Tx Queue 3 Finish Interrupt
++              unsigned int swtq14_fin         : 1;    // bit 22       GMAC1 SW Tx Queue 4 Finish Interrupt
++              unsigned int swtq15_fin         : 1;    // bit 23       GMAC1 SW Tx Queue 5 Finish Interrupt
++              unsigned int rxPerr0            : 1;    // bit 24       GMAC0 Rx Descriptor Protocol Error
++              unsigned int rxDerr0            : 1;    // bit 25       GMAC0 AHB Bus Error while Rx
++              unsigned int rxPerr1            : 1;    // bit 26       GMAC1 Rx Descriptor Protocol Error
++              unsigned int rxDerr1            : 1;    // bit 27       GMAC1 AHB Bus Error while Rx
++              unsigned int txPerr0            : 1;    // bit 28       GMAC0 Tx Descriptor Protocol Error
++              unsigned int txDerr0            : 1;    // bit 29       GMAC0 AHB Bus Error while Tx
++              unsigned int txPerr1            : 1;    // bit 30       GMAC1 Tx Descriptor Protocol Error
++              unsigned int txDerr1            : 1;    // bit 31       GMAC1 AHB Bus Error while Tx
++#endif
++      } bits;
++} INTR_REG0_T;
++
++#define GMAC1_TXDERR_INT_BIT          BIT(31)
++#define GMAC1_TXPERR_INT_BIT          BIT(30)
++#define GMAC0_TXDERR_INT_BIT          BIT(29)
++#define GMAC0_TXPERR_INT_BIT          BIT(28)
++#define GMAC1_RXDERR_INT_BIT          BIT(27)
++#define GMAC1_RXPERR_INT_BIT          BIT(26)
++#define GMAC0_RXDERR_INT_BIT          BIT(25)
++#define GMAC0_RXPERR_INT_BIT          BIT(24)
++#define GMAC1_SWTQ15_FIN_INT_BIT      BIT(23)
++#define GMAC1_SWTQ14_FIN_INT_BIT      BIT(22)
++#define GMAC1_SWTQ13_FIN_INT_BIT      BIT(21)
++#define GMAC1_SWTQ12_FIN_INT_BIT      BIT(20)
++#define GMAC1_SWTQ11_FIN_INT_BIT      BIT(19)
++#define GMAC1_SWTQ10_FIN_INT_BIT      BIT(18)
++#define GMAC0_SWTQ05_FIN_INT_BIT      BIT(17)
++#define GMAC0_SWTQ04_FIN_INT_BIT      BIT(16)
++#define GMAC0_SWTQ03_FIN_INT_BIT      BIT(15)
++#define GMAC0_SWTQ02_FIN_INT_BIT      BIT(14)
++#define GMAC0_SWTQ01_FIN_INT_BIT      BIT(13)
++#define GMAC0_SWTQ00_FIN_INT_BIT      BIT(12)
++#define GMAC1_SWTQ15_EOF_INT_BIT      BIT(11)
++#define GMAC1_SWTQ14_EOF_INT_BIT      BIT(10)
++#define GMAC1_SWTQ13_EOF_INT_BIT      BIT(9)
++#define GMAC1_SWTQ12_EOF_INT_BIT      BIT(8)
++#define GMAC1_SWTQ11_EOF_INT_BIT      BIT(7)
++#define GMAC1_SWTQ10_EOF_INT_BIT      BIT(6)
++#define GMAC0_SWTQ05_EOF_INT_BIT      BIT(5)
++#define GMAC0_SWTQ04_EOF_INT_BIT      BIT(4)
++#define GMAC0_SWTQ03_EOF_INT_BIT      BIT(3)
++#define GMAC0_SWTQ02_EOF_INT_BIT      BIT(2)
++#define GMAC0_SWTQ01_EOF_INT_BIT      BIT(1)
++#define GMAC0_SWTQ00_EOF_INT_BIT      BIT(0)
++
++
++/**********************************************************************
++ * Interrupt Status Register 1        (offset 0x0030)
++ * Interrupt Mask Register 1  (offset 0x0034)
++ * Interrupt Select Register 1        (offset 0x0038)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_0030
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int toe_iq3_full       : 1;    // bit 31       TOE Interrupt Queue 3 Full Interrupt
++              unsigned int toe_iq2_full       : 1;    // bit 30       TOE Interrupt Queue 2 Full Interrupt
++              unsigned int toe_iq1_full       : 1;    // bit 29       TOE Interrupt Queue 1 Full Interrupt
++              unsigned int toe_iq0_full       : 1;    // bit 28       TOE Interrupt Queue 0 Full Interrupt
++              unsigned int toe_iq3_intr       : 1;    // bit 27       TOE Interrupt Queue 3 with Interrupts
++              unsigned int toe_iq2_intr       : 1;    // bit 26       TOE Interrupt Queue 2 with Interrupts
++              unsigned int toe_iq1_intr       : 1;    // bit 25       TOE Interrupt Queue 1 with Interrupts
++              unsigned int toe_iq0_intr       : 1;    // bit 24       TOE Interrupt Queue 0 with Interrupts
++              unsigned int hwtq13_eof         : 1;    // bit 23       GMAC1 HW Tx Queue3 EOF Interrupt
++              unsigned int hwtq12_eof         : 1;    // bit 22       GMAC1 HW Tx Queue2 EOF Interrupt
++              unsigned int hwtq11_eof         : 1;    // bit 21       GMAC1 HW Tx Queue1 EOF Interrupt
++              unsigned int hwtq10_eof         : 1;    // bit 20       GMAC1 HW Tx Queue0 EOF Interrupt
++              unsigned int hwtq03_eof         : 1;    // bit 19       GMAC0 HW Tx Queue3 EOF Interrupt
++              unsigned int hwtq02_eof         : 1;    // bit 18       GMAC0 HW Tx Queue2 EOF Interrupt
++              unsigned int hwtq01_eof         : 1;    // bit 17       GMAC0 HW Tx Queue1 EOF Interrupt
++              unsigned int hwtq00_eof         : 1;    // bit 16       GMAC0 HW Tx Queue0 EOF Interrupt
++              unsigned int class_rx           : 14;   // bit 15:2     Classification Queue Rx Interrupt
++              unsigned int default_q1_eof     : 1;    // bit 1        Default Queue 1 EOF Interrupt
++              unsigned int default_q0_eof     : 1;    // bit 0        Default Queue 0 EOF Interrupt
++#else
++              unsigned int default_q0_eof     : 1;    // bit 0        Default Queue 0 EOF Interrupt
++              unsigned int default_q1_eof     : 1;    // bit 1        Default Queue 1 EOF Interrupt
++              unsigned int class_rx           : 14;   // bit 15:2     Classification Queue Rx Interrupt
++              unsigned int hwtq00_eof         : 1;    // bit 16       GMAC0 HW Tx Queue0 EOF Interrupt
++              unsigned int hwtq01_eof         : 1;    // bit 17       GMAC0 HW Tx Queue1 EOF Interrupt
++              unsigned int hwtq02_eof         : 1;    // bit 18       GMAC0 HW Tx Queue2 EOF Interrupt
++              unsigned int hwtq03_eof         : 1;    // bit 19       GMAC0 HW Tx Queue3 EOF Interrupt
++              unsigned int hwtq10_eof         : 1;    // bit 20       GMAC1 HW Tx Queue0 EOF Interrupt
++              unsigned int hwtq11_eof         : 1;    // bit 21       GMAC1 HW Tx Queue1 EOF Interrupt
++              unsigned int hwtq12_eof         : 1;    // bit 22       GMAC1 HW Tx Queue2 EOF Interrupt
++              unsigned int hwtq13_eof         : 1;    // bit 23       GMAC1 HW Tx Queue3 EOF Interrupt
++              unsigned int toe_iq0_intr       : 1;    // bit 24       TOE Interrupt Queue 0 with Interrupts
++              unsigned int toe_iq1_intr       : 1;    // bit 25       TOE Interrupt Queue 1 with Interrupts
++              unsigned int toe_iq2_intr       : 1;    // bit 26       TOE Interrupt Queue 2 with Interrupts
++              unsigned int toe_iq3_intr       : 1;    // bit 27       TOE Interrupt Queue 3 with Interrupts
++              unsigned int toe_iq0_full       : 1;    // bit 28       TOE Interrupt Queue 0 Full Interrupt
++              unsigned int toe_iq1_full       : 1;    // bit 29       TOE Interrupt Queue 1 Full Interrupt
++              unsigned int toe_iq2_full       : 1;    // bit 30       TOE Interrupt Queue 2 Full Interrupt
++              unsigned int toe_iq3_full       : 1;    // bit 31       TOE Interrupt Queue 3 Full Interrupt
++#endif
++      } bits;
++} INTR_REG1_T;
++
++#define TOE_IQ3_FULL_INT_BIT          BIT(31)
++#define TOE_IQ2_FULL_INT_BIT          BIT(30)
++#define TOE_IQ1_FULL_INT_BIT          BIT(29)
++#define TOE_IQ0_FULL_INT_BIT          BIT(28)
++#define TOE_IQ3_INT_BIT                               BIT(27)
++#define TOE_IQ2_INT_BIT                               BIT(26)
++#define TOE_IQ1_INT_BIT                               BIT(25)
++#define TOE_IQ0_INT_BIT                               BIT(24)
++#define GMAC1_HWTQ13_EOF_INT_BIT      BIT(23)
++#define GMAC1_HWTQ12_EOF_INT_BIT      BIT(22)
++#define GMAC1_HWTQ11_EOF_INT_BIT      BIT(21)
++#define GMAC1_HWTQ10_EOF_INT_BIT      BIT(20)
++#define GMAC0_HWTQ03_EOF_INT_BIT      BIT(19)
++#define GMAC0_HWTQ02_EOF_INT_BIT      BIT(18)
++#define GMAC0_HWTQ01_EOF_INT_BIT      BIT(17)
++#define GMAC0_HWTQ00_EOF_INT_BIT      BIT(16)
++#define CLASS_RX_INT_BIT(x)                   BIT((x+2))
++#define DEFAULT_Q1_INT_BIT                    BIT(1)
++#define DEFAULT_Q0_INT_BIT                    BIT(0)
++
++#define TOE_IQ_INT_BITS                               (TOE_IQ0_INT_BIT | TOE_IQ1_INT_BIT | \
++                                                      TOE_IQ2_INT_BIT | TOE_IQ3_INT_BIT)
++#define       TOE_IQ_FULL_BITS                        (TOE_IQ0_FULL_INT_BIT | TOE_IQ1_FULL_INT_BIT | \
++                                                      TOE_IQ2_FULL_INT_BIT | TOE_IQ3_FULL_INT_BIT)
++#define       TOE_IQ_ALL_BITS                         (TOE_IQ_INT_BITS | TOE_IQ_FULL_BITS)
++#define TOE_CLASS_RX_INT_BITS         0xfffc
++
++/**********************************************************************
++ * Interrupt Status Register 2        (offset 0x0040)
++ * Interrupt Mask Register 2  (offset 0x0044)
++ * Interrupt Select Register 2        (offset 0x0048)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_0040
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int toe_q31_full       : 1;    // bit 31       TOE Queue 31 Full Interrupt
++              unsigned int toe_q30_full       : 1;    // bit 30       TOE Queue 30 Full Interrupt
++              unsigned int toe_q29_full       : 1;    // bit 29       TOE Queue 29 Full Interrupt
++              unsigned int toe_q28_full       : 1;    // bit 28       TOE Queue 28 Full Interrupt
++              unsigned int toe_q27_full       : 1;    // bit 27       TOE Queue 27 Full Interrupt
++              unsigned int toe_q26_full       : 1;    // bit 26       TOE Queue 26 Full Interrupt
++              unsigned int toe_q25_full       : 1;    // bit 25       TOE Queue 25 Full Interrupt
++              unsigned int toe_q24_full       : 1;    // bit 24       TOE Queue 24 Full Interrupt
++              unsigned int toe_q23_full       : 1;    // bit 23       TOE Queue 23 Full Interrupt
++              unsigned int toe_q22_full       : 1;    // bit 22       TOE Queue 22 Full Interrupt
++              unsigned int toe_q21_full       : 1;    // bit 21       TOE Queue 21 Full Interrupt
++              unsigned int toe_q20_full       : 1;    // bit 20       TOE Queue 20 Full Interrupt
++              unsigned int toe_q19_full       : 1;    // bit 19       TOE Queue 19 Full Interrupt
++              unsigned int toe_q18_full       : 1;    // bit 18       TOE Queue 18 Full Interrupt
++              unsigned int toe_q17_full       : 1;    // bit 17       TOE Queue 17 Full Interrupt
++              unsigned int toe_q16_full       : 1;    // bit 16       TOE Queue 16 Full Interrupt
++              unsigned int toe_q15_full       : 1;    // bit 15       TOE Queue 15 Full Interrupt
++              unsigned int toe_q14_full       : 1;    // bit 14       TOE Queue 14 Full Interrupt
++              unsigned int toe_q13_full       : 1;    // bit 13       TOE Queue 13 Full Interrupt
++              unsigned int toe_q12_full       : 1;    // bit 12       TOE Queue 12 Full Interrupt
++              unsigned int toe_q11_full       : 1;    // bit 11       TOE Queue 11 Full Interrupt
++              unsigned int toe_q10_full       : 1;    // bit 10       TOE Queue 10 Full Interrupt
++              unsigned int toe_q9_full        : 1;    // bit 9        TOE Queue 9 Full Interrupt
++              unsigned int toe_q8_full        : 1;    // bit 8        TOE Queue 8 Full Interrupt
++              unsigned int toe_q7_full        : 1;    // bit 7        TOE Queue 7 Full Interrupt
++              unsigned int toe_q6_full        : 1;    // bit 6        TOE Queue 6 Full Interrupt
++              unsigned int toe_q5_full        : 1;    // bit 5        TOE Queue 5 Full Interrupt
++              unsigned int toe_q4_full        : 1;    // bit 4        TOE Queue 4 Full Interrupt
++              unsigned int toe_q3_full        : 1;    // bit 3        TOE Queue 3 Full Interrupt
++              unsigned int toe_q2_full        : 1;    // bit 2        TOE Queue 2 Full Interrupt
++              unsigned int toe_q1_full        : 1;    // bit 1        TOE Queue 1 Full Interrupt
++              unsigned int toe_q0_full        : 1;    // bit 0        TOE Queue 0 Full Interrupt
++#else
++              unsigned int toe_q0_full        : 1;    // bit 0        TOE Queue 0 Full Interrupt
++              unsigned int toe_q1_full        : 1;    // bit 1        TOE Queue 1 Full Interrupt
++              unsigned int toe_q2_full        : 1;    // bit 2        TOE Queue 2 Full Interrupt
++              unsigned int toe_q3_full        : 1;    // bit 3        TOE Queue 3 Full Interrupt
++              unsigned int toe_q4_full        : 1;    // bit 4        TOE Queue 4 Full Interrupt
++              unsigned int toe_q5_full        : 1;    // bit 5        TOE Queue 5 Full Interrupt
++              unsigned int toe_q6_full        : 1;    // bit 6        TOE Queue 6 Full Interrupt
++              unsigned int toe_q7_full        : 1;    // bit 7        TOE Queue 7 Full Interrupt
++              unsigned int toe_q8_full        : 1;    // bit 8        TOE Queue 8 Full Interrupt
++              unsigned int toe_q9_full        : 1;    // bit 9        TOE Queue 9 Full Interrupt
++              unsigned int toe_q10_full       : 1;    // bit 10       TOE Queue 10 Full Interrupt
++              unsigned int toe_q11_full       : 1;    // bit 11       TOE Queue 11 Full Interrupt
++              unsigned int toe_q12_full       : 1;    // bit 12       TOE Queue 12 Full Interrupt
++              unsigned int toe_q13_full       : 1;    // bit 13       TOE Queue 13 Full Interrupt
++              unsigned int toe_q14_full       : 1;    // bit 14       TOE Queue 14 Full Interrupt
++              unsigned int toe_q15_full       : 1;    // bit 15       TOE Queue 15 Full Interrupt
++              unsigned int toe_q16_full       : 1;    // bit 16       TOE Queue 16 Full Interrupt
++              unsigned int toe_q17_full       : 1;    // bit 17       TOE Queue 17 Full Interrupt
++              unsigned int toe_q18_full       : 1;    // bit 18       TOE Queue 18 Full Interrupt
++              unsigned int toe_q19_full       : 1;    // bit 19       TOE Queue 19 Full Interrupt
++              unsigned int toe_q20_full       : 1;    // bit 20       TOE Queue 20 Full Interrupt
++              unsigned int toe_q21_full       : 1;    // bit 21       TOE Queue 21 Full Interrupt
++              unsigned int toe_q22_full       : 1;    // bit 22       TOE Queue 22 Full Interrupt
++              unsigned int toe_q23_full       : 1;    // bit 23       TOE Queue 23 Full Interrupt
++              unsigned int toe_q24_full       : 1;    // bit 24       TOE Queue 24 Full Interrupt
++              unsigned int toe_q25_full       : 1;    // bit 25       TOE Queue 25 Full Interrupt
++              unsigned int toe_q26_full       : 1;    // bit 26       TOE Queue 26 Full Interrupt
++              unsigned int toe_q27_full       : 1;    // bit 27       TOE Queue 27 Full Interrupt
++              unsigned int toe_q28_full       : 1;    // bit 28       TOE Queue 28 Full Interrupt
++              unsigned int toe_q29_full       : 1;    // bit 29       TOE Queue 29 Full Interrupt
++              unsigned int toe_q30_full       : 1;    // bit 30       TOE Queue 30 Full Interrupt
++              unsigned int toe_q31_full       : 1;    // bit 31       TOE Queue 31 Full Interrupt
++#endif
++      } bits;
++} INTR_REG2_T;
++
++#define TOE_QL_FULL_INT_BIT(x)                BIT(x)
++
++/**********************************************************************
++ * Interrupt Status Register 3        (offset 0x0050)
++ * Interrupt Mask Register 3  (offset 0x0054)
++ * Interrupt Select Register 3        (offset 0x0058)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_0050
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int toe_q63_full       : 1;    // bit 63       TOE Queue 63 Full Interrupt
++              unsigned int toe_q62_full       : 1;    // bit 62       TOE Queue 62 Full Interrupt
++              unsigned int toe_q61_full       : 1;    // bit 61       TOE Queue 61 Full Interrupt
++              unsigned int toe_q60_full       : 1;    // bit 60       TOE Queue 60 Full Interrupt
++              unsigned int toe_q59_full       : 1;    // bit 59       TOE Queue 59 Full Interrupt
++              unsigned int toe_q58_full       : 1;    // bit 58       TOE Queue 58 Full Interrupt
++              unsigned int toe_q57_full       : 1;    // bit 57       TOE Queue 57 Full Interrupt
++              unsigned int toe_q56_full       : 1;    // bit 56       TOE Queue 56 Full Interrupt
++              unsigned int toe_q55_full       : 1;    // bit 55       TOE Queue 55 Full Interrupt
++              unsigned int toe_q54_full       : 1;    // bit 54       TOE Queue 54 Full Interrupt
++              unsigned int toe_q53_full       : 1;    // bit 53       TOE Queue 53 Full Interrupt
++              unsigned int toe_q52_full       : 1;    // bit 52       TOE Queue 52 Full Interrupt
++              unsigned int toe_q51_full       : 1;    // bit 51       TOE Queue 51 Full Interrupt
++              unsigned int toe_q50_full       : 1;    // bit 50       TOE Queue 50 Full Interrupt
++              unsigned int toe_q49_full       : 1;    // bit 49       TOE Queue 49 Full Interrupt
++              unsigned int toe_q48_full       : 1;    // bit 48       TOE Queue 48 Full Interrupt
++              unsigned int toe_q47_full       : 1;    // bit 47       TOE Queue 47 Full Interrupt
++              unsigned int toe_q46_full       : 1;    // bit 46       TOE Queue 46 Full Interrupt
++              unsigned int toe_q45_full       : 1;    // bit 45       TOE Queue 45 Full Interrupt
++              unsigned int toe_q44_full       : 1;    // bit 44       TOE Queue 44 Full Interrupt
++              unsigned int toe_q43_full       : 1;    // bit 43       TOE Queue 43 Full Interrupt
++              unsigned int toe_q42_full       : 1;    // bit 42       TOE Queue 42 Full Interrupt
++              unsigned int toe_q41_full       : 1;    // bit 41       TOE Queue 41 Full Interrupt
++              unsigned int toe_q40_full       : 1;    // bit 40       TOE Queue 40 Full Interrupt
++              unsigned int toe_q39_full       : 1;    // bit 39       TOE Queue 39 Full Interrupt
++              unsigned int toe_q38_full       : 1;    // bit 38       TOE Queue 38 Full Interrupt
++              unsigned int toe_q37_full       : 1;    // bit 37       TOE Queue 37 Full Interrupt
++              unsigned int toe_q36_full       : 1;    // bit 36       TOE Queue 36 Full Interrupt
++              unsigned int toe_q35_full       : 1;    // bit 35       TOE Queue 35 Full Interrupt
++              unsigned int toe_q34_full       : 1;    // bit 34       TOE Queue 34 Full Interrupt
++              unsigned int toe_q33_full       : 1;    // bit 33       TOE Queue 33 Full Interrupt
++              unsigned int toe_q32_full       : 1;    // bit 32       TOE Queue 32 Full Interrupt
++#else
++              unsigned int toe_q32_full       : 1;    // bit 32       TOE Queue 32 Full Interrupt
++              unsigned int toe_q33_full       : 1;    // bit 33       TOE Queue 33 Full Interrupt
++              unsigned int toe_q34_full       : 1;    // bit 34       TOE Queue 34 Full Interrupt
++              unsigned int toe_q35_full       : 1;    // bit 35       TOE Queue 35 Full Interrupt
++              unsigned int toe_q36_full       : 1;    // bit 36       TOE Queue 36 Full Interrupt
++              unsigned int toe_q37_full       : 1;    // bit 37       TOE Queue 37 Full Interrupt
++              unsigned int toe_q38_full       : 1;    // bit 38       TOE Queue 38 Full Interrupt
++              unsigned int toe_q39_full       : 1;    // bit 39       TOE Queue 39 Full Interrupt
++              unsigned int toe_q40_full       : 1;    // bit 40       TOE Queue 40 Full Interrupt
++              unsigned int toe_q41_full       : 1;    // bit 41       TOE Queue 41 Full Interrupt
++              unsigned int toe_q42_full       : 1;    // bit 42       TOE Queue 42 Full Interrupt
++              unsigned int toe_q43_full       : 1;    // bit 43       TOE Queue 43 Full Interrupt
++              unsigned int toe_q44_full       : 1;    // bit 44       TOE Queue 44 Full Interrupt
++              unsigned int toe_q45_full       : 1;    // bit 45       TOE Queue 45 Full Interrupt
++              unsigned int toe_q46_full       : 1;    // bit 46       TOE Queue 46 Full Interrupt
++              unsigned int toe_q47_full       : 1;    // bit 47       TOE Queue 47 Full Interrupt
++              unsigned int toe_q48_full       : 1;    // bit 48       TOE Queue 48 Full Interrupt
++              unsigned int toe_q49_full       : 1;    // bit 49       TOE Queue 49 Full Interrupt
++              unsigned int toe_q50_full       : 1;    // bit 50       TOE Queue 50 Full Interrupt
++              unsigned int toe_q51_full       : 1;    // bit 51       TOE Queue 51 Full Interrupt
++              unsigned int toe_q52_full       : 1;    // bit 52       TOE Queue 52 Full Interrupt
++              unsigned int toe_q53_full       : 1;    // bit 53       TOE Queue 53 Full Interrupt
++              unsigned int toe_q54_full       : 1;    // bit 54       TOE Queue 54 Full Interrupt
++              unsigned int toe_q55_full       : 1;    // bit 55       TOE Queue 55 Full Interrupt
++              unsigned int toe_q56_full       : 1;    // bit 56       TOE Queue 56 Full Interrupt
++              unsigned int toe_q57_full       : 1;    // bit 57       TOE Queue 57 Full Interrupt
++              unsigned int toe_q58_full       : 1;    // bit 58       TOE Queue 58 Full Interrupt
++              unsigned int toe_q59_full       : 1;    // bit 59       TOE Queue 59 Full Interrupt
++              unsigned int toe_q60_full       : 1;    // bit 60       TOE Queue 60 Full Interrupt
++              unsigned int toe_q61_full       : 1;    // bit 61       TOE Queue 61 Full Interrupt
++              unsigned int toe_q62_full       : 1;    // bit 62       TOE Queue 62 Full Interrupt
++              unsigned int toe_q63_full       : 1;    // bit 63       TOE Queue 63 Full Interrupt
++#endif
++      } bits;
++} INTR_REG3_T;
++
++#define TOE_QH_FULL_INT_BIT(x)                BIT(x-32)
++
++/**********************************************************************
++ * Interrupt Status Register 4        (offset 0x0060)
++ * Interrupt Mask Register 4  (offset 0x0064)
++ * Interrupt Select Register 4        (offset 0x0068)
++ **********************************************************************/
++typedef union
++{
++      unsigned char byte;
++      struct bit_0060
++      {
++#if (BIG_ENDIAN==1)
++              unsigned char reserved          : 1;    //
++              unsigned char cnt_full          : 1;    // MIB counters half full interrupt
++              unsigned char rx_pause_on       : 1;    // received pause on frame interrupt
++              unsigned char tx_pause_on       : 1;    // transmit pause on frame interrupt
++              unsigned char rx_pause_off  : 1;        // received pause off frame interrupt
++              unsigned char tx_pause_off      : 1;    // received pause off frame interrupt
++              unsigned char rx_overrun        : 1;    // GMAC Rx FIFO overrun interrupt
++              unsigned char status_changed: 1;        // Status Changed Intr for RGMII Mode
++#else
++              unsigned char status_changed: 1;        // Status Changed Intr for RGMII Mode
++              unsigned char rx_overrun        : 1;   // GMAC Rx FIFO overrun interrupt
++              unsigned char tx_pause_off      : 1;    // received pause off frame interrupt
++              unsigned char rx_pause_off  : 1;        // received pause off frame interrupt
++              unsigned char tx_pause_on       : 1;    // transmit pause on frame interrupt
++              unsigned char rx_pause_on       : 1;    // received pause on frame interrupt
++              unsigned char cnt_full          : 1;    // MIB counters half full interrupt
++              unsigned char reserved          : 1;    //
++#endif
++      } _PACKED_ bits;
++} _PACKED_ GMAC_INTR_T;
++
++typedef union
++{
++      unsigned int bits32;
++      struct bit_0060_2
++      {
++#if (BIG_ENDIAN==1)
++              GMAC_INTR_T             gmac1;
++              GMAC_INTR_T             gmac0;
++              unsigned int    class_qf_int: 14;       // bit 15:2 Classification Rx Queue13-0 Full Intr.
++              unsigned int    hwfq_empty      : 1;    // bit 1        Hardware Free Queue Empty Intr.
++              unsigned int    swfq_empty      : 1;    // bit 0        Software Free Queue Empty Intr.
++#else
++#endif
++              unsigned int    swfq_empty      : 1;    // bit 0        Software Free Queue Empty Intr.
++              unsigned int    hwfq_empty      : 1;    // bit 1        Hardware Free Queue Empty Intr.
++              unsigned int    class_qf_int: 14;       // bit 15:2 Classification Rx Queue13-0 Full Intr.
++              GMAC_INTR_T             gmac0;
++              GMAC_INTR_T             gmac1;
++      } bits;
++} INTR_REG4_T;
++
++#define GMAC1_RESERVED_INT_BIT                BIT(31)
++#define GMAC1_MIB_INT_BIT                     BIT(30)
++#define GMAC1_RX_PAUSE_ON_INT_BIT     BIT(29)
++#define GMAC1_TX_PAUSE_ON_INT_BIT     BIT(28)
++#define GMAC1_RX_PAUSE_OFF_INT_BIT    BIT(27)
++#define GMAC1_TX_PAUSE_OFF_INT_BIT    BIT(26)
++#define GMAC1_RX_OVERRUN_INT_BIT      BIT(25)
++#define GMAC1_STATUS_CHANGE_INT_BIT   BIT(24)
++#define GMAC0_RESERVED_INT_BIT                BIT(23)
++#define GMAC0_MIB_INT_BIT                     BIT(22)
++#define GMAC0_RX_PAUSE_ON_INT_BIT     BIT(21)
++#define GMAC0_TX_PAUSE_ON_INT_BIT     BIT(20)
++#define GMAC0_RX_PAUSE_OFF_INT_BIT    BIT(19)
++#define GMAC0_TX_PAUSE_OFF_INT_BIT    BIT(18)
++#define GMAC0_RX_OVERRUN_INT_BIT      BIT(17)
++#define GMAC0_STATUS_CHANGE_INT_BIT   BIT(16)
++#define CLASS_RX_FULL_INT_BIT(x)      BIT((x+2))
++#define HWFQ_EMPTY_INT_BIT                    BIT(1)
++#define SWFQ_EMPTY_INT_BIT                    BIT(0)
++
++#if 1
++#define GMAC0_INT_BITS                                (GMAC0_MIB_INT_BIT)
++#define GMAC1_INT_BITS                                (GMAC1_MIB_INT_BIT)
++#else
++#define GMAC0_INT_BITS                                (GMAC0_RESERVED_INT_BIT | GMAC0_MIB_INT_BIT | \
++                                                                       GMAC0_RX_PAUSE_ON_INT_BIT | GMAC0_TX_PAUSE_ON_INT_BIT |        \
++                                                                       GMAC0_RX_PAUSE_OFF_INT_BIT | GMAC0_TX_PAUSE_OFF_INT_BIT |      \
++                                                                       GMAC0_RX_OVERRUN_INT_BIT | GMAC0_STATUS_CHANGE_INT_BIT)
++#define GMAC1_INT_BITS                                (GMAC1_RESERVED_INT_BIT | GMAC1_MIB_INT_BIT | \
++                                                                       GMAC1_RX_PAUSE_ON_INT_BIT | GMAC1_TX_PAUSE_ON_INT_BIT |        \
++                                                                       GMAC1_RX_PAUSE_OFF_INT_BIT | GMAC1_TX_PAUSE_OFF_INT_BIT |      \
++                                                                       GMAC1_RX_OVERRUN_INT_BIT | GMAC1_STATUS_CHANGE_INT_BIT)
++#endif
++
++#define CLASS_RX_FULL_INT_BITS                0xfffc
++
++/**********************************************************************
++ * GLOBAL_QUEUE_THRESHOLD_REG         (offset 0x0070)
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_0070_2
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    toe_class       : 8;    // 31:24
++              unsigned int    intrq           : 8;    // 23:16
++              unsigned int    hwfq_empty      : 8;    // 15:8         Hardware Free Queue Empty Threshold
++              unsigned int    swfq_empty      : 8;    //  7:0         Software Free Queue Empty Threshold
++#else
++#endif
++              unsigned int    swfq_empty      : 8;    //  7:0         Software Free Queue Empty Threshold
++              unsigned int    hwfq_empty      : 8;    // 15:8         Hardware Free Queue Empty Threshold
++              unsigned int    intrq           : 8;    // 23:16
++              unsigned int    toe_class       : 8;    // 31:24
++      } bits;
++} QUEUE_THRESHOLD_T;
++
++
++/**********************************************************************
++ * GMAC DMA Control Register
++ * GMAC0 offset 0x8000
++ * GMAC1 offset 0xC000
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8000
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    rd_enable               : 1;    // bit 31       Rx DMA Enable
++              unsigned int    td_enable               : 1;    // bit 30       Tx DMA Enable
++              unsigned int    loopback                : 1;    // bit 29       Loopback TxDMA to RxDMA
++              unsigned int    drop_small_ack  : 1;    // bit 28       1: Drop, 0: Accept
++              unsigned int    reserved                : 10;   // bit 27:18
++              unsigned int    rd_insert_bytes : 2;    // bit 17:16
++              unsigned int    rd_prot                 : 4;    // bit 15:12 DMA Protection Control
++              unsigned int    rd_burst_size   : 2;    // bit 11:10 DMA max burst size for every AHB request
++              unsigned int    rd_bus              : 2;        // bit 9:8      Peripheral Bus Width
++              unsigned int    td_prot                 : 4;    // bit 7:4  TxDMA protection control
++              unsigned int    td_burst_size   : 2;    // bit 3:2      TxDMA max burst size for every AHB request
++              unsigned int    td_bus              : 2;        // bit 1:0  Peripheral Bus Width
++#else
++              unsigned int    td_bus              : 2;        // bit 1:0  Peripheral Bus Width
++              unsigned int    td_burst_size   : 2;    // bit 3:2      TxDMA max burst size for every AHB request
++              unsigned int    td_prot                 : 4;    // bit 7:4  TxDMA protection control
++              unsigned int    rd_bus              : 2;        // bit 9:8      Peripheral Bus Width
++              unsigned int    rd_burst_size   : 2;    // bit 11:10 DMA max burst size for every AHB request
++              unsigned int    rd_prot                 : 4;    // bit 15:12 DMA Protection Control
++              unsigned int    rd_insert_bytes : 2;    // bit 17:16
++              unsigned int    reserved                : 10;   // bit 27:18
++              unsigned int    drop_small_ack  : 1;    // bit 28       1: Drop, 0: Accept
++              unsigned int    loopback                : 1;    // bit 29       Loopback TxDMA to RxDMA
++              unsigned int    td_enable               : 1;    // bit 30       Tx DMA Enable
++              unsigned int    rd_enable               : 1;    // bit 31       Rx DMA Enable
++#endif
++      } bits;
++} GMAC_DMA_CTRL_T;
++
++/**********************************************************************
++ * GMAC Tx Weighting Control Register 0
++ * GMAC0 offset 0x8004
++ * GMAC1 offset 0xC004
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8004
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    reserved                : 8;    // bit 31:24
++              unsigned int    hw_tq3                  : 6;    // bit 23:18    HW TX Queue 0
++              unsigned int    hw_tq2                  : 6;    // bit 17:12    HW TX Queue 1
++              unsigned int    hw_tq1                  : 6;    // bit 11:6             HW TX Queue 2
++              unsigned int    hw_tq0                  : 6;    // bit 5:0              HW TX Queue 3
++#else
++              unsigned int    hw_tq0                  : 6;    // bit 5:0              HW TX Queue 3
++              unsigned int    hw_tq1                  : 6;    // bit 11:6             HW TX Queue 2
++              unsigned int    hw_tq2                  : 6;    // bit 17:12    HW TX Queue 1
++              unsigned int    hw_tq3                  : 6;    // bit 23:18    HW TX Queue 0
++              unsigned int    reserved                : 8;    // bit 31:24
++#endif
++      } bits;
++} GMAC_TX_WCR0_T;     // Weighting Control Register 0
++
++/**********************************************************************
++ * GMAC Tx Weighting Control Register 1
++ * GMAC0 offset 0x8008
++ * GMAC1 offset 0xC008
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8008
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    reserved                : 2;    // bit 31:30
++              unsigned int    sw_tq5                  : 5;    // bit 29:25    SW TX Queue 5
++              unsigned int    sw_tq4                  : 5;    // bit 24:20    SW TX Queue 4
++              unsigned int    sw_tq3                  : 5;    // bit 19:15    SW TX Queue 3
++              unsigned int    sw_tq2                  : 5;    // bit 14:10    SW TX Queue 2
++              unsigned int    sw_tq1                  : 5;    // bit 9:5              SW TX Queue 1
++              unsigned int    sw_tq0                  : 5;    // bit 4:0              SW TX Queue 0
++#else
++              unsigned int    sw_tq0                  : 5;    // bit 4:0              SW TX Queue 0
++              unsigned int    sw_tq1                  : 5;    // bit 9:5              SW TX Queue 1
++              unsigned int    sw_tq2                  : 5;    // bit 14:10    SW TX Queue 2
++              unsigned int    sw_tq3                  : 5;    // bit 19:15    SW TX Queue 3
++              unsigned int    sw_tq4                  : 5;    // bit 24:20    SW TX Queue 4
++              unsigned int    sw_tq5                  : 5;    // bit 29:25    SW TX Queue 5
++              unsigned int    reserved                : 2;    // bit 31:30
++#endif
++      } bits;
++} GMAC_TX_WCR1_T;     // Weighting Control Register 1
++
++/**********************************************************************
++ * Queue Read/Write Pointer
++ * GMAC SW TX Queue 0~5 Read/Write Pointer register
++ * GMAC0 offset 0x800C ~ 0x8020
++ * GMAC1 offset 0xC00C ~ 0xC020
++ * GMAC HW TX Queue 0~3 Read/Write Pointer register
++ * GMAC0 offset 0x8024 ~ 0x8030
++ * GMAC1 offset 0xC024 ~ 0xC030
++ **********************************************************************/
++// see DMA_RWPTR_T structure
++
++/**********************************************************************
++ * GMAC DMA Tx First Description Address Register
++ * GMAC0 offset 0x8038
++ * GMAC1 offset 0xC038
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8038
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int td_first_des_ptr   : 28;   // bit 31:4     first descriptor address
++              unsigned int td_busy                    :  1;   // bit 3        1: TxDMA busy; 0: TxDMA idle
++              unsigned int reserved                   :  3;
++#else
++              unsigned int reserved                   :  3;
++              unsigned int td_busy                    :  1;   // bit 3        1: TxDMA busy; 0: TxDMA idle
++              unsigned int td_first_des_ptr   : 28;   // bit 31:4     first descriptor address
++#endif
++      } bits;
++} GMAC_TXDMA_FIRST_DESC_T;
++
++/**********************************************************************
++ * GMAC DMA Tx Current Description Address Register
++ * GMAC0 offset 0x803C
++ * GMAC1 offset 0xC03C
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_803C
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int td_curr_desc_ptr   : 28;   // bit 31:4     current descriptor address
++              unsigned int reserved                   :  4;
++#else
++              unsigned int reserved                   :  4;
++              unsigned int td_curr_desc_ptr   : 28;   // bit 31:4     current descriptor address
++#endif
++      } bits;
++} GMAC_TXDMA_CURR_DESC_T;
++
++/**********************************************************************
++ * GMAC DMA Tx Description Word 0 Register
++ * GMAC0 offset 0x8040
++ * GMAC1 offset 0xC040
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8040
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int reserved           : 1;    // bit 31
++              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
++              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
++              unsigned int status_rvd         : 6;    // bit 28:23 Tx Status, Reserved bits
++              unsigned int status_tx_ok       : 1;    // bit 22    Tx Status, 1: Successful 0: Failed
++              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
++              unsigned int buffer_size        : 16;   // bit 15:0  Transfer size
++#else
++              unsigned int buffer_size        : 16;   // bit 15:0  Transfer size
++              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
++              unsigned int status_tx_ok       : 1;    // bit 22    Tx Status, 1: Successful 0: Failed
++              unsigned int status_rvd         : 6;    // bit 28:23 Tx Status, Reserved bits
++              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
++              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
++              unsigned int reserved           : 1;    // bit 31
++#endif
++      } bits;
++} GMAC_TXDESC_0_T;
++
++/**********************************************************************
++ * GMAC DMA Tx Description Word 1 Register
++ * GMAC0 offset 0x8044
++ * GMAC1 offset 0xC044
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct txdesc_word1
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    reserved        : 9;    // bit 31:23    Tx Flag, Reserved
++              unsigned int    ip_fixed_len: 1;        // bit 22
++              unsigned int    bypass_tss      : 1;    // bit 21
++              unsigned int    udp_chksum      : 1;    // bit 20               UDP Checksum Enable
++              unsigned int    tcp_chksum      : 1;    // bit 19               TCP Checksum Enable
++              unsigned int    ipv6_enable     : 1;    // bit 18               IPV6 Tx Enable
++              unsigned int    ip_chksum       : 1;    // bit 17               IPV4 Header Checksum Enable
++              unsigned int    mtu_enable      : 1;    // bit 16               TSS segmentation use MTU setting
++              unsigned int    byte_count      : 16;   // bit 15: 0    Tx Frame Byte Count
++#else
++              unsigned int    byte_count      : 16;   // bit 15: 0    Tx Frame Byte Count
++              unsigned int    mtu_enable      : 1;    // bit 16               TSS segmentation use MTU setting
++              unsigned int    ip_chksum       : 1;    // bit 17               IPV4 Header Checksum Enable
++              unsigned int    ipv6_enable     : 1;    // bit 18               IPV6 Tx Enable
++              unsigned int    tcp_chksum      : 1;    // bit 19               TCP Checksum Enable
++              unsigned int    udp_chksum      : 1;    // bit 20               UDP Checksum Enable
++              unsigned int    bypass_tss      : 1;    // bit 21
++              unsigned int    ip_fixed_len: 1;        // bit 22
++              unsigned int    reserved        : 9;    // bit 31:23    Tx Flag, Reserved
++#endif
++      } bits;
++} GMAC_TXDESC_1_T;
++
++#define TSS_IP_FIXED_LEN_BIT  BIT(22)
++#define TSS_UDP_CHKSUM_BIT            BIT(20)
++#define TSS_TCP_CHKSUM_BIT            BIT(19)
++#define TSS_IPV6_ENABLE_BIT           BIT(18)
++#define TSS_IP_CHKSUM_BIT             BIT(17)
++#define TSS_MTU_ENABLE_BIT            BIT(16)
++
++/**********************************************************************
++ * GMAC DMA Tx Description Word 2 Register
++ * GMAC0 offset 0x8048
++ * GMAC1 offset 0xC048
++ **********************************************************************/
++typedef union
++{
++      unsigned int    bits32;
++      unsigned int    buf_adr;
++} GMAC_TXDESC_2_T;
++
++/**********************************************************************
++ * GMAC DMA Tx Description Word 3 Register
++ * GMAC0 offset 0x804C
++ * GMAC1 offset 0xC04C
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct txdesc_word3
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
++              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
++              unsigned int    reserved        : 18;   // bit 28:11
++              unsigned int    mtu_size        : 11;   // bit 10: 0    Tx Frame Byte Count
++#else
++              unsigned int    mtu_size        : 11;   // bit 10: 0    Tx Frame Byte Count
++              unsigned int    reserved        : 18;   // bit 28:11
++              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
++              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
++#endif
++      } bits;
++} GMAC_TXDESC_3_T;
++#define SOF_EOF_BIT_MASK      0x3fffffff
++#define SOF_BIT                               0x80000000
++#define EOF_BIT                               0x40000000
++#define EOFIE_BIT                     BIT(29)
++#define MTU_SIZE_BIT_MASK     0x7ff
++
++/**********************************************************************
++ * GMAC Tx Descriptor
++ **********************************************************************/
++typedef struct
++{
++      GMAC_TXDESC_0_T word0;
++      GMAC_TXDESC_1_T word1;
++      GMAC_TXDESC_2_T word2;
++      GMAC_TXDESC_3_T word3;
++} GMAC_TXDESC_T;
++
++
++/**********************************************************************
++ * GMAC DMA Rx First Description Address Register
++ * GMAC0 offset 0x8058
++ * GMAC1 offset 0xC058
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8058
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rd_first_des_ptr   : 28;   // bit 31:4 first descriptor address
++              unsigned int rd_busy                    :  1;   // bit 3        1-RxDMA busy; 0-RxDMA idle
++              unsigned int reserved                   :  3;   // bit 2:0
++#else
++              unsigned int reserved                   :  3;   // bit 2:0
++              unsigned int rd_busy                    :  1;   // bit 3        1-RxDMA busy; 0-RxDMA idle
++              unsigned int rd_first_des_ptr   : 28;   // bit 31:4 first descriptor address
++#endif
++      } bits;
++} GMAC_RXDMA_FIRST_DESC_T;
++
++/**********************************************************************
++ * GMAC DMA Rx Current Description Address Register
++ * GMAC0 offset 0x805C
++ * GMAC1 offset 0xC05C
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_805C
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rd_curr_des_ptr    : 28;   // bit 31:4 current descriptor address
++              unsigned int reserved                   :  4;   // bit 3:0
++#else
++              unsigned int reserved                   :  4;   // bit 3:0
++              unsigned int rd_curr_des_ptr    : 28;   // bit 31:4 current descriptor address
++#endif
++      } bits;
++} GMAC_RXDMA_CURR_DESC_T;
++
++/**********************************************************************
++ * GMAC DMA Rx Description Word 0 Register
++ * GMAC0 offset 0x8060
++ * GMAC1 offset 0xC060
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8060
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int drop                       : 1;    // bit 31        TOE/CIS Queue Full dropped packet to default queue
++              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
++              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
++              unsigned int chksum_status      : 3;    // bit 28:26 Check Sum Status
++              unsigned int status                     : 4;    // bit 24:22 Status of rx frame
++              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
++              unsigned int buffer_size        : 16;   // bit 15:0  number of descriptors used for the current frame
++#else
++              unsigned int buffer_size        : 16;   // bit 15:0  number of descriptors used for the current frame
++              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
++              unsigned int status                     : 4;    // bit 24:22 Status of rx frame
++              unsigned int chksum_status      : 3;    // bit 28:26 Check Sum Status
++              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
++              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
++              unsigned int drop                       : 1;    // bit 31        TOE/CIS Queue Full dropped packet to default queue
++#endif
++      } bits;
++} GMAC_RXDESC_0_T;
++
++#define               GMAC_RXDESC_0_T_derr                            BIT(30)
++#define               GMAC_RXDESC_0_T_perr                            BIT(29)
++#define               GMAC_RXDESC_0_T_chksum_status(x)        BIT((x+26))
++#define               GMAC_RXDESC_0_T_status(x)                       BIT((x+22))
++#define               GMAC_RXDESC_0_T_desc_count(x)           BIT((x+16))
++
++#define       RX_CHKSUM_IP_UDP_TCP_OK                 0
++#define       RX_CHKSUM_IP_OK_ONLY                    1
++#define       RX_CHKSUM_NONE                                  2
++#define       RX_CHKSUM_IP_ERR_UNKNOWN                4
++#define       RX_CHKSUM_IP_ERR                                5
++#define       RX_CHKSUM_TCP_UDP_ERR                   6
++#define RX_CHKSUM_NUM                                 8
++
++#define RX_STATUS_GOOD_FRAME                  0
++#define RX_STATUS_TOO_LONG_GOOD_CRC           1
++#define RX_STATUS_RUNT_FRAME                  2
++#define RX_STATUS_SFD_NOT_FOUND                       3
++#define RX_STATUS_CRC_ERROR                           4
++#define RX_STATUS_TOO_LONG_BAD_CRC            5
++#define RX_STATUS_ALIGNMENT_ERROR             6
++#define RX_STATUS_TOO_LONG_BAD_ALIGN  7
++#define RX_STATUS_RX_ERR                              8
++#define RX_STATUS_DA_FILTERED                 9
++#define RX_STATUS_BUFFER_FULL                 10
++#define RX_STATUS_NUM                                 16
++
++
++/**********************************************************************
++ * GMAC DMA Rx Description Word 1 Register
++ * GMAC0 offset 0x8064
++ * GMAC1 offset 0xC064
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct rxdesc_word1
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    sw_id           : 16;   // bit 31:16    Software ID
++              unsigned int    byte_count      : 16;   // bit 15: 0    Rx Frame Byte Count
++#else
++              unsigned int    byte_count      : 16;   // bit 15: 0    Rx Frame Byte Count
++              unsigned int    sw_id           : 16;   // bit 31:16    Software ID
++#endif
++      } bits;
++} GMAC_RXDESC_1_T;
++
++/**********************************************************************
++ * GMAC DMA Rx Description Word 2 Register
++ * GMAC0 offset 0x8068
++ * GMAC1 offset 0xC068
++ **********************************************************************/
++typedef union
++{
++      unsigned int    bits32;
++      unsigned int    buf_adr;
++} GMAC_RXDESC_2_T;
++
++#define RX_INSERT_NONE                0
++#define RX_INSERT_1_BYTE      1
++#define RX_INSERT_2_BYTE      2
++#define RX_INSERT_3_BYTE      3
++
++#define RX_INSERT_BYTES               RX_INSERT_2_BYTE
++/**********************************************************************
++ * GMAC DMA Rx Description Word 3 Register
++ * GMAC0 offset 0x806C
++ * GMAC1 offset 0xC06C
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct rxdesc_word3
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
++              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
++              unsigned int    ctrl_flag       : 1;    // bit 28               Control Flag is present
++              unsigned int    out_of_seq      : 1;    // bit 27               Out of Sequence packet
++              unsigned int    option          : 1;    // bit 26               IPV4 option or IPV6 extension header
++              unsigned int    abnormal        : 1;    // bit 25               abnormal case found
++              unsigned int    dup_ack         : 1;    // bit 24               Duplicated ACK detected
++              unsigned int    l7_offset       : 8;    // bit 23: 16   L7 data offset
++              unsigned int    l4_offset       : 8;    // bit 15: 8    L4 data offset
++              unsigned int    l3_offset       : 8;    // bit 7: 0             L3 data offset
++#else
++              unsigned int    l3_offset       : 8;    // bit 7: 0             L3 data offset
++              unsigned int    l4_offset       : 8;    // bit 15: 8    L4 data offset
++              unsigned int    l7_offset       : 8;    // bit 23: 16   L7 data offset
++              unsigned int    dup_ack         : 1;    // bit 24               Duplicated ACK detected
++              unsigned int    abnormal        : 1;    // bit 25               abnormal case found
++              unsigned int    option          : 1;    // bit 26               IPV4 option or IPV6 extension header
++              unsigned int    out_of_seq      : 1;    // bit 27               Out of Sequence packet
++              unsigned int    ctrl_flag       : 1;    // bit 28               Control Flag is present
++              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
++              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
++#endif
++      } bits;
++} GMAC_RXDESC_3_T;
++
++/**********************************************************************
++ * GMAC Rx Descriptor
++ **********************************************************************/
++typedef struct
++{
++      GMAC_RXDESC_0_T word0;
++      GMAC_RXDESC_1_T word1;
++      GMAC_RXDESC_2_T word2;
++      GMAC_RXDESC_3_T word3;
++} GMAC_RXDESC_T;
++
++/**********************************************************************
++ * GMAC Hash Engine Enable/Action Register 0 Offset Register
++ * GMAC0 offset 0x8070
++ * GMAC1 offset 0xC070
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8070
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    mr1en           : 1;    // bit 31               Enable Matching Rule 1
++              unsigned int    reserved1       : 1;    // bit 30
++              unsigned int    timing          : 3;    // bit 29:27
++              unsigned int    mr1_action      : 5;    // bit 26:22    Matching Rule 1 action offset
++              unsigned int    mr1hel          : 6;    // bit 21:16    match rule 1 hash entry size
++              unsigned int    mr0en           : 1;    // bit 15               Enable Matching Rule 0
++              unsigned int    reserved0       : 4;    // bit 14:11
++              unsigned int    mr0_action      : 5;    // bit 10:6             Matching Rule 0 action offset
++              unsigned int    mr0hel          : 6;    // bit 5:0              match rule 0 hash entry size
++#else
++              unsigned int    mr0hel          : 6;    // bit 5:0              match rule 0 hash entry size
++              unsigned int    mr0_action      : 5;    // bit 10:6             Matching Rule 0 action offset
++              unsigned int    reserved0       : 4;    // bit 14:11
++              unsigned int    mr0en           : 1;    // bit 15               Enable Matching Rule 0
++              unsigned int    mr1hel          : 6;    // bit 21:16    match rule 1 hash entry size
++              unsigned int    mr1_action      : 5;    // bit 26:22    Matching Rule 1 action offset
++              unsigned int    timing          : 3;    // bit 29:27
++              unsigned int    reserved1       : 1;    // bit 30
++              unsigned int    mr1en           : 1;    // bit 31               Enable Matching Rule 1
++#endif
++      } bits;
++} GMAC_HASH_ENABLE_REG0_T;
++
++/**********************************************************************
++ * GMAC Hash Engine Enable/Action Register 1 Offset Register
++ * GMAC0 offset 0x8074
++ * GMAC1 offset 0xC074
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8074
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    mr3en           : 1;    // bit 31               Enable Matching Rule 3
++              unsigned int    reserved3       : 4;    // bit 30:27
++              unsigned int    mr3_action      : 5;    // bit 26:22    Matching Rule 3 action offset
++              unsigned int    mr3hel          : 6;    // bit 21:16    match rule 3 hash entry size
++              unsigned int    mr2en           : 1;    // bit 15               Enable Matching Rule 2
++              unsigned int    reserved2       : 4;    // bit 14:11
++              unsigned int    mr2_action      : 5;    // bit 10:6             Matching Rule 2 action offset
++              unsigned int    mr2hel          : 6;    // bit 5:0              match rule 2 hash entry size
++#else
++              unsigned int    mr2hel          : 6;    // bit 5:0              match rule 2 hash entry size
++              unsigned int    mr2_action      : 5;    // bit 10:6             Matching Rule 2 action offset
++              unsigned int    reserved2       : 4;    // bit 14:11
++              unsigned int    mr2en           : 1;    // bit 15               Enable Matching Rule 2
++              unsigned int    mr3hel          : 6;    // bit 21:16    match rule 3 hash entry size
++              unsigned int    mr3_action      : 5;    // bit 26:22    Matching Rule 3 action offset
++              unsigned int    reserved1       : 4;    // bit 30:27
++              unsigned int    mr3en           : 1;    // bit 31               Enable Matching Rule 3
++#endif
++      } bits;
++} GMAC_HASH_ENABLE_REG1_T;
++
++
++/**********************************************************************
++ * GMAC Matching Rule Control Register 0
++ * GMAC0 offset 0x8078
++ * GMAC1 offset 0xC078
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_8078
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    l2                      : 1;    // bit 31               L2 matching enable
++              unsigned int    l3                      : 1;    // bit 30               L3 matching enable
++              unsigned int    l4                      : 1;    // bit 29               L4 matching enable
++              unsigned int    l7                      : 1;    // bit 28               L7 matching enable
++              unsigned int    port            : 1;    // bit 27               PORT ID matching enable
++              unsigned int    priority        : 3;    // bit 26:24    priority if multi-rules matched
++              unsigned int    da                      : 1;    // bit 23               MAC DA enable
++              unsigned int    sa                      : 1;    // bit 22               MAC SA enable
++              unsigned int    ether_type      : 1;    // bit 21               Ethernet type enable
++              unsigned int    vlan            : 1;    // bit 20               VLAN ID enable
++              unsigned int    pppoe           : 1;    // bit 19               PPPoE Session ID enable
++              unsigned int    reserved1       : 3;    // bit 18:16
++              unsigned int    ip_version      : 1;    // bit 15               0: IPV4, 1: IPV6
++              unsigned int    ip_hdr_len      : 1;    // bit 14               IPV4 Header length
++              unsigned int    flow_lable      : 1;    // bit 13               IPV6 Flow label
++              unsigned int    tos_traffic     : 1;    // bit 12               IPV4 TOS or IPV6 Traffice Class
++              unsigned int    reserved2       : 4;    // bit 11:8
++              unsigned int    sprx            : 8;    // bit 7:0              Support Protocol Register 7:0
++#else
++              unsigned int    sprx            : 8;    // bit 7:0              Support Protocol Register 7:0
++              unsigned int    reserved2       : 4;    // bit 11:8
++              unsigned int    tos_traffic     : 1;    // bit 12               IPV4 TOS or IPV6 Traffice Class
++              unsigned int    flow_lable      : 1;    // bit 13               IPV6 Flow label
++              unsigned int    ip_hdr_len      : 1;    // bit 14               IPV4 Header length
++              unsigned int    ip_version      : 1;    // bit 15               0: IPV4, 1: IPV6
++              unsigned int    reserved1       : 3;    // bit 18:16
++              unsigned int    pppoe           : 1;    // bit 19               PPPoE Session ID enable
++              unsigned int    vlan            : 1;    // bit 20               VLAN ID enable
++              unsigned int    ether_type      : 1;    // bit 21               Ethernet type enable
++              unsigned int    sa                      : 1;    // bit 22               MAC SA enable
++              unsigned int    da                      : 1;    // bit 23               MAC DA enable
++              unsigned int    priority        : 3;    // bit 26:24    priority if multi-rules matched
++              unsigned int    port            : 1;    // bit 27               PORT ID matching enable
++              unsigned int    l7                      : 1;    // bit 28               L7 matching enable
++              unsigned int    l4                      : 1;    // bit 29               L4 matching enable
++              unsigned int    l3                      : 1;    // bit 30               L3 matching enable
++              unsigned int    l2                      : 1;    // bit 31               L2 matching enable
++#endif
++      } bits;
++} GMAC_MRxCR0_T;
++
++#define MR_L2_BIT                     BIT(31)
++#define MR_L3_BIT                     BIT(30)
++#define MR_L4_BIT                     BIT(29)
++#define MR_L7_BIT                     BIT(28)
++#define MR_PORT_BIT                   BIT(27)
++#define MR_PRIORITY_BIT               BIT(26)
++#define MR_DA_BIT                     BIT(23)
++#define MR_SA_BIT                     BIT(22)
++#define MR_ETHER_TYPE_BIT     BIT(21)
++#define MR_VLAN_BIT                   BIT(20)
++#define MR_PPPOE_BIT          BIT(19)
++#define MR_IP_VER_BIT         BIT(15)
++#define MR_IP_HDR_LEN_BIT     BIT(14)
++#define MR_FLOW_LABLE_BIT     BIT(13)
++#define MR_TOS_TRAFFIC_BIT    BIT(12)
++#define MR_SPR_BIT(x)         BIT(x)
++#define MR_SPR_BITS           0xff
++
++/**********************************************************************
++ * GMAC Matching Rule Control Register 1
++ * GMAC0 offset 0x807C
++ * GMAC1 offset 0xC07C
++ **********************************************************************/
++ typedef union
++{
++      unsigned int bits32;
++      struct bit_807C
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    sip                     : 1;    // bit 31               Srce IP
++              unsigned int    sip_netmask     : 7;    // bit 30:24    Srce IP net mask, number of mask bits
++              unsigned int    dip                     : 1;    // bit 23               Dest IP
++              unsigned int    dip_netmask     : 7;    // bit 22:16    Dest IP net mask, number of mask bits
++              unsigned int    l4_byte0_15     : 16;   // bit 15: 0
++#else
++              unsigned int    l4_byte0_15     : 16;   // bit 15: 0
++              unsigned int    dip_netmask     : 7;    // bit 22:16    Dest IP net mask, number of mask bits
++              unsigned int    dip                     : 1;    // bit 23               Dest IP
++              unsigned int    sip_netmask     : 7;    // bit 30:24    Srce IP net mask, number of mask bits
++              unsigned int    sip                     : 1;    // bit 31               Srce IP
++#endif
++      } bits;
++} GMAC_MRxCR1_T;
++
++/**********************************************************************
++ * GMAC Matching Rule Control Register 2
++ * GMAC0 offset 0x8080
++ * GMAC1 offset 0xC080
++ **********************************************************************/
++ typedef union
++{
++      unsigned int bits32;
++      struct bit_8080
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    l4_byte16_24: 8;        // bit 31: 24
++              unsigned int    l7_byte0_23     : 24;   // bit 23:0
++#else
++              unsigned int    l7_byte0_23     : 24;   // bit 23:0
++              unsigned int    l4_byte16_24: 8;        // bit 31: 24
++#endif
++      } bits;
++} GMAC_MRxCR2_T;
++
++
++/**********************************************************************
++ * GMAC Support registers
++ * GMAC0 offset 0x80A8
++ * GMAC1 offset 0xC0A8
++ **********************************************************************/
++ typedef union
++{
++      unsigned int bits32;
++      struct bit_80A8
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    reserved: 21;   // bit 31:11
++              unsigned int    swap    : 3;    // bit 10:8             Swap
++              unsigned int    protocol: 8;    // bit 7:0              Supported protocol
++#else
++              unsigned int    protocol: 8;    // bit 7:0              Supported protocol
++              unsigned int    swap    : 3;    // bit 10:8             Swap
++              unsigned int    reserved: 21;   // bit 31:11
++#endif
++      } bits;
++} GMAC_SPR_T;
++
++/**********************************************************************
++ * GMAC_AHB_WEIGHT registers
++ * GMAC0 offset 0x80C8
++ * GMAC1 offset 0xC0C8
++ **********************************************************************/
++ typedef union
++{
++      unsigned int bits32;
++      struct bit_80C8
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int    reserved                : 7;    // 31:25
++              unsigned int    tqDV_threshold  : 5;    // 24:20 DMA TqCtrl to Start tqDV FIFO Threshold
++              unsigned int    pre_req                 : 5;    // 19:15 Rx Data Pre Request FIFO Threshold
++              unsigned int    tx_weight               : 5;    // 14:10
++              unsigned int    rx_weight               : 5;    // 9:5
++              unsigned int    hash_weight             : 5;    // 4:0
++#else
++              unsigned int    hash_weight             : 5;    // 4:0
++              unsigned int    rx_weight               : 5;    // 9:5
++              unsigned int    tx_weight               : 5;    // 14:10
++              unsigned int    pre_req                 : 5;    // 19:15 Rx Data Pre Request FIFO Threshold
++              unsigned int    tqDV_threshold  : 5;    // 24:20 DMA TqCtrl to Start tqDV FIFO Threshold
++              unsigned int    reserved                : 7;    // 31:25
++#endif
++      } bits;
++} GMAC_AHB_WEIGHT_T;
++/**********************************************************************
++ * the register structure of GMAC
++ **********************************************************************/
++
++/**********************************************************************
++ * GMAC RX FLTR
++ * GMAC0 Offset 0xA00C
++ * GMAC1 Offset 0xE00C
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_000c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 27;
++              unsigned int error                      :  1;   /* enable receive of all error frames */
++              unsigned int promiscuous        :  1;   /* enable receive of all frames */
++              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
++              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
++              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
++#else
++              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
++              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
++              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
++              unsigned int promiscuous        :  1;   /* enable receive of all frames */
++              unsigned int error                      :  1;   /* enable receive of all error frames */
++              unsigned int                            : 27;
++#endif
++      } bits;
++} GMAC_RX_FLTR_T;
++
++/**********************************************************************
++ * GMAC Configuration 0
++ * GMAC0 Offset 0xA018
++ * GMAC1 Offset 0xE018
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0018
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int reserved           :  2;   // 31
++              unsigned int port1_chk_classq :  1;     // 29
++              unsigned int port0_chk_classq :  1;     // 28
++              unsigned int port1_chk_toeq     :  1;   // 27
++              unsigned int port0_chk_toeq     :  1;   // 26
++              unsigned int port1_chk_hwq      :  1;   // 25
++              unsigned int port0_chk_hwq      :  1;   // 24
++              unsigned int rx_err_detect  :  1;       // 23
++              unsigned int ipv6_exthdr_order: 1;      // 22
++              unsigned int rxc_inv            :  1;   // 21
++              unsigned int rgmm_edge          :  1;   // 20
++        unsigned int rx_tag_remove  :  1;   /* 19: Remove Rx VLAN tag */
++        unsigned int ipv6_rx_chksum :  1;   /* 18: IPv6 RX Checksum enable */
++        unsigned int ipv4_rx_chksum :  1;   /* 17: IPv4 RX Checksum enable */
++        unsigned int rgmii_en       :  1;   /* 16: RGMII in-band status enable */
++              unsigned int tx_fc_en           :  1;   /* 15: TX flow control enable */
++              unsigned int rx_fc_en           :  1;   /* 14: RX flow control enable */
++              unsigned int sim_test           :  1;   /* 13: speed up timers in simulation */
++              unsigned int dis_col            :  1;   /* 12: disable 16 collisions abort function */
++              unsigned int dis_bkoff          :  1;   /* 11: disable back-off function */
++              unsigned int max_len            :  3;   /* 8-10 maximum receive frame length allowed */
++              unsigned int adj_ifg            :  4;   /* 4-7: adjust IFG from 96+/-56 */
++        unsigned int flow_ctrl      :  1;   /* 3: flow control also trigged by Rx queues */
++              unsigned int loop_back          :  1;   /* 2: transmit data loopback enable */
++              unsigned int dis_rx                     :  1;   /* 1: disable receive */
++              unsigned int dis_tx                     :  1;   /* 0: disable transmit */
++#else
++              unsigned int dis_tx                     :  1;   /* 0: disable transmit */
++              unsigned int dis_rx                     :  1;   /* 1: disable receive */
++              unsigned int loop_back          :  1;   /* 2: transmit data loopback enable */
++        unsigned int flow_ctrl      :  1;   /* 3: flow control also trigged by Rx queues */
++              unsigned int adj_ifg            :  4;   /* 4-7: adjust IFG from 96+/-56 */
++              unsigned int max_len            :  3;   /* 8-10 maximum receive frame length allowed */
++              unsigned int dis_bkoff          :  1;   /* 11: disable back-off function */
++              unsigned int dis_col            :  1;   /* 12: disable 16 collisions abort function */
++              unsigned int sim_test           :  1;   /* 13: speed up timers in simulation */
++              unsigned int rx_fc_en           :  1;   /* 14: RX flow control enable */
++              unsigned int tx_fc_en           :  1;   /* 15: TX flow control enable */
++        unsigned int rgmii_en       :  1;   /* 16: RGMII in-band status enable */
++        unsigned int ipv4_rx_chksum :  1;   /* 17: IPv4 RX Checksum enable */
++        unsigned int ipv6_rx_chksum :  1;   /* 18: IPv6 RX Checksum enable */
++        unsigned int rx_tag_remove  :  1;   /* 19: Remove Rx VLAN tag */
++              unsigned int rgmm_edge          :  1;   // 20
++              unsigned int rxc_inv            :  1;   // 21
++              unsigned int ipv6_exthdr_order: 1;      // 22
++              unsigned int rx_err_detect  :  1;       // 23
++              unsigned int port0_chk_hwq      :  1;   // 24
++              unsigned int port1_chk_hwq      :  1;   // 25
++              unsigned int port0_chk_toeq     :  1;   // 26
++              unsigned int port1_chk_toeq     :  1;   // 27
++              unsigned int port0_chk_classq :  1;     // 28
++              unsigned int port1_chk_classq :  1;     // 29
++              unsigned int reserved           :  2;   // 31
++#endif
++      } bits;
++} GMAC_CONFIG0_T;
++
++/**********************************************************************
++ * GMAC Configuration 1
++ * GMAC0 Offset 0xA01C
++ * GMAC1 Offset 0xE01C
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_001c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int reserved           : 16;
++              unsigned int rel_threshold      : 8;    /* flow control release threshold */
++              unsigned int set_threshold      : 8;    /* flow control set threshold */
++#else
++              unsigned int set_threshold      : 8;    /* flow control set threshold */
++              unsigned int rel_threshold      : 8;    /* flow control release threshold */
++              unsigned int reserved           : 16;
++#endif
++      } bits;
++} GMAC_CONFIG1_T;
++
++#define GMAC_FLOWCTRL_SET_MAX         32
++#define GMAC_FLOWCTRL_SET_MIN         0
++#define GMAC_FLOWCTRL_RELEASE_MAX     32
++#define GMAC_FLOWCTRL_RELEASE_MIN     0
++
++/**********************************************************************
++ * GMAC Configuration 2
++ * GMAC0 Offset 0xA020
++ * GMAC1 Offset 0xE020
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0020
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rel_threshold      : 16;   /* flow control release threshold */
++              unsigned int set_threshold      : 16;   /* flow control set threshold */
++#else
++              unsigned int set_threshold      : 16;   /* flow control set threshold */
++              unsigned int rel_threshold      : 16;   /* flow control release threshold */
++#endif
++      } bits;
++} GMAC_CONFIG2_T;
++
++/**********************************************************************
++ * GMAC Configuration 3
++ * GMAC0 Offset 0xA024
++ * GMAC1 Offset 0xE024
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_0024
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int rel_threshold      : 16;   /* flow control release threshold */
++              unsigned int set_threshold      : 16;   /* flow control set threshold */
++#else
++              unsigned int set_threshold      : 16;   /* flow control set threshold */
++              unsigned int rel_threshold      : 16;   /* flow control release threshold */
++#endif
++      } bits;
++} GMAC_CONFIG3_T;
++
++
++/**********************************************************************
++ * GMAC STATUS
++ * GMAC0 Offset 0xA02C
++ * GMAC1 Offset 0xE02C
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit1_002c
++      {
++#if (BIG_ENDIAN==1)
++              unsigned int                            : 25;
++              unsigned int mii_rmii           :  2;   /* PHY interface type */
++              unsigned int reserved           :  1;
++              unsigned int duplex                     :  1;   /* duplex mode */
++              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
++              unsigned int link                       :  1;   /* link status */
++#else
++              unsigned int link                       :  1;   /* link status */
++              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
++              unsigned int duplex                     :  1;   /* duplex mode */
++              unsigned int reserved           :  1;
++              unsigned int mii_rmii           :  2;   /* PHY interface type */
++              unsigned int                            : 25;
++#endif
++      } bits;
++} GMAC_STATUS_T;
++
++#define GMAC_SPEED_10                 0
++#define GMAC_SPEED_100                        1
++#define GMAC_SPEED_1000                       2
++
++#define GMAC_PHY_MII                  0
++#define GMAC_PHY_GMII                 1
++#define GMAC_PHY_RGMII_100            2
++#define GMAC_PHY_RGMII_1000           3
++
++/**********************************************************************
++ * Queue Header
++ *    (1) TOE Queue Header
++ *    (2) Non-TOE Queue Header
++ *    (3) Interrupt Queue Header
++ *
++ * memory Layout
++ *    TOE Queue Header
++ *     0x60003000 +---------------------------+ 0x0000
++ *                            |     TOE Queue 0 Header        |
++ *                            |         8 * 4 Bytes       |
++ *                            +---------------------------+ 0x0020
++ *                            |     TOE Queue 1 Header        |
++ *                            |         8 * 4 Bytes           |
++ *                            +---------------------------+ 0x0040
++ *                            |       ......                          |
++ *                            |                                               |
++ *                            +---------------------------+
++ *
++ *    Non TOE Queue Header
++ *     0x60002000 +---------------------------+ 0x0000
++ *                            |   Default Queue 0 Header  |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+ 0x0008
++ *                            |   Default Queue 1 Header      |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+ 0x0010
++ *                            |   Classification Queue 0      |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+
++ *                            |   Classification Queue 1      |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+ (n * 8 + 0x10)
++ *                            |               ...                             |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+ (13 * 8 + 0x10)
++ *                            |   Classification Queue 13     |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+ 0x80
++ *                            |      Interrupt Queue 0        |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+
++ *                            |      Interrupt Queue 1        |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+
++ *                            |      Interrupt Queue 2        |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+
++ *                            |      Interrupt Queue 3        |
++ *                            |         2 * 4 Bytes           |
++ *                            +---------------------------+
++ *
++ **********************************************************************/
++#define TOE_QUEUE_HDR_ADDR(n)         (TOE_TOE_QUE_HDR_BASE + n * 32)
++#define TOE_Q_HDR_AREA_END                    (TOE_QUEUE_HDR_ADDR(TOE_TOE_QUEUE_MAX+1))
++#define TOE_DEFAULT_Q0_HDR_BASE               (TOE_NONTOE_QUE_HDR_BASE + 0x00)
++#define TOE_DEFAULT_Q1_HDR_BASE               (TOE_NONTOE_QUE_HDR_BASE + 0x08)
++#define TOE_CLASS_Q_HDR_BASE          (TOE_NONTOE_QUE_HDR_BASE + 0x10)
++#define TOE_INTR_Q_HDR_BASE                   (TOE_NONTOE_QUE_HDR_BASE + 0x80)
++#define INTERRUPT_QUEUE_HDR_ADDR(n)   (TOE_INTR_Q_HDR_BASE + n * 8)
++#define NONTOE_Q_HDR_AREA_END         (INTERRUPT_QUEUE_HDR_ADDR(TOE_INTR_QUEUE_MAX+1))
++/**********************************************************************
++ * TOE Queue Header Word 0
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      unsigned int base_size;
++} TOE_QHDR0_T;
++
++#define TOE_QHDR0_BASE_MASK   (~0x0f)
++
++/**********************************************************************
++ * TOE Queue Header Word 1
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_qhdr1
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int wptr                       : 16;   // bit 31:16
++              unsigned int rptr                       : 16;   // bit 15:0
++#else
++              unsigned int rptr                       : 16;   // bit 15:0
++              unsigned int wptr                       : 16;   // bit 31:16
++#endif
++      } bits;
++} TOE_QHDR1_T;
++
++/**********************************************************************
++ * TOE Queue Header Word 2
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_qhdr2
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int usd                        : 1;    // bit 31               0: if no data assembled yet
++              unsigned int ctl                        : 1;    // bit 30               1: have control flag bits (except ack)
++              unsigned int osq                        : 1;    // bit 29               1: out of sequence
++              unsigned int sat                        : 1;    // bit 28               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
++              unsigned int ip_opt                     : 1;    // bit 27               1: have IPV4 option or IPV6 Extension header
++              unsigned int tcp_opt            : 1;    // bit 26               1: Have TCP option
++              unsigned int abn                        : 1;    // bit 25               1: Abnormal case Found
++              unsigned int dack                       : 1;    // bit 24               1: Duplicated ACK
++              unsigned int reserved           : 7;    // bit 23:17
++              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
++#else
++              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
++              unsigned int reserved           : 7;    // bit 23:17
++              unsigned int dack                       : 1;    // bit 24               1: Duplicated ACK
++              unsigned int abn                        : 1;    // bit 25               1: Abnormal case Found
++              unsigned int tcp_opt            : 1;    // bit 26               1: Have TCP option
++              unsigned int ip_opt                     : 1;    // bit 27               1: have IPV4 option or IPV6 Extension header
++              unsigned int sat                        : 1;    // bit 28               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
++              unsigned int osq                        : 1;    // bit 29               1: out of sequence
++              unsigned int ctl                        : 1;    // bit 30               1: have control flag bits (except ack)
++              unsigned int usd                        : 1;    // bit 31               0: if no data assembled yet
++#endif
++      } bits;
++} TOE_QHDR2_T;
++
++/**********************************************************************
++ * TOE Queue Header Word 3
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      unsigned int seq_num;
++} TOE_QHDR3_T;
++
++/**********************************************************************
++ * TOE Queue Header Word 4
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      unsigned int ack_num;
++} TOE_QHDR4_T;
++
++/**********************************************************************
++ * TOE Queue Header Word 5
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_qhdr5
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int SeqCnt             : 16;   // bit 31:16
++              unsigned int AckCnt             : 16;   // bit 15:0
++#else
++              unsigned int AckCnt             : 16;   // bit 15:0
++              unsigned int SeqCnt             : 16;   // bit 31:16
++#endif
++      } bits;
++} TOE_QHDR5_T;
++
++/**********************************************************************
++ * TOE Queue Header Word 6
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_qhdr6
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int MaxPktSize : 14;   // bit 31:18
++              unsigned int iq_num             : 2;    // bit 17:16
++              unsigned int WinSize    : 16;   // bit 15:0
++#else
++              unsigned int WinSize    : 16;   // bit 15:0
++              unsigned int iq_num             : 2;    // bit 17:16
++              unsigned int MaxPktSize : 14;   // bit 31:18
++#endif
++      } bits;
++} TOE_QHDR6_T;
++
++/**********************************************************************
++ * TOE Queue Header Word 7
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_qhdr7
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int SeqThreshold       : 16;   // bit 31:16
++              unsigned int AckThreshold       : 16;   // bit 15:0
++#else
++              unsigned int AckThreshold       : 16;   // bit 15:0
++              unsigned int SeqThreshold       : 16;   // bit 31:16
++#endif
++      } bits;
++} TOE_QHDR7_T;
++
++/**********************************************************************
++ * TOE Queue Header
++ **********************************************************************/
++typedef struct
++{
++      TOE_QHDR0_T             word0;
++      TOE_QHDR1_T             word1;
++      TOE_QHDR2_T             word2;
++      TOE_QHDR3_T             word3;
++      TOE_QHDR4_T             word4;
++      TOE_QHDR5_T             word5;
++      TOE_QHDR6_T             word6;
++      TOE_QHDR7_T             word7;
++} TOE_QHDR_T;
++
++/**********************************************************************
++ * NONTOE Queue Header Word 0
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      unsigned int base_size;
++} NONTOE_QHDR0_T;
++
++#define NONTOE_QHDR0_BASE_MASK        (~0x0f)
++
++/**********************************************************************
++ * NONTOE Queue Header Word 1
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_nonqhdr1
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int wptr                       : 16;   // bit 31:16
++              unsigned int rptr                       : 16;   // bit 15:0
++#else
++              unsigned int rptr                       : 16;   // bit 15:0
++              unsigned int wptr                       : 16;   // bit 31:16
++#endif
++      } bits;
++} NONTOE_QHDR1_T;
++
++/**********************************************************************
++ * Non-TOE Queue Header
++ **********************************************************************/
++typedef struct
++{
++      NONTOE_QHDR0_T          word0;
++      NONTOE_QHDR1_T          word1;
++} NONTOE_QHDR_T;
++
++/**********************************************************************
++ * Interrupt Queue Header Word 0
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_intrqhdr0
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int wptr               : 16;   // bit 31:16    Write Pointer where hw stopped
++              unsigned int win_size   : 16;   // bit 15:0     Descriptor Ring Size
++#else
++              unsigned int win_size   : 16;   // bit 15:0     Descriptor Ring Size
++              unsigned int wptr               : 16;   // bit 31:16    Write Pointer where hw stopped
++#endif
++      } bits;
++} INTR_QHDR0_T;
++
++/**********************************************************************
++ * Interrupt Queue Header Word 1
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_intrqhdr1
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int ctl                        : 1;    // bit 31               1: have control flag bits (except ack)
++              unsigned int osq                        : 1;    // bit 30               1: out of sequence
++              unsigned int sat                        : 1;    // bit 29               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
++              unsigned int ip_opt                     : 1;    // bit 28               1: have IPV4 option or IPV6 Extension header
++              unsigned int tcp_opt            : 1;    // bit 27               1: Have TCP option
++              unsigned int abn                        : 1;    // bit 26               1: Abnormal case Found
++              unsigned int dack                       : 1;    // bit 25               1: Duplicated ACK
++              unsigned int tcp_qid            : 8;    // bit 24:17    TCP Queue ID
++              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
++#else
++              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
++              unsigned int tcp_qid            : 8;    // bit 24:17    TCP Queue ID
++              unsigned int dack                       : 1;    // bit 25               1: Duplicated ACK
++              unsigned int abn                        : 1;    // bit 26               1: Abnormal case Found
++              unsigned int tcp_opt            : 1;    // bit 27               1: Have TCP option
++              unsigned int ip_opt                     : 1;    // bit 28               1: have IPV4 option or IPV6 Extension header
++              unsigned int sat                        : 1;    // bit 29               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
++              unsigned int osq                        : 1;    // bit 30               1: out of sequence
++              unsigned int ctl                        : 1;    // bit 31               1: have control flag bits (except ack)
++#endif
++      } bits;
++} INTR_QHDR1_T;
++
++/**********************************************************************
++ * Interrupt Queue Header Word 2
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      unsigned int seq_num;
++} INTR_QHDR2_T;
++
++/**********************************************************************
++ * Interrupt Queue Header Word 3
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      unsigned int ack_num;
++} INTR_QHDR3_T;
++
++/**********************************************************************
++ * Interrupt Queue Header Word 4
++ **********************************************************************/
++typedef union
++{
++      unsigned int bits32;
++      struct bit_intrqhdr4
++      {
++#if (BIG_ENDIAN==1)
++
++              unsigned int SeqCnt             : 16;   // bit 31:16    Seq# change since last seq# intr.
++              unsigned int AckCnt             : 16;   // bit 15:0     Ack# change since last ack# intr.
++#else
++              unsigned int AckCnt             : 16;   // bit 15:0             Ack# change since last ack# intr.
++              unsigned int SeqCnt             : 16;   // bit 31:16    Seq# change since last seq# intr.
++#endif
++      } bits;
++} INTR_QHDR4_T;
++
++/**********************************************************************
++ * Interrupt Queue Header
++ **********************************************************************/
++typedef struct
++{
++      INTR_QHDR0_T            word0;
++      INTR_QHDR1_T            word1;
++      INTR_QHDR2_T            word2;
++      INTR_QHDR3_T            word3;
++      INTR_QHDR4_T            word4;
++      unsigned int            word5;
++      unsigned int            word6;
++      unsigned int            word7;
++} INTR_QHDR_T;
++
++/**********************************************************************
++ * GMAC Conf
++ **********************************************************************/
++typedef struct gmac_conf {
++      struct net_device *dev;
++      int portmap;
++      int vid;
++      int flag;     /* 1: active  0: non-active */
++} sys_gmac_conf;
++
++/**********************************************************************
++ * GMAC private data
++ **********************************************************************/
++typedef struct {
++      unsigned int            rwptr_reg;
++      unsigned int            desc_base;
++      unsigned int            total_desc_num;
++      unsigned short          finished_idx;
++      GMAC_TXDESC_T           *curr_tx_desc;
++      GMAC_TXDESC_T           *curr_finished_desc;
++      struct sk_buff          *tx_skb[TX_DESC_NUM];
++      unsigned long           total_sent;
++      unsigned long           total_finished;
++      unsigned long           intr_cnt;
++} GMAC_SWTXQ_T;
++
++typedef struct {
++      unsigned int            desc_base;
++      unsigned long           eof_cnt;
++} GMAC_HWTXQ_T;
++
++typedef struct gmac_private{
++      struct net_device       *dev;
++      unsigned int            existed;
++      unsigned int            port_id;        // 0 or 1
++      unsigned int            base_addr;
++      unsigned int            dma_base_addr;
++      unsigned char           *mac_addr1;
++      unsigned char           *mac_addr2;
++      unsigned int            swtxq_desc_base;
++      unsigned int            hwtxq_desc_base;
++      GMAC_SWTXQ_T            swtxq[TOE_SW_TXQ_NUM];
++      GMAC_HWTXQ_T            hwtxq[TOE_HW_TXQ_NUM];
++      NONTOE_QHDR_T           *default_qhdr;
++      unsigned int            default_desc_base;
++      unsigned int            default_desc_num;
++      unsigned int            rx_curr_desc;
++      DMA_RWPTR_T                     rx_rwptr;
++      struct sk_buff          *curr_rx_skb;
++      dma_addr_t                      default_desc_base_dma;
++      dma_addr_t                      swtxq_desc_base_dma;
++      dma_addr_t                      hwtxq_desc_base_dma;
++      unsigned int            irq;
++      unsigned int            flow_control_enable     ;
++      unsigned int            pre_phy_status;
++      unsigned int            full_duplex_cfg;
++      unsigned int            speed_cfg;
++      unsigned int            auto_nego_cfg;
++      unsigned int            full_duplex_status;
++      unsigned int            speed_status;
++      unsigned int            phy_mode;       /* 0->MII 1->GMII 2->RGMII(10/100) 3->RGMII(1000) */
++      unsigned int            phy_addr;
++      unsigned int            intr0_enabled;  // 1: enabled
++      unsigned int            intr1_enabled;  // 1: enabled
++      unsigned int            intr2_enabled;  // 1: enabled
++      unsigned int            intr3_enabled;  // 1: enabled
++      unsigned int            intr4_enabled;  // 1: enabled
++//    unsigned int            intr4_enabled_1;        // 1: enabled
++      unsigned int            intr0_selected; // 1: selected
++      unsigned int            intr1_selected; // 1: selected
++      unsigned int            intr2_selected; // 1: selected
++      unsigned int            intr3_selected; // 1: selected
++      unsigned int            intr4_selected; // 1: selected
++      // void                                 (*gmac_rcv_handler)(struct sk_buff *, int);
++      struct net_device_stats ifStatics;
++      unsigned long           txDerr_cnt[GMAC_NUM];
++      unsigned long           txPerr_cnt[GMAC_NUM];
++      unsigned long           RxDerr_cnt[GMAC_NUM];
++      unsigned long           RxPerr_cnt[GMAC_NUM];
++      unsigned int            isr_rx_cnt;
++      unsigned int            isr_tx_cnt;
++      unsigned long           rx_discard;
++      unsigned long           rx_error;
++      unsigned long           rx_mcast;
++      unsigned long           rx_bcast;
++      unsigned long           rx_status_cnt[8];
++      unsigned long           rx_chksum_cnt[8];
++      unsigned long           rx_sta1_ucast;  // for STA 1 MAC Address
++      unsigned long           rx_sta2_ucast;  // for STA 2 MAC Address
++      unsigned long           mib_full_cnt;
++      unsigned long           rx_pause_on_cnt;
++      unsigned long           tx_pause_on_cnt;
++      unsigned long           rx_pause_off_cnt;
++      unsigned long           tx_pause_off_cnt;
++      unsigned long           rx_overrun_cnt;
++      unsigned long           status_changed_cnt;
++      unsigned long           default_q_cnt;
++      unsigned long           hw_fq_empty_cnt;
++      unsigned long           sw_fq_empty_cnt;
++      unsigned long           default_q_intr_cnt;
++      pid_t               thr_pid;
++      wait_queue_head_t   thr_wait;
++      struct completion   thr_exited;
++    spinlock_t          lock;
++    int                 time_to_die;
++    int                                       operation;
++#ifdef SL351x_GMAC_WORKAROUND
++    unsigned long             short_frames_cnt;
++#endif
++}GMAC_INFO_T ;
++
++typedef struct toe_private {
++      unsigned int    swfq_desc_base;
++      unsigned int    hwfq_desc_base;
++      unsigned int    hwfq_buf_base;
++//    unsigned int    toe_desc_base[TOE_TOE_QUEUE_NUM];
++//    unsigned int    toe_desc_num;
++//    unsigned int    class_desc_base;
++//    unsigned int    class_desc_num;
++//    unsigned int    intr_desc_base;
++//    unsigned int    intr_desc_num;
++//    unsigned int    intr_buf_base;
++      DMA_RWPTR_T             fq_rx_rwptr;
++      GMAC_INFO_T             gmac[GMAC_NUM];
++      dma_addr_t              sw_freeq_desc_base_dma;
++      dma_addr_t              hw_freeq_desc_base_dma;
++      dma_addr_t              hwfq_buf_base_dma;
++      dma_addr_t              hwfq_buf_end_dma;
++//    dma_addr_t              toe_desc_base_dma[TOE_TOE_QUEUE_NUM];
++//    dma_addr_t              class_desc_base_dma;
++//    dma_addr_t              intr_desc_base_dma;
++//    dma_addr_t              intr_buf_base_dma;
++//    unsigned long   toe_iq_intr_full_cnt[TOE_INTR_QUEUE_NUM];
++//    unsigned long   toe_iq_intr_cnt[TOE_INTR_QUEUE_NUM];
++//    unsigned long   toe_q_intr_full_cnt[TOE_TOE_QUEUE_NUM];
++//    unsigned long   class_q_intr_full_cnt[TOE_CLASS_QUEUE_NUM];
++//    unsigned long   class_q_intr_cnt[TOE_CLASS_QUEUE_NUM];
++} TOE_INFO_T;
++
++extern TOE_INFO_T toe_private_data;
++
++#define GMAC_PORT0    0
++#define GMAC_PORT1    1
++/**********************************************************************
++ * PHY Definition
++ **********************************************************************/
++#define HPHY_ADDR                     0x01
++#define GPHY_ADDR                     0x02
++
++enum phy_state
++{
++    LINK_DOWN   = 0,
++    LINK_UP     = 1
++};
++
++/* transmit timeout value */
++
++#endif //_GMAC_SL351x_H
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/sl351x_hash_cfg.h
+@@ -0,0 +1,365 @@
++/*-----------------------------------------------------------------------------------
++*     sl351x_hash_cfg.h
++*
++*     Description:
++*     
++*     History:
++*
++*     9/14/2005       Gary Chen       Create
++*
++*-------------------------------------------------------------------------------------*/
++#ifndef _SL351x_HASH_CFG_H_
++#define _SL351x_HASH_CFG_H_   1
++
++// #define NAT_DEBUG_MSG      1
++// #define DEBUG_NAT_MIXED_HW_SW_TX   1
++#ifdef DEBUG_NAT_MIXED_HW_SW_TX
++      // #define NAT_DEBUG_LAN_HASH_TIMEOUT   1
++      // #define NAT_DEBUG_WAN_HASH_TIMEOUT   1
++#endif
++
++#define IPIV(a,b,c,d)         ((a<<24)+(b<<16)+(c<<8)+d)
++#define       IPIV1(a)                        ((a>>24)&0xff)
++#define       IPIV2(a)                        ((a>>16)&0xff)
++#define IPIV3(a)                      ((a>>8)&0xff)
++#define IPIV4(a)                      ((a)&0xff)
++
++#define HASH_MAX_BYTES                        64      // 128
++#define HASH_ACTION_DWORDS            9
++#define HASH_MAX_DWORDS                       (HASH_MAX_BYTES / sizeof(u32))
++#define HASH_MAX_KEY_DWORD            (HASH_MAX_DWORDS - HASH_ACTION_DWORDS)
++#define HASH_INIT_KEY                 0x534C4F52
++#define HASH_BITS                             12      // 12 : Normal, 7: Simulation
++#define HASH_TOTAL_ENTRIES            (1 << HASH_BITS)
++#define HASH_MAX_ENTRIES              (1 << 12)
++#define HASH_TOE_ENTRIES              (HASH_TOTAL_ENTRIES >> 5)
++#define HASH_BITS_MASK                        ((1 << HASH_BITS) - 1)
++
++#define hash_lock(lock)                       // spin_lock_bh(lock)
++#define hash_unlock(lock)             // spin_unlock_bh(lock)
++
++/*----------------------------------------------------------------------
++ *  special macro
++ ----------------------------------------------------------------------*/
++#define HASH_PUSH_WORD(cp, data)      {*cp++ = (((u16)(data))     ) & 0xff;   \
++                                                                      *cp++ = (((u16)(data)) >> 8) & 0xff;} 
++#define HASH_PUSH_DWORD(cp, data)     {*cp++ = (u8)(((u32)(data))      ) & 0xff;      \
++                                                                      *cp++ = (u8)(((u32)(data)) >>  8) & 0xff;       \
++                                                                      *cp++ = (u8)(((u32)(data)) >> 16) & 0xff;       \
++                                                                      *cp++ = (u8)(((u32)(data)) >> 24) & 0xff;}
++#define HASH_PUSH_BYTE(cp, data)      {*cp++ = ((u8)(data)) & 0xff;}
++
++/*----------------------------------------------------------------------
++ *  key
++ ----------------------------------------------------------------------*/
++typedef struct {
++      u8              port;
++      u16             Ethertype;
++      u8              da[6];
++      u8              sa[6];
++      u16             pppoe_sid;      
++      u16             vlan_id;        
++      u8              ipv4_hdrlen;    
++      u8              ip_tos; 
++      u8              ip_protocol;    
++      u32             ipv6_flow_label;
++      u8              sip[16];
++      u8              dip[16];
++      //__u32                 sip[4];
++      //__u32                 dip[4];
++      u8              l4_bytes[24];
++      u8              l7_bytes[24];
++      u8              ipv6;   // 1: IPv6, 0: IPV4
++} ENTRY_KEY_T;
++
++/*----------------------------------------------------------------------
++ *  key for NAT
++ *    Note: packed
++ ----------------------------------------------------------------------*/
++typedef struct {
++      u16             Ethertype;              // not used
++      u8              port_id;
++      u8              rule_id;
++      u8              ip_protocol;
++      u8              reserved1;              // ip_tos, not used
++      u16             reserved2;              // not used
++      u32             sip;
++      u32             dip;
++      u16             sport;
++      u16             dport;
++} NAT_KEY_T;
++
++#define NAT_KEY_DWORD_SIZE    (sizeof(NAT_KEY_T)/sizeof(u32))
++#define NAT_KEY_SIZE          (sizeof(NAT_KEY_T))
++
++/*----------------------------------------------------------------------
++ *  key for NAT
++ *    Note: packed
++ ----------------------------------------------------------------------*/
++typedef struct {
++      u16             Ethertype;              // not used
++      u8              port_id;
++      u8              rule_id;
++      u8              ip_protocol;
++      u8              reserved1;              // ip_tos, not used
++      u16             reserved2;              // not used
++      u32             sip;
++      u32             dip;
++      u16             reserved3;
++      u16             protocol;
++      u16             reserved4;
++      u16             call_id;
++} GRE_KEY_T;
++
++#define GRE_KEY_DWORD_SIZE    (sizeof(GRE_KEY_T)/sizeof(u32))
++#define GRE_KEY_SIZE          (sizeof(GRE_KEY_T))
++/*----------------------------------------------------------------------
++ *  key present or not
++ ----------------------------------------------------------------------*/
++typedef struct {
++      u32             port                    : 1;
++      u32             Ethertype               : 1;
++      u32             da                              : 1;
++      u32             sa                              : 1;
++      u32             pppoe_sid               : 1;    
++      u32             vlan_id                 : 1;    
++      u32             ipv4_hdrlen             : 1;    
++      u32             ip_tos                  : 1;
++      u32             ip_protocol             : 1;    
++      u32             ipv6_flow_label : 1;
++      u32             sip                             : 1;
++      u32             dip                             : 1;
++      u32             l4_bytes_0_3    : 1;
++      u32             l4_bytes_4_7    : 1;
++      u32             l4_bytes_8_11   : 1;
++      u32             l4_bytes_12_15  : 1;
++      u32             l4_bytes_16_19  : 1;
++      u32             l4_bytes_20_23  : 1;
++      u32             l7_bytes_0_3    : 1;
++      u32             l7_bytes_4_7    : 1;
++      u32             l7_bytes_8_11   : 1;
++      u32             l7_bytes_12_15  : 1;
++      u32             l7_bytes_16_19  : 1;
++      u32             l7_bytes_20_23  : 1;
++      u32             reserved                : 8;
++} KEY_FIELD_T;
++
++/*----------------------------------------------------------------------
++ *  action
++ ----------------------------------------------------------------------*/
++typedef struct {
++      u32             reserved0       : 5;    // bit 0:4
++      u32             pppoe           : 2;    // bit 5:6
++      u32             vlan            : 2;    // bit 7:8
++      u32             sa                      : 1;    // bit 9
++      u32             da                      : 1;    // bit 10
++      u32             Dport           : 1;    // bit 11
++      u32             Sport           : 1;    // bit 12
++      u32             Dip                     : 1;    // bit 13
++      u32             Sip                     : 1;    // bit 14
++      u32             sw_id           : 1;    // bit 15
++      u32             frag            : 1;    // bit 16
++      u32             option          : 1;    // bit 17
++      u32             ttl_0           : 1;    // bit 18
++      u32             ttl_1           : 1;    // bit 19
++      u32             mtu                     : 1;    // bit 20
++      u32             exception       : 1;    // bit 21
++      u32             srce_qid        : 1;    // bit 22
++      u32             discard         : 1;    // bit 23
++      u32             dest_qid        : 8;    // bit 24:31
++} ENTRY_ACTION_T;
++
++#define ACTION_DISCARD_BIT            BIT(23)
++#define ACTION_SRCE_QID_BIT           BIT(22)
++#define ACTION_EXCEPTION_BIT  BIT(21)
++#define ACTION_MTU_BIT                        BIT(20)
++#define ACTION_TTL_1_BIT              BIT(19)
++#define ACTION_TTL_0_BIT              BIT(18)
++#define ACTION_IP_OPTION              BIT(17)
++#define ACTION_FRAG_BIT                       BIT(16)
++#define ACTION_SWID_BIT                       BIT(15)
++#define ACTION_SIP_BIT                        BIT(14)
++#define ACTION_DIP_BIT                        BIT(13)
++#define ACTION_SPORT_BIT              BIT(12)
++#define ACTION_DPORT_BIT              BIT(11)
++#define ACTION_DA_BIT                 BIT(10)
++#define ACTION_SA_BIT                 BIT(9)
++#define ACTION_VLAN_DEL_BIT           BIT(8)
++#define ACTION_VLAN_INS_BIT           BIT(7)
++#define ACTION_PPPOE_DEL_BIT  BIT(6)
++#define ACTION_PPPOE_INS_BIT  BIT(5)
++#define ACTION_L4_THIRD_BIT           BIT(4)
++#define ACTION_L4_FOURTH_BIT  BIT(3)
++
++#define NAT_ACTION_BITS                       (ACTION_SRCE_QID_BIT  | ACTION_EXCEPTION_BIT |  \
++                                                              ACTION_TTL_1_BIT | ACTION_TTL_0_BIT |                   \
++                                                              ACTION_IP_OPTION | ACTION_FRAG_BIT |                    \
++                                                              ACTION_DA_BIT | ACTION_SA_BIT)
++#define NAT_LAN2WAN_ACTIONS           (NAT_ACTION_BITS | ACTION_SIP_BIT | ACTION_SPORT_BIT)
++#define NAT_WAN2LAN_ACTIONS           (NAT_ACTION_BITS | ACTION_DIP_BIT | ACTION_DPORT_BIT)
++#define NAT_PPPOE_LAN2WAN_ACTIONS     (NAT_LAN2WAN_ACTIONS | ACTION_PPPOE_INS_BIT)
++#define NAT_PPPOE_WAN2LAN_ACTIONS     (NAT_WAN2LAN_ACTIONS | ACTION_PPPOE_DEL_BIT)
++#define NAT_PPTP_LAN2WAN_ACTIONS      (NAT_ACTION_BITS | ACTION_SIP_BIT | ACTION_L4_FOURTH_BIT)
++#define NAT_PPTP_WAN2LAN_ACTIONS      (NAT_ACTION_BITS | ACTION_DIP_BIT | ACTION_L4_FOURTH_BIT)
++#define NAT_PPPOE_PPTP_LAN2WAN_ACTIONS        (NAT_PPTP_LAN2WAN_ACTIONS | ACTION_PPPOE_INS_BIT)
++#define NAT_PPPOE_PPTP_WAN2LAN_ACTIONS        (NAT_PPTP_WAN2LAN_ACTIONS | ACTION_PPPOE_DEL_BIT)
++                                                              
++/*----------------------------------------------------------------------
++ *  parameter
++ ----------------------------------------------------------------------*/
++typedef struct {
++      u8              da[6];
++      u8              sa[6];
++      u16             vlan;   
++      u16     pppoe;  
++      u32             Sip;
++      u32             Dip;
++      u16     Sport;  
++      u16     Dport;  
++      u16     sw_id;  
++      u16     mtu;    
++} ENTRY_PARAM_T;
++
++/*----------------------------------------------------------------------
++ *  Hash Entry
++ ----------------------------------------------------------------------*/
++typedef struct {
++      char                    rule;
++      ENTRY_KEY_T             key;
++      KEY_FIELD_T             key_present;
++      ENTRY_ACTION_T  action;
++      ENTRY_PARAM_T   param;
++      int                             index;
++      int                             total_dwords;
++} HASH_ENTRY_T;
++
++/*----------------------------------------------------------------------
++ *  NAT Hash Entry
++ ----------------------------------------------------------------------*/
++typedef struct {
++      short   counter;
++      short   interval;
++} HASH_TIMEOUT_T;
++
++/*----------------------------------------------------------------------
++ *  NAT Hash Entry for TCP/UDP protocol
++ ----------------------------------------------------------------------*/
++typedef struct {
++      NAT_KEY_T                       key;
++      union {
++              u32                             dword;
++              ENTRY_ACTION_T  bits;
++      } action;
++      ENTRY_PARAM_T           param;
++      HASH_TIMEOUT_T          tmo;    // used by software only, to use memory space efficiently
++} NAT_HASH_ENTRY_T;
++
++#define NAT_HASH_ENTRY_SIZE           (sizeof(NAT_HASH_ENTRY_T))
++
++/*----------------------------------------------------------------------
++ *  GRE Hash Entry for PPTP/GRE protocol
++ ----------------------------------------------------------------------*/
++typedef struct {
++      GRE_KEY_T                       key;
++      union {
++              u32                             dword;
++              ENTRY_ACTION_T  bits;
++      } action;
++      ENTRY_PARAM_T           param;
++      HASH_TIMEOUT_T          tmo;    // used by software only, to use memory space efficiently
++} GRE_HASH_ENTRY_T;
++
++#define GRE_HASH_ENTRY_SIZE           (sizeof(GRE_HASH_ENTRY_T))
++
++/*----------------------------------------------------------------------
++ *  External Variables
++ ----------------------------------------------------------------------*/
++extern char                           hash_tables[HASH_TOTAL_ENTRIES][HASH_MAX_BYTES] __attribute__ ((aligned(16)));
++extern u32                            hash_nat_owner_bits[HASH_TOTAL_ENTRIES/32];
++/*----------------------------------------------------------------------
++* hash_get_valid_flag
++*----------------------------------------------------------------------*/
++static inline int hash_get_valid_flag(int index)
++{
++      volatile u32 *hash_valid_bits_ptr = (volatile u32 *)TOE_V_BIT_BASE;
++
++#ifdef SL351x_GMAC_WORKAROUND
++      if (index >= (0x80 * 8) && index < (0x8c * 8))
++              return 1;
++#endif        
++      return (hash_valid_bits_ptr[index/32] & (1 << (index %32)));
++}
++
++/*----------------------------------------------------------------------
++* hash_get_nat_owner_flag
++*----------------------------------------------------------------------*/
++static inline int hash_get_nat_owner_flag(int index)
++{
++      return (hash_nat_owner_bits[index/32] & (1 << (index %32)));
++}
++
++/*----------------------------------------------------------------------
++* hash_validate_entry
++*----------------------------------------------------------------------*/
++static inline void hash_validate_entry(int index)
++{
++      volatile u32    *hash_valid_bits_ptr = (volatile u32 *)TOE_V_BIT_BASE;
++      register int    ptr = index/32, bits = 1 << (index %32);
++      
++      hash_valid_bits_ptr[ptr] |= bits;
++}
++
++/*----------------------------------------------------------------------
++* hash_invalidate_entry
++*----------------------------------------------------------------------*/
++static inline void hash_invalidate_entry(int index)
++{
++      volatile u32 *hash_valid_bits_ptr = (volatile u32 *)TOE_V_BIT_BASE;
++      register int    ptr = index/32, bits = 1 << (index %32);
++      
++      hash_valid_bits_ptr[ptr] &= ~(bits);
++}
++
++/*----------------------------------------------------------------------
++* hash_nat_enable_owner
++*----------------------------------------------------------------------*/
++static inline void hash_nat_enable_owner(int index)
++{
++      hash_nat_owner_bits[index/32] |= (1 << (index % 32));
++}
++
++/*----------------------------------------------------------------------
++* hash_nat_disable_owner
++*----------------------------------------------------------------------*/
++static inline void hash_nat_disable_owner(int index)
++{
++      hash_nat_owner_bits[index/32] &= ~(1 << (index % 32));
++}
++
++/*----------------------------------------------------------------------
++* hash_get_entry
++*----------------------------------------------------------------------*/
++static inline void *hash_get_entry(int index)
++{
++      return (void*) &hash_tables[index][0];
++}
++
++/*----------------------------------------------------------------------
++* Functions
++*----------------------------------------------------------------------*/
++extern int hash_add_entry(HASH_ENTRY_T *entry);
++extern void sl351x_hash_init(void);
++extern void hash_set_valid_flag(int index, int valid);
++extern void hash_set_nat_owner_flag(int index, int valid);
++extern void *hash_get_entry(int index);
++extern int hash_build_keys(u32 *destp, HASH_ENTRY_T *entry);
++extern void hash_build_nat_keys(u32 *destp, HASH_ENTRY_T *entry);
++extern int hash_write_entry(HASH_ENTRY_T *entry, u8 *key);
++extern int hash_add_entry(HASH_ENTRY_T *entry);
++extern        u16 hash_crc16(u16 crc, u8 *datap, u32 len);
++extern        u16 hash_gen_crc16(u8 *datap, u32 len);
++
++#endif // _SL351x_HASH_CFG_H_
++
++
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/sl351x_nat_cfg.h
+@@ -0,0 +1,211 @@
++/**************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.                
++*--------------------------------------------------------------------------
++*     sl_nat_cfg.h
++*
++*     Description:
++*             - Define the Device Control Commands for NAT Configuration
++*     
++*     History:
++*
++*     4/28/2006       Gary Chen       Create
++*
++*-----------------------------------------------------------------------------*/
++#ifndef _SL351x_NAT_CFG_H_
++#define _SL351x_NAT_CFG_H_    1
++
++/*----------------------------------------------------------------------
++* Confiuration
++*----------------------------------------------------------------------*/
++#ifdef CONFIG_NETFILTER
++#define CONFIG_SL351x_NAT                     1
++#undef CONFIG_SL351x_NAT
++#undef CONFIG_SL351x_SYSCTL
++#endif
++#define CONFIG_NAT_MAX_IP_NUM         4       // per device (eth0 or eth1)
++#define CONFIG_NAT_MAX_XPORT          64
++#define CONFIG_NAT_MAX_WRULE          16      // per Queue
++#define CONFIG_NAT_TXQ_NUM                    4
++/*----------------------------------------------------------------------
++* Command set
++*----------------------------------------------------------------------*/
++#define SIOCDEVSL351x SIOCDEVPRIVATE  // 0x89F0
++#define NATSSTATUS            0
++#define NATGSTATUS            1
++#define NATSETPORT            2
++#define NATGETPORT            3
++#define NATADDIP              4
++#define NATDELIP              5
++#define NATGETIP              6
++#define NATAXPORT             7
++#define NATDXPORT             8
++#define NATGXPORT             9
++#define NATSWEIGHT            10
++#define NATGWEIGHT            11
++#define NATAWRULE             12
++#define NATDWRULE             13
++#define NATGWRULE             14
++#define NATSDEFQ              15
++#define NATGDEFQ              16
++#define NATRMIPCFG            17              // remove IP config
++#define NATTESTENTRY  18
++#define NATSETMEM             19
++#define NATSHOWMEM            20
++/*----------------------------------------------------------------------
++* Command Structure
++*----------------------------------------------------------------------*/
++// Common Header
++typedef struct {
++      unsigned short          cmd;    // command ID
++      unsigned short          len;    // data length, excluding this header
++} NATCMD_HDR_T;
++
++// NATSSTATUS & NATGSTATUS commands
++typedef struct {
++      unsigned char           enable;
++} NAT_STATUS_T;       
++
++// NATSETPORT & NATGETPORT commands
++typedef struct {
++      unsigned char           portmap;
++} NAT_PORTCFG_T;
++
++typedef struct {
++      unsigned int            ipaddr;
++      unsigned int            netmask;
++} NAT_IP_ENTRY_T;
++
++// NATADDIP & NATDELIP commands
++typedef struct {
++      NAT_IP_ENTRY_T  entry;
++} NAT_IPCFG_T;
++
++// NATGETIP command
++typedef struct {
++      unsigned int    total;
++      NAT_IP_ENTRY_T  entry[CONFIG_NAT_MAX_IP_NUM];
++} NAT_IPCFG_ALL_T;
++
++typedef struct {
++      unsigned int            protocol;
++      unsigned short          sport_start;
++      unsigned short          sport_end;
++      unsigned short          dport_start;
++      unsigned short          dport_end;
++} NAT_XPORT_ENTRY_T;
++
++// NATAXPORT & NATDXPORT Commands
++typedef struct {
++      NAT_XPORT_ENTRY_T       entry;
++} NAT_XPORT_T;
++
++// NATGXPORT Command
++typedef struct {
++      unsigned int            total;
++      NAT_XPORT_ENTRY_T       entry[CONFIG_NAT_MAX_XPORT];
++} NAT_XPORT_ALL_T;
++
++// NATSWEIGHT & NATGWEIGHT Commands
++typedef struct {
++      unsigned char           weight[CONFIG_NAT_TXQ_NUM];
++} NAT_WEIGHT_T;
++
++typedef struct {
++      unsigned int            protocol;
++      unsigned int            sip_start;
++      unsigned int            sip_end;
++      unsigned int            dip_start;
++      unsigned int            dip_end;
++      unsigned short          sport_start;
++      unsigned short          sport_end;
++      unsigned short          dport_start;
++      unsigned short          dport_end;
++} NAT_WRULE_ENTRY_T;  
++
++// NATAWRULE & NATDWRULE Commands
++typedef struct {
++      unsigned int            qid;
++      NAT_WRULE_ENTRY_T       entry;
++} NAT_WRULE_T;
++
++// NATGWRULE Command
++typedef struct {
++      unsigned int            total;
++      NAT_WRULE_ENTRY_T       entry[CONFIG_NAT_MAX_WRULE];
++} NAT_WRULE_ALL_T;
++
++// NATSDEFQ & NATGDEFQ commands
++typedef struct {
++      unsigned int            qid;
++} NAT_QUEUE_T;        
++
++// NATTESTENTRY 
++typedef struct {
++      u_int16_t               cmd;    // command ID
++      u_int16_t               len;    // data length, excluding this header
++      u_int8_t                init_enable;
++} NAT_TESTENTRY_T;    
++      
++typedef union
++{
++      NAT_STATUS_T            status;
++      NAT_PORTCFG_T           portcfg;
++      NAT_IPCFG_T                     ipcfg;
++      NAT_XPORT_T                     xport;
++      NAT_WEIGHT_T            weight;
++      NAT_WRULE_T                     wrule;
++      NAT_QUEUE_T                     queue;
++      NAT_TESTENTRY_T init_entry;
++} NAT_REQ_E;
++      
++/*----------------------------------------------------------------------
++* NAT Configuration
++*     - Used by driver only
++*----------------------------------------------------------------------*/
++typedef struct {
++      unsigned int            enabled;
++      unsigned int            init_enabled;
++      unsigned int            tcp_udp_rule_id;
++      unsigned int            gre_rule_id;
++      unsigned int            lan_port;
++      unsigned int            wan_port;
++      unsigned int            default_hw_txq;
++      short                           tcp_tmo_interval;
++      short                           udp_tmo_interval;
++      short                           gre_tmo_interval;
++      NAT_IPCFG_ALL_T         ipcfg[2];       // LAN/WAN port
++      NAT_XPORT_ALL_T         xport;
++      NAT_WEIGHT_T            weight;
++      NAT_WRULE_ALL_T         wrule[CONFIG_NAT_TXQ_NUM];
++} NAT_CFG_T;
++
++/*----------------------------------------------------------------------
++* NAT Control Block
++*     - Used by driver only
++*     - Stores LAN-IN or WAN-IN information
++*     - WAN-OUT and LAN-OUT driver use them to build up a hash entry
++*     - NOTES: To update this data structure, MUST take care of alignment issue
++*   -          MUST make sure that the size of skbuff structure must 
++*            be larger than (40 + sizof(NAT_CB_T))
++*----------------------------------------------------------------------*/
++typedef struct {
++      unsigned short          tag;
++      unsigned char           sa[6];
++      unsigned int            sip;
++      unsigned int            dip;
++      unsigned short          sport;
++      unsigned short          dport;
++      unsigned char           pppoe_frame;
++      unsigned char           state;                  // same to enum tcp_conntrack
++      unsigned char           reserved[2];
++} NAT_CB_T;
++
++#define NAT_CB_TAG            0x4C53  // "SL"
++#define NAT_CB_SIZE           sizeof(NAT_CB_T)
++// #define NAT_SKB_CB(skb)    (NAT_CB_T *)(((unsigned int)&((skb)->cb[40]) + 3) & ~3)  // for align 4
++#define NAT_SKB_CB(skb)       (NAT_CB_T *)&((skb)->cb[40])  // for align 4
++
++#endif // _SL351x_NAT_CFG_H_
++
++
++
+--- /dev/null
++++ b/include/asm-arm/arch-sl2312/sl351x_toe.h
+@@ -0,0 +1,88 @@
++/**************************************************************************
++* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
++*--------------------------------------------------------------------------
++* Name                        : sl351x_toe.h
++* Description :
++*             Define for TOE driver of Storlink SL351x
++*
++* History
++*
++*     Date            Writer          Description
++*----------------------------------------------------------------------------
++*                             Xiaochong       Create
++*
++****************************************************************************/
++#ifndef __SL351x_TOE_H
++#define __SL351x_TOE_H        1
++#include <net/sock.h>
++#include <asm/arch/sl351x_gmac.h>
++#include <linux/timer.h>
++#include <linux/netdevice.h>
++#include <linux/ip.h>
++#include <linux/if_ether.h>
++/*
++ * TOE_CONN_T is data structure of tcp connection info, used at both
++ * device layer and kernel tcp layer
++ * skb is the jumbo frame
++ */
++
++struct toe_conn{
++      __u8    qid;            // connection qid 0~63.
++      __u8    ip_ver;         // 0: not used; 4: ipv4; 6: ipv6.
++      /* hash key of the connection */
++      __u16   source;
++      __u16   dest;
++      __u32   saddr[4];
++      __u32   daddr[4];
++
++      __u32   seq;
++      __u32   ack_seq;
++
++      /* these fields are used to set TOE QHDR */
++      __u32   ack_threshold;
++      __u32   seq_threshold;
++      __u16   max_pktsize;
++
++      /* used by sw toe, accumulated ack_seq of ack frames */
++      __u16   ack_cnt;
++      /* used by sw toe, accumulated data frames held at driver */
++      __u16   cur_pktsize;
++
++      __u8    status;
++#define       TCP_CONN_UNDEFINE               0X00
++#define       TCP_CONN_CREATION               0X01
++#define       TCP_CONN_CONNECTING             0X02
++#define       TCP_CONN_ESTABLISHED    0X04
++#define       TCP_CONN_RESET                  0X08    // this is used for out-of-order
++                                                      // or congestion window is small
++#define       TCP_CONN_CLOSING                0X10
++#define       TCP_CONN_CLOSED                 0x11
++
++      __u16   hash_entry_index;       /* associated hash entry */
++
++      // one timer per connection. Otherwise all connections should be scanned
++      // in a timeout interrupt, and timeout interrupt is triggered no matter
++      // a connection is actually timeout or not.
++      struct timer_list       rx_timer;
++      unsigned long           last_rx_jiffies;
++      GMAC_INFO_T                     *gmac;
++      struct net_device       *dev;
++
++      //      for generating pure ack frame.
++      struct ethhdr           l2_hdr;
++      struct iphdr            l3_hdr;
++
++      spinlock_t                      conn_lock;
++      DMA_RWPTR_T                     toeq_rwptr;
++      GMAC_RXDESC_T           *curr_desc;
++      struct sk_buff          *curr_rx_skb;
++};
++
++struct jumbo_frame {
++      struct sk_buff  *skb0;          // the head of jumbo frame
++      struct sk_buff  *tail;          // the tail of jumbo frame
++      struct iphdr    *iphdr0;        // the ip hdr of skb0.
++      struct tcphdr   *tcphdr0;       // the tcp hdr of skb0.
++};
++
++#endif // __SL351x_TOE_H
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -2131,6 +2131,42 @@
+         The safe and default value for this is N.
++config NET_GMAC
++      tristate "Storlink Gigabit Ethernet support"
++      depends on ARCH_SL2312
++      help
++        This driver supports Storlink dual Gigabit Ethernet.
++
++config NET_SL2312
++      tristate "Storlink Gigabit Ethernet support"
++      depends on NET_GMAC
++      help
++        This driver supports Storlink dual Gigabit Ethernet.
++
++config NET_SL351X
++      tristate "Storlink Lepus Gigabit Ethernet support"
++      depends on NET_GMAC
++      help
++        This driver supports Storlink TOE and NAT dual Gigabit Ethernet.
++
++config SL2312_TSO
++      bool "Tx Segmentation Enable"
++      depends on NET_GMAC
++      help
++        TBD
++
++config SL2312_MPAGE
++      bool "Tx Multipage Enable"
++      depends on NET_GMAC
++      help
++        TBD
++
++config SL2312_RECVFILE
++      bool "Rx Multipage Enable"
++      depends on NET_GMAC
++      help
++        TBD
++
+ config DL2K
+       tristate "D-Link DL2000-based Gigabit Ethernet support"
+       depends on PCI
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -236,4 +236,8 @@
+ obj-$(CONFIG_FS_ENET) += fs_enet/
+-obj-$(CONFIG_NETXEN_NIC) += netxen/
++
++obj-$(CONFIG_NET_SL351X)+= sl351x_gmac.o sl351x_nat.o sl351x_hash.o sl351x_crc16.o sl351x_proc.o sl_switch.o
++obj-$(CONFIG_NET_SL2312)+= sl2312_emac.o
++
++
diff --git a/target/linux/storm/patches/003-gmac_one_phy.patch b/target/linux/storm/patches/003-gmac_one_phy.patch
new file mode 100644 (file)
index 0000000..15a69c9
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/include/asm-arm/arch-sl2312/sl351x_gmac.h
++++ b/include/asm-arm/arch-sl2312/sl351x_gmac.h
+@@ -21,7 +21,7 @@
+ #undef BIG_ENDIAN
+ #define BIG_ENDIAN                            0
+ #define GMAC_DEBUG                            1
+-#define GMAC_NUM                                      2
++#define GMAC_NUM                                      1
+ //#define     L2_jumbo_frame                          1
+ #define _PACKED_                                      __attribute__ ((aligned(1), packed))
diff --git a/target/linux/storm/patches/004-gmac_enable_napi.patch b/target/linux/storm/patches/004-gmac_enable_napi.patch
new file mode 100644 (file)
index 0000000..ea374c4
--- /dev/null
@@ -0,0 +1,81 @@
+--- a/drivers/net/sl351x_gmac.c
++++ b/drivers/net/sl351x_gmac.c
+@@ -68,9 +68,11 @@
+ #include <linux/ip.h>
+ #endif
++/* Enables NAPI unconditionally */
++#define CONFIG_SL_NAPI                                        1
++
+ // #define SL351x_TEST_WORKAROUND
+ #ifdef CONFIG_SL351x_NAT
+-#define CONFIG_SL_NAPI                                        1
+ #endif
+ #define GMAX_TX_INTR_DISABLED                 1
+ #define DO_HW_CHKSUM                                  1
+@@ -124,12 +126,17 @@
+  *************************************************************/
+ static int    gmac_initialized = 0;
+ TOE_INFO_T toe_private_data;
+-//static int          do_again = 0;
++static int            do_again = 0;
+ spinlock_t gmac_fq_lock;
+ unsigned int FLAG_SWITCH;
+ static unsigned int           next_tick = 3 * HZ;
+-static unsigned char          eth_mac[CONFIG_MAC_NUM][6]= {{0x00,0x11,0x11,0x87,0x87,0x87}, {0x00,0x22,0x22,0xab,0xab,0xab}};
++static unsigned char          eth_mac[CONFIG_MAC_NUM][6]= {
++              {0x00,0x11,0x11,0x87,0x87,0x87},
++#if GMAC_NUM != 1
++              {0x00,0x22,0x22,0xab,0xab,0xab}
++#endif
++};
+ #undef CONFIG_SL351x_RXTOE
+ extern NAT_CFG_T nat_cfg;
+@@ -2443,7 +2450,8 @@
+       toe = (TOE_INFO_T *)&toe_private_data;
+ //    handle NAPI
+ #ifdef CONFIG_SL_NAPI
+-if (storlink_ctl.pauseoff == 1)
++      /* XXX: check this, changed from 'storlink_ctl.pauseoff == 1' to if (1) */
++if (1)
+ {
+ /* disable GMAC interrupt */
+     //toe_gmac_disable_interrupt(tp->irq);
+@@ -2530,7 +2538,7 @@
+                               {
+                                       if (likely(netif_rx_schedule_prep(dev)))
+                               {
+-                                      unsigned int data32;
++                                      // unsigned int data32;
+                                       // disable GMAC-0 rx interrupt
+                                       // class-Q & TOE-Q are implemented in future
+                                       //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+@@ -2563,7 +2571,7 @@
+                       {
+                               if (likely(netif_rx_schedule_prep(dev)))
+                       {
+-                              unsigned int data32;
++                              // unsigned int data32;
+                               // disable GMAC-0 rx interrupt
+                               // class-Q & TOE-Q are implemented in future
+                               //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+@@ -4217,7 +4225,7 @@
+       GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
+       unsigned int            status4;
+       volatile DMA_RWPTR_T    fq_rwptr;
+-      int                                     max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
++      // int                                  max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
+       //unsigned long         rx_old_bytes;
+       struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
+       //unsigned long long    rx_time;
+@@ -4479,7 +4487,7 @@
+       if (rwptr.bits.rptr == rwptr.bits.wptr)
+       {
+-              unsigned int data32;
++              // unsigned int data32;
+                       //printk("%s:---[rwptr.bits.rptr == rwptr.bits.wptr]   rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
+           /* Receive descriptor is empty now */
diff --git a/target/linux/storm/patches/005-gmac_napi_mask_intrs.patch b/target/linux/storm/patches/005-gmac_napi_mask_intrs.patch
new file mode 100644 (file)
index 0000000..f0b6375
--- /dev/null
@@ -0,0 +1,248 @@
+--- a/drivers/net/sl351x_gmac.c
++++ b/drivers/net/sl351x_gmac.c
+@@ -127,6 +127,7 @@
+ static int    gmac_initialized = 0;
+ TOE_INFO_T toe_private_data;
+ static int            do_again = 0;
++static int rx_poll_enabled;
+ spinlock_t gmac_fq_lock;
+ unsigned int FLAG_SWITCH;
+@@ -1065,7 +1066,8 @@
+           tp->intr3_enabled =         0xffffffff;
+           tp->intr4_selected =        GMAC0_INT_BITS | CLASS_RX_FULL_INT_BITS |
+                                                       HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
+-          tp->intr4_enabled =         GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT;
++          tp->intr4_enabled =         GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT| GMAC0_RX_OVERRUN_INT_BIT;
++          // GMAC0_TX_PAUSE_OFF_INT_BIT| GMAC0_MIB_INT_BIT;
+           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) & ~tp->intr0_selected;
+           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
+@@ -1115,7 +1117,7 @@
+               tp->intr3_enabled       |=      0xffffffff;
+               tp->intr4_selected      |=      CLASS_RX_FULL_INT_BITS |
+                                                               HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
+-              tp->intr4_enabled       |=      SWFQ_EMPTY_INT_BIT;
++              tp->intr4_enabled       |=      SWFQ_EMPTY_INT_BIT | GMAC1_RX_OVERRUN_INT_BIT;
+               }
+           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) | tp->intr0_selected;
+           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
+@@ -2408,7 +2410,7 @@
+       // unsigned short max_cnt=TOE_SW_FREEQ_DESC_NUM>>1;
+       fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-      spin_lock_irqsave(&gmac_fq_lock, flags);
++      // spin_lock_irqsave(&gmac_fq_lock, flags);
+       //while ((max_cnt--) && (unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
+       //                              TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
+       while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
+@@ -2428,10 +2430,47 @@
+               SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
+               toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
+       }
+-      spin_unlock_irqrestore(&gmac_fq_lock, flags);
++      // spin_unlock_irqrestore(&gmac_fq_lock, flags);
+ }
+ // EXPORT_SYMBOL(toe_gmac_fill_free_q);
++static void gmac_registers(const char *message)
++{
++      unsigned int            status0;
++      unsigned int            status1;
++      unsigned int            status2;
++      unsigned int            status3;
++      unsigned int            status4;
++
++      printk("%s\n", message);
++
++      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
++      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
++      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
++      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++
++      printk("status: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
++                 status0, status1, status2, status3, status4);
++
++      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_0_REG);
++      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_2_REG);
++      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_3_REG);
++      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++
++      printk("mask  : s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
++                 status0, status1, status2, status3, status4);
++
++      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
++      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
++      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
++      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
++      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++
++      printk("select: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
++                 status0, status1, status2, status3, status4);
++}
+ /*----------------------------------------------------------------------
+ * toe_gmac_interrupt
+ *----------------------------------------------------------------------*/
+@@ -2492,6 +2531,7 @@
+               writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
+       if (status4)
+               writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
++
+ #if 0
+       /* handle freeq interrupt first */
+       if (status4 & tp->intr4_enabled) {
+@@ -2536,10 +2576,31 @@
+                       }
+                               if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
+                               {
+-                                      if (likely(netif_rx_schedule_prep(dev)))
++                                      if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
+                               {
+-                                      // unsigned int data32;
+-                                      // disable GMAC-0 rx interrupt
++                                      unsigned int data32;
++
++                                              if (rx_poll_enabled)
++                                                              gmac_registers("check #1");
++
++                                              BUG_ON(rx_poll_enabled == 1);
++
++#if 0
++                                      /* Masks GMAC-0 rx interrupt */
++                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                              data32 &= ~(DEFAULT_Q0_INT_BIT);
++                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++
++                                      /* Masks GMAC-0 queue empty interrupt */
++                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++                                              data32 &= ~DEFAULT_Q0_INT_BIT;
++                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++
++                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++                                              data32 &= ~DEFAULT_Q0_INT_BIT;
++                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++#endif
++
+                                       // class-Q & TOE-Q are implemented in future
+                                       //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+                                       //data32 &= ~DEFAULT_Q0_INT_BIT;
+@@ -2549,7 +2610,8 @@
+                                               //tp->total_q_cnt_napi=0;
+                                               //rx_time = jiffies;
+                                               //rx_old_bytes = isPtr->rx_bytes;
+-                              __netif_rx_schedule(dev);
++                                              __netif_rx_schedule(dev);
++                                              rx_poll_enabled = 1;
+                               }
+                       }
+               }
+@@ -2569,9 +2631,31 @@
+                       if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
+                       {
+-                              if (likely(netif_rx_schedule_prep(dev)))
++                              if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
+                       {
+-                              // unsigned int data32;
++                              unsigned int data32;
++
++                                      if (rx_poll_enabled)
++                                                      gmac_registers("check #2");
++
++                                      BUG_ON(rx_poll_enabled == 1);
++
++#if 0
++                                      /* Masks GMAC-1 rx interrupt */
++                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                      data32 &= ~(DEFAULT_Q1_INT_BIT);
++                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++
++                              /* Masks GMAC-1 queue empty interrupt */
++                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++                                      data32 &= ~DEFAULT_Q1_INT_BIT;
++                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++
++                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++                                      data32 &= ~DEFAULT_Q1_INT_BIT;
++                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++#endif
++
+                               // disable GMAC-0 rx interrupt
+                               // class-Q & TOE-Q are implemented in future
+                               //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+@@ -2583,9 +2667,13 @@
+                                       //rx_time = jiffies;
+                                       //rx_old_bytes = isPtr->rx_bytes;
+                               __netif_rx_schedule(dev);
++                              rx_poll_enabled = 1;
+                       }
+                       }
+               }
++      } else {
++
++              gmac_registers("check #3");
+       }
+       // Interrupt Status 0
+@@ -3306,8 +3394,10 @@
+               SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
+       tp->rx_rwptr.bits32 = rwptr.bits32;
+-              toe_gmac_fill_free_q();
+       }
++
++      /* Handles first available packets only then refill the queue. */
++      toe_gmac_fill_free_q();
+ }
+ /*----------------------------------------------------------------------
+@@ -4217,6 +4307,7 @@
+     GMAC_RXDESC_T     *curr_desc;
+       struct sk_buff          *skb;
+     DMA_RWPTR_T                       rwptr;
++    unsigned int data32;
+       unsigned int            pkt_size;
+       unsigned int        desc_count;
+       unsigned int        good_frame, chksum_status, rx_status;
+@@ -4231,7 +4322,7 @@
+       //unsigned long long    rx_time;
+-
++      BUG_ON(rx_poll_enabled == 0);
+ #if 1
+       if (do_again)
+       {
+@@ -4516,6 +4607,30 @@
+ #endif
+         //toe_gmac_fill_free_q();
+         netif_rx_complete(dev);
++
++              rx_poll_enabled = 0;
++
++              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++              if (tp->port_id == 0)
++                              data32 |= DEFAULT_Q0_INT_BIT;
++              else
++                              data32 |= DEFAULT_Q1_INT_BIT;
++              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++
++              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++              if (tp->port_id == 0)
++                              data32 |= DEFAULT_Q0_INT_BIT;
++              else
++                              data32 |= DEFAULT_Q1_INT_BIT;
++              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++
++              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++              if (tp->port_id == 0)
++                              data32 |= DEFAULT_Q0_INT_BIT;
++              else
++                              data32 |= DEFAULT_Q1_INT_BIT;
++              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++
+         // enable GMAC-0 rx interrupt
+         // class-Q & TOE-Q are implemented in future
+         //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
diff --git a/target/linux/storm/patches/006-gmac_napi_tx.patch b/target/linux/storm/patches/006-gmac_napi_tx.patch
new file mode 100644 (file)
index 0000000..5861a65
--- /dev/null
@@ -0,0 +1,2094 @@
+--- a/drivers/net/sl351x_gmac.c
++++ b/drivers/net/sl351x_gmac.c
+@@ -43,9 +43,13 @@
+ #include <linux/mtd/kvctl.h>
++#define GET_RPTR(x) ((x) & 0xFFFF)
++#define GET_WPTR(x) ((x) >> 16)
++
+ #define        MIDWAY
+ #define        SL_LEPUS
+-#define VITESSE_G5SWITCH      1
++// #define VITESSE_G5SWITCH   1
++#undef VITESSE_G5SWITCH
+ #ifndef CONFIG_SL351x_RXTOE
+ //#define CONFIG_SL351x_RXTOE 1
+@@ -126,7 +130,6 @@
+  *************************************************************/
+ static int    gmac_initialized = 0;
+ TOE_INFO_T toe_private_data;
+-static int            do_again = 0;
+ static int rx_poll_enabled;
+ spinlock_t gmac_fq_lock;
+ unsigned int FLAG_SWITCH;
+@@ -190,7 +193,7 @@
+ void mac_set_sw_tx_weight(struct net_device *dev, char *weight);
+ void mac_get_hw_tx_weight(struct net_device *dev, char *weight);
+ void mac_set_hw_tx_weight(struct net_device *dev, char *weight);
+-static inline void toe_gmac_fill_free_q(void);
++static inline void toe_gmac_fill_free_q(int count);
+ #ifdef VITESSE_G5SWITCH
+ extern int Get_Set_port_status(void);
+@@ -295,12 +298,14 @@
+       for(j = 0; i<CONFIG_MAC_NUM; j++)
+       {
+               i=j;
++#ifdef VITESSE_G5SWITCH
+               if(Giga_switch){                // if gswitch present, swap eth0/1
+                       if(j==0)
+                               i=1;
+                       else if(j==1)
+                               i=0;
+               }
++#endif
+               tp = (GMAC_INFO_T *)&toe_private_data.gmac[i];
+               tp->dev = NULL;
+@@ -459,7 +464,7 @@
+               toe->gmac[1].dma_base_addr = TOE_GMAC1_DMA_BASE;
+         toe->gmac[0].auto_nego_cfg = 1;
+         toe->gmac[1].auto_nego_cfg = 1;
+-#ifdef CONFIG_SL3516_ASIC
++#ifndef CONFIG_SL3516_ASIC
+         toe->gmac[0].speed_cfg = GMAC_SPEED_1000;
+         toe->gmac[1].speed_cfg = GMAC_SPEED_1000;
+ #else
+@@ -508,7 +513,7 @@
+               // Write GLOBAL_QUEUE_THRESHOLD_REG
+               threshold.bits32 = 0;
+               threshold.bits.swfq_empty = (TOE_SW_FREEQ_DESC_NUM > 256) ? 255 :
+-                                                      TOE_SW_FREEQ_DESC_NUM/2;
++                                                      TOE_SW_FREEQ_DESC_NUM/16;
+               threshold.bits.hwfq_empty = (TOE_HW_FREEQ_DESC_NUM > 256) ? 256/4 :
+                                                       TOE_HW_FREEQ_DESC_NUM/4;
+               threshold.bits.toe_class = (TOE_TOE_DESC_NUM > 256) ? 256/4 :
+@@ -613,18 +618,25 @@
+       rwptr_reg.bits.rptr = 0;
+       toe->fq_rx_rwptr.bits32 = rwptr_reg.bits32;
+       writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++      printk("SWFQ: %08X\n", readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG));
+       // SW Free Queue Descriptors
+       for (i=0; i<TOE_SW_FREEQ_DESC_NUM; i++)
+       {
++              void *data = NULL;
+               sw_desc_ptr->word0.bits.buffer_size = SW_RX_BUF_SIZE;
+-              sw_desc_ptr->word1.bits.sw_id = i;      // used to locate skb
++              sw_desc_ptr->word1.bits.sw_id = 0;      // used to locate skb
+               if ( (skb = dev_alloc_skb(SW_RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
+               {
+                       printk("%s::skb buffer allocation fail !\n",__func__); while(1);
+               }
+-              REG32(skb->data) = (unsigned int)skb;
++
++              data = skb->data;
+               skb_reserve(skb, SKB_RESERVE_BYTES);
++
++              REG32(data + 0) = (unsigned int)skb;
++              REG32(data + 4) = (unsigned short)i;
++
+               // toe->rx_skb[i] = skb;
+               sw_desc_ptr->word2.buf_adr = (unsigned int)__pa(skb->data);
+ //            consistent_sync((unsigned int)desc_ptr, sizeof(GMAC_RXDESC_T), PCI_DMA_TODEVICE);
+@@ -851,14 +863,14 @@
+ *----------------------------------------------------------------------*/
+ static void toe_init_default_queue(void)
+ {
+-      TOE_INFO_T                              *toe;
++      TOE_INFO_T              *toe;
+       volatile NONTOE_QHDR_T  *qhdr;
+-      GMAC_RXDESC_T                   *desc_ptr;
+-      DMA_SKB_SIZE_T                  skb_size;
++      GMAC_RXDESC_T           *desc_ptr;
++      DMA_SKB_SIZE_T          skb_size;
+       toe = (TOE_INFO_T *)&toe_private_data;
+       desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T)),
+-                                                                                      (dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
++                                             (dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
+       if (!desc_ptr)
+       {
+               printk("%s::DMA_MALLOC fail !\n",__func__);
+@@ -866,14 +878,17 @@
+       }
+       memset((void *)desc_ptr, 0, TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T));
+       toe->gmac[0].default_desc_base = (unsigned int)desc_ptr;
++      printk("toe->gmac[0].default_desc_base_dma: %08X\n", toe->gmac[0].default_desc_base_dma);
++
+       toe->gmac[0].default_desc_num = TOE_DEFAULT_Q0_DESC_NUM;
+       qhdr = (volatile NONTOE_QHDR_T *)TOE_DEFAULT_Q0_HDR_BASE;
+       qhdr->word0.base_size = ((unsigned int)toe->gmac[0].default_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_DEFAULT_Q0_DESC_POWER;
+       qhdr->word1.bits32 = 0;
+       toe->gmac[0].rx_rwptr.bits32 = 0;
+       toe->gmac[0].default_qhdr = (NONTOE_QHDR_T *)qhdr;
++
+       desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q1_DESC_NUM * sizeof(GMAC_RXDESC_T)),
+-                                                                                      (dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
++                                             (dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
+       if (!desc_ptr)
+       {
+               printk("%s::DMA_MALLOC fail !\n",__func__);
+@@ -1071,12 +1086,16 @@
+           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) & ~tp->intr0_selected;
+           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
++
+           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG) & ~tp->intr1_selected;
+           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
++
+           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG) & ~tp->intr2_selected;
+           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
++
+           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG) & ~tp->intr3_selected;
+           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
++
+           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG) & ~tp->intr4_selected;
+           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
+       }
+@@ -1176,11 +1195,11 @@
+       GMAC_CONFIG2_T  config2_val;
+       GMAC_CONFIG0_T  config0,config0_mask;
+       GMAC_CONFIG1_T  config1;
+-      #ifdef CONFIG_SL351x_NAT
+       GMAC_CONFIG3_T  config3_val;
+-      #endif
+       GMAC_TX_WCR0_T  hw_weigh;
+       GMAC_TX_WCR1_T  sw_weigh;
++
++      uint32_t weight = 0;
+ //    GMAC_HASH_ENABLE_REG0_T hash_ctrl;
+ //
+ #if 0 /* mac address will be set in late_initcall */
+@@ -1202,24 +1221,23 @@
+       //      config1.bits32 = 0x002004;      //next version
+       /* set flow control threshold */
+       config1.bits32 = 0;
+-      config1.bits.set_threshold = 32 / 2;
+-      config1.bits.rel_threshold = 32 / 4 * 3;
++      config1.bits.set_threshold = (32 / 2);
++      config1.bits.rel_threshold = (32 / 4) * 3;
+       gmac_write_reg(tp->base_addr, GMAC_CONFIG1, config1.bits32, 0xffffffff);
+-      /* set flow control threshold */
++      /* TODO: set flow control threshold */
+       config2_val.bits32 = 0;
+-      config2_val.bits.set_threshold = TOE_SW_FREEQ_DESC_NUM/2;
+-      config2_val.bits.rel_threshold = TOE_SW_FREEQ_DESC_NUM*3/4;
++      config2_val.bits.set_threshold = TOE_SW_FREEQ_DESC_NUM/4;
++      config2_val.bits.rel_threshold = TOE_SW_FREEQ_DESC_NUM/2;
+       gmac_write_reg(tp->base_addr, GMAC_CONFIG2, config2_val.bits32,0xffffffff);
+-      #ifdef CONFIG_SL351x_NAT
+-      /* set HW free queue flow control threshold */
++      /* TODO: set HW free queue flow control threshold */
+       config3_val.bits32 = 0;
+       config3_val.bits.set_threshold = PAUSE_SET_HW_FREEQ;
+       config3_val.bits.rel_threshold = PAUSE_REL_HW_FREEQ;
+       gmac_write_reg(tp->base_addr, GMAC_CONFIG3, config3_val.bits32,0xffffffff);
+-      #endif
+-      /* set_mcast_filter mask*/
++
++      /* TODO: set_mcast_filter mask*/
+       //      gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL0,0x0,0xffffffff);
+       //  gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL1,0x0,0xffffffff);
+@@ -1249,7 +1267,7 @@
+       config0.bits.dis_rx = 1;  /* disable rx */
+       config0.bits.dis_tx = 1;  /* disable tx */
+       config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
+-      config0.bits.rx_err_detect = 1;
++      config0.bits.rx_err_detect = 1; /* TODO: was 1, means disabled, 0 enabled ! */
+       config0.bits.rgmii_en = 0;
+       config0.bits.rgmm_edge = 1;
+       config0.bits.rxc_inv = 0;
+@@ -1342,6 +1360,9 @@
+       gmac_write_reg(tp->dma_base_addr, GMAC_AHB_WEIGHT_REG, ahb_weight.bits32, ahb_weight_mask.bits32);
+       #endif
++      weight = gmac_read_reg(tp->dma_base_addr, GMAC_AHB_WEIGHT_REG);
++      printk("====> %08X\n", weight);
++
+       #if defined(CONFIG_SL351x_NAT) || defined(CONFIG_SL351x_RXTOE)
+       gmac_write_reg(tp->dma_base_addr, GMAC_SPR0, IPPROTO_TCP, 0xffffffff);
+       #endif
+@@ -1552,7 +1573,7 @@
+               rwptr.bits32 = readl(swtxq->rwptr_reg);
+               if (rwptr.bits.rptr == swtxq->finished_idx)
+                       break;
+-      curr_desc = (volatile GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
++              curr_desc = (volatile GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
+ //            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_FROMDEVICE);
+               word0.bits32 = curr_desc->word0.bits32;
+               word1.bits32 = curr_desc->word1.bits32;
+@@ -1573,6 +1594,7 @@
+                               swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
+                               curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
+                               word0.bits32 = curr_desc->word0.bits32;
++
+ #ifdef _DUMP_TX_TCP_CONTENT
+                               if (curr_desc->word0.bits.buffer_size < 16)
+                               {
+@@ -1592,12 +1614,12 @@
+                       word0.bits.status_tx_ok = 0;
+                       if (swtxq->tx_skb[swtxq->finished_idx])
+                       {
+-                              if (interrupt)
+-                                      dev_kfree_skb_irq(swtxq->tx_skb[swtxq->finished_idx]);
+-                              else
+-                                      dev_kfree_skb(swtxq->tx_skb[swtxq->finished_idx]);
++                              dev_kfree_skb(swtxq->tx_skb[swtxq->finished_idx]);
+                               swtxq->tx_skb[swtxq->finished_idx] = NULL;
++                      } else {
++                              BUG();
+                       }
++
+                       curr_desc->word0.bits32 = word0.bits32;
+                       swtxq->curr_finished_desc = (GMAC_TXDESC_T *)curr_desc;
+                       swtxq->total_finished++;
+@@ -1624,31 +1646,29 @@
+ *----------------------------------------------------------------------*/
+ static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+-      GMAC_INFO_T                     *tp= dev->priv;
+-//    static unsigned int     pcount = 0;
+-//    unsigned int                    tx_qid;
+-    DMA_RWPTR_T                               rwptr;
+-      volatile GMAC_TXDESC_T  *curr_desc;
+-      int                                     snd_pages = skb_shinfo(skb)->nr_frags + 1;  /* get number of descriptor */
+-      int                                     frag_id = 0;
+-      int                                     len, total_len = skb->len;
++      GMAC_INFO_T *tp= dev->priv;
++      DMA_RWPTR_T rwptr;
++      GMAC_TXDESC_T *curr_desc;
++      int snd_pages = skb_shinfo(skb)->nr_frags + 1;  /* get number of descriptor */
++      int frag_id = 0;
++      int len, total_len = skb->len;
+       struct net_device_stats *isPtr;
+-      unsigned int                    free_desc;
+-      GMAC_SWTXQ_T                    *swtxq;
++      unsigned int free_desc;
++      GMAC_SWTXQ_T *swtxq;
+       register unsigned long  word0, word1, word2, word3;
+       unsigned short                  wptr, rptr;
+ #ifdef        L2_jumbo_frame
+       int header_len = skb->len;
+       struct iphdr    *ip_hdr;
+-    struct tcphdr     *tcp_hdr;
+-    int             tcp_hdr_len;
+-    unsigned char     *ptr;
+-    int             data_len,a;
+-    unsigned int    val;
++      struct tcphdr   *tcp_hdr;
++      int             tcp_hdr_len;
++      unsigned char   *ptr;
++      int             data_len,a;
++      unsigned int    val;
+ #endif
+ #ifdef GMAC_LEN_1_2_ISSUE
+-      int                                             total_pages;
++      int total_pages;
+       total_pages = snd_pages;
+ #endif
+@@ -1664,13 +1684,6 @@
+     }
+ #endif
+-#if 0
+-      if (storlink_ctl.recvfile==2)
+-      {
+-          printk("snd_pages=%d skb->len=%d\n",snd_pages,skb->len);
+-      }
+-#endif
+-
+ #ifdef GMAC_USE_TXQ0
+       #define tx_qid  0
+ #endif
+@@ -1703,9 +1716,9 @@
+       toe_gmac_tx_complete(tp, tx_qid, dev, 0);
+       if (wptr >= swtxq->finished_idx)
+-              free_desc = swtxq->total_desc_num - wptr - 1 + swtxq->finished_idx;
++              free_desc = swtxq->total_desc_num - wptr + swtxq->finished_idx;
+       else
+-              free_desc = swtxq->finished_idx - wptr - 1;
++              free_desc = swtxq->finished_idx - wptr;
+       if (free_desc < snd_pages)
+       {
+ //            spin_unlock(&tp->tx_mutex);
+@@ -2063,9 +2076,10 @@
+ struct net_device_stats * gmac_get_stats(struct net_device *dev)
+ {
+     GMAC_INFO_T *tp = (GMAC_INFO_T *)dev->priv;
++#if 0 /* don't read stats from hardware, scary numbers. */
+     // unsigned int        flags;
+-    unsigned int        pkt_drop;
+-    unsigned int        pkt_error;
++    unsigned int        pkt_drop = 0;
++    unsigned int        pkt_error = 0;
+     if (netif_running(dev))
+     {
+@@ -2073,10 +2087,14 @@
+         // spin_lock_irqsave(&tp->lock,flags);
+         pkt_drop = gmac_read_reg(tp->base_addr,GMAC_IN_DISCARDS);
+         pkt_error = gmac_read_reg(tp->base_addr,GMAC_IN_ERRORS);
++      printk("**** stack: %lu, hw: %lu\n", tp->ifStatics.rx_dropped, pkt_drop);
++
+         tp->ifStatics.rx_dropped = tp->ifStatics.rx_dropped + pkt_drop;
+         tp->ifStatics.rx_errors = tp->ifStatics.rx_errors + pkt_error;
+         // spin_unlock_irqrestore(&tp->lock,flags);
+     }
++#endif
++
+     return &tp->ifStatics;
+ }
+@@ -2401,36 +2419,63 @@
+ * toe_gmac_fill_free_q
+ * allocate buffers for free queue.
+ *----------------------------------------------------------------------*/
+-static inline void toe_gmac_fill_free_q(void)
++static inline void toe_gmac_fill_free_q(int count)
+ {
+       struct sk_buff  *skb;
+       volatile DMA_RWPTR_T    fq_rwptr;
+       volatile GMAC_RXDESC_T  *fq_desc;
+-      unsigned long   flags;
++      unsigned long flags;
++      unsigned short index;
++      int filled = 0;
++      static int entered;
+       // unsigned short max_cnt=TOE_SW_FREEQ_DESC_NUM>>1;
++      BUG_ON(entered == 1);
++
++      entered = 1;
++
++
+       fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+       // spin_lock_irqsave(&gmac_fq_lock, flags);
+       //while ((max_cnt--) && (unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
+       //                              TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
+-      while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
+-                                      TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
++      index = fq_rwptr.bits.wptr;
++#if 0
++      printk("wptr: %hu, rptr: %hu, refill idx: %hu\n",
++             GET_RPTR(fq_rwptr.bits32),
++             GET_WPTR(fq_rwptr.bits32),
++             index);
++#endif
++
++      index = RWPTR_ADVANCE_ONE(index, TOE_SW_FREEQ_DESC_NUM);
++      fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base + index;
++      while (fq_desc->word2.buf_adr == 0) {
++              void *data = NULL;
++
+               if ((skb = dev_alloc_skb(SW_RX_BUF_SIZE)) == NULL) {
+                       printk("%s::skb allocation fail!\n", __func__);
+-                      //while(1);
+-                      break;
++                      goto out;
+               }
+-              REG32(skb->data) = (unsigned int)skb;
++              ++ filled;
++              data = skb->data;
+               skb_reserve(skb, SKB_RESERVE_BYTES);
+-              // fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
+-                      TOE_SW_FREEQ_DESC_NUM);
+-              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base+fq_rwptr.bits.wptr;
++
++              REG32(data + 0) = (unsigned int)skb;
++              REG32(data + 4) = (unsigned short)index;
++
++              // printk("refill skb: %p, idx: %hu\n", skb, index);
+               fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
+-              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
+-              toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
++      writel(0x07960202, TOE_GMAC0_BASE+GMAC_CONFIG0);
++              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, index);
++      writel(0x07960200, TOE_GMAC0_BASE+GMAC_CONFIG0);
++
++              index = RWPTR_ADVANCE_ONE(index, TOE_SW_FREEQ_DESC_NUM);
++              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base+index;
+       }
++out:
+       // spin_unlock_irqrestore(&gmac_fq_lock, flags);
++
++      entered = 0;
+ }
+ // EXPORT_SYMBOL(toe_gmac_fill_free_q);
+@@ -2442,14 +2487,14 @@
+       unsigned int            status3;
+       unsigned int            status4;
+-      printk("%s\n", message);
+-
+       status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
+       status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
+       status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
+       status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
+       status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++      printk("%s\n", message);
++
+       printk("status: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
+                  status0, status1, status2, status3, status4);
+@@ -2468,8 +2513,9 @@
+       status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
+       status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
+-      printk("select: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
+-                 status0, status1, status2, status3, status4);
++      if (status0 || status1 || status2 || status3 || status4)
++                      printk("select: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
++                                 status0, status1, status2, status3, status4);
+ }
+ /*----------------------------------------------------------------------
+ * toe_gmac_interrupt
+@@ -2485,75 +2531,44 @@
+       unsigned int            status3;
+       unsigned int            status4;
+-//    struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
+       toe = (TOE_INFO_T *)&toe_private_data;
+-//    handle NAPI
+-#ifdef CONFIG_SL_NAPI
+-      /* XXX: check this, changed from 'storlink_ctl.pauseoff == 1' to if (1) */
+-if (1)
+-{
+-/* disable GMAC interrupt */
+-    //toe_gmac_disable_interrupt(tp->irq);
+-//    isPtr->interrupts++;
++      if (0 && rx_poll_enabled) {
++              gmac_registers("interrupt handler");
++      }
++
+       /* read Interrupt status */
+       status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
+       status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
+       status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
+       status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
+       status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
+-      // prompt warning if status bit ON but not enabled
++
+ #if 0
+-      if (status0 & ~tp->intr0_enabled)
+-              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status0, tp->intr0_enabled);
+-      if (status1 & ~tp->intr1_enabled)
+-              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status1, tp->intr1_enabled);
+-      if (status2 & ~tp->intr2_enabled)
+-              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status2, tp->intr2_enabled);
+-      if (status3 & ~tp->intr3_enabled)
+-              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status3, tp->intr3_enabled);
+-      if (status4 & ~tp->intr4_enabled)
+-              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status4, tp->intr4_enabled);
++      /* handle freeq interrupt first */
++      if (status4 & SWFQ_EMPTY_INT_BIT)
++      {
++              toe_gmac_fill_free_q();
++              writel(status4 & SWFQ_EMPTY_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
++              tp->sw_fq_empty_cnt++;
++      }
+ #endif
++      if (status4 & GMAC0_MIB_INT_BIT)
++              writel(GMAC0_MIB_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
++
++      if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
++              writel(GMAC0_RX_OVERRUN_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
++
+       if (status0)
+               writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
+-      if (status1)
+-              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
+       if (status2)
+               writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
+       if (status3)
+               writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
+-      if (status4)
+-              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
+-
+-#if 0
+-      /* handle freeq interrupt first */
+-      if (status4 & tp->intr4_enabled) {
+-              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
+-              {
+-                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
+-                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
+-
+-                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
+-                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
+-                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
+-                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
+-                      printk("\nfreeq int\n");
+-                      toe_gmac_fill_free_q();
+-                      tp->sw_fq_empty_cnt++;
+-              }
+-      }
+-#endif
+       // Interrupt Status 1
+-      if (status1 & tp->intr1_enabled)
++      if ((status1 & 3) || (status4 & 1))
+       {
+               #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
+               #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
+@@ -2563,7 +2578,7 @@
+               // because they should pass packets to upper layer
+               if (tp->port_id == 0)
+               {
+-                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
++                      if (((status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS)) || (status4 & 1))
+                       {
+                               if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
+                                       tp->hwtxq[3].eof_cnt++;
+@@ -2574,50 +2589,51 @@
+                               if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
+                                       tp->hwtxq[0].eof_cnt++;
+                       }
+-                              if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
++                      if (status1 & DEFAULT_Q0_INT_BIT || status4 & 1)
++                      {
++                              if (likely(netif_rx_schedule_prep(dev)))
+                               {
+-                                      if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
+-                              {
+-                                      unsigned int data32;
++                                      unsigned int data32;
++
++                                      BUG_ON(rx_poll_enabled == 1);
+-                                              if (rx_poll_enabled)
+-                                                              gmac_registers("check #1");
++                                      /* Masks GMAC-0 rx interrupt */
++                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                      data32 &= ~(DEFAULT_Q0_INT_BIT);
++                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-                                              BUG_ON(rx_poll_enabled == 1);
++                                      /* Masks GMAC-0 queue empty interrupt */
++                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++                                      data32 &= ~DEFAULT_Q0_INT_BIT;
++                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++                                      __netif_rx_schedule(dev);
++                                      rx_poll_enabled = 1;
++                              } else {
+ #if 0
+-                                      /* Masks GMAC-0 rx interrupt */
+-                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-                                              data32 &= ~(DEFAULT_Q0_INT_BIT);
+-                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-
+-                                      /* Masks GMAC-0 queue empty interrupt */
+-                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
+-                                              data32 &= ~DEFAULT_Q0_INT_BIT;
+-                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
+-
+-                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
+-                                              data32 &= ~DEFAULT_Q0_INT_BIT;
+-                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
+-#endif
+-
+-                                      // class-Q & TOE-Q are implemented in future
+-                                      //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-                                      //data32 &= ~DEFAULT_Q0_INT_BIT;
+-                                              //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-                                              //printk("\%s: DEFAULT_Q0_INT_BIT===================>>>>>>>>>>>>\n",__func__);
+-                                              writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
+-                                              //tp->total_q_cnt_napi=0;
+-                                              //rx_time = jiffies;
+-                                              //rx_old_bytes = isPtr->rx_bytes;
+-                                              __netif_rx_schedule(dev);
+-                                              rx_poll_enabled = 1;
+-                              }
++                                      unsigned int data32;
++
++                                      if (rx_poll_enabled)
++                                              gmac_registers("->poll() running.");
++                                      /* Masks GMAC-0 rx interrupt */
++                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                      data32 &= ~(DEFAULT_Q0_INT_BIT);
++                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++
++                                      /* Masks GMAC-0 queue empty interrupt */
++                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++                                      data32 &= ~DEFAULT_Q0_INT_BIT;
++                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
++#endif
++                              }
++                      } else {
++                              if (0)
++                                      gmac_registers("status1 & DEFAULT_Q0_INT_BIT || status4 & 1");
+                       }
+               }
+-              else if (tp->port_id == 1)
++              else if (tp->port_id == 1 && netif_running(dev))
+               {
+-                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
++                      if ((status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
+                       {
+                               if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
+                                       tp->hwtxq[3].eof_cnt++;
+@@ -2629,14 +2645,14 @@
+                                       tp->hwtxq[0].eof_cnt++;
+                       }
+-                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
++                      if ((status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
+                       {
+                               if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
+-                      {
+-                              unsigned int data32;
++                              {
++                                      unsigned int data32;
+                                       if (rx_poll_enabled)
+-                                                      gmac_registers("check #2");
++                                              gmac_registers("check #2");
+                                       BUG_ON(rx_poll_enabled == 1);
+@@ -2646,7 +2662,7 @@
+                                       data32 &= ~(DEFAULT_Q1_INT_BIT);
+                                       writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-                              /* Masks GMAC-1 queue empty interrupt */
++                                      /* Masks GMAC-1 queue empty interrupt */
+                                       data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
+                                       data32 &= ~DEFAULT_Q1_INT_BIT;
+                                       writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
+@@ -2656,24 +2672,21 @@
+                                       writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
+ #endif
+-                              // disable GMAC-0 rx interrupt
+-                              // class-Q & TOE-Q are implemented in future
+-                              //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-                              //data32 &= ~DEFAULT_Q1_INT_BIT;
++                                      // disable GMAC-0 rx interrupt
++                                      // class-Q & TOE-Q are implemented in future
++                                      //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++                                      //data32 &= ~DEFAULT_Q1_INT_BIT;
+                                       //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+                                       //printk("\%s: 1111111111--->DEFAULT_Q1_INT_BIT===================>>>>>>>>>>>>\n",__func__);
+                                       writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
+                                       //tp->total_q_cnt_napi=0;
+                                       //rx_time = jiffies;
+                                       //rx_old_bytes = isPtr->rx_bytes;
+-                              __netif_rx_schedule(dev);
+-                              rx_poll_enabled = 1;
+-                      }
++                                      __netif_rx_schedule(dev);
++                                      rx_poll_enabled = 1;
++                              }
+                       }
+               }
+-      } else {
+-
+-              gmac_registers("check #3");
+       }
+       // Interrupt Status 0
+@@ -2814,676 +2827,93 @@
+               }
+       }
+-      //toe_gmac_enable_interrupt(tp->irq);
+-#ifdef IxscriptMate_1518
+-      if (storlink_ctl.pauseoff == 1)
+-      {
+-              GMAC_CONFIG0_T config0;
+-              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
+-              config0.bits.dis_rx = 0;
+-              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
+-              config0.bits.dis_rx = 0;
+-              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-      }
+-#endif
+-//     enable_irq(gmac_irq[dev_index]);
+-      //printk("gmac_interrupt complete!\n\n");
+-//    return IRQ_RETVAL(handled);
+       return  IRQ_RETVAL(1);
+ }
+-else
+-{
+-#endif        //endif NAPI
++/*----------------------------------------------------------------------
++* gmac_get_phy_vendor
++*----------------------------------------------------------------------*/
++static unsigned int gmac_get_phy_vendor(int phy_addr)
++{
++    unsigned int      reg_val;
++    reg_val=(mii_read(phy_addr,0x02) << 16) + mii_read(phy_addr,0x03);
++    return reg_val;
++}
+-      /* disable GMAC interrupt */
+-    toe_gmac_disable_interrupt(tp->irq);
++/*----------------------------------------------------------------------
++* gmac_set_phy_status
++*----------------------------------------------------------------------*/
++void gmac_set_phy_status(struct net_device *dev)
++{
++      GMAC_INFO_T *tp = dev->priv;
++      GMAC_STATUS_T   status;
++      unsigned int    reg_val, ability,wan_port_id;
++      unsigned int    i = 0;
+-//    isPtr->interrupts++;
+-      /* read Interrupt status */
+-      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
+-      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
+-      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
+-      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
+-      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
+-      // prompt warning if status bit ON but not enabled
++#ifdef VITESSE_G5SWITCH
++      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1)){
+ #if 0
+-      if (status0 & ~tp->intr0_enabled)
+-              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status0, tp->intr0_enabled);
+-      if (status1 & ~tp->intr1_enabled)
+-              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status1, tp->intr1_enabled);
+-      if (status2 & ~tp->intr2_enabled)
+-              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status2, tp->intr2_enabled);
+-      if (status3 & ~tp->intr3_enabled)
+-              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status3, tp->intr3_enabled);
+-      if (status4 & ~tp->intr4_enabled)
+-              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
+-                              status4, tp->intr4_enabled);
+-#endif
+-#define       INTERRUPT_SELECT                        1
+-      if (status0)
+-              writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
+-      if (status1)
+-              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
+-      if (status2)
+-              writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
+-      if (status3)
+-              writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
+-      if (status4)
+-              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
+-
+-      /* handle freeq interrupt first */
+-      if (status4 & tp->intr4_enabled) {
+-              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
+-              {
+-                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
+-                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
+-
+-                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
+-                      //      SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
+-                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
+-                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
+-                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
+-                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
+-                      printk("\nfreeq int\n");
+-                      toe_gmac_fill_free_q();
+-                      tp->sw_fq_empty_cnt++;
+-
+-                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
+-                              SWFQ_EMPTY_INT_BIT);
+-              }
+-      }
+-
+-      // Interrupt Status 1
+-      if (status1 & tp->intr1_enabled)
+-      {
+-              #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
+-              #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
+-              // Handle GMAC 0/1 HW Tx queue 0-3 EOF events
+-              // Only count
+-              // TOE, Classification, and default queues interrupts are handled by ISR
+-              // because they should pass packets to upper layer
+-              if (tp->port_id == 0)
+-              {
+-#ifndef       INTERRUPT_SELECT
+-                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
+-                      {
+-                              if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
+-                                      tp->hwtxq[3].eof_cnt++;
+-                              if (status1 & GMAC0_HWTQ02_EOF_INT_BIT)
+-                                      tp->hwtxq[2].eof_cnt++;
+-                              if (status1 & GMAC0_HWTQ01_EOF_INT_BIT)
+-                                      tp->hwtxq[1].eof_cnt++;
+-                              if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
+-                                      tp->hwtxq[0].eof_cnt++;
+-#endif        //INTERRUPT_SELECT
+-#ifndef       INTERRUPT_SELECT
+-                      }
+-#endif        //INTERRUPT_SELECT
+-                      if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
+-                      {
+-                              tp->default_q_intr_cnt++;
+-                              toe_gmac_handle_default_rxq(dev, tp);
++              rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
++              rcv_mask |= 0x4F;
++              for(i=0;i<4;i++){
++                      reg_val = BIT(26)|(i<<21)|(10<<16);
++                      SPI_write(3,0,1,reg_val);
++                      msleep(10);
++                      reg_val = SPI_read(3,0,2);
++                      if(reg_val & 0x0c00){
++                              printk("Port%d:Giga mode\n",i);
++                              SPI_write(1,i,0x00,0x300701B1);
++                              SPI_write(1,i,0x00,0x10070181);
++                              switch_pre_link[i]=LINK_UP;
++                              switch_pre_speed[i]=GMAC_SPEED_1000;
+                       }
+-#ifdef CONFIG_SL351x_RXTOE
+-                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
+-                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
+-                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
+-                              toe_gmac_handle_toeq(dev, tp, status1);
+-                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
++                      else{
++                              reg_val = BIT(26)|(i<<21)|(5<<16);
++                              SPI_write(3,0,1,reg_val);
++                              msleep(10);
++                              ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5;
++                              if ((ability & 0x0C)) /* 100M full duplex */
++                              {
++                                      SPI_write(1,i,0x00,0x30050472);
++                                      SPI_write(1,i,0x00,0x10050442);
++                                      printk("Port%d:100M\n",i);
++                                      switch_pre_link[i]=LINK_UP;
++                              switch_pre_speed[i]=GMAC_SPEED_100;
++                              }
++                              else if((ability & 0x03)) /* 10M full duplex */
++                              {
++                                      SPI_write(1,i,0x00,0x30050473);
++                                      SPI_write(1,i,0x00,0x10050443);
++                                      printk("Port%d:10M\n",i);
++                                      switch_pre_link[i]=LINK_UP;
++                                      switch_pre_speed[i]=GMAC_SPEED_10;
++                              }
++                              else{
++                                      SPI_write(1,i,0x00,BIT(16));                    // disable RX
++                                      SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
++                                      while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
++                                              msleep(1);
++
++                                      SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
++                                      switch_pre_link[i]=LINK_DOWN;
++                                      switch_pre_speed[i]=GMAC_SPEED_10;
++                                      rcv_mask &= ~BIT(i);
++                                      SPI_write(2,0,0x10,rcv_mask);                   // Disable Receive
++                              }
+                       }
+-#endif
+               }
+-              else if (tp->port_id == 1)
+-              {
+-#ifndef       INTERRUPT_SELECT
+-                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
+-                      {
+-                              if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
+-                                      tp->hwtxq[3].eof_cnt++;
+-                              if (status1 & GMAC1_HWTQ12_EOF_INT_BIT)
+-                                      tp->hwtxq[2].eof_cnt++;
+-                              if (status1 & GMAC1_HWTQ11_EOF_INT_BIT)
+-                                      tp->hwtxq[1].eof_cnt++;
+-                              if (status1 & GMAC1_HWTQ10_EOF_INT_BIT)
+-                                      tp->hwtxq[0].eof_cnt++;
+-#endif        //INTERRUPT_SELECT
+-#ifndef       INTERRUPT_SELECT
+-                      }
+-#endif        //INTERRUPT_SELECT
+-                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
+-                      {
+-                              tp->default_q_intr_cnt++;
+-                              toe_gmac_handle_default_rxq(dev, tp);
+-                      }
+-#ifdef CONFIG_SL351x_RXTOE
+-                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
+-                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
+-                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
+-                              toe_gmac_handle_toeq(dev, tp, status1);
+-                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
+-                      }
+ #endif
+-              }
++              gmac_get_switch_status(dev);
++              gmac_write_reg(tp->base_addr, GMAC_STATUS, 0x7d, 0x0000007f);
++//            SPI_write(2,0,0x10,rcv_mask);                   // Enable Receive
++              return ;
+       }
++#endif
++      reg_val = gmac_get_phy_vendor(tp->phy_addr);
++      printk("GMAC-%d Addr %d Vendor ID: 0x%08x\n", tp->port_id, tp->phy_addr, reg_val);
+-      // Interrupt Status 0
+-      if (status0 & tp->intr0_enabled)
+-      {
+-
+-              #define ERR_INTR_BITS   (GMAC0_TXDERR_INT_BIT | GMAC0_TXPERR_INT_BIT |  \
+-                                                               GMAC1_TXDERR_INT_BIT | GMAC1_TXPERR_INT_BIT |  \
+-                                                               GMAC0_RXDERR_INT_BIT | GMAC0_RXPERR_INT_BIT |  \
+-                                                               GMAC1_RXDERR_INT_BIT | GMAC1_RXPERR_INT_BIT)
+-#ifndef       INTERRUPT_SELECT
+-              if (status0 &  ERR_INTR_BITS)
+-              {
+-                      if ((status0 & GMAC0_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXDERR_INT_BIT))
+-                      {
+-                              tp->txDerr_cnt[0]++;
+-                              printk("GMAC0 TX AHB Bus Error!\n");
+-                      }
+-                      if ((status0 & GMAC0_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXPERR_INT_BIT))
+-                      {
+-                              tp->txPerr_cnt[0]++;
+-                              printk("GMAC0 Tx Descriptor Protocol Error!\n");
+-                      }
+-                      if ((status0 & GMAC1_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXDERR_INT_BIT))
+-                      {
+-                              tp->txDerr_cnt[1]++;
+-                              printk("GMAC1 Tx AHB Bus Error!\n");
+-                      }
+-                      if ((status0 & GMAC1_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXPERR_INT_BIT))
+-                      {
+-                              tp->txPerr_cnt[1]++;
+-                              printk("GMAC1 Tx Descriptor Protocol Error!\n");
+-                      }
+-
+-                      if ((status0 & GMAC0_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXDERR_INT_BIT))
+-                      {
+-                              tp->RxDerr_cnt[0]++;
+-                              printk("GMAC0 Rx AHB Bus Error!\n");
+-                      }
+-                      if ((status0 & GMAC0_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXPERR_INT_BIT))
+-                      {
+-                              tp->RxPerr_cnt[0]++;
+-                              printk("GMAC0 Rx Descriptor Protocol Error!\n");
+-                      }
+-                      if ((status0 & GMAC1_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXDERR_INT_BIT))
+-                      {
+-                              tp->RxDerr_cnt[1]++;
+-                              printk("GMAC1 Rx AHB Bus Error!\n");
+-                      }
+-                      if ((status0 & GMAC1_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXPERR_INT_BIT))
+-                      {
+-                              tp->RxPerr_cnt[1]++;
+-                              printk("GMAC1 Rx Descriptor Protocol Error!\n");
+-                      }
+-              }
+-#endif        //INTERRUPT_SELECT
+-#ifndef       GMAX_TX_INTR_DISABLED
+-              if (tp->port_id == 1 && netif_running(dev) &&
+-                      (((status0 & GMAC1_SWTQ10_FIN_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_FIN_INT_BIT))
+-                      ||
+-                      ((status0 & GMAC1_SWTQ10_EOF_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_EOF_INT_BIT))))
+-              {
+-                      toe_gmac_tx_complete(&toe_private_data.gmac[1], 0, dev, 1);
+-              }
+-
+-              if (tp->port_id == 0 && netif_running(dev) &&
+-                      (((status0 & GMAC0_SWTQ00_FIN_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_FIN_INT_BIT))
+-                      ||
+-                      ((status0 & GMAC0_SWTQ00_EOF_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_EOF_INT_BIT))))
+-              {
+-                      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
+-              }
+-#endif
+-              // clear enabled status bits
+-      }
+-      // Interrupt Status 4
+-#ifndef       INTERRUPT_SELECT
+-      if (status4 & tp->intr4_enabled)
+-      {
+-              #define G1_INTR4_BITS           (0xff000000)
+-              #define G0_INTR4_BITS           (0x00ff0000)
+-
+-              if (tp->port_id == 0)
+-              {
+-                      if ((status4 & G0_INTR4_BITS) && (tp->intr4_enabled & G0_INTR4_BITS))
+-                      {
+-                              if (status4 & GMAC0_RESERVED_INT_BIT)
+-                                      printk("GMAC0_RESERVED_INT_BIT is ON\n");
+-                              if (status4 & GMAC0_MIB_INT_BIT)
+-                                      tp->mib_full_cnt++;
+-                              if (status4 & GMAC0_RX_PAUSE_ON_INT_BIT)
+-                                      tp->rx_pause_on_cnt++;
+-                              if (status4 & GMAC0_TX_PAUSE_ON_INT_BIT)
+-                                      tp->tx_pause_on_cnt++;
+-                              if (status4 & GMAC0_RX_PAUSE_OFF_INT_BIT)
+-                                      tp->rx_pause_off_cnt++;
+-                              if (status4 & GMAC0_TX_PAUSE_OFF_INT_BIT)
+-                                      tp->rx_pause_off_cnt++;
+-                              if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
+-                                      tp->rx_overrun_cnt++;
+-                              if (status4 & GMAC0_STATUS_CHANGE_INT_BIT)
+-                                      tp->status_changed_cnt++;
+-                      }
+-              }
+-              else if (tp->port_id == 1)
+-              {
+-                      if ((status4 & G1_INTR4_BITS) && (tp->intr4_enabled & G1_INTR4_BITS))
+-                      {
+-                              if (status4 & GMAC1_RESERVED_INT_BIT)
+-                                      printk("GMAC1_RESERVED_INT_BIT is ON\n");
+-                              if (status4 & GMAC1_MIB_INT_BIT)
+-                                      tp->mib_full_cnt++;
+-                              if (status4 & GMAC1_RX_PAUSE_ON_INT_BIT)
+-                              {
+-                                      //printk("Gmac pause on\n");
+-                                      tp->rx_pause_on_cnt++;
+-                              }
+-                              if (status4 & GMAC1_TX_PAUSE_ON_INT_BIT)
+-                              {
+-                                      //printk("Gmac pause on\n");
+-                                      tp->tx_pause_on_cnt++;
+-                              }
+-                              if (status4 & GMAC1_RX_PAUSE_OFF_INT_BIT)
+-                              {
+-                                      //printk("Gmac pause off\n");
+-                                      tp->rx_pause_off_cnt++;
+-                              }
+-                              if (status4 & GMAC1_TX_PAUSE_OFF_INT_BIT)
+-                              {
+-                                      //printk("Gmac pause off\n");
+-                                      tp->rx_pause_off_cnt++;
+-                              }
+-                              if (status4 & GMAC1_RX_OVERRUN_INT_BIT)
+-                              {
+-                                      //printk("Gmac Rx Overrun \n");
+-                                      tp->rx_overrun_cnt++;
+-                              }
+-                              if (status4 & GMAC1_STATUS_CHANGE_INT_BIT)
+-                                      tp->status_changed_cnt++;
+-                      }
+-              }
+-#if 0
+-              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
+-              {
+-                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-//                    mac_stop_rxdma(tp->sc);
+-                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
+-                              tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
+-
+-                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
+-                              SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
+-                      toe_gmac_fill_free_q();
+-                      tp->sw_fq_empty_cnt++;
+-
+-                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
+-                              SWFQ_EMPTY_INT_BIT);
+-//#if 0
+-/*                    if (netif_running(dev))
+-                              toe_gmac_handle_default_rxq(dev, tp);
+-                      printk("SWFQ_EMPTY_INT_BIT is ON!\n");  // should not be happened */
+-//#endif
+-              }
+-#endif
+-      }
+-#endif        //INTERRUPT_SELECT
+-      toe_gmac_enable_interrupt(tp->irq);
+-//enable gmac rx function when do RFC 2544
+-#ifdef IxscriptMate_1518
+-      if (storlink_ctl.pauseoff == 1)
+-      {
+-              GMAC_CONFIG0_T config0;
+-              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
+-              config0.bits.dis_rx = 0;
+-              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
+-              config0.bits.dis_rx = 0;
+-              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-      }
+-#endif
+-      //printk("gmac_interrupt complete!\n\n");
+-//    return IRQ_RETVAL(handled);
+-      return  IRQ_RETVAL(1);
+-#ifdef CONFIG_SL_NAPI
+-}
+-#endif
+-}
+-
+-/*----------------------------------------------------------------------
+-*     toe_gmac_handle_default_rxq
+-*     (1) Get rx Buffer for default Rx queue
+-*     (2) notify or call upper-routine to handle it
+-*     (3) get a new buffer and insert it into SW free queue
+-*     (4) Note: The SW free queue Read-Write Pointer should be locked when accessing
+-*----------------------------------------------------------------------*/
+-//static inline void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
+-static void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
+-{
+-      TOE_INFO_T                      *toe;
+-    GMAC_RXDESC_T     *curr_desc;
+-      struct sk_buff          *skb;
+-    DMA_RWPTR_T                       rwptr;
+-      unsigned int            pkt_size;
+-      int                                     max_cnt;
+-      unsigned int        desc_count;
+-      unsigned int        good_frame, chksum_status, rx_status;
+-      struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
+-
+-//when do ixia RFC 2544 test and packet size is select 1518 bytes,disable gmace rx function immediately after one interrupt come in.
+-#ifdef IxscriptMate_1518
+-      if (storlink_ctl.pauseoff == 1)
+-      {
+-              GMAC_CONFIG0_T config0;
+-              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
+-              config0.bits.dis_rx = 1;
+-              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
+-              config0.bits.dis_rx = 1;
+-              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-      }
+-#endif
+-      rwptr.bits32 = readl(&tp->default_qhdr->word1);
+-#if 0
+-      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
+-      {
+-              mac_stop_txdma((struct net_device *)tp->dev);
+-              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
+-                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
+-              while(1);
+-      }
+-#endif
+-      toe = (TOE_INFO_T *)&toe_private_data;
+-      max_cnt = DEFAULT_RXQ_MAX_CNT;
+-      while ((--max_cnt) && rwptr.bits.rptr != rwptr.bits.wptr)
+-//    while (rwptr.bits.rptr != rwptr.bits.wptr)
+-      {
+-//if packet size is not 1518 for RFC 2544,enable gmac rx function.The other packet size have RX workaround.
+-#ifdef IxscriptMate_1518
+-      if (storlink_ctl.pauseoff == 1)
+-              {
+-                      if (pkt_size != 1514)
+-                      {
+-                                              GMAC_CONFIG0_T config0;
+-                                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
+-                                              config0.bits.dis_rx = 0;
+-                                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-                                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
+-                                              config0.bits.dis_rx = 0;
+-                                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-                      }
+-              }
+-#endif
+-      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
+-//            consistent_sync(curr_desc, sizeof(GMAC_RXDESC_T), PCI_DMA_FROMDEVICE);
+-              tp->default_q_cnt++;
+-      tp->rx_curr_desc = (unsigned int)curr_desc;
+-      rx_status = curr_desc->word0.bits.status;
+-      chksum_status = curr_desc->word0.bits.chksum_status;
+-      tp->rx_status_cnt[rx_status]++;
+-      tp->rx_chksum_cnt[chksum_status]++;
+-        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
+-              desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
+-              good_frame=1;
+-              if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
+-                      || (pkt_size < 60)
+-                  || (chksum_status & 0x4)
+-                      || rx_status)
+-              {
+-                      good_frame = 0;
+-                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
+-                              printk("%s::derr (GMAC-%d)!!!\n", __func__, tp->port_id);
+-                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_perr)
+-                              printk("%s::perr (GMAC-%d)!!!\n", __func__, tp->port_id);
+-                      if (rx_status)
+-                      {
+-                              if (rx_status == 4 || rx_status == 7)
+-                                      isPtr->rx_crc_errors++;
+-//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
+-                      }
+-#ifdef SL351x_GMAC_WORKAROUND
+-                      else if (pkt_size < 60)
+-                      {
+-                              if (tp->short_frames_cnt < GMAC_SHORT_FRAME_THRESHOLD)
+-                                      tp->short_frames_cnt++;
+-                              if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
+-                              {
+-                                      GMAC_CONFIG0_T config0;
+-                                      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
+-                                      config0.bits.dis_rx = 1;
+-                                      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-                                      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
+-                                      config0.bits.dis_rx = 1;
+-                                      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-                              }
+-                      }
+-#endif
+-//                    if (chksum_status)
+-//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
+-                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
+-                      dev_kfree_skb_irq(skb);
+-              }
+-              if (good_frame)
+-              {
+-                      if (curr_desc->word0.bits.drop)
+-                              printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
+-//                    if (chksum_status)
+-//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
+-
+-              /* get frame information from the first descriptor of the frame */
+-#ifdef SL351x_GMAC_WORKAROUND
+-                      if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
+-                      {
+-                              GMAC_CONFIG0_T config0;
+-                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
+-                              config0.bits.dis_rx = 0;
+-                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
+-                              config0.bits.dis_rx = 0;
+-                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-                      }
+-                      tp->short_frames_cnt = 0;
+-#endif
+-                      isPtr->rx_packets++;
+-                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr - SKB_RESERVE_BYTES)));
+-                      if (!skb)
+-                      {
+-                              printk("Fatal Error!!skb==NULL\n");
+-                              goto next_rx;
+-                      }
+-                      tp->curr_rx_skb = skb;
+-                      // consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
+-
+-      //              curr_desc->word2.buf_adr = 0;
+-
+-                      skb_reserve (skb, RX_INSERT_BYTES);     /* 16 byte align the IP fields. */
+-                      skb_put(skb, pkt_size);
+-                      skb->dev = dev;
+-                      if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
+-                      {
+-                              skb->ip_summed = CHECKSUM_UNNECESSARY;
+-#ifdef CONFIG_SL351x_NAT
+-                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
+-                              {
+-                                      struct iphdr    *ip_hdr;
+-                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
+-                                      sl351x_nat_input(skb,
+-                                                                      tp->port_id,
+-                                                                      (void *)curr_desc->word3.bits.l3_offset,
+-                                                                      (void *)curr_desc->word3.bits.l4_offset);
+-                              }
+-#endif
+-                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
+-#if 0
+-#ifdef CONFIG_SL351x_RXTOE
+-                              if (storlink_ctl.rx_max_pktsize) {
+-                                      struct iphdr    *ip_hdr;
+-                                      struct tcphdr   *tcp_hdr;
+-                                      int ip_hdrlen;
+-
+-                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
+-                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
+-                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
+-                                              ip_hdrlen = ip_hdr->ihl << 2;
+-                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
+-                                              if (tcp_hdr->syn) {
+-                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
+-                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
+-                                                      TCP_SKB_CB(skb)->connection = connection;
+-                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
+-                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
+-                                                      //                      __func__, skb->data, connection, connection->mode);
+-                                              }
+-                                      }
+-                              }
+-#endif
+-#endif
+-                      }
+-                      else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
+-                      {
+-                              skb->ip_summed = CHECKSUM_UNNECESSARY;
+-#ifdef CONFIG_SL351x_NAT
+-                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
+-                              {
+-                                      struct iphdr            *ip_hdr;
+-                                      //struct tcphdr         *tcp_hdr;
+-                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
+-                                      //tcp_hdr = (struct tcphdr *)&(skb->data[curr_desc->word3.bits.l4_offset]);
+-                                      if (ip_hdr->protocol == IPPROTO_UDP)
+-                                      {
+-                                              sl351x_nat_input(skb,
+-                                                                              tp->port_id,
+-                                                                              (void *)curr_desc->word3.bits.l3_offset,
+-                                                                              (void *)curr_desc->word3.bits.l4_offset);
+-                                      }
+-                                      else if (ip_hdr->protocol == IPPROTO_GRE)
+-                                      {
+-                                              sl351x_nat_input(skb,
+-                                                                      tp->port_id,
+-                                                                      (void *)curr_desc->word3.bits.l3_offset,
+-                                                                      (void *)curr_desc->word3.bits.l4_offset);
+-                                      }
+-                              }
+-#endif
+-                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
+-                      }
+-                      else
+-                      {
+-                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
+-                      }
+-
+-                      netif_rx(skb);  /* socket rx */
+-                      dev->last_rx = jiffies;
+-
+-                      isPtr->rx_bytes += pkt_size;
+-
+-        }
+-
+-next_rx:
+-              // advance one for Rx default Q 0/1
+-              rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
+-              SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
+-      tp->rx_rwptr.bits32 = rwptr.bits32;
+-
+-      }
+-
+-      /* Handles first available packets only then refill the queue. */
+-      toe_gmac_fill_free_q();
+-}
+-
+-/*----------------------------------------------------------------------
+-* gmac_get_phy_vendor
+-*----------------------------------------------------------------------*/
+-static unsigned int gmac_get_phy_vendor(int phy_addr)
+-{
+-    unsigned int      reg_val;
+-    reg_val=(mii_read(phy_addr,0x02) << 16) + mii_read(phy_addr,0x03);
+-    return reg_val;
+-}
+-
+-/*----------------------------------------------------------------------
+-* gmac_set_phy_status
+-*----------------------------------------------------------------------*/
+-void gmac_set_phy_status(struct net_device *dev)
+-{
+-      GMAC_INFO_T *tp = dev->priv;
+-      GMAC_STATUS_T   status;
+-      unsigned int    reg_val, ability,wan_port_id;
+-      unsigned int    i = 0;
+-
+-#ifdef VITESSE_G5SWITCH
+-      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1)){
+-#if 0
+-              rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
+-              rcv_mask |= 0x4F;
+-              for(i=0;i<4;i++){
+-                      reg_val = BIT(26)|(i<<21)|(10<<16);
+-                      SPI_write(3,0,1,reg_val);
+-                      msleep(10);
+-                      reg_val = SPI_read(3,0,2);
+-                      if(reg_val & 0x0c00){
+-                              printk("Port%d:Giga mode\n",i);
+-                              SPI_write(1,i,0x00,0x300701B1);
+-                              SPI_write(1,i,0x00,0x10070181);
+-                              switch_pre_link[i]=LINK_UP;
+-                              switch_pre_speed[i]=GMAC_SPEED_1000;
+-                      }
+-                      else{
+-                              reg_val = BIT(26)|(i<<21)|(5<<16);
+-                              SPI_write(3,0,1,reg_val);
+-                              msleep(10);
+-                              ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5;
+-                              if ((ability & 0x0C)) /* 100M full duplex */
+-                              {
+-                                      SPI_write(1,i,0x00,0x30050472);
+-                                      SPI_write(1,i,0x00,0x10050442);
+-                                      printk("Port%d:100M\n",i);
+-                                      switch_pre_link[i]=LINK_UP;
+-                              switch_pre_speed[i]=GMAC_SPEED_100;
+-                              }
+-                              else if((ability & 0x03)) /* 10M full duplex */
+-                              {
+-                                      SPI_write(1,i,0x00,0x30050473);
+-                                      SPI_write(1,i,0x00,0x10050443);
+-                                      printk("Port%d:10M\n",i);
+-                                      switch_pre_link[i]=LINK_UP;
+-                                      switch_pre_speed[i]=GMAC_SPEED_10;
+-                              }
+-                              else{
+-                                      SPI_write(1,i,0x00,BIT(16));                    // disable RX
+-                                      SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
+-                                      while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
+-                                              msleep(1);
+-
+-                                      SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
+-                                      switch_pre_link[i]=LINK_DOWN;
+-                                      switch_pre_speed[i]=GMAC_SPEED_10;
+-                                      rcv_mask &= ~BIT(i);
+-                                      SPI_write(2,0,0x10,rcv_mask);                   // Disable Receive
+-                              }
+-                      }
+-              }
+-#endif
+-              gmac_get_switch_status(dev);
+-              gmac_write_reg(tp->base_addr, GMAC_STATUS, 0x7d, 0x0000007f);
+-//            SPI_write(2,0,0x10,rcv_mask);                   // Enable Receive
+-              return ;
+-      }
+-#endif
+-
+-      reg_val = gmac_get_phy_vendor(tp->phy_addr);
+-      printk("GMAC-%d Addr %d Vendor ID: 0x%08x\n", tp->port_id, tp->phy_addr, reg_val);
+-
+-      switch (tp->phy_mode)
++      switch (tp->phy_mode)
+       {
+               case GMAC_PHY_GMII:
+               mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
+@@ -3552,6 +2982,7 @@
+               status.bits.link = LINK_DOWN;
+               //              clear_bit(__LINK_STATE_START, &dev->state);
+               printk("Link Down (0x%04x) ", reg_val);
++#ifdef VITESSE_G5SWITCH
+               if(Giga_switch == 1)
+               {
+                               wan_port_id = 1;
+@@ -3565,6 +2996,7 @@
+                               storlink_ctl.link[ tp->port_id] = 0;
+ #endif
+               }
++#endif
+       }
+       else
+       {
+@@ -3572,6 +3004,7 @@
+               status.bits.link = LINK_UP;
+               //              set_bit(__LINK_STATE_START, &dev->state);
+               printk("Link Up (0x%04x) ",reg_val);
++#ifdef VITESSE_G5SWITCH
+               if(Giga_switch == 1)
+               {
+                               wan_port_id = 1;
+@@ -3585,6 +3018,7 @@
+                               storlink_ctl.link[ tp->port_id] = 1;
+ #endif
+               }
++#endif
+       }
+       //    value = mii_read(PHY_ADDR,0x05);
+@@ -3863,6 +3297,7 @@
+                       }
+               }
+               status.bits.link = LINK_UP; /* link up */
++#ifdef VITESSE_G5SWITCH
+               if(Giga_switch==1)
+               {
+                               wan_port_id = 1;
+@@ -3874,6 +3309,7 @@
+                               storlink_ctl.link[ tp->port_id] = 1;
+ #endif
+               }
++#endif
+               if ((ability & 0x20)==0x20)
+               {
+                       if (tp->flow_control_enable == 0)
+@@ -3914,6 +3350,7 @@
+       else
+       {
+               status.bits.link = LINK_DOWN; /* link down */
++#ifdef VITESSE_G5SWITCH
+               if(Giga_switch == 1)
+               {
+                               wan_port_id = 1;
+@@ -3925,6 +3362,7 @@
+                               storlink_ctl.link[ tp->port_id] = 0;
+ #endif
+               }
++#endif
+               if (tp->pre_phy_status == LINK_UP)
+               {
+                       printk("GMAC-%d LINK_Down......\n",tp->port_id);
+@@ -4298,86 +3736,102 @@
+ }
+ #ifdef CONFIG_SL_NAPI
++
++static int gmax_rx(struct net_device *dev, int *budget)
++{
++      return 0;
++}
++
++static int gmac_tx(struct net_device *dev, int *budget)
++{
++      return 0;
++}
++
+ /*----------------------------------------------------------------------
+ * gmac_rx_poll
+ *----------------------------------------------------------------------*/
+ static int gmac_rx_poll(struct net_device *dev, int *budget)
+ {
+-      TOE_INFO_T                      *toe;
+-    GMAC_RXDESC_T     *curr_desc;
+-      struct sk_buff          *skb;
+-    DMA_RWPTR_T                       rwptr;
+-    unsigned int data32;
+-      unsigned int            pkt_size;
+-      unsigned int        desc_count;
+-      unsigned int        good_frame, chksum_status, rx_status;
+-      int                 rx_pkts_num = 0;
+-      int                 quota = min(dev->quota, *budget);
+-      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
+-      unsigned int            status4;
+-      volatile DMA_RWPTR_T    fq_rwptr;
+-      // int                                  max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
+-      //unsigned long         rx_old_bytes;
++      TOE_INFO_T      *toe;
++      GMAC_RXDESC_T   *curr_desc;
++      struct sk_buff  *skb;
++      DMA_RWPTR_T     rwptr;
++      unsigned int    data32;
++      unsigned int    pkt_size;
++      unsigned int    desc_count;
++      unsigned int    good_frame, chksum_status, rx_status;
++      int             rx_pkts_num = 0;
++      int             quota = min(dev->quota, *budget);
++      GMAC_INFO_T     *tp = (GMAC_INFO_T *)dev->priv;
++      unsigned int    status1;
++      unsigned int    status4;
+       struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
+-      //unsigned long long    rx_time;
+-
+       BUG_ON(rx_poll_enabled == 0);
+-#if 1
+-      if (do_again)
+-      {
+-                      toe_gmac_fill_free_q();
+-                      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
+-                      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-                      //printk("\n%s:: do_again toe_gmac_fill_free_q =======>status4=0x%x =====fq_rwptr =0x%8x======>JKJKJKJKJKJKJKJKJ \n", __func__,status4,fq_rwptr.bits32);
+-                      if (fq_rwptr.bits.wptr != fq_rwptr.bits.rptr)
+-                      {
+-                                              //status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
+-                                              do_again =0;
+-                                              //netif_rx_complete(dev);
+-                                              gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4, 0x1);
+-                                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-                                              rwptr.bits32 = readl(&tp->default_qhdr->word1);
+-                      }
+-                      else
+-                              return 1;
+-      }
+-#endif
+-      rwptr.bits32 = readl(&tp->default_qhdr->word1);
+-#if 0
+-      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
+-      {
+-              mac_stop_txdma((struct net_device *)tp->dev);
+-              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
+-                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
+-              while(1);
+-      }
+-#endif
++
+       toe = (TOE_INFO_T *)&toe_private_data;
+-      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-      //printk("%s:---Before-------------->Default Queue HW RW ptr (0x%8x),   fq_rwptr =0x%8x \n",__func__,rwptr.bits32,fq_rwptr.bits32 );
+-      //printk("%s:---Before while   rx_pkts_num=%d------rx_finished_idx=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rx_finished_idx,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
+-//    while ((--max_cnt) && (rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
++rx_poll_retry:
++      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++      if (status1 & 1) {
++              writel(1, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++      }
++      rwptr.bits32 = readl(&tp->default_qhdr->word1);
+       while ((rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
+       {
+-
+-      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
++              curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
+               tp->default_q_cnt++;
+-      tp->rx_curr_desc = (unsigned int)curr_desc;
+-      rx_status = curr_desc->word0.bits.status;
+-      chksum_status = curr_desc->word0.bits.chksum_status;
+-      tp->rx_status_cnt[rx_status]++;
+-      tp->rx_chksum_cnt[chksum_status]++;
+-        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
++              tp->rx_curr_desc = (unsigned int)curr_desc;
++              rx_status = curr_desc->word0.bits.status;
++              chksum_status = curr_desc->word0.bits.chksum_status;
++              tp->rx_status_cnt[rx_status]++;
++              tp->rx_chksum_cnt[chksum_status]++;
++              pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
+               desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
+               good_frame=1;
++
++              if (0) {
++
++                              int free, busy;
++                              uint32_t rwptr1;
++                              uint32_t rwptr2;
++
++                              rwptr1 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                              free = (GET_WPTR(rwptr1) - GET_RPTR(rwptr1)) & 0xFF;
++
++                              rwptr2 = readl(&tp->default_qhdr->word1);
++                              busy = (GET_RPTR(rwptr2) - GET_WPTR(rwptr2)) & 0xFF;
++
++                              if (GET_WPTR(rwptr1) == GET_RPTR(rwptr1)) {
++                                      printk("frame  status: %d\n"
++                                             "SWFQ: wptr: %hu, rptr: %hu, free: %d\n"
++                                             "GMAC: wptr: %hu, rptr: %hu, free: %d\n",
++                                             rx_status,
++                                             GET_WPTR(rwptr1), GET_RPTR(rwptr1), free,
++                                             GET_WPTR(rwptr2), GET_RPTR(rwptr2), busy);
++                              }
++              }
++
++              {
++                      GMAC_RXDESC_T   *fq_desc;
++                      void *data;
++                      struct sk_buff *skb;
++                      unsigned short idx;
++
++                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
++                      idx = (unsigned short)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES + 4));
++
++                      BUG_ON(idx > TOE_SW_FREEQ_DESC_NUM);
++                      BUG_ON(skb == NULL);
++                      fq_desc = (GMAC_RXDESC_T*)toe->swfq_desc_base + idx;
++                      fq_desc->word2.buf_adr = 0;
++              }
++
+               if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
+-                      || (pkt_size < 60)
++                  || (pkt_size < 60)
+                   || (chksum_status & 0x4)
+                   || rx_status )
+-//                    || rx_status || (rwptr.bits.rptr > rwptr.bits.wptr ))
+               {
+                       good_frame = 0;
+                       if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
+@@ -4388,7 +3842,6 @@
+                       {
+                               if (rx_status == 4 || rx_status == 7)
+                                       isPtr->rx_crc_errors++;
+-//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
+                       }
+ #ifdef SL351x_GMAC_WORKAROUND
+                       else if (pkt_size < 60)
+@@ -4407,17 +3860,32 @@
+                               }
+                       }
+ #endif
+-//                    if (chksum_status)
+-//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
+                       skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
+-                      dev_kfree_skb_irq(skb);
++                      dev_kfree_skb(skb);
++
++                      if (0) {
++                              int free, busy;
++                              uint32_t rwptr1;
++                              uint32_t rwptr2;
++
++                              rwptr1 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
++                              free = (GET_WPTR(rwptr1) - GET_RPTR(rwptr1)) & 0xFF;
++
++                              rwptr2 = readl(&tp->default_qhdr->word1);
++                              busy = (GET_RPTR(rwptr2) - GET_WPTR(rwptr2)) & 0xFF;
++
++                              printk("frame  status: %d\n"
++                                     "SWFQ: wptr: %hu, rptr: %hu, free: %d\n"
++                                     "GMAC: wptr: %hu, rptr: %hu, free: %d\n",
++                                     rx_status,
++                                     GET_WPTR(rwptr1), GET_RPTR(rwptr1), free,
++                                     GET_WPTR(rwptr2), GET_RPTR(rwptr2), busy);
++                      }
+               }
+               if (good_frame)
+               {
+                       if (curr_desc->word0.bits.drop)
+                               printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
+-//                    if (chksum_status)
+-//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
+ #ifdef SL351x_GMAC_WORKAROUND
+                       if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
+@@ -4432,225 +3900,118 @@
+                       }
+                       tp->short_frames_cnt = 0;
+ #endif
+-              /* get frame information from the first descriptor of the frame */
++                      /* get frame information from the first descriptor of the frame */
+                       isPtr->rx_packets++;
+-                      //consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
++                      consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
+                       skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
+                       tp->curr_rx_skb = skb;
+-      //              curr_desc->word2.buf_adr = 0;
+-                  //skb_reserve (skb, SKB_RESERVE_BYTES);
+                       skb_reserve (skb, RX_INSERT_BYTES);     /* 2 byte align the IP fields. */
+-                      //if ((skb->tail+pkt_size) > skb->end )
+-                      //printk("%s::------------->Here skb->len=%d,pkt_size= %d,skb->head=0x%x,skb->tail= 0x%x, skb->end= 0x%x\n", __func__, skb->len, pkt_size,skb->head,skb->tail,skb->end);
+                       skb_put(skb, pkt_size);
+-
+                       skb->dev = dev;
+                       if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
+                       {
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
+-#ifdef CONFIG_SL351x_NAT
+-                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
+-                              {
+-                                      struct iphdr    *ip_hdr;
+-                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
+-                                      sl351x_nat_input(skb,
+-                                                                      tp->port_id,
+-                                                                      (void *)curr_desc->word3.bits.l3_offset,
+-                                                                      (void *)curr_desc->word3.bits.l4_offset);
+-                              }
+-#endif
+                               skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
+-#if 0
+-#ifdef CONFIG_SL351x_RXTOE
+-                              if (storlink_ctl.rx_max_pktsize) {
+-                                      struct iphdr    *ip_hdr;
+-                                      struct tcphdr   *tcp_hdr;
+-                                      int ip_hdrlen;
+-
+-                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
+-                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
+-                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
+-                                              ip_hdrlen = ip_hdr->ihl << 2;
+-                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
+-                                              if (tcp_hdr->syn) {
+-                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
+-                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
+-                                                      TCP_SKB_CB(skb)->connection = connection;
+-                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
+-                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
+-                                                      //                      __func__, skb->data, connection, connection->mode);
+-                                              }
+-                                      }
+-                              }
+-#endif
+-#endif
+                       }
+                       else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
+                       {
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
+-#ifdef CONFIG_SL351x_NAT
+-                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
+-                              {
+-                                      struct iphdr    *ip_hdr;
+-                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
+-                                      if (ip_hdr->protocol == IPPROTO_UDP)
+-                                      {
+-                                              sl351x_nat_input(skb,
+-                                                                              tp->port_id,
+-                                                                              (void *)curr_desc->word3.bits.l3_offset,
+-                                                                              (void *)curr_desc->word3.bits.l4_offset);
+-                                      }
+-                                      else if (ip_hdr->protocol == IPPROTO_GRE)
+-                                      {
+-                                              sl351x_nat_input(skb,
+-                                                                      tp->port_id,
+-                                                                      (void *)curr_desc->word3.bits.l3_offset,
+-                                                                      (void *)curr_desc->word3.bits.l4_offset);
+-                                      }
+-                              }
+-#endif
+                               skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
+                       }
+                       else
+                       {
+                               skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
+                       }
+-                      //netif_rx(skb);  /* socket rx */
++
+                       netif_receive_skb(skb); //For NAPI
+                       dev->last_rx = jiffies;
+                       isPtr->rx_bytes += pkt_size;
+-                      //printk("------------------->isPtr->rx_bytes = %d\n",isPtr->rx_bytes);
+-
++              }
+-        }
+               // advance one for Rx default Q 0/1
+               rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
+               SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
+-      tp->rx_rwptr.bits32 = rwptr.bits32;
++              tp->rx_rwptr.bits32 = rwptr.bits32;
+               rx_pkts_num++;
+-              //rwptr.bits32 = readl(&tp->default_qhdr->word1);//try read default_qhdr again
+-              //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-              //printk("%s:---Loop  -------->rx_pkts_num=%d------------>Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits32,fq_rwptr.bits32 );
+-#if 0
+-              if ((status4 & 0x1) == 0)
+-              {
+-                      //if (!((dev->last_rx <= (rx_time + 2)) &&  (isPtr->rx_bytes > (rx_old_bytes + 1000000 ))))
+-                      if (tp->total_q_cnt_napi < 1024)
+-                      {
+-                              tp->total_q_cnt_napi++;
+-                              toe_gmac_fill_free_q();  //for iperf test disable
+-                      }
+-                      //else
+-                              //printk("%s:---isPtr->rx_bytes =%u , rx_old_bytes =%u\n",__func__,isPtr->rx_bytes,rx_old_bytes );
++              // rwptr.bits32 = readl(&tp->default_qhdr->word1);
++              status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++              if (status4 & 1) {
++                      writel(status4 & SWFQ_EMPTY_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
+               }
++
++              toe_gmac_fill_free_q(5);
++      }
++
++#if 0
++      /* avoid races with hard_start_xmit() */
++
++      spin_lock(&gmac_fq_lock);
++      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
++      spin_unlock(&gmac_fq_lock);
+ #endif
+-              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
+-              //printk("%s:---Loop  -------->rx_pkts_num=%d----rwptr.bits.rptr=0x%x-------->Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits32,fq_rwptr.bits32 );
+-              //printk("%s:---Loop  rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
++
++      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++      if (status4 & 1)
++      {
++              writel(status4 & SWFQ_EMPTY_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
++              status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
++              toe_gmac_fill_free_q(rx_pkts_num);
+       }
+-      // advance one for Rx default Q 0/1
+-              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
+-              //SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
+-      //tp->rx_rwptr.bits32 = rwptr.bits32;
+-      //rwptr.bits.rptr = rwptr.bits.rptr;
++      rwptr.bits32 = readl(&tp->default_qhdr->word1);
++      if (rwptr.bits.rptr != rwptr.bits.wptr &&
++          quota > rx_pkts_num)
++              goto rx_poll_retry;
+       dev->quota -= rx_pkts_num;
+       *budget -= rx_pkts_num;
+-      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);//try read SWFQ empty again
+-      //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
+-      rwptr.bits32 = readl(&tp->default_qhdr->word1); //try read default_qhdr again
+-      //printk("%s:---After    rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
+-//    if (rwptr.bits.rptr > rwptr.bits.wptr )
+-//                    {
+-                              //toe_gmac_disable_rx(dev);
+-                              //wait_event_interruptible_timeout(freeq_wait,
+-                                      //(rx_pkts_num == 100), CMTP_INTEROP_TIMEOUT);
+-                              //printk("\n%s:: return 22222=======> rx_pkts_num =%d,   rwptr.bits.rptr=%d,   rwptr.bits.wptr = %d ====---------=======>JKJKJKJKJK\n",
+-                                      //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
+-//                            return 1;
+-//                    }
+-
+-      if (rwptr.bits.rptr == rwptr.bits.wptr)
++      /* Receive queue is empty now */
++      if (quota >= rx_pkts_num)
+       {
+-              // unsigned int data32;
+-                      //printk("%s:---[rwptr.bits.rptr == rwptr.bits.wptr]   rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
+-
+-          /* Receive descriptor is empty now */
+-#if 1
+-     if (status4 & 0x1)
+-                      {
+-                              do_again =1;
+-                              //writel(0x40400000, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_4_REG); //disable SWFQ empty interrupt
+-                              //toe_gmac_disable_interrupt(tp->irq);
+-                              tp->sw_fq_empty_cnt++;
+-                              //toe_gmac_disable_rx(dev);
+-                              writel(0x07960202, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-                              writel(0x07960202, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-                              //printk("\n%s ::  freeq int-----tp->sw_fq_empty_cnt  =%d---------====================----------------->\n",__func__,tp->sw_fq_empty_cnt);
+-                              //while ((fq_rwptr.bits.wptr >= (fq_rwptr.bits.rptr+256)) || (fq_rwptr.bits.wptr <= (fq_rwptr.bits.rptr+256)))
+-                              //{
+-                                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
+-                                      //0x1);
+-                              //printk("\n%s::fq_rwptr.wrptr = %x =======> ===========>here \n", __func__,fq_rwptr.bits32);
+-                              //if ((status4 & 0x1) == 0)
+-                                      //break;
+-                               return 1;
+-                              //}
++              unsigned long flags;
++              netif_rx_complete(dev);
++              rx_poll_enabled = 0;
++#if 0
++              status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
++              if (status1 & 1) {
++                      if (netif_rx_reschedule(dev, rx_pkts_num)) {
++                              rx_poll_enabled = 1;
++                              return 1;
+                       }
++              }
+ #endif
+-        //toe_gmac_fill_free_q();
+-        netif_rx_complete(dev);
+-
+-              rx_poll_enabled = 0;
+-              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-              if (tp->port_id == 0)
+-                              data32 |= DEFAULT_Q0_INT_BIT;
+-              else
+-                              data32 |= DEFAULT_Q1_INT_BIT;
+-              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
++              spin_lock_irqsave(&gmac_fq_lock, flags);
+               data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
+               if (tp->port_id == 0)
+-                              data32 |= DEFAULT_Q0_INT_BIT;
++                      data32 |= DEFAULT_Q0_INT_BIT;
+               else
+-                              data32 |= DEFAULT_Q1_INT_BIT;
++                      data32 |= DEFAULT_Q1_INT_BIT;
+               writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
+-              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+               if (tp->port_id == 0)
+-                              data32 |= DEFAULT_Q0_INT_BIT;
++                      data32 |= DEFAULT_Q0_INT_BIT;
+               else
+-                              data32 |= DEFAULT_Q1_INT_BIT;
+-              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
++                      data32 |= DEFAULT_Q1_INT_BIT;
++              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-        // enable GMAC-0 rx interrupt
+-        // class-Q & TOE-Q are implemented in future
+-        //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-        //if (tp->port_id == 0)
+-              //data32 |= DEFAULT_Q0_INT_BIT;
+-        //else
+-              //data32 |= DEFAULT_Q1_INT_BIT;
+-        //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
+-              writel(0x3, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
+-              //printk("\n%s::netif_rx_complete-->  rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x ====---------=======>JKJKJKJKJK\n",
+-              //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
+-        writel(0x07960200, TOE_GMAC0_BASE+GMAC_CONFIG0);
+-              writel(0x07960200, TOE_GMAC1_BASE+GMAC_CONFIG0);
+-        return 0;
+-    }
+-    else
+-    {
+-        //printk("\n%s:: return 1 -->status4= 0x%x,rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x  ======> \n", __func__,status4,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
+-        return 1;
+-    }
++              spin_unlock_irqrestore(&gmac_fq_lock, flags);
++
++              return 0;
++      }
++      else
++      {
++              /* not done, will call ->poll() later. */
++              return 1;
++      }
+ }
+ #endif
+@@ -5114,6 +4475,7 @@
+                       {
+                               sl351x_nat_workaround_cnt++;
+                               sl351x_nat_workaround_handler();
++                              printk("%():%d - workaround\n", __func__, __LINE__);
+                       }
+ #endif
+ #endif
+@@ -5124,6 +4486,7 @@
+       }
+ do_workaround:
++      printk("doing workaround ?!\n");
+       gmac_initialized = 0;
+       if (hanged_state)
+@@ -5290,6 +4653,7 @@
+       GMAC_SWTXQ_T    *swtxq;
+       DMA_RWPTR_T             rwptr;
++      printk("**** %s():%d\n", __func__, __LINE__);
+       toe = (TOE_INFO_T *)&toe_private_data;
+       tp = (GMAC_INFO_T *)&toe->gmac[0];
+       for (i=0; i<GMAC_NUM; i++, tp++)
+@@ -5341,6 +4705,7 @@
+       volatile GMAC_RXDESC_T  *curr_desc;
+       struct sk_buff                  *skb;
++      printk("**** %s():%d\n", __func__, __LINE__);
+       toe = (TOE_INFO_T *)&toe_private_data;
+       tp = (GMAC_INFO_T *)&toe->gmac[0];
+       for (i=0; i<GMAC_NUM; i++, tp++)
+@@ -5374,6 +4739,7 @@
+       volatile GMAC_RXDESC_T  *curr_desc;
+       struct sk_buff                  *skb;
++      printk("**** %s():%d\n", __func__, __LINE__);
+       toe = (TOE_INFO_T *)&toe_private_data;
+       classq = (CLASSQ_INFO_T *)&toe->classq[0];
+       for (i=0; i<TOE_CLASS_QUEUE_NUM; i++, classq++)
+@@ -5410,6 +4776,7 @@
+       GMAC_RXDESC_T   *toe_curr_desc;
+       struct sk_buff                  *skb;
++      printk("**** %s():%d\n", __func__, __LINE__);
+       toe = (TOE_INFO_T *)&toe_private_data;
+       toe_qhdr = (TOE_QHDR_T *)TOE_TOE_QUE_HDR_BASE;
+       for (i=0; i<TOE_TOE_QUEUE_NUM; i++, toe_qhdr++)
+--- a/include/asm-arm/arch-sl2312/sl351x_gmac.h
++++ b/include/asm-arm/arch-sl2312/sl351x_gmac.h
+@@ -107,7 +107,7 @@
+  * The base address and descriptor number are configured at
+  * DMA Queues Descriptor Ring Base Address/Size Register (offset 0x0004)
+  **********************************************************************/
+-#define TOE_SW_FREEQ_DESC_POWER               10
++#define TOE_SW_FREEQ_DESC_POWER               8
+ #define TOE_SW_FREEQ_DESC_NUM         (1<<TOE_SW_FREEQ_DESC_POWER)
+ #define TOE_HW_FREEQ_DESC_POWER               8
+ #define TOE_HW_FREEQ_DESC_NUM         (1<<TOE_HW_FREEQ_DESC_POWER)
+@@ -123,12 +123,12 @@
+ #define TOE_DEFAULT_Q0_DESC_NUM               (1<<TOE_DEFAULT_Q0_DESC_POWER)
+ #define TOE_DEFAULT_Q1_DESC_POWER     8
+ #define TOE_DEFAULT_Q1_DESC_NUM               (1<<TOE_DEFAULT_Q1_DESC_POWER)
+-#define TOE_TOE_DESC_POWER                    8
+-#define TOE_TOE_DESC_NUM                      (1<<TOE_TOE_DESC_POWER)
++#define TOE_TOE_DESC_POWER            8
++#define TOE_TOE_DESC_NUM              (1<<TOE_TOE_DESC_POWER)
+ #define TOE_CLASS_DESC_POWER          8
+-#define TOE_CLASS_DESC_NUM                    (1<<TOE_CLASS_DESC_POWER)
+-#define TOE_INTR_DESC_POWER                   8
+-#define TOE_INTR_DESC_NUM                     (1<<TOE_INTR_DESC_POWER)
++#define TOE_CLASS_DESC_NUM            (1<<TOE_CLASS_DESC_POWER)
++#define TOE_INTR_DESC_POWER           8
++#define TOE_INTR_DESC_NUM             (1<<TOE_INTR_DESC_POWER)
+ #define TOE_TOE_QUEUE_MAX                     64
+ #define TOE_TOE_QUEUE_NUM                     64
diff --git a/target/linux/storm/patches/007-mtd.patch b/target/linux/storm/patches/007-mtd.patch
new file mode 100644 (file)
index 0000000..8e397bc
--- /dev/null
@@ -0,0 +1,4949 @@
+--- a/drivers/mtd/chips/Kconfig
++++ b/drivers/mtd/chips/Kconfig
+@@ -220,6 +220,13 @@
+         This option enables basic support for ROM chips accessed through
+         a bus mapping driver.
++config MTD_SERIAL
++      tristate "Support for Serial chips in bus mapping"
++      depends on MTD
++      help
++        This option enables basic support for Serial chips accessed through
++        a bus mapping driver.
++
+ config MTD_ABSENT
+       tristate "Support for absent chips in bus mapping"
+       help
+--- a/drivers/mtd/chips/cfi_cmdset_0002.c
++++ b/drivers/mtd/chips/cfi_cmdset_0002.c
+@@ -39,10 +39,15 @@
+ #include <linux/mtd/cfi.h>
+ #include <linux/mtd/xip.h>
++//****** Storlink SoC ******
+ #define AMD_BOOTLOC_BUG
+-#define FORCE_WORD_WRITE 0
+-
+-#define MAX_WORD_RETRIES 3
++//#define FORCE_WORD_WRITE 0
++#define FORCE_WORD_WRITE 1
++#define FORCE_FAST_PROG 0
++
++//#define MAX_WORD_RETRIES 3
++#define MAX_WORD_RETRIES 3 // CONFIG_MTD_CFI_AMDSTD_RETRY
++//**************************
+ #define MANUFACTURER_AMD      0x0001
+ #define MANUFACTURER_ATMEL    0x001F
+@@ -322,6 +327,13 @@
+ #endif
+               bootloc = extp->TopBottom;
++//****** Storlink SoC ******
++              if(bootloc == 5)
++              {
++                      bootloc = 3;
++                      extp->TopBottom = 3;
++              }
++//**************************
+               if ((bootloc != 2) && (bootloc != 3)) {
+                       printk(KERN_WARNING "%s: CFI does not contain boot "
+                              "bank location. Assuming top.\n", map->name);
+@@ -340,6 +352,9 @@
+                               cfi->cfiq->EraseRegionInfo[j] = swap;
+                       }
+               }
++#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
++              cfi->device_type = CFI_DEVICETYPE_X8;
++#endif
+               /* Set the default CFI lock/unlock addresses */
+               cfi->addr_unlock1 = 0x555;
+               cfi->addr_unlock2 = 0x2aa;
+@@ -461,6 +476,7 @@
+       map_word d, t;
+       d = map_read(map, addr);
++      udelay(20);     //Storlink SoC
+       t = map_read(map, addr);
+       return map_word_equal(map, d, t);
+@@ -626,7 +642,9 @@
+       default:
+               printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate);
+       }
++//****** Storlink SoC ******
+       wake_up(&chip->wq);
++//**************************
+ }
+ #ifdef CONFIG_MTD_XIP
+@@ -940,7 +958,9 @@
+       cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
++//****** Storlink SoC ******
+       wake_up(&chip->wq);
++//**************************
+       spin_unlock(chip->mutex);
+       return 0;
+@@ -1005,7 +1025,10 @@
+        */
+       unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
+       int ret = 0;
+-      map_word oldd;
++//****** Storlink SoC ******
++//    map_word oldd;
++      map_word oldd, tmp;
++//**************************
+       int retry_cnt = 0;
+       adr += chip->start;
+@@ -1037,9 +1060,15 @@
+       ENABLE_VPP(map);
+       xip_disable(map, chip, adr);
+  retry:
++//****** Storlink SoC ******
++#if FORCE_FAST_PROG  /* Unlock bypass */
++      cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
++#else
+       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
++#endif
++//**************************
+       map_write(map, datum, adr);
+       chip->state = FL_WRITING;
+@@ -1072,7 +1101,13 @@
+               }
+               if (chip_ready(map, adr))
+-                      break;
++              {
++                      tmp = map_read(map, adr);
++                      if(map_word_equal(map, tmp, datum))
++//                            goto op_done;
++                break;
++
++              }
+               /* Latency issues. Drop the lock, wait a while and retry */
+               UDELAY(map, chip, adr, 1);
+@@ -1084,8 +1119,17 @@
+               /* FIXME - should have reset delay before continuing */
+               if (++retry_cnt <= MAX_WORD_RETRIES)
++              {
++//****** Storlink SoC ******
++#if FORCE_FAST_PROG
++                      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
++                      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
++                      cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
++              //udelay(1);
++#endif
++                      udelay(1);
+                       goto retry;
+-
++              }
+               ret = -EIO;
+       }
+       xip_enable(map, chip, adr);
+@@ -1171,7 +1215,14 @@
+                               return 0;
+               }
+       }
+-
++//****** Storlink SoC ******
++      map_write( map, CMD(0xF0), chipstart );
++#if FORCE_FAST_PROG
++              cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
++//**************************
+       /* We are now aligned, write as much as possible */
+       while(len >= map_bankwidth(map)) {
+               map_word datum;
+@@ -1181,7 +1232,15 @@
+               ret = do_write_oneword(map, &cfi->chips[chipnum],
+                                      ofs, datum);
+               if (ret)
++              {
++//****** Storlink SoC ******
++#if FORCE_FAST_PROG
++                      /* Get out of unlock bypass mode */
++                      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
++                      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
+                       return ret;
++              }
+               ofs += map_bankwidth(map);
+               buf += map_bankwidth(map);
+@@ -1189,19 +1248,38 @@
+               len -= map_bankwidth(map);
+               if (ofs >> cfi->chipshift) {
++//****** Storlink SoC ******
++#if FORCE_FAST_PROG
++                      /* Get out of unlock bypass mode */
++                      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
++                      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
+                       chipnum ++;
+                       ofs = 0;
+                       if (chipnum == cfi->numchips)
+                               return 0;
+                       chipstart = cfi->chips[chipnum].start;
++#if FORCE_FAST_PROG
++                      /* Go into unlock bypass mode for next set of chips */
++                      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
++                      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
++                      cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
+               }
+       }
++#if FORCE_FAST_PROG
++      /* Get out of unlock bypass mode */
++      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
++      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
++
+       /* Write the trailing bytes if any */
+       if (len & (map_bankwidth(map)-1)) {
+               map_word tmp_buf;
+  retry1:
++
+               spin_lock(cfi->chips[chipnum].mutex);
+               if (cfi->chips[chipnum].state != FL_READY) {
+@@ -1221,7 +1299,11 @@
+ #endif
+                       goto retry1;
+               }
+-
++#if FORCE_FAST_PROG
++              cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
+               tmp_buf = map_read(map, ofs + chipstart);
+               spin_unlock(cfi->chips[chipnum].mutex);
+@@ -1231,11 +1313,23 @@
+               ret = do_write_oneword(map, &cfi->chips[chipnum],
+                               ofs, tmp_buf);
+               if (ret)
++              {
++#if FORCE_FAST_PROG
++      /* Get out of unlock bypass mode */
++      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
++      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
+                       return ret;
+-
++              }
++#if FORCE_FAST_PROG
++      /* Get out of unlock bypass mode */
++      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
++      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
++#endif
+               (*retlen) += len;
+       }
++      map_write( map, CMD(0xF0), chipstart );
+       return 0;
+ }
+@@ -1275,6 +1369,7 @@
+       ENABLE_VPP(map);
+       xip_disable(map, chip, cmd_adr);
++      map_write( map, CMD(0xF0), chip->start );       //Storlink
+       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
+       //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+@@ -1535,6 +1630,9 @@
+       DECLARE_WAITQUEUE(wait, current);
+       int ret = 0;
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_lock();                             // sl2312 share pin lock
++#endif
+       adr += chip->start;
+       spin_lock(chip->mutex);
+@@ -1613,6 +1711,9 @@
+       chip->state = FL_READY;
+       put_chip(map, chip, adr);
+       spin_unlock(chip->mutex);
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
+       return ret;
+ }
+--- /dev/null
++++ b/drivers/mtd/chips/map_serial.c
+@@ -0,0 +1,188 @@
++/*
++ * Common code to handle map devices which are simple ROM
++ * (C) 2000 Red Hat. GPL'd.
++ * $Id: map_serial.c,v 1.3 2006/06/05 02:34:54 middle Exp $
++ */
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++
++#include <asm/byteorder.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++
++#include <asm/hardware.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/mtd.h>
++#include <linux/init.h> //add
++#include <asm/arch/sl2312.h>
++#include <asm/arch/flash.h>
++
++static int mapserial_erase(struct mtd_info *mtd, struct erase_info *instr);
++static int mapserial_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
++static int mapserial_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
++static void mapserial_nop (struct mtd_info *);
++struct mtd_info *map_serial_probe(struct map_info *map);
++
++extern int m25p80_sector_erase(__u32 address, __u32 schip_en);
++
++static struct mtd_chip_driver mapserial_chipdrv = {
++      probe: map_serial_probe,
++      name: "map_serial",
++      module: THIS_MODULE
++};
++
++struct mtd_info *map_serial_probe(struct map_info *map)
++{
++      struct mtd_info *mtd;
++
++      mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
++      if (!mtd)
++              return NULL;
++
++      memset(mtd, 0, sizeof(*mtd));
++
++      map->fldrv = &mapserial_chipdrv;
++      mtd->priv = map;
++      mtd->name = map->name;
++      mtd->type = MTD_OTHER;
++      mtd->erase = mapserial_erase;
++      mtd->size = map->size;
++      mtd->read = mapserial_read;
++      mtd->write = mapserial_write;
++      mtd->sync = mapserial_nop;
++      mtd->flags = (MTD_WRITEABLE|MTD_ERASEABLE);
++//    mtd->erasesize = 512; // page size;
++#ifdef CONFIG_MTD_SL2312_SERIAL_ST
++      mtd->erasesize = M25P80_SECTOR_SIZE; // block size;
++#else
++      mtd->erasesize = 0x1000; // block size;
++#endif
++
++      __module_get(THIS_MODULE);
++      //MOD_INC_USE_COUNT;
++      return mtd;
++}
++
++#define       FLASH_ACCESS_OFFSET                             0x00000010
++#define       FLASH_ADDRESS_OFFSET                            0x00000014
++#define       FLASH_WRITE_DATA_OFFSET                         0x00000018
++#define       FLASH_READ_DATA_OFFSET                          0x00000018
++
++static __u32 readflash_ctrl_reg(__u32 ofs)
++{
++    __u32 *base;
++
++    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
++    return __raw_readl(base);
++}
++
++static void writeflash_ctrl_reg(__u32 data, __u32 ofs)
++{
++    __u32 *base;
++
++    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
++    __raw_writel(data, base);
++}
++
++static int mapserial_erase_block(struct map_info *map,unsigned int block)
++{
++
++      __u32 address;
++#ifdef CONFIG_MTD_SL2312_SERIAL_ST
++
++      if(!m25p80_sector_erase(block, 0))
++              return (MTD_ERASE_DONE);
++#else
++      __u32 opcode;
++      __u32 count=0;
++//      __u8  status;
++
++ //     printk("mapserial_erase_block : erase block %d \n",block);
++//      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd;
++      opcode = 0x80000000 | 0x0200 | 0x50;
++      address = (block << 13);
++      writeflash_ctrl_reg(address,FLASH_ADDRESS_OFFSET);
++      writeflash_ctrl_reg(opcode,FLASH_ACCESS_OFFSET);
++      opcode=readflash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode = readflash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          count++;
++          if (count > 10000)
++          {
++            return (MTD_ERASE_FAILED);
++          }
++      }
++      return (MTD_ERASE_DONE);
++#endif
++}
++
++static int mapserial_erase(struct mtd_info *mtd, struct erase_info *instr)
++{
++      struct map_info *map = (struct map_info *)mtd->priv;
++    unsigned int    addr;
++    int             len;
++    unsigned int    block;
++    unsigned int    ret=0;
++
++      addr = instr->addr;
++      len = instr->len;
++    while (len > 0)
++    {
++        block = addr / mtd->erasesize;
++#ifdef CONFIG_MTD_SL2312_SERIAL_ST
++        ret = mapserial_erase_block(map,addr);
++#else
++              ret = mapserial_erase_block(map,block);
++#endif
++        addr = addr + mtd->erasesize;
++        len = len - mtd->erasesize;
++    }
++    return (ret);
++}
++
++static int mapserial_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
++{
++      struct map_info *map = (struct map_info *)mtd->priv;
++//        printk("mapserial_read : \n");
++      map->copy_from(map, buf, from, len);
++      *retlen = len;
++      return 0;
++}
++
++static void mapserial_nop(struct mtd_info *mtd)
++{
++      /* Nothing to see here */
++}
++
++static int mapserial_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
++{
++      struct map_info *map = (struct map_info *)mtd->priv;
++//    printk("mapserial_write : buf %x to %x len %x \n",(int)buf, (int)to, (int)len);
++      //map->copy_to(map, buf, to, len);
++      map->copy_to(map, to, buf, len);
++      *retlen = len;
++      return 0;
++}
++
++int __init map_serial_init(void)
++{
++      register_mtd_chip_driver(&mapserial_chipdrv);
++      return 0;
++}
++
++static void __exit map_serial_exit(void)
++{
++      unregister_mtd_chip_driver(&mapserial_chipdrv);
++}
++
++module_init(map_serial_init);
++module_exit(map_serial_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
++MODULE_DESCRIPTION("MTD chip driver for ROM chips");
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -614,5 +614,30 @@
+         This selection automatically selects the map_ram driver.
++#***************************************************************************************
++# Storlink parallel/Serial Flash configuration
++#***************************************************************************************
++config MTD_SL2312_CFI
++        tristate "CFI Flash device mapped on SL2312"
++        depends on MTD_CFI
++        help
++          Map driver for SL2312 demo board.
++
++config MTD_SL2312_SERIAL_ATMEL
++        tristate "ATMEL Serial Flash device mapped on SL2312"
++        depends on MTD_PARTITIONS && ARCH_SL2312
++        help
++          Map driver for SL2312 demo board.
++
++config MTD_SL2312_SERIAL_ST
++        tristate "ST Serial Flash device mapped on SL2312"
++        depends on MTD_PARTITIONS && ARCH_SL2312
++        help
++          Map driver for SL2312 demo board.
++
++config SL2312_SHARE_PIN
++        tristate "Parallel Flash share pin on SL2312 ASIC"
++        depends on SL3516_ASIC
++
+ endmenu
+--- /dev/null
++++ b/drivers/mtd/maps/sl2312-flash-atmel.c
+@@ -0,0 +1,554 @@
++/*
++ * $Id: sl2312-flash-atmel.c,v 1.2 2006/06/05 02:35:57 middle Exp $
++ *
++ * Flash and EPROM on Hitachi Solution Engine and similar boards.
++ *
++ * (C) 2001 Red Hat, Inc.
++ *
++ * GPL'd
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <asm/io.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <asm/hardware.h>
++
++#include <asm/arch/sl2312.h>
++#include <asm/arch/flash.h>
++#include <linux/init.h> //add
++
++
++#define  g_page_addr  AT45DB321_PAGE_SHIFT    //321 : shift 10  ; 642 : shift 11
++#define  g_chipen     SERIAL_FLASH_CHIP0_EN   //atmel
++
++extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
++
++void address_to_page(__u32 address, __u16 *page, __u16 *offset)
++{
++    *page = address / SPAGE_SIZE;
++    *offset = address % SPAGE_SIZE;
++}
++
++static __u32 read_flash_ctrl_reg(__u32 ofs)
++{
++    __u32 *base;
++
++    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
++    return __raw_readl(base);
++}
++
++static void write_flash_ctrl_reg(__u32 ofs,__u32 data)
++{
++    __u32 *base;
++
++    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
++    __raw_writel(data, base);
++}
++
++void atmel_read_status(__u8 cmd, __u8 *data)
++{
++      __u32 opcode;
++      __u32 value;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | cmd | g_chipen;
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++
++      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      *data = value & 0xff;
++}
++
++void main_memory_page_read(__u8 cmd, __u16 page, __u16 offset, __u8 *data)
++{
++      __u32 opcode;
++      __u32 address;
++      __u32 value;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA | cmd | g_chipen;
++      address = (page << g_page_addr) + offset;
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++
++      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      *data = value & 0xff;
++}
++
++void buffer_to_main_memory(__u8 cmd, __u16 page)
++{
++      __u32 opcode;
++      __u32 address;
++      __u8  status;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
++      address = (page << g_page_addr);
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++      atmel_read_status(READ_STATUS_SPI, &status);
++      while(!(status&0x80))
++      {
++          atmel_read_status(READ_STATUS_SPI, &status);
++          flash_delay();
++          schedule();
++      }
++
++}
++
++
++void atmel_flash_read_page(__u32 address, __u8 *buffer, __u32 len)
++{
++    __u8  byte;
++    __u16 page, offset;
++    __u16 i;
++
++    address_to_page(address, &page, &offset);
++
++     for(i=0; i<len; i++,offset++)
++    {
++        main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
++        buffer [i]= byte;
++    }
++}
++
++void atmel_flash_program_page(__u32 address, __u8 *buffer, __u32 len)
++{
++    __u8  pattern;
++    __u16 page, offset;
++    __u32 i;
++
++    address_to_page(address, &page, &offset);
++ //   printk("atmel_flash_program_page: offset %x len %x page %x \n", offset, len, page);
++
++    if(offset)
++          main_memory_to_buffer(MAIN_MEMORY_TO_BUFFER1,page);
++
++    for(i=0; i<len; i++,offset++)
++    {
++        pattern = buffer[i];
++        atmel_buffer_write(BUFFER1_WRITE,offset,pattern);
++    }
++
++  //  printk("atmel_flash_program_page: offset %x \n", offset);
++    buffer_to_main_memory(BUFFER1_TO_MAIN_MEMORY, page);
++  //  printk("atmel_flash_program_page: buffer_to_main_memory %x page\n", page);
++
++}
++
++
++void main_memory_to_buffer(__u8 cmd, __u16 page)
++{
++      __u32 opcode;
++      __u32 address;
++      __u8  status;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
++      address = (page << g_page_addr);
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++      atmel_read_status(READ_STATUS_SPI, &status);
++      while(!(status&0x80))
++      {
++          atmel_read_status(READ_STATUS_SPI, &status);
++          flash_delay();
++          schedule();
++      }
++
++}
++
++void main_memory_page_program(__u8 cmd, __u16 page, __u16 offset, __u8 data)
++{
++      __u32 opcode;
++      __u32 address;
++      __u8  status;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | cmd | g_chipen;
++      address = (page << g_page_addr) + offset;
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, data);
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++      atmel_read_status(READ_STATUS_SPI, &status);
++      while(!(status&0x80))
++      {
++          atmel_read_status(READ_STATUS_SPI, &status);
++          flash_delay();
++          schedule();
++      }
++}
++
++void atmel_buffer_write(__u8 cmd, __u16 offset, __u8 data)
++{
++      __u32 opcode;
++      __u32 address;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | cmd  | g_chipen;
++      address = offset;
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, data);
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++
++}
++
++void atmel_erase_page(__u8 cmd, __u16 page)
++{
++      __u32 opcode;
++      __u32 address;
++      __u8  status;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
++      address = (page << g_page_addr);
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++      atmel_read_status(READ_STATUS_SPI, &status);
++      while(!(status&0x80))
++      {
++          atmel_read_status(READ_STATUS_SPI, &status);
++          flash_delay();
++          schedule();
++      }
++
++}
++
++void atmel_erase_block(__u8 cmd, __u16 block)
++{
++      __u32 opcode;
++      __u32 address;
++      __u8  status;
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
++      address = (block << 13);
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(opcode&0x80000000)
++      {
++          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++      atmel_read_status(READ_STATUS_SPI, &status);
++      while(!(status&0x80))
++      {
++          atmel_read_status(READ_STATUS_SPI, &status);
++          flash_delay();
++          schedule();
++      }
++
++}
++
++void flash_delay(void)
++{
++      int i;
++
++      for(i=0; i<50; i++)
++           i=i;
++}
++
++
++
++
++__u32 sl2312_read32(struct map_info *map, unsigned long ofs)
++{
++
++#if 0
++    __u16 page, offset;
++    __u32 pattern;
++    __u8  byte, i;
++
++     pattern = 0;
++     address_to_page(ofs, &page, &offset);
++     for(i=0; i<4; i++, offset++)
++    {
++        pattern = pattern << 8;
++        main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
++//printk("sl2312_read32:: address = %08x  data = %c \n",ofs,byte);
++        pattern += byte;
++    }
++    return pattern;
++#else
++      return read_flash_ctrl_reg(ofs);
++#endif
++
++}
++
++__u8 sl2312_read8(struct map_info *map, unsigned long ofs)
++{
++    __u16 page, offset;
++    __u8  byte;
++
++     address_to_page(ofs, &page, &offset);
++     main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
++       //printk("sl2312_read8:: address = %08x  data = %c \n",ofs,byte);
++     return byte;
++
++}
++
++void sl2312_write32(struct map_info *map, __u32 d, unsigned long ofs)
++{
++#if 0
++    __u16 page, offset;
++    __u8  byte, i;
++
++     address_to_page(ofs, &page, &offset);
++     for(i=0; i<4; i++, offset++)
++    {
++      byte = d & 0xff;
++        main_memory_page_program(MAIN_MEMORY_PROGRAM_BUFFER1, page, offset, byte);
++        d = d >> 8;
++//printk("sl2312_write32:: address = %08x  data = %c \n",ofs,byte);
++    }
++#else
++      write_flash_ctrl_reg(ofs, d);
++#endif
++}
++
++void sl2312_write8(struct map_info *map, __u8 d, unsigned long ofs)
++{
++     __u16 page, offset;
++
++     address_to_page(ofs, &page, &offset);
++     main_memory_page_program(MAIN_MEMORY_PROGRAM_BUFFER1, page, offset, d);
++//printk("sl2312_write8:: address = %08x  data = %c \n",ofs,d);
++
++}
++
++void sl2312_copy_from(struct map_info *map, void *buf, unsigned long ofs, ssize_t len)
++{
++     __u32 size;
++     __u8  *buffer;
++     __u32 length;//i, j,
++
++     //printk("sl2312_copy_from:: address = %08x  datalen = %d \n",ofs,len);
++
++     length = len;
++     buffer = (__u8 *)buf;
++     while(len)
++     {
++        size = SPAGE_SIZE - (ofs%SPAGE_SIZE);
++        if(size > len)
++            size = len;
++        atmel_flash_read_page(ofs, buffer, size);
++        buffer+=size;
++        ofs+=size;
++        len -= size;
++     }
++
++#if 0
++        buffer = (__u8 *)buf;
++        for(i=0; i<length; i+=16)
++       {
++          for(j=0; j<16; j++,buffer++)
++         {
++            if((i*16+j)<length)
++              printk("%x  ",(int)*buffer);
++       }
++          printk("\n");
++       }
++
++       printk("\n");
++#endif
++
++}
++
++
++void sl2312_copy_to(struct map_info *map, unsigned long ofs, void *buf, ssize_t len)
++{
++     __u32 size;
++     __u8  *buffer;
++
++     buffer = (__u8 *)buf;
++     //printk("sl2312_copy_to:offset %x len %x \n", ofs, len);
++//     printk("sl2312_copy_to:buf is %x \n", (int)buf);
++
++     while(len)
++     {
++        size = SPAGE_SIZE - (ofs%SPAGE_SIZE);
++        if(size > len)
++            size = len;
++        atmel_flash_program_page(ofs, buffer, size);
++        buffer+=size;
++        ofs+=size;
++      len-=size;
++    }
++
++
++}
++
++
++static struct mtd_info *serial_mtd;
++
++static struct mtd_partition *parsed_parts;
++
++static struct map_info sl2312_serial_map = {
++//    name: "SL2312 serial flash",
++//    size: 4194304, //0x400000,
++//            //buswidth: 4,
++//    bankwidth: 4,
++//    phys:            SL2312_FLASH_BASE,
++//#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
++//    //read32: sl2312_read32,
++//    //read8: sl2312_read8,
++//    copy_from: sl2312_copy_from,
++//    //write8: sl2312_write8,
++//    //write32: sl2312_write32,
++//    read: sl2312_read32,
++//    write: sl2312_write32,
++//    copy_to: sl2312_copy_to
++//#endif
++      .name = "SL2312 serial flash",
++      .size = 4194304, //0x400000,
++              //buswidth: 4,
++      .bankwidth = 4,
++      .phys =          SL2312_FLASH_BASE,
++#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
++      //read32: sl2312_read32,
++      //read8: sl2312_read8,
++      .copy_from = sl2312_copy_from,
++      //write8: sl2312_write8,
++      //write32: sl2312_write32,
++      .read = sl2312_read32,
++      .write = sl2312_write32,
++      .copy_to = sl2312_copy_to
++#endif
++};
++
++
++
++static struct mtd_partition sl2312_partitions[] = {
++
++
++      ///* boot code */
++      //{ name: "bootloader", offset: 0x00000000, size: 0x20000, },
++      ///* kernel image */
++      //{ name: "kerel image", offset: 0x000020000, size: 0x2E0000 },
++      ///* All else is writable (e.g. JFFS) */
++      //{ name: "user data", offset: 0x00300000, size: 0x00100000, },
++      /* boot code */
++      { .name = "bootloader", .offset = 0x00000000, .size = 0x20000, },
++      /* kernel image */
++      { .name = "kerel image", .offset = 0x000020000, .size = 0xE0000 },
++      /* All else is writable (e.g. JFFS) */
++      { .name = "user data", .offset = 0x00100000, .size = 0x00300000, },
++
++
++};
++
++
++
++static int __init init_sl2312_maps(void)
++{
++      int nr_parts = 0;
++      struct mtd_partition *parts;
++
++      serial_mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
++      if (!serial_mtd)
++              return NULL;
++
++      memset(serial_mtd, 0, sizeof(struct mtd_info));
++      //sl2312flash_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
++    //sl2312_serial_map.map_priv_1 = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)FLASH_VBASE;
++    sl2312_serial_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)ioremap(FLASH_START, SFLASH_SIZE);
++    if (!sl2312_serial_map.virt) {
++              printk(" failed to ioremap \n");
++              return -EIO;
++      }
++      serial_mtd = do_map_probe("map_serial", &sl2312_serial_map);
++      if (serial_mtd) {
++              //serial_mtd->module = THIS_MODULE;
++              serial_mtd->owner = THIS_MODULE;
++
++      }
++
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++      nr_parts = parse_redboot_partitions(serial_mtd, &parsed_parts);
++      if (nr_parts > 0)
++              printk(KERN_NOTICE "Found RedBoot partition table.\n");
++      else if (nr_parts < 0)
++              printk(KERN_NOTICE "Error looking for RedBoot partitions.\n");
++#else
++      parsed_parts = sl2312_partitions;
++      parts = sl2312_partitions;
++      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
++      nr_parts = sizeof(sl2312_partitions)/sizeof(*parsed_parts);
++#endif /* CONFIG_MTD_REDBOOT_PARTS */
++
++      if (nr_parts > 0)
++          add_mtd_partitions(serial_mtd, parsed_parts, nr_parts);
++      else
++          add_mtd_device(serial_mtd);
++
++      return 0;
++}
++
++static void __exit cleanup_sl2312_maps(void)
++{
++      if (parsed_parts)
++          del_mtd_partitions(serial_mtd);
++      else
++          del_mtd_device(serial_mtd);
++
++      map_destroy(serial_mtd);
++
++
++}
++
++module_init(init_sl2312_maps);
++module_exit(cleanup_sl2312_maps);
++
++
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Plus Chen <plus@storlink.com.tw>");
++MODULE_DESCRIPTION("MTD map driver for Storlink Sword boards");
++
+--- /dev/null
++++ b/drivers/mtd/maps/sl2312-flash-cfi.c
+@@ -0,0 +1,370 @@
++/*======================================================================
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++======================================================================*/
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/string.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <asm/arch/sl2312.h>
++#include <linux/mtd/kvctl.h>
++#include "sl2312_flashmap.h"
++
++
++//extern int parse_afs_partitions(struct mtd_info *, struct mtd_partition **);
++
++/* the base address of FLASH control register */
++#define FLASH_CONTROL_BASE_ADDR           (IO_ADDRESS(SL2312_FLASH_CTRL_BASE))
++#define SL2312_GLOBAL_BASE_ADDR     (IO_ADDRESS(SL2312_GLOBAL_BASE))
++
++/* define read/write register utility */
++#define FLASH_READ_REG(offset)                        (__raw_readl(offset+FLASH_CONTROL_BASE_ADDR))
++#define FLASH_WRITE_REG(offset,val)   (__raw_writel(val,offset+FLASH_CONTROL_BASE_ADDR))
++
++/* the offset of FLASH control register */
++enum EMAC_REGISTER {
++      FLASH_ID        = 0x0000,
++      FLASH_STATUS    = 0x0008,
++      FLASH_TYPE      = 0x000c,
++      FLASH_ACCESS    = 0x0020,
++      FLASH_ADDRESS   = 0x0024,
++      FLASH_DATA              = 0x0028,
++      FLASH_TIMING    = 0x002c,
++};
++
++//#define FLASH_BASE  FLASH_CONTROL_BASE_ADDR
++//#define FLASH_SIZE  0x00800000 //INTEGRATOR_FLASH_SIZE
++
++//#define FLASH_PART_SIZE 8388608
++
++static unsigned int flash_indirect_access = 0;
++
++#ifdef CONFIG_SL2312_SHARE_PIN
++static unsigned int chip_en = 0x00000000;
++
++void sl2312flash_enable_parallel_flash(void)
++{
++    unsigned int    reg_val;
++
++    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
++    reg_val = reg_val & 0xfffffffd;
++    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
++    return;
++}
++
++void sl2312flash_disable_parallel_flash(void)
++{
++    unsigned int    reg_val;
++
++    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
++    reg_val = reg_val | 0x00000002;
++    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
++    return;
++}
++#endif
++
++
++static struct map_info sl2312flash_map =
++{
++      name:           "SL2312 CFI Flash",
++      size:       FLASH_SIZE,
++      bankwidth:   2,
++      //bankwidth:   1, //for 8 bits width
++    phys:       SL2312_FLASH_BASE,
++};
++
++static struct mtd_info *mtd;
++#if 0
++static struct mtd_partition sl2312_partitions[] = {
++      /* boot code */
++      {
++              name: "bootloader",
++              offset: 0x00000000,
++              size: 0x20000,
++//            mask_flags: MTD_WRITEABLE,
++      },
++      /* kernel image */
++      {
++              name: "kerel image",
++              offset: 0x00020000,
++              size: 0x2E0000
++      },
++      /* All else is writable (e.g. JFFS) */
++      {
++              name: "user data",
++              offset: 0x00300000,
++              size: 0x00100000,
++      }
++};
++#endif
++
++
++
++static int __init sl2312flash_init(void)
++{
++      struct mtd_partition *parts;
++      int nr_parts = 0;
++      int ret;
++#ifndef CONFIG_SL2312_SHARE_PIN
++    unsigned int    reg_val;
++#endif
++
++    printk("SL2312 MTD Driver Init.......\n");
++
++#ifndef CONFIG_SL2312_SHARE_PIN
++      /* enable flash */
++    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
++    reg_val = reg_val & 0xfffffffd;
++    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
++#else
++    sl2312flash_enable_parallel_flash();      /* enable Parallel FLASH */
++#endif
++    FLASH_WRITE_REG(FLASH_ACCESS,0x00004000); /* parallel flash direct access mode */
++    ret = FLASH_READ_REG(FLASH_ACCESS);
++    if (ret == 0x00004000)
++    {
++        flash_indirect_access = 0;  /* parallel flash direct access */
++    }
++    else
++    {
++        flash_indirect_access = 1;  /* parallel flash indirect access */
++    }
++
++      /*
++       * Also, the CFI layer automatically works out what size
++       * of chips we have, and does the necessary identification
++       * for us automatically.
++       */
++#ifdef CONFIG_GEMINI_IPI
++      sl2312flash_map.virt = FLASH_VBASE;//(unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
++#else
++      sl2312flash_map.virt = (unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
++#endif
++      //printk("sl2312flash_map.virt  = %08x\n",(unsigned int)sl2312flash_map.virt);
++
++//    simple_map_init(&sl2312flash_map);
++
++      mtd = do_map_probe("cfi_probe", &sl2312flash_map);
++      if (!mtd)
++      {
++#ifdef CONFIG_SL2312_SHARE_PIN
++        sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
++#endif
++              return -ENXIO;
++      }
++      mtd->owner = THIS_MODULE;
++//    mtd->erase = flash_erase;
++//    mtd->read = flash_read;
++//    mtd->write = flash_write;
++
++    parts = sl2312_partitions;
++      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
++      ret = add_mtd_partitions(mtd, parts, nr_parts);
++      /*If we got an error, free all resources.*/
++      if (ret < 0) {
++              del_mtd_partitions(mtd);
++              map_destroy(mtd);
++      }
++#ifdef CONFIG_SL2312_SHARE_PIN
++    sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
++#endif
++    printk("SL2312 MTD Driver Init Success ......\n");
++      return ret;
++}
++
++static void __exit sl2312flash_exit(void)
++{
++      if (mtd) {
++              del_mtd_partitions(mtd);
++              map_destroy(mtd);
++      }
++
++      if (sl2312flash_map.virt) {
++          iounmap((void *)sl2312flash_map.virt);
++          sl2312flash_map.virt = 0;
++      }
++}
++
++char chrtohex(char c)
++{
++  char val;
++  if ((c >= '0') && (c <= '9'))
++  {
++    val = c - '0';
++    return val;
++  }
++  else if ((c >= 'a') && (c <= 'f'))
++  {
++    val = 10 + (c - 'a');
++    return val;
++  }
++  else if ((c >= 'A') && (c <= 'F'))
++  {
++    val = 10 + (c - 'A');
++    return val;
++  }
++  printk("<1>Error number\n");
++  return 0;
++}
++
++
++int get_vlaninfo(vlaninfo* vlan)
++{
++      vctl_mheader head;
++      vctl_entry entry;
++      struct mtd_info *mymtd=NULL;
++      int i, j, loc = 0;
++      char *payload=0, *tmp1, *tmp2, tmp3[9];
++      size_t retlen;
++
++      #ifdef CONFIG_SL2312_SHARE_PIN
++      sl2312flash_enable_parallel_flash();
++      #endif
++      for(i=0;i<MAX_MTD_DEVICES;i++)
++      {
++              mymtd=get_mtd_device(NULL,i);
++              //    printk("mymtd->name: %s\n", mymtd->name);
++              if(mymtd && !strcmp(mymtd->name,"VCTL"))
++              {
++                      //      printk("%s\n", mymtd->name);
++                      break;
++              }
++      }
++      if( i >= MAX_MTD_DEVICES)
++      {
++              printk("Can't find version control\n");
++              #ifdef CONFIG_SL2312_SHARE_PIN
++              sl2312flash_disable_parallel_flash();
++              #endif
++              return 0;
++      }
++
++      if (!mymtd | !mymtd->read)
++      {
++              printk("<1>Can't read Version Configuration\n");
++              #ifdef CONFIG_SL2312_SHARE_PIN
++              sl2312flash_disable_parallel_flash();
++              #endif
++              return 0;
++      }
++
++      mymtd->read(mymtd, 0, VCTL_HEAD_SIZE, &retlen, (u_char*)&head);
++      //  printk("entry header: %c%c%c%c\n", head.header[0], head.header[1], head.header[2], head.header[3]);
++      //  printk("entry number: %x\n", head.entry_num);
++      if ( strncmp(head.header, "FLFM", 4) )
++      {
++              printk("VCTL is a erase block\n");
++              #ifdef CONFIG_SL2312_SHARE_PIN
++              sl2312flash_disable_parallel_flash();
++              #endif
++              return 0;
++      }
++      loc += retlen;
++      for (i = 0; i < head.entry_num; i++)
++      {
++              mymtd->read(mymtd, loc, VCTL_ENTRY_LEN, &retlen, (u_char*)&entry);
++              //    printk("type: %x\n", entry.type);
++              //    printk("size: %x\n", entry.size);
++              strncpy(tmp3, entry.header, 4);
++              if (entry.type == VCT_VLAN)
++              {
++                      for (j = 0; j < 6 ; j++)
++                      {
++                              vlan[0].mac[j] = 0;
++                              vlan[1].mac[j] = 0;
++                      }
++                      vlan[0].vlanid = 1;
++                      vlan[1].vlanid = 2;
++                      vlan[0].vlanmap = 0x7F;
++                      vlan[1].vlanmap = 0x80;
++
++                      payload = (char *)kmalloc(entry.size - VCTL_ENTRY_LEN, GFP_KERNEL);
++                      loc += VCTL_ENTRY_LEN;
++                      mymtd->read(mymtd, loc, entry.size - VCTL_ENTRY_LEN, &retlen, payload);
++                      //      printk("%s\n", payload);
++                      tmp1 = strstr(payload, "MAC1:");
++                      tmp2 = strstr(payload, "MAC2:");
++                      if(!tmp1||!tmp2){
++                              kfree(payload);
++                              #ifdef CONFIG_SL2312_SHARE_PIN
++                              sl2312flash_disable_parallel_flash();
++                              #endif
++                              printk("Error VCTL format!!\n");
++                              return 0;
++                      }
++                      tmp1 += 7;
++                      tmp2 += 7;
++
++
++                      for (j = 0; j < 6; j++)
++                      {
++                              vlan[0].mac[j] = chrtohex(tmp1[2*j])*16 + chrtohex(tmp1[(2*j)+1]);
++                              vlan[1].mac[j] = chrtohex(tmp2[2*j])*16 + chrtohex(tmp2[(2*j)+1]);
++                      }
++                      tmp1 = strstr(payload, "ID1:");
++                      tmp2 = strstr(payload, "ID2:");
++                      tmp1 += 4;
++                      tmp2 += 4;
++                      vlan[0].vlanid = tmp1[0] - '0';
++                      vlan[1].vlanid = tmp2[0] - '0';
++                      tmp1 = strstr(payload, "MAP1:");
++                      tmp2 = strstr(payload, "MAP2:");
++                      tmp1 += 7;
++                      tmp2 += 7;
++                      vlan[0].vlanmap = chrtohex(tmp1[0]) * 16 + chrtohex(tmp1[1]);
++                      vlan[1].vlanmap = chrtohex(tmp2[0]) * 16 + chrtohex(tmp2[1]);
++                      //  printk("Vlan1 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[0].vlanid, vlan[0].vlanmap, vlan[0].mac[0], vlan[0].mac[1], vlan[0].mac[2], vlan[0].mac[3], vlan[0].mac[4], vlan[0].mac[5]);
++                      //  printk("Vlan2 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[1].vlanid, vlan[1].vlanmap, vlan[1].mac[0], vlan[1].mac[1], vlan[1].mac[2], vlan[1].mac[3], vlan[1].mac[4], vlan[1].mac[5]);
++                      break;
++              }
++              loc += entry.size;
++      }
++      if ( entry.type == VCT_VLAN )
++      {
++              #ifdef CONFIG_SL2312_SHARE_PIN
++              sl2312flash_disable_parallel_flash();
++              #endif
++              kfree(payload);
++              return 1;
++      }
++      if (i >= head.entry_num)
++      printk("Can't find vlan information\n");
++      #ifdef CONFIG_SL2312_SHARE_PIN
++      sl2312flash_disable_parallel_flash();
++      #endif
++      return 0;
++}
++
++EXPORT_SYMBOL(get_vlaninfo);
++
++
++module_init(sl2312flash_init);
++module_exit(sl2312flash_exit);
++
++MODULE_AUTHOR("Storlink Ltd");
++MODULE_DESCRIPTION("CFI map driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/mtd/maps/sl2312-flash-m25p80.c
+@@ -0,0 +1,498 @@
++/*
++ * $Id: sl2312-flash-m25p80.c,v 1.2 2006/06/02 08:46:02 middle Exp $
++ *
++ * Flash and EPROM on Hitachi Solution Engine and similar boards.
++ *
++ * (C) 2001 Red Hat, Inc.
++ *
++ * GPL'd
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <asm/io.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <asm/hardware.h>
++
++#include <asm/arch/sl2312.h>
++#include <asm/arch/flash.h>
++#include <linux/init.h> //add
++#define  g_chipen     SERIAL_FLASH_CHIP0_EN   //ST
++
++//static int m25p80_page_program(__u32 address, __u8 data, __u32 schip_en);
++static void m25p80_write_cmd(__u8 cmd, __u32 schip_en);
++extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
++
++
++static __u32 read_flash_ctrl_reg(__u32 ofs)
++{
++    __u32 *base;
++
++    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
++    return __raw_readl(base);
++}
++
++static void write_flash_ctrl_reg(__u32 ofs,__u32 data)
++{
++    __u32 *base;
++
++    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
++    __raw_writel(data, base);
++}
++
++static void m25p80_read(__u32 address, __u8 *data, __u32 schip_en)
++{
++      __u32 opcode,status;
++      __u32 value;
++
++      //opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ;
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | M25P80_READ;
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++
++              opcode|=g_chipen;
++
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      status=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(status&0x80000000)
++      {
++          status=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++
++      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      *data = value & 0xff;
++}
++
++static int m25p80_page_program(__u32 address, __u8 *data, __u32 schip_en)
++{
++      __u32 opcode;
++      __u32  status;
++        __u32 tmp;
++        int res = FLASH_ERR_OK;
++        //volatile FLASH_DATA_T* data_ptr = (volatile FLASH_DATA_T*) data;
++        opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
++
++                    opcode|=g_chipen;
++
++          write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++          //middle delay_ms(130);
++          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++          if((status&0x02)==0x02)
++                {
++                     //middle delay_ms(100);
++               m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
++          }
++
++
++      m25p80_write_cmd(M25P80_WRITE_ENABLE, schip_en);
++      ////middle delay_ms(10);
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | M25P80_PAGE_PROGRAM;
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, *data);
++
++      //status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      //while(status!=data)
++      //{
++      //    status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      //    //middle delay_ms(10);
++      //}
++
++              opcode|=g_chipen;
++
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++      //opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
++
++              opcode|=g_chipen;
++
++
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      //while(status&0xfd)
++      while(status&0x01)
++      {
++                //if((status&0x9c)!=0)
++                //    printf("  m25p80_page_program   Protect Status = %x\n",status);
++                write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++                tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++          flash_delay();
++          schedule();
++          //middle delay_ms(50);
++      }
++      //printf("status = %x, data = %x\n",status,data);
++      if((status&0x02)==0x02)
++      {
++        //middle delay_ms(100);
++          m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
++      }
++    //};//while (len > 0)
++    return res;
++}
++
++void m25p80_copy_from(struct map_info *map, void *buf, unsigned long ofs, ssize_t len)
++{
++//     __u32 size;
++     __u8  *buffer;
++     __u32 length;//i, j,
++
++      length = len;
++     buffer = (__u8 *)buf;
++     while(len)
++     {
++        m25p80_read(ofs, buffer, g_chipen);
++        buffer++;
++        ofs++;
++        len --;
++     }        ;
++
++}
++
++__u32 m25p80_read32(struct map_info *map, unsigned long ofs)
++{
++
++      return read_flash_ctrl_reg(ofs);
++
++
++}
++
++void m25p80_write32(struct map_info *map, __u32 d, unsigned long ofs)
++{
++
++      write_flash_ctrl_reg(ofs, d);
++
++}
++
++void m25p80_copy_to(struct map_info *map, unsigned long ofs, void *buf, ssize_t len)
++{
++     __u32 size, i, ret;
++
++     while(len > 0)
++     {
++        if(len >= M25P80_PAGE_SIZE)
++                      size = M25P80_PAGE_SIZE;
++              else
++                      size = len;
++
++        for(i=0;i<size;i++)
++          {
++              ret = m25p80_page_program( (ofs+i),  (buf+i),  g_chipen);
++          }
++        buf+=M25P80_PAGE_SIZE;
++        ofs+=M25P80_PAGE_SIZE;
++              len-=M25P80_PAGE_SIZE;
++
++    };
++
++
++}
++
++static struct mtd_info *serial_mtd;
++
++static struct mtd_partition *parsed_parts;
++
++static struct map_info m25p80_map = {
++
++      .name = "SL2312 serial flash m25p80",
++      .size = 1048576, //0x100000,
++              //buswidth: 4,
++      .bankwidth = 4,
++      .phys =          SL2312_FLASH_BASE,
++#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
++      .copy_from = m25p80_copy_from,
++      .read = m25p80_read32,
++      .write = m25p80_write32,
++      .copy_to = m25p80_copy_to
++#endif
++};
++
++
++
++static struct mtd_partition m25p80_partitions[] = {
++
++      /* boot code */
++      { .name = "bootloader", .offset = 0x00000000, .size = 0x20000, },
++      /* kernel image */
++      { .name = "kerel image", .offset = 0x000020000, .size = 0xC0000 },
++      /* All else is writable (e.g. JFFS) */
++      { .name = "user data", .offset = 0x000E0000, .size = 0x00010000, },
++
++
++};
++
++void flash_delay()
++{
++      int i,j;
++      for(i=0;i<0x100;i++)
++              j=i*3+5;
++}
++
++int m25p80_sector_erase(__u32 address, __u32 schip_en)
++{
++      __u32 opcode;
++      __u32  status;
++      __u32 tmp;
++      int res = FLASH_ERR_OK;
++      //printf("\n-->m25p80_sector_erase");
++      if(address >= FLASH_START)
++              address-=FLASH_START;
++
++      m25p80_write_cmd(M25P80_WRITE_ENABLE, schip_en);
++      //printf("\n     m25p80_sector_erase : after we-en");
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | M25P80_SECTOR_ERASE;
++      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
++      #ifdef MIDWAY_DIAG
++              opcode|=schip_en;
++      #endif
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
++      #ifdef MIDWAY_DIAG
++              opcode|=schip_en;
++      #endif
++
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      //while(status&0xfd)
++      while(status&0x01)
++      {
++                //if((status&0x9c)!=0)
++                //    printf("  m25p80_sector_erase   Protect Status = %x\n",status);
++                write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++                tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++          flash_delay();
++          schedule();
++          //middle delay_ms(50);
++      }
++      if((status&0x02)==0x02)
++      {
++                //middle delay_ms(100);
++          m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
++      }
++      //printf("\n<--m25p80_sector_erase");
++      return res;
++}
++
++static void m25p80_write_cmd(__u8 cmd, __u32 schip_en)
++{
++      __u32 opcode,tmp;
++      __u32  status;
++
++
++
++
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE | cmd;
++
++              opcode|=g_chipen;
++
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(tmp&0x80000000)
++      {
++          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++      //////
++      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
++
++              opcode|=g_chipen;
++
++      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++      while(tmp&0x80000000)
++      {
++          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++          flash_delay();
++          schedule();
++      }
++      //middle delay_ms(130);
++      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++      //printf("\ncmd =%x  status = %x",cmd,status);
++      if(cmd==M25P80_WRITE_ENABLE)
++      {
++              //printf("\n**-->enable**  status = %x",status);
++              //middle delay_ms(100);
++                 while((status&0x03) != 2)
++                 {
++                      //if((status&0x9c)!=0)
++                      //    printf("  M25P80_WRITE_ENABLE   Protect Status = %x\n",status);
++
++                        write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++                        tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  //flash_delay();
++                              }
++                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++                     //printf("\n**enable**  status = %x",status);
++                     flash_delay();
++                     schedule();
++                     //middle delay_ms(100);
++                 }
++      }
++      else if(cmd==M25P80_WRITE_DISABLE)
++      {
++                 //while((status&0x03) == 2)
++                 //   printf("\n**disable**  status = %x",status);
++                 //middle delay_ms(100);
++                 while((status&0x03) != 0)
++                 {
++             //m25p80_write_status((status&0xfd),schip_en);
++                     write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++                     tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                      while(tmp&0x80000000)
++                      {
++                          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                          flash_delay();
++                          schedule();
++                      }
++                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++                     //printf("\n**disable**  status = %x",status);
++                     flash_delay();
++                     schedule();
++                     //middle delay_ms(50);
++                 }
++      }
++      else
++      {
++                 //while((status&0x01) !=0)
++                 while((status&0x01) !=0)
++                 {
++                        write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
++                        tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                              while(tmp&0x80000000)
++                              {
++                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
++                                  flash_delay();
++                                  schedule();
++                              }
++                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
++                     flash_delay();
++                     schedule();
++                     //middle delay_ms(50);
++                 }
++      }
++      //////
++
++      //printf("\n<--  status = %x",status);
++}
++
++static int __init init_sl2312_m25p80(void)
++{
++      int nr_parts = 0;
++      struct mtd_partition *parts;
++
++      serial_mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
++      if (!serial_mtd)
++              return NULL;
++
++      memset(serial_mtd, 0, sizeof(struct mtd_info));
++      m25p80_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)ioremap(FLASH_START, SFLASH_SIZE);
++    if (!m25p80_map.virt) {
++              printk(" failed to ioremap \n");
++              return -EIO;
++      }
++      serial_mtd = do_map_probe("map_serial", &m25p80_map);
++      if (serial_mtd) {
++              serial_mtd->owner = THIS_MODULE;
++
++      }
++
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++      nr_parts = parse_redboot_partitions(serial_mtd, &parsed_parts);
++      if (nr_parts > 0)
++              printk(KERN_NOTICE "Found RedBoot partition table.\n");
++      else if (nr_parts < 0)
++              printk(KERN_NOTICE "Error looking for RedBoot partitions.\n");
++#else
++      parsed_parts = m25p80_partitions;
++      parts = m25p80_partitions;
++      nr_parts = sizeof(m25p80_partitions)/sizeof(*parts);
++      nr_parts = sizeof(m25p80_partitions)/sizeof(*parsed_parts);
++#endif /* CONFIG_MTD_REDBOOT_PARTS */
++
++      if (nr_parts > 0)
++          add_mtd_partitions(serial_mtd, parsed_parts, nr_parts);
++      else
++          add_mtd_device(serial_mtd);
++
++      return 0;
++}
++
++static void __exit cleanup_sl2312_m25p80(void)
++{
++      if (parsed_parts)
++          del_mtd_partitions(serial_mtd);
++      else
++          del_mtd_device(serial_mtd);
++
++      map_destroy(serial_mtd);
++
++
++}
++
++module_init(init_sl2312_m25p80);
++module_exit(cleanup_sl2312_m25p80);
++
++
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Plus Chen <plus@storlink.com.tw>");
++MODULE_DESCRIPTION("MTD map driver for Storlink Sword boards");
++
+--- /dev/null
++++ b/drivers/mtd/maps/sl2312_flashmap.h
+@@ -0,0 +1,21 @@
++/*
++ * Please note that the name are used in mkflash script. Therefore
++ * don't change them.  If you want to add different partitions, you
++ * will need to modify mkflash script as well so that the end image
++ * is what you include here!
++ *
++ * Also, the 7th item is always the size, so please don't add extra
++ * spaces in the name or other items.
++ *
++ *  - Alan
++ */
++
++static struct mtd_partition sl2312_partitions[] = {
++      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
++      { name: "kernel",        offset: 0x00020000, size: 0x00100000, },
++      { name: "rootfs",        offset: 0x00120000, size: 0x00500000, },
++      { name: "rootfs_data",   offset: 0x00620000, size: 0x001A0000, },
++      { name: "VCTL",          offset: 0x007C0000, size: 0x00010000, },
++      { name: "cfg",           offset: 0x007D0000, size: 0x00020000, },
++      { name: "FIS directory", offset: 0x007F0000, size: 0x00010000, }
++};
+--- /dev/null
++++ b/drivers/mtd/maps/sl2312_flashmap.h.16MB
+@@ -0,0 +1,21 @@
++/*
++ * Please note that the name are used in mkflash script. Therefore
++ * don't change them.  If you want to add different partitions, you
++ * will need to modify mkflash script as well so that the end image
++ * is what you include here!
++ *
++ * Also, the 7th item is always the size, so please don't add extra
++ * spaces in the name or other items.
++ *
++ *  - Alan
++ */
++
++static struct mtd_partition sl2312_partitions[] = {
++      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
++      { name: "Kernel",        offset: 0x00020000, size: 0x00300000, },
++      { name: "Ramdisk",       offset: 0x00320000, size: 0x00600000, },
++      { name: "Application",   offset: 0x00920000, size: 0x00600000, },
++      { name: "VCTL",          offset: 0x00F20000, size: 0x00020000, },
++      { name: "CurConf",       offset: 0x00F40000, size: 0x000A0000, },
++      { name: "FIS directory", offset: 0x00FE0000, size: 0x00020000, }
++};
+--- /dev/null
++++ b/drivers/mtd/maps/sl2312_flashmap.h.8MB
+@@ -0,0 +1,21 @@
++/*
++ * Please note that the name are used in mkflash script. Therefore
++ * don't change them.  If you want to add different partitions, you
++ * will need to modify mkflash script as well so that the end image
++ * is what you include here!
++ *
++ * Also, the 7th item is always the size, so please don't add extra
++ * spaces in the name or other items.
++ *
++ *  - Alan
++ */
++
++static struct mtd_partition sl2312_partitions[] = {
++      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
++      { name: "Kernel",        offset: 0x00020000, size: 0x00200000, },
++      { name: "Ramdisk",       offset: 0x00220000, size: 0x00280000, },
++      { name: "Application",   offset: 0x004A0000, size: 0x00300000, },
++      { name: "VCTL",          offset: 0x007A0000, size: 0x00020000, },
++      { name: "CurConf",       offset: 0x007C0000, size: 0x00020000, },
++      { name: "FIS directory", offset: 0x007E0000, size: 0x00020000, }
++};
+--- a/drivers/mtd/mtdchar.c
++++ b/drivers/mtd/mtdchar.c
+@@ -59,6 +59,77 @@
+       enum mtd_file_modes mode;
+ };
++/***********************************************************************
++/*             Storlink SoC -- flash
++/***********************************************************************/
++#ifdef CONFIG_SL2312_SHARE_PIN
++unsigned int share_pin_flag=0;                // bit0:FLASH, bit1:UART, bit2:EMAC, bit3-4:IDE
++unsigned int check_sleep_flag=0;      // bit0:FLASH, bit1:IDE
++static spinlock_t sl2312_flash_lock = SPIN_LOCK_UNLOCKED;
++EXPORT_SYMBOL(share_pin_flag);
++int dbg=0;
++DECLARE_WAIT_QUEUE_HEAD(wq);
++extern struct wait_queue_head_t *flash_wait;
++unsigned int flash_req=0;
++void mtd_lock()
++{
++      struct task_struct *tsk = current;
++      unsigned int value ;
++      unsigned long flags;
++      flash_req = 1;
++      DECLARE_WAITQUEUE(wait, tsk);
++      add_wait_queue(&wq, &wait);
++      for(;;)
++      {
++              set_task_state(tsk, TASK_INTERRUPTIBLE);
++              spin_lock_irqsave(&sl2312_flash_lock,flags);
++              if((share_pin_flag&0x1E)){//||(check_sleep_flag&0x00000002)) {
++                      spin_unlock_irqrestore(&sl2312_flash_lock, flags);
++                      check_sleep_flag |= 0x00000001;
++                      if(dbg)
++                              printk("mtd yield %x %x\n",share_pin_flag,check_sleep_flag);
++                      wake_up_interruptible(&flash_wait);
++                      schedule();
++              }
++              else {
++                      check_sleep_flag &= ~0x01;
++                      share_pin_flag |= 0x00000001 ;                  // set share pin flag
++                      spin_unlock_irqrestore(&sl2312_flash_lock, flags);
++                      value = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
++                      value = value & (~PFLASH_SHARE_BIT) ;
++                      writel(value,IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
++                      if(dbg)
++                              printk("mtd Go %x %x\n",share_pin_flag,check_sleep_flag);
++                      tsk->state = TASK_RUNNING;
++                      remove_wait_queue(&wq, &wait);
++                      return ;
++              }
++      }
++}
++
++void mtd_unlock()
++{
++      unsigned int value ;
++      unsigned long flags;
++
++      spin_lock_irqsave(&sl2312_flash_lock,flags);            // Disable IRQ
++      value = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
++      value = value | PFLASH_SHARE_BIT ;                              // Disable Flash PADs
++      writel(value,IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
++      share_pin_flag &= ~(0x00000001);                        // clear share pin flag
++      check_sleep_flag &= ~0x00000001;
++      spin_unlock_irqrestore(&sl2312_flash_lock, flags);      // Restore IRQ
++      if (check_sleep_flag & 0x00000002)
++      {
++              check_sleep_flag &= ~(0x00000002);
++              wake_up_interruptible(&flash_wait);
++      }
++      DEBUG(MTD_DEBUG_LEVEL0, "Flash Unlock...\n");
++      flash_req = 0;
++}
++#endif
++/***********************************************************************/
++
+ static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
+ {
+       struct mtd_file_info *mfi = file->private_data;
+@@ -162,13 +233,21 @@
+       int len;
+       char *kbuf;
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_lock();                             // sl2312 share pin lock
++#endif
++
+       DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
+       if (*ppos + count > mtd->size)
+               count = mtd->size - *ppos;
+-      if (!count)
++      if (!count){
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
+               return 0;
++      }
+       /* FIXME: Use kiovec in 2.5 to lock down the user's buffers
+          and pass them directly to the MTD functions */
+@@ -178,8 +257,12 @@
+       else
+               kbuf=kmalloc(count, GFP_KERNEL);
+-      if (!kbuf)
++      if (!kbuf) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
+               return -ENOMEM;
++      }
+       while (count) {
+@@ -224,6 +307,9 @@
+                       *ppos += retlen;
+                       if (copy_to_user(buf, kbuf, retlen)) {
+                               kfree(kbuf);
++#ifdef CONFIG_SL2312_SHARE_PIN
++                              mtd_unlock();                           // sl2312 share pin lock
++#endif
+                               return -EFAULT;
+                       }
+                       else
+@@ -235,13 +321,19 @@
+                               count = 0;
+               }
+               else {
+-                      kfree(kbuf);
++                      kfree(kbuf);
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return ret;
+               }
+       }
+       kfree(kbuf);
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
+       return total_retlen;
+ } /* mtd_read */
+@@ -255,24 +347,40 @@
+       int ret=0;
+       int len;
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_lock();                             // sl2312 share pin lock
++#endif
++
+       DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
+-      if (*ppos == mtd->size)
++      if (*ppos == mtd->size){
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
+               return -ENOSPC;
++      }
+       if (*ppos + count > mtd->size)
+               count = mtd->size - *ppos;
+-      if (!count)
++      if (!count){
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
+               return 0;
++      }
+       if (count > MAX_KMALLOC_SIZE)
+               kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
+       else
+               kbuf=kmalloc(count, GFP_KERNEL);
+-      if (!kbuf)
++      if (!kbuf) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++              mtd_unlock();                           // sl2312 share pin lock
++#endif
+               return -ENOMEM;
++      }
+       while (count) {
+@@ -283,6 +391,9 @@
+               if (copy_from_user(kbuf, buf, len)) {
+                       kfree(kbuf);
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
+               }
+@@ -323,11 +434,17 @@
+               }
+               else {
+                       kfree(kbuf);
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return ret;
+               }
+       }
+       kfree(kbuf);
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
+       return total_retlen;
+ } /* mtd_write */
+@@ -381,36 +498,67 @@
+       u_long size;
+       struct mtd_info_user info;
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_lock();                             // sl2312 share pin lock
++#endif
++
+       DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
+       size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
+       if (cmd & IOC_IN) {
+               if (!access_ok(VERIFY_READ, argp, size))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+       }
+       if (cmd & IOC_OUT) {
+               if (!access_ok(VERIFY_WRITE, argp, size))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+       }
+       switch (cmd) {
+       case MEMGETREGIONCOUNT:
+               if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+               break;
+       case MEMGETREGIONINFO:
+       {
+               struct region_info_user ur;
+-              if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
++              if (copy_from_user(&ur, argp, sizeof(struct region_info_user))) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+-              if (ur.regionindex >= mtd->numeraseregions)
++              if (ur.regionindex >= mtd->numeraseregions) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EINVAL;
++              }
+               if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
+-                              sizeof(struct mtd_erase_region_info)))
++                              sizeof(struct mtd_erase_region_info))) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+               break;
+       }
+@@ -433,7 +581,12 @@
+               struct erase_info *erase;
+               if(!(file->f_mode & 2))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EPERM;
++              }
+               erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
+               if (!erase)
+@@ -447,6 +600,9 @@
+                       if (copy_from_user(&erase->addr, argp,
+                                   sizeof(struct erase_info_user))) {
+                               kfree(erase);
++#ifdef CONFIG_SL2312_SHARE_PIN
++                              mtd_unlock();                           // sl2312 share pin lock
++#endif
+                               return -EFAULT;
+                       }
+                       erase->mtd = mtd;
+@@ -484,14 +640,26 @@
+               struct mtd_oob_buf buf;
+               struct mtd_oob_ops ops;
+-              if(!(file->f_mode & 2))
++              if(!(file->f_mode & 2)) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EPERM;
++              }
+-              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
++              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+-              if (buf.length > 4096)
++              if (buf.length > 4096) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EINVAL;
++              }
+               if (!mtd->write_oob)
+                       ret = -EOPNOTSUPP;
+@@ -499,8 +667,12 @@
+                       ret = access_ok(VERIFY_READ, buf.ptr,
+                                       buf.length) ? 0 : EFAULT;
+-              if (ret)
++              if (ret) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return ret;
++              }
+               ops.ooblen = buf.length;
+               ops.ooboffs = buf.start & (mtd->oobsize - 1);
+@@ -536,19 +708,35 @@
+               struct mtd_oob_buf buf;
+               struct mtd_oob_ops ops;
+-              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
++              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+-              if (buf.length > 4096)
++              if (buf.length > 4096) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EINVAL;
++              }
+-              if (!mtd->read_oob)
++              if (!mtd->read_oob) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       ret = -EOPNOTSUPP;
++              }
+               else
+                       ret = access_ok(VERIFY_WRITE, buf.ptr,
+                                       buf.length) ? 0 : -EFAULT;
+-              if (ret)
++              if (ret) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return ret;
++              }
+               ops.ooblen = buf.length;
+               ops.ooboffs = buf.start & (mtd->oobsize - 1);
+@@ -580,7 +768,12 @@
+               struct erase_info_user info;
+               if (copy_from_user(&info, argp, sizeof(info)))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+               if (!mtd->lock)
+                       ret = -EOPNOTSUPP;
+@@ -594,7 +787,12 @@
+               struct erase_info_user info;
+               if (copy_from_user(&info, argp, sizeof(info)))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+               if (!mtd->unlock)
+                       ret = -EOPNOTSUPP;
+@@ -629,11 +827,21 @@
+               loff_t offs;
+               if (copy_from_user(&offs, argp, sizeof(loff_t)))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+               if (!mtd->block_isbad)
+                       ret = -EOPNOTSUPP;
+               else
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return mtd->block_isbad(mtd, offs);
++              }
+               break;
+       }
+@@ -642,11 +850,21 @@
+               loff_t offs;
+               if (copy_from_user(&offs, argp, sizeof(loff_t)))
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+               if (!mtd->block_markbad)
+                       ret = -EOPNOTSUPP;
+               else
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return mtd->block_markbad(mtd, offs);
++              }
+               break;
+       }
+@@ -654,8 +872,12 @@
+       case OTPSELECT:
+       {
+               int mode;
+-              if (copy_from_user(&mode, argp, sizeof(int)))
++              if (copy_from_user(&mode, argp, sizeof(int))) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
++              }
+               mfi->mode = MTD_MODE_NORMAL;
+@@ -670,7 +892,12 @@
+       {
+               struct otp_info *buf = kmalloc(4096, GFP_KERNEL);
+               if (!buf)
++              {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -ENOMEM;
++              }
+               ret = -EOPNOTSUPP;
+               switch (mfi->mode) {
+               case MTD_MODE_OTP_FACTORY:
+@@ -701,12 +928,24 @@
+       {
+               struct otp_info info;
+-              if (mfi->mode != MTD_MODE_OTP_USER)
++              if (mfi->mode != MTD_MODE_OTP_USER) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EINVAL;
+-              if (copy_from_user(&info, argp, sizeof(info)))
++              }
++              if (copy_from_user(&info, argp, sizeof(info))) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EFAULT;
+-              if (!mtd->lock_user_prot_reg)
++              }
++              if (!mtd->lock_user_prot_reg) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                      mtd_unlock();                           // sl2312 share pin lock
++#endif
+                       return -EOPNOTSUPP;
++              }
+               ret = mtd->lock_user_prot_reg(mtd, info.start, info.length);
+               break;
+       }
+@@ -742,8 +981,12 @@
+                       break;
+               case MTD_MODE_RAW:
+-                      if (!mtd->read_oob || !mtd->write_oob)
++                      if (!mtd->read_oob || !mtd->write_oob) {
++#ifdef CONFIG_SL2312_SHARE_PIN
++                              mtd_unlock();                           // sl2312 share pin lock
++#endif
+                               return -EOPNOTSUPP;
++                      }
+                       mfi->mode = arg;
+               case MTD_MODE_NORMAL:
+@@ -766,6 +1009,10 @@
+               ret = -ENOTTY;
+       }
++#ifdef CONFIG_SL2312_SHARE_PIN
++      mtd_unlock();                           // sl2312 share pin lock
++#endif
++
+       return ret;
+ } /* memory_ioctl */
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -44,6 +44,13 @@
+         This enables the driver for the autronix autcpu12 board to
+         access the SmartMediaCard.
++config MTD_NAND_SL2312
++      tristate "NAND Flash device on Storlink board"
++      depends on ARM && MTD_NAND && ARCH_SL2312
++      help
++        This enables the driver for the Storlink board to
++        access the nand device.
++
+ config MTD_NAND_EDB7312
+       tristate "Support for Cirrus Logic EBD7312 evaluation board"
+       depends on ARCH_EDB7312
+--- /dev/null
++++ b/drivers/mtd/nand/sl2312-flash-nand.c
+@@ -0,0 +1,2287 @@
++/*
++ *  drivers/mtd/sl2312.c
++ *
++ * $Id: sl2312-flash-nand.c,v 1.5 2006/06/15 07:02:29 middle Exp $
++ *
++ * Copyright (C) 2001 Toshiba Corporation
++ *
++ * 2003 (c) MontaVista Software, Inc. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ *
++ */
++
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/nand_ecc.h>
++#include <linux/mtd/partitions.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/arch/sl2312.h>
++#include "sl2312-flash-nand.h"
++
++
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/mtd/compatmac.h>
++#include <linux/interrupt.h>
++#include <linux/bitops.h>
++
++
++/*
++ * NAND low-level MTD interface functions
++ */
++static void sl2312_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
++static void sl2312_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
++static int sl2312_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
++
++static int sl2312_nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
++static int sl2312_nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
++static int sl2312_nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
++static int sl2312_nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
++static int sl2312_nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
++                         size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
++static int sl2312_nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);
++static int sl2312_nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
++                      unsigned long count, loff_t to, size_t * retlen);
++static int sl2312_nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
++                      unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
++static int sl2312_nand_erase (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
++static void sl2312_nand_sync (struct mtd_info *mtd);
++static int sl2312_nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  struct nand_oobinfo *oobsel);
++static int sl2312_nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt);
++static int sl2312_nand_erase_block(struct mtd_info *mtd, int page);
++
++/*
++ * MTD structure for sl2312 NDFMC
++ */
++static struct mtd_info *sl2312_mtd = NULL;
++static int nand_page=0,nand_col=0;
++
++/* Define default oob placement schemes for large and small page devices */
++static struct nand_oobinfo nand_oob_8 = {
++      .useecc = MTD_NANDECC_AUTOPLACE,
++      .eccbytes = 3,
++      .eccpos = {0, 1, 2},
++      .oobfree = { {3, 2}, {6, 2} }
++};
++
++static struct nand_oobinfo nand_oob_16 = {
++      .useecc = MTD_NANDECC_AUTOPLACE,
++      .eccbytes = 6,
++      .eccpos = {0, 1, 2, 3, 6, 7},
++      .oobfree = { {8, 8} }
++};
++
++static struct nand_oobinfo nand_oob_64 = {
++      .useecc = MTD_NANDECC_AUTOPLACE,
++      .eccbytes = 24,
++      .eccpos = {
++              40, 41, 42, 43, 44, 45, 46, 47,
++              48, 49, 50, 51, 52, 53, 54, 55,
++              56, 57, 58, 59, 60, 61, 62, 63},
++      .oobfree = { {2, 38} }
++};
++
++
++/*
++ * Define partitions for flash device
++ */
++/* the base address of FLASH control register */
++#define FLASH_CONTROL_BASE_ADDR           (IO_ADDRESS(SL2312_FLASH_CTRL_BASE))
++#define SL2312_GLOBAL_BASE_ADDR     (IO_ADDRESS(SL2312_GLOBAL_BASE))
++//#define SL2312_FLASH_BASE_ADDR      (IO_ADDRESS(SL2312_FLASH_BASE))
++#define SL2312_FLASH_BASE_ADDR       FLASH_VADDR(SL2312_FLASH_BASE)
++static unsigned int CHIP_EN;
++/* define read/write register utility */
++//#define FLASH_READ_REG(offset)                      (__raw_readl(offset+FLASH_CONTROL_BASE_ADDR))
++//#define FLASH_WRITE_REG(offset,val)         (__raw_writel(val,offset+FLASH_CONTROL_BASE_ADDR))
++//#define FLASH_READ_DATA(offset)                     (__raw_readb(offset+SL2312_FLASH_BASE_ADDR))
++//#define FLASH_WRITE_DATA(offset,val)        (__raw_writeb(val,offset+SL2312_FLASH_BASE_ADDR))
++
++unsigned int FLASH_READ_REG(unsigned int addr)
++{
++    unsigned int *base;
++    unsigned int data;
++
++    base = (unsigned int *)(FLASH_CONTROL_BASE_ADDR + addr);
++    data = *base;
++    return (data);
++}
++
++void FLASH_WRITE_REG(unsigned int addr,unsigned int data)
++{
++    unsigned int *base;
++
++    base = (unsigned int *)(FLASH_CONTROL_BASE_ADDR + addr);
++    *base = data;
++    return;
++}
++
++unsigned int FLASH_READ_DATA(unsigned int addr)
++{
++    unsigned char *base;
++    unsigned int data;
++
++    base = (unsigned char *)(SL2312_FLASH_BASE_ADDR + addr);
++    data = *base;
++    return (data);
++}
++
++void FLASH_WRITE_DATA(unsigned int addr,unsigned int data)
++{
++    unsigned char *base;
++
++    base = (unsigned char *)(SL2312_FLASH_BASE_ADDR + addr);
++    *base = data;
++    return;
++}
++
++/* the offset of FLASH control register */
++enum NFLASH_REGISTER {
++      NFLASH_ID                       = 0x0000,
++      NFLASH_STATUS                   = 0x0008,
++      NFLASH_TYPE                     = 0x000c,
++      NFLASH_ACCESS                   = 0x0030,
++      NFLASH_COUNT                    = 0x0034,
++      NFLASH_CMD_ADDR                 = 0x0038,
++      NFLASH_ADDRESS                  = 0x003C,
++      NFLASH_DATA                             = 0x0040,
++      NFLASH_TIMING                   = 0x004C,
++      NFLASH_ECC_STATUS               = 0x0050,
++      NFLASH_ECC_CONTROL              = 0x0054,
++      NFLASH_ECC_OOB                  = 0x005c,
++      NFLASH_ECC_CODE_GEN0    = 0x0060,
++      NFLASH_ECC_CODE_GEN1    = 0x0064,
++      NFLASH_ECC_CODE_GEN2    = 0x0068,
++      NFLASH_ECC_CODE_GEN3    = 0x006C,
++      NFLASH_FIFO_CONTROL             = 0x0070,
++      NFLASH_FIFO_STATUS              = 0x0074,
++      NFLASH_FIFO_ADDRESS             = 0x0078,
++      NFLASH_FIFO_DATA                = 0x007c,
++};
++
++
++
++//#define FLASH_BASE  FLASH_CONTROL_BASE_ADDR
++//#define FLASH_SIZE  0x00800000 //INTEGRATOR_FLASH_SIZE
++
++//#define FLASH_PART_SIZE 8388608
++
++//static unsigned int flash_indirect_access = 0;
++
++
++#ifdef CONFIG_SL2312_SHARE_PIN
++void sl2312flash_enable_nand_flash(void)
++{
++    unsigned int    reg_val;
++
++    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
++    reg_val = reg_val & 0xfffffffb;
++    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
++    return;
++}
++
++void sl2312flash_disable_nand_flash(void)
++{
++    unsigned int    reg_val;
++
++    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
++    reg_val = reg_val | 0x00000004;
++    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
++    return;
++}
++#endif
++
++extern struct nand_oobinfo jffs2_oobinfo;
++/*
++ * Define partitions for flash devices
++ */
++
++static struct mtd_partition sl2312_partitions[] = {
++      { name: "RedBoot", offset: 0x00000000, size: 0x0020000, },
++      { name: "Kernel", offset: 0x00020000, size: 0x00200000, },
++      { name: "Ramdisk", offset: 0x00220000, size: 0x00280000, },
++      { name: "Application", offset: 0x004A0000, size: 0x00320000, },
++      { name: "VCTL", offset: 0x007C0000, size: 0x20000, },
++      { name: "CurConf", offset: 0x007E0000, size: 0x20000, },
++      { name: "FIS directory", offset: 0x007e0000, size: 0x00020000, }
++
++};
++
++
++/*
++ *    hardware specific access to control-lines
++*/
++static void sl2312_hwcontrol(struct mtd_info *mtd, int cmd)
++{
++
++      return ;
++}
++
++static int sl2312_nand_scan_bbt(struct mtd_info *mtd)
++{
++      return 0;
++}
++
++/**
++ * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
++ * @mtd:      MTD device structure
++ * @ofs:      offset relative to mtd start
++ */
++static int sl2312_nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
++{
++      /* Check for invalid offset */
++      if (ofs > mtd->size)
++              return -EINVAL;
++
++      return sl2312_nand_block_checkbad (mtd, ofs, 1, 0);
++}
++
++/**
++ * nand_block_checkbad - [GENERIC] Check if a block is marked bad
++ * @mtd:      MTD device structure
++ * @ofs:      offset from device start
++ * @getchip:  0, if the chip is already selected
++ * @allowbbt: 1, if its allowed to access the bbt area
++ *
++ * Check, if the block is bad. Either by reading the bad block table or
++ * calling of the scan function.
++ */
++
++static int sl2312_nand_erase_block(struct mtd_info *mtd, int page)
++{
++      int opcode;
++      /* Send commands to erase a page */
++              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
++
++              if(mtd->oobblock > 528)
++                  FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff21);  // 3 address & 2 command
++              else
++                  FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff11);  // 2 address & 2 command
++
++              FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x0000d060); // write read id command
++              FLASH_WRITE_REG(NFLASH_ADDRESS, page); //write address 0x00
++
++
++
++              /* read maker code */
++              opcode = 0x80003000|DWIDTH|CHIP_EN; //set start bit & 8bits write command
++              FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
++
++              while(opcode&0x80000000) //polling flash access 31b
++              {
++           opcode=FLASH_READ_REG(NFLASH_ACCESS);
++           //sl2312_flash_delay();
++           schedule();
++           //cond_resched();
++              }
++}
++
++void sl2312_flash_delay(void)
++{
++      int i;
++
++      for(i=0; i<50; i++)
++           i=i;
++}
++
++static int sl2312_nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
++{
++      struct nand_chip *this = mtd->priv;
++
++      if (!this->bbt)
++              return this->block_bad(mtd, ofs, getchip);
++
++      /* Return info from the table */
++      return nand_isbad_bbt (mtd, ofs, allowbbt);
++}
++
++/**
++ * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
++ * @mtd:      MTD device structure
++ * @ofs:      offset relative to mtd start
++ */
++static int sl2312_nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
++{
++      struct nand_chip *this = mtd->priv;
++      int ret;
++
++        if ((ret = sl2312_nand_block_isbad(mtd, ofs))) {
++              /* If it was bad already, return success and do nothing. */
++              if (ret > 0)
++                      return 0;
++              return ret;
++        }
++
++      return this->block_markbad(mtd, ofs);
++}
++
++/*
++ *    Get chip for selected access
++ */
++static inline void sl2312_nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state, int *erase_state)
++{
++
++      DECLARE_WAITQUEUE (wait, current);
++
++      /*
++       * Grab the lock and see if the device is available
++       * For erasing, we keep the spinlock until the
++       * erase command is written.
++      */
++retry:
++      spin_lock_bh (&this->chip_lock);
++
++      if (this->state == FL_READY) {
++              this->state = new_state;
++              if (new_state != FL_ERASING)
++                      spin_unlock_bh (&this->chip_lock);
++              return;
++      }
++
++      if (this->state == FL_ERASING) {
++              if (new_state != FL_ERASING) {
++                      this->state = new_state;
++                      spin_unlock_bh (&this->chip_lock);
++                      this->select_chip(mtd, 0);      /* select in any case */
++                      this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
++                      return;
++              }
++      }
++
++      set_current_state (TASK_UNINTERRUPTIBLE);
++      add_wait_queue (&this->wq, &wait);
++      spin_unlock_bh (&this->chip_lock);
++      schedule ();
++      remove_wait_queue (&this->wq, &wait);
++      goto retry;
++}
++
++/*
++*     read device ready pin
++*/
++static int sl2312_device_ready(struct mtd_info *mtd)
++{
++      int ready;
++
++      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
++      FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000070); //set only command no address and two data
++
++      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000070); //write read status command
++
++
++      ready = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
++      FLASH_WRITE_REG(NFLASH_ACCESS, ready);
++
++      while(ready&0x80000000) //polling flash access 31b
++    {
++        ready=FLASH_READ_REG(NFLASH_ACCESS);
++        //sl2312_flash_delay();
++              schedule();
++    }
++    FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++              ready=FLASH_READ_REG(NFLASH_DATA)&0xff;
++      return ready;
++}
++void sl2312_enable_hwecc(struct mtd_info *mtd, int mode)
++{
++      /* reset first */
++      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
++
++}
++
++
++void sl2312_device_setup(void)
++{
++
++}
++static u_char sl2312_nand_read_byte(struct mtd_info *mtd)
++{
++
++        unsigned int    data=0, page=0, col=0, tmp, i;
++
++        printk ("**************************sl2312_nand_read_byte !! \n");
++        //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
++        //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
++        page = nand_page;
++        col  = nand_col;
++        for(i=0;i<(mtd->oobblock+mtd->oobsize);i++)
++        {
++              if(i==col)
++                              data = FLASH_READ_DATA(page*mtd->oobblock +i);
++                      else
++                              tmp = FLASH_READ_DATA(page*mtd->oobblock +i);
++        }
++        return data&0xff;
++}
++
++static void sl2312_nand_write_byte(struct mtd_info *mtd, u_char byte)
++{
++        //struct nand_chip *this = mtd->priv;
++        unsigned int    page=0, col=0, i;
++        u_char *databuf,oobbuf[mtd->oobsize];
++        size_t  retlen;
++        retlen=0;
++              printk ("********************sl2312_nand_write_byte !! \n");
++              page = nand_page;
++        col  = nand_col;
++              databuf = kmalloc (mtd->oobsize+mtd->oobblock,GFP_KERNEL);
++
++              if (!databuf) {
++                      printk ("sl2312_nand_write_byte : Unable to allocate SL2312 NAND MTD device structure.\n");
++
++              }
++
++               for(i=0;i<(mtd->oobblock+mtd->oobsize);i++)
++              databuf[i] = FLASH_READ_DATA(page*mtd->oobblock +i);
++
++        databuf[col] = byte;
++        sl2312_nand_write_ecc (mtd, page, mtd->oobblock, &retlen, databuf, oobbuf, NULL);
++
++}
++
++static void sl2312_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
++{
++      int i, page=0,col=0;
++      struct nand_chip *this = mtd->priv;
++      u_char *databuf, *oobbuf;
++        size_t  retlen;
++        retlen=0;
++
++
++              printk ("***********************sl2312_nand_write_buf !! \n");
++              databuf = &(this->data_buf[0]);
++              oobbuf = &(this->data_buf[mtd->oobblock]);
++              for (i = 0; i < mtd->oobsize; i++)
++                      oobbuf[i] = 0xff;
++
++      if(len < mtd->oobblock)
++      {
++              //addr = FLASH_READ_REG(NFLASH_ADDRESS);
++              //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
++              //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
++              page = nand_page;
++        col  = nand_col;
++
++              sl2312_nand_read_ecc (mtd, page, mtd->oobblock , &retlen, databuf, oobbuf, NULL);
++
++        for(i=col;i<len;i++)
++              databuf[col+i] = buf[i];
++
++        sl2312_nand_write_ecc (mtd, page, mtd->oobblock, &retlen, databuf, oobbuf, NULL);
++
++      }
++
++}
++
++static void sl2312_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
++{
++      int i, page=0,col=0,addr=0,tmp=0;
++      //struct nand_chip *this = mtd->priv;
++      printk ("********************sl2312_nand_read_buf !! \n");
++      if(len < mtd->oobblock)
++      {
++              //addr = FLASH_READ_REG(NFLASH_ADDRESS);
++              //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
++              //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
++              page = nand_page;
++        col  = nand_col;
++              for (i=col; i<((mtd->oobblock+mtd->oobsize)-col); i++)
++              {
++                      if(i<len)
++                              buf[i] = FLASH_READ_DATA(addr+i);
++                      else
++                              tmp = FLASH_READ_DATA(addr+i);
++              }
++      }
++}
++
++static int sl2312_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
++{
++      int i;
++      //struct nand_chip *this = mtd->priv;
++      u_char *datatmp, *oobtmp;
++      size_t  retlen;
++      retlen=0;
++
++      datatmp = kmalloc (mtd->oobblock,GFP_KERNEL);
++      oobtmp = kmalloc (mtd->oobsize,GFP_KERNEL);
++
++      if ((!datatmp)||(!oobtmp)) {
++              printk ("sl2312_nand_verify_buf : Unable to allocate SL2312 NAND MTD device structure.\n");
++
++      }
++      //page = nand_page;
++      for(i=0;i<mtd->oobblock;i++)
++              datatmp[i] = FLASH_READ_DATA(nand_page*mtd->oobblock +i);
++      /* read oobdata */
++      for (i = 0; i <  mtd->oobsize; i++)
++              oobtmp[i] = FLASH_READ_DATA(nand_page*mtd->oobblock + mtd->oobblock + i);
++
++      if(len==mtd->oobblock)
++      {
++              for (i=0; i<len; i++)
++              {
++                      if (buf[i] != datatmp[i])
++                      {
++                              kfree(datatmp);
++                              kfree(oobtmp);
++                              printk("Data verify error -> page: %x, byte: %x \n",nand_page,i);
++                              return i;
++                      }
++              }
++      }
++      else if(len == mtd->oobsize)
++      {
++              for (i=0; i<len; i++)
++              {
++                      if (buf[i] != oobtmp[i])
++                      {
++                              kfree(datatmp);
++                              kfree(oobtmp);
++                              printk("OOB verify error -> page: %x, byte: %x \n",nand_page,i);
++                              return i;
++                      }
++              }
++      }
++      else
++      {
++              printk (KERN_WARNING "sl2312_nand_verify_buf : verify length not match 0x%08x\n", len);
++              kfree(datatmp);
++              kfree(oobtmp);
++              return -1;
++      }
++
++      kfree(datatmp);
++      kfree(oobtmp);
++      return 0;
++}
++
++/*
++ * Send command to NAND device
++ */
++static void sl2312_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
++{
++      register struct nand_chip *this = mtd->priv;
++      int opcode;
++
++
++      /*
++       * program and erase have their own busy handlers
++       * status and sequential in needs no delay
++      */
++      switch (command) {
++
++      case NAND_CMD_PAGEPROG:
++      case NAND_CMD_ERASE1:
++      case NAND_CMD_ERASE2:
++      case NAND_CMD_SEQIN:
++      case NAND_CMD_STATUS:
++      case NAND_CMD_READ0:
++
++              /*
++               * Write out the command to the device.
++               */
++              if (column != -1 || page_addr != -1) {
++
++                      /* Serially input address */
++                      if (column != -1)
++                              //FLASH_WRITE_REG(NFLASH_ADDRESS,column);
++                              nand_col=column;
++
++                      opcode = FLASH_READ_REG(NFLASH_ADDRESS);
++
++                      if (page_addr != -1)
++                              //FLASH_WRITE_REG(NFLASH_ADDRESS,opcode|(page_addr<<8));
++                              nand_page = page_addr;
++
++              }
++              return;
++
++      case NAND_CMD_RESET:
++              if (this->dev_ready)
++                      break;
++              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
++              FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff70); //set only command and no other data
++              FLASH_WRITE_REG(NFLASH_CMD_ADDR, NAND_CMD_RESET); //write reset command
++
++              opcode = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
++              FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
++
++              while(opcode&0x80000000) //polling flash access 31b
++              {
++           opcode=FLASH_READ_REG(NFLASH_ACCESS);
++           //sl2312_flash_delay();
++           schedule();
++              }
++              while ( !(sl2312_device_ready(mtd) & 0x40));
++              {
++                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++                      //sl2312_flash_delay();
++                      schedule();
++                      return;
++              }
++      /* This applies to read commands */
++      default:
++              /*
++               * If we don't have access to the busy pin, we apply the given
++               * command delay
++              */
++              if (!this->dev_ready) {
++                      udelay (this->chip_delay);
++                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++                      return;
++              }
++      }
++
++      /* wait until command is processed */
++      while (!this->dev_ready(mtd));
++
++}
++/*Add function*/
++static void nand_read_id(int chip_no, unsigned char *id)
++{
++      unsigned int opcode, i;
++
++      if(chip_no==0)
++              CHIP_EN = NFLASH_CHIP0_EN;
++      else
++              CHIP_EN = NFLASH_CHIP1_EN;
++
++      opcode = FLASH_READ_REG(NFLASH_TYPE);
++
++      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
++      if((opcode&0x00000300)<=0x00000100)
++          FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000100); //set only command & address and two data
++      else
++          FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000300); //set only command & address and 4 data
++
++      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000090); //write read id command
++      FLASH_WRITE_REG(NFLASH_ADDRESS, 0x00000000); //write address 0x00
++
++      /* read maker code */
++      opcode = 0x80002000|DWIDTH|CHIP_EN;//|chip0_en; //set start bit & 8bits read command
++      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
++      opcode=FLASH_READ_REG(NFLASH_ACCESS);
++              while(opcode&0x80000000) //polling flash access 31b
++              {
++           opcode=FLASH_READ_REG(NFLASH_ACCESS);
++           //sl2312_flash_delay();
++           schedule();
++              }
++
++    opcode = FLASH_READ_REG(NFLASH_DATA);
++    if(DWIDTH==NFLASH_WiDTH16)
++    {
++                      id[0] = opcode&0xff;
++                      id[1] = (opcode&0xff00)>>8;
++    }
++    else
++    {
++          id[0] = opcode&0xff;
++          opcode = 0x80002000|DWIDTH|CHIP_EN;//|chip0_en; //set start bit & 8bits read command
++                      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
++                      opcode=FLASH_READ_REG(NFLASH_ACCESS);
++                      while(opcode&0x80000000) //polling flash access 31b
++              {
++             opcode=FLASH_READ_REG(NFLASH_ACCESS);
++             //sl2312_flash_delay();
++             schedule();
++              }
++              opcode = FLASH_READ_REG(NFLASH_DATA);
++                      id[1] = (opcode&0xff00)>>8;
++
++                      opcode=FLASH_READ_REG(NFLASH_TYPE);
++                      if((opcode&0x300)>0x100)
++                      {
++                          for(i=0;i<2;i++)
++                          {
++                                      //data cycle 3 & 4 ->not use
++                                      opcode = 0x80002000|DWIDTH|CHIP_EN;//set start bit & 8bits read command
++                                      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
++                                      opcode=FLASH_READ_REG(NFLASH_ACCESS);
++                                      while(opcode&0x80000000) //polling flash access 31b
++                                      {
++                                 opcode=FLASH_READ_REG(NFLASH_ACCESS);
++                                 //sl2312_flash_delay();
++                                 schedule();
++                                      }
++
++                                      opcode=FLASH_READ_REG(NFLASH_DATA);
++                                      id[2+i] = (opcode&(0xff0000<<i*8))>>(8*(2+i));
++                          }
++                      }
++    }
++    FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++}
++
++/*
++ * NAND erase a block
++ */
++static int sl2312_nand_erase (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
++{
++      int page, len, status, pages_per_block, ret, chipnr;
++      struct nand_chip *this = mtd->priv;
++
++      DEBUG (MTD_DEBUG_LEVEL3,
++             "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
++
++      /* Start address must align on block boundary */
++      if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
++              return -EINVAL;
++      }
++
++      /* Length must align on block boundary */
++      if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
++              return -EINVAL;
++      }
++
++      /* Do not allow erase past end of device */
++      if ((instr->len + instr->addr) > mtd->size) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
++              return -EINVAL;
++      }
++
++      instr->fail_addr = 0xffffffff;
++
++      /* Grab the lock and see if the device is available */
++      sl2312_nand_get_chip (this, mtd, FL_ERASING, NULL);
++
++      /* Shift to get first page */
++      page = (int) (instr->addr >> this->page_shift);
++      chipnr = (int) (instr->addr >> this->chip_shift);
++
++      /* Calculate pages in each block */
++      pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
++
++      /* Select the NAND device */
++      //this->select_chip(mtd, chipnr);
++      this->select_chip(mtd, 0);
++
++      /* Check the WP bit */
++      /* Check, if it is write protected */
++      status = sl2312_device_ready(mtd);
++      if (!(status & 0x80)) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
++              instr->state = MTD_ERASE_FAILED;
++              goto erase_exit;
++      }
++
++      /* Loop through the pages */
++      len = instr->len;
++
++      instr->state = MTD_ERASING;
++
++      while (len) {
++              /* Check if we have a bad block, we do not erase bad blocks ! */
++              if (this->block_bad(mtd, ((loff_t) page) << this->page_shift, 0)) {
++                      printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
++                      //instr->state = MTD_ERASE_FAILED;
++                      //goto erase_exit;
++              }
++
++              /* Invalidate the page cache, if we erase the block which contains
++                 the current cached page */
++              if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
++                      this->pagebuf = -1;
++              /////////
++
++              ///* Send commands to erase a page */
++              //FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
++          //
++              //if(mtd->oobblock > 528)
++              //    FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff21);  // 3 address & 2 command
++              //else
++              //    FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff11);  // 2 address & 2 command
++              //
++              //FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x0000d060); // write read id command
++              //FLASH_WRITE_REG(NFLASH_ADDRESS, page); //write address 0x00
++              //
++              //
++              //
++              ///* read maker code */
++              //opcode = 0x80003000|DWIDTH|CHIP_EN; //set start bit & 8bits write command
++              //FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
++              //
++              //while(opcode&0x80000000) //polling flash access 31b
++              //{
++        //   opcode=FLASH_READ_REG(NFLASH_ACCESS);
++        //   //sl2312_flash_delay();
++        //   schedule();
++        //   //cond_resched();
++              //}
++              sl2312_nand_erase_block(mtd, page);
++              //////////////
++              status = this->waitfunc (mtd, this, FL_ERASING);
++              /* See if block erase succeeded */
++              if (status & 0x01) {
++                      DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
++                      instr->state = MTD_ERASE_FAILED;
++                      instr->fail_addr = (page << this->page_shift);
++                      goto erase_exit;
++              }
++
++              /* Increment page address and decrement length */
++              len -= (1 << this->phys_erase_shift);
++              page += pages_per_block;
++
++              /* Check, if we cross a chip boundary */
++              if (len && !(page & this->pagemask)) {
++                      chipnr++;
++                      this->select_chip(mtd, 0);
++                      this->select_chip(mtd, 0);
++              }
++              //sl2312_flash_delay();
++           schedule();
++           //cond_resched();
++      }
++      instr->state = MTD_ERASE_DONE;
++
++erase_exit:
++      /* De-select the NAND device */
++      this->select_chip(mtd, 0);
++      spin_unlock_bh (&this->chip_lock);
++
++      ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;;
++      /* Do call back function */
++      if (!ret && instr->callback)
++              instr->callback (instr);
++
++      /* The device is ready */
++      spin_lock_bh (&this->chip_lock);
++      this->state = FL_READY;
++      spin_unlock_bh (&this->chip_lock);
++      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++      /* Return more or less happy */
++      return ret;
++}
++
++static void sl2312_nand_select_chip(struct mtd_info *mtd, int chip)
++{
++      //struct nand_chip *this = mtd->priv;
++
++      switch(chip) {
++      case -1:
++              CHIP_EN = NFLASH_CHIP0_EN;
++              break;
++      case 0:
++              CHIP_EN = NFLASH_CHIP0_EN;
++              break;
++      case 1:
++              CHIP_EN = NFLASH_CHIP1_EN;
++              break;
++      default:
++                      CHIP_EN = NFLASH_CHIP0_EN;
++                      break;
++      }
++}
++
++/**
++ * nand_default_block_markbad - [DEFAULT] mark a block bad
++ * @mtd:      MTD device structure
++ * @ofs:      offset from device start
++ *
++ * This is the default implementation, which can be overridden by
++ * a hardware specific driver.
++*/
++static int sl2312_nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
++{
++      struct nand_chip *this = mtd->priv;
++      u_char buf[2] = {0, 0};
++      size_t  retlen;
++      int block;
++
++      /* Get block number */
++      block = ((int) ofs) >> this->bbt_erase_shift;
++      this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
++
++      /* Do we have a flash based bad block table ? */
++      if (this->options & NAND_USE_FLASH_BBT)
++              return nand_update_bbt (mtd, ofs);
++
++      /* We write two bytes, so we dont have to mess with 16 bit access */
++      ofs += mtd->oobsize + (this->badblockpos & ~0x01);
++      return sl2312_nand_write_oob (mtd, ofs , 2, &retlen, buf);
++}
++
++/* Appropriate chip should already be selected */
++static int sl2312_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)//(struct mtd_info *mtd, unsigned long page, )
++{
++      u_char *buf, *oobbuf;
++      size_t  retlen;
++      unsigned long page, chipnr;
++      struct nand_chip *this = mtd->priv;
++
++      if (getchip) {
++              page = (int)(ofs >> this->page_shift);
++              chipnr = (int)(ofs >> this->chip_shift);
++
++              /* Grab the lock and see if the device is available */
++              sl2312_nand_get_chip (this, mtd, FL_READING, NULL);
++              /* Select the NAND device */
++              this->select_chip(mtd, chipnr);
++      } else
++              page = (int) ofs;
++
++      buf = kmalloc (mtd->oobblock,GFP_KERNEL);
++      oobbuf = kmalloc (mtd->oobsize,GFP_KERNEL);
++
++      if ((!buf)||(!oobbuf)) {
++              printk ("sl2312_nand_block_bad : Unable to allocate SL2312 NAND MTD device structure.\n");
++
++      }
++
++      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , &retlen, buf, oobbuf, NULL);
++
++
++      if(((mtd->oobblock < 528)&&(oobbuf[5] != 0xff))||((mtd->oobblock > 528)&&(oobbuf[0] != 0xff)))
++      {
++              kfree(buf);
++              kfree(oobbuf);
++              return 1;
++      }
++
++      kfree(buf);
++      kfree(oobbuf);
++      return 0;
++}
++
++/*
++*     Use NAND read ECC
++*/
++static int sl2312_nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
++{
++      return sl2312_nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
++}
++
++/*
++ * NAND read with ECC
++ */
++static int sl2312_nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
++                        size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
++{
++      int j, col, page, opcode, i;
++      int end=0;//, ecc=0;//, end_page=0;
++      int erase_state = 0;
++      int read = 0, oob = 0, ecc_failed = 0;//, ecc_status = 0
++      struct nand_chip *this = mtd->priv;
++      u_char *data_poi, *oob_data = oob_buf;
++      //u_char ecc_calc[6];
++      //u_char ecc_code[6];
++      int     eccmode;
++      int     *oob_config;
++
++
++
++      // use chip default if zero
++      if (oobsel == NULL)
++              oobsel = &mtd->oobinfo;
++
++      eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
++      oob_config = oobsel->eccpos;
++
++      DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
++
++      /* Do not allow reads past end of device */
++      if ((from + len) > mtd->size) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
++              *retlen = 0;
++              return -EINVAL;
++      }
++
++      /* Grab the lock and see if the device is available */
++      sl2312_nand_get_chip (this, mtd ,FL_READING, &erase_state);
++
++      /* Select the NAND device */
++      this->select_chip(mtd, 0);
++
++      /* First we calculate the starting page */
++      page = from >> this->page_shift;
++
++      //end_page = mtd->oobblock + mtd->oobsize;
++      end = mtd->oobblock;
++      //ecc = mtd->eccsize;
++      /* Get raw starting column */
++      col = (from & (mtd->oobblock - 1));
++
++
++      /* Send the read command */
++      //this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
++
++      /* Loop until all data read */
++      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++      while (read < len) {
++
++              //udelay(1200);
++              /* If we have consequent page reads, apply delay or wait for ready/busy pin */
++              if (read) {
++                      if (!this->dev_ready)
++                              udelay (this->chip_delay);
++                      else
++                              while (!this->dev_ready(mtd));
++              }
++
++              /*
++               * If the read is not page aligned, we have to read into data buffer
++               * due to ecc, else we read into return buffer direct
++               */
++              if (!col && (len - read) >= end)
++                      data_poi = &buf[read];
++              else
++                      data_poi = this->data_buf;
++
++              /* get oob area, if we have no oob buffer from fs-driver */
++              if (!oob_buf) {
++                      oob_data = &this->data_buf[end];
++                      oob = 0;
++              }
++
++              j = 0;
++              switch (eccmode) {
++                      case NAND_ECC_NONE: {   /* No ECC, Read in a page */
++                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
++                              break;
++                      }
++
++                      case NAND_ECC_SOFT:     /* Software ECC 3/256: Read in a page + oob data */
++                              break;
++
++                      case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data: Read in first 256 byte, get ecc, */
++                              break;
++
++                      case NAND_ECC_HW3_512:
++                      case NAND_ECC_HW6_512: /* Hardware ECC 3/6 byte / 512 byte data : Read in a page  */
++                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
++                              break;
++
++                      default:
++                              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
++                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0);
++                              //BUG();
++              }//end switch
++
++                      for(i=0;i<end;i++)
++                      {
++                              //udelay(7);
++                              data_poi[i] = FLASH_READ_DATA(page*mtd->oobblock +i);
++                      }
++                      /* read oobdata */
++                      for (i = 0; i <  mtd->oobsize; i++)
++                      {
++                              //udelay(7);
++                              oob_data[oob + i] = FLASH_READ_DATA(page*mtd->oobblock +end+i);
++                      }
++
++              /* Skip ECC, if not active */
++                      if (eccmode == NAND_ECC_NONE)
++                              goto readdata;
++
++                      // compare ecc and correct data
++
++                              opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
++                              while(!(opcode&0x80000000)) //polling flash access 31b
++                              {
++                                 opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
++                                 //sl2312_flash_delay();
++                                 schedule();
++                              }
++                              for(j=0;j<(end/512);j++)
++                              {//for 2k page
++
++                                      opcode = 0x00000000|oob_data[mtd->oobsize-3-4*j]<<16|oob_data[mtd->oobsize-2-4*j]<<8|oob_data[mtd->oobsize-1-4*j];
++
++                                      //opcode=FLASH_READ_REG(NFLASH_ECC_CODE_GEN0+(j*4));
++
++                                      FLASH_WRITE_REG(NFLASH_ECC_OOB, opcode);
++                                      opcode = 0x00000000|(j<<8); //select ECC code generation 0
++                                      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, opcode); //???
++
++                                      opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
++                                      if((opcode&0x00000003)==0x03)
++                                      {
++                                              printk (KERN_WARNING "\nPageRead Uncorrectable error !!\n");
++                                              ecc_failed++;
++                                      }
++                                      else if((opcode&0x00000003)==0x01)
++                                      {
++                                              printk (KERN_WARNING "\nPageRead One bit data error !!");
++                                              // correct data
++                                              if((data_poi[(opcode&0xff80)>>7]>>((opcode&0x38)>>3))%1)
++                                                      data_poi[(opcode&0xff80)>>7] &= ~(1<<((opcode&0x38)>>3));
++                                              else
++                                                      data_poi[(opcode&0xff80)>>7] |= (1<<((opcode&0x38)>>3));
++
++                                      }
++                                      else if((opcode&0x00000003)==0x02)
++                                      {
++                                              printk (KERN_WARNING "\nPageRead One bit ECC error !!\n");
++                                      }
++                                      else if((opcode&0x00000003)==0x00)
++                                      {
++
++                                      }
++
++                              }//for 2k page
++readdata:
++              if (col || (len - read) < end) {
++                      for (j = col; j < end && read < len; j++)
++                              buf[read++] = data_poi[j];
++              } else
++                      read += mtd->oobblock;
++              /* For subsequent reads align to page boundary. */
++              col = 0;
++              /* Increment page address */
++              page++;
++              schedule();
++      }
++      /* De-select the NAND device */
++      //this->select_chip(mtd, -1);
++      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
++      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_INDIRECT);
++      /* Wake up anyone waiting on the device */
++      spin_lock_bh (&this->chip_lock);
++      this->state = FL_READY;
++      wake_up (&this->wq);
++      spin_unlock_bh (&this->chip_lock);
++
++      /*
++       * Return success, if no ECC failures, else -EIO
++       * fs driver will take care of that, because
++       * retlen == desired len and result == -EIO
++       */
++      *retlen = read;
++      return ecc_failed ? -EIO : 0;
++}
++
++/*
++ * Wait for command done. This applies to erase and program only
++ * Erase can take up to 400ms and program up to 20ms according to
++ * general NAND and SmartMedia specs
++ *
++*/
++static int sl2312_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
++{
++      unsigned long   timeo = jiffies;
++      int     status, opcode;
++
++      if (state == FL_ERASING)
++               timeo += (HZ * 400) / 1000;
++      else
++               timeo += (HZ * 20) / 1000;
++
++      spin_lock_bh (&this->chip_lock);
++      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
++      FLASH_WRITE_REG(NFLASH_COUNT, 0x007f000070); //set only command no address and two data
++
++      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000070); //write read status command
++
++
++      opcode = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
++      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
++
++      while(opcode&0x80000000) //polling flash access 31b
++    {
++        opcode=FLASH_READ_REG(NFLASH_ACCESS);
++        //sl2312_flash_delay();
++        schedule();
++    }
++
++      while (time_before(jiffies, timeo)) {
++              /* Check, if we were interrupted */
++              if (this->state != state) {
++                      spin_unlock_bh (&this->chip_lock);
++                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++                      return 0;
++              }
++              if (this->dev_ready) {
++                      if (this->dev_ready(mtd))
++                              break;
++              }
++              if (FLASH_READ_REG(NFLASH_DATA) & 0x40)
++                      break;
++
++              spin_unlock_bh (&this->chip_lock);
++              yield ();
++              spin_lock_bh (&this->chip_lock);
++      }
++      status = FLASH_READ_REG(NFLASH_DATA)&0xff;
++      spin_unlock_bh (&this->chip_lock);
++      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++      return status;
++}
++
++static int sl2312_nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
++{
++      int i, col, page, j=0;
++      //int erase_state = 0;
++      struct nand_chip *this = mtd->priv;
++      u_char *databuf, *oobbuf;
++
++      databuf = &this->data_buf[0];
++      oobbuf = &this->data_buf[mtd->oobblock];
++              for (i = 0; i < mtd->oobsize; i++)
++                      oobbuf[i] = 0xff;
++
++      DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
++
++      /* Shift to get page */
++      page = ((int) from) >> this->page_shift;
++
++      /* Mask to get column */
++      col = from & (mtd->oobsize-1);  //0x0f;
++
++      /* Initialize return length value */
++      *retlen = 0;
++      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , retlen, databuf, oobbuf, NULL);
++      for(i=col,j=0;i<mtd->oobsize||i<(col+len);i++,j++)
++              buf[j] = oobbuf[i];
++
++      *retlen = j ;
++      return 0;
++}
++
++#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
++/*
++*     Use NAND write ECC
++*/
++static int sl2312_nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
++{
++      return (sl2312_nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
++}
++
++/*
++ * NAND write with ECC
++ */
++static int sl2312_nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
++                         size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
++{
++      int page, ret = 0, oob = 0, written = 0;
++      struct nand_chip *this = mtd->priv;
++
++      DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
++
++
++      /* Do not allow write past end of device */
++      if ((to + len) > mtd->size) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
++              return -EINVAL;
++      }
++
++      /* reject writes, which are not page aligned */
++      if (NOTALIGNED (to) || NOTALIGNED(len)) {
++              printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
++              return -EINVAL;
++      }
++
++      // if oobsel is NULL, use chip defaults
++      if (oobsel == NULL)
++              oobsel = &mtd->oobinfo;
++
++      /* Shift to get page */
++      page = ((int) to) >> this->page_shift;
++
++      /* Grab the lock and see if the device is available */
++      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
++
++      /* Select the NAND device */
++      this->select_chip(mtd, 0);
++
++      /* Check the WP bit */
++      if (!(sl2312_device_ready(mtd) & 0x80)) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Device is write protected!!!\n");
++              ret = -EIO;
++              goto out;
++      }
++
++      /* Loop until all data is written */
++      while (written < len) {
++              //udelay(100);
++              int cnt = mtd->oobblock;
++              this->data_poi = (u_char*) &buf[written];
++              /* We use the same function for write and writev */
++              if (eccbuf) {
++                      ret = sl2312_nand_write_page (mtd, this, page, &eccbuf[oob], oobsel);
++                      oob += mtd->oobsize;
++              } else
++                      ret = sl2312_nand_write_page (mtd, this, page, NULL, oobsel);
++
++              if (ret)
++                      goto out;
++
++              /* Update written bytes count */
++              written += cnt;
++              /* Increment page address */
++              page++;
++      }
++
++out:
++      /* De-select the NAND device */
++      //this->select_chip(mtd, -1);
++
++      /* Wake up anyone waiting on the device */
++      spin_lock_bh (&this->chip_lock);
++      this->state = FL_READY;
++      wake_up (&this->wq);
++      spin_unlock_bh (&this->chip_lock);
++
++      *retlen = written;
++      return ret;
++}
++
++/*
++ *    Nand_page_program function is used for write and writev !
++ *    This function will always program a full page of data
++ *    If you call it with a non page aligned buffer, you're lost :)
++ */
++static int sl2312_nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  struct nand_oobinfo *oobsel)
++{
++      int     i, j, status, opcode;
++      u_char  ecc_code[16], *oob_data;
++      int     eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
++      //int   *oob_config = oobsel->eccpos;
++
++      /* pad oob area, if we have no oob buffer from fs-driver */
++      if (!oob_buf) {
++              oob_data = &this->data_buf[mtd->oobblock];
++              for (i = 0; i < mtd->oobsize; i++)
++                      oob_data[i] = 0xff;
++      } else
++              oob_data = oob_buf;
++
++      /* Send command to begin auto page programming */
++
++      memset(oob_data,0xff,mtd->oobsize);
++      /* Write out complete page of data, take care of eccmode */
++      switch (eccmode) {
++      /* No ecc and software ecc 3/256, write all */
++      case NAND_ECC_NONE:
++              printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
++              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
++              break;
++      case NAND_ECC_SOFT:
++              break;
++
++      /* Hardware ecc 3 byte / 256 data, write first half, get ecc, then second, if 512 byte pagesize */
++      case NAND_ECC_HW3_256:
++              break;
++
++      /* Hardware ecc 3 byte / 512 byte data, write full page */
++      case NAND_ECC_HW3_512:
++              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
++
++      /* Hardware ecc 6 byte / 512 byte data, write full page */
++      case NAND_ECC_HW6_512:
++              break;
++
++      default:
++              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
++              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
++              //BUG();
++      }
++
++      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
++
++      for(i=0;i<mtd->oobblock;i++)
++      {
++              //udelay(5);
++              FLASH_WRITE_DATA((page*mtd->oobblock)+i,this->data_poi[i]);
++      }
++      ///////////////
++      if(eccmode!=NAND_ECC_NONE)
++      {
++              opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
++              while(!(opcode&0x80000000)) //polling flash access 31b
++      {
++                 opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
++                 //sl2312_flash_delay();
++                 schedule();
++      }
++
++
++      for(i=0;i<(mtd->oobblock/512);i++)
++      {
++              opcode=FLASH_READ_REG(NFLASH_ECC_CODE_GEN0+(i*4));
++
++              for(j=3;j>0;j--)
++                    oob_data[(mtd->oobsize-j-(i*4))] = (opcode<<((4-j)*8)) >>24;
++
++              for(j=0;j<4;j++)
++              {
++                      ecc_code[15-i*4] = opcode;
++                      ecc_code[15-i*4-1] = opcode>>8;
++                      ecc_code[15-i*4-2] = opcode>>16;
++              }
++      }
++
++      //disable ecc
++      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000);
++
++      /* Write out OOB data */
++      for(i=0;i<mtd->oobsize;i++)
++      {
++              //udelay(5);
++                      FLASH_WRITE_DATA((page*mtd->oobblock)+mtd->oobblock+i,oob_data[i]);
++              }
++    }
++    else
++    {
++      for(i=0;i<mtd->oobsize;i++)
++      {
++              //udelay(5);
++                      FLASH_WRITE_DATA((page*mtd->oobblock)+mtd->oobblock+i,0xff);
++              }
++    }
++
++
++      /* call wait ready function */
++      status = this->waitfunc (mtd, this, FL_WRITING);
++      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
++      /* See if device thinks it succeeded */
++      if (status & 0x01) {
++              DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
++              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
++              return -EIO;
++      }
++
++#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
++      /*
++       * The NAND device assumes that it is always writing to
++       * a cleanly erased page. Hence, it performs its internal
++       * write verification only on bits that transitioned from
++       * 1 to 0. The device does NOT verify the whole page on a
++       * byte by byte basis. It is possible that the page was
++       * not completely erased or the page is becoming unusable
++       * due to wear. The read with ECC would catch the error
++       * later when the ECC page check fails, but we would rather
++       * catch it early in the page write stage. Better to write
++       * no data than invalid data.
++       */
++
++      /* Send command to read back the page */
++      this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
++      /* Loop through and verify the data */
++      if (this->verify_buf(mtd, this->data_poi, mtd->oobblock)) {
++              DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
++              return -EIO;
++      }
++
++      /* check, if we have a fs-supplied oob-buffer */
++      if (oob_buf) {
++              if (this->verify_buf(mtd, oob_data, mtd->oobsize)) {
++                      DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
++                      return -EIO;
++              }
++      } else {
++              if (eccmode != NAND_ECC_NONE) {
++                      int ecc_bytes = 0;
++
++                      switch (this->eccmode) {
++                      case NAND_ECC_SOFT:
++                      case NAND_ECC_HW3_256: ecc_bytes = (mtd->oobblock == 512) ? 6 : 3; break;
++                      case NAND_ECC_HW3_512: ecc_bytes = 3; break;
++                      case NAND_ECC_HW6_512: ecc_bytes = 6; break;
++                      }
++
++
++
++                      for(i=0;i < (mtd->oobblock+mtd->oobsize);i++)
++                      {
++                              if(i>=mtd->oobblock)
++                                      oob_data[i-mtd->oobblock] = FLASH_READ_DATA((page*mtd->oobblock) +i);
++                              else
++                                      oob_data[0] = FLASH_READ_DATA((page*mtd->oobblock) +i);
++                      }
++
++                      if(this->eccmode == NAND_ECC_HW3_512)
++                      {
++                              for(i=0;i<(mtd->oobblock/512);i++)
++                      {
++                              for(j=0;j<3;j++)
++                              {
++                                  if (oob_data[mtd->oobsize-1-j-4*i] != ecc_code[15-j-4*i]) {
++                                                      DEBUG (MTD_DEBUG_LEVEL0,
++                                                             "%s: Failed ECC write "
++                                                     "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
++                                                      return -EIO;
++                                              }
++                              }
++                      }
++                      }
++              }//eccmode != NAND_ECC_NONE
++      }
++      /*
++       * Terminate the read command. This is faster than sending a reset command or
++       * applying a 20us delay before issuing the next programm sequence.
++       * This is not a problem for all chips, but I have found a bunch of them.
++       */
++      //this->select_chip(mtd, -1);
++      //this->select_chip(mtd, 0);
++#endif
++
++      return 0;
++}
++
++/*
++ * NAND write with iovec
++ */
++static int sl2312_nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
++              loff_t to, size_t * retlen)
++{
++      return (sl2312_nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, 0));
++}
++
++static int sl2312_nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
++              loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel)
++{
++      int i, page, len, total_len, ret = 0, written = 0;
++      struct nand_chip *this = mtd->priv;
++
++      /* Calculate total length of data */
++      total_len = 0;
++      for (i = 0; i < count; i++)
++              total_len += (int) vecs[i].iov_len;
++
++      DEBUG (MTD_DEBUG_LEVEL3,
++             "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
++
++      /* Do not allow write past end of page */
++      if ((to + total_len) > mtd->size) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n");
++              return -EINVAL;
++      }
++
++      /* reject writes, which are not page aligned */
++      if (NOTALIGNED (to) || NOTALIGNED(total_len)) {
++              printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
++              return -EINVAL;
++      }
++
++      // if oobsel is NULL, use chip defaults
++      if (oobsel == NULL)
++              oobsel = &mtd->oobinfo;
++
++      /* Shift to get page */
++      page = ((int) to) >> this->page_shift;
++
++      /* Grab the lock and see if the device is available */
++      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
++
++      /* Select the NAND device */
++      this->select_chip(mtd, 0);
++
++      /* Check the WP bit */
++      if (!(sl2312_device_ready(mtd) & 0x80)) {
++              DEBUG (MTD_DEBUG_LEVEL0, "sl2312_nand_writev_ecc: Device is write protected!!!\n");
++              ret = -EIO;
++              goto out;
++      }
++
++      /* Loop until all iovecs' data has been written */
++      len = 0;
++      while (count) {
++              /*
++               *  Check, if the tuple gives us not enough data for a
++               *  full page write. Then we can use the iov direct,
++               *  else we have to copy into data_buf.
++               */
++              if ((vecs->iov_len - len) >= mtd->oobblock) {
++                      this->data_poi = (u_char *) vecs->iov_base;
++                      this->data_poi += len;
++                      len += mtd->oobblock;
++                      /* Check, if we have to switch to the next tuple */
++                      if (len >= (int) vecs->iov_len) {
++                              vecs++;
++                              len = 0;
++                              count--;
++                      }
++              } else {
++                      /*
++                       * Read data out of each tuple until we have a full page
++                       * to write or we've read all the tuples.
++                      */
++                      int cnt = 0;
++                      while ((cnt < mtd->oobblock) && count) {
++                              if (vecs->iov_base != NULL && vecs->iov_len) {
++                                      this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
++                              }
++                              /* Check, if we have to switch to the next tuple */
++                              if (len >= (int) vecs->iov_len) {
++                                      vecs++;
++                                      len = 0;
++                                      count--;
++                              }
++                      }
++                      this->data_poi = this->data_buf;
++              }
++
++              /* We use the same function for write and writev !) */
++              ret = sl2312_nand_write_page (mtd, this, page, NULL, oobsel);
++              if (ret)
++                      goto out;
++
++              /* Update written bytes count */
++              written += mtd->oobblock;;
++
++              /* Increment page address */
++              page++;
++      }
++
++out:
++      /* De-select the NAND device */
++      //this->select_chip(mtd, -1);
++
++      /* Wake up anyone waiting on the device */
++      spin_lock_bh (&this->chip_lock);
++      this->state = FL_READY;
++      wake_up (&this->wq);
++      spin_unlock_bh (&this->chip_lock);
++
++      *retlen = written;
++      return ret;
++}
++
++/*
++static u_char ffchars[] = {
++      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
++};
++*/
++/*
++ * NAND write out-of-band
++ */
++static int sl2312_nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
++{
++      int column, page, status, ret = 0, j=0;
++      struct nand_chip *this = mtd->priv;
++      u_char *databuf, *oobbuf;
++
++
++              databuf = &this->data_buf[0];
++              oobbuf = &this->data_buf[mtd->oobblock];
++              for (j = 0; j < mtd->oobsize; j++)
++                      oobbuf[j] = 0xff;
++//#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
++//    int     i;
++//#endif
++
++      DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
++
++      /* Shift to get page */
++      page = ((int) to) >> this->page_shift;
++
++      /* Mask to get column */
++      column = to & 0x1f;
++
++      /* Initialize return length value */
++      *retlen = 0;
++
++      /* Do not allow write past end of page */
++      if ((column + len) > mtd->oobsize) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
++              return -EINVAL;
++      }
++
++      /* Grab the lock and see if the device is available */
++      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
++
++      /* Select the NAND device */
++      this->select_chip(mtd, 0);
++
++      /* Reset the chip. Some chips (like the Toshiba TC5832DC found
++         in one of my DiskOnChip 2000 test units) will clear the whole
++         data page too if we don't do this. I have no clue why, but
++         I seem to have 'fixed' it in the doc2000 driver in
++         August 1999.  dwmw2. */
++      this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
++
++      /* Check the WP bit */
++      if (!(sl2312_device_ready(mtd) & 0x80)) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Device is write protected!!!\n");
++              ret = -EIO;
++              goto out;
++      }
++      /* Write out desired data */
++      this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page);
++
++      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , retlen, databuf, oobbuf, NULL);
++
++    for(j=column;j<(column+len);j++)
++      oobbuf[j] = buf[j-column];
++    sl2312_nand_write_ecc (mtd, page, mtd->oobblock, retlen, databuf, oobbuf, NULL);
++
++      status = this->waitfunc (mtd, this, FL_WRITING);
++
++      /* See if device thinks it succeeded */
++      if (status & 0x01) {
++              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
++              ret = -EIO;
++              goto out;
++      }
++      /* Return happy */
++      *retlen = len;
++
++
++out:
++      /* De-select the NAND device */
++      //this->select_chip(mtd, -1);
++
++      /* Wake up anyone waiting on the device */
++      spin_lock_bh (&this->chip_lock);
++      this->state = FL_READY;
++      wake_up (&this->wq);
++      spin_unlock_bh (&this->chip_lock);
++
++      return ret;
++}
++
++/*
++ * NAND sync
++ */
++static void sl2312_nand_sync (struct mtd_info *mtd)
++{
++      struct nand_chip *this = mtd->priv;
++      DECLARE_WAITQUEUE (wait, current);
++
++      DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
++
++retry:
++      /* Grab the spinlock */
++      spin_lock_bh (&this->chip_lock);
++
++      /* See what's going on */
++      switch (this->state) {
++      case FL_READY:
++      case FL_SYNCING:
++              this->state = FL_SYNCING;
++              spin_unlock_bh (&this->chip_lock);
++              break;
++
++      default:
++              /* Not an idle state */
++              add_wait_queue (&this->wq, &wait);
++              spin_unlock_bh (&this->chip_lock);
++              schedule ();
++
++              remove_wait_queue (&this->wq, &wait);
++              goto retry;
++      }
++
++      /* Lock the device */
++      spin_lock_bh (&this->chip_lock);
++
++      /* Set the device to be ready again */
++      if (this->state == FL_SYNCING) {
++              this->state = FL_READY;
++              wake_up (&this->wq);
++      }
++
++      /* Unlock the device */
++      spin_unlock_bh (&this->chip_lock);
++}
++
++
++/*
++ * Scan for the NAND device
++ */
++int sl2312_nand_scan (struct mtd_info *mtd, int maxchips)
++{
++      int i, j, nand_maf_id, nand_dev_id, busw;
++      struct nand_chip *this = mtd->priv;
++      unsigned char id[4];
++
++      /* Get buswidth to select the correct functions*/
++      busw = this->options & NAND_BUSWIDTH_16;
++
++      /* check for proper chip_delay setup, set 20us if not */
++      if (!this->chip_delay)
++              this->chip_delay = 20;
++
++      /* check, if a user supplied command function given */
++      if (this->cmdfunc == NULL)
++              this->cmdfunc = sl2312_nand_command;
++
++      /* check, if a user supplied wait function given */
++      if (this->waitfunc == NULL)
++              this->waitfunc = sl2312_nand_waitfunc;
++
++      if (!this->select_chip)
++              this->select_chip = sl2312_nand_select_chip;
++      if (!this->write_byte)
++              this->write_byte = sl2312_nand_write_byte; //busw ? nand_write_byte16 : nand_write_byte;
++      if (!this->read_byte)
++              this->read_byte = sl2312_nand_read_byte; //busw ? nand_read_byte16 : nand_read_byte;
++//    if (!this->write_word)
++//            this->write_word = nand_write_word;
++//    if (!this->read_word)
++//            this->read_word = nand_read_word;
++//    if (!this->block_bad)
++              this->block_bad = sl2312_nand_block_bad; //nand_block_bad;
++      if (!this->block_markbad)
++              this->block_markbad = sl2312_nand_default_block_markbad;
++      if (!this->write_buf)
++              this->write_buf = sl2312_nand_write_buf; //busw ? nand_write_buf16 : nand_write_buf;
++      if (!this->read_buf)
++              this->read_buf = sl2312_nand_read_buf; //busw ? nand_read_buf16 : nand_read_buf;
++      if (!this->verify_buf)
++              this->verify_buf = sl2312_nand_verify_buf; //busw ? nand_verify_buf16 : nand_verify_buf;
++      if (!this->scan_bbt)
++              this->scan_bbt = sl2312_nand_scan_bbt;
++
++      /* Select the device */
++      this->select_chip(mtd, 0);
++
++      /* Read manufacturer and device IDs */
++      nand_read_id(0,id);
++
++      nand_maf_id = id[0];
++      nand_dev_id = id[1];
++
++      /* Print and store flash device information */
++      for (i = 0; nand_flash_ids[i].name != NULL; i++) {
++
++              if (nand_dev_id != nand_flash_ids[i].id)
++                      continue;
++
++              if (!mtd->name) mtd->name = nand_flash_ids[i].name;
++              this->chipsize = nand_flash_ids[i].chipsize << 20;
++
++              /* New devices have all the information in additional id bytes */
++              if (!nand_flash_ids[i].pagesize) {
++                      int extid;
++
++                      /* The 4th id byte is the important one */
++                      extid = id[3];
++                      /* Calc pagesize */
++                      mtd->oobblock = 1024 << (extid & 0x3);
++                      extid >>= 2;
++                      /* Calc oobsize */
++                      mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512);
++                      extid >>= 2;
++                      /* Calc blocksize. Blocksize is multiples of 64KiB */
++                      mtd->erasesize = (64 * 1024)  << (extid & 0x03);
++                      extid >>= 2;
++                      /* Get buswidth information */
++                      busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
++
++              } else {
++                      /* Old devices have this data hardcoded in the
++                       * device id table */
++                      mtd->erasesize = nand_flash_ids[i].erasesize;
++                      mtd->oobblock = nand_flash_ids[i].pagesize;
++                      mtd->oobsize = mtd->oobblock / 32;
++                      busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
++              }
++
++              /* Check, if buswidth is correct. Hardware drivers should set
++               * this correct ! */
++              if (busw != (this->options & NAND_BUSWIDTH_16)) {
++                      printk (KERN_INFO "NAND device: Manufacturer ID:"
++                              " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
++                              nand_manuf_ids[i].name , mtd->name);
++                      printk (KERN_WARNING
++                              "NAND bus width %d instead %d bit\n",
++                                      (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
++                                      busw ? 16 : 8);
++                      this->select_chip(mtd, -1);
++                      return 1;
++              }
++
++              /* Calculate the address shift from the page size */
++              this->page_shift = ffs(mtd->oobblock) - 1;
++              this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
++              this->chip_shift = ffs(this->chipsize) - 1;
++
++              /* Set the bad block position */
++              this->badblockpos = mtd->oobblock > 512 ?
++                      NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
++
++              /* Get chip options, preserve non chip based options */
++              this->options &= ~NAND_CHIPOPTIONS_MSK;
++              this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
++              /* Set this as a default. Board drivers can override it, if neccecary */
++              this->options |= NAND_NO_AUTOINCR;
++              /* Check if this is a not a samsung device. Do not clear the options
++               * for chips which are not having an extended id.
++               */
++              if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
++                      this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
++
++              /* Check for AND chips with 4 page planes */
++      //      if (this->options & NAND_4PAGE_ARRAY)
++      //              this->erase_cmd = multi_erase_cmd;
++      //      else
++      //              this->erase_cmd = single_erase_cmd;
++
++              /* Do not replace user supplied command function ! */
++      //      if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
++      //              this->cmdfunc = nand_command_lp;
++
++              /* Try to identify manufacturer */
++              for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
++                      if (nand_manuf_ids[j].id == nand_maf_id)
++                              break;
++              }
++              printk (KERN_INFO "NAND device: Manufacturer ID:"
++                      " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
++                      nand_manuf_ids[j].name , nand_flash_ids[i].name);
++              break;
++      }
++      /////////////////////////////
++
++      for (i=1; i < maxchips; i++) {
++              this->select_chip(mtd, i);
++
++              /* Send the command for reading device ID */
++              nand_read_id(1,id);
++
++              /* Read manufacturer and device IDs */
++              if (nand_maf_id != id[0] ||
++                  nand_dev_id != id[1])
++                      break;
++      }
++      if (i > 1)
++              printk(KERN_INFO "%d NAND chips detected\n", i);
++
++      /* Allocate buffers, if neccecary */
++      if (!this->oob_buf) {
++              size_t len;
++              len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);
++              this->oob_buf = kmalloc (len, GFP_KERNEL);
++              if (!this->oob_buf) {
++                      printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");
++                      return -ENOMEM;
++              }
++              this->options |= NAND_OOBBUF_ALLOC;
++      }
++
++      if (!this->data_buf) {
++              size_t len;
++              len = mtd->oobblock + mtd->oobsize;
++              this->data_buf = kmalloc (len, GFP_KERNEL);
++              if (!this->data_buf) {
++                      if (this->options & NAND_OOBBUF_ALLOC)
++                              kfree (this->oob_buf);
++                      printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
++                      return -ENOMEM;
++              }
++              this->options |= NAND_DATABUF_ALLOC;
++      }
++
++      /* Store the number of chips and calc total size for mtd */
++      this->numchips = i;
++      mtd->size = i * this->chipsize;
++      /* Convert chipsize to number of pages per chip -1. */
++      this->pagemask = (this->chipsize >> this->page_shift) - 1;
++      /* Preset the internal oob buffer */
++      memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
++
++      /* If no default placement scheme is given, select an
++       * appropriate one */
++      if (!this->autooob) {
++              /* Select the appropriate default oob placement scheme for
++               * placement agnostic filesystems */
++              switch (mtd->oobsize) {
++              case 8:
++                      this->autooob = &nand_oob_8;
++                      break;
++              case 16:
++                      this->autooob = &nand_oob_16;
++                      break;
++              case 64:
++                      this->autooob = &nand_oob_64;
++                      break;
++              default:
++                      printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
++                              mtd->oobsize);
++                      BUG();
++              }
++      }
++
++      /* The number of bytes available for the filesystem to place fs dependend
++       * oob data */
++      if (this->options & NAND_BUSWIDTH_16) {
++              mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2);
++              if (this->autooob->eccbytes & 0x01)
++                      mtd->oobavail--;
++      } else
++              mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1);
++
++
++      /*
++       * check ECC mode, default to software
++       * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize
++       * fallback to software ECC
++      */
++      this->eccsize = 256;    /* set default eccsize */
++      this->eccbytes = 3;
++
++      switch (this->eccmode) {
++      case NAND_ECC_HW12_2048:
++              if (mtd->oobblock < 2048) {
++                      printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
++                             mtd->oobblock);
++                      this->eccmode = NAND_ECC_SOFT;
++                      this->calculate_ecc = nand_calculate_ecc;
++                      this->correct_data = nand_correct_data;
++              } else
++                      this->eccsize = 2048;
++              break;
++
++      case NAND_ECC_HW3_512:
++      case NAND_ECC_HW6_512:
++      case NAND_ECC_HW8_512:
++              if (mtd->oobblock == 256) {
++                      printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
++                      this->eccmode = NAND_ECC_SOFT;
++                      this->calculate_ecc = nand_calculate_ecc;
++                      this->correct_data = nand_correct_data;
++              } else
++                      this->eccsize = 512; /* set eccsize to 512 */
++              break;
++
++      case NAND_ECC_HW3_256:
++              break;
++
++      case NAND_ECC_NONE:
++              printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");
++              this->eccmode = NAND_ECC_NONE;
++              break;
++
++      case NAND_ECC_SOFT:
++              this->calculate_ecc = nand_calculate_ecc;
++              this->correct_data = nand_correct_data;
++              break;
++
++      default:
++              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
++              BUG();
++      }
++
++      /* Check hardware ecc function availability and adjust number of ecc bytes per
++       * calculation step
++      */
++      switch (this->eccmode) {
++      case NAND_ECC_HW12_2048:
++              this->eccbytes += 4;
++      case NAND_ECC_HW8_512:
++              this->eccbytes += 2;
++      case NAND_ECC_HW6_512:
++              this->eccbytes += 3;
++//    case NAND_ECC_HW3_512:
++      case NAND_ECC_HW3_256:
++              if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
++                      break;
++              printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
++              BUG();
++      }
++
++      mtd->eccsize = this->eccsize;
++
++      /* Set the number of read / write steps for one page to ensure ECC generation */
++      switch (this->eccmode) {
++      case NAND_ECC_HW12_2048:
++              this->eccsteps = mtd->oobblock / 2048;
++              break;
++      case NAND_ECC_HW3_512:
++      case NAND_ECC_HW6_512:
++      case NAND_ECC_HW8_512:
++              this->eccsteps = mtd->oobblock / 512;
++              break;
++      case NAND_ECC_HW3_256:
++      case NAND_ECC_SOFT:
++              this->eccsteps = mtd->oobblock / 256;
++              break;
++
++      case NAND_ECC_NONE:
++              this->eccsteps = 1;
++              break;
++      }
++
++      /* Initialize state, waitqueue and spinlock */
++      this->state = FL_READY;
++      init_waitqueue_head (&this->wq);
++      spin_lock_init (&this->chip_lock);
++
++      /* De-select the device */
++      this->select_chip(mtd, 0);
++
++      /* Print warning message for no device */
++      if (!mtd->size) {
++              printk (KERN_WARNING "No NAND device found!!!\n");
++              return 1;
++      }
++
++      /* Fill in remaining MTD driver data */
++      mtd->type = MTD_NANDFLASH;
++      mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
++      mtd->ecctype = MTD_ECC_SW;
++      mtd->erase = sl2312_nand_erase;
++      mtd->point = NULL;
++      mtd->unpoint = NULL;
++      mtd->read = sl2312_nand_read;
++      mtd->write = sl2312_nand_write;
++      mtd->read_ecc = sl2312_nand_read_ecc;
++      mtd->write_ecc = sl2312_nand_write_ecc;
++      mtd->read_oob = sl2312_nand_read_oob;
++      mtd->write_oob = sl2312_nand_write_oob;
++      mtd->readv = NULL;
++      mtd->writev = sl2312_nand_writev;
++      mtd->writev_ecc = sl2312_nand_writev_ecc;
++      mtd->sync = sl2312_nand_sync;
++      mtd->lock = NULL;
++      mtd->unlock = NULL;
++      mtd->suspend = NULL;
++      mtd->resume = NULL;
++      mtd->block_isbad = sl2312_nand_block_isbad;
++      mtd->block_markbad = sl2312_nand_block_markbad;
++
++      /* and make the autooob the default one */
++      memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
++
++      mtd->owner = THIS_MODULE;
++
++      /* Build bad block table */
++      return this->scan_bbt (mtd);
++}
++
++/*End Add function*/
++
++/*
++ * Main initialization routine
++ */
++extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
++
++int __init sl2312_mtd_init (void)
++{
++      struct nand_chip *this;
++      int err = 0;
++      struct mtd_partition *parts;
++      int nr_parts = 0;
++      int ret, data, *base;
++
++      printk("NAND MTD Driver Start Init ......\n");
++
++      base = (unsigned int *)(IO_ADDRESS(SL2312_GLOBAL_BASE) + 0x30);
++      data = *base;
++      data&=0xffffffeb;
++      data|=0x3; //disable p & s flash
++        *base = data;
++
++      /* Allocate memory for MTD device structure and private data */
++      sl2312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
++      if (!sl2312_mtd) {
++              printk ("Unable to allocate SL2312 NAND MTD device structure.\n");
++              err = -ENOMEM;
++              goto out;
++      }
++
++      //  sl2312_device_setup();
++
++      /* io is indirect via a register so don't need to ioremap address */
++
++      /* Get pointer to private data */
++      this = (struct nand_chip *) (&sl2312_mtd[1]);
++
++      /* Initialize structures */
++      memset((char *) sl2312_mtd, 0, sizeof(struct mtd_info));
++      memset((char *) this, 0, sizeof(struct nand_chip));
++
++      /* Link the private data with the MTD structure */
++      sl2312_mtd->priv = this;
++      sl2312_mtd->name = "sl2312-nand";
++
++      /* Set address of NAND IO lines */
++      this->IO_ADDR_R = (void __iomem *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE+NFLASH_DATA)); //(unsigned long)&(sl2312_ndfmcptr->dtr);
++      this->IO_ADDR_W = (void __iomem *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE+NFLASH_DATA)); //(unsigned long)&(sl2312_ndfmcptr->dtr);
++      this->read_byte = sl2312_nand_read_byte;
++    this->write_byte = sl2312_nand_write_byte;
++    this->write_buf = sl2312_nand_write_buf;
++      this->read_buf = sl2312_nand_read_buf;
++      this->verify_buf = sl2312_nand_verify_buf;
++      this->select_chip = sl2312_nand_select_chip;
++      this->block_bad = sl2312_nand_block_bad;
++      this->hwcontrol = sl2312_hwcontrol;
++      this->dev_ready = sl2312_device_ready;
++      this->cmdfunc = sl2312_nand_command;
++      this->waitfunc = sl2312_nand_waitfunc;
++      //this->calculate_ecc = sl2312_readecc;
++      this->enable_hwecc = sl2312_enable_hwecc;
++      this->eccmode = NAND_ECC_HW3_512;
++      /*this->eccsize = 512;  */
++      /* 20 us command delay time */
++      this->chip_delay = 20;
++
++      this->correct_data = nand_correct_data;
++//    this->scan_bbt = sl2312_nand_scan_bbt;
++
++      /* Allocate memory for internal data buffer */
++      this->data_buf = kmalloc (sizeof(u_char) * (sl2312_mtd->oobblock + sl2312_mtd->oobsize), GFP_KERNEL);
++      if (!this->data_buf) {
++              printk ("Unable to allocate NAND data buffer.\n");
++              err = -ENOMEM;
++              goto out_ior;
++      }
++
++      /* Scan to find existance of the device */
++      if (sl2312_nand_scan(sl2312_mtd, 1)) {
++              err = -ENXIO;
++              goto out_ior;
++      }
++
++      /* Register the partitions */
++      parts = sl2312_partitions;
++      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
++
++      ret = add_mtd_partitions(sl2312_mtd, sl2312_partitions, nr_parts);
++      /*If we got an error, free all resources.*/
++      if (ret < 0) {
++              del_mtd_partitions(sl2312_mtd);
++              map_destroy(sl2312_mtd);
++      }
++      goto out;
++
++//out_buf:
++//    kfree (this->data_buf);
++out_ior:
++out:
++      printk("NAND MTD Driver Init Success ......\n");
++      return err;
++}
++
++module_init(sl2312_mtd_init);
++
++/*
++ * Clean up routine
++ */
++#ifdef MODULE
++static void __exit sl2312_cleanup (void)
++{
++      struct nand_chip *this = (struct nand_chip *) &sl2312_mtd[1];
++
++      /* Unregister partitions */
++      del_mtd_partitions(sl2312_mtd);
++
++      /* Unregister the device */
++      del_mtd_device (sl2312_mtd);
++
++      /* Free internal data buffers */
++      kfree (this->data_buf);
++
++      /* Free the MTD device structure */
++      kfree (sl2312_mtd);
++}
++module_exit(sl2312_cleanup);
++#endif
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
++MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBsl2312");
+--- /dev/null
++++ b/drivers/mtd/nand/sl2312-flash-nand.h
+@@ -0,0 +1,24 @@
++#ifndef SL2312_FLASH_NAND_H
++#define SL2312_FLASH_NAND_H
++
++#include <linux/wait.h>
++#include <linux/spinlock.h>
++
++/*Add function*/
++static void nand_read_id(int chip_no,unsigned char *id);
++
++
++
++#define       NFLASH_WiDTH8              0x00000000
++#define       NFLASH_WiDTH16             0x00000400
++#define       NFLASH_WiDTH32             0x00000800
++#define NFLASH_CHIP0_EN            0x00000000  // 16th bit = 0
++#define NFLASH_CHIP1_EN            0x00010000  // 16th bit = 1
++#define       NFLASH_DIRECT              0x00004000
++#define       NFLASH_INDIRECT            0x00000000
++
++
++#define       DWIDTH             NFLASH_WiDTH8
++
++
++#endif /* SL2312_FLASH_NAND_H */
+--- /dev/null
++++ b/include/linux/mtd/kvctl.h
+@@ -0,0 +1,40 @@
++#ifndef KVCTL_H
++#define KVCTL_H
++
++#define VCTL_HEAD_SIZE        8
++#define VCTL_ENTRY_LEN        20
++
++typedef struct
++{
++  char header[4];
++  unsigned int entry_num;
++} vctl_mheader;
++
++typedef struct
++{
++  char header[4];
++  unsigned int size;
++  unsigned int type;
++  char majorver[4];
++  char minorver[4];
++  unsigned char *payload;
++} vctl_entry;
++
++typedef struct
++{
++  unsigned char mac[6];
++  unsigned char vlanid;
++  unsigned char vlanmap;
++} vlaninfo;
++
++#define VCT_VENDORSPEC                0
++#define VCT_BOOTLOADER                1
++#define VCT_KERNEL            2
++#define VCT_VERCTL            3
++#define VCT_CURRCONF          4
++#define VCT_DEFAULTCONF               5
++#define VCT_ROOTFS            6
++#define VCT_APP                       7
++#define VCT_VLAN              8
++
++#endif
+--- a/drivers/mtd/maps/Makefile
++++ b/drivers/mtd/maps/Makefile
+@@ -71,3 +71,7 @@
+ obj-$(CONFIG_MTD_OMAP_NOR)    += omap_nor.o
+ obj-$(CONFIG_MTD_MTX1)                += mtx-1_flash.o
+ obj-$(CONFIG_MTD_TQM834x)     += tqm834x.o
++###### for Storlink Soc #######
++obj-$(CONFIG_MTD_SL2312_CFI) += sl2312-flash-cfi.o
++obj-$(CONFIG_MTD_SL2312_SERIAL_ATMEL) += sl2312-flash-atmel.o
++obj-$(CONFIG_MTD_SL2312_SERIAL_ST) += sl2312-flash-m25p80.o
diff --git a/target/linux/storm/patches/008-serial.patch b/target/linux/storm/patches/008-serial.patch
new file mode 100644 (file)
index 0000000..b7009af
--- /dev/null
@@ -0,0 +1,2809 @@
+--- /dev/null
++++ b/drivers/serial/it8712.c
+@@ -0,0 +1,858 @@
++/*
++ *  linux/drivers/char/serial_uart00.c
++ *
++ *  Driver for UART00 serial ports
++ *
++ *  Based on drivers/char/serial_amba.c, by ARM Limited &
++ *                                          Deep Blue Solutions Ltd.
++ *  Copyright 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *  $Id: it8712.c,v 1.2 2006/06/06 06:36:04 middle Exp $
++ *
++ */
++#include <linux/module.h>
++#include <linux/tty.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/serial.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <asm/hardware.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/sizes.h>
++
++#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/serial_core.h>
++#include <asm/arch/sl2312.h>
++#include <asm/arch/int_ctrl.h>
++#include <asm/arch/it8712.h>
++#include "it8712.h"
++
++//#define DEBUG           1
++#define UART_NR               1
++
++#define SERIAL_IT8712_NAME    "ttySI"
++#define SERIAL_IT8712_MAJOR   204
++#define SERIAL_IT8712_MINOR   41      /* Temporary - will change in future */
++#define SERIAL_IT8712_NR      UART_NR
++#define UART_PORT_SIZE 0x50
++#define LPC_HOST_CONTINUE_MODE        0x00000040
++
++#define IT8712_NO_PORTS         UART_NR
++#define IT8712_ISR_PASS_LIMIT 256
++
++#define LPC_BUS_CTRL  *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
++#define LPC_BUS_STATUS        *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
++#define LPC_SERIAL_IRQ_CTRL   *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 8))
++#define LPC_SERIAL_IRQ_STATUS *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x0c))
++#define LPC_SERIAL_IRQ_TRITYPE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x10))
++#define LPC_SERIAL_IRQ_POLARITY       *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x14))
++#define LPC_SERIAL_IRQ_ENABLE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x18))
++
++
++
++
++/*
++ * Access macros for the SL2312 UARTs
++ */
++#define UART_GET_INT_STATUS(p)        (inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
++#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
++#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
++#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
++#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
++#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
++#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
++#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
++#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
++#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
++#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
++#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
++#define UART_GET_DIV_HI(p)    inb(((p)->membase+UART_DLM))
++#define UART_PUT_DIV_HI(p, c) outb(c,((p)->membase+UART_DLM))
++#define UART_GET_DIV_LO(p)    inb(((p)->membase+UART_DLL))
++#define UART_PUT_DIV_LO(p, c) outb(c,((p)->membase+UART_DLL))
++#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
++#define UART_RX_DATA(s)               ((s) & UART_LSR_DR)
++#define UART_TX_READY(s)      ((s) & UART_LSR_THRE)
++
++static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
++{
++        unsigned int reg;
++
++        //printk("it8712 stop tx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_THRI);
++      UART_PUT_IER(port, reg);
++}
++
++static void it8712_stop_rx(struct uart_port *port)
++{
++        unsigned int reg;
++
++        //printk("it8712 stop rx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_RDI);
++      UART_PUT_IER(port, reg);
++
++}
++
++static void it8712_enable_ms(struct uart_port *port)
++{
++        unsigned int reg;
++
++        //printk("it8712 enable ms : \n");
++
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_MSI);
++      UART_PUT_IER(port, reg);
++
++}
++
++static void it8712_rx_chars(struct uart_port *port, struct pt_regs *regs)
++{
++      struct tty_struct *tty = port->info->tty;
++      unsigned int status, mask, ch, flg, ignored = 0;
++
++ //       printk("it8712_rx_chars : \n");
++      status = UART_GET_LSR(port);
++      while (UART_RX_DATA(status)) {
++
++              /*
++               * We need to read rds before reading the
++               * character from the fifo
++               */
++              ch = UART_GET_CHAR(port);
++              port->icount.rx++;
++
++              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++                      goto ignore_char;
++
++              flg = TTY_NORMAL;
++
++              /*
++               * Note that the error handling code is
++               * out of the main execution path
++               */
++
++              if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
++                      goto handle_error;
++              if (uart_handle_sysrq_char(port, ch, regs))
++                      goto ignore_char;
++
++      error_return:
++              *tty->flip.flag_buf_ptr++ = flg;
++              *tty->flip.char_buf_ptr++ = ch;
++              tty->flip.count++;
++      ignore_char:
++              status = UART_GET_LSR(port);
++      } // end of while
++out:
++      tty_flip_buffer_push(tty);
++      return;
++
++handle_error:
++      if (status & UART_LSR_BI) {
++              status &= ~(UART_LSR_FE);
++              port->icount.brk++;
++
++#ifdef SUPPORT_SYSRQ
++              if (uart_handle_break(port))
++                      goto ignore_char;
++#endif
++      } else if (status & UART_LSR_PE)
++              port->icount.parity++;
++      else if (status & UART_LSR_FE)
++              port->icount.frame++;
++
++      if (status & UART_LSR_OE)
++              port->icount.overrun++;
++
++      if (status & port->ignore_status_mask) {
++              if (++ignored > 100)
++                      goto out;
++              goto ignore_char;
++      }
++
++      mask = status & port->read_status_mask;
++
++      if (mask & UART_LSR_BI)
++              flg = TTY_BREAK;
++      else if (mask & UART_LSR_PE)
++              flg = TTY_PARITY;
++      else if (mask & UART_LSR_FE)
++              flg = TTY_FRAME;
++
++      if (status & UART_LSR_OE) {
++              /*
++               * CHECK: does overrun affect the current character?
++               * ASSUMPTION: it does not.
++               */
++              *tty->flip.flag_buf_ptr++ = flg;
++              *tty->flip.char_buf_ptr++ = ch;
++              tty->flip.count++;
++              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++                      goto ignore_char;
++              ch = 0;
++              flg = TTY_OVERRUN;
++      }
++#ifdef SUPPORT_SYSRQ
++      port->sysrq = 0;
++#endif
++      goto error_return;
++}
++
++static void it8712_tx_chars(struct uart_port *port)
++{
++        struct circ_buf *xmit = &port->info->xmit;
++      int count;
++
++      if (port->x_char) {
++              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++              UART_PUT_CHAR(port, port->x_char);
++              port->icount.tx++;
++              port->x_char = 0;
++
++              return;
++      }
++      if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
++              it8712_stop_tx(port, 0);
++              return;
++      }
++
++      count = port->fifosize >> 1;
++      do {
++              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++              UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
++              xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++              port->icount.tx++;
++              if (uart_circ_empty(xmit))
++                      break;
++      } while (--count > 0);
++
++      if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++              uart_write_wakeup(port);
++
++      if (uart_circ_empty(xmit))
++              it8712_stop_tx(port, 0);
++}
++
++static void it8712_start_tx(struct uart_port *port, unsigned int tty_start)
++{
++        unsigned int reg;
++
++        //printk("it8712 start tx : \n");
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_THRI);
++      UART_PUT_IER(port, reg);
++      it8712_tx_chars(port);
++}
++
++static void it8712_modem_status(struct uart_port *port)
++{
++      unsigned int status;
++
++//        printk("it8712 modem status : \n");
++
++      status = UART_GET_MSR(port);
++
++      if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
++                     UART_MSR_TERI | UART_MSR_DDCD)))
++              return;
++
++        if (status & UART_MSR_DDCD)
++                uart_handle_dcd_change(port, status & UART_MSR_DCD);
++
++        if (status & UART_MSR_DDSR)
++                port->icount.dsr++;
++
++        if (status & UART_MSR_DCTS)
++                uart_handle_cts_change(port, status & UART_MSR_CTS);
++
++      wake_up_interruptible(&port->info->delta_msr_wait);
++
++}
++
++static irqreturn_t  it8712_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct uart_port *port = dev_id;
++      unsigned int status, pass_counter = 0, data;
++
++
++              data = LPC_SERIAL_IRQ_STATUS;
++      if((data&0x10)==0x10)
++      {
++              status = UART_GET_INT_STATUS(port);
++              do {
++//                         printk("it8712_int: status %x \n", status);
++                      switch(status)
++                      {
++                         case UART_IIR_RDI:
++                         case UART_IIR_RLSI:
++                         case UART_IIR_RCTO:
++                              it8712_rx_chars(port, regs);
++                         break;
++                         case UART_IIR_THRI:
++                              it8712_tx_chars(port);
++                         break;
++                         case UART_IIR_MSI:
++                              it8712_modem_status(port);
++                         break;
++                         default:
++                         break;
++                      }
++                      if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
++                              break;
++
++                      status = UART_GET_INT_STATUS(port);
++              } while (status);
++      }
++
++              status = 0;
++        status |= (IRQ_LPC_MASK);
++        *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = status;
++
++      //cnt=0;
++      //do{
++      //      data = LPC_SERIAL_IRQ_STATUS;
++              LPC_SERIAL_IRQ_STATUS = data;
++      //      cnt++;
++      //}while(data);
++      //if(cnt>2)
++      //      printf("it8712_uart_Isr clear LPC_SERIAL_IRQ_STATUS %x \n", cnt);
++        return IRQ_HANDLED;
++}
++
++static u_int it8712_tx_empty(struct uart_port *port)
++{
++//        printk("it8712 tx empty : \n");
++
++      return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
++}
++
++static u_int it8712_get_mctrl(struct uart_port *port)
++{
++      unsigned int result = 0;
++      unsigned int status;
++
++//        printk("it8712 get mctrl : \n");
++
++      status = UART_GET_MSR(port);
++      if (status & UART_MSR_DCD)
++              result |= TIOCM_CAR;
++      if (status & UART_MSR_DSR)
++              result |= TIOCM_DSR;
++      if (status & UART_MSR_CTS)
++              result |= TIOCM_CTS;
++      if (status & UART_MSR_RI)
++              result |= TIOCM_RI;
++
++      return result;
++}
++
++static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
++{
++}
++
++static void it8712_break_ctl(struct uart_port *port, int break_state)
++{
++      unsigned int lcr;
++
++//        printk("it8712 break ctl : \n");
++
++      lcr = UART_GET_LCR(port);
++      if (break_state == -1)
++              lcr |= UART_LCR_SBC;
++      else
++              lcr &= ~UART_LCR_SBC;
++      UART_PUT_LCR(port, lcr);
++}
++
++static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
++{
++      u_int quot;
++
++      /* Special case: B0 rate */
++      if (!baud)
++              baud = 9600;
++
++      quot = (port->uartclk/(16 * baud)) ;
++
++      return quot;
++}
++static void it8712_set_termios(struct uart_port *port, struct termios *termios,
++                               struct termios *old)
++{
++      unsigned int  uart_mc, old_ier, baud, quot;
++      unsigned long flags;
++
++        termios->c_cflag |= CREAD;
++        termios->c_cflag |= CLOCAL;
++#ifdef DEBUG
++      printk("it8712_set_cflag(0x%x) called\n", cflag);
++#endif
++        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++        quot = uart_get_divisor(port, baud);
++
++      /* byte size and parity */
++      switch (termios->c_cflag & CSIZE) {
++      case CS5:
++              uart_mc = UART_LCR_WLEN5;
++              break;
++      case CS6:
++              uart_mc = UART_LCR_WLEN6;
++              break;
++      case CS7:
++              uart_mc = UART_LCR_WLEN7;
++              break;
++      default: // CS8
++              uart_mc = UART_LCR_WLEN8;
++              break;
++      }
++
++      if (termios->c_cflag & CSTOPB)
++              uart_mc|= UART_LCR_STOP;
++      if (termios->c_cflag & PARENB) {
++              uart_mc |= UART_LCR_EVEN;
++              if (!(termios->c_cflag & PARODD))
++                      uart_mc |= UART_LCR_ODD;
++      }
++
++        spin_lock_irqsave(&port->lock, flags);
++        /*
++         * Update the per-port timeout
++         */
++        uart_update_timeout(port, termios->c_cflag, baud);
++      port->read_status_mask = UART_LSR_OE;
++      if (termios->c_iflag & INPCK)
++              port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++      if (termios->c_iflag & (BRKINT | PARMRK))
++              port->read_status_mask |= UART_LSR_BI;
++
++      /*
++       * Characters to ignore
++       */
++      port->ignore_status_mask = 0;
++      if (termios->c_iflag & IGNPAR)
++              port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
++      if (termios->c_iflag & IGNBRK) {
++              port->ignore_status_mask |= UART_LSR_BI;
++              /*
++               * If we're ignoring parity and break indicators,
++               * ignore overruns to (for real raw support).
++               */
++              if (termios->c_iflag & IGNPAR)
++                      port->ignore_status_mask |= UART_LSR_OE;
++      }
++
++      old_ier = UART_GET_IER(port);
++
++        if(UART_ENABLE_MS(port, termios->c_cflag))
++             old_ier |= UART_IER_MSI;
++
++      /* Set baud rate */
++      quot = quot / 13;
++      UART_PUT_LCR(port, UART_LCR_DLAB);
++      UART_PUT_DIV_LO(port, (quot & 0xff));
++      UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
++
++      UART_PUT_LCR(port, uart_mc);
++//    UART_PUT_LCR(port, 0x07); // ???? it is wired
++        UART_PUT_MCR(port, 0x08);
++        UART_PUT_FCR(port, 0x01);
++      UART_PUT_IER(port, 0x07);
++
++      spin_unlock_irqrestore(&port->lock, flags);
++}
++
++static int it8712_startup(struct uart_port *port)
++{
++      int retval, i;
++      unsigned int regs;
++
++        //printk("it8712 startup : \n");
++
++      /*
++       * Use iobase to store a pointer to info. We need this to start a
++       * transmission as the tranmittr interrupt is only generated on
++       * the transition to the idle state
++       */
++
++      //      regs = 0;
++    //    regs |= (IRQ_LPC_MASK);
++    //    *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++
++      /*
++       * Allocate the IRQ
++       */
++      retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", port);
++      if (retval)
++              return retval;
++
++      //printk("Init LPC int...........\n");
++        /* setup interrupt controller  */
++        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_LPC_MASK);
++        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_LPC_MASK);
++        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_LPC_MASK);
++
++      LPC_SERIAL_IRQ_POLARITY = 0x10; //0x10; //0x02;
++      LPC_SERIAL_IRQ_TRITYPE = 0x10; //0x10;//
++      LPC_SERIAL_IRQ_ENABLE = 0x10;
++
++      LPC_BUS_CTRL = 0xc0;
++      LPC_SERIAL_IRQ_CTRL = 0xc0;
++      for(i=0;i<1000;i++) ;
++      LPC_SERIAL_IRQ_CTRL = 0x80;
++      /*
++       * Finally, enable interrupts. Use the TII interrupt to minimise
++       * the number of interrupts generated. If higher performance is
++       * needed, consider using the TI interrupt with a suitable FIFO
++       * threshold
++       */
++      //UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
++      UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI|UART_IER_RLSI));//middle
++
++      return 0;
++}
++
++static void it8712_shutdown(struct uart_port *port)
++{
++        //printk("it8712 shutdown : \n");
++
++      /*
++       * disable all interrupts, disable the port
++       */
++      UART_PUT_IER(port, 0x0);
++
++      /* disable break condition and fifos */
++//    UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
++
++      /*
++       * Free the interrupt
++       */
++      free_irq(port->irq, port);
++}
++
++static const char *it8712_type(struct uart_port *port)
++{
++      return port->type == PORT_IT8712 ? "IT8712" : NULL;
++}
++
++/*
++ * Release the memory region(s) being used by 'port'
++ */
++static void it8712_release_port(struct uart_port *port)
++{
++//        printk("it8712 release port : \n");
++
++      release_mem_region(port->mapbase, UART_PORT_SIZE);
++}
++
++/*
++ * Request the memory region(s) being used by 'port'
++ */
++static int it8712_request_port(struct uart_port *port)
++{
++      return request_mem_region(port->mapbase, UART_PORT_SIZE,
++                                  "serial_it8712") != NULL ? 0 : -EBUSY;
++}
++
++/*
++ * Configure/autoconfigure the port.
++ */
++static void it8712_config_port(struct uart_port *port, int flags)
++{
++
++      if (flags & UART_CONFIG_TYPE) {
++              if (it8712_request_port(port) == 0)
++                      port->type = PORT_IT8712;
++      }
++}
++
++/*
++ * verify the new serial_struct (for TIOCSSERIAL).
++ */
++static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++      int ret = 0;
++
++      if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
++              ret = -EINVAL;
++      if (ser->irq < 0 || ser->irq >= NR_IRQS)
++              ret = -EINVAL;
++      if (ser->baud_base < 9600)
++              ret = -EINVAL;
++      return ret;
++}
++
++static struct uart_ops it8712_pops = {
++      .tx_empty       = it8712_tx_empty,
++      .set_mctrl      = it8712_set_mctrl_null,
++      .get_mctrl      = it8712_get_mctrl,
++      .stop_tx        = it8712_stop_tx,
++      .start_tx       = it8712_start_tx,
++      .stop_rx        = it8712_stop_rx,
++      .enable_ms      = it8712_enable_ms,
++      .break_ctl      = it8712_break_ctl,
++      .startup        = it8712_startup,
++      .shutdown       = it8712_shutdown,
++      .set_termios    = it8712_set_termios,
++      .type           = it8712_type,
++      .release_port   = it8712_release_port,
++      .request_port   = it8712_request_port,
++      .config_port    = it8712_config_port,
++      .verify_port    = it8712_verify_port,
++};
++
++#ifdef CONFIG_ARCH_SL2312
++
++static struct uart_port it8712_ports[UART_NR] = {
++      {
++              membase:        (void *)0,
++              mapbase:        0,
++              iotype:         SERIAL_IO_MEM,
++              irq:            0,
++              uartclk:        UART_CLK/2,
++              fifosize:       16,
++              ops:            &it8712_pops,
++              flags:          ASYNC_BOOT_AUTOCONF,
++      }
++};
++
++#endif
++
++#ifdef CONFIG_SERIAL_IT8712_CONSOLE
++#ifdef used_and_not_const_char_pointer
++static int it8712_console_read(struct uart_port *port, char *s, u_int count)
++{
++      unsigned int status;
++      int c;
++#ifdef DEBUG
++      printk("it8712_console_read() called\n");
++#endif
++
++      c = 0;
++      while (c < count) {
++              status = UART_GET_LSR(port);
++              if (UART_RX_DATA(status)) {
++                      *s++ = UART_GET_CHAR(port);
++                      c++;
++              } else {
++                      // nothing more to get, return
++                      return c;
++              }
++      }
++      // return the count
++      return c;
++}
++#endif
++static void it8712_console_write(struct console *co, const char *s, unsigned count)
++{
++#ifdef CONFIG_ARCH_SL2312
++      struct uart_port *port = it8712_ports + co->index;
++      unsigned int status, old_ies;
++      int i;
++
++      /*
++       *      First save the CR then disable the interrupts
++       */
++      old_ies = UART_GET_IER(port);
++      //if(old_ies!=7)
++      //{
++      //
++      //      printk("old_ies = %x\n",old_ies);
++      //      old_ies = 7;
++      //}
++      UART_PUT_IER(port,0x0);
++
++      /*
++       *      Now, do each character
++       */
++      for (i = 0; i < count; i++) {
++              do {
++                      status = UART_GET_LSR(port);
++              } while (!UART_TX_READY(status));
++              UART_PUT_CHAR(port, s[i]);
++              if (s[i] == '\n') {
++                      do {
++                              status = UART_GET_LSR(port);
++                      } while (!UART_TX_READY(status));
++                      UART_PUT_CHAR(port, '\r');
++              }
++      }
++
++      /*
++       *      Finally, wait for transmitter to become empty
++       *      and restore the IES
++       */
++      do {
++              status = UART_GET_LSR(port);
++      } while (!(status&UART_LSR_THRE));
++      UART_PUT_IER(port, old_ies);
++#endif
++}
++
++static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
++{
++      //printk("it8712 console get options : \n");
++
++      u_int uart_mc, quot;
++      uart_mc= UART_GET_MCR(port);
++
++      *parity = 'n';
++      if (uart_mc & UART_LCR_PARITY) {
++              if (uart_mc & UART_LCR_EVEN)
++                      *parity = 'e';
++              else
++                      *parity = 'o';
++      }
++
++      switch (uart_mc & UART_LCR_MSK){
++
++      case UART_LCR_WLEN5:
++              *bits = 5;
++              break;
++      case UART_LCR_WLEN6:
++              *bits = 6;
++              break;
++      case UART_LCR_WLEN7:
++              *bits = 7;
++              break;
++      case UART_LCR_WLEN8:
++              *bits = 8;
++              break;
++      }
++      UART_PUT_MCR(port,UART_LCR_DLAB);
++      quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
++      UART_PUT_MCR(port,uart_mc);
++      *baud = (port->uartclk / (16 *quot));
++}
++
++static int __init it8712_console_setup(struct console *co, char *options)
++{
++      struct uart_port *port;
++      int baud = 38400;
++      int bits = 8;
++      int parity = 'n';
++      int flow= 'n';
++      int base;//, irq;
++      int i ;
++
++      printk("it8712 console setup : \n");
++
++      LPCSetConfig(0, 0x02, 0x01);
++        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
++        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
++      base = IT8712_IO_BASE;
++      base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
++      it8712_ports[0].mapbase = base;
++      it8712_ports[0].membase = (void *)IO_ADDRESS(base);
++      it8712_ports[0].irq = IRQ_LPC_OFFSET;
++    //        irq = LPCGetConfig(LDN_SERIAL1, 0x70);
++      //it8712_ports[0].irq += irq;
++
++      //printk("it8712 irq is %x \n", it8712_ports[0].irq);
++
++      // setup LPC Host 'quiet mode'
++      //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
++      //for(i=0;i<1000;i++) ;                                         // delay
++      //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
++      LPC_BUS_CTRL = 0xc0;
++      LPC_SERIAL_IRQ_CTRL = 0xc0;
++      for(i=0;i<1000;i++) ;
++      LPC_SERIAL_IRQ_CTRL = 0x80;
++
++#ifdef CONFIG_ARCH_SL2312
++      /*
++       * Check whether an invalid uart number has been specified, and
++       * if so, search for the first available port that does have
++       * console support.
++       */
++      port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
++#else
++      return -ENODEV;
++#endif
++
++      if (options)
++              uart_parse_options(options, &baud, &parity, &bits, &flow);
++      else
++              it8712_console_get_options(port, &baud, &parity, &bits);
++
++      return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++extern struct uart_driver it8712_reg;
++static struct console it8712_console = {
++      .name           = SERIAL_IT8712_NAME,
++      .write          = it8712_console_write,
++      .device         = uart_console_device,
++        .setup          = it8712_console_setup,
++      .flags          = CON_PRINTBUFFER,
++      .index          = 0,
++        .data           = &it8712_reg,
++};
++
++static int __init it8712_console_init(void)
++{
++      register_console(&it8712_console);
++        return 0;
++}
++
++console_initcall(it8712_console_init);
++
++#define IT8712_CONSOLE        &it8712_console
++#else
++#define IT8712_CONSOLE        NULL
++#endif
++
++static struct uart_driver it8712_reg = {
++      .owner                  = NULL,
++      .driver_name            = SERIAL_IT8712_NAME,
++      .dev_name               = SERIAL_IT8712_NAME,
++        .major                  = SERIAL_IT8712_MAJOR,
++      .minor                  = SERIAL_IT8712_MINOR,
++      .nr                     = UART_NR,
++      .cons                   = IT8712_CONSOLE,
++};
++
++static int __init it8712_init(void)
++{
++        int result;
++      //printk("serial_it8712: it871212_init \n");
++
++
++        result = uart_register_driver(&it8712_reg);
++        if(result)
++             return result;
++      result = uart_add_one_port(&it8712_reg, &it8712_ports[0]);
++
++        return result;
++
++}
++
++
++__initcall(it8712_init);
+--- /dev/null
++++ b/drivers/serial/it8712.h
+@@ -0,0 +1,135 @@
++#define UART_RX               0       /* In:  Receive buffer (DLAB=0) */
++#define UART_TX               0       /* Out: Transmit buffer (DLAB=0) */
++#define UART_DLL      0       /* Out: Divisor Latch Low (DLAB=1) */
++#define UART_TRG      0       /* (LCR=BF) FCTR bit 7 selects Rx or Tx
++                               * In: Fifo count
++                               * Out: Fifo custom trigger levels
++                               * XR16C85x only */
++
++#define UART_DLM      1       /* Out: Divisor Latch High (DLAB=1) */
++#define UART_IER      1       /* Out: Interrupt Enable Register */
++#define UART_FCTR     1       /* (LCR=BF) Feature Control Register
++                               * XR16C85x only */
++
++#define UART_IIR      2       /* In:  Interrupt ID Register */
++#define UART_FCR      2       /* Out: FIFO Control Register */
++#define UART_EFR      2       /* I/O: Extended Features Register */
++                              /* (DLAB=1, 16C660 only) */
++
++#define UART_LCR      3       /* Out: Line Control Register */
++#define UART_MCR      4       /* Out: Modem Control Register */
++#define UART_LSR      5       /* In:  Line Status Register */
++#define UART_MSR      6       /* In:  Modem Status Register */
++#define UART_SCR      7       /* I/O: Scratch Register */
++#define UART_EMSR     7       /* (LCR=BF) Extended Mode Select Register
++                               * FCTR bit 6 selects SCR or EMSR
++                               * XR16c85x only */
++
++/*
++ * These are the definitions for the FIFO Control Register
++ * (16650 only)
++ */
++#define UART_FCR_ENABLE_FIFO  0x01 /* Enable the FIFO */
++#define UART_FCR_CLEAR_RCVR   0x02 /* Clear the RCVR FIFO */
++#define UART_FCR_CLEAR_XMIT   0x04 /* Clear the XMIT FIFO */
++#define UART_FCR_DMA_SELECT   0x08 /* For DMA applications */
++#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
++#define UART_FCR_TRIGGER_1    0x00 /* Mask for trigger set at 1 */
++#define UART_FCR_TRIGGER_4    0x40 /* Mask for trigger set at 4 */
++#define UART_FCR_TRIGGER_8    0x80 /* Mask for trigger set at 8 */
++#define UART_FCR_TRIGGER_14   0xC0 /* Mask for trigger set at 14 */
++/* 16650 redefinitions */
++#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
++#define UART_FCR6_R_TRIGGER_16        0x40 /* Mask for receive trigger set at 4 */
++#define UART_FCR6_R_TRIGGER_24  0x80 /* Mask for receive trigger set at 8 */
++#define UART_FCR6_R_TRIGGER_28        0xC0 /* Mask for receive trigger set at 14 */
++#define UART_FCR6_T_TRIGGER_16        0x00 /* Mask for transmit trigger set at 16 */
++#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
++#define UART_FCR6_T_TRIGGER_24  0x20 /* Mask for transmit trigger set at 24 */
++#define UART_FCR6_T_TRIGGER_30        0x30 /* Mask for transmit trigger set at 30 */
++/* TI 16750 definitions */
++#define UART_FCR7_64BYTE      0x20 /* Go into 64 byte mode */
++
++/*
++ * These are the definitions for the Line Control Register
++ *
++ * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
++ * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
++ */
++#define UART_LCR_DLAB 0x80    /* Divisor latch access bit */
++#define UART_LCR_SBC  0x40    /* Set break control */
++#define UART_LCR_SPAR 0x20    /* Stick parity (?) */
++#define UART_LCR_EPAR 0x10    /* Even parity select */
++#define UART_LCR_PARITY       0x08    /* Parity Enable */
++#define UART_LCR_STOP 0x04    /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
++#define UART_LCR_WLEN5  0x00  /* Wordlength: 5 bits */
++#define UART_LCR_WLEN6  0x01  /* Wordlength: 6 bits */
++#define UART_LCR_WLEN7  0x02  /* Wordlength: 7 bits */
++#define UART_LCR_WLEN8  0x03  /* Wordlength: 8 bits */
++#define UART_LCR_EVEN   0x18    /* Even parity */
++#define UART_LCR_ODD    0x08    /* Odd parity */
++#define UART_LCR_MSK    0x03
++/*
++ * These are the definitions for the Line Status Register
++ */
++#define UART_LSR_DE     0x80    /* FIFO Data Error */
++#define UART_LSR_TEMT 0x40    /* Transmitter empty */
++#define UART_LSR_THRE 0x20    /* Transmit-hold-register empty */
++#define UART_LSR_BI   0x10    /* Break interrupt indicator */
++#define UART_LSR_FE   0x08    /* Frame error indicator */
++#define UART_LSR_PE   0x04    /* Parity error indicator */
++#define UART_LSR_OE   0x02    /* Overrun error indicator */
++#define UART_LSR_DR   0x01    /* Receiver data ready */
++
++/*
++ * These are the definitions for the Interrupt Identification Register
++ */
++#define UART_IIR_NO_INT       0x01    /* No interrupts pending */
++#define UART_IIR_ID   0x06    /* Mask for the interrupt ID */
++
++#define UART_IIR_MSI  0x00    /* Modem status interrupt */
++#define UART_IIR_THRI 0x02    /* Transmitter holding register empty */
++#define UART_IIR_RDI  0x04    /* Receiver data interrupt */
++#define UART_IIR_RLSI 0x06    /* Receiver line status interrupt */
++#define UART_IIR_RCTO 0x0c    /* Receiver character timeout interrupt */
++/*
++ * These are the definitions for the Interrupt Enable Register
++ */
++#define UART_IER_MSI  0x08    /* Enable Modem status interrupt */
++#define UART_IER_RLSI 0x04    /* Enable receiver line status interrupt */
++#define UART_IER_THRI 0x02    /* Enable Transmitter holding register int. */
++#define UART_IER_RDI  0x01    /* Enable receiver data interrupt */
++/*
++ * Sleep mode for ST16650 and TI16750.
++ * Note that for 16650, EFR-bit 4 must be selected as well.
++ */
++#define UART_IERX_SLEEP  0x10 /* Enable sleep mode */
++
++/*
++ * These are the definitions for the Modem Control Register
++ */
++#define UART_MCR_LOOP 0x10    /* Enable loopback test mode */
++#define UART_MCR_OUT2 0x08    /* Out2 complement */
++#define UART_MCR_OUT1 0x04    /* Out1 complement */
++#define UART_MCR_RTS  0x02    /* RTS complement */
++#define UART_MCR_DTR  0x01    /* DTR complement */
++
++/*
++ * These are the definitions for the Modem Status Register
++ */
++#define UART_MSR_DCD  0x80    /* Data Carrier Detect */
++#define UART_MSR_RI   0x40    /* Ring Indicator */
++#define UART_MSR_DSR  0x20    /* Data Set Ready */
++#define UART_MSR_CTS  0x10    /* Clear to Send */
++#define UART_MSR_DDCD 0x08    /* Delta DCD */
++#define UART_MSR_TERI 0x04    /* Trailing edge ring indicator */
++#define UART_MSR_DDSR 0x02    /* Delta DSR */
++#define UART_MSR_DCTS 0x01    /* Delta CTS */
++#define UART_MSR_ANY_DELTA 0x0F       /* Any of the delta bits! */
++
++#define UART_PARITY_NONE      0x00
++#define UART_PARITY_ODD               0x01
++#define UART_PARITY_EVEN      0x02
++
++
++
+--- /dev/null
++++ b/drivers/serial/serial_it8712.c
+@@ -0,0 +1,876 @@
++/*
++ *  linux/drivers/char/serial_uart00.c
++ *
++ *  Driver for UART00 serial ports
++ *
++ *  Based on drivers/char/serial_amba.c, by ARM Limited &
++ *                                          Deep Blue Solutions Ltd.
++ *  Copyright 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *  $Id: serial_it8712.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
++ *
++ */
++#include <linux/module.h>
++
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/circ_buf.h>
++#include <linux/serial.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/sizes.h>
++
++#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/serial_core.h>
++#include <asm/arch/sl2312.h>
++#include <asm/arch/int_ctrl.h>
++#include <asm/arch/it8712.h>
++#include "serial_it8712.h"
++
++//#define DEBUG           1
++#define UART_NR               1
++
++#define SERIAL_IT8712_NAME    "ttySI"
++#define SERIAL_IT8712_MAJOR   204
++#define SERIAL_IT8712_MINOR   41      /* Temporary - will change in future */
++#define SERIAL_IT8712_NR      UART_NR
++#define UART_PORT_SIZE 0x50
++
++#define CALLOUT_IT8712_NAME   "cuaslI"
++#define CALLOUT_IT8712_MAJOR  205
++#define CALLOUT_IT8712_MINOR  41      /* Temporary - will change in future */
++#define CALLOUT_IT8712_NR     UART_NR
++#define LPC_HOST_CONTINUE_MODE        0x00000040
++
++#define IT8712_NO_PORTS         UART_NR
++
++static struct tty_driver normal, callout;
++static struct tty_struct *it8712_table[UART_NR];
++static struct termios *it8712_termios[UART_NR], *it8712_termios_locked[UART_NR];
++static struct console it8712_console;
++
++#define IT8712_ISR_PASS_LIMIT 256
++
++/*
++ * Access macros for the SL2312 UARTs
++ */
++#define UART_GET_INT_STATUS(p)        (inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
++#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
++#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
++#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
++#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
++#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
++#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
++#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
++#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
++#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
++#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
++#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
++#define UART_GET_DIV_HI(p)    inb(((p)->membase+UART_DLM))
++#define UART_PUT_DIV_HI(p, c) outb(c,((p)->membase+UART_DLM))
++#define UART_GET_DIV_LO(p)    inb(((p)->membase+UART_DLL))
++#define UART_PUT_DIV_LO(p, c) outb(c,((p)->membase+UART_DLL))
++#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
++#define UART_RX_DATA(s)               ((s) & UART_LSR_DR)
++#define UART_TX_READY(s)      ((s) & UART_LSR_THRE)
++
++static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
++{
++        unsigned int reg;
++
++//        printk("it8712 stop tx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_THRI);
++      UART_PUT_IER(port, reg);
++}
++
++static void it8712_stop_rx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("it8712 stop rx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_RDI);
++      UART_PUT_IER(port, reg);
++
++}
++
++static void it8712_enable_ms(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("it8712 enable ms : \n");
++
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_MSI);
++      UART_PUT_IER(port, reg);
++
++}
++
++static void
++it8712_rx_chars(struct uart_info *info, struct pt_regs *regs)
++{
++      struct tty_struct *tty = info->tty;
++      unsigned int status, mask, ch, flg, ignored = 0;
++      struct uart_port *port = info->port;
++
++ //       printk("it8712_rx_chars : \n");
++      status = UART_GET_LSR(port);
++      while (UART_RX_DATA(status)) {
++
++              /*
++               * We need to read rds before reading the
++               * character from the fifo
++               */
++              ch = UART_GET_CHAR(port);
++              port->icount.rx++;
++
++              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++                      goto ignore_char;
++
++              flg = TTY_NORMAL;
++
++              /*
++               * Note that the error handling code is
++               * out of the main execution path
++               */
++
++              if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
++                      goto handle_error;
++              if (uart_handle_sysrq_char(info, ch, regs))
++                      goto ignore_char;
++
++      error_return:
++              *tty->flip.flag_buf_ptr++ = flg;
++              *tty->flip.char_buf_ptr++ = ch;
++              tty->flip.count++;
++      ignore_char:
++              status = UART_GET_LSR(port);
++      } // end of while
++out:
++      tty_flip_buffer_push(tty);
++      return;
++
++handle_error:
++      if (status & UART_LSR_BI) {
++              status &= ~(UART_LSR_FE);
++              port->icount.brk++;
++
++#ifdef SUPPORT_SYSRQ
++              if (uart_handle_break(info, &it8712_console))
++                      goto ignore_char;
++#endif
++      } else if (status & UART_LSR_PE)
++              port->icount.parity++;
++      else if (status & UART_LSR_FE)
++              port->icount.frame++;
++
++      if (status & UART_LSR_OE)
++              port->icount.overrun++;
++
++      if (status & port->ignore_status_mask) {
++              if (++ignored > 100)
++                      goto out;
++              goto ignore_char;
++      }
++
++      mask = status & port->read_status_mask;
++
++      if (mask & UART_LSR_BI)
++              flg = TTY_BREAK;
++      else if (mask & UART_LSR_PE)
++              flg = TTY_PARITY;
++      else if (mask & UART_LSR_FE)
++              flg = TTY_FRAME;
++
++      if (status & UART_LSR_OE) {
++              /*
++               * CHECK: does overrun affect the current character?
++               * ASSUMPTION: it does not.
++               */
++              *tty->flip.flag_buf_ptr++ = flg;
++              *tty->flip.char_buf_ptr++ = ch;
++              tty->flip.count++;
++              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++                      goto ignore_char;
++              ch = 0;
++              flg = TTY_OVERRUN;
++      }
++#ifdef SUPPORT_SYSRQ
++      info->sysrq = 0;
++#endif
++      goto error_return;
++}
++
++static void it8712_tx_chars(struct uart_info *info)
++{
++      int count;
++      struct uart_port *port=info->port;
++
++      if (port->x_char) {
++              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++              UART_PUT_CHAR(port, port->x_char);
++              port->icount.tx++;
++              port->x_char = 0;
++
++              return;
++      }
++      if (info->xmit.head == info->xmit.tail
++          || info->tty->stopped
++          || info->tty->hw_stopped) {
++              it8712_stop_tx(info->port, 0);
++              return;
++      }
++
++      count = port->fifosize >> 1;
++      do {
++              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++              UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
++              info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
++              port->icount.tx++;
++              if (info->xmit.head == info->xmit.tail)
++                      break;
++      } while (--count > 0);
++
++      if (CIRC_CNT(info->xmit.head,
++                   info->xmit.tail,
++                   UART_XMIT_SIZE) < WAKEUP_CHARS)
++              uart_event(info, EVT_WRITE_WAKEUP);
++
++      if (info->xmit.head == info->xmit.tail)
++              it8712_stop_tx(info->port, 0);
++}
++
++static void it8712_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
++{
++        unsigned int reg;
++      struct uart_info *info=(struct uart_info*)(port->iobase);
++
++//        printk("it8712 start tx : \n");
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_THRI);
++      UART_PUT_IER(port, reg);
++      it8712_tx_chars(info);
++}
++
++static void it8712_modem_status(struct uart_info *info)
++{
++      unsigned int status;
++      struct uart_icount *icount = &info->port->icount;
++
++//        printk("it8712 modem status : \n");
++
++      status = UART_GET_MSR(info->port);
++
++      if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
++                     UART_MSR_TERI | UART_MSR_DDCD)))
++              return;
++
++      if (status & UART_MSR_DCD) {
++              icount->dcd++;
++#ifdef CONFIG_HARD_PPS
++              if ((info->flags & ASYNC_HARDPPS_CD) &&
++                  (status & UART_MSR_DCD_MSK))
++                      hardpps();
++#endif
++              if (info->flags & ASYNC_CHECK_CD) {
++                      if (status & UART_MSR_DCD)
++                              wake_up_interruptible(&info->open_wait);
++                      else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
++                                 (info->flags & ASYNC_CALLOUT_NOHUP))) {
++                              if (info->tty)
++                                      tty_hangup(info->tty);
++                      }
++              }
++      }
++
++      if (status & UART_MSR_DDSR)
++              icount->dsr++;
++
++      if (status & UART_MSR_DCTS) {
++              icount->cts++;
++
++              if (info->flags & ASYNC_CTS_FLOW) {
++                      status &= UART_MSR_CTS;
++
++                      if (info->tty->hw_stopped) {
++                              if (status) {
++                                      info->tty->hw_stopped = 0;
++                                      info->ops->start_tx(info->port, 1, 0);
++                                      uart_event(info, EVT_WRITE_WAKEUP);
++                              }
++                      } else {
++                              if (!status) {
++                                      info->tty->hw_stopped = 1;
++                                      info->ops->stop_tx(info->port, 0);
++                              }
++                      }
++              }
++      }
++      wake_up_interruptible(&info->delta_msr_wait);
++
++}
++
++static void it8712_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct uart_info *info = dev_id;
++      unsigned int status, pass_counter = 0;
++
++      status = UART_GET_INT_STATUS(info->port);
++      do {
++//                 printk("it8712_int: status %x \n", status);
++              switch(status)
++              {
++                 case UART_IIR_RDI:
++                 case UART_IIR_RLSI:
++                 case UART_IIR_RCTO:
++                      it8712_rx_chars(info, regs);
++                 break;
++                 case UART_IIR_THRI:
++                      it8712_tx_chars(info);
++                 break;
++                 case UART_IIR_MSI:
++                      it8712_modem_status(info);
++                 break;
++                 default:
++                 break;
++              }
++              if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
++                      break;
++
++              status = UART_GET_INT_STATUS(info->port);
++      } while (status);
++}
++
++static u_int it8712_tx_empty(struct uart_port *port)
++{
++//        printk("it8712 tx empty : \n");
++
++      return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
++}
++
++static u_int it8712_get_mctrl(struct uart_port *port)
++{
++      unsigned int result = 0;
++      unsigned int status;
++
++//        printk("it8712 get mctrl : \n");
++
++      status = UART_GET_MSR(port);
++      if (status & UART_MSR_DCD)
++              result |= TIOCM_CAR;
++      if (status & UART_MSR_DSR)
++              result |= TIOCM_DSR;
++      if (status & UART_MSR_CTS)
++              result |= TIOCM_CTS;
++      if (status & UART_MSR_RI)
++              result |= TIOCM_RI;
++
++      return result;
++}
++
++static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
++{
++}
++
++static void it8712_break_ctl(struct uart_port *port, int break_state)
++{
++      unsigned int lcr;
++
++//        printk("it8712 break ctl : \n");
++
++      lcr = UART_GET_LCR(port);
++      if (break_state == -1)
++              lcr |= UART_LCR_SBC;
++      else
++              lcr &= ~UART_LCR_SBC;
++      UART_PUT_LCR(port, lcr);
++}
++
++static inline u_int uart_calculate_quot(struct uart_info *info, u_int baud)
++{
++      u_int quot;
++
++      /* Special case: B0 rate */
++      if (!baud)
++              baud = 9600;
++
++      quot = (info->port->uartclk/(16 * baud)) ;
++
++      return quot;
++}
++static void it8712_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
++{
++      u_int uart_mc=0, old_ier;
++      unsigned long flags;
++
++#ifdef DEBUG
++      printk("it8712_set_cflag(0x%x) called\n", cflag);
++#endif
++
++
++      /* byte size and parity */
++      switch (cflag & CSIZE) {
++      case CS5: uart_mc = UART_LCR_WLEN5; break;
++      case CS6: uart_mc = UART_LCR_WLEN6; break;
++      case CS7: uart_mc = UART_LCR_WLEN7; break;
++      default:  uart_mc = UART_LCR_WLEN8; break; // CS8
++      }
++      if (cflag & CSTOPB)
++              uart_mc|= UART_LCR_STOP;
++      if (cflag & PARENB) {
++              uart_mc |= UART_LCR_EVEN;
++              if (!(cflag & PARODD))
++                      uart_mc |= UART_LCR_ODD;
++      }
++
++      port->read_status_mask = UART_LSR_OE;
++      if (iflag & INPCK)
++              port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++      if (iflag & (BRKINT | PARMRK))
++              port->read_status_mask |= UART_LSR_BI;
++
++      /*
++       * Characters to ignore
++       */
++      port->ignore_status_mask = 0;
++      if (iflag & IGNPAR)
++              port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
++      if (iflag & IGNBRK) {
++              port->ignore_status_mask |= UART_LSR_BI;
++              /*
++               * If we're ignoring parity and break indicators,
++               * ignore overruns to (for real raw support).
++               */
++              if (iflag & IGNPAR)
++                      port->ignore_status_mask |= UART_LSR_OE;
++      }
++
++      /* first, disable everything */
++      save_flags(flags); cli();
++      old_ier = UART_GET_IER(port);
++
++      if ((port->flags & ASYNC_HARDPPS_CD) ||
++          (cflag & CRTSCTS) || !(cflag & CLOCAL))
++              old_ier |= UART_IER_MSI;
++
++      /* Set baud rate */
++      quot = quot / 13;
++      UART_PUT_LCR(port, UART_LCR_DLAB);
++      UART_PUT_DIV_LO(port, (quot & 0xff));
++      UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
++
++      UART_PUT_LCR(port, uart_mc);
++//    UART_PUT_LCR(port, 0x07); // ???? it is wired
++        UART_PUT_MCR(port, 0x08);
++        UART_PUT_FCR(port, 0x01);
++      UART_PUT_IER(port, 0x05);
++
++      restore_flags(flags);
++}
++
++static int it8712_startup(struct uart_port *port, struct uart_info *info)
++{
++      int retval;
++      unsigned int regs;
++
++//        printk("it8712 startup : \n");
++
++      /*
++       * Use iobase to store a pointer to info. We need this to start a
++       * transmission as the tranmittr interrupt is only generated on
++       * the transition to the idle state
++       */
++
++      port->iobase=(u_int)info;
++
++      /*
++       * Allocate the IRQ
++       */
++      retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", info);
++      if (retval)
++              return retval;
++
++        /* setup interrupt controller  */
++        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs |= (IRQ_SERIRQ0_MASK);
++        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        regs = *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_SERIRQ0_MASK);
++        *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_SERIRQ0_MASK);
++
++      /*
++       * Finally, enable interrupts. Use the TII interrupt to minimise
++       * the number of interrupts generated. If higher performance is
++       * needed, consider using the TI interrupt with a suitable FIFO
++       * threshold
++       */
++      UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
++
++      return 0;
++}
++
++static void it8712_shutdown(struct uart_port *port, struct uart_info *info)
++{
++//        printk("it8712 shutdown : \n");
++
++      /*
++       * disable all interrupts, disable the port
++       */
++      UART_PUT_IER(port, 0x0);
++
++      /* disable break condition and fifos */
++//    UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
++
++      /*
++       * Free the interrupt
++       */
++      free_irq(port->irq, info);
++}
++
++static const char *it8712_type(struct uart_port *port)
++{
++      return port->type == PORT_IT8712 ? "IT8712" : NULL;
++}
++
++/*
++ * Release the memory region(s) being used by 'port'
++ */
++static void it8712_release_port(struct uart_port *port)
++{
++//        printk("it8712 release port : \n");
++
++      release_mem_region(port->mapbase, UART_PORT_SIZE);
++}
++
++/*
++ * Request the memory region(s) being used by 'port'
++ */
++static int it8712_request_port(struct uart_port *port)
++{
++      return request_mem_region(port->mapbase, UART_PORT_SIZE,
++                                  "serial_it8712") != NULL ? 0 : -EBUSY;
++}
++
++/*
++ * Configure/autoconfigure the port.
++ */
++static void it8712_config_port(struct uart_port *port, int flags)
++{
++
++      if (flags & UART_CONFIG_TYPE) {
++              if (it8712_request_port(port) == 0)
++                      port->type = PORT_IT8712;
++      }
++}
++
++/*
++ * verify the new serial_struct (for TIOCSSERIAL).
++ */
++static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++      int ret = 0;
++
++      if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
++              ret = -EINVAL;
++      if (ser->irq < 0 || ser->irq >= NR_IRQS)
++              ret = -EINVAL;
++      if (ser->baud_base < 9600)
++              ret = -EINVAL;
++      return ret;
++}
++
++static struct uart_ops it8712_pops = {
++      tx_empty:       it8712_tx_empty,
++      set_mctrl:      it8712_set_mctrl_null,
++      get_mctrl:      it8712_get_mctrl,
++      stop_tx:        it8712_stop_tx,
++      start_tx:       it8712_start_tx,
++      stop_rx:        it8712_stop_rx,
++      enable_ms:      it8712_enable_ms,
++      break_ctl:      it8712_break_ctl,
++      startup:        it8712_startup,
++      shutdown:       it8712_shutdown,
++      change_speed:   it8712_change_speed,
++      type:           it8712_type,
++      release_port:   it8712_release_port,
++      request_port:   it8712_request_port,
++      config_port:    it8712_config_port,
++      verify_port:    it8712_verify_port,
++};
++
++#ifdef CONFIG_ARCH_SL2312
++
++static struct uart_port it8712_ports[UART_NR] = {
++      {
++              membase:        (void *)0,
++              mapbase:        0,
++              iotype:         SERIAL_IO_MEM,
++              irq:            0,
++              uartclk:        UART_CLK/2,
++              fifosize:       16,
++              ops:            &it8712_pops,
++              flags:          ASYNC_BOOT_AUTOCONF,
++      }
++};
++
++#endif
++
++#ifdef CONFIG_SERIAL_IT8712_CONSOLE
++#ifdef used_and_not_const_char_pointer
++static int it8712_console_read(struct uart_port *port, char *s, u_int count)
++{
++      unsigned int status;
++      int c;
++#ifdef DEBUG
++      printk("it8712_console_read() called\n");
++#endif
++
++      c = 0;
++      while (c < count) {
++              status = UART_GET_LSR(port);
++              if (UART_RX_DATA(status)) {
++                      *s++ = UART_GET_CHAR(port);
++                      c++;
++              } else {
++                      // nothing more to get, return
++                      return c;
++              }
++      }
++      // return the count
++      return c;
++}
++#endif
++static void it8712_console_write(struct console *co, const char *s, unsigned count)
++{
++#ifdef CONFIG_ARCH_SL2312
++      struct uart_port *port = it8712_ports + co->index;
++      unsigned int status, old_ies;
++      int i;
++
++      /*
++       *      First save the CR then disable the interrupts
++       */
++      old_ies = UART_GET_IER(port);
++      UART_PUT_IER(port,0x0);
++
++      /*
++       *      Now, do each character
++       */
++      for (i = 0; i < count; i++) {
++              do {
++                      status = UART_GET_LSR(port);
++              } while (!UART_TX_READY(status));
++              UART_PUT_CHAR(port, s[i]);
++              if (s[i] == '\n') {
++                      do {
++                              status = UART_GET_LSR(port);
++                      } while (!UART_TX_READY(status));
++                      UART_PUT_CHAR(port, '\r');
++              }
++      }
++
++      /*
++       *      Finally, wait for transmitter to become empty
++       *      and restore the IES
++       */
++      do {
++              status = UART_GET_LSR(port);
++      } while (!(status&UART_LSR_THRE));
++      UART_PUT_IER(port, old_ies);
++#endif
++}
++
++static kdev_t it8712_console_device(struct console *co)
++{
++      return MKDEV(SERIAL_IT8712_MAJOR, SERIAL_IT8712_MINOR + co->index);
++}
++
++static int it8712_console_wait_key(struct console *co)
++{
++#ifdef CONFIG_ARCH_SL2312
++      struct uart_port *port = (it8712_ports + co->index);
++      unsigned int status;
++
++      do {
++              status = UART_GET_LSR(port);
++      } while (!UART_RX_DATA(status));
++      return UART_GET_CHAR(port);
++#else
++      return 0;
++#endif
++}
++
++static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
++{
++      printk("it8712 console get options : \n");
++
++      u_int uart_mc, quot;
++      uart_mc= UART_GET_MCR(port);
++
++      *parity = 'n';
++      if (uart_mc & UART_LCR_PARITY) {
++              if (uart_mc & UART_LCR_EVEN)
++                      *parity = 'e';
++              else
++                      *parity = 'o';
++      }
++
++      switch (uart_mc & UART_LCR_MSK){
++
++      case UART_LCR_WLEN5:
++              *bits = 5;
++              break;
++      case UART_LCR_WLEN6:
++              *bits = 6;
++              break;
++      case UART_LCR_WLEN7:
++              *bits = 7;
++              break;
++      case UART_LCR_WLEN8:
++              *bits = 8;
++              break;
++      }
++      UART_PUT_MCR(port,UART_LCR_DLAB);
++      quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
++      UART_PUT_MCR(port,uart_mc);
++      *baud = (port->uartclk / (16 *quot));
++}
++
++static int __init it8712_console_setup(struct console *co, char *options)
++{
++      struct uart_port *port;
++      int baud = 38400;
++      int bits = 8;
++      int parity = 'n';
++      int flow= 'n';
++      int base, irq;
++      int i ;
++
++//    printk("it8712 console setup : \n");
++
++      LPCSetConfig(0, 0x02, 0x01);
++        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
++        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
++      base = IT8712_IO_BASE;
++      base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
++      it8712_ports[0].mapbase = base;
++      it8712_ports[0].membase = IO_ADDRESS(base);
++      it8712_ports[0].irq = IRQ_SERIRQ0_OFFSET;
++              irq = LPCGetConfig(LDN_SERIAL1, 0x70);
++      it8712_ports[0].irq += irq;
++
++      printk("it8712 irq is %x %x \n", it8712_ports[0].irq, irq);
++
++      // setup LPC Host 'quiet mode'
++      *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
++      for(i=0;i<1000;i++) ;                                           // delay
++      *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
++
++#ifdef CONFIG_ARCH_SL2312
++      /*
++       * Check whether an invalid uart number has been specified, and
++       * if so, search for the first available port that does have
++       * console support.
++       */
++      port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
++#else
++      return -ENODEV;
++#endif
++
++      if (options)
++              uart_parse_options(options, &baud, &parity, &bits, &flow);
++      else
++              it8712_console_get_options(port, &baud, &parity, &bits);
++
++      return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++static struct console it8712_console = {
++      name:           SERIAL_IT8712_NAME,
++      write:          it8712_console_write,
++#ifdef used_and_not_const_char_pointer
++      read:           it8712_console_read,
++#endif
++      device:         it8712_console_device,
++//    wait_key:       it8712_console_wait_key,
++      setup:          it8712_console_setup,
++      flags:          (CON_PRINTBUFFER|CON_ENABLED),
++      index:          -1,
++};
++
++void __init it8712_console_init(void)
++{
++      register_console(&it8712_console);
++}
++
++#define IT8712_CONSOLE        &it8712_console
++#else
++#define IT8712_CONSOLE        NULL
++#endif
++
++static struct uart_driver it8712_reg = {
++      owner:                  NULL,
++      normal_major:           SERIAL_IT8712_MAJOR,
++      normal_name:            SERIAL_IT8712_NAME,
++      normal_driver:          &normal,
++      callout_major:          CALLOUT_IT8712_MAJOR,
++      callout_name:           CALLOUT_IT8712_NAME,
++      callout_driver:         &callout,
++      table:                  it8712_table,
++      termios:                it8712_termios,
++      termios_locked:         it8712_termios_locked,
++      minor:                  SERIAL_IT8712_MINOR,
++      nr:                     UART_NR,
++#ifdef CONFIG_ARCH_SL2312
++      port:                   it8712_ports,
++#endif
++      state:                  NULL,
++      cons:                   IT8712_CONSOLE,
++};
++
++static int __init it8712_init(void)
++{
++//    printk("serial_it8712: it871212_init \n");
++
++      return uart_register_driver(&it8712_reg);
++}
++
++
++__initcall(it8712_init);
+--- /dev/null
++++ b/drivers/serial/serial_sl2312.c
+@@ -0,0 +1,827 @@
++/*
++ *  linux/drivers/char/serial_uart00.c
++ *
++ *  Driver for UART00 serial ports
++ *
++ *  Based on drivers/char/serial_amba.c, by ARM Limited &
++ *                                          Deep Blue Solutions Ltd.
++ *  Copyright 2001 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *  $Id: serial_sl2312.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
++ *
++ */
++#include <linux/module.h>
++
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/circ_buf.h>
++#include <linux/serial.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <linux/serial_core.h>
++
++#include <asm/system.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/sizes.h>
++#include <linux/spinlock.h>
++#include <linux/irq.h>
++
++
++#if defined(CONFIG_SERIAL_SL2312_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <asm/arch/sl2312.h>
++#define UART_TYPE (volatile unsigned int*)
++#include <asm/arch/uart.h>
++#include <asm/arch/int_ctrl.h>
++
++// #define DEBUG           1
++#define UART_NR               1
++
++
++#define SERIAL_SL2312_NAME    "ttyS"
++#define SERIAL_SL2312_MAJOR   204
++#define SERIAL_SL2312_MINOR   40      /* Temporary - will change in future */
++#define SERIAL_SL2312_NR      UART_NR
++#define UART_PORT_SIZE 0x50
++
++#define SL2312_NO_PORTS         UART_NR
++#define SL2312_ISR_PASS_LIMIT 256
++
++/*
++ * Access macros for the SL2312 UARTs
++ */
++#define UART_GET_INT_STATUS(p)        (inl(UART_IIR((p)->membase)) & 0x0F)      // interrupt identification
++#define UART_PUT_IER(p, c)      outl(c,UART_IER((p)->membase))    // interrupt enable
++#define UART_GET_IER(p)         inl(UART_IER((p)->membase))
++#define UART_PUT_CHAR(p, c)     outl(c,UART_THR((p)->membase))    // transmitter holding
++#define UART_GET_CHAR(p)        inl(UART_RBR((p)->membase))       // receive buffer
++#define UART_GET_LSR(p)         inl(UART_LSR((p)->membase))       // line status
++#define UART_GET_MSR(p)         inl(UART_MSR((p)->membase))       // modem status
++#define UART_GET_MCR(p)         inl(UART_MCR((p)->membase))       // modem control
++#define UART_PUT_MCR(p, c)      outl(c,UART_MCR((p)->membase))
++#define UART_GET_LCR(p)         inl(UART_LCR((p)->membase))       // mode control
++#define UART_PUT_LCR(p, c)      outl(c,UART_LCR((p)->membase))
++#define UART_GET_DIV_HI(p)    inl(UART_DIV_HI((p)->membase))
++#define UART_PUT_DIV_HI(p, c) outl(c,UART_DIV_HI((p)->membase))
++#define UART_GET_DIV_LO(p)    inl(UART_DIV_LO((p)->membase))
++#define UART_PUT_DIV_LO(p, c) outl(c,UART_DIV_LO((p)->membase))
++#define UART_PUT_MDR(p, c)      outl(c,UART_MDR((p)->membase))
++#define UART_RX_DATA(s)               ((s) & UART_LSR_DR)
++#define UART_TX_READY(s)      ((s) & UART_LSR_THRE)
++
++
++static void sl2312_stop_tx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 stop tx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_TE);
++      UART_PUT_IER(port, reg);
++}
++
++static void sl2312_stop_rx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 stop rx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_DR);
++      UART_PUT_IER(port, reg);
++
++}
++
++static void sl2312_enable_ms(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 enable ms : \n");
++
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_MS);
++      UART_PUT_IER(port, reg);
++
++}
++
++static void
++sl2312_rx_chars(struct uart_port *port)
++{
++      struct tty_struct *tty = port->info->tty;
++      unsigned int status, mask, ch, flg, ignored = 0;
++
++
++ //       printk("sl2312_rx_chars : \n");
++      status = UART_GET_LSR(port);
++      while (UART_RX_DATA(status)) {
++
++              /*
++               * We need to read rds before reading the
++               * character from the fifo
++               */
++              ch = UART_GET_CHAR(port);
++              port->icount.rx++;
++
++              //if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++              if (tty && !tty_buffer_request_room(tty, 1))
++                      goto ignore_char;
++
++              flg = TTY_NORMAL;
++
++              /*
++               * Note that the error handling code is
++               * out of the main execution path
++               */
++
++              if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
++                      goto handle_error;
++              if (uart_handle_sysrq_char(port, ch))
++                      goto ignore_char;
++
++      error_return:
++              //*tty->flip.flag_buf_ptr++ = flg;
++              //*tty->flip.char_buf_ptr++ = ch;
++              //tty->flip.count++;
++              tty_insert_flip_char(tty, ch, flg);
++      ignore_char:
++              status = UART_GET_LSR(port);
++      } // end of while
++out:
++      tty_flip_buffer_push(tty);
++      return;
++
++handle_error:
++      if (status & UART_LSR_BI) {
++              status &= ~(UART_LSR_FE);
++              port->icount.brk++;
++
++#ifdef SUPPORT_SYSRQ
++              if (uart_handle_break(port))
++                      goto ignore_char;
++#endif
++      } else if (status & UART_LSR_PE)
++              port->icount.parity++;
++      else if (status & UART_LSR_FE)
++              port->icount.frame++;
++
++      if (status & UART_LSR_OE)
++              port->icount.overrun++;
++
++      if (status & port->ignore_status_mask) {
++              if (++ignored > 100)
++                      goto out;
++              goto ignore_char;
++      }
++
++      mask = status & port->read_status_mask;
++
++      if (mask & UART_LSR_BI)
++              flg = TTY_BREAK;
++      else if (mask & UART_LSR_PE)
++              flg = TTY_PARITY;
++      else if (mask & UART_LSR_FE)
++              flg = TTY_FRAME;
++
++      if (status & UART_LSR_OE) {
++              /*
++               * CHECK: does overrun affect the current character?
++               * ASSUMPTION: it does not.
++               */
++              //*tty->flip.flag_buf_ptr++ = flg;
++              //*tty->flip.char_buf_ptr++ = ch;
++              //tty->flip.count++;
++
++              tty_insert_flip_char(tty, 0, TTY_BREAK);
++
++              // if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++              if (tty_buffer_request_room(tty, 1))
++                      goto ignore_char;
++              ch = 0;
++              flg = TTY_OVERRUN;
++      }
++#ifdef SUPPORT_SYSRQ
++      port->sysrq = 0;
++#endif
++      goto error_return;
++}
++
++static void sl2312_tx_chars(struct uart_port *port)
++{
++      struct circ_buf *xmit = &port->info->xmit;
++      int count;
++
++
++      if (port->x_char) {
++              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++              UART_PUT_CHAR(port, port->x_char);
++              port->icount.tx++;
++              port->x_char = 0;
++
++              return;
++      }
++      if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
++              sl2312_stop_tx(port);
++
++              return;
++      }
++
++      count = port->fifosize >> 1;
++      do {
++              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++              UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
++              xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++              port->icount.tx++;
++              if (uart_circ_empty(xmit))
++                      break;
++      } while (--count > 0);
++
++      if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++              uart_write_wakeup(port);
++
++      if (uart_circ_empty(xmit))
++              sl2312_stop_tx(port);
++
++}
++
++static void sl2312_start_tx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 start tx : \n");
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_TE);
++      UART_PUT_IER(port, reg);
++
++      sl2312_tx_chars(port);
++}
++
++static void sl2312_modem_status(struct uart_port *port)
++{
++      unsigned int status;
++
++//        printk("it8712 modem status : \n");
++
++      status = UART_GET_MSR(port);
++
++      if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
++                     UART_MSR_TERI | UART_MSR_DDCD)))
++              return;
++
++        if (status & UART_MSR_DDCD)
++                uart_handle_dcd_change(port, status & UART_MSR_DCD);
++
++        if (status & UART_MSR_DDSR)
++                port->icount.dsr++;
++
++        if (status & UART_MSR_DCTS)
++                uart_handle_cts_change(port, status & UART_MSR_CTS);
++
++      wake_up_interruptible(&port->info->delta_msr_wait);
++
++}
++
++static irqreturn_t sl2312_int(int irq, void *dev_id)
++{
++      struct uart_port *port = dev_id;
++      unsigned int status, pass_counter = 0;
++
++      status = UART_GET_INT_STATUS(port);
++      do {
++              switch(status)
++              {
++                 case UART_IIR_DR:
++                 case UART_IIR_RLS:
++                      sl2312_rx_chars(port);
++                 break;
++                 case UART_IIR_TE:
++                      sl2312_tx_chars(port);
++                 break;
++                 case UART_IIR_MODEM:
++                      sl2312_modem_status(port);
++                 break;
++                 default:
++                 break;
++              }
++              if (pass_counter++ > SL2312_ISR_PASS_LIMIT)
++                      break;
++
++              status = UART_GET_INT_STATUS(port);
++      } while (status);
++
++      return IRQ_HANDLED;
++}
++
++static u_int sl2312_tx_empty(struct uart_port *port)
++{
++//        printk("sl2312 tx empty : \n");
++
++      return ((UART_GET_LSR(port) & UART_LSR_TE)? TIOCSER_TEMT : 0);
++}
++
++static u_int sl2312_get_mctrl(struct uart_port *port)
++{
++      unsigned int result = 0;
++      unsigned int status;
++
++//        printk("sl2312 get mctrl : \n");
++
++      status = UART_GET_MSR(port);
++      if (status & UART_MSR_DCD)
++              result |= TIOCM_CAR;
++      if (status & UART_MSR_DSR)
++              result |= TIOCM_DSR;
++      if (status & UART_MSR_CTS)
++              result |= TIOCM_CTS;
++      if (status & UART_MSR_RI)
++              result |= TIOCM_RI;
++
++      return result;
++}
++
++static void sl2312_set_mctrl_null(struct uart_port *port, u_int mctrl)
++{
++}
++
++static void sl2312_break_ctl(struct uart_port *port, int break_state)
++{
++      unsigned int lcr;
++
++//        printk("sl2312 break ctl : \n");
++
++      lcr = UART_GET_LCR(port);
++      if (break_state == -1)
++              lcr |= UART_LCR_SETBREAK;
++      else
++              lcr &= ~UART_LCR_SETBREAK;
++      UART_PUT_LCR(port, lcr);
++}
++
++static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
++{
++      u_int quot;
++
++      /* Special case: B0 rate */
++      if (!baud)
++              baud = 9600;
++
++      quot = (port->uartclk / (16 * baud)-1)  ;
++
++      return quot;
++}
++
++static void sl2312_set_termios(struct uart_port *port, struct ktermios *termios,
++                               struct ktermios *old)
++{
++      unsigned int  uart_mc, old_ier, baud, quot;
++      unsigned long flags;
++
++        termios->c_cflag |= CREAD;
++#ifdef DEBUG
++      printk("it8712_set_cflag(0x%x) called\n", cflag);
++#endif
++        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++        quot = (port->uartclk / (16 * baud))  ;
++        //uart_get_divisor(port, baud);
++
++      /* byte size and parity */
++      switch (termios->c_cflag & CSIZE) {
++      case CS5:
++              uart_mc = UART_LCR_LEN5;
++              break;
++      case CS6:
++              uart_mc = UART_LCR_LEN6;
++              break;
++      case CS7:
++              uart_mc = UART_LCR_LEN7;
++              break;
++      default: // CS8
++              uart_mc = UART_LCR_LEN8;
++              break;
++      }
++
++      if (termios->c_cflag & CSTOPB)
++              uart_mc|= UART_LCR_STOP;
++      if (termios->c_cflag & PARENB) {
++              uart_mc |= UART_LCR_EVEN;
++              if (!(termios->c_cflag & PARODD))
++                      uart_mc |= UART_LCR_ODD;
++      }
++
++    spin_lock_irqsave(&port->lock, flags);
++        /*
++         * Update the per-port timeout
++         */
++        uart_update_timeout(port, termios->c_cflag, baud);
++      port->read_status_mask = UART_LSR_OE;
++      if (termios->c_iflag & INPCK)
++              port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++      if (termios->c_iflag & (BRKINT | PARMRK))
++              port->read_status_mask |= UART_LSR_BI;
++
++      /*
++       * Characters to ignore
++       */
++      port->ignore_status_mask = 0;
++      if (termios->c_iflag & IGNPAR)
++              port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
++      if (termios->c_iflag & IGNBRK) {
++              port->ignore_status_mask |= UART_LSR_BI;
++              /*
++               * If we're ignoring parity and break indicators,
++               * ignore overruns to (for real raw support).
++               */
++              if (termios->c_iflag & IGNPAR)
++                      port->ignore_status_mask |= UART_LSR_OE;
++      }
++
++      //save_flags(flags); cli();
++      old_ier = UART_GET_IER(port);
++
++        if(UART_ENABLE_MS(port, termios->c_cflag))
++             old_ier |= UART_IER_MS;
++
++      /* Set baud rate */
++      UART_PUT_LCR(port, UART_LCR_DLAB);
++      UART_PUT_DIV_LO(port, (quot & 0xff));
++      UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
++
++      UART_PUT_LCR(port, uart_mc);
++      UART_PUT_IER(port, old_ier);
++
++      //restore_flags(flags);
++      spin_unlock_irqrestore(&port->lock, flags);
++}
++
++
++
++static int sl2312_startup(struct uart_port *port)
++{
++      int retval;
++      unsigned int regs;
++
++//        printk("sl2312 startup : \n");
++
++      /*
++       * Use iobase to store a pointer to info. We need this to start a
++       * transmission as the tranmittr interrupt is only generated on
++       * the transition to the idle state
++       */
++
++      /*
++       * Allocate the IRQ
++       */
++      retval = request_irq(port->irq, sl2312_int, IRQF_DISABLED, "sl2312", port);
++      if (retval)
++              return retval;
++
++        /* setup interrupt controller  */
++        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_UART_MASK);
++        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_UART_MASK);
++        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_UART_MASK);
++
++      /*
++       * Finally, enable interrupts. Use the TII interrupt to minimise
++       * the number of interrupts generated. If higher performance is
++       * needed, consider using the TI interrupt with a suitable FIFO
++       * threshold
++       */
++      UART_PUT_IER(port, (UART_IER_DR|UART_IER_TE));
++
++      return 0;
++}
++
++static void sl2312_shutdown(struct uart_port *port)
++{
++//        printk("sl2312 shutdown : \n");
++
++      /*
++       * disable all interrupts, disable the port
++       */
++      UART_PUT_IER(port, 0x0);
++
++      /* disable break condition and fifos */
++//    UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
++
++      /*
++       * Free the interrupt
++       */
++      free_irq(port->irq, port);
++}
++
++static const char *sl2312_type(struct uart_port *port)
++{
++      return port->type == PORT_SL2312 ? "SL2312" : NULL;
++}
++
++/*
++ * Release the memory region(s) being used by 'port'
++ */
++static void sl2312_release_port(struct uart_port *port)
++{
++//        printk("sl2312 release port : \n");
++
++      release_mem_region(port->mapbase, UART_PORT_SIZE);
++}
++
++/*
++ * Request the memory region(s) being used by 'port'
++ */
++static int sl2312_request_port(struct uart_port *port)
++{
++      return request_mem_region(port->mapbase, UART_PORT_SIZE,
++                                  "serial_sl2312") != NULL ? 0 : -EBUSY;
++}
++
++/*
++ * Configure/autoconfigure the port.
++ */
++static void sl2312_config_port(struct uart_port *port, int flags)
++{
++
++      if (flags & UART_CONFIG_TYPE) {
++              if (sl2312_request_port(port) == 0)
++                      port->type = PORT_SL2312;
++      }
++}
++
++/*
++ * verify the new serial_struct (for TIOCSSERIAL).
++ */
++static int sl2312_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++      int ret = 0;
++
++      if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
++              ret = -EINVAL;
++      if (ser->irq < 0 || ser->irq >= NR_IRQS)
++              ret = -EINVAL;
++      if (ser->baud_base < 9600)
++              ret = -EINVAL;
++      return ret;
++}
++
++static struct uart_ops sl2312_pops = {
++      .tx_empty               =sl2312_tx_empty,
++      .set_mctrl              =sl2312_set_mctrl_null,
++      .get_mctrl              =sl2312_get_mctrl,
++      .stop_tx                =sl2312_stop_tx,
++      .start_tx               =sl2312_start_tx,
++      .stop_rx                =sl2312_stop_rx,
++      .enable_ms              =sl2312_enable_ms,
++      .break_ctl              =sl2312_break_ctl,
++      .startup                =sl2312_startup,
++      .shutdown               =sl2312_shutdown,
++      .set_termios    =sl2312_set_termios,
++      .type                   =sl2312_type,
++      .release_port   =sl2312_release_port,
++      .request_port   =sl2312_request_port,
++      .config_port    =sl2312_config_port,
++      .verify_port    =sl2312_verify_port,
++};
++
++#ifdef CONFIG_ARCH_SL2312
++
++static struct uart_port sl2312_ports[UART_NR] = {
++      {
++              membase:        (void *)IO_ADDRESS(SL2312_UART_BASE),
++              mapbase:        SL2312_UART_BASE,
++              iotype:         SERIAL_IO_MEM,
++              irq:            IRQ_UART,
++              uartclk:        UART_CLK,
++              fifosize:       16,
++              ops:            &sl2312_pops,
++              flags:          ASYNC_BOOT_AUTOCONF,
++      }
++};
++
++#endif
++
++#ifdef CONFIG_SERIAL_SL2312_CONSOLE
++#ifdef used_and_not_const_char_pointer
++static int sl2312_console_read(struct uart_port *port, char *s, u_int count)
++{
++      unsigned int status;
++      int c;
++#ifdef DEBUG
++      printk("sl2312_console_read() called\n");
++#endif
++
++      c = 0;
++      while (c < count) {
++              status = UART_GET_LSR(port);
++              if (UART_RX_DATA(status)) {
++                      *s++ = UART_GET_CHAR(port);
++                      c++;
++              } else {
++                      // nothing more to get, return
++                      return c;
++              }
++      }
++      // return the count
++      return c;
++}
++#endif
++static void sl2312_console_write(struct console *co, const char *s, unsigned count)
++{
++#ifdef CONFIG_ARCH_SL2312
++      struct uart_port *port = sl2312_ports + co->index;
++      unsigned int status, old_ies;
++      int i;
++
++      /*
++       *      First save the CR then disable the interrupts
++       */
++      old_ies = UART_GET_IER(port);
++      UART_PUT_IER(port,0x0);
++
++      /*
++       *      Now, do each character
++       */
++      for (i = 0; i < count; i++) {
++              do {
++                      status = UART_GET_LSR(port);
++              } while (!UART_TX_READY(status));
++              UART_PUT_CHAR(port, s[i]);
++              if (s[i] == '\n') {
++                      do {
++                              status = UART_GET_LSR(port);
++                      } while (!UART_TX_READY(status));
++                      UART_PUT_CHAR(port, '\r');
++              }
++      }
++
++      /*
++       *      Finally, wait for transmitter to become empty
++       *      and restore the IES
++       */
++      do {
++              status = UART_GET_LSR(port);
++      } while (!(status&UART_LSR_TE));
++      UART_PUT_IER(port, old_ies);
++#endif
++}
++
++#if 0
++static void sl2312_console_device(struct console *co,int *index)
++{
++
++      struct uart_driver *p = co->data;
++    *index = co->index;
++    return p->tty_driver;
++
++}
++#endif
++
++static void /*__init*/ sl2312_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
++{
++//    printk("sl2312 console get options : \n");
++
++      u_int uart_mc, quot;
++      uart_mc= UART_GET_MCR(port);
++
++      *parity = 'n';
++      if (uart_mc & UART_LCR_PE) {
++              if (uart_mc & UART_LCR_EVEN)
++                      *parity = 'e';
++              else
++                      *parity = 'o';
++      }
++
++      switch (uart_mc & UART_LCR_MSK){
++
++      case UART_LCR_LEN5:
++              *bits = 5;
++              break;
++      case UART_LCR_LEN6:
++              *bits = 6;
++              break;
++      case UART_LCR_LEN7:
++              *bits = 7;
++              break;
++      case UART_LCR_LEN8:
++              *bits = 8;
++              break;
++      }
++      UART_PUT_MCR(port,UART_LCR_DLAB);
++      quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
++      UART_PUT_MCR(port,uart_mc);
++      *baud = port->uartclk / (16 *quot );
++}
++
++static int __init sl2312_console_setup(struct console *co, char *options)
++{
++      struct uart_port *port;
++      int baud = 19200;
++      int bits = 8;
++      int parity = 'n';
++      int flow= 'n';
++
++      printk("sl2312 console setup : \n");
++
++#ifdef CONFIG_ARCH_SL2312
++      /*
++       * Check whether an invalid uart number has been specified, and
++       * if so, search for the first available port that does have
++       * console support.
++       */
++      port = uart_get_console(sl2312_ports,SL2312_NO_PORTS,co);
++#else
++      return -ENODEV;
++#endif
++
++      if (options)
++              uart_parse_options(options, &baud, &parity, &bits, &flow);
++      else
++              sl2312_console_get_options(port, &baud, &parity, &bits);
++
++      return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++extern struct uart_driver sl2312_reg;
++static struct console sl2312_console = {
++      .name      = SERIAL_SL2312_NAME,
++      .write          = sl2312_console_write,
++      .device         = uart_console_device,
++//    .device         = sl2312_console_device,
++      .setup          = sl2312_console_setup,
++//    .flags          = (CON_PRINTBUFFER|CON_ENABLED),
++      .flags          = CON_PRINTBUFFER,
++      .index          = -1,
++      .data       = &sl2312_reg,
++};
++
++static int __init sl2312_console_init(void)
++{
++      register_console(&sl2312_console);
++      return 0;
++
++}
++
++console_initcall(sl2312_console_init);
++
++#define SL2312_CONSOLE        &sl2312_console
++#else
++#define SL2312_CONSOLE        NULL
++#endif
++
++// static
++struct uart_driver sl2312_reg = {
++      .owner         = NULL,
++      .driver_name    = SERIAL_SL2312_NAME,
++      .dev_name               = SERIAL_SL2312_NAME,
++      .major          = SERIAL_SL2312_MAJOR,
++      .minor                  = SERIAL_SL2312_MINOR,
++      .nr                             = UART_NR,
++      .cons                   = SL2312_CONSOLE,
++};
++
++static int __init sl2312_init(void)
++{
++       int result;
++      //printk("serial_it8712: it871212_init \n");
++
++        result = uart_register_driver(&sl2312_reg);
++        if(result)
++             return result;
++      result = uart_add_one_port(&sl2312_reg, &sl2312_ports[0]);
++
++        return result;
++}
++
++
++__initcall(sl2312_init);
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -147,6 +147,10 @@
+ #define PORT_SB1250_DUART     77
++/* Storlink Soc */
++#define PORT_SL2312     72
++#define PORT_IT8712     73
++
+ #ifdef __KERNEL__
+ #include <linux/compiler.h>
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -70,6 +70,16 @@
+ obj-$(CONFIG_APPLICOM)                += applicom.o
+ obj-$(CONFIG_SONYPI)          += sonypi.o
+ obj-$(CONFIG_RTC)             += rtc.o
++
++###  for Storlink SoC ###
++obj-$(CONFIG_SL2312_RTC) += sl2312_rtc.o
++obj-$(CONFIG_IT8712_GPIO)   += it8712_gpio.o
++obj-$(CONFIG_GEMINI_GPIO)   += gemini_gpio.o
++obj-$(CONFIG_GEMINI_PWC) += gemini_pwr.o
++obj-$(CONFIG_GEMINI_CIR)    += gemini_cir.o
++obj-$(CONFIG_GEMINI_I2S)    += gemini_i2s.o
++obj-$(CONFIG_SL2312_WATCHDOG) += sl2312_wd.o
++
+ obj-$(CONFIG_HPET)            += hpet.o
+ obj-$(CONFIG_GEN_RTC)         += genrtc.o
+ obj-$(CONFIG_EFI_RTC)         += efirtc.o
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -280,6 +280,56 @@
+ comment "Non-8250 serial port support"
++config SERIAL_SL2312
++      bool "SL2312  serial port (sl2312) support"
++      depends on ARCH_SL2312
++      select SERIAL_CORE
++      select SERIAL_SL2312_CONSOLE
++      help
++         Say Y here if you want to use the hard logic uart on SWORD. This
++         driver also supports soft logic implentations of this uart core.
++
++config SERIAL_SL2312_CONSOLE
++      bool "Support for console on SL2312 serial port"
++      depends on SERIAL_SL2312
++      select SERIAL_CORE_CONSOLE
++      help
++        Say Y here if you want to support a serial console on an SWORD
++        hard logic uart or uart00 IP core.
++
++        Even if you say Y here, the currently visible virtual console
++        (/dev/tty0) will still be used as the system console by default, but
++        you can alter that using a kernel command line option such as
++        "console=ttyS0". (Try "man bootparam" or see the documentation of
++        your boot loader (lilo or loadlin) about how to pass options to the
++        kernel at boot time.)
++
++
++config SERIAL_IT8712
++      bool "Sl2312 serial port(IT8712) support"
++      depends on ARM && ARCH_SL2312 && SL2312_LPC
++      select SERIAL_CORE
++      select SERIAL_IT8712_CONSOLE
++      help
++        Say Y here if you want to use the hard logic uart on Excalibur. This
++        driver also supports soft logic implentations of this uart core.
++
++config SERIAL_IT8712_CONSOLE
++      bool "Support for console on Sword serial port(IT8712)"
++      depends on SERIAL_IT8712
++      select SERIAL_CORE_CONSOLE
++      help
++        Say Y here if you want to support a serial console on an Excalibur
++        hard logic uart or uart00 IP core.
++
++        Even if you say Y here, the currently visible virtual console
++        (/dev/tty0) will still be used as the system console by default, but
++        you can alter that using a kernel command line option such as
++        "console=ttySI0". (Try "man bootparam" or see the documentation of
++        your boot loader (lilo or loadlin) about how to pass options to the
++        kernel at boot time.)
++
++
+ config SERIAL_AMBA_PL010
+       tristate "ARM AMBA PL010 serial port support"
+       depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -62,5 +62,7 @@
+ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
+ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
+ obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
++obj-$(CONFIG_SERIAL_IT8712) += it8712.o
++obj-$(CONFIG_SERIAL_SL2312) += serial_sl2312.o
+ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
+ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
diff --git a/target/linux/storm/patches/009-watchdog.patch b/target/linux/storm/patches/009-watchdog.patch
new file mode 100644 (file)
index 0000000..3055a94
--- /dev/null
@@ -0,0 +1,398 @@
+--- a/arch/arm/mach-sl2312/sl3516_device.c
++++ b/arch/arm/mach-sl2312/sl3516_device.c
+@@ -76,9 +76,30 @@
+       .resource       = sl3516_sata0_resources,
+ };
++static struct resource sl351x_wdt_resources[] = {
++      [0] = {
++              .start  = SL2312_WAQTCHDOG_BASE + 0x00,
++              .end    = SL2312_WAQTCHDOG_BASE + 0x1C,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = IRQ_WATCHDOG,
++              .end    = IRQ_WATCHDOG,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device sl351x_wdt = {
++      .name           = "sl351x-wdt",
++      .id             = -1,
++      .resource       = sl351x_wdt_resources,
++      .num_resources  = ARRAY_SIZE(sl351x_wdt_resources),
++};
++
+ static struct platform_device *sata_devices[] __initdata = {
+       &sata_device,
+       &sata0_device,
++      &sl351x_wdt,
+ };
+ static int __init sl3516_init(void)
+--- a/drivers/char/watchdog/Kconfig
++++ b/drivers/char/watchdog/Kconfig
+@@ -171,6 +171,17 @@
+         To compile this driver as a module, choose M here: the
+         module will be called ep93xx_wdt.
++config WATCHDOG_SL351X
++      tristate "SL351x Watchdog"
++      depends on WATCHDOG && ARCH_SL2312
++      help
++        This driver adds watchdog support for the integrated watchdog in the
++        SL351x processors (Farraday core). If you have one of these processors
++        and wish to have watchdog support enabled, say Y, otherwise say N.
++
++        To compile this driver as a module, choose M here: the
++        module will be called sl351x_wdt.
++
+ config OMAP_WATCHDOG
+       tristate "OMAP Watchdog"
+       depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+--- a/drivers/char/watchdog/Makefile
++++ b/drivers/char/watchdog/Makefile
+@@ -36,6 +36,7 @@
+ obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
+ obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
+ obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
++obj-$(CONFIG_WATCHDOG_SL351X) += sl351x_wdt.o
+ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
+ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
+ obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
+--- /dev/null
++++ b/drivers/char/watchdog/sl351x_wdt.c
+@@ -0,0 +1,332 @@
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/platform_device.h>
++#include <asm/uaccess.h>
++#include <asm/arch/sl2312.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/watchdog.h>
++#include <asm/io.h>
++#include <linux/interrupt.h>
++
++#define WATCHDOG_TEST 1
++#define PFX "sl351x-wdt: "
++
++#define _WATCHDOG_COUNTER  0x00
++#define _WATCHDOG_LOAD     0x04
++#define _WATCHDOG_RESTART  0x08
++#define _WATCHDOG_CR       0x0C
++#define _WATCHDOG_STATUS   0x10
++#define _WATCHDOG_CLEAR    0x14
++#define _WATCHDOG_INTRLEN  0x18
++
++static struct resource  *wdt_mem;
++static struct resource  *wdt_irq;
++static void __iomem     *wdt_base;
++static int            wdt_margin = WATCHDOG_TIMEOUT_MARGIN;   /* in range of 0 .. 60s */
++
++static int open_state = WATCHDOG_DRIVER_CLOSE;
++static int wd_expire = 0;
++
++static void watchdog_enable(void)
++{
++      unsigned long wdcr;
++
++      wdcr = readl(wdt_base + _WATCHDOG_CR);
++      wdcr |= (WATCHDOG_WDENABLE_MSK|WATCHDOG_WDRST_MSK);
++#ifdef WATCHDOG_TEST
++      wdcr |= WATCHDOG_WDINTR_MSK;
++//    wdcr &= ~WATCHDOG_WDRST_MSK;
++#endif
++      wdcr &= ~WATCHDOG_WDCLOCK_MSK;
++      writel(wdcr, wdt_base + _WATCHDOG_CR);
++}
++
++static void watchdog_set_timeout(unsigned long timeout)
++{
++      timeout = WATCHDOG_TIMEOUT_SCALE * timeout;
++      writel(timeout, wdt_base + _WATCHDOG_LOAD);
++      writel(WATCHDOG_RESTART_VALUE, wdt_base + _WATCHDOG_RESTART);
++}
++
++static void watchdog_keepalive(void)
++{
++      writel(WATCHDOG_RESTART_VALUE, wdt_base + _WATCHDOG_RESTART);
++}
++
++static void watchdog_disable(void)
++{
++      unsigned long wdcr;
++
++      wdcr = readl(wdt_base + _WATCHDOG_CR);
++      wdcr &= ~WATCHDOG_WDENABLE_MSK;
++      writel(wdcr, wdt_base + _WATCHDOG_CR);
++}
++
++
++#ifdef WATCHDOG_TEST
++static irqreturn_t watchdog_irq(int irq, void *dev_id, struct pt_regs *regs)
++{
++      unsigned int clear;
++
++      writel(WATCHDOG_CLEAR_STATUS, wdt_base + _WATCHDOG_CLEAR);
++      printk(KERN_INFO PFX "Watchdog timeout, resetting system...\n");
++
++      clear = __raw_readl(IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x0C);
++      clear &= 0x01;
++      __raw_writel(clear,IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x08);
++      wd_expire = 1;
++      return IRQ_HANDLED;
++}
++
++#endif
++
++#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE
++static struct watchdog_info sl351x_wdt_ident = {
++      .options          =     OPTIONS,
++      .firmware_version =     0,
++      .identity         =     "sl351x Watchdog",
++};
++
++struct file_operations watchdog_fops = {
++      .write          = watchdog_write,
++      .read           = watchdog_read,
++      .open           = watchdog_open,
++      .release        = watchdog_release,
++      .ioctl          = watchdog_ioctl,
++};
++
++static int watchdog_open(struct inode *inode, struct file *filp)
++{
++      if (open_state == WATCHDOG_DRIVER_OPEN)
++              return -EBUSY;
++
++      wd_expire = 0;
++
++      watchdog_disable();
++      watchdog_set_timeout(wdt_margin);
++      watchdog_enable();
++
++      printk(KERN_INFO PFX "watchog timer enabled, margin: %ds.\n", wdt_margin);
++      open_state = WATCHDOG_DRIVER_OPEN;
++
++      return nonseekable_open(inode, filp);
++}
++
++static int watchdog_release(struct inode *inode, struct file *filp)
++{
++      watchdog_disable();
++
++      open_state = WATCHDOG_DRIVER_CLOSE;
++      wd_expire = 0;
++      printk(KERN_INFO PFX "watchog timer disabled, margin: %ds.\n", wdt_margin);
++
++      return 0;
++}
++
++static ssize_t watchdog_read(struct file *filp, char *buf, size_t count, loff_t *off)
++{
++      int i;
++      unsigned long val;
++
++
++      for(i=0;i< count;i++)
++      {
++              if ((i%4)==0)
++                      val = *((unsigned long *)WATCHDOG_COUNTER);
++              buf[i] = (val & 0xFF);
++              val >>= 8;
++      }
++      return count;
++}
++
++static ssize_t watchdog_write(struct file *filp, const char *buf, size_t len, loff_t *off)
++{
++      /*  Refresh the timer. */
++      if (len) {
++              watchdog_keepalive();
++      }
++      return len;
++
++}
++
++static int watchdog_ioctl(struct inode *inode, struct file *filp,
++                        unsigned int cmd, unsigned long arg)
++{
++      void __user *argp = (void __user *)arg;
++      int margin;
++
++      switch(cmd)
++      {
++      case WDIOC_GETSUPPORT:
++              return copy_to_user(argp, &sl351x_wdt_ident,
++                                  sizeof(sl351x_wdt_ident)) ? -EFAULT : 0;
++
++      case WDIOC_GETSTATUS:
++      case WDIOC_GETBOOTSTATUS:
++              return put_user(0, (int __user*)argp);
++
++      case WDIOC_KEEPALIVE:
++              watchdog_keepalive();
++              return 0;
++
++      case WDIOC_SETTIMEOUT:
++              if (get_user(margin, (int __user*)argp))
++                      return -EFAULT;
++
++              /* Arbitrary, can't find the card's limits */
++              if ((margin < 0) || (margin > 60))
++                      return -EINVAL;
++
++              // watchdog_disable();
++              wdt_margin = margin;
++              watchdog_set_timeout(margin);
++              watchdog_keepalive();
++              // watchdog_enable();
++
++              /* Fall through */
++
++      case WDIOC_GETTIMEOUT:
++              return put_user(wdt_margin, (int *)arg);
++
++      default:
++              return -ENOIOCTLCMD;
++      }
++}
++
++static struct miscdevice wd_dev= {
++      WATCHDOG_MINOR,
++      "watchdog",
++      &watchdog_fops
++};
++
++static char banner[] __initdata = KERN_INFO "SL351x Watchdog Timer, (c) 2007 WILIBOX\n";
++
++static int sl351x_wdt_probe(struct platform_device *pdev)
++{
++      struct resource *res;
++      int ret, size;
++      unsigned long wdcr;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (res == NULL) {
++              printk(KERN_INFO PFX "failed to get memory region resouce\n");
++              return -ENOMEM;
++      }
++
++      size = (res->end-res->start)+1;
++
++      wdt_mem = request_mem_region(res->start, size, pdev->name);
++      if (wdt_mem == NULL) {
++              printk(KERN_INFO PFX "failed to get memory region\n");
++              return -ENOENT;
++      }
++
++      wdt_base = ioremap(res->start, size);
++      if (wdt_base == NULL) {
++              printk(KERN_INFO PFX "failed to ioremap() region\n");
++              return -EINVAL;
++      }
++
++      res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++      if (res == NULL) {
++               printk(KERN_INFO PFX "failed to get irq resource\n");
++               return -ENOENT;
++      }
++
++      wdt_irq = res;
++
++      ret = request_irq(res->start, watchdog_irq, 0, pdev->name, pdev);
++      if (ret != 0) {
++              printk(KERN_INFO PFX "failed to install irq (%d)\n", ret);
++              return ret;
++      }
++
++      wdcr = readl(wdt_base + _WATCHDOG_CR);
++      if (wdcr & WATCHDOG_WDENABLE_MSK) {
++              printk(KERN_INFO PFX "Found watchdog in enabled state, reseting ...\n");
++              wdcr &= ~WATCHDOG_WDENABLE_MSK;
++              writel(wdcr, wdt_base + _WATCHDOG_CR);
++      }
++
++      ret = misc_register(&wd_dev);
++
++      return ret;
++}
++
++static int sl351x_wdt_remove(struct platform_device *pdev)
++{
++      if (wdt_base != NULL) {
++              iounmap(wdt_base);
++              wdt_base = NULL;
++      }
++
++      if (wdt_irq != NULL) {
++              free_irq(wdt_irq->start, pdev);
++              release_resource(wdt_irq);
++              wdt_irq = NULL;
++      }
++
++      if (wdt_mem != NULL) {
++              release_resource(wdt_mem);
++              wdt_mem = NULL;
++      }
++
++      misc_deregister(&wd_dev);
++
++      return 0;
++}
++
++static void sl351x_wdt_shutdown(struct platform_device *dev)
++{
++      watchdog_disable();
++}
++
++#ifdef CONFIG_PM
++static int sl351x_wdt_suspend(struct platform_device *dev, pm_message_t state)
++{
++      watchdog_disable();
++}
++
++static int sl351x_wdt_resume(struct platform_device *dev)
++{
++      watchdog_set_timeout(wdt_margin);
++      watchdog_enable();
++}
++
++#else
++#define sl351x_wdt_suspend    NULL
++#define sl351x_wdt_resume     NULL
++#endif
++
++static struct platform_driver sl351x_wdt_driver = {
++      .probe          = sl351x_wdt_probe,
++      .remove         = sl351x_wdt_remove,
++      .shutdown       = sl351x_wdt_shutdown,
++      .suspend        = sl351x_wdt_suspend,
++      .resume         = sl351x_wdt_resume,
++      .driver         = {
++              .owner  = THIS_MODULE,
++              .name   = "sl351x-wdt",
++      },
++};
++
++static int __init watchdog_init(void)
++{
++      printk(banner);
++      return platform_driver_register(&sl351x_wdt_driver);
++}
++
++static void __exit watchdog_exit(void)
++{
++      platform_driver_unregister(&sl351x_wdt_driver);
++}
++
++module_init(watchdog_init);
++module_exit(watchdog_exit);
diff --git a/target/linux/storm/patches/1001-arch.patch b/target/linux/storm/patches/1001-arch.patch
deleted file mode 100644 (file)
index b0461d4..0000000
+++ /dev/null
@@ -1,8864 +0,0 @@
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -220,6 +220,9 @@
-       help
-         This enables support for the Cirrus EP93xx series of CPUs.
-+config ARCH_SL2312
-+    bool "SL2312"
-+
- config ARCH_FOOTBRIDGE
-       bool "FootBridge"
-       select FOOTBRIDGE
-@@ -414,6 +417,8 @@
- source "arch/arm/mach-footbridge/Kconfig"
-+source "arch/arm/mach-sl2312/Kconfig"
-+
- source "arch/arm/mach-integrator/Kconfig"
- source "arch/arm/mach-iop32x/Kconfig"
-@@ -549,6 +554,16 @@
- config PCI_SYSCALL
-       def_bool PCI
-+config SL2312_LPC
-+    bool "LPC Host Support"
-+    depends on ARCH_SL2312
-+    help
-+
-+config SL2312_LPC_IT8712
-+    bool "IT8712 Support"
-+    depends on ARCH_SL2312 && SL2312_LPC
-+    help
-+
- # Select the host bridge type
- config PCI_HOST_VIA82C505
-       bool
-@@ -988,6 +1003,10 @@
- source "drivers/mtd/Kconfig"
- endif
-+if ARCH_SL2312
-+source "drivers/telephony/Kconfig"
-+endif
-+
- source "drivers/parport/Kconfig"
- source "drivers/pnp/Kconfig"
-@@ -997,7 +1016,7 @@
- if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
-       || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
-       || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
--      || ARCH_IXP23XX
-+      || ARCH_IXP23XX || ARCH_SL2312
- source "drivers/ide/Kconfig"
- endif
---- a/arch/arm/Makefile
-+++ b/arch/arm/Makefile
-@@ -72,6 +72,7 @@
- tune-$(CONFIG_CPU_ARM922T)    :=-mtune=arm9tdmi
- tune-$(CONFIG_CPU_ARM925T)    :=-mtune=arm9tdmi
- tune-$(CONFIG_CPU_ARM926T)    :=-mtune=arm9tdmi
-+tune-$(CONFIG_CPU_FA52X)    :=-mtune=arm9tdmi
- tune-$(CONFIG_CPU_SA110)      :=-mtune=strongarm110
- tune-$(CONFIG_CPU_SA1100)     :=-mtune=strongarm1100
- tune-$(CONFIG_CPU_XSCALE)     :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
-@@ -111,6 +112,7 @@
-  machine-$(CONFIG_ARCH_PXA)      := pxa
-  machine-$(CONFIG_ARCH_L7200)    := l7200
-  machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
-+ machine-$(CONFIG_ARCH_SL2312)     := sl2312
-  textofs-$(CONFIG_ARCH_CLPS711X)   := 0x00028000
-  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
-  machine-$(CONFIG_ARCH_IOP32X)           := iop32x
---- a/arch/arm/boot/compressed/Makefile
-+++ b/arch/arm/boot/compressed/Makefile
-@@ -19,6 +19,10 @@
- OBJS          += head-shark.o ofw-shark.o
- endif
-+ifeq ($(CONFIG_ARCH_SL2312),y)
-+OBJS          += head-sl2312.o
-+endif
-+
- ifeq ($(CONFIG_ARCH_L7200),y)
- OBJS          += head-l7200.o
- endif
---- /dev/null
-+++ b/arch/arm/boot/compressed/head-sl2312.S
-@@ -0,0 +1,6 @@
-+#include <asm/mach-types.h>
-+#include <asm/arch/sl2312.h>
-+
-+              .section        ".start", "ax"
-+              mov     r7, #MACH_TYPE_SL2312
-+
---- a/arch/arm/boot/compressed/head.S
-+++ b/arch/arm/boot/compressed/head.S
-@@ -57,6 +57,17 @@
-               mov     \rb, #0x50000000
-               add     \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
-               .endm
-+/*****************************************************
-+ *      for Storlink SoC
-+ *****************************************************/
-+#elif defined(CONFIG_ARCH_SL2312)
-+              .macro  loadsp, rb
-+              mov     \rb, #0x16000000
-+              .endm
-+              .macro  writeb, rb
-+              strb    \rb, [r3, #0]
-+              .endm
-+/****************************************************/
- #else
-               .macro  loadsp, rb
-               addruart \rb
-@@ -116,7 +127,28 @@
-               .rept   8
-               mov     r0, r0
-               .endr
--
-+/*****************************************************************************
-+ *  for Storlink Soc -- on chip UART
-+ *****************************************************************************/
-+#ifndef CONFIG_SERIAL_IT8712          // Jason test
-+@                mov     r3, #0x22000000
-+                mov     r3, #0x42000000
-+                mov     r11, #0x80
-+                strb    r11, [r3, #0xc]
-+                mov     r11, #0x0
-+                strb    r11, [r3, #0x4]
-+#ifndef CONFIG_SL3516_ASIC
-+                mov     r11, #0x9C            /*0x9c->19200 0x4E->38400 0x34->57600 */
-+#else
-+              mov     r11, #0x9C              /* 0x61 for 30MHz on GeminiA chip*/
-+#endif
-+                strb    r11, [r3, #0x0]
-+                mov     r11, #0x03
-+                strb    r11, [r3, #0xc]
-+                      mov     r11, #0xFB
-+                strb    r11, [r3, #0x18]
-+#endif
-+/*****************************************************************************/
-               b       1f
-               .word   0x016f2818              @ Magic numbers to help the loader
-               .word   start                   @ absolute load/run zImage address
-@@ -458,6 +490,39 @@
-               mcr     p15, 0, r0, c7, c5, 4   @ ISB
-               mov     pc, r12
-+/*****************************************************************************
-+ *  for Storlink Soc -- CPU cache
-+ *****************************************************************************/
-+__fa526_cache_on:
-+                mov     r12, lr
-+                bl      __setup_mmu
-+                mov     r0, #0
-+                mcr     p15, 0, r0, c7, c6, 0   @ Invalidate D cache
-+                mcr     p15, 0, r0, c7, c5, 0   @ Invalidate I cache
-+                mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
-+                mcr     p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
-+                mcr     p15, 0, r3, c2, c0, 0   @ load page table pointer
-+                mov     r0, #-1
-+                mcr     p15, 0, r0, c3, c0, 0   @ load domain access register
-+                mrc     p15, 0, r0, c1, c0, 0
-+                mov     r0, r0
-+                mov     r0, r0
-+#ifndef CONFIG_CPU_DCACHE_DISABLE
-+        orr     r0, r0, #0x0004                 @ .... .... .... .1..
-+#endif
-+#ifndef CONFIG_CPU_ICACHE_DISABLE
-+        orr     r0, r0, #0x1000                 @ ...1 .... .... ....
-+#endif
-+
-+#ifndef DEBUG
-+                orr     r0, r0, #0x0039         @ Write buffer, mmu
-+#endif
-+                mcr     p15, 0, r0, c1, c0
-+                mov     r0, r0
-+                mov     r0, r0
-+                mov     pc, r12
-+/********************************************************************************/
-+
- __arm6_mmu_cache_on:
-               mov     r12, lr
-               bl      __setup_mmu
-@@ -625,6 +690,16 @@
-               @ These match on the architecture ID
-+/*****************************************************************************
-+ *  for Storlink Soc -- CPU architecture ID
-+ *****************************************************************************/
-+        .word   0x66015261              @ FA526
-+        .word   0xff01fff1
-+        b       __fa526_cache_on
-+        b       __fa526_cache_off
-+        b       __fa526_cache_flush
-+/*****************************************************************************/
-+
-               .word   0x00020000              @ ARMv4T
-               .word   0x000f0000
-               b       __armv4_mmu_cache_on
-@@ -712,6 +787,23 @@
-               mcr     p15, 0, r0, c8, c7, 0   @ invalidate whole TLB
-               mov     pc, r12
-+/*****************************************************************************
-+ *  for Storlink Soc -- CPU cache
-+ *****************************************************************************/
-+__fa526_cache_off:
-+        mrc     p15, 0, r0, c1, c0
-+        bic     r0, r0, #0x000d
-+        mov     r1, #0
-+        mcr     p15, 0, r1, c7, c14, 0  @ clean and invalidate D cache
-+        mcr     p15, 0, r1, c7, c10, 4  @ drain WB
-+        mcr     p15, 0, r0, c1, c0      @ turn MMU and cache off
-+        mov     r0, #0
-+        mcr     p15, 0, r0, c7, c5, 0   @ invalidate whole cache v4
-+        mcr     p15, 0, r0, c8, c7, 0   @ invalidate whole TLB v4
-+        mov     pc, lr
-+/*****************************************************************************/
-+
-+
- __arm6_mmu_cache_off:
-               mov     r0, #0x00000030         @ ARM6 control reg.
-               b       __armv3_mmu_cache_off
-@@ -759,6 +851,17 @@
-               mcr     p15, 0, ip, c7, c10, 4  @ drain WB
-               mov     pc, lr
-               
-+/*****************************************************************************
-+ *  for Storlink Soc -- CPU cache
-+ *****************************************************************************/
-+__fa526_cache_flush:
-+                mov     r1, #0
-+                mcr     p15, 0, r1, c7, c14, 0  @ clean and invalidate D cache
-+                mcr     p15, 0, r1, c7, c5, 0   @ flush I cache
-+                mcr     p15, 0, r1, c7, c10, 4  @ drain WB
-+                mov     pc, lr
-+/*****************************************************************************/
-+
- __armv6_mmu_cache_flush:
-               mov     r1, #0
---- /dev/null
-+++ b/arch/arm/boot/compressed/it8712.h
-@@ -0,0 +1,25 @@
-+
-+#ifndef __IT8712_H__
-+#define __IT8712_H__
-+
-+#include "asm/arch/sl2312.h"
-+
-+#define IT8712_IO_BASE                        SL2312_LPC_IO_BASE
-+//#define IT8712_IO_BASE                      0x27000000
-+// Device LDN
-+#define LDN_SERIAL1                           0x01
-+#define LDN_SERIAL2                           0x02
-+#define LDN_PARALLEL                  0x03
-+#define LDN_KEYBOARD                  0x05
-+#define LDN_MOUSE                             0x06
-+#define LDN_GPIO                              0x07
-+
-+#define IT8712_UART1_PORT             0x3F8
-+#define IT8712_UART2_PORT             0x2F8
-+
-+#define IT8712_GPIO_BASE              0x800   // 0x800-0x804 for GPIO set1-set5
-+
-+void LPCSetConfig(char LdnNumber, char Index, char data);
-+char LPCGetConfig(char LdnNumber, char Index);
-+
-+#endif
---- a/arch/arm/boot/compressed/misc.c
-+++ b/arch/arm/boot/compressed/misc.c
-@@ -30,7 +30,7 @@
- #include <asm/arch/uncompress.h>
- #ifdef CONFIG_DEBUG_ICEDCC
--
-+#include "it8712.h"
- #ifdef CONFIG_CPU_V6
- static void icedcc_putc(int ch)
-@@ -69,6 +69,7 @@
- #define flush()       do { } while (0)
- #endif
-+#if 0
- static void putstr(const char *ptr)
- {
-       char c;
-@@ -81,11 +82,36 @@
-       flush();
- }
-+#endif
- #endif
- #define __ptr_t void *
-+#ifdef CONFIG_SERIAL_IT8712
-+unsigned int it8712_uart_base;
-+#define UART_RX         0
-+#define UART_TX         0
-+#define UART_DLL        0
-+#define UART_TRG        0
-+#define UART_DLM        1
-+#define UART_IER        1
-+#define UART_FCTR       1
-+#define UART_IIR        2
-+#define UART_FCR        2
-+#define UART_EFR        2
-+#define UART_LCR        3
-+#define UART_MCR        4
-+#define UART_LSR        5
-+#define UART_MSR        6
-+#define UART_SCR        7
-+#define UART_EMSR       7
-+void LPCEnterMBPnP(void);
-+void LPCExitMBPnP(void);
-+int SearchIT8712(void);
-+int InitLPCInterface(void);
-+#endif
-+
- /*
-  * Optimised C version of memzero for the ARM.
-  */
-@@ -346,6 +372,9 @@
- decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
-                 int arch_id)
- {
-+#ifdef CONFIG_SERIAL_IT8712
-+        unsigned char *addr;
-+#endif
-       output_data             = (uch *)output_start;  /* Points to kernel start */
-       free_mem_ptr            = free_mem_ptr_p;
-       free_mem_ptr_end        = free_mem_ptr_end_p;
-@@ -353,6 +382,33 @@
-       arch_decomp_setup();
-+#ifdef CONFIG_SERIAL_IT8712
-+
-+        InitLPCInterface();
-+        LPCSetConfig(0, 0x02, 0x01);
-+        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
-+        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
-+        it8712_uart_base = IT8712_IO_BASE;
-+        it8712_uart_base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
-+
-+        do {
-+        addr = (unsigned char *)(it8712_uart_base + UART_LCR) ;
-+        *addr = 0x80;
-+        // Set Baud Rate
-+        addr = (unsigned char *)(it8712_uart_base+UART_DLL);
-+        *addr = 0x06 ;
-+        addr = (unsigned char *)(it8712_uart_base+UART_DLM);
-+        *addr = 0x00 ;
-+
-+        addr = (unsigned char *)(it8712_uart_base+UART_LCR);    // LCR
-+        *addr = 0x07 ;
-+        addr = (unsigned char *)(it8712_uart_base+UART_MCR);    // MCR
-+        *addr = 0x08 ;
-+        addr = (unsigned char *)(it8712_uart_base+UART_FCR);    // FCR
-+        *addr = 0x01 ;
-+      } while(0);
-+#endif
-+
-       makecrc();
-       putstr("Uncompressing Linux...");
-       gunzip();
-@@ -374,4 +430,119 @@
-       return 0;
- }
- #endif
-+
-+#ifdef CONFIG_SERIAL_IT8712
-+
-+#define LPC_KEY_ADDR    (unsigned char *)(SL2312_LPC_IO_BASE + 0x2e)
-+#define LPC_DATA_ADDR   (unsigned char *)(SL2312_LPC_IO_BASE + 0x2f)
-+#define LPC_BUS_CTRL                    *( unsigned char*) (SL2312_LPC_HOST_BASE + 0)
-+#define LPC_BUS_STATUS                  *( unsigned char*) (SL2312_LPC_HOST_BASE + 2)
-+#define LPC_SERIAL_IRQ_CTRL             *( unsigned char*) (SL2312_LPC_HOST_BASE + 4)
-+
-+char LPCGetConfig(char LdnNumber, char Index)
-+{
-+        char rtn;
-+        unsigned char *addr ;
-+
-+        LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
-+
-+        addr = LPC_KEY_ADDR;
-+        *addr = 0x07 ;
-+
-+        addr = LPC_DATA_ADDR;
-+        *addr = LdnNumber ;
-+
-+        addr = LPC_KEY_ADDR;
-+        *addr = Index ;
-+
-+        addr = LPC_DATA_ADDR ;
-+        rtn = *addr ;
-+
-+        LPCExitMBPnP();
-+        return rtn;
-+
-+}
-+
-+void LPCSetConfig(char LdnNumber, char Index, char data)
-+{
-+        unsigned char *addr;
-+        LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
-+        addr = LPC_KEY_ADDR;
-+        *addr = 0x07;
-+        addr = LPC_DATA_ADDR;
-+        *addr = LdnNumber;
-+        addr = LPC_KEY_ADDR;
-+        *addr = Index;
-+        addr = LPC_DATA_ADDR;
-+        *addr = data;
-+
-+        LPCExitMBPnP();
-+}
-+
-+//unsigned char key[4] ;
-+void LPCEnterMBPnP(void)
-+{
-+        unsigned char *addr;
-+        addr = LPC_KEY_ADDR;
-+        unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
-+
-+              do {
-+              *addr = key[0];
-+              *addr = key[1];
-+              *addr = key[2];
-+              *addr = key[3];
-+              }while(0);
-+}
-+
-+void LPCExitMBPnP(void)
-+{
-+        unsigned char *addr;
-+        addr = LPC_KEY_ADDR;
-+        *addr = 0x02 ;
-+
-+        addr = LPC_DATA_ADDR;
-+        *addr = 0x02 ;
-+}
-+
-+int InitLPCInterface(void)
-+{
-+        int i;
-+        LPC_BUS_CTRL = 0xc0;
-+        LPC_SERIAL_IRQ_CTRL = 0xc0;
-+
-+        for(i=0;i<0x2000;i++) ;
-+
-+        LPC_SERIAL_IRQ_CTRL = 0x80;
-+        if (!SearchIT8712()) ;
-+//                    while(1);
-+        return 0;
-+}
-+
-+int SearchIT8712(void)
-+{
-+        unsigned char Id1, Id2;
-+        unsigned short Id;
-+        unsigned char *addr;
-+
-+        LPCEnterMBPnP();
-+        addr = LPC_KEY_ADDR;
-+        *addr = 0x20 ;
-+        addr = LPC_DATA_ADDR;
-+        Id1 = *addr ;
-+
-+        addr = LPC_KEY_ADDR;
-+        *addr = 0x21 ;
-+        addr = LPC_DATA_ADDR;
-+        Id2 = *addr ;
-+
-+        Id = (Id1 << 8) | Id2;
-+        LPCExitMBPnP();
-+
-+        if (Id == 0x8712)
-+                return 1;
-+        else
-+                return 0;
-+}
-+
-+#endif
-       
---- a/arch/arm/kernel/entry-armv.S
-+++ b/arch/arm/kernel/entry-armv.S
-@@ -18,6 +18,8 @@
- #include <asm/memory.h>
- #include <asm/glue.h>
- #include <asm/vfpmacros.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/hardware.h>
- #include <asm/arch/entry-macro.S>
- #include <asm/thread_notify.h>
---- a/arch/arm/kernel/irq.c
-+++ b/arch/arm/kernel/irq.c
-@@ -40,6 +40,8 @@
- #include <asm/system.h>
- #include <asm/mach/time.h>
-+extern int fixup_irq(unsigned int irq);
-+
- /*
-  * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
-  */
-@@ -111,8 +113,11 @@
- asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
- {
-       struct pt_regs *old_regs = set_irq_regs(regs);
--      struct irq_desc *desc = irq_desc + irq;
-+//    struct irq_desc *desc = irq_desc + irq;
-+      struct irq_desc *desc;
-+      irq = fixup_irq(irq);
-+      desc = irq_desc + irq;
-       /*
-        * Some hardware gives randomly wrong interrupts.  Rather
-        * than crashing, do something sensible.
---- a/arch/arm/kernel/process.c
-+++ b/arch/arm/kernel/process.c
-@@ -117,7 +117,7 @@
- void (*pm_idle)(void);
- EXPORT_SYMBOL(pm_idle);
--void (*pm_power_off)(void);
-+//void (*pm_power_off)(void);
- EXPORT_SYMBOL(pm_power_off);
- void (*arm_pm_restart)(char str) = arm_machine_restart;
-@@ -188,13 +188,37 @@
- void machine_halt(void)
- {
-+      unsigned int reg_v;
-+
-+      printk("arch_power_off\n");
-+
-+      reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
-+      reg_v &= ~0x00000002;
-+      reg_v |= 0x1;
-+      mdelay(5);
-+      // Power off
-+      __raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
-+
- }
- void machine_power_off(void)
- {
--      if (pm_power_off)
-+      unsigned int reg_v;
-+
-+//    if (pm_power_off)
-+      if (&pm_power_off!=NULL)
-               pm_power_off();
-+
-+      printk("arch_power_off\n");
-+
-+      reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
-+      reg_v &= ~0x00000002;
-+      reg_v |= 0x1;
-+      mdelay(5);
-+      // Power off
-+      __raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
-+
- }
- void machine_restart(char * __unused)
---- a/arch/arm/kernel/time.c
-+++ b/arch/arm/kernel/time.c
-@@ -502,8 +502,13 @@
- device_initcall(timer_init_sysfs);
-+extern unsigned int rtc_get_time_second(void);
-+
- void __init time_init(void)
- {
-+#ifdef CONFIG_SL2312_RTC
-+      xtime.tv_sec  = rtc_get_time_second() ;
-+#endif
- #ifndef CONFIG_GENERIC_TIME
-       if (system_timer->offset == NULL)
-               system_timer->offset = dummy_gettimeoffset;
---- /dev/null
-+++ b/arch/arm/mach-sl2312/Kconfig
-@@ -0,0 +1,33 @@
-+
-+menu "SL2312"
-+
-+config SL3516_ASIC
-+      bool "SL3516 ASIC version"
-+      depends on ARCH_SL2312
-+      help
-+        This option to select AISC or FPGA
-+config PCI
-+       bool "SL2312 PCI"
-+       depends on ARCH_SL2312
-+       help
-+         This option to enable Storlink PCI controller
-+
-+config SL2312_LPC
-+       bool "SL2312 LPC"
-+       depends on ARCH_SL2312
-+       help
-+         This option to enable Low Pin Count controller
-+
-+config SL2312_USB
-+       bool "SL2312 USB"
-+       depends on ARCH_SL2312
-+       help
-+         This option to enable USB OTG host controller
-+
-+config GEMINI_IPI
-+       bool "Gemini IPI test"
-+       depends on ARCH_SL2312
-+       help
-+       Enable this option to test dual cpu Inter-Processor-Interrupt
-+endmenu
-+
---- /dev/null
-+++ b/arch/arm/mach-sl2312/Makefile
-@@ -0,0 +1,16 @@
-+#
-+# Makefile for the linux kernel.
-+#
-+
-+# Object file lists.
-+
-+obj-y                 := arch.o irq.o mm.o time.o sl3516_device.o
-+obj-m                 :=
-+obj-n                 :=
-+
-+
-+obj-$(CONFIG_PCI) += pci.o
-+obj-$(CONFIG_SL2312_LPC) += lpc.o
-+obj-$(CONFIG_SL2312_USB) += sl2312-otg.o # sl2312-otg-1.o
-+obj-$(CONFIG_GEMINI_XOR_ACCE) += xor.o
-+obj-$(CONFIG_GEMINI_IPI)      += gemini_ipi.o
---- /dev/null
-+++ b/arch/arm/mach-sl2312/Makefile.boot
-@@ -0,0 +1,5 @@
-+   zreladdr-y := 0x00008000
-+params_phys-y := 0x00508100
-+#params_phys-y        := 0x00008100
-+initrd_phys-y := 0x00800000
-+
---- /dev/null
-+++ b/arch/arm/mach-sl2312/arch.c
-@@ -0,0 +1,72 @@
-+/*
-+ *  linux/arch/arm/mach-epxa10db/arch.c
-+ *
-+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include <linux/types.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/setup.h>
-+#include <asm/mach-types.h>
-+#include <asm/mach/time.h>
-+#include <asm/mach/arch.h>
-+
-+extern void sl2312_map_io(void);
-+extern void sl2312_init_irq(void);
-+extern unsigned long sl2312_gettimeoffset (void);
-+extern void __init sl2312_time_init(void);
-+
-+static struct sys_timer sl2312_timer = {
-+      .init           = sl2312_time_init,
-+      .offset         = sl2312_gettimeoffset,
-+};
-+
-+static void __init
-+sl2312_fixup(struct machine_desc *desc, struct tag *tags,
-+                 char **cmdline, struct meminfo *mi)
-+{
-+        mi->nr_banks      = 1;
-+        mi->bank[0].start = 0;
-+#ifdef CONFIG_GEMINI_IPI
-+        mi->bank[0].size  = (64*1024*1024);  // 128M
-+#else
-+        mi->bank[0].size  = (128*1024*1024);  // 128M
-+#endif
-+        mi->bank[0].node  = 0;
-+}
-+
-+/* MACHINE_START(SL2312, "GeminiA")
-+      MAINTAINER("Storlink Semi")
-+      BOOT_MEM(0x00000000, 0x90000000, 0xf0000000)
-+        FIXUP(sl2312_fixup)
-+      MAPIO(sl2312_map_io)
-+      INITIRQ(sl2312_init_irq)
-+      .timer = &sl2312_timer,
-+MACHINE_END */
-+
-+MACHINE_START(SL2312, "GeminiA")
-+      /* .phys_ram    = 0x00000000, */
-+      .phys_io        = 0x7fffc000,
-+      .io_pg_offst    = ((0xffffc000) >> 18) & 0xfffc,
-+      .boot_params    = 0x100,
-+      .fixup      = sl2312_fixup,
-+      .map_io         = sl2312_map_io,
-+      .init_irq       = sl2312_init_irq,
-+      .timer          = &sl2312_timer,
-+MACHINE_END
---- /dev/null
-+++ b/arch/arm/mach-sl2312/gemini_ipi.c
-@@ -0,0 +1,593 @@
-+/*
-+ * FILE NAME sl_cir.c
-+ *
-+ * BRIEF MODULE DESCRIPTION
-+ *  IPI Driver for CPU1.
-+ *
-+ *  Author: StorLink, Corp.
-+ *          Jason Lee
-+ *
-+ * Copyright 2002~2006 StorLink, Corp.
-+ *
-+ *  This program is free software; you can redistribute  it and/or modify it
-+ *  under  the terms of  the GNU General  Public License as published by the
-+ *  Free Software Foundation;  either version 2 of the  License, or (at your
-+ *  option) any later version.
-+ *
-+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
-+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMit8712D  TO, THE IMPLIED WARRANTIES OF
-+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
-+ *  NO  EVENT  SHALL   THE AUTHOR  BE LIABLE FOR ANY   DIRECT, INDIRECT,
-+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ *  NOT LIMit8712D   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
-+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
-+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ *  You should have received a copy of the  GNU General Public License along
-+ *  with this program; if not, writ8712  to the Free Software Foundation, Inc.,
-+ *  675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/miscdevice.h>
-+#include <linux/init.h>
-+#include <linux/pagemap.h>
-+#include <asm/uaccess.h>
-+#include <linux/ioport.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <asm/io.h>
-+#include <asm/delay.h>
-+#include <linux/signal.h>
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/int_ctrl.h>
-+#include <asm/arch/ipi.h>
-+#include <linux/dma-mapping.h>
-+
-+
-+#include <linux/mm.h>
-+
-+#include <linux/bootmem.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/page.h>
-+#include <asm/setup.h>
-+#include <asm/pgtable.h>
-+#include <asm/pgalloc.h>
-+
-+#include <asm/mach/map.h>
-+
-+
-+static int sl_ipi_debug = 1 ;
-+#define DEB(x)  if(sl_ipi_debug>=1) x
-+
-+#define SRAM_PTR              IO_ADDRESS(SL2312_SRAM_BASE)
-+volatile JSCALE_REQ_T *req=(JSCALE_REQ_T*)SRAM_PTR;
-+volatile JSCALE_RSP_T *rsp=(JSCALE_RSP_T*)(SRAM_PTR+0x20);
-+
-+unsigned int jscale_status=0;
-+
-+#define JSCALE_WAIT   0
-+#define XXXXXX_WAIT   1
-+#define MAX_WAIT_Q    8
-+wait_queue_head_t gemini_ipi_wait[MAX_WAIT_Q];
-+
-+#define DRAMCTL_DMA_CTL               0X20
-+#define DRAMCTL_DMA_SA                0X24
-+#define DRAMCTL_DMA_DA                0X28
-+#define DRAMCTL_DMA_CNT               0X2C
-+#define MEMCPY_UNIT           0x40000
-+int hw_memcpy(const void *to, const void *from, unsigned int bytes)
-+{
-+      unsigned int reg_a,reg_d;
-+      int count = bytes,i=0;
-+
-+      consistent_sync((unsigned int *)to, bytes, DMA_BIDIRECTIONAL);
-+      consistent_sync((unsigned int *)from,bytes, DMA_TO_DEVICE);
-+
-+      DEB(printk("hwmemcpy:count %d\n",count));
-+      while(count>0){
-+              // SA
-+              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_SA;
-+              reg_d = (unsigned int )__virt_to_phys(from) + i*MEMCPY_UNIT;
-+              DEB(printk("hwmemcpy:from 0x%08x\n",reg_d));
-+              writel(reg_d,reg_a);
-+              // DA
-+              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_DA;
-+              reg_d = (unsigned int )__virt_to_phys(to) + i*MEMCPY_UNIT;
-+              writel(reg_d,reg_a);
-+              DEB(printk("hwmemcpy:to 0x%08x\n",reg_d));
-+              // byte count
-+              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CNT;
-+              reg_d = (count>=MEMCPY_UNIT)?MEMCPY_UNIT:count;
-+              writel(reg_d,reg_a);
-+              // start DMA
-+              reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL;
-+              writel(0x80000001,reg_a);
-+
-+              do{
-+                      cond_resched();
-+//                    msleep(4);
-+                      reg_d = readl(IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL);
-+              }while(reg_d&0x1);
-+
-+              count -= MEMCPY_UNIT;
-+              i++;
-+      }
-+
-+      return bytes;
-+}
-+
-+static irqreturn_t ipi_interrupt()
-+{
-+      unsigned int id=getcpuid(),tmp;
-+
-+      //dmac_inv_range(__phys_to_virt(SL2312_SRAM_BASE),__phys_to_virt(SHAREADDR)+0x2000);
-+
-+
-+      // Clear Interrupt
-+      if(id==CPU0) {
-+              tmp = readl(CPU1_STATUS);
-+              tmp &= ~CPU_IPI_BIT_MASK;
-+              writel(tmp,CPU1_STATUS);
-+      }
-+      else{
-+              tmp = readl(CPU0_STATUS);
-+              tmp &= ~CPU_IPI_BIT_MASK;
-+              writel(tmp,CPU0_STATUS);
-+      }
-+
-+      //
-+      DEB(printk("ipi interrupt:0x%x\n",rsp->status));
-+      switch(rsp->status){
-+              case JSCALE_STATUS_OK:
-+
-+                      break;
-+              case JSCALE_UNKNOWN_MSG_TYPE:
-+
-+                      break;
-+              case JSCALE_FAILED_FILE_SIZE:
-+
-+                      break;
-+              case JSCALE_FAILED_MALLOC:
-+
-+                      break;
-+              case JSCALE_FAILED_FORMAT:
-+
-+                      break;
-+              case JSCALE_DECODE_ERROR:
-+
-+                      break;
-+
-+      }
-+      jscale_status = rsp->status;
-+//    wake_up(&gemini_ipi_wait[JSCALE_WAIT]);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int gemini_ipi_open(struct inode *inode, struct file *file)
-+{
-+      DEB(printk("ipi open\n"));
-+      return 0;
-+}
-+
-+
-+static int gemini_ipi_release(struct inode *inode, struct file *file)
-+{
-+      DEB(printk("ipi release\n"));
-+      return 0;
-+}
-+
-+
-+static int gemini_ipi_ioctl(struct inode *inode, struct file *file,
-+      unsigned int cmd, unsigned long arg)
-+{
-+      JSCALE_RSP_T tmp;
-+
-+      switch(cmd) {
-+              case GEMINI_IPI_JSCALE_REQ:
-+                      DEB(printk("ipi:ioctl jscale request %dX%d Q:%d\n",req->ScaledImageWidth,req->ScaledImageHeight,req->ScaledImageQuality));
-+                      if (copy_from_user(req, (JSCALE_REQ_T *)arg, sizeof(JSCALE_REQ_T)))
-+                              return -EFAULT;
-+                      req->hdr.type = IPC_JSCALE_REQ_MSG;
-+                      req->hdr.length = sizeof(JSCALE_REQ_T);
-+                      req->input_location  = CPU_1_DATA_OFFSET;
-+                      req->output_location = CPU_1_DATA_OFFSET;
-+                      break;
-+              case GEMINI_IPI_JSCALE_STAT:
-+                      DEB(printk("ipi:ioctl jscale stat \n"));
-+                      if(jscale_status==JSCALE_BUSY){                                         // not yet
-+                              tmp.status = JSCALE_BUSY;
-+                              if (copy_to_user((JSCALE_RSP_T *)arg,&tmp, sizeof(JSCALE_RSP_T)))
-+                                      return -EFAULT;
-+                      }
-+                      else{                                                                                           // finish or error
-+                              if (copy_to_user((JSCALE_RSP_T *)arg,rsp, sizeof(JSCALE_RSP_T)))
-+                                      return -EFAULT;
-+                      }
-+                      break;
-+              default:
-+                      printk("IPI: Error IOCTL number\n");
-+                      return -ENOIOCTLCMD;
-+      }
-+
-+      return 0;
-+}
-+
-+#define SRAM_SIZE     0x2000
-+static ssize_t gemini_ipi_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos)
-+{
-+      int i=0,tmp=0,j;
-+      const char *ptr=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
-+      DEB(printk("ipi:write 0x%x to 0x%x length:%d\n",&buf,ptr,count));
-+      memcpy(ptr,buf,count);
-+      consistent_sync(ptr,count, DMA_TO_DEVICE);
-+      //hw_memcpy(ptr,&buf,count);
-+
-+/*    if(count>SRAM_SIZE){
-+              for(i=0;i<(count/SRAM_SIZE);i++)
-+                      raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,SRAM_SIZE);
-+              if(count%SRAM_SIZE)
-+                      raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,count%SRAM_SIZE);
-+      }
-+      else
-+              raid_memcpy(ptr,buf,count);
-+*/
-+
-+/*    for(i=0;i<count;i++){
-+              if(buf[i]!=ptr[i])
-+                      printk("ipi error:offset %d valud %x[should %x]\n",i,ptr[i],buf[i]);
-+      }
-+
-+      printk("===========input buf===============\n");
-+      for(i=0;i<64;i+=16){
-+              for(j=0;j<16;j++)
-+                      printk("%02x ",buf[i+j]);
-+              printk("\n");
-+              cond_resched();
-+      }
-+      printk("===========output buf==============\n");
-+      for(i=0;i<64;i+=16){
-+              for(j=0;j<16;j++)
-+                      printk("%02x ",ptr[i+j]);
-+              printk("\n");
-+              cond_resched();
-+      }
-+*/
-+      // send irq for CPU1
-+      tmp |= CPU_IPI_BIT_MASK;
-+      writel(tmp,CPU0_STATUS);
-+      jscale_status = JSCALE_BUSY;
-+
-+      return count;
-+}
-+
-+static ssize_t gemini_ipi_read(struct file * file_p, char *buf, size_t length, loff_t * ppos)
-+{
-+      int i=0;
-+      const char *ptr=(unsigned int )__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
-+
-+      consistent_sync(ptr,length, DMA_FROM_DEVICE);
-+      memcpy(buf,ptr,length);
-+      DEB(printk("ipi:read 0x%x to 0x%x length:%d\n",ptr,buf,length));
-+
-+      //consistent_sync((unsigned int *)ptr,0x2000, DMA_FROM_DEVICE);         // invalid
-+      //hw_memcpy(buf,ptr,length);
-+
-+      // need encoded file size ********
-+/*    if(count>SRAM_SIZE){
-+              for(i=0;i<(count/SRAM_SIZE);i++)
-+                      raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,SRAM_SIZE);
-+              if(count%0xFFFF)
-+                      raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,length%SRAM_SIZE);
-+      }
-+      else
-+              raid_memcpy(buf,p_mbox->message,length);
-+*/
-+      return length;
-+}
-+
-+void do_mapping_read(struct address_space *mapping,
-+                           struct file_ra_state *_ra,
-+                           struct file *filp,
-+                           loff_t *ppos,
-+                           read_descriptor_t *desc,
-+                           read_actor_t actor)
-+{
-+      struct inode *inode = mapping->host;
-+      unsigned long index;
-+      unsigned long end_index;
-+      unsigned long offset;
-+      unsigned long last_index;
-+      unsigned long next_index;
-+      unsigned long prev_index;
-+      loff_t isize;
-+      struct page *cached_page;
-+      int error;
-+      struct file_ra_state ra = *_ra;
-+
-+      cached_page = NULL;
-+      index = *ppos >> PAGE_CACHE_SHIFT;
-+      next_index = index;
-+      prev_index = ra.prev_page;
-+      last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
-+      offset = *ppos & ~PAGE_CACHE_MASK;
-+
-+      isize = i_size_read(inode);
-+      if (!isize)
-+              goto out;
-+
-+      end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
-+      for (;;) {
-+              struct page *page;
-+              unsigned long nr, ret;
-+
-+              /* nr is the maximum number of bytes to copy from this page */
-+              nr = PAGE_CACHE_SIZE;
-+              if (index >= end_index) {
-+                      if (index > end_index)
-+                              goto out;
-+                      nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
-+                      if (nr <= offset) {
-+                              goto out;
-+                      }
-+              }
-+              nr = nr - offset;
-+
-+              cond_resched();
-+              if (index == next_index)
-+                      next_index = page_cache_readahead(mapping, &ra, filp,
-+                                      index, last_index - index);
-+
-+find_page:
-+              page = find_get_page(mapping, index);
-+              if (unlikely(page == NULL)) {
-+                      handle_ra_miss(mapping, &ra, index);
-+                      goto no_cached_page;
-+              }
-+              if (!PageUptodate(page))
-+                      goto page_not_up_to_date;
-+page_ok:
-+
-+              /* If users can be writing to this page using arbitrary
-+               * virtual addresses, take care about potential aliasing
-+               * before reading the page on the kernel side.
-+               */
-+              if (mapping_writably_mapped(mapping))
-+                      flush_dcache_page(page);
-+
-+              /*
-+               * When (part of) the same page is read multiple times
-+               * in succession, only mark it as accessed the first time.
-+               */
-+              if (prev_index != index)
-+                      mark_page_accessed(page);
-+              prev_index = index;
-+
-+              /*
-+               * Ok, we have the page, and it's up-to-date, so
-+               * now we can copy it to user space...
-+               *
-+               * The actor routine returns how many bytes were actually used..
-+               * NOTE! This may not be the same as how much of a user buffer
-+               * we filled up (we may be padding etc), so we can only update
-+               * "pos" here (the actor routine has to update the user buffer
-+               * pointers and the remaining count).
-+               */
-+              ret = actor(desc, page, offset, nr);
-+              offset += ret;
-+              index += offset >> PAGE_CACHE_SHIFT;
-+              offset &= ~PAGE_CACHE_MASK;
-+
-+              page_cache_release(page);
-+              if (ret == nr && desc->count)
-+                      continue;
-+              goto out;
-+
-+page_not_up_to_date:
-+              /* Get exclusive access to the page ... */
-+              lock_page(page);
-+
-+              /* Did it get unhashed before we got the lock? */
-+              if (!page->mapping) {
-+                      unlock_page(page);
-+                      page_cache_release(page);
-+                      continue;
-+              }
-+
-+              /* Did somebody else fill it already? */
-+              if (PageUptodate(page)) {
-+                      unlock_page(page);
-+                      goto page_ok;
-+              }
-+
-+readpage:
-+              /* Start the actual read. The read will unlock the page. */
-+              error = mapping->a_ops->readpage(filp, page);
-+
-+              if (unlikely(error))
-+                      goto readpage_error;
-+
-+              if (!PageUptodate(page)) {
-+                      lock_page(page);
-+                      if (!PageUptodate(page)) {
-+                              if (page->mapping == NULL) {
-+                                      /*
-+                                       * invalidate_inode_pages got it
-+                                       */
-+                                      unlock_page(page);
-+                                      page_cache_release(page);
-+                                      goto find_page;
-+                              }
-+                              unlock_page(page);
-+                              error = -EIO;
-+                              goto readpage_error;
-+                      }
-+                      unlock_page(page);
-+              }
-+
-+              /*
-+               * i_size must be checked after we have done ->readpage.
-+               *
-+               * Checking i_size after the readpage allows us to calculate
-+               * the correct value for "nr", which means the zero-filled
-+               * part of the page is not copied back to userspace (unless
-+               * another truncate extends the file - this is desired though).
-+               */
-+              isize = i_size_read(inode);
-+              end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
-+              if (unlikely(!isize || index > end_index)) {
-+                      page_cache_release(page);
-+                      goto out;
-+              }
-+
-+              /* nr is the maximum number of bytes to copy from this page */
-+              nr = PAGE_CACHE_SIZE;
-+              if (index == end_index) {
-+                      nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
-+                      if (nr <= offset) {
-+                              page_cache_release(page);
-+                              goto out;
-+                      }
-+              }
-+              nr = nr - offset;
-+              goto page_ok;
-+
-+readpage_error:
-+              /* UHHUH! A synchronous read error occurred. Report it */
-+              desc->error = error;
-+              page_cache_release(page);
-+              goto out;
-+
-+no_cached_page:
-+              /*
-+               * Ok, it wasn't cached, so we need to create a new
-+               * page..
-+               */
-+              if (!cached_page) {
-+                      cached_page = page_cache_alloc_cold(mapping);
-+                      if (!cached_page) {
-+                              desc->error = -ENOMEM;
-+                              goto out;
-+                      }
-+              }
-+              error = add_to_page_cache_lru(cached_page, mapping,
-+                                              index, GFP_KERNEL);
-+              if (error) {
-+                      if (error == -EEXIST)
-+                              goto find_page;
-+                      desc->error = error;
-+                      goto out;
-+              }
-+              page = cached_page;
-+              cached_page = NULL;
-+              goto readpage;
-+      }
-+
-+out:
-+      *_ra = ra;
-+
-+      *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
-+      if (cached_page)
-+              page_cache_release(cached_page);
-+      if (filp)
-+              file_accessed(filp);
-+}
-+
-+int ipi_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
-+{
-+      ssize_t written;
-+      unsigned long count = desc->count;
-+      struct file *file = desc->arg.data;
-+      unsigned int *ptr_to=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET) + desc->written;
-+      void *ptr_from;
-+
-+      if (size > count)
-+              size = count;
-+
-+      ptr_from = page_address(page)+offset;
-+      written = memcpy(ptr_to,ptr_from,size);
-+
-+      if (written < 0) {
-+              desc->error = written;
-+              written = 0;
-+      }
-+      desc->count = count - written;
-+      desc->written += written;
-+      return written;
-+}
-+
-+ssize_t gemini_ipi_sendfile(struct file *in_file, loff_t *ppos,
-+                       size_t count, read_actor_t actor, void *TARGET)
-+{
-+      read_descriptor_t desc;
-+
-+      if (!count)
-+              return 0;
-+
-+      desc.written = 0;
-+      desc.count = count;
-+      desc.arg.data = TARGET;
-+      desc.error = 0;
-+
-+      do_mapping_read(in_file->f_mapping,&in_file->f_ra,in_file, ppos, &desc, ipi_send_actor);
-+
-+      if (desc.written)
-+              return desc.written;
-+      return desc.error;
-+}
-+static struct file_operations gemini_ipi_fops = {
-+      .owner  =       THIS_MODULE,
-+      .ioctl  =       gemini_ipi_ioctl,
-+      .open   =       gemini_ipi_open,
-+      .release=       gemini_ipi_release,
-+      .write  =       gemini_ipi_write,
-+      .read   =       gemini_ipi_read,
-+      .sendfile = gemini_ipi_sendfile,
-+};
-+
-+#ifndef STORLINK_IPI
-+#define STORLINK_IPI  242             // Documents/devices.txt suggest to use 240~255 for local driver!!
-+#endif
-+
-+static struct miscdevice gemini_ipi_miscdev =
-+{
-+      STORLINK_IPI,
-+      "slave_ipc",
-+      &gemini_ipi_fops
-+};
-+
-+int __init sl_ipi_init(void)
-+{
-+
-+      printk("Gemini IPI Driver Initialization...\n");
-+      printk("REQ Head :0x%x(phy:0x%x)\n",(unsigned int)req,(unsigned int)SL2312_SRAM_BASE);
-+      printk("RSP Head :0x%x(phy:0x%x)\n",(unsigned int)rsp,(unsigned int)SL2312_SRAM_BASE+0x20);
-+      printk("Data buff:0x%x(phy:0x%x)\n",__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET),CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
-+
-+      misc_register(&gemini_ipi_miscdev);
-+
-+      if (request_irq(IRQ_CPU0_IP_IRQ_OFFSET, ipi_interrupt, SA_INTERRUPT, "ipi", NULL))
-+              printk("Error: Register IRQ for Storlink IPI failed\n");
-+
-+      return 0;
-+}
-+
-+void __exit sl_ipi_exit(void)
-+{
-+
-+}
-+
-+module_init(sl_ipi_init);
-+module_exit(sl_ipi_exit);
-+
-+MODULE_AUTHOR("Jason Lee <jason@storlink.com.tw>");
-+MODULE_DESCRIPTION("Storlink IPI driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/arch/arm/mach-sl2312/hw_xor.h
-@@ -0,0 +1,573 @@
-+/*
-+*  linux/include/asm-arm/xor.h
-+*
-+*  Copyright (C) 2001 Storlink Semi.
-+*     Jason Lee <jason@storlink.com.tw>
-+*
-+*/
-+#include <asm/arch/sl2312.h>
-+#include <asm/io.h>
-+//#include <linux/compatmac.h>
-+
-+#undef BIG_ENDIAN
-+#define CPU           0
-+#define DMA           1
-+
-+#define DESC_NO       8
-+#define TX_DESC_NUM           DESC_NO
-+#define RX_DESC_NUM           DESC_NO
-+
-+#define RAID_BASE_ADDR        IO_ADDRESS(SL2312_RAID_BASE)
-+
-+#define SRAM_PAR_0k           0
-+#define SRAM_PAR_4k           1
-+#define SRAM_PAR_8k           2
-+#define SRAM_PAR_16k          3
-+#define SRAM_PAR_SIZE SRAM_PAR_8k
-+
-+#define RUNNING               0x1
-+#define COMPLETE      0x2
-+#define ERROR                 0x4
-+
-+#define CMD_XOR               0x0
-+#define CMD_FILL      0x1
-+#define CMD_CPY               0x3
-+#define CMD_CHK               0x4
-+
-+enum RAID_DMA_REGISTER {
-+      RAID_DMA_DEVICE_ID              = 0xff00,
-+      RAID_DMA_STATUS                 = 0xff04,
-+      RAID_FCHDMA_CTRL                = 0xff08,
-+      RAID_FCHDMA_FIRST_DESC  = 0xff0C,
-+      RAID_FCHDMA_CURR_DESC   = 0xff10,
-+      RAID_STRDMA_CTRL                = 0xff14,
-+      RAID_STRDMA_FIRST_DESC  = 0xff18,
-+      RAID_STRDMA_CURR_DESC   = 0xff1C,
-+      RAID_TX_FLG_REG                 = 0xff24,
-+      RAID_RX_FLG_REG                 = 0xff34,
-+      RAID_PCR                                = 0xff50,
-+      SMC_CMD_REG                             = 0xff60,
-+      SMC_STATUS_REG                  = 0xff64
-+      };
-+
-+enum RAID_FUNC_MODE {
-+      RAID_XOR                        = 0,
-+      RAID_MIX                        = 2,
-+      RAID_SRAM                       = 3,
-+      RAID_ENDIAN                     = 4,
-+      RAID_MEM_BLK            = 5,
-+      RAID_MEM2MEM            = 7,
-+      RAID_BUF_SIZE           = 8,
-+      RAID_ERR_TEST           = 9,
-+      RAID_BURST                      = 10,
-+      RAID_BUS                        = 11
-+      };
-+
-+typedef struct reg_info {
-+      int mask;
-+      char err[32];
-+      int offset;
-+} REG_INFO;
-+
-+/********************************************************/
-+/*    the definition of RAID DMA Module Register      */
-+/********************************************************/
-+typedef union
-+{
-+      unsigned int bit32;
-+      struct bits_ff00
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int                            : 8;
-+              unsigned int teytPerr           : 4; /* define protocol error under tsPErrI*/
-+              unsigned int reytPerr           : 14; /* define protocol error under rsPErrI */
-+              unsigned int device_id          : 12;
-+              unsigned int revision_id        : 4;
-+              #else
-+              unsigned int revision_id        : 4;
-+              unsigned int device_id          : 12;
-+              unsigned int reytPerr           : 14; /* define protocol error under rsPErrI */
-+              unsigned int teytPerr           : 4; /* define protocol error under tsPErrI*/
-+              unsigned int                            : 8;
-+              #endif
-+      } bits;
-+} RAID_DMA_DEVICE_ID_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff04
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int tsFinishI          : 1; /* owner bit error interrupt */
-+              unsigned int tsDErrI            : 1; /* AHB bus error interrupt */
-+              unsigned int tsPErrI            : 1; /* RAID XOR fetch descriptor protocol error interrupt */
-+              unsigned int tsEODI                     : 1; /* RAID XOR fetch DMA end of descriptor interrupt */
-+              unsigned int tsEOFI                     : 1; /* RAID XOR fetch DMA end of frame interrupt */
-+              unsigned int rsFinishI          : 1; /* owner bit error interrupt */
-+              unsigned int rsDErrI            : 1; /* AHB bus error while RAID XOR store interrupt */
-+              unsigned int rsPErrI            : 1; /* RAID XOR store descriptor protocol error interrupt */
-+              unsigned int rsEODI                     : 1; /* RAID XOR store DMA end of descriptor interrupt */
-+              unsigned int rsEOFI                     : 1; /* RAID XOR store DMA end of frame interrupt */
-+              unsigned int inter                      : 8; /* pattern check error interrupt */
-+              unsigned int                            : 5;
-+              unsigned int Loopback           : 1; /* loopback */
-+              unsigned int intEnable          : 8; /*pattern check error interrupt enable */
-+              #else
-+              unsigned int intEnable          : 8; /*pattern check error interrupt enable */
-+              unsigned int Loopback           : 1; /* loopback */
-+              unsigned int                            : 5;
-+              unsigned int inter                      : 8; /* pattern check error interrupt */
-+              unsigned int rsEOFI                     : 1; /* RAID XOR store DMA end of frame interrupt */
-+              unsigned int rsEODI                     : 1; /* RAID XOR store DMA end of descriptor interrupt */
-+              unsigned int rsPErrI            : 1; /* RAID XOR store descriptor protocol error interrupt */
-+              unsigned int rsDErrI            : 1; /* AHB bus error while RAID XOR store interrupt */
-+              unsigned int rsFinishI          : 1; /* owner bit error interrupt */
-+              unsigned int tsEOFI                     : 1; /* RAID XOR fetch DMA end of frame interrupt */
-+              unsigned int tsEODI                     : 1; /* RAID XOR fetch DMA end of descriptor interrupt */
-+              unsigned int tsPErrI            : 1; /* RAID XOR fetch descriptor protocol error interrupt */
-+              unsigned int tsDErrI            : 1; /* AHB bus error interrupt */
-+              unsigned int tsFinishI          : 1; /* owner bit error interrupt */
-+              #endif
-+      } bits;
-+} RAID_DMA_STATUS_T;
-+
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff08
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int td_start           :  1;   /* Start DMA transfer */
-+              unsigned int td_continue        :  1;   /* Continue DMA operation */
-+              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int                            :  1;
-+              unsigned int td_prot            :  4;   /* DMA protection control */
-+              unsigned int td_burst_size  :  2;       /* DMA max burst size for every AHB request */
-+              unsigned int td_bus                 :  2;       /* peripheral bus width */
-+              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int                            : 14;
-+              #else
-+              unsigned int                            : 14;
-+              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int td_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
-+              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
-+              unsigned int td_prot            :  4;   /* TxDMA protection control */
-+              unsigned int                            :  1;
-+              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int td_continue        :  1;   /* Continue DMA operation */
-+              unsigned int td_start           :  1;   /* Start DMA transfer */
-+              #endif
-+      } bits;
-+} RAID_TXDMA_CTRL_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff0c
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
-+              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
-+              unsigned int                                    :  3;
-+              #else
-+              unsigned int                                    :  3;
-+              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
-+              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
-+              #endif
-+      } bits;
-+} RAID_TXDMA_FIRST_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff10
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int                            :  1;
-+              unsigned int sof_eof            :  2;
-+              #else
-+              unsigned int sof_eof            :  2;
-+              unsigned int                            :  1;
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              #endif
-+      } bits;
-+} RAID_TXDMA_CURR_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff14
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int rd_start           :  1;   /* Start DMA transfer */
-+              unsigned int rd_continue        :  1;   /* Continue DMA operation */
-+              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int                            :  1;
-+              unsigned int rd_prot            :  4;   /* DMA protection control */
-+              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
-+              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
-+              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int                            : 14;
-+              #else
-+              unsigned int                            : 14;
-+              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
-+              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
-+              unsigned int rd_prot            :  4;   /* DMA protection control */
-+              unsigned int                            :  1;
-+              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int rd_continue        :  1;   /* Continue DMA operation */
-+              unsigned int rd_start           :  1;   /* Start DMA transfer */
-+              #endif
-+      } bits;
-+} RAID_RXDMA_CTRL_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff18
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
-+              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
-+              unsigned int                                    :  3;
-+              #else
-+              unsigned int                                    :  3;
-+              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
-+              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
-+              #endif
-+      } bits;
-+} RAID_RXDMA_FIRST_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff1c
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
-+              unsigned int sof_eof            :  2;
-+              #else
-+              unsigned int sof_eof            :  2;
-+              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              #endif
-+      } bits;
-+} RAID_RXDMA_CURR_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bit32;
-+      struct bits_ff50
-+      {
-+              unsigned int pat                        : 32; /* data for pattern check */
-+      } bits;
-+} RAID_PACR_T;
-+
-+/******************************************************/
-+/*    the definition of DMA Descriptor Register     */
-+/******************************************************/
-+typedef struct raid_descriptor_t
-+{
-+      union func_ctrl_t
-+      {
-+              unsigned int bit32;
-+              struct bits_0000
-+              {
-+                      #ifdef BIG_ENDIAN
-+                      unsigned int own                                : 1; /* owner bit */
-+                      unsigned int derr                               : 1;    /* data error during processing this descriptor */
-+                      unsigned int perr                               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int raid_ctrl_status   : 7; /* pass RAID XOR fetch/store control status to CPU */
-+                      unsigned int desc_cnt                   : 6;
-+                      unsigned int buffer_size                : 16;   /* transfer buffer size associated with current description*/
-+                      #else
-+                      unsigned int buffer_size                : 16;   /* transfer buffer size associated with current description*/
-+                      unsigned int desc_cnt                   : 6;
-+                      unsigned int raid_ctrl_status   : 7; /* pass RAID XOR fetch/store control status to CPU */
-+                      unsigned int perr                               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int derr                               : 1;    /* data error during processing this descriptor */
-+                      unsigned int own                                : 1; /* owner bit */
-+                      #endif
-+              } bits;
-+      } func_ctrl;
-+
-+      union flg_status_t
-+      {
-+              unsigned int bits32;
-+              struct bit_004
-+              {
-+                      #ifdef BIG_ENDIAN
-+                      unsigned int bcc                : 16;
-+                      unsigned int                    : 13
-+                      unsigned int mode               : 3;
-+                      #else
-+                      unsigned int mode               : 3;
-+                      unsigned int                    : 13;
-+                      unsigned int bcc                : 16;
-+                      #endif
-+              } bits_cmd_status;
-+      } flg_status;  //Sanders
-+
-+      unsigned int buf_addr;
-+
-+      union next_desc_addr_t
-+      {
-+              unsigned int bits32;
-+              struct bits_000c
-+              {
-+                      #ifdef BIG_ENDIAN
-+                      unsigned int ndar               : 28; /* next descriptor address */
-+                      unsigned int eofie              : 1; /* end of frame interrupt enable */
-+                      unsigned int                    : 1;
-+                      unsigned int sof_eof    : 2; /* the position of the descriptor in chain */
-+                      #else
-+                      unsigned int sof_eof    : 2; /* the position of the descriptor in chain */
-+                      unsigned int                    : 1;
-+                      unsigned int eofie              : 1; /* end of frame interrupt enable */
-+                      unsigned int ndar               : 28; /* next descriptor address */
-+                      #endif
-+              } bits;
-+      } next_desc_addr;
-+} RAID_DESCRIPTOR_T;
-+
-+/******************************************************/
-+/*    the offset of RAID SMC register               */
-+/******************************************************/
-+enum RAID_SMC_REGISTER {
-+      RAID_SMC_CMD_REG                = 0xff60,
-+      RAID_SMC_STATUS_REG             = 0xff64
-+      };
-+
-+/******************************************************/
-+/*    the definition of RAID SMC module register    */
-+/******************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff60
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int pat_mode           : 2; /* partition mode selection */
-+              unsigned int                            : 14;
-+              unsigned int device_id          : 12;
-+              unsigned int revision_id        : 4;
-+              #else
-+              unsigned int revision_id        : 4;
-+              unsigned int device_id          : 12;
-+              unsigned int                            : 14;
-+              unsigned int pat_mode           : 2; /* partition mode selection */
-+              #endif
-+      } bits;
-+} RAID_SMC_CMD;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bits_ff64
-+      {
-+              #ifdef BIG_ENDIAN
-+              unsigned int addr_err1          : 1; /* address is out of range for controller 1 */
-+              unsigned int ahb_err1           : 1; /* AHB bus error for controller 1 */
-+              unsigned int                            : 14;
-+              unsigned int addr_err2          : 1;    /* address is out of range for controller 2 */
-+              unsigned int ahb_err2           : 1; /* AHB bus error for controller 2 */
-+              unsigned int                            : 14;
-+              #else
-+              unsigned int                            : 14;
-+              unsigned int ahb_err2           : 1; /* AHB bus error for controller 2 */
-+              unsigned int addr_err2          : 1;    /* address is out of range for controller 2 */
-+              unsigned int                            : 14;
-+              unsigned int ahb_err1           : 1; /* AHB bus error for controller 1 */
-+              unsigned int addr_err1          : 1; /* address is out of range for controller 1 */
-+              #endif
-+      } bits;
-+} RAID_SMC_STATUS;
-+
-+typedef struct RAID_S
-+{
-+      const char *device_name;
-+      wait_queue_head_t wait;
-+      unsigned int busy;
-+      int irq;
-+      unsigned int status;
-+      RAID_DESCRIPTOR_T *tx_desc;  /*   point to virtual TX descriptor address */
-+      RAID_DESCRIPTOR_T *rx_desc;  /* point ot virtual RX descriptor address */
-+      RAID_DESCRIPTOR_T *tx_cur_desc; /* current TX descriptor */
-+      RAID_DESCRIPTOR_T *rx_cur_desc; /* current RX descriptor */
-+      RAID_DESCRIPTOR_T *tx_finished_desc;
-+      RAID_DESCRIPTOR_T *rx_finished_desc;
-+      RAID_DESCRIPTOR_T *tx_first_desc;
-+      RAID_DESCRIPTOR_T *rx_first_desc;
-+
-+//    unsigned int *tx_buf[TX_DESC_NUM];
-+      unsigned int *rx_desc_dma;                      // physical address of rx_descript
-+      unsigned int *tx_desc_dma;                      // physical address of tx_descript
-+      unsigned int *rx_bufs_dma;
-+      unsigned int *tx_bufs_dma;
-+
-+} RAID_T;
-+
-+struct reg_ioctl
-+{
-+      unsigned int reg_addr;
-+      unsigned int val_in;
-+      unsigned int val_out;
-+};
-+
-+typedef struct dma_ctrl {
-+      int sram;
-+      int prot;
-+      int burst;
-+      int bus;
-+      int endian;
-+      int mode;
-+} DMA_CTRL;
-+
-+
-+#ifdef XOR_SW_FILL_IN
-+
-+#define __XOR(a1, a2) a1 ^= a2
-+
-+#define GET_BLOCK_2(dst) \
-+      __asm__("ldmia  %0, {%1, %2}" \
-+              : "=r" (dst), "=r" (a1), "=r" (a2) \
-+              : "0" (dst))
-+
-+#define GET_BLOCK_4(dst) \
-+      __asm__("ldmia  %0, {%1, %2, %3, %4}" \
-+              : "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \
-+              : "0" (dst))
-+
-+#define XOR_BLOCK_2(src) \
-+      __asm__("ldmia  %0!, {%1, %2}" \
-+              : "=r" (src), "=r" (b1), "=r" (b2) \
-+              : "0" (src)); \
-+      __XOR(a1, b1); __XOR(a2, b2);
-+
-+#define XOR_BLOCK_4(src) \
-+      __asm__("ldmia  %0!, {%1, %2, %3, %4}" \
-+              : "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \
-+              : "0" (src)); \
-+      __XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4)
-+
-+#define PUT_BLOCK_2(dst) \
-+      __asm__ __volatile__("stmia     %0!, {%2, %3}" \
-+              : "=r" (dst) \
-+              : "0" (dst), "r" (a1), "r" (a2))
-+
-+#define PUT_BLOCK_4(dst) \
-+      __asm__ __volatile__("stmia     %0!, {%2, %3, %4, %5}" \
-+              : "=r" (dst) \
-+              : "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4))
-+
-+static void
-+xor_arm4regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
-+{
-+      unsigned int lines = bytes / sizeof(unsigned long) / 4;
-+      register unsigned int a1 __asm__("r4");
-+      register unsigned int a2 __asm__("r5");
-+      register unsigned int a3 __asm__("r6");
-+      register unsigned int a4 __asm__("r7");
-+      register unsigned int b1 __asm__("r8");
-+      register unsigned int b2 __asm__("r9");
-+      register unsigned int b3 __asm__("ip");
-+      register unsigned int b4 __asm__("lr");
-+
-+      do {
-+              GET_BLOCK_4(p1);
-+              XOR_BLOCK_4(p2);
-+              PUT_BLOCK_4(p1);
-+      } while (--lines);
-+}
-+
-+static void
-+xor_arm4regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+              unsigned long *p3)
-+{
-+      unsigned int lines = bytes / sizeof(unsigned long) / 4;
-+      register unsigned int a1 __asm__("r4");
-+      register unsigned int a2 __asm__("r5");
-+      register unsigned int a3 __asm__("r6");
-+      register unsigned int a4 __asm__("r7");
-+      register unsigned int b1 __asm__("r8");
-+      register unsigned int b2 __asm__("r9");
-+      register unsigned int b3 __asm__("ip");
-+      register unsigned int b4 __asm__("lr");
-+
-+      do {
-+              GET_BLOCK_4(p1);
-+              XOR_BLOCK_4(p2);
-+              XOR_BLOCK_4(p3);
-+              PUT_BLOCK_4(p1);
-+      } while (--lines);
-+}
-+
-+static void
-+xor_arm4regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+              unsigned long *p3, unsigned long *p4)
-+{
-+      unsigned int lines = bytes / sizeof(unsigned long) / 2;
-+      register unsigned int a1 __asm__("r8");
-+      register unsigned int a2 __asm__("r9");
-+      register unsigned int b1 __asm__("ip");
-+      register unsigned int b2 __asm__("lr");
-+
-+      do {
-+              GET_BLOCK_2(p1);
-+              XOR_BLOCK_2(p2);
-+              XOR_BLOCK_2(p3);
-+              XOR_BLOCK_2(p4);
-+              PUT_BLOCK_2(p1);
-+      } while (--lines);
-+}
-+
-+static void
-+xor_arm4regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+              unsigned long *p3, unsigned long *p4, unsigned long *p5)
-+{
-+      unsigned int lines = bytes / sizeof(unsigned long) / 2;
-+      register unsigned int a1 __asm__("r8");
-+      register unsigned int a2 __asm__("r9");
-+      register unsigned int b1 __asm__("ip");
-+      register unsigned int b2 __asm__("lr");
-+
-+      do {
-+              GET_BLOCK_2(p1);
-+              XOR_BLOCK_2(p2);
-+              XOR_BLOCK_2(p3);
-+              XOR_BLOCK_2(p4);
-+              XOR_BLOCK_2(p5);
-+              PUT_BLOCK_2(p1);
-+      } while (--lines);
-+}
-+#endif        //XOR_SW_FILL_IN
-+
---- /dev/null
-+++ b/arch/arm/mach-sl2312/irq.c
-@@ -0,0 +1,202 @@
-+/*
-+ *  linux/arch/arm/mach-epxa10db/irq.c
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/stddef.h>
-+#include <linux/list.h>
-+#include <linux/sched.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+#include <asm/mach/irq.h>
-+#include <asm/arch/platform.h>
-+#include <asm/arch/int_ctrl.h>
-+
-+#ifdef CONFIG_PCI
-+#include <asm/arch/pci.h>
-+#endif
-+
-+int fixup_irq(unsigned int irq)
-+{
-+#ifdef CONFIG_PCI
-+      if (irq == IRQ_PCI) {
-+              return sl2312_pci_get_int_src();
-+      }
-+#endif
-+      return irq;
-+}
-+
-+static void sl2312_ack_irq(unsigned int irq)
-+{
-+   __raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+}
-+
-+static void sl2312_mask_irq(unsigned int irq)
-+{
-+      unsigned int mask;
-+
-+#ifdef CONFIG_PCI
-+      if (irq >= PCI_IRQ_OFFSET)
-+      {
-+              mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+              mask &= ~IRQ_PCI_MASK ;
-+              __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+              sl2312_pci_mask_irq(irq - PCI_IRQ_OFFSET);
-+      }
-+      else
-+#endif
-+      if(irq >= FIQ_OFFSET)
-+      {
-+           mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+           mask &= ~(1 << (irq - FIQ_OFFSET));
-+           __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        }
-+        else
-+        {
-+           mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+           mask &= ~(1 << irq);
-+           __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        }
-+
-+}
-+
-+static void sl2312_unmask_irq(unsigned int irq)
-+{
-+      unsigned int mask;
-+
-+#ifdef CONFIG_PCI
-+      if (irq >= PCI_IRQ_OFFSET)
-+      {
-+              mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+              mask |= IRQ_PCI_MASK ;
-+              __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+              sl2312_pci_unmask_irq(irq - PCI_IRQ_OFFSET);
-+      }
-+      else
-+#endif
-+      if(irq >= FIQ_OFFSET)
-+        {
-+          mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+          mask |= (1 << (irq - FIQ_OFFSET));
-+          __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+      }
-+        else
-+        {
-+          mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+          mask |= (1 << irq);
-+          __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        }
-+}
-+
-+static struct irq_chip sl2312_level_irq = {
-+        .ack            = sl2312_mask_irq,
-+        .mask           = sl2312_mask_irq,
-+        .unmask         = sl2312_unmask_irq,
-+//            .set_type       = ixp4xx_set_irq_type,
-+};
-+
-+static struct irq_chip sl2312_edge_irq = {
-+        .ack            = sl2312_ack_irq,
-+        .mask           = sl2312_mask_irq,
-+        .unmask         = sl2312_unmask_irq,
-+//            .set_type       = ixp4xx_set_irq_type,
-+};
-+
-+static struct resource irq_resource = {
-+        .name   = "irq_handler",
-+        .start  = IO_ADDRESS(SL2312_INTERRUPT_BASE),
-+        .end    = IO_ADDRESS(FIQ_STATUS(SL2312_INTERRUPT_BASE))+4,
-+};
-+
-+void __init sl2312_init_irq(void)
-+{
-+      unsigned int i, mode, level;
-+
-+    request_resource(&iomem_resource, &irq_resource);
-+
-+      for (i = 0; i < NR_IRQS; i++)
-+      {
-+          if((i>=IRQ_TIMER1 && i<=IRQ_TIMER3)||(i>=IRQ_SERIRQ0 && i<=IRQ_SERIRQ_MAX))
-+        {
-+              set_irq_chip(i, &sl2312_edge_irq);
-+              set_irq_handler(i, handle_edge_irq);
-+        }
-+          else
-+        {
-+              set_irq_chip(i, &sl2312_level_irq);
-+            set_irq_handler(i,handle_level_irq);
-+        }
-+        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-+      }
-+
-+      /* Disable all interrupt */
-+      __raw_writel(0,IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+      __raw_writel(0,FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+
-+      /* Set interrupt mode */
-+    /* emac & ipsec type is level trigger and high active */
-+    mode = __raw_readl(IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+    level = __raw_readl(IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+
-+      mode &= ~IRQ_GMAC0_MASK;
-+      level &= ~IRQ_GMAC0_MASK;
-+
-+      mode &= ~IRQ_GMAC1_MASK;
-+      level &= ~IRQ_GMAC1_MASK;
-+
-+      mode &= ~IRQ_IPSEC_MASK;
-+      level &= ~IRQ_IPSEC_MASK;
-+
-+      // for IDE0,1, high active and level trigger
-+      mode &= ~IRQ_IDE0_MASK;
-+      level &= ~IRQ_IDE0_MASK;
-+      mode &= ~IRQ_IDE1_MASK;
-+      level &= ~IRQ_IDE1_MASK;
-+
-+
-+      // for PCI, high active and level trigger
-+      mode &= ~IRQ_PCI_MASK;
-+      level &= ~IRQ_PCI_MASK;
-+
-+      // for USB, high active and level trigger
-+      mode &= ~IRQ_USB0_MASK;
-+      level &= ~IRQ_USB0_MASK;
-+
-+      mode &= ~IRQ_USB1_MASK;
-+      level &= ~IRQ_USB1_MASK;
-+
-+      // for LPC, high active and edge trigger
-+      mode |= 0xffff0000;
-+      level &= 0x0000ffff;
-+
-+      // for GPIO, high active and level trigger
-+      mode &= ~(IRQ_GPIO_MASK);
-+      level &= ~(IRQ_GPIO_MASK);
-+
-+      mode &= ~(IRQ_GPIO1_MASK);
-+      level &= ~(IRQ_GPIO1_MASK);
-+
-+      mode &= ~(IRQ_GPIO2_MASK);
-+      level &= ~(IRQ_GPIO2_MASK);
-+
-+      __raw_writel(mode,IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+      __raw_writel(level,IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+
-+}
---- /dev/null
-+++ b/arch/arm/mach-sl2312/lpc.c
-@@ -0,0 +1,125 @@
-+/*
-+ *
-+ * BRIEF MODULE DESCRIPTION
-+ *    ITE Semi IT8712 Super I/O functions.
-+ *
-+ * Copyright 2001 MontaVista Software Inc.
-+ * Author: MontaVista Software, Inc.
-+ *            ppopov@mvista.com or source@mvista.com
-+ *
-+ *  This program is free software; you can redistribute  it and/or modify it
-+ *  under  the terms of  the GNU General  Public License as published by the
-+ *  Free Software Foundation;  either version 2 of the  License, or (at your
-+ *  option) any later version.
-+ *
-+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
-+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
-+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
-+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
-+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
-+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
-+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ *  You should have received a copy of the  GNU General Public License along
-+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
-+ *  675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <asm/io.h>
-+#include <asm/types.h>
-+#include <asm/arch/it8712.h>
-+#include <linux/init.h>
-+#include <asm/arch/hardware.h>
-+
-+#ifndef TRUE
-+#define TRUE 1
-+#endif
-+
-+#ifndef FALSE
-+#define FALSE 0
-+#endif
-+
-+
-+// MB PnP configuration register
-+#define LPC_KEY_ADDR  (IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2e)
-+#define LPC_DATA_ADDR (IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2f)
-+
-+#define LPC_BUS_CTRL                  *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 0)
-+#define LPC_BUS_STATUS                        *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 2)
-+#define LPC_SERIAL_IRQ_CTRL           *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 4)
-+
-+int it8712_exist;
-+
-+static void LPCEnterMBPnP(void)
-+{
-+      int i;
-+      unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
-+
-+      for (i = 0; i<4; i++)
-+              outb(key[i], LPC_KEY_ADDR);
-+
-+}
-+
-+static void LPCExitMBPnP(void)
-+{
-+      outb(0x02, LPC_KEY_ADDR);
-+      outb(0x02, LPC_DATA_ADDR);
-+}
-+
-+void LPCSetConfig(char LdnNumber, char Index, char data)
-+{
-+      LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
-+      outb(0x07, LPC_KEY_ADDR);
-+      outb(LdnNumber, LPC_DATA_ADDR);
-+      outb(Index, LPC_KEY_ADDR);
-+      outb(data, LPC_DATA_ADDR);
-+      LPCExitMBPnP();
-+}
-+
-+char LPCGetConfig(char LdnNumber, char Index)
-+{
-+      char rtn;
-+
-+      LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
-+      outb(0x07, LPC_KEY_ADDR);
-+      outb(LdnNumber, LPC_DATA_ADDR);
-+      outb(Index, LPC_KEY_ADDR);
-+      rtn = inb(LPC_DATA_ADDR);
-+      LPCExitMBPnP();
-+      return rtn;
-+}
-+
-+static int SearchIT8712(void)
-+{
-+      unsigned char Id1, Id2;
-+      unsigned short Id;
-+
-+      LPCEnterMBPnP();
-+      outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */
-+      Id1 = inb(LPC_DATA_ADDR);
-+      outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */
-+      Id2 = inb(LPC_DATA_ADDR);
-+      Id = (Id1 << 8) | Id2;
-+      LPCExitMBPnP();
-+      if (Id == 0x8712)
-+              return TRUE;
-+      else
-+              return FALSE;
-+}
-+
-+int InitLPCInterface(void)
-+{
-+      LPC_BUS_CTRL = 0xc0;
-+      LPC_SERIAL_IRQ_CTRL = 0xc0;
-+      mdelay(1);              // wait for 1 serial IRQ cycle
-+      LPC_SERIAL_IRQ_CTRL = 0x80;
-+      it8712_exist = SearchIT8712();
-+      printk("IT8712 %s exist\n", it8712_exist?"":"doesn't");
-+      return 0;
-+}
-+
-+//__initcall(InitLPCInterface);
---- /dev/null
-+++ b/arch/arm/mach-sl2312/mm.c
-@@ -0,0 +1,80 @@
-+/*
-+ *  linux/arch/arm/mach-epxa10db/mm.c
-+ *
-+ *  MM routines for Altera'a Epxa10db board
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include <linux/sched.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/pgtable.h>
-+#include <asm/page.h>
-+#include <asm/sizes.h>
-+
-+#include <asm/mach/map.h>
-+
-+/* Page table mapping for I/O region */
-+static struct map_desc sl2312_io_desc[] __initdata = {
-+#ifdef CONFIG_GEMINI_IPI
-+{__phys_to_virt(CPU_1_MEM_BASE),         __phys_to_pfn(CPU_1_MEM_BASE),        SZ_64M,  MT_MEMORY},
-+#endif
-+{IO_ADDRESS(SL2312_SRAM_BASE),         __phys_to_pfn(SL2312_SRAM_BASE),        SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_DRAM_CTRL_BASE),    __phys_to_pfn(SL2312_DRAM_CTRL_BASE),   SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_GLOBAL_BASE),       __phys_to_pfn(SL2312_GLOBAL_BASE),      SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_WAQTCHDOG_BASE),    __phys_to_pfn(SL2312_WAQTCHDOG_BASE),   SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_UART_BASE),         __phys_to_pfn(SL2312_UART_BASE),        SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_TIMER_BASE),        __phys_to_pfn(SL2312_TIMER_BASE),       SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_LCD_BASE),          __phys_to_pfn(SL2312_LCD_BASE),         SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_RTC_BASE),          __phys_to_pfn(SL2312_RTC_BASE),         SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_SATA_BASE),         __phys_to_pfn(SL2312_SATA_BASE),        SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_LPC_HOST_BASE),     __phys_to_pfn(SL2312_LPC_HOST_BASE),    SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_LPC_IO_BASE),       __phys_to_pfn(SL2312_LPC_IO_BASE),      SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_INTERRUPT_BASE),    __phys_to_pfn(SL2312_INTERRUPT_BASE),   SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_INTERRUPT1_BASE),   __phys_to_pfn(SL2312_INTERRUPT1_BASE),  SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_SSP_CTRL_BASE),     __phys_to_pfn(SL2312_SSP_CTRL_BASE),    SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_POWER_CTRL_BASE),   __phys_to_pfn(SL2312_POWER_CTRL_BASE),  SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_CIR_BASE),          __phys_to_pfn(SL2312_CIR_BASE),         SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_GPIO_BASE),         __phys_to_pfn(SL2312_GPIO_BASE),        SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_GPIO_BASE1),        __phys_to_pfn(SL2312_GPIO_BASE1),       SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_GPIO_BASE2),        __phys_to_pfn(SL2312_GPIO_BASE2),       SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_PCI_IO_BASE),         __phys_to_pfn(SL2312_PCI_IO_BASE),      SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_PCI_MEM_BASE),        __phys_to_pfn(SL2312_PCI_MEM_BASE),     SZ_512K,  MT_DEVICE},
-+#ifdef CONFIG_NET_SL351X
-+{IO_ADDRESS(SL2312_TOE_BASE),         __phys_to_pfn(SL2312_TOE_BASE)       ,   SZ_512K,  MT_DEVICE},
-+#endif
-+{IO_ADDRESS(SL2312_GMAC0_BASE),              __phys_to_pfn(SL2312_GMAC0_BASE),           SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_GMAC1_BASE),              __phys_to_pfn(SL2312_GMAC1_BASE),           SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_SECURITY_BASE),     __phys_to_pfn(SL2312_SECURITY_BASE),    SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_IDE0_BASE),         __phys_to_pfn(SL2312_IDE0_BASE),        SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_IDE1_BASE),         __phys_to_pfn(SL2312_IDE1_BASE),        SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_RAID_BASE),         __phys_to_pfn(SL2312_RAID_BASE),        SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_FLASH_CTRL_BASE),   __phys_to_pfn(SL2312_FLASH_CTRL_BASE),  SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_DRAM_CTRL_BASE),    __phys_to_pfn(SL2312_DRAM_CTRL_BASE),   SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_GENERAL_DMA_BASE),  __phys_to_pfn(SL2312_GENERAL_DMA_BASE), SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_USB0_BASE),         __phys_to_pfn(SL2312_USB_BASE),         SZ_512K,  MT_DEVICE},
-+{IO_ADDRESS(SL2312_USB1_BASE),         __phys_to_pfn(SL2312_USB1_BASE),        SZ_512K,  MT_DEVICE},
-+{FLASH_VADDR(SL2312_FLASH_BASE),       __phys_to_pfn(SL2312_FLASH_BASE),       SZ_16M,    MT_DEVICE},
-+};
-+
-+void __init sl2312_map_io(void)
-+{
-+      iotable_init(sl2312_io_desc, ARRAY_SIZE(sl2312_io_desc));
-+}
---- /dev/null
-+++ b/arch/arm/mach-sl2312/pci.c
-@@ -0,0 +1,359 @@
-+/*
-+ *  linux/arch/arm/mach-sl2312/pci_sl2312.c
-+ *
-+ *  PCI functions for sl2312 host PCI bridge
-+ *
-+ *  Copyright (C) 2003 StorLink Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include <linux/sched.h>
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/ptrace.h>
-+#include <linux/slab.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/spinlock.h>
-+#include <linux/init.h>
-+
-+#include <asm/sizes.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+#include <asm/mach/pci.h>
-+#include <asm/mach/irq.h>
-+#include <asm/mach-types.h>
-+
-+#include <asm/arch/pci.h>
-+
-+//#define DEBUG
-+
-+// sl2312 PCI bridge access routines
-+
-+#define PCI_IOSIZE_REG        (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE)))
-+#define PCI_PROT_REG  (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x04))
-+#define PCI_CTRL_REG  (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x08))
-+#define PCI_SOFTRST_REG       (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x10))
-+#define PCI_CONFIG_REG        (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x28))
-+#define PCI_DATA_REG  (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x2C))
-+
-+static spinlock_t sl2312_pci_lock = SPIN_LOCK_UNLOCKED;
-+// for initialize PCI devices
-+struct resource pci_ioport_resource = {
-+              .name = "PCI I/O Space",
-+              .start = IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x100,
-+              .end = IO_ADDRESS(SL2312_PCI_IO_BASE) + SZ_512K - 1,
-+              .flags = IORESOURCE_IO,
-+};
-+struct resource pci_iomem_resource = {
-+              .name = "PCI Mem Space",
-+              .start = SL2312_PCI_MEM_BASE,
-+              .end = SL2312_PCI_MEM_BASE + SZ_128M - 1,
-+              .flags = IORESOURCE_MEM,
-+};
-+
-+static int sl2312_read_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 *val)
-+{
-+      unsigned long addr,data;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&sl2312_pci_lock, flags);
-+    addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3);
-+      PCI_CONFIG_REG = addr;
-+      data = PCI_DATA_REG;
-+
-+      switch (size) {
-+      case 1:
-+          *val = (u8) (data >> ((where & 0x03) * 8));
-+              break;
-+      case 2:
-+          *val = (u16) (data >> ((where & 0x02) * 8));
-+              break;
-+      case 4:
-+          *val = data;
-+      if ((where >= 0x10) && (where <= 0x24)) {
-+              if ((*val & 0xfff00000) == SL2312_PCI_IO_BASE) {
-+                      *val &= 0x000fffff;
-+                      *val |= IO_ADDRESS(SL2312_PCI_IO_BASE);
-+              }
-+      }
-+              break;
-+      }
-+      spin_unlock_irqrestore(&sl2312_pci_lock, flags);
-+//    printk("READ==>slot=%d fn=%d where=%d value=%x\n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,*val);
-+      return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int sl2312_write_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 val)
-+{
-+      unsigned long addr,data;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&sl2312_pci_lock, flags);
-+    addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3);
-+      PCI_CONFIG_REG = addr;
-+      data = PCI_DATA_REG;
-+
-+      switch (size) {
-+      case 1:
-+      data &= ~(0xff << ((where & 0x03) * 8));
-+      data |= (val << ((where & 0x03) * 8));
-+      PCI_DATA_REG = data;
-+              break;
-+      case 2:
-+      data &= ~(0xffff << ((where & 0x02) * 8));
-+      data |= (val << ((where & 0x02) * 8));
-+      PCI_DATA_REG = data;
-+              break;
-+      case 4:
-+      if ((where >= 0x10) && (where <= 0x24)) {
-+              if ((val & 0xfff00000) == IO_ADDRESS(SL2312_PCI_IO_BASE)) {
-+                      val &= 0x000fffff;
-+                      val |= SL2312_PCI_IO_BASE;
-+              }
-+      }
-+          PCI_DATA_REG = val;
-+              break;
-+      }
-+      spin_unlock_irqrestore(&sl2312_pci_lock, flags);
-+
-+//    printk("WRITE==> slot=%d fn=%d where=%d value=%x \n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,val);
-+      return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static struct pci_ops sl2312_pci_ops = {
-+      .read   = sl2312_read_config,
-+      .write  = sl2312_write_config,
-+};
-+
-+
-+int __init sl2312_pci_setup_resources(struct resource **resource)
-+{
-+      PCI_IOSIZE_REG = 0;             // 1M IO size
-+      PCI_CTRL_REG = 0x06;
-+
-+      resource[0] = &pci_ioport_resource;
-+      resource[1] = &pci_iomem_resource;
-+      resource[2] = NULL;
-+
-+      return 1;
-+}
-+
-+//static int sl2312_pci_fault(unsigned long addr, struct pt_regs *regs)
-+//{
-+//    return 1;
-+//}
-+
-+
-+/**********************************************************************
-+ * MASK(disable) PCI interrupt
-+ *    0: PCI INTA, 1: PCI INTB, ...           // for Linux interrupt routing
-+ *   16: PERR                                                         // for PCI module internal use
-+ *   17: SERR,.. respect to PCI CTRL2 REG
-+ **********************************************************************/
-+void sl2312_pci_mask_irq(unsigned int irq)
-+{
-+    struct pci_bus bus;
-+      unsigned int tmp;
-+
-+    bus.number = 0;
-+    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
-+      if (irq < 16) {                                         // for linux int routing
-+              tmp &= ~(1 << (irq + 16 + 6));
-+      }
-+      else {
-+              tmp &= ~(1 << irq);
-+      }
-+    sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
-+}
-+
-+/* UNMASK(enable) PCI interrupt */
-+void sl2312_pci_unmask_irq(unsigned int irq)
-+{
-+    struct pci_bus bus;
-+      unsigned int tmp;
-+
-+    bus.number = 0;
-+    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
-+      if (irq < 16) {                                         // for linux int routing
-+              tmp |= (1 << (irq + 16 + 6));
-+      }
-+      else {
-+              tmp |= (1 << irq);
-+      }
-+    sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
-+}
-+
-+/* Get PCI interrupt source */
-+int sl2312_pci_get_int_src(void)
-+{
-+    struct pci_bus bus;
-+      unsigned int tmp=0;
-+
-+    bus.number = 0;
-+    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
-+      if (tmp & (1 << 28)) {          // PCI INTA
-+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
-+              return IRQ_PCI_INTA;
-+      }
-+      if (tmp & (1 << 29)) {          // PCI INTB
-+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
-+              return IRQ_PCI_INTB;
-+      }
-+      if (tmp & (1 << 30)) {          // PCI INTC
-+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
-+              return IRQ_PCI_INTC;
-+      }
-+      if (tmp & (1 << 31)) {          // PCI INTD
-+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
-+              return IRQ_PCI_INTD;
-+      }
-+      // otherwise, it should be a PCI error
-+      return IRQ_PCI;
-+}
-+
-+static irqreturn_t sl2312_pci_irq(int irq, void *devid)
-+{
-+    struct irq_desc *desc;
-+      struct irqaction *action;
-+      int retval = 0;
-+
-+    return 1;
-+
-+      irq = sl2312_pci_get_int_src();
-+      desc = &irq_desc[irq];
-+      action = desc->action;
-+      do {
-+              retval |= action->handler(irq, devid);
-+              action = action->next;
-+      } while (action);
-+
-+    return 1;
-+}
-+
-+//extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
-+
-+void __init sl2312_pci_preinit(void)
-+{
-+    struct pci_bus bus;
-+      unsigned long flags;
-+      unsigned int temp;
-+      int ret;
-+
-+      /*
-+       * Hook in our fault handler for PCI errors
-+       */
-+//    external_fault = sl2312_pci_fault;
-+
-+      spin_lock_irqsave(&sl2312_pci_lock, flags);
-+
-+      /*
-+       * Grab the PCI interrupt.
-+       */
-+      ret = request_irq(IRQ_PCI, sl2312_pci_irq, 0, "sl2312 pci int", NULL);
-+      if (ret)
-+              printk(KERN_ERR "PCI: unable to grab PCI error "
-+                     "interrupt: %d\n", ret);
-+
-+      spin_unlock_irqrestore(&sl2312_pci_lock, flags);
-+
-+      // setup pci bridge
-+    bus.number = 0;   /* device 0, function 0 */
-+      temp = (SL2312_PCI_DMA_MEM1_BASE & 0xfff00000) | (SL2312_PCI_DMA_MEM1_SIZE << 16);
-+    sl2312_write_config(&bus, 0, SL2312_PCI_MEM1_BASE_SIZE, 4, temp);
-+}
-+
-+/*
-+ *    No swizzle on SL2312
-+ */
-+static u8 __init sl2312_pci_swizzle(struct pci_dev *dev, u8 *pinp)
-+{
-+      return PCI_SLOT(dev->devfn);
-+}
-+
-+/*
-+ * map the specified device/slot/pin to an IRQ.  This works out such
-+ * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1.
-+ */
-+static int __init sl2312_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+      int intnr = ((slot  + (pin - 1)) & 3) + 4;  /* the IRQ number of PCI bridge */
-+
-+      // printk("%s : slot = %d  pin = %d \n",__func__,slot,pin);
-+    switch (slot)
-+    {
-+        case 12:
-+              if (pin==1)
-+              {
-+                      intnr = 3;
-+                  }
-+                  else
-+                  {
-+                      intnr = 0;
-+                  }
-+            break;
-+        case 11:
-+                  intnr = (2 + (pin - 1)) & 3;
-+            break;
-+        case 10:
-+                  intnr = (1 + (pin - 1)) & 3;
-+            break;
-+        case  9:
-+                  intnr = (pin - 1) & 3;
-+            break;
-+    }
-+//    if (slot == 10)
-+//            intnr = (1 + (pin - 1)) & 3;
-+//    else if (slot == 9)
-+//            intnr = (pin - 1) & 3;
-+      return (IRQ_PCI_INTA + intnr);
-+}
-+
-+struct pci_bus * __init sl2312_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
-+{
-+      return (pci_scan_bus(0, &sl2312_pci_ops, sysdata));
-+
-+}
-+
-+int __init sl2312_pci_setup(int nr, struct pci_sys_data *sys)
-+{
-+      int ret = 0;
-+
-+      if (nr == 0) {
-+              ret = sl2312_pci_setup_resources(sys->resource);
-+      }
-+
-+      return ret;
-+}
-+
-+
-+struct hw_pci sl2312_pci __initdata = {
-+      .setup          =       sl2312_pci_setup,
-+      .preinit                =       sl2312_pci_preinit,
-+      .nr_controllers =   1,
-+      .swizzle                =       sl2312_pci_swizzle,
-+      .map_irq                =       sl2312_pci_map_irq,
-+      .scan           =   sl2312_pci_scan_bus,
-+};
-+
-+static int __init sl2312_pci_init(void)
-+{
-+      if (machine_is_sl2312())
-+              pci_common_init(&sl2312_pci);
-+      return 0;
-+}
-+
-+subsys_initcall(sl2312_pci_init);
---- /dev/null
-+++ b/arch/arm/mach-sl2312/sl2312-otg-1.c
-@@ -0,0 +1,64 @@
-+/*
-+ *  linux/arch/arm/mach-pxa/sl2312.c
-+ *
-+ *  Author:   Nicolas Pitre
-+ *  Created:  Nov 05, 2002
-+ *  Copyright:        MontaVista Software Inc.
-+ *
-+ * Code specific to sl2312 aka Bulverde.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/device.h>
-+#include "asm/arch/sl2312.h"
-+#include "asm/arch/irqs.h"
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/platform_device.h>
-+
-+/*
-+ * device registration specific to sl2312.
-+ */
-+
-+static u64 sl2312_dmamask_1 = 0xffffffffUL;
-+
-+static struct resource sl2312_otg_resources_1[] = {
-+      [0] = {
-+              .start  = 0x69000000,
-+              .end    = 0x69000fff,
-+              .flags  = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start  = IRQ_USB1,
-+              .end    = IRQ_USB1,
-+              .flags  = IORESOURCE_IRQ,
-+      },
-+};
-+
-+static struct platform_device ehci_1_device = {
-+      .name           = "ehci-hcd-FOTG2XX",
-+      .id             = -1,
-+      .dev            = {
-+              .dma_mask = &sl2312_dmamask_1,
-+              .coherent_dma_mask = 0xffffffff,
-+      },
-+      .num_resources  = ARRAY_SIZE(sl2312_otg_resources_1),
-+      .resource       = sl2312_otg_resources_1,
-+};
-+
-+static struct platform_device *devices[] __initdata = {
-+      &ehci_1_device,
-+};
-+
-+static int __init sl2312_1_init(void)
-+{
-+      return platform_add_devices(devices, ARRAY_SIZE(devices));
-+}
-+
-+subsys_initcall(sl2312_1_init);
---- /dev/null
-+++ b/arch/arm/mach-sl2312/sl2312-otg.c
-@@ -0,0 +1,87 @@
-+/*
-+ *  linux/arch/arm/mach-pxa/sl2312.c
-+ *
-+ *  Author:   Nicolas Pitre
-+ *  Created:  Nov 05, 2002
-+ *  Copyright:        MontaVista Software Inc.
-+ *
-+ * Code specific to sl2312 aka Bulverde.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/device.h>
-+#include "asm/arch/sl2312.h"
-+#include "asm/arch/irqs.h"
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/platform_device.h>
-+
-+/*
-+ * device registration specific to sl2312.
-+ */
-+
-+static u64 sl2312_dmamask = 0xffffffffUL;
-+
-+static struct resource sl2312_otg_resources_1[] = {
-+      [0] = {
-+              .start  = 0x68000000,
-+              .end    = 0x68000fff,
-+              .flags  = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start  = IRQ_USB0,
-+              .end    = IRQ_USB0,
-+              .flags  = IORESOURCE_IRQ,
-+      },
-+};
-+static struct resource sl2312_otg_resources_2[] = {
-+      [2] = {
-+              .start  = 0x69000000,
-+              .end    = 0x69000fff,
-+              .flags  = IORESOURCE_MEM,
-+      },
-+      [3] = {
-+              .start  = IRQ_USB1,
-+              .end    = IRQ_USB1,
-+              .flags  = IORESOURCE_IRQ,
-+      },
-+};
-+
-+static struct platform_device ehci_device_1 = {
-+      .name           = "ehci-hcd-FOTG2XX",
-+      .id             = 1,
-+      .dev            = {
-+              .dma_mask = &sl2312_dmamask,
-+              .coherent_dma_mask = 0xffffffff,
-+      },
-+      .num_resources  = ARRAY_SIZE(sl2312_otg_resources_1),
-+      .resource       = sl2312_otg_resources_1,
-+};
-+
-+static struct platform_device ehci_device_2 = {
-+      .name           = "ehci-hcd-FOTG2XX",
-+      .id             = 2,
-+      .dev            = {
-+              .dma_mask = &sl2312_dmamask,
-+              .coherent_dma_mask = 0xffffffff,
-+      },
-+      .num_resources  = ARRAY_SIZE(sl2312_otg_resources_2),
-+      .resource       = sl2312_otg_resources_2,
-+};
-+
-+static struct platform_device *devices[] __initdata = {
-+      &ehci_device_1, /* &ehci_device_2, */
-+};
-+
-+static int __init sl2312_init(void)
-+{
-+      return platform_add_devices(devices, ARRAY_SIZE(devices));
-+}
-+
-+subsys_initcall(sl2312_init);
---- /dev/null
-+++ b/arch/arm/mach-sl2312/sl3516_device.c
-@@ -0,0 +1,89 @@
-+/*
-+ *  linux/arch/arm/mach-2312/sl3516_device.c
-+ *
-+ *  Author:   Nicolas Pitre
-+ *  Created:  Nov 05, 2002
-+ *  Copyright:        MontaVista Software Inc.
-+ *
-+ * Code specific to sl2312 aka Bulverde.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
-+#include "asm/arch/sl2312.h"
-+#include "asm/arch/irqs.h"
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+/*
-+ * device registration specific to sl2312.
-+ */
-+
-+static u64 sl3516_dmamask = 0xffffffffUL;
-+
-+static struct resource sl3516_sata_resources[] = {
-+      [0] = {
-+              .start  = 0x63400000,
-+              .end    = 0x63400040,
-+              .flags  = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start  = IRQ_IDE1,
-+              .end    = IRQ_IDE1,
-+              .flags  = IORESOURCE_IRQ,
-+      },
-+};
-+
-+static struct platform_device sata_device = {
-+      .name           = "lepus-sata",
-+      .id             = -1,
-+      .dev            = {
-+              .dma_mask = &sl3516_dmamask,
-+              .coherent_dma_mask = 0xffffffff,
-+      },
-+      .num_resources  = ARRAY_SIZE(sl3516_sata_resources),
-+      .resource       = sl3516_sata_resources,
-+};
-+
-+static struct resource sl3516_sata0_resources[] = {
-+      [0] = {
-+              .start  = 0x63000000,
-+              .end    = 0x63000040,
-+              .flags  = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start  = IRQ_IDE0,
-+              .end    = IRQ_IDE0,
-+              .flags  = IORESOURCE_IRQ,
-+      },
-+};
-+
-+static struct platform_device sata0_device = {
-+      .name           = "lepus-sata0",
-+      .id             = -1,
-+      .dev            = {
-+              .dma_mask = &sl3516_dmamask,
-+              .coherent_dma_mask = 0xffffffff,
-+      },
-+      .num_resources  = ARRAY_SIZE(sl3516_sata0_resources),
-+      .resource       = sl3516_sata0_resources,
-+};
-+
-+static struct platform_device *sata_devices[] __initdata = {
-+      &sata_device,
-+      &sata0_device,
-+};
-+
-+static int __init sl3516_init(void)
-+{
-+      return platform_add_devices(sata_devices, ARRAY_SIZE(sata_devices));
-+}
-+
-+subsys_initcall(sl3516_init);
---- /dev/null
-+++ b/arch/arm/mach-sl2312/time.c
-@@ -0,0 +1,134 @@
-+/*
-+ *  linux/include/asm-arm/arch-epxa10db/time.h
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <asm/io.h>
-+#include <asm/system.h>
-+#include <asm/leds.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/mach/time.h>
-+#define TIMER_TYPE (volatile unsigned int*)
-+#include <asm/arch/timer.h>
-+// #define FIQ_PLUS     1
-+
-+
-+/*
-+ * IRQ handler for the timer
-+ */
-+static irqreturn_t sl2312_timer_interrupt(int irq, void *dev_id)
-+{
-+//        unsigned int led;
-+      // ...clear the interrupt
-+#ifdef FIQ_PLUS
-+      *((volatile unsigned int *)FIQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
-+#else
-+      *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
-+#endif
-+
-+#if 0
-+        if(!(jiffies % HZ))
-+        {
-+            led = jiffies / HZ;
-+//            printk("ticks %x \n", led);
-+          }
-+      do_leds();
-+      do_timer(regs);
-+      do_profile(regs);
-+#endif
-+    timer_tick();
-+    return IRQ_HANDLED;
-+}
-+
-+static struct irqaction sl2312_timer_irq = {
-+      .name           = "SL2312 Timer Tick",
-+      .flags          = IRQF_DISABLED | IRQF_TIMER,
-+      .handler        = sl2312_timer_interrupt,
-+};
-+
-+unsigned long sl2312_gettimeoffset (void)
-+{
-+    return 0L;
-+}
-+
-+/*
-+ * Set up timer interrupt, and return the current time in seconds.
-+ */
-+void __init sl2312_time_init(void)
-+{
-+      // For clock rate adjusting
-+      unsigned int tick_rate=0;
-+
-+#ifdef CONFIG_SL3516_ASIC
-+      unsigned int clock_rate_base = 130000000;
-+      unsigned int reg_v=0;
-+
-+      //--> Add by jason for clock adjust
-+      reg_v = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_STATUS)));
-+      reg_v >>= 15;
-+      tick_rate = (clock_rate_base + (reg_v & 0x07)*10000000);
-+
-+      //  FPGA use AHB bus tick rate
-+      printk("Bus: %dMHz",tick_rate/1000000);
-+
-+      tick_rate /= 6;                         // APB bus run AHB*(1/6)
-+
-+      switch((reg_v>>3)&3){
-+              case 0: printk("(1/1)\n") ;
-+                                      break;
-+              case 1: printk("(3/2)\n") ;
-+                                      break;
-+              case 2: printk("(24/13)\n") ;
-+                                      break;
-+              case 3: printk("(2/1)\n") ;
-+                                      break;
-+      }
-+      //<--
-+#else
-+      printk("Bus: %dMHz(1/1)\n",CLOCK_TICK_RATE/1000000);            // FPGA use 20MHz
-+      tick_rate = CLOCK_TICK_RATE;
-+#endif
-+
-+
-+      /*
-+       * Make irqs happen for the system timer
-+       */
-+      // initialize timer interrupt
-+      // low active and edge trigger
-+#ifdef FIQ_PLUS
-+      *((volatile unsigned int *)FIQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
-+      *((volatile unsigned int *)FIQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
-+      setup_irq(IRQ_TIMER1, &sl2312_timer_irq);
-+      /* Start the timer */
-+      *TIMER_COUNT(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ);
-+      *TIMER_LOAD(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ);
-+      *TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_1_CR_ENABLE_MSK|TIMER_1_CR_INT_MSK);
-+#else
-+      *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
-+      *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
-+      setup_irq(IRQ_TIMER2, &sl2312_timer_irq);
-+      /* Start the timer */
-+      *TIMER_COUNT(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ);
-+      *TIMER_LOAD(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ);
-+      *TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_2_CR_ENABLE_MSK|TIMER_2_CR_INT_MSK);
-+#endif
-+
-+}
-+
-+
---- /dev/null
-+++ b/arch/arm/mach-sl2312/xor.c
-@@ -0,0 +1,1200 @@
-+/*
-+ * arch/arm/mach-sl2312/xor.c
-+ *
-+ * Support functions for the Gemini Soc. This is
-+ * a HW XOR unit that is specifically designed for use with RAID5
-+ * applications.  This driver provides an interface that is used by
-+ * the Linux RAID stack.
-+ *
-+ * Original Author: Jason Lee<jason@storlink.com.tw>
-+ *
-+ * Contributors:Sanders<sanders@storlink.com.tw>
-+                              Jason Lee<jason@storlink.com.tw>
-+ *
-+ *
-+ * Maintainer: Jason Lee<jason@storlink.com.tw>
-+ *
-+ * Copyright (C) 2005 Storlink Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ * History:   (06/25/2005, DJ) Initial Creation
-+ *
-+ *    Versing 1.0.0   Initial version
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/spinlock.h>
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+#include <linux/wait.h>
-+#include <linux/list.h>
-+#include <linux/pci.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/mm.h>
-+#include <asm/irq.h>
-+#include <asm/delay.h>
-+#include <asm/uaccess.h>
-+#include <asm/cacheflush.h>
-+#include <asm/hardware.h>
-+#include <asm/arch/xor.h>
-+#include <asm/pci.h>
-+#include <linux/version.h>
-+
-+/*
-+ * pick up local definitions
-+ */
-+#define XOR_SW_FILL_IN
-+#include "hw_xor.h"
-+
-+
-+//#define XOR_DEBUG
-+//#define XOR_TEST    1
-+#ifdef XOR_TEST
-+#define TEST_ITERATION 1000
-+#define SPIN_WAIT     1
-+#endif
-+#ifdef XOR_DEBUG
-+#define DPRINTK(s, args...) printk("Gemini XOR: " s "\n", ## args)
-+#define DENTER() DPRINTK("Entered...\n");
-+#define DEXIT() DPRINTK("Exited...\n");
-+#else
-+#define DPRINTK(s, args...)
-+#define DENTER()
-+#define DEXIT()
-+#endif
-+
-+//#define SPIN_WAIT
-+
-+/* globals */
-+static RAID_T tp;
-+static RAID_TXDMA_CTRL_T      txdma_ctrl;
-+RAID_RXDMA_CTRL_T                     rxdma_ctrl;
-+
-+//#ifndef SPIN_WAIT
-+static spinlock_t         raid_lock;
-+//#endif
-+
-+static unsigned int     tx_desc_virtual_base;
-+static unsigned int     rx_desc_virtual_base;
-+RAID_DESCRIPTOR_T     *tx_desc_ptr;
-+RAID_DESCRIPTOR_T     *rx_desc_ptr;
-+
-+/* static prototypes */
-+#define DMA_MALLOC(size,handle)               pci_alloc_consistent(NULL,size,handle)
-+#define DMA_MFREE(mem,size,handle)    pci_free_consistent(NULL,size,mem,handle)
-+
-+static int gemini_xor_init_desc(void);
-+
-+static unsigned int raid_read_reg(unsigned int offset)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(RAID_BASE_ADDR + offset);
-+      return (reg_val);
-+}
-+
-+static void raid_write_reg(unsigned int offset,unsigned int data,unsigned int bit_mask)
-+{
-+      unsigned int reg_val;
-+    unsigned int *addr;
-+
-+      reg_val = ( raid_read_reg(offset) & (~bit_mask) ) | (data & bit_mask);
-+      addr = (unsigned int *)(RAID_BASE_ADDR + offset);
-+    writel(reg_val,addr);
-+      return;
-+}
-+
-+#ifndef SPIN_WAIT
-+__inline__ void xor_queue_descriptor(void)
-+{
-+      unsigned int flags,status=1;
-+
-+      DPRINTK("Going to sleep");
-+
-+      while(status){
-+              yield();
-+              //schedule();
-+              spin_lock_irqsave(&raid_lock,flags);
-+              status = tp.busy;
-+              spin_unlock_irqrestore(&raid_lock, flags);
-+      }
-+//    tp.status = COMPLETE;
-+      DPRINTK("woken up!");
-+
-+}
-+#endif
-+
-+#ifdef SPIN_WAIT
-+static void gemini_xor_isr(int d_n)
-+#else
-+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
-+static void gemini_xor_isr(int irq, void *dev_id, struct pt_regs *regs)
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+static irqreturn_t gemini_xor_isr(int irq, void *dev_instance, struct pt_regs *regs)
-+#endif
-+#endif
-+{
-+
-+      unsigned int err;
-+      RAID_DMA_STATUS_T       dma_status;
-+//    RAID_DESCRIPTOR_T *rdesc,*tdesc;
-+//    unsigned int *paddr;
-+
-+      dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
-+#ifdef SPIN_WAIT
-+      while( (dma_status.bits32& (1<<31) ) ==0 ){
-+              udelay(1);
-+              dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
-+      }
-+
-+/*    tdesc = tp.tx_first_desc;
-+      rdesc = tp.rx_first_desc;
-+      for(d_n;d_n>0;d_n--){
-+              if( tdesc->func_ctrl.bits.own == DMA ){
-+                      paddr = tdesc;
-+                      printk("error tx desc:0x%x\n",*paddr++);
-+                      printk("error tx desc:0x%x\n",*paddr++);
-+                      printk("error tx desc:0s%x\n",*paddr++);
-+                      printk("error tx desc:0x%x\n",*paddr);
-+                      while(1);
-+              }
-+              tdesc = (RAID_DESCRIPTOR_T *)((tdesc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+      }
-+
-+      if( rdesc->func_ctrl.bits.own == DMA ){
-+              paddr = rdesc;
-+              printk("error rx desc:0x%x\n",*paddr++);
-+              printk("error rx desc:0x%x\n",*paddr++);
-+              printk("error rx desc:0s%x\n",*paddr++);
-+              printk("error rx desc:0x%x\n",*paddr);
-+              while(1);
-+      }
-+*/
-+#endif
-+
-+      if(dma_status.bits32 & ((1<<31)|(1<<26))){
-+              // if no bug , we can turn off rx finish interrupt
-+              dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
-+              err = raid_read_reg(RAID_DMA_DEVICE_ID);
-+              tp.busy = 0;
-+
-+              if(err&0x00FF0000){
-+                      tp.status = ERROR;
-+                      printk("XOR:<HW>%s error code %x\n",(err&0x00F00000)?"tx":"rx",err);
-+
-+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
-+                      return ;
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+#ifndef SPIN_WAIT
-+                      return IRQ_RETVAL(IRQ_HANDLED);
-+#endif
-+#endif
-+              }
-+              // 16~19 rx error code
-+              // 20~23 tx error codd
-+
-+              dma_status.bits.tsFinishI = 1;
-+              dma_status.bits.rsFinishI = 1;
-+              raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0x84000000);  // clear INT
-+
-+//            printk("xor %d\n",d_n);
-+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
-+                      return ;
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+#ifndef SPIN_WAIT
-+                      return IRQ_RETVAL(IRQ_HANDLED);
-+#endif
-+#endif
-+      }
-+
-+      #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
-+              return ;
-+      #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+      #ifndef SPIN_WAIT
-+              printk("XOR: DMA status register(0x%8x)\n",dma_status.bits32);
-+              return IRQ_RETVAL(IRQ_HANDLED);
-+      #endif
-+      #endif
-+}
-+
-+void
-+xor_gemini_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
-+{
-+      int status=0;
-+      unsigned int flags;
-+
-+      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
-+              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
-+      }
-+
-+      spin_lock_irqsave(&raid_lock,flags);
-+      while(tp.status != COMPLETE){
-+              spin_unlock_irqrestore(&raid_lock, flags);
-+              //printk("XOR yield2\n");
-+#ifdef XOR_SW_FILL_IN
-+              xor_arm4regs_2(bytes,p1,p2);
-+              return ;
-+#else
-+              yield();
-+#endif
-+      }
-+      spin_unlock_irqrestore(&raid_lock, flags);
-+      tp.status = RUNNING;
-+
-+      // flush the cache to memory before H/W XOR touches them
-+      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
-+      consistent_sync(p2, bytes, DMA_TO_DEVICE);
-+
-+
-+      tp.tx_desc = tp.tx_first_desc;
-+      tp.rx_desc = tp.rx_first_desc;
-+      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
-+              // prepare tx descript
-+              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
-+              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00020000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+              wmb();
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p2);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00010000;
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);                                                  // keep last descript
-+
-+      wmb();
-+      // prepare rx descript
-+      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf);
-+      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
-+      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
-+//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+
-+      }
-+      else{
-+              /* no free tx descriptor */
-+              printk("XOR:no free tx descript");
-+              return ;
-+      }
-+
-+      // change status
-+//    tp.status = RUNNING;
-+      status = tp.busy = 1;
-+
-+      // start tx DMA
-+      rxdma_ctrl.bits.rd_start = 1;
-+      // start rx DMA
-+      txdma_ctrl.bits.td_start = 1;
-+
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
-+      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
-+
-+#ifdef SPIN_WAIT
-+      gemini_xor_isr(2);
-+#else
-+      xor_queue_descriptor();
-+#endif
-+
-+      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*2) ;
-+      tp.status = COMPLETE;
-+//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
-+//    tp.rx_desc = tp.rx_first_desc ;
-+//    tp.rx_desc->func_ctrl.bits.own = DMA;
-+
-+}
-+
-+void
-+xor_gemini_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+              unsigned long *p3)
-+{
-+      int status=0;
-+      unsigned int flags;
-+
-+      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
-+              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
-+      }
-+
-+      spin_lock_irqsave(&raid_lock,flags);
-+      if(tp.status != COMPLETE){
-+              spin_unlock_irqrestore(&raid_lock, flags);
-+              //printk("XOR yield3\n");
-+#ifdef XOR_SW_FILL_IN
-+              xor_arm4regs_3(bytes,p1,p2,p3);
-+              return;
-+#else
-+              yield();
-+#endif
-+      }
-+      spin_unlock_irqrestore(&raid_lock, flags);
-+      tp.status = RUNNING;
-+
-+      // flush the cache to memory before H/W XOR touches them
-+      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
-+      consistent_sync(p2, bytes, DMA_TO_DEVICE);
-+      consistent_sync(p3, bytes, DMA_TO_DEVICE);
-+
-+      tp.tx_desc = tp.tx_first_desc;
-+      tp.rx_desc = tp.rx_first_desc;
-+      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
-+              // prepare tx descript
-+              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
-+              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00020000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p2);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x0000000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p3);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00010000;
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);                                                  // keep last descript
-+
-+      // prepare rx descript
-+      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf);
-+      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
-+      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
-+//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+
-+      }
-+      else{
-+              /* no free tx descriptor */
-+              printk("XOR:no free tx descript \n");
-+              return ;
-+      }
-+
-+      // change status
-+//    tp.status = RUNNING;
-+      status = tp.busy = 1;
-+
-+      // start tx DMA
-+      rxdma_ctrl.bits.rd_start = 1;
-+      // start rx DMA
-+      txdma_ctrl.bits.td_start = 1;
-+      wmb();
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
-+      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
-+
-+#ifdef SPIN_WAIT
-+      gemini_xor_isr(3);
-+#else
-+      xor_queue_descriptor();
-+#endif
-+      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*3) | 0x0B;
-+      tp.status = COMPLETE;
-+//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
-+      //tp.rx_desc = tp.rx_first_desc ;
-+//    tp.rx_desc->func_ctrl.bits.own = DMA;
-+
-+}
-+
-+void
-+xor_gemini_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+              unsigned long *p3, unsigned long *p4)
-+{
-+      int status=0;
-+      unsigned int flags;
-+
-+      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
-+              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
-+      }
-+
-+      spin_lock_irqsave(&raid_lock,flags);
-+      if(tp.status != COMPLETE){
-+              spin_unlock_irqrestore(&raid_lock, flags);
-+              //printk("S\n");
-+#ifdef XOR_SW_FILL_IN
-+              xor_arm4regs_4(bytes,p1,p2,p3,p4);
-+              return;
-+#else
-+              msleep(1);
-+              yield();
-+#endif
-+      }
-+      spin_unlock_irqrestore(&raid_lock, flags);
-+
-+      tp.status = RUNNING;
-+
-+      // flush the cache to memory before H/W XOR touches them
-+      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
-+      consistent_sync(p2, bytes, DMA_TO_DEVICE);
-+      consistent_sync(p3, bytes, DMA_TO_DEVICE);
-+      consistent_sync(p4, bytes, DMA_TO_DEVICE);
-+
-+      tp.tx_desc = tp.tx_first_desc;
-+      tp.rx_desc = tp.rx_first_desc;
-+      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
-+              // prepare tx descript
-+              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
-+              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00020000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_cur_desc->buf_addr = (unsigned int)__pa(p2);              // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00000000;
-+      tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p3);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00000000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p4);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00010000;
-+//            tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);                                                  // keep last descript
-+
-+      // prepare rx descript
-+      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
-+      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
-+      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
-+//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+
-+      }
-+      else{
-+              /* no free tx descriptor */
-+              printk("XOR:no free tx descript");
-+              return ;
-+      }
-+
-+      // change status
-+//    tp.status = RUNNING;
-+      status = tp.busy = 1;
-+
-+      // start tx DMA
-+      rxdma_ctrl.bits.rd_start = 1;
-+      // start rx DMA
-+      txdma_ctrl.bits.td_start = 1;
-+      wmb();
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
-+      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
-+
-+#ifdef SPIN_WAIT
-+      gemini_xor_isr(4);
-+#else
-+      xor_queue_descriptor();
-+#endif
-+
-+      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*4) | 0x0B;
-+      tp.status = COMPLETE;
-+//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
-+      //tp.rx_desc = tp.rx_first_desc ;
-+//    tp.rx_desc->func_ctrl.bits.own = DMA;
-+
-+}
-+
-+void
-+xor_gemini_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+              unsigned long *p3, unsigned long *p4, unsigned long *p5)
-+{
-+
-+      int status=0;
-+      unsigned int flags;
-+
-+
-+      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
-+              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
-+      }
-+
-+      spin_lock_irqsave(&raid_lock,flags);
-+      while(tp.status != COMPLETE){
-+              spin_unlock_irqrestore(&raid_lock, flags);
-+              //printk("XOR yield5\n");
-+#ifdef XOR_SW_FILL_IN
-+              xor_arm4regs_5(bytes,p1,p2,p3,p4,p5);
-+              return;
-+#else
-+              msleep(1);
-+              yield();
-+#endif
-+      }
-+      spin_unlock_irqrestore(&raid_lock, flags);
-+      tp.status = RUNNING;
-+
-+      // flush the cache to memory before H/W XOR touches them
-+      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
-+      consistent_sync(p2, bytes, DMA_TO_DEVICE);
-+      consistent_sync(p3, bytes, DMA_TO_DEVICE);
-+      consistent_sync(p4, bytes, DMA_TO_DEVICE);
-+      consistent_sync(p5, bytes, DMA_TO_DEVICE);
-+
-+      tp.tx_desc = tp.tx_first_desc;
-+      tp.rx_desc = tp.rx_first_desc;
-+      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
-+              // prepare tx descript
-+              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
-+              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00020000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      wmb();
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p2);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00000000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      wmb();
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p3);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00000000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      wmb();
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+              tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p4);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;                 // first descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+              tp.tx_desc->flg_status.bits32 = 0x00000000;
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      wmb();
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+
-+
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc->buf_addr = (unsigned int)__pa(p5);          // pysical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+//            tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;                 // last descript
-+//            tp.tx_desc->flg_status.bits_cmd_status.mode = 0;                // only support XOR command
-+//            tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+              tp.tx_desc->flg_status.bits32 = 0x00010000;
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+      tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
-+      tp.tx_finished_desc = tp.tx_desc;                                                               // keep last descript
-+
-+      // prepare rx descript
-+      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
-+      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
-+      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
-+//            tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+
-+      }
-+      else{
-+              /* no free tx descriptor */
-+              printk("XOR:no free tx descript");
-+              return ;
-+      }
-+
-+      // change status
-+//    tp.status = RUNNING;
-+      status = tp.busy = 1;
-+
-+      // start tx DMA
-+      rxdma_ctrl.bits.rd_start = 1;
-+      // start rx DMA
-+      txdma_ctrl.bits.td_start = 1;
-+      wmb();
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
-+      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
-+
-+#ifdef SPIN_WAIT
-+      gemini_xor_isr(5);
-+#else
-+      xor_queue_descriptor();
-+#endif
-+
-+      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*5) | 0x0B;
-+      tp.status = COMPLETE;
-+//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
-+      //tp.rx_desc = tp.rx_first_desc ;
-+//    tp.rx_desc->func_ctrl.bits.own = DMA;
-+
-+}
-+
-+#ifdef XOR_TEST
-+void
-+raid_memset(unsigned int *p1, unsigned int pattern, unsigned int bytes)
-+{
-+      int status=0,i;
-+
-+      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
-+              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
-+      }
-+
-+      *p1 = pattern;
-+
-+      // flush the cache to memory before H/W XOR touches them
-+      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
-+
-+      while(tp.status != COMPLETE){
-+              DPRINTK("XOR yield\n");
-+              //schedule();
-+              yield();
-+      }
-+      tp.status = RUNNING;
-+
-+      tp.tx_desc = tp.tx_first_desc;
-+      tp.rx_desc = tp.rx_first_desc;
-+      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
-+              // prepare tx descript
-+              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
-+              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = 4;             /* total frame byte count */
-+      tp.tx_desc->flg_status.bits_cmd_status.bcc = bytes;                     // bytes to fill
-+      tp.tx_desc->flg_status.bits_cmd_status.mode = CMD_FILL;         // only support memory FILL command
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
-+//            tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
-+
-+      // prepare rx descript
-+      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
-+      tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
-+      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
-+      tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+//            tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base);
-+      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+      tp.rx_finished_desc = tp.rx_desc;
-+
-+      }
-+      else{
-+              /* no free tx descriptor */
-+              printk("XOR:no free tx descript");
-+              return ;
-+      }
-+
-+      // change status
-+      //tp.status = RUNNING;
-+      status = tp.busy = 1;
-+
-+      // start tx DMA
-+      rxdma_ctrl.bits.rd_start = 1;
-+      // start rx DMA
-+      txdma_ctrl.bits.td_start = 1;
-+
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
-+      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
-+
-+#ifdef SPIN_WAIT
-+      gemini_xor_isr(2);
-+#else
-+      xor_queue_descriptor();
-+#endif
-+
-+      for(i=1; i<(bytes/sizeof(int)); i++) {
-+              if(p1[0]!=p1[i]){
-+                      printk("pattern set error!\n");
-+                      while(1);
-+              }
-+      }
-+
-+      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
-+      tp.status = COMPLETE;
-+//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
-+      //tp.rx_desc = tp.rx_first_desc ;
-+//    tp.rx_desc->func_ctrl.bits.own = DMA;
-+
-+}
-+#endif
-+
-+void
-+raid_memcpy(unsigned int *to, unsigned int *from, unsigned int bytes)
-+{
-+      int status=0,i;
-+
-+      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
-+              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
-+      }
-+
-+      // flush the cache to memory before H/W XOR touches them
-+      consistent_sync(to, bytes, DMA_BIDIRECTIONAL);
-+      consistent_sync(from,bytes, DMA_TO_DEVICE);
-+
-+      while(tp.status != COMPLETE){
-+              DPRINTK("XOR yield\n");
-+              //schedule();
-+              yield();
-+      }
-+      tp.status = RUNNING;
-+
-+      tp.tx_desc = tp.tx_first_desc;
-+      tp.rx_desc = tp.rx_first_desc;
-+      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
-+              // prepare tx descript
-+              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
-+              tp.tx_desc->buf_addr = (unsigned int)__pa(from);                // physical address
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+      tp.tx_desc->flg_status.bits32 = CMD_CPY;                // only support memory FILL command
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
-+//            tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
-+
-+      // prepare rx descript
-+      raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
-+      tp.rx_desc->buf_addr = (unsigned int)__pa(to);
-+      tp.rx_desc->func_ctrl.bits.buffer_size = bytes;                 /* total frame byte count */
-+      tp.rx_desc->flg_status.bits32 = 0;                              // link data from XOR
-+      tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.rx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+//            tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base);
-+      tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
-+
-+      }
-+      else{
-+              /* no free tx descriptor */
-+              printk("XOR:no free tx descript");
-+              return ;
-+      }
-+
-+      // change status
-+      //tp.status = RUNNING;
-+      status = tp.busy = 1;
-+
-+      // start tx DMA
-+      rxdma_ctrl.bits.rd_start = 1;
-+      // start rx DMA
-+      txdma_ctrl.bits.td_start = 1;
-+
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
-+      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
-+
-+#ifdef SPIN_WAIT
-+      gemini_xor_isr(2);
-+#else
-+      xor_queue_descriptor();
-+#endif
-+
-+#ifdef XOR_TEST
-+      for(i=1; i<(bytes/sizeof(int)); i++) {
-+              if(to[i]!=from[i]){
-+                      printk("pattern check error!\n");
-+                      printk("offset=0x%x p1=%x p2=%x\n",i*4,to[i],from[i]);
-+                      while(1);
-+              }
-+      }
-+#endif
-+
-+      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
-+      tp.status = COMPLETE;
-+//    tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
-+      //tp.rx_desc = tp.rx_first_desc ;
-+//    tp.rx_desc->func_ctrl.bits.own = DMA;
-+
-+}
-+EXPORT_SYMBOL(raid_memcpy);
-+
-+#ifdef XOR_TEST
-+int
-+raid_memchk(unsigned int *p1, unsigned int pattern, unsigned int bytes)
-+{
-+      int status=0;
-+      RAID_DMA_STATUS_T       dma_status;
-+
-+      if(bytes > (1<<(SRAM_PAR_SIZE+11))){
-+              printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
-+      }
-+
-+      status = ((pattern&0xFFFF)%bytes )/4;
-+      p1[status] = pattern;
-+
-+      while(tp.status != COMPLETE){
-+              DPRINTK("XOR yield\n");
-+              //schedule();
-+              yield();
-+      }
-+      tp.status = RUNNING;
-+
-+      // flush the cache to memory before H/W XOR touches them
-+      consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
-+
-+      tp.tx_desc = tp.tx_first_desc;
-+      if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
-+              // prepare tx descript
-+              raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
-+              tp.tx_desc->buf_addr = (unsigned int)__pa(p1);          // physical address
-+      tp.tx_desc->func_ctrl.bits.raid_ctrl_status = 0;
-+      tp.tx_desc->func_ctrl.bits.buffer_size = bytes ;                /* total frame byte count */
-+      tp.tx_desc->flg_status.bits32 = CMD_CHK;                // only support memory FILL command
-+      tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
-+      tp.tx_desc->func_ctrl.bits.own = DMA;                           /* set owner bit */
-+      tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
-+//            tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
-+
-+      }
-+      else{
-+              /* no free tx descriptor */
-+              printk("XOR:no free tx descript");
-+              return -1;
-+      }
-+
-+      // change status
-+      //tp.status = RUNNING;
-+      status = tp.busy = 1;
-+
-+      // start tx DMA
-+      txdma_ctrl.bits.td_start = 1;
-+
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
-+//    raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
-+
-+#ifdef SPIN_WAIT
-+      gemini_xor_isr(2);
-+#else
-+      xor_queue_descriptor();
-+#endif
-+
-+//    dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
-+//    if (dma_status.bits32 & (1<<15))        {
-+
-+      if((tp.tx_first_desc->func_ctrl.bits.raid_ctrl_status & 0x2)) {
-+              status = 1;
-+//            raid_write_reg(RAID_DMA_STATUS,0x00008000,0x00080000);
-+      }
-+      else{
-+              status = 0;
-+      }
-+
-+      tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
-+      tp.status = COMPLETE;
-+//    tp.rx_desc->func_ctrl.bits.own = DMA;
-+      return status ;
-+}
-+#endif
-+
-+int __init gemini_xor_init(void)
-+{
-+      unsigned int res;
-+      unsigned int *paddr1,*paddr2,*paddr3,i;
-+      unsigned volatile char  *charact;
-+      unsigned volatile short *two_char;
-+      unsigned volatile int   *four_char;
-+
-+      // init descript
-+      res = gemini_xor_init_desc();
-+      if(res) {
-+              printk("Init RAID Descript Fail!!\n");
-+              return -res;
-+      }
-+
-+      tp.device_name = "Gemini XOR Acceleration";
-+
-+      // request irq
-+#ifndef SPIN_WAIT
-+      res = request_irq(IRQ_RAID, gemini_xor_isr, SA_INTERRUPT, tp.device_name, NULL);
-+#endif
-+      if(res){
-+              printk(KERN_ERR "%s: unable to request IRQ %d for "
-+                     "HW XOR %d\n", tp.device_name, IRQ_RAID, res);
-+              return -EBUSY;
-+      }
-+
-+#ifdef XOR_TEST
-+
-+RETEST:
-+      paddr1 = kmalloc(0x1000,GFP_KERNEL);
-+      paddr2 = kmalloc(0x1000,GFP_KERNEL);
-+      paddr3 = kmalloc(0x1000,GFP_KERNEL);
-+      for(i=0;i<TEST_ITERATION;i++) {
-+              printk("XOR test round %d\n",i);
-+              for(res=0;res<(0x1000)/sizeof(int);res++){              // prepare data pattern
-+                      paddr1[res]= readl(0xf62000ac);
-+                      paddr2[res]= readl(0xf62000ac);
-+              }
-+              for(res=0;res<0x1000/sizeof(int);res++){                // calculate xor by software
-+                      paddr3[res] = paddr1[res]^paddr2[res];
-+              }
-+              xor_gemini_2(0x1000,paddr1,paddr2);                             // calculate xor by hw
-+              for(res=0;res<0x1000/sizeof(int);res++){                // check error
-+                      if(paddr1[res]!=paddr3[res]){
-+                              printk("XOR ERROR\n");
-+                              printk("[%d][0x%x]=0x%x should be %x\n",res,&paddr1[res],paddr1[res],paddr3[res]);
-+                              while(1);
-+                      }
-+              }
-+      }
-+      kfree(paddr1);
-+      kfree(paddr2);
-+      kfree(paddr3);
-+
-+
-+      // memcpy test
-+      paddr1 = kmalloc(0x4000,GFP_KERNEL);
-+      for(i=0;i<TEST_ITERATION;i++) {
-+              for(res=0;res<(0x4000)/sizeof(int);res++)
-+                      paddr1[res]= readl(0xf62000ac);
-+
-+              printk("MEMCOPY round %d\n",i);
-+              paddr2 = kmalloc(0x4000,GFP_KERNEL);
-+              raid_memcpy(paddr2,paddr1,0x4000);
-+              kfree(paddr2);
-+      }
-+      kfree(paddr1);
-+
-+      // memset test
-+      for(i=0;i<TEST_ITERATION;i++) {
-+              raid_memset(paddr1,0xFFFFFFFF,0x4000);
-+              res = readl(0xf62000ac);
-+              printk("MEMFILL fill 0x%x round %d\n",res,i);
-+              paddr1 = kmalloc(0x4000,GFP_KERNEL);
-+              raid_memset(paddr1,res,0x4000);
-+              raid_memset(paddr1,0x0,0x4000);
-+              kfree(paddr1);
-+      }
-+
-+      paddr1 = kmalloc(0x4000,GFP_KERNEL);
-+      for(i=0;i<TEST_ITERATION;i++){
-+              raid_memset(paddr1, i,0x4000);
-+              printk("Pattern check same ? ");
-+              res = raid_memchk(paddr1, i,0x4000);
-+              printk("%s\n",res?"Fail":"OK");
-+              if(res) while(1);
-+
-+              printk("Pattern check diff ? ");
-+              res = raid_memchk(paddr1,readl(0xf62000ac),0x4000);
-+              printk("%s\n",res?"OK":"Fail");
-+              if(!res)        while(1);
-+      }
-+      kfree(paddr1);
-+
-+      // SRAM test
-+      raid_write_reg(RAID_PCR, 0,0x00000003);
-+      for(i=0;i<TEST_ITERATION;i++) {
-+              printk("SRAM test %d\n",i);
-+              charact = 0xF7000000;
-+              two_char = 0xF7000000;
-+              four_char = 0xF7000000;
-+              for(res=0;res<(16*1024)/sizeof(char);res++) {           // 8-bit access
-+                      *charact++ = (unsigned char)res;
-+              }
-+              charact = 0xF7000000;
-+              for(res=0;res<(16*1024)/sizeof(char);res++) {
-+                      if(*charact++ != (unsigned char)res){
-+                              printk("SRAM data error(8)\n");
-+                              while(1);
-+                      }
-+              }
-+
-+              for(res=0;res<(16*1024)/sizeof(short);res++) {          // 16-bit access
-+                      *two_char++ = (unsigned short)res;
-+              }
-+              two_char = 0xF7000000;
-+              for(res=0;res<(16*1024)/sizeof(short);res++) {
-+                      if(*two_char++ != (unsigned short)res){
-+                              printk("SRAM data error(16)\n");
-+                              while(1);
-+                      }
-+              }
-+
-+              for(res=0;res<(16*1024)/sizeof(int);res++) {            // 32-bit access
-+                      *four_char++ = (unsigned int)res;
-+              }
-+              four_char = 0xF7000000;
-+              for(res=0;res<(16*1024)/sizeof(int);res++) {
-+                      if(*four_char++ != (unsigned int)res){
-+                              printk("SRAM data error(32)\n");
-+                              while(1);
-+                      }
-+              }
-+      }
-+      raid_write_reg(RAID_PCR, SRAM_PAR_SIZE,0x00000003);
-+
-+#endif
-+      return 0;
-+}
-+
-+void __exit gemini_xor_exit(void)
-+{
-+      DMA_MFREE(tp.tx_desc, TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(unsigned int)tp.tx_desc_dma);
-+      DMA_MFREE(tp.rx_desc, RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(unsigned int)tp.rx_desc_dma);
-+      free_irq(IRQ_RAID, NULL);
-+}
-+
-+
-+static int gemini_xor_init_desc(void)
-+{
-+      unsigned int i;
-+      dma_addr_t          tx_first_desc_dma;
-+      dma_addr_t          rx_first_desc_dma;
-+      RAID_DMA_STATUS_T       dma_status;
-+
-+      printk("Initial RAID Descripter...\n");
-+
-+      tp.tx_desc = (RAID_DESCRIPTOR_T*)DMA_MALLOC(TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t *)&tp.tx_desc_dma);
-+    tx_desc_virtual_base = (unsigned int)tp.tx_desc - (unsigned int)tp.tx_desc_dma;
-+    memset(tp.tx_desc,0x00,TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T));
-+
-+      tp.rx_desc = (RAID_DESCRIPTOR_T*)DMA_MALLOC(RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t *)&tp.rx_desc_dma);
-+    rx_desc_virtual_base = (unsigned int)tp.rx_desc - (unsigned int)tp.rx_desc_dma;
-+    memset(tp.rx_desc,0x00,RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T));
-+      printk("XOR:tx_desc = %08x\n",(unsigned int)tp.tx_desc);
-+    printk("XOR:rx_desc = %08x\n",(unsigned int)tp.rx_desc);
-+      printk("XOR:tx_desc_dma = %08x\n",(unsigned int)tp.tx_desc_dma);
-+      printk("XOR:rx_desc_dma = %08x\n",(unsigned int)tp.rx_desc_dma);
-+
-+      if ((tp.tx_desc == NULL) || (tp.rx_desc == NULL)) {
-+              if (tp.tx_desc)
-+                      DMA_MFREE(tp.tx_desc, TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t)tp.tx_desc_dma);
-+              if (tp.rx_desc)
-+                      DMA_MFREE(tp.rx_desc, RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t)tp.rx_desc_dma);
-+              return -ENOMEM;
-+      }
-+
-+      tp.tx_cur_desc = tp.tx_desc;  /* virtual address */
-+      tp.tx_finished_desc = tp.tx_desc; /* virtual address */
-+      tx_first_desc_dma = (dma_addr_t)tp.tx_desc_dma; /* physical address */
-+      for (i = 1; i < TX_DESC_NUM; i++) {
-+              tp.tx_desc->func_ctrl.bits.own = CPU;
-+              tp.tx_desc->func_ctrl.bits.buffer_size = 0;
-+              tp.tx_desc_dma = tp.tx_desc_dma + sizeof(RAID_DESCRIPTOR_T);
-+//            tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tp.tx_desc_dma | 0x0B;
-+              tp.tx_desc->next_desc_addr.bits32 = ((unsigned int)tx_first_desc_dma | 0x0B) + i*0x10;
-+              tp.tx_desc = &tp.tx_desc[1];
-+      }
-+      tp.tx_desc->func_ctrl.bits.own = DMA;
-+      tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tx_first_desc_dma|0x0b;
-+      tp.tx_desc = tp.tx_cur_desc;
-+      tp.tx_desc_dma = (unsigned int*)tx_first_desc_dma;
-+      tp.tx_first_desc = tp.tx_desc ;
-+
-+      tp.rx_cur_desc = tp.rx_desc;  /* virtual address */
-+      tp.rx_finished_desc = tp.rx_desc; /* virtual address */
-+      rx_first_desc_dma = (dma_addr_t)tp.rx_desc_dma; /* physical address */
-+      for (i = 1; i < RX_DESC_NUM; i++) {
-+              tp.rx_desc->func_ctrl.bits.own = DMA;
-+              tp.rx_desc->func_ctrl.bits.buffer_size = 0;
-+              tp.rx_desc_dma = tp.rx_desc_dma + sizeof(RAID_DESCRIPTOR_T);
-+//            tp.rx_desc->next_desc_addr.bits32 = (unsigned int)tp.rx_desc_dma | 0x0B;
-+              tp.rx_desc->next_desc_addr.bits32 = ((unsigned int)rx_first_desc_dma | 0x0B) + i*0x10;
-+              tp.rx_desc = &tp.rx_desc[1];
-+      }
-+      tp.rx_desc->func_ctrl.bits.own = DMA;
-+      tp.rx_desc->next_desc_addr.bits32 = rx_first_desc_dma|0x0b;
-+      tp.rx_desc = tp.rx_cur_desc;
-+      tp.rx_desc_dma = (unsigned int*)rx_first_desc_dma;
-+      tp.rx_first_desc = tp.rx_desc ;
-+      tp.busy = 0;
-+      tp.status = COMPLETE;
-+
-+      // Partition SRAM size
-+      raid_write_reg(RAID_PCR, SRAM_PAR_SIZE,0x00000003);
-+
-+      // config tx DMA controler
-+      txdma_ctrl.bits32 = 0;
-+      txdma_ctrl.bits.td_start = 0;
-+      txdma_ctrl.bits.td_continue = 1;
-+      txdma_ctrl.bits.td_chain_mode = 1;
-+      txdma_ctrl.bits.td_prot = 0;
-+      txdma_ctrl.bits.td_burst_size = 1;
-+      txdma_ctrl.bits.td_bus = 3;
-+      txdma_ctrl.bits.td_endian = 0;
-+      txdma_ctrl.bits.td_finish_en = 1;
-+      txdma_ctrl.bits.td_fail_en = 1;
-+      txdma_ctrl.bits.td_perr_en = 1;
-+      txdma_ctrl.bits.td_eod_en = 0;  // enable tx descript
-+      txdma_ctrl.bits.td_eof_en = 0;
-+      raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0xFFFFFFFF);
-+
-+      // config rx DMA controler
-+      rxdma_ctrl.bits32 = 0;
-+      rxdma_ctrl.bits.rd_start = 0;
-+      rxdma_ctrl.bits.rd_continue = 1;
-+      rxdma_ctrl.bits.rd_chain_mode = 1;
-+      rxdma_ctrl.bits.rd_prot = 0;
-+      rxdma_ctrl.bits.rd_burst_size = 1;
-+      rxdma_ctrl.bits.rd_bus = 3;
-+      rxdma_ctrl.bits.rd_endian = 0;
-+      rxdma_ctrl.bits.rd_finish_en = 0;
-+      rxdma_ctrl.bits.rd_fail_en = 1;
-+      rxdma_ctrl.bits.rd_perr_en = 1;
-+      rxdma_ctrl.bits.rd_eod_en = 0;
-+      rxdma_ctrl.bits.rd_eof_en = 0;
-+      raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0xFFFFFFFF);
-+
-+      // enable interrupt
-+      dma_status.bits32 = 3;  // enable RpInt
-+      raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0xFFFFFFFF);
-+
-+      return 0;
-+}
-+
-+module_init(gemini_xor_init);
-+module_exit(gemini_xor_exit);
-+
---- a/arch/arm/mm/Kconfig
-+++ b/arch/arm/mm/Kconfig
-@@ -187,6 +187,26 @@
-         Say Y if you want support for the ARM926T processor.
-         Otherwise, say N.
-+###### for Storlink SoC ######
-+config CPU_FA526
-+      bool "FA526 processor"
-+      depends on ARCH_SL2312
-+      default y
-+      select CPU_32v4
-+      select CPU_ABRT_EV4
-+      select CPU_CACHE_FA
-+      select CPU_CACHE_VIVT
-+      select CPU_CP15_MMU
-+      select CPU_COPY_FA
-+      select CPU_TLB_FA
-+      select CPU_FA_BTB
-+      help
-+        The FA526 is a version of the ARM9 compatible processor, but with smaller
-+        instruction and data caches. It is used in Storlink Sword device family.
-+
-+        Say Y if you want support for the FA526 processor.
-+        Otherwise, say N.
-+
- # ARM940T
- config CPU_ARM940T
-       bool "Support ARM940T processor" if ARCH_INTEGRATOR
-@@ -461,6 +481,9 @@
- config CPU_CACHE_VIPT
-       bool
-+config CPU_CACHE_FA
-+      bool
-+
- if MMU
- # The copy-page model
- config CPU_COPY_V3
-@@ -475,6 +498,12 @@
- config CPU_COPY_V6
-       bool
-+config CPU_COPY_FA
-+      bool
-+
-+config CPU_FA_BTB
-+      bool
-+
- # This selects the TLB model
- config CPU_TLB_V3
-       bool
-@@ -534,6 +563,14 @@
- config IO_36
-       bool
-+config CPU_TLB_FA
-+      bool
-+      help
-+        //TODO
-+        Faraday ARM FA526 architecture, unified TLB with writeback cache
-+        and invalidate instruction cache entry. Branch target buffer is also
-+        supported.
-+
- comment "Processor Features"
- config ARM_THUMB
-@@ -600,7 +637,7 @@
- config CPU_DCACHE_WRITETHROUGH
-       bool "Force write through D-cache"
--      depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
-+      depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FA526) && !CPU_DCACHE_DISABLE
-       default y if CPU_ARM925T
-       help
-         Say Y here to use the data cache in writethrough mode. Unless you
---- a/arch/arm/mm/Makefile
-+++ b/arch/arm/mm/Makefile
-@@ -32,6 +32,7 @@
- obj-$(CONFIG_CPU_CACHE_V4WB)  += cache-v4wb.o
- obj-$(CONFIG_CPU_CACHE_V6)    += cache-v6.o
- obj-$(CONFIG_CPU_CACHE_V7)    += cache-v7.o
-+obj-$(CONFIG_CPU_CACHE_FA)    += cache-fa.o
- obj-$(CONFIG_CPU_COPY_V3)     += copypage-v3.o
- obj-$(CONFIG_CPU_COPY_V4WT)   += copypage-v4wt.o
-@@ -40,6 +41,7 @@
- obj-$(CONFIG_CPU_SA1100)      += copypage-v4mc.o
- obj-$(CONFIG_CPU_XSCALE)      += copypage-xscale.o
- obj-$(CONFIG_CPU_XSC3)                += copypage-xsc3.o
-+obj-$(CONFIG_CPU_COPY_FA)     += copypage-fa.o
- obj-$(CONFIG_CPU_TLB_V3)      += tlb-v3.o
- obj-$(CONFIG_CPU_TLB_V4WT)    += tlb-v4.o
-@@ -47,6 +49,7 @@
- obj-$(CONFIG_CPU_TLB_V4WBI)   += tlb-v4wbi.o
- obj-$(CONFIG_CPU_TLB_V6)      += tlb-v6.o
- obj-$(CONFIG_CPU_TLB_V7)      += tlb-v7.o
-+obj-$(CONFIG_CPU_TLB_FA)      += tlb-fa.o
- obj-$(CONFIG_CPU_ARM610)      += proc-arm6_7.o
- obj-$(CONFIG_CPU_ARM710)      += proc-arm6_7.o
-@@ -60,6 +63,7 @@
- obj-$(CONFIG_CPU_ARM926T)     += proc-arm926.o
- obj-$(CONFIG_CPU_ARM940T)     += proc-arm940.o
- obj-$(CONFIG_CPU_ARM946E)     += proc-arm946.o
-+obj-$(CONFIG_CPU_FA526)               += proc-fa526.o
- obj-$(CONFIG_CPU_ARM1020)     += proc-arm1020.o
- obj-$(CONFIG_CPU_ARM1020E)    += proc-arm1020e.o
- obj-$(CONFIG_CPU_ARM1022)     += proc-arm1022.o
---- /dev/null
-+++ b/arch/arm/mm/cache-fa.S
-@@ -0,0 +1,400 @@
-+/*
-+ *  linux/arch/arm/mm/cache-fa.S
-+ *
-+ *  Copyright (C) 2005 Faraday Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *  Processors: FA520 FA526 FA626     
-+ * 03/31/2005 :       Luke Lee created, modified from cache-v4wb.S
-+ * 04/06/2005 :       1. Read CR0-1 and determine the cache size dynamically,
-+ *               to suit all Faraday CPU series
-+ *            2. Fixed all functions
-+ * 04/08/2005 :       insert CONFIG_CPU_ICACHE_DISABLE and CONFIG_CPU_DCACHE_DISABLE
-+ * 04/12/2005 :       TODO: make this processor dependent or a self-modifying code to 
-+ *            inline cache len/size info into the instructions, as reading cache 
-+ *            size and len info in memory could cause another cache miss.
-+ * 05/05/2005 :       Modify fa_flush_user_cache_range to comply APCS.
-+ * 05/19/2005 :       Adjust for boundary conditions.
-+ */
-+#include <linux/linkage.h>
-+#include <linux/init.h>
-+#include <asm/hardware.h>
-+#include <asm/page.h>
-+#include "proc-macros.S"
-+
-+#define CACHE_DLINESIZE          16
-+#ifdef CONFIG_SL3516_ASIC
-+#define CACHE_DSIZE      8192
-+#else
-+#define CACHE_DSIZE      16384 
-+#endif 
-+#define CACHE_ILINESIZE          16
-+#define CACHE_ISIZE      16384
-+
-+/* Luke Lee 04/06/2005 ins begin */
-+/*
-+ *    initialize_cache_info()
-+ *
-+ *    Automatic detection of DSIZE, DLEN, ISIZE, ILEN variables according to 
-+ *    system register CR0-1
-+ *    Destroyed register: r0, r1, r2, r3, ip
-+ */
-+      .align
-+ENTRY(fa_initialize_cache_info)
-+      mov     r3, #1                          @ r3 always = 1
-+      adr     ip, __fa_cache_ilen
-+      
-+      mrc     p15, 0, r0, c0, c0, 1
-+      /* ILEN */
-+      and     r1, r0, #3                      @ bits [1:0]
-+      add     r1, r1, #3                      @ cache line size is at least 8 bytes (2^3)
-+      mov     r2, r3, lsl r1                  @ r2 = 1<<r1
-+      str     r2, [ip], #4
-+      /* ISIZE */
-+      mov     r1, r0, lsr #6                  @ bits [8:6]
-+      and     r1, r1, #7
-+      add     r1, r1, #9                      @ cache size is at least 512 bytes (2^9)
-+      mov     r2, r3, lsl r1
-+      str     r2, [ip], #4
-+      /* DLEN */
-+      mov     r1, r0, lsr #12
-+      and     r1, r1, #3                      @ bits [13:12]
-+      add     r1, r1, #3                      @ cache line size is at least 8 bytes (2^3)
-+      mov     r2, r3, lsl r1                  @ r2 = 1<<r1
-+      str     r2, [ip], #4
-+      /* DSIZE */
-+      mov     r1, r0, lsr #18                 @ bits [20:18]
-+      and     r1, r1, #7
-+      add     r1, r1, #9                      @ cache size is at least 512 bytes (2^9)
-+      mov     r2, r3, lsl r1
-+      str     r2, [ip]
-+      mov     pc, lr
-+
-+      /* Warning : Do not change the order ! Successive codes depends on this */
-+      .align
-+      .globl __fa_cache_ilen, __fa_cache_isize, __fa_cache_dlen, __fa_cache_dsize
-+__fa_cache_ilen:
-+      .word   0                               @ instruction cache line length
-+__fa_cache_isize:
-+      .word   0                               @ instruction cache size
-+__fa_cache_dlen:
-+      .word   0                               @ data cahce line length        
-+__fa_cache_dsize:
-+      .word   0                               @ data cache size
-+
-+/* Luke Lee 04/06/2005 ins end */
-+
-+/*
-+ *    flush_user_cache_all()
-+ *
-+ *    Clean and invalidate all cache entries in a particular address
-+ *    space.
-+ */
-+ENTRY(fa_flush_user_cache_all)
-+      /* FALLTHROUGH */
-+/*
-+ *    flush_kern_cache_all()
-+ *
-+ *    Clean and invalidate the entire cache.
-+ */
-+ENTRY(fa_flush_kern_cache_all)
-+/* Luke Lee 04/06/2005 mod ok */
-+      mov     ip, #0
-+      
-+#ifndef CONFIG_CPU_ICACHE_DISABLE
-+      mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
-+#endif
-+      
-+__flush_whole_cache:
-+      
-+#ifndef CONFIG_CPU_DCACHE_DISABLE
-+      mov     ip, #0
-+#  ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
-+#  else
-+      mcr     p15, 0, ip, c7,c14, 0           @ clean/invalidate D cache
-+#  endif
-+#endif /*CONFIG_CPU_DCACHE_DISABLE*/
-+      
-+#ifndef CONFIG_CPU_FA_WB_DISABLE      
-+      mcr     p15, 0, ip, c7, c10, 4          @ drain write buffer
-+#endif
-+      
-+#ifdef CONFIG_CPU_FA_BTB
-+      mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB
-+      nop
-+      nop
-+#endif
-+      
-+/* Luke Lee 04/06/2005 que todo tofix : should iscratchpad and dscratchpad be invalidated ? */
-+      mov     pc, lr
-+
-+/*
-+ *    flush_user_cache_range(start, end, flags)
-+ *
-+ *    Invalidate a range of cache entries in the specified
-+ *    address space.
-+ *
-+ *    - start - start address (inclusive, page aligned)
-+ *    - end   - end address (exclusive, page aligned)
-+ *    - flags - vma_area_struct flags describing address space
-+ */
-+ENTRY(fa_flush_user_cache_range)
-+
-+/* Luke Lee 04/06/2005 mod ok */
-+      /* Luke Lee 04/07/2005 ins 1 */
-+      mov     ip, #0
-+      sub     r3, r1, r0                      @ calculate total size
-+#ifndef CONFIG_CPU_ICACHE_DISABLE
-+      tst     r2, #VM_EXEC                    @ executable region?
-+      mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
-+#endif
-+
-+#ifndef CONFIG_CPU_DCACHE_DISABLE     
-+      /* Luke Lee 04/06/2005 ins 2 mod 1 */
-+      cmp     r3, #CACHE_DSIZE                @ total size >= limit?
-+      bhs     __flush_whole_cache             @ flush whole D cache
-+
-+      //debug_Aaron
-+        bic     r0, r0, #CACHE_DLINESIZE-1  
-+      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate boundary D entry
-+        bic     r1, r1, #CACHE_DLINESIZE-1  
-+      mcr     p15, 0, r1, c7, c14, 1          @ clean and invalidate boundary D entry
-+
-+
-+1:    /* Luke Lee 04/06/2005 del 2 ins 5 */
-+      
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
-+#else
-+      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
-+#endif
-+      /* Luke Lee 04/06/2005 mod 1 */
-+      add     r0, r0, #CACHE_DLINESIZE
-+      cmp     r0, r1
-+      bls     1b                              @ Luke Lee 05/19/2005
-+#endif        /* CONFIG_CPU_DCACHE_DISABLE */
-+      
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      tst     r2, #VM_EXEC
-+      /* Luke Lee 04/06/2005 mod 1 tofix todo : ne->eq */
-+      mcreq   p15, 0, r4, c7, c10, 4          @ drain write buffer
-+#endif
-+
-+      /* Luke Lee 04/06/2005 ins block */
-+#ifdef CONFIG_CPU_FA_BTB
-+        tst     r2, #VM_EXEC
-+      mov     ip, #0
-+      mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
-+      nop
-+      nop
-+#endif
-+      mov     pc, lr
-+
-+/*
-+ *    flush_kern_dcache_page(void *page)
-+ *
-+ *    Ensure no D cache aliasing occurs, either with itself or
-+ *    the I cache
-+ *
-+ *    - addr  - page aligned address
-+ */
-+ENTRY(fa_flush_kern_dcache_page)
-+      add     r1, r0, #PAGE_SZ
-+      /* fall through */
-+
-+/*
-+ *    coherent_kern_range(start, end)
-+ *
-+ *    Ensure coherency between the Icache and the Dcache in the
-+ *    region described by start.  If you have non-snooping
-+ *    Harvard caches, you need to implement this function.
-+ *
-+ *    - start  - virtual start address
-+ *    - end    - virtual end address
-+ */
-+ENTRY(fa_coherent_kern_range)
-+      /* fall through */
-+
-+/*
-+ *    coherent_user_range(start, end)
-+ *
-+ *    Ensure coherency between the Icache and the Dcache in the
-+ *    region described by start.  If you have non-snooping
-+ *    Harvard caches, you need to implement this function.
-+ *
-+ *    - start  - virtual start address
-+ *    - end    - virtual end address
-+ */
-+ENTRY(fa_coherent_user_range)
-+
-+/* Luke Lee 04/06/2005 mod ok */
-+      /* Luke Lee 04/06/2005 ins 3 mod 1 */
-+      bic     r0, r0, #CACHE_DLINESIZE-1
-+
-+ //debug_Aaron
-+        bic     r0, r0, #CACHE_DLINESIZE-1
-+        mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate boundary D entry
-+        bic     r1, r1, #CACHE_DLINESIZE-1
-+        mcr     p15, 0, r1, c7, c14, 1          @ clean and invalidate boundary D entry
-+
-+#if !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE))
-+1:    /* Luke Lee 04/06/2005 del 2 ins 5 mod 1 */
-+#ifndef CONFIG_CPU_DCACHE_DISABLE     
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
-+#else
-+      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
-+#endif
-+#endif /* CONFIG_CPU_DCACHE_DISABLE */
-+      
-+#ifndef CONFIG_CPU_ICACHE_DISABLE
-+      mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
-+#endif
-+      add     r0, r0, #CACHE_DLINESIZE
-+      cmp     r0, r1
-+      bls     1b                              @ Luke Lee 05/19/2005 blo->bls  
-+#endif /* !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) */
-+
-+      mov     ip, #0
-+#ifdef CONFIG_CPU_FA_BTB
-+      mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB
-+      nop
-+      nop
-+#endif
-+
-+/* Luke Lee 04/08/2005 ins 1 skp 1 ins 1 */
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mcr     p15, 0, ip, c7, c10, 4          @ drain WB
-+#endif
-+
-+      mov     pc, lr
-+
-+/*
-+ *    dma_inv_range(start, end)
-+ *
-+ *    Invalidate (discard) the specified virtual address range.
-+ *    May not write back any entries.  If 'start' or 'end'
-+ *    are not cache line aligned, those lines must be written
-+ *    back.
-+ *
-+ *    - start  - virtual start address
-+ *    - end    - virtual end address
-+ */
-+ENTRY(fa_dma_inv_range)
-+
-+/* Luke Lee 04/06/2005 mod ok */
-+
-+#ifndef CONFIG_CPU_DCACHE_DISABLE     
-+
-+ //debug_Aaron
-+        bic     r0, r0, #CACHE_DLINESIZE-1
-+        mcr     p15, 0, r0, c7, c6, 1          @ invalidate boundary D entry
-+        bic     r1, r1, #CACHE_DLINESIZE-1
-+        mcr     p15, 0, r1, c7, c6, 1          @ invalidate boundary D entry
-+
-+      /* Luke Lee 04/06/2005 ins 4 mod 2 */
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      tst     r0, #CACHE_DLINESIZE -1
-+      bic     r0, r0, #CACHE_DLINESIZE -1
-+
-+//debug_Aaron
-+      //mcrne p15, 0, r0, c7, c10, 1          @ clean boundary D entry
-+
-+      /* Luke Lee 04/06/2005 mod 1 */
-+      /* Luke Lee 05/19/2005 always clean the end-point boundary mcrne->mcr */
-+      ////tst r1, #CACHE_DLINESIZE -1
-+      //mcr   p15, 0, r1, c7, c10, 1          @ clean boundary D entry
-+      /* Luke Lee 04/06/2005 ins 1 */
-+#else
-+      bic     r0, r0, #CACHE_DLINESIZE -1     
-+#endif
-+
-+//debug_Aaron 
-+1:    mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
-+//1:  mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
-+
-+      /* Luke Lee 04/06/2005 mod 1 */ 
-+      add     r0, r0, #CACHE_DLINESIZE
-+      cmp     r0, r1
-+      bls     1b                              @ Luke Lee 05/19/2005 blo->bls
-+#endif /* CONFIG_CPU_DCACHE_DISABLE */
-+
-+      /* Luke Lee 04/06/2005 ins 1 */         
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mov     r0, #0
-+      mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
-+#endif        
-+
-+      mov     pc, lr
-+
-+/*
-+ *    dma_clean_range(start, end)
-+ *
-+ *    Clean (write back) the specified virtual address range.
-+ *
-+ *    - start  - virtual start address
-+ *    - end    - virtual end address
-+ */
-+ENTRY(fa_dma_clean_range)
-+
-+/* Luke Lee 04/06/2005 mod ok */
-+#ifndef CONFIG_CPU_DCACHE_DISABLE     
-+
-+ //debug_Aaron
-+        bic     r0, r0, #CACHE_DLINESIZE-1
-+        mcr     p15, 0, r0, c7, c10, 1          @ clean boundary D entry
-+        bic     r1, r1, #CACHE_DLINESIZE-1
-+        mcr     p15, 0, r1, c7, c10, 1          @ clean boundary D entry
-+
-+      /* Luke Lee 04/06/2005 ins 4 mod 2 */
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      bic     r0, r0, #CACHE_DLINESIZE - 1
-+
-+//debug_Aaron
-+1:    mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
-+//1:  mcr     p15, 0, r0, c7, c14, 1          @ clean D entry
-+      add     r0, r0, #CACHE_DLINESIZE
-+      cmp     r0, r1
-+      bls     1b                              @ Luke Lee 05/19/2005 blo->bls
-+      /* Luke Lee 04/06/2005 ins 2 */
-+#endif
-+#endif /* CONFIG_CPU_DCACHE_DISABLE */
-+
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mov     r0, #0  
-+      mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
-+#endif        
-+
-+      mov     pc, lr
-+
-+/*
-+ *    dma_flush_range(start, end)
-+ *
-+ *    Clean and invalidate the specified virtual address range.
-+ *
-+ *    - start  - virtual start address
-+ *    - end    - virtual end address
-+ *
-+ *    This is actually the same as fa_coherent_kern_range()
-+ */
-+      .globl  fa_dma_flush_range
-+      .set    fa_dma_flush_range, fa_coherent_kern_range
-+
-+      __INITDATA
-+
-+      .type   fa_cache_fns, #object
-+ENTRY(fa_cache_fns)
-+      .long   fa_flush_kern_cache_all
-+      .long   fa_flush_user_cache_all
-+      .long   fa_flush_user_cache_range
-+      .long   fa_coherent_kern_range
-+      .long   fa_coherent_user_range
-+      .long   fa_flush_kern_dcache_page
-+      .long   fa_dma_inv_range
-+      .long   fa_dma_clean_range
-+      .long   fa_dma_flush_range
-+      .size   fa_cache_fns, . - fa_cache_fns
---- /dev/null
-+++ b/arch/arm/mm/copypage-fa.S
-@@ -0,0 +1,106 @@
-+/*
-+ *  linux/arch/arm/lib/copypage-fa.S
-+ *
-+ *  Copyright (C) 2005 Faraday Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *  ASM optimised string functions
-+ * 05/18/2005 :       Luke Lee created, modified from copypage-v4wb.S
-+ */
-+#include <linux/linkage.h>
-+#include <linux/init.h>
-+#include <asm/asm-offsets.h>
-+
-+      .text
-+/*
-+ * ARMv4 optimised copy_user_page for Faraday processors
-+ *
-+ * We flush the destination cache lines just before we write the data into the
-+ * corresponding address.  Since the Dcache is read-allocate, this removes the
-+ * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
-+ * and merged as appropriate.
-+ *
-+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
-+ * instruction.  If your processor does not supply this, you have to write your
-+ * own copy_user_page that does the right thing.
-+ *
-+ * copy_user_page(to,from,vaddr)
-+ */
-+      .align  4
-+ENTRY(fa_copy_user_page)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      /* Write through */
-+      stmfd   sp!, {r4, lr}                   @ 2
-+      mov     r2, #PAGE_SZ/32                 @ 1
-+
-+      ldmia   r1!, {r3, r4, ip, lr}           @ 4
-+1:    stmia   r0!, {r3, r4, ip, lr}           @ 4
-+      ldmia   r1!, {r3, r4, ip, lr}           @ 4+1
-+      subs    r2, r2, #1                      @ 1
-+      stmia   r0!, {r3, r4, ip, lr}           @ 4
-+      ldmneia r1!, {r3, r4, ip, lr}           @ 4
-+      bne     1b                              @ 1
-+
-+      mcr     p15, 0, r2, c7, c7, 0           @ flush ID cache
-+      ldmfd   sp!, {r4, pc}                   @ 3
-+#else
-+      /* Write back */
-+      stmfd   sp!, {r4, lr}                   @ 2
-+      mov     r2, #PAGE_SZ/32                 @ 1
-+
-+1:    ldmia   r1!, {r3, r4, ip, lr}           @ 4
-+      mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-+      stmia   r0!, {r3, r4, ip, lr}           @ 4
-+      ldmia   r1!, {r3, r4, ip, lr}           @ 4
-+      mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-+      stmia   r0!, {r3, r4, ip, lr}           @ 4
-+      subs    r2, r2, #1                      @ 1
-+      bne     1b
-+      mcr     p15, 0, r2, c7, c10, 4          @ 1   drain WB
-+      ldmfd   sp!, {r4, pc}                   @ 3
-+#endif
-+
-+/*
-+ * ARMv4 optimised clear_user_page
-+ *
-+ * Same story as above.
-+ */
-+      .align  4
-+ENTRY(fa_clear_user_page)
-+      str     lr, [sp, #-4]!
-+      mov     r1, #PAGE_SZ/32                 @ 1
-+      mov     r2, #0                          @ 1
-+      mov     r3, #0                          @ 1
-+      mov     ip, #0                          @ 1
-+      mov     lr, #0                          @ 1
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      /* Write through */
-+1:    stmia   r0!, {r2, r3, ip, lr}           @ 4
-+      stmia   r0!, {r2, r3, ip, lr}           @ 4
-+      subs    r1, r1, #1                      @ 1
-+      bne     1b                              @ 1
-+
-+      mcr     p15, 0, r1, c7, c7, 0           @ flush ID cache
-+      ldr     pc, [sp], #4
-+#else
-+      /* Write back */
-+1:    mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-+      stmia   r0!, {r2, r3, ip, lr}           @ 4
-+      mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-+      stmia   r0!, {r2, r3, ip, lr}           @ 4
-+      subs    r1, r1, #1                      @ 1
-+      bne     1b                              @ 1
-+      mcr     p15, 0, r1, c7, c10, 4          @ 1   drain WB
-+      ldr     pc, [sp], #4
-+#endif
-+
-+      __INITDATA
-+
-+      .type   fa_user_fns, #object
-+ENTRY(fa_user_fns)
-+      .long   fa_clear_user_page
-+      .long   fa_copy_user_page
-+      .size   fa_user_fns, . - fa_user_fns
---- a/arch/arm/mm/init.c
-+++ b/arch/arm/mm/init.c
-@@ -23,6 +23,7 @@
- #include <asm/mach/arch.h>
- #include <asm/mach/map.h>
-+#include <asm/arch/ipi.h>
- #include "mm.h"
-@@ -252,6 +253,11 @@
-               initrd_end = initrd_start + phys_initrd_size;
-       }
- #endif
-+#ifdef CONFIG_GEMINI_IPI
-+      printk("CPU ID:%d\n",getcpuid());
-+//    reserve_bootmem_node(NODE_DATA(0), 0x400000, 0x400000);         //CPU0 space
-+//    reserve_bootmem_node(NODE_DATA(0), SHAREADDR, SHARE_MEM_SIZE);          //share memory
-+#endif
-       /*
-        * Finally, reserve any node zero regions.
---- /dev/null
-+++ b/arch/arm/mm/proc-fa526.S
-@@ -0,0 +1,407 @@
-+/*
-+ *  linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526
-+ *
-+ *  Copyright (C) 2005 Faraday Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *
-+ * These are the low level assembler for performing cache and TLB
-+ * functions on the fa526.
-+ *
-+ *  Written by : Luke Lee
-+ */
-+#include <linux/linkage.h>
-+#include <linux/init.h>
-+#include <asm/assembler.h>
-+#include <asm/pgtable.h>
-+#include <asm/pgtable-hwdef.h>
-+#include <asm/elf.h>
-+#include <asm/hardware.h>
-+#include <asm/page.h>
-+#include <asm/ptrace.h>
-+#include <asm/system.h>
-+#include "proc-macros.S"
-+
-+#define CACHE_DLINESIZE          16
-+
-+      .text
-+/*
-+ * cpu_fa526_proc_init()
-+ */
-+ENTRY(cpu_fa526_proc_init)
-+      /* MMU is already ON here, ICACHE, DCACHE conditionally disabled */
-+
-+        mov     r0, #1
-+      nop
-+      nop
-+        mcr     p15, 0, r0, c1, c1, 0         @ turn-on ECR
-+      nop
-+      nop
-+
-+      mrc     p15, 0, r0, c1, c0, 0           @ read ctrl register
-+
-+#ifdef CONFIG_CPU_FA_BTB
-+      orr     r0, r0, #CR_Z
-+#else
-+      bic     r0, r0, #CR_Z
-+#endif
-+#ifdef CONFIG_CPU_FA_WB_DISABLE
-+      mov     r1, #0
-+      mcr     p15, 0, r1, c7, c10, 4          @ drain write buffer
-+      nop
-+      nop
-+      bic     r0, r0, #CR_W
-+#else
-+      orr     r0, r0, #CR_W
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_DISABLE
-+      bic     r0, r0, #CR_C
-+#else
-+      orr     r0, r0, #CR_C
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_DISABLE
-+      bic     r0, r0, #CR_I
-+#else
-+      orr     r0, r0, #CR_I
-+#endif
-+
-+      nop
-+      nop
-+      mcr     p15, 0, r0, c1, c0, 0
-+      nop
-+      nop
-+
-+      mov     r5, lr
-+      bl      fa_initialize_cache_info        @ destroy r0~r4
-+      mov     pc, r5                          @ return
-+
-+
-+/*
-+ * cpu_fa526_proc_fin()
-+ */
-+ENTRY(cpu_fa526_proc_fin)
-+      stmfd   sp!, {lr}
-+      mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
-+      msr     cpsr_c, ip
-+
-+      bl      fa_flush_kern_cache_all
-+      mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
-+      bic     r0, r0, #0x1000                 @ ...i............
-+      bic     r0, r0, #0x000e                 @ ............wca.
-+      mcr     p15, 0, r0, c1, c0, 0           @ disable caches
-+
-+      nop
-+      nop
-+      ldmfd   sp!, {pc}
-+
-+/*
-+ * cpu_fa526_reset(loc)
-+ *
-+ * Perform a soft reset of the system.  Put the CPU into the
-+ * same state as it would be if it had been reset, and branch
-+ * to what would be the reset vector.
-+ *
-+ * loc: location to jump to for soft reset
-+ */
-+      .align  4
-+ENTRY(cpu_fa526_reset)
-+      mov     ip, #0
-+      mcr     p15, 0, ip, c7, c7, 0           @ invalidate I,D caches
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mcr     p15, 0, ip, c7, c10, 4          @ drain WB
-+#endif
-+      mcr     p15, 0, ip, c8, c7, 0           @ invalidate I & D TLBs
-+      mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
-+      bic     ip, ip, #0x000f                 @ ............wcam
-+      bic     ip, ip, #0x1100                 @ ...i...s........
-+
-+      bic     ip, ip, #0x0800                 @ BTB off
-+      mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
-+      nop
-+      nop
-+      mov     pc, r0
-+
-+/*
-+ * cpu_fa526_do_idle()
-+ */
-+      .align  4
-+ENTRY(cpu_fa526_do_idle)
-+
-+#ifdef CONFIG_CPU_FA_IDLE
-+      nop
-+      nop
-+      mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt (IDLE mode)
-+#endif
-+      mov     pc, lr
-+
-+
-+ENTRY(cpu_fa526_dcache_clean_area)
-+
-+#ifndef CONFIG_CPU_DCACHE_DISABLE
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-+1:    mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
-+      add     r0, r0, #CACHE_DLINESIZE
-+      subs    r1, r1, #CACHE_DLINESIZE
-+      bhi     1b
-+#endif
-+#endif
-+      mov     pc, lr
-+
-+
-+/* =============================== PageTable ============================== */
-+
-+/*
-+ * cpu_fa526_switch_mm(pgd)
-+ *
-+ * Set the translation base pointer to be as described by pgd.
-+ *
-+ * pgd: new page tables
-+ */
-+      .align  4
-+
-+      .globl  fault_address
-+fault_address:
-+      .long   0
-+
-+ENTRY(cpu_fa526_switch_mm)
-+
-+      mov     ip, #0
-+#ifndef CONFIG_CPU_DCACHE_DISABLE
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
-+#else
-+      mcr     p15, 0, ip, c7, c14, 0          @ Clean and invalidate whole DCache
-+#endif
-+#endif /*CONFIG_CPU_DCACHE_DISABLE*/
-+
-+#ifndef CONFIG_CPU_ICACHE_DISABLE
-+      mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
-+#endif
-+
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mcr     p15, 0, ip, c7, c10, 4          @ drain WB
-+#endif
-+
-+#ifdef CONFIG_CPU_FA_BTB
-+      mcr     p15, 0, ip, c7, c5, 6           @ invalidate BTB since mm changed
-+      nop
-+      nop
-+#endif
-+      bic     r0, r0, #0xff                   @ clear bits [7:0]
-+      bic     r0, r0, #0x3f00                 @ clear bits [13:8]
-+      mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
-+      mcr     p15, 0, ip, c8, c7, 0           @ invalidate UTLB
-+      nop
-+      nop
-+      mov     pc, lr
-+
-+/*
-+ * cpu_fa526_set_pte_ext(ptep, pte, ext)
-+ *
-+ * Set a PTE and flush it out
-+ */
-+      .align  4
-+ENTRY(cpu_fa526_set_pte_ext)
-+      str     r1, [r0], #-2048                @ linux version
-+
-+      eor     r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
-+
-+      bic     r2, r1, #PTE_SMALL_AP_MASK
-+      bic     r2, r2, #PTE_TYPE_MASK
-+      orr     r2, r2, #PTE_TYPE_SMALL
-+
-+      tst     r1, #L_PTE_USER                 @ User?
-+      orrne   r2, r2, #PTE_SMALL_AP_URO_SRW
-+
-+      tst     r1, #L_PTE_WRITE | L_PTE_DIRTY  @ Write and Dirty?
-+      orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW
-+
-+      tst     r1, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
-+      movne   r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      eor     r3, r2, #0x0a                   @ C & small page?  1010
-+      tst     r3, #0x0b                       @                  1011
-+      biceq   r2, r2, #4
-+#endif
-+      str     r2, [r0]                        @ hardware version
-+
-+      mov     r2, #0
-+      mcr     p15, 0, r2, c7, c10, 0          @ clean D cache all
-+
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mcr     p15, 0, r2, c7, c10, 4          @ drain WB
-+#endif
-+#ifdef CONFIG_CPU_FA_BTB
-+      mcr     p15, 0, r2, c7, c5, 6           @ invalidate BTB
-+      nop
-+      nop
-+#endif
-+      mov     pc, lr
-+
-+      __INIT
-+
-+      .type   __fa526_setup, #function
-+__fa526_setup:
-+      /* On return of this routine, r0 must carry correct flags for CFG register */
-+      mov     r0, #0
-+      mcr     p15, 0, r0, c7, c7              @ invalidate I,D caches on v4
-+      mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer on v4
-+      mcr     p15, 0, r0, c8, c7              @ invalidate I,D TLBs on v4
-+
-+      mcr     p15, 0, r0, c7, c5, 5           @ invalidate IScratchpad RAM
-+
-+        mov     r0, #1
-+        mcr     p15, 0, r0, c1, c1, 0         @ turn-on ECR
-+
-+      mrc     p15, 0, r0, c9, c1, 0           @ DScratchpad
-+      bic     r0, r0, #1
-+      mcr     p15, 0, r0, c9, c1, 0
-+      mrc     p15, 0, r0, c9, c1, 1           @ IScratchpad
-+      bic     r0, r0, #1
-+      mcr     p15, 0, r0, c9, c1, 1
-+
-+      mov     r0, #0
-+      mcr     p15, 0, r0, c1, c1, 0           @ turn-off ECR
-+
-+#ifdef CONFIG_CPU_FA_BTB
-+      mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB All
-+      nop
-+      nop
-+#endif
-+
-+      mov     r0, #0x1f                       @ Domains 0, 1 = manager, 2 = client
-+      mcr     p15, 0, r0, c3, c0              @ load domain access register
-+
-+      mrc     p15, 0, r0, c1, c0              @ get control register v4
-+      ldr     r5, fa526_cr1_clear
-+      bic     r0, r0, r5
-+      ldr     r5, fa526_cr1_set
-+      orr     r0, r0, r5
-+
-+#ifdef CONFIG_CPU_FA_BTB
-+      orr     r0, r0, #CR_Z
-+#else
-+      bic     r0, r0, #CR_Z
-+#endif
-+#ifdef CONFIG_CPU_FA_WB_DISABLE
-+      mov     r12, #0
-+      mcr     p15, 0, r12, c7, c10, 4         @ drain write buffer
-+      nop
-+      nop
-+      bic     r0, r0, #CR_W                   @ .... .... .... 1...
-+#else
-+      orr     r0, r0, #CR_W
-+#endif
-+
-+      mov     pc, lr
-+      .size   __fa526_setup, . - __fa526_setup
-+
-+      /*
-+       * .RVI ZFRS BLDP WCAM
-+       * ..11 0001 .111 1101
-+       *
-+       */
-+      .type   fa526_cr1_clear, #object
-+      .type   fa526_cr1_set, #object
-+fa526_cr1_clear:
-+      .word   0x3f3f
-+fa526_cr1_set:
-+      .word   0x317D
-+
-+      __INITDATA
-+
-+/*
-+ * Purpose : Function pointers used to access above functions - all calls
-+ *         come through these
-+ */
-+      .type   fa526_processor_functions, #object
-+fa526_processor_functions:
-+      .word   v4_early_abort
-+      .word   cpu_fa526_proc_init
-+      .word   cpu_fa526_proc_fin
-+      .word   cpu_fa526_reset
-+      .word   cpu_fa526_do_idle
-+      .word   cpu_fa526_dcache_clean_area
-+      .word   cpu_fa526_switch_mm
-+      .word   cpu_fa526_set_pte_ext
-+      .size   fa526_processor_functions, . - fa526_processor_functions
-+
-+      .section ".rodata"
-+
-+      .type   cpu_arch_name, #object
-+cpu_arch_name:
-+      .asciz  "armv4"
-+      .size   cpu_arch_name, . - cpu_arch_name
-+
-+      .type   cpu_elf_name, #object
-+cpu_elf_name:
-+      .asciz  "v4"
-+      .size   cpu_elf_name, . - cpu_elf_name
-+
-+      .type   cpu_fa526_name, #object
-+cpu_fa526_name:
-+      .ascii  "FA526"
-+#ifndef CONFIG_CPU_ICACHE_DISABLE
-+      .ascii  "i"
-+#endif
-+#ifndef CONFIG_CPU_DCACHE_DISABLE
-+      .ascii  "d"
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+      .ascii  "(wt)"
-+#else
-+      .ascii  "(wb)"
-+#endif
-+#endif
-+      .ascii  "\0"
-+      .size   cpu_fa526_name, . - cpu_fa526_name
-+
-+      .align
-+
-+      .section ".proc.info.init", #alloc, #execinstr
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+#define __PMD_SECT_BUFFERABLE 0
-+#else
-+#define __PMD_SECT_BUFFERABLE PMD_SECT_BUFFERABLE
-+#endif
-+
-+      .type   __fa526_proc_info,#object
-+__fa526_proc_info:
-+      .long   0x66015261
-+      .long   0xff01fff1
-+      .long   PMD_TYPE_SECT | \
-+              __PMD_SECT_BUFFERABLE | \
-+              PMD_SECT_CACHEABLE | \
-+              PMD_BIT4 | \
-+              PMD_SECT_AP_WRITE | \
-+              PMD_SECT_AP_READ
-+      .long   PMD_TYPE_SECT | \
-+              PMD_BIT4 | \
-+              PMD_SECT_AP_WRITE | \
-+              PMD_SECT_AP_READ
-+      b       __fa526_setup
-+      .long   cpu_arch_name
-+      .long   cpu_elf_name
-+      .long   HWCAP_SWP | HWCAP_HALF
-+      .long   cpu_fa526_name
-+      .long   fa526_processor_functions
-+      .long   fa_tlb_fns
-+      .long   fa_user_fns
-+      .long   fa_cache_fns
-+      .size   __fa526_proc_info, . - __fa526_proc_info
-+
-+
---- /dev/null
-+++ b/arch/arm/mm/tlb-fa.S
-@@ -0,0 +1,96 @@
-+/*
-+ *  linux/arch/arm/mm/tlb-fa.S
-+ *
-+ *  Copyright (C) 2005 Faraday Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *  ARM architecture version 4, Faraday variation.
-+ *  This assume an unified TLBs, with a write buffer, and branch target buffer (BTB)
-+ *
-+ *  Processors: FA520 FA526 FA626
-+ *  03/31/2005 : Created by Luke Lee, modified from tlb-v4wbi.S
-+ *  05/06/2005 : Fixed buggy CPU versions that did not invalidate the associated
-+ *               data cache entries when invalidating TLB entries.
-+ */
-+#include <linux/linkage.h>
-+#include <linux/init.h>
-+#include <asm/asm-offsets.h>
-+#include <asm/tlbflush.h>
-+#include "proc-macros.S"
-+
-+
-+/*
-+ *    flush_user_tlb_range(start, end, mm)
-+ *
-+ *    Invalidate a range of TLB entries in the specified address space.
-+ *
-+ *    - start - range start address
-+ *    - end   - range end address
-+ *    - mm    - mm_struct describing address space
-+ */
-+      .align  4
-+ENTRY(fa_flush_user_tlb_range)
-+
-+      vma_vm_mm ip, r2
-+      act_mm  r3                              @ get current->active_mm
-+      eors    r3, ip, r3                      @ == mm ?
-+      movne   pc, lr                          @ no, we dont do anything
-+      mov     r3, #0
-+
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mcr     p15, 0, r3, c7, c10, 4          @ drain WB
-+#endif
-+
-+      vma_vm_flags r2, r2
-+      bic     r0, r0, #0x0ff
-+      bic     r0, r0, #0xf00
-+
-+1:    mcr     p15, 0, r0, c8, c7, 1           @ invalidate UTLB entry
-+      add     r0, r0, #PAGE_SZ
-+      cmp     r0, r1
-+      bls     1b                              @ Luke Lee 05/19/2005 blo -> bls
-+
-+#ifdef CONFIG_CPU_FA_BTB
-+      mcr     p15, 0, r3, c7, c5, 6           @ invalidate BTB
-+      nop
-+      nop
-+#endif
-+      mov     pc, lr
-+
-+
-+ENTRY(fa_flush_kern_tlb_range)
-+      mov     r3, #0
-+
-+      mcr     p15, 0, r3, c7, c10, 0          @ clean Dcache all 06/03/2005
-+
-+#ifndef CONFIG_CPU_FA_WB_DISABLE
-+      mcr     p15, 0, r3, c7, c10, 4          @ drain WB
-+#endif
-+
-+      bic     r0, r0, #0x0ff
-+      bic     r0, r0, #0xf00
-+1:
-+      mcr     p15, 0, r0, c8, c7, 1           @ invalidate UTLB entry
-+      add     r0, r0, #PAGE_SZ
-+      cmp     r0, r1
-+      bls     1b                              @ Luke Lee 05/19/2005 blo -> bls
-+
-+#ifdef CONFIG_CPU_FA_BTB
-+      mcr     p15, 0, r3, c7, c5, 6           @ invalidate BTB
-+      nop
-+      nop
-+#endif
-+      mov     pc, lr
-+
-+
-+      __INITDATA
-+
-+      .type   fa_tlb_fns, #object
-+ENTRY(fa_tlb_fns)
-+      .long   fa_flush_user_tlb_range
-+      .long   fa_flush_kern_tlb_range
-+      .long   fa_tlb_flags
-+      .size   fa_tlb_fns, . - fa_tlb_fns
---- a/arch/arm/tools/mach-types
-+++ b/arch/arm/tools/mach-types
-@@ -208,7 +208,8 @@
- fester                        SA1100_FESTER           FESTER                  191
- gpi                   ARCH_GPI                GPI                     192
- smdk2410              ARCH_SMDK2410           SMDK2410                193
--i519                  ARCH_I519               I519                    194
-+#i519                 ARCH_I519               I519                    194
-+sl2312          ARCH_SL2312         SL2312          194
- nexio                 SA1100_NEXIO            NEXIO                   195
- bitbox                        SA1100_BITBOX           BITBOX                  196
- g200                  SA1100_G200             G200                    197
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/SL_gpio.h
-@@ -0,0 +1,59 @@
-+#define GPIO_MINOR_LAST 31
-+#define GPIO_MAJOR    120     // Experiemental
-+
-+#define GPIO_IRQ_NBR  12
-+
-+#define GPIOBASEADDR          (IO_ADDRESS(0x021000000))
-+
-+#define GPIODATAOUTOFF                0x00
-+#define GPIODATAINOFF         0x04
-+#define GPIOPINDIROFF         0x08
-+#define GPIOPINBYPASSOFF      0x0C
-+#define GPIODATASETOFF                0x10
-+#define GPIODATACLEAROFF      0x14
-+#define GPIOPINPULLENBOFF     0x18
-+#define GPIOPINPULLTPOFF      0x1C
-+#define GPIOINTRENBOFF                0x20
-+#define GPIOINTRRAWSOFF               0x24
-+#define GPIOINTRMASKEDSTATEOFF        0x28
-+#define GPIOINTRMASKOFF               0x2C
-+#define GPIOINTRCLEAROFF      0x30
-+#define GPIOINTRTRIGGEROFF    0x34
-+#define GPIOINTRBOTHOFF               0x38
-+#define GPIOINTRRISENEGOFF    0x3C
-+#define GPIOBNCEENBOFF                0x40
-+#define GPIOBNCEPRESOFF               0x44
-+
-+#define GPIO_IOCTRL_SETDIR    0x20
-+#define GPIO_IOCTRL_SET               0x40
-+#define GPIO_IOCTRL_CLEAR     0x50
-+#define GPIO_IOCTRL_ENBINT    0x60
-+#define GPIO_IOCTRL_MASKINT   0x70
-+#define GPIO_IOCTRL_LVLTRIG   0x75
-+#define GPIO_IOCTRL_EDGINT    0x77
-+#define GPIO_IOCTRL_EDGPOLINT 0x78
-+#define GPIO_IOCTRL_BYPASS    0x30
-+#define GPIO_IOCTRL_PRESCLK   0x80
-+#define GPIO_IOCTRL_CLKVAL    0x90
-+#define GPIO_IOCTRL_PULLENB   0xA0
-+#define GPIO_IOCTRL_PULLTYPE  0xA8
-+
-+
-+#define GPIO_MAJOR    120     /* experimental MAJOR number */
-+                              // Minor - 0 : 31 gpio pins
-+
-+#define GPIO_SET      0x01
-+#define GPIO_CLEAR    0x01
-+
-+#define GPIO_INPUT    0
-+#define GPIO_OUTPUT   1
-+#define GPIO_EDGEINTR         0
-+#define GPIO_EDGESINGL        0
-+#define GPIO_EDGEBOTH 1
-+#define GPIO_POSITIVE 0
-+#define GPIO_ENBINT   1
-+#define GPIO_DISABLEMASK      1
-+#define GPIO_PULLDOWN 0
-+#define GPIO_PULLUP   1
-+#define GPIO_ENABLEPULL       1
-+#define GPIO_DISABLEPULL      0
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/debug-macro.S
-@@ -0,0 +1,20 @@
-+/* linux/include/asm-arm/arch-ebsa110/debug-macro.S
-+ *
-+ * Debugging macro include header
-+ *
-+ *  Copyright (C) 1994-1999 Russell King
-+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+**/
-+
-+              .macro  addruart,rx
-+              mov     \rx, #0x42000000
-+              .endm
-+
-+#define UART_SHIFT    2
-+#define FLOW_CONTROL
-+#include <asm/hardware/debug-8250.S>
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/dma.h
-@@ -0,0 +1,28 @@
-+/*
-+ *  linux/include/asm-arm/arch-camelot/dma.h
-+ *
-+ *  Copyright (C) 1997,1998 Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __ASM_ARCH_DMA_H
-+#define __ASM_ARCH_DMA_H
-+
-+#define MAX_DMA_ADDRESS               0xffffffff
-+
-+#define MAX_DMA_CHANNELS      0
-+
-+#endif /* _ASM_ARCH_DMA_H */
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/entry-macro.S
-@@ -0,0 +1,42 @@
-+/*
-+ * include/asm-arm/arch-arm/entry-macro.S
-+ *
-+ * Low-level IRQ helper macros for ebsa110 platform.
-+ *
-+ * This file is licensed under  the terms of the GNU General Public
-+ * License version 2. This program is licensed "as is" without any
-+ * warranty of any kind, whether express or implied.
-+ */
-+#include <asm/arch/platform.h>
-+#include <asm/arch/int_ctrl.h>
-+
-+
-+                .macro  disable_fiq
-+                .endm
-+
-+                .macro  get_irqnr_preamble, base, tmp
-+                .endm
-+
-+                .macro  arch_ret_to_user, tmp1, tmp2
-+                .endm
-+
-+                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-+                ldr     \irqstat, =IRQ_STATUS(IO_ADDRESS(SL2312_INTERRUPT_BASE))
-+                ldr     \irqnr,[\irqstat]
-+                cmp     \irqnr,#0
-+                beq     2313f
-+                mov     \tmp,\irqnr
-+                mov     \irqnr,#0
-+2312:
-+                tst     \tmp, #1
-+                bne     2313f
-+                add     \irqnr, \irqnr, #1
-+                mov     \tmp, \tmp, lsr #1
-+                cmp     \irqnr, #31
-+                bcc     2312b
-+2313:
-+                .endm
-+
-+                .macro  irq_prio_table
-+                .endm
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/flash.h
-@@ -0,0 +1,83 @@
-+#ifndef __ASM_ARM_ARCH_FLASH_H
-+#define __ASM_ARM_ARCH_FLASH_H
-+
-+#define FLASH_START                                     SL2312_FLASH_BASE
-+#define SFLASH_SIZE                                   0x00400000
-+#define SPAGE_SIZE                                    0x200
-+#define BLOCK_ERASE                                   0x50
-+#define BUFFER1_READ                                  0x54
-+#define BUFFER2_READ                                  0x56
-+#define PAGE_ERASE                                    0x81
-+#define MAIN_MEMORY_PAGE_READ                         0x52
-+#define MAIN_MEMORY_PROGRAM_BUFFER1                   0x82
-+#define MAIN_MEMORY_PROGRAM_BUFFER2                   0x85
-+#define BUFFER1_TO_MAIN_MEMORY                        0x83
-+#define BUFFER2_TO_MAIN_MEMORY                        0x86
-+#define MAIN_MEMORY_TO_BUFFER1                        0x53
-+#define MAIN_MEMORY_TO_BUFFER2                        0x55
-+#define BUFFER1_WRITE                                 0x84
-+#define BUFFER2_WRITE                                 0x87
-+#define AUTO_PAGE_REWRITE_BUFFER1                     0x58
-+#define AUTO_PAGE_REWRITE_BUFFER2                     0x59
-+#define READ_STATUS                                   0x57
-+
-+#define MAIN_MEMORY_PAGE_READ_SPI                     0xD2
-+#define BUFFER1_READ_SPI                              0xD4
-+#define BUFFER2_READ_SPI                              0xD6
-+#define READ_STATUS_SPI                               0xD7
-+
-+#define       FLASH_ACCESS_OFFSET                             0x00000010
-+#define       FLASH_ADDRESS_OFFSET                            0x00000014
-+#define       FLASH_WRITE_DATA_OFFSET                         0x00000018
-+#define       FLASH_READ_DATA_OFFSET                          0x00000018
-+#define SERIAL_FLASH_CHIP1_EN            0x00010000  // 16th bit = 1
-+#define SERIAL_FLASH_CHIP0_EN            0x00000000  // 16th bit = 0
-+#define AT45DB321_PAGE_SHIFT                   0xa
-+#define AT45DB642_PAGE_SHIFT                   0xb
-+#define CONTINUOUS_MODE                        0x00008000
-+
-+#define FLASH_ACCESS_ACTION_OPCODE                      0x0000
-+#define FLASH_ACCESS_ACTION_OPCODE_DATA                 0x0100
-+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS               0x0200
-+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA          0x0300
-+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_X_DATA          0x0400
-+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_2X_DATA         0x0500
-+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_3X_DATA         0x0600
-+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA         0x0700
-+//#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_X_DATA        0x0600
-+//#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA       0x0700
-+
-+#define M25P80_PAGE_SIZE  0x100
-+#define M25P80_SECTOR_SIZE  0x10000
-+
-+
-+//#define M25P80_BULK_ERASE                                      1
-+//#define M25P80_SECTOR_ERASE                                    2
-+//#define M25P80_SECTOR_SIZE                                     0x10000
-+
-+#define M25P80_WRITE_ENABLE                           0x06
-+#define M25P80_WRITE_DISABLE                          0x04
-+#define M25P80_READ_STATUS                            0x05
-+#define M25P80_WRITE_STATUS                           0x01
-+#define M25P80_READ                                   0x03
-+#define M25P80_FAST_READ                              0x0B
-+#define M25P80_PAGE_PROGRAM                           0x02
-+#define M25P80_SECTOR_ERASE                           0xD8
-+#define M25P80_BULK_ERASE                             0xC7
-+#define FLASH_ERR_OK                                                  0x0
-+
-+extern void address_to_page(__u32, __u16 *, __u16 *);
-+extern void main_memory_page_read(__u8, __u16, __u16, __u8 *);
-+extern void buffer_to_main_memory(__u8, __u16);
-+extern void main_memory_to_buffer(__u8, __u16);
-+extern void main_memory_page_program(__u8, __u16, __u16, __u8);
-+extern void atmel_flash_read_page(__u32, __u8 *, __u32);
-+extern void atmel_erase_page(__u8, __u16);
-+extern void atmel_read_status(__u8, __u8 *);
-+extern void atmel_flash_program_page(__u32, __u8 *, __u32);
-+extern void atmel_buffer_write(__u8, __u16, __u8);
-+extern void flash_delay(void);
-+
-+extern int m25p80_sector_erase(__u32 address, __u32 schip_en);
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/gemini_cir.h
-@@ -0,0 +1,102 @@
-+#ifndef _ASM_ARCH_CIR_H
-+#define _ASM_ARCH_CIR_H
-+#include <linux/ioctl.h>
-+
-+#define VCR_KEY_POWER         0x613E609F
-+#define TV1_KEY_POWER         0x40040100
-+#define TV1_KEY_POWER_EXT     0xBCBD
-+#define RC5_KER_POWER         0x0CF3
-+
-+#define VCC_H_ACT_PER         (16-1)
-+#define VCC_L_ACT_PER         (8-1)
-+#define VCC_DATA_LEN          (32-1)
-+#define TV1_H_ACT_PER         (8-1)
-+#define TV1_L_ACT_PER         (4-1)
-+#define TV1_DATA_LEN          (48-1)
-+
-+#define VCC_BAUD              540
-+#define TV1_BAUD              430
-+#ifdef  CONFIG_SL3516_ASIC
-+#define       EXT_CLK                 60
-+#else
-+#define       EXT_CLK                 20
-+#endif
-+
-+#define       NEC_PROTOCOL    0x0
-+#define       RC5_PROTOCOL    0x1
-+#define VCC_PROTOCOL  0x0
-+#define TV1_PROTOCOL  0x01
-+
-+#ifndef       SL2312_CIR_BASE
-+#define       SL2312_CIR_BASE         0x4C000000
-+#endif
-+#define       CIR_BASE_ADDR           IO_ADDRESS(SL2312_CIR_BASE)
-+#define STORLINK_CIR_ID               0x00010400
-+
-+#define       CIR_IP_ID               *(volatile unsigned int *)(CIR_BASE_ADDR + 0x00)
-+#define       CIR_CTR_REG             *(volatile unsigned int *)(CIR_BASE_ADDR + 0x04)
-+#define       CIR_STATUS_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x08)
-+#define       CIR_RX_REG              *(volatile unsigned int *)(CIR_BASE_ADDR + 0x0C)
-+#define       CIR_RX_EXT_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x10)
-+#define       CIR_PWR_REG             *(volatile unsigned int *)(CIR_BASE_ADDR + 0x14)
-+#define       CIR_PWR_EXT_REG         *(volatile unsigned int *)(CIR_BASE_ADDR + 0x18)
-+#define       CIR_TX_CTR_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x1C)
-+#define       CIR_TX_FEQ_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x20)
-+#define       CIR_TX_REG              *(volatile unsigned int *)(CIR_BASE_ADDR + 0x24)
-+#define       CIR_TX_EXT_REG          *(volatile unsigned int *)(CIR_BASE_ADDR + 0x28)
-+
-+
-+#ifndef       SL2312_POWER_CTRL_BASE
-+#define       SL2312_POWER_CTRL_BASE          0x4B000000
-+#endif
-+
-+#ifndef PWR_BASE_ADDR
-+#define       PWR_BASE_ADDR           IO_ADDRESS(SL2312_POWER_CTRL_BASE)
-+#endif
-+#define       PWR_CTRL_ID             *(unsigned int*)(PWR_BASE_ADDR+0x00)
-+#define       PWR_CTRL_REG            *(unsigned int*)(PWR_BASE_ADDR+0x04)
-+#define       PWR_STATUS_REG          *(unsigned int*)(PWR_BASE_ADDR+0x08)
-+
-+
-+#define BIT(x)                        (1<<x)
-+#define TX_STATUS             BIT(3)
-+
-+#define       PWR_STAT_CIR            0x10
-+#define       PWR_STAT_RTC            0x20
-+#define       PWR_STAT_PUSH           0x40
-+#define       PWR_SHUTDOWN            0x01
-+
-+#define CARR_FREQ             38000
-+
-+struct cir_ioctl_data {
-+      __u32 data;
-+};
-+struct cir_ioctl_data48 {
-+      __u32 timeout;
-+      __u32 length;
-+      __u8  ret;
-+      __u32 data;
-+      __u32 data_ext;
-+};
-+#define OLD_DATA                      0
-+#define NEW_RECEIVE                   1
-+
-+#define       CIR_IOCTL_BASE          ('I'|'R')
-+#define CIR_SET_BAUDRATE                      _IOW (CIR_IOCTL_BASE,  0, struct cir_ioctl_data)
-+#define CIR_SET_HIGH_PERIOD                   _IOW (CIR_IOCTL_BASE,  1, struct cir_ioctl_data)
-+#define CIR_SET_LOW_PERIOD                    _IOW (CIR_IOCTL_BASE,  2, struct cir_ioctl_data)
-+#define CIR_SET_PROTOCOL                      _IOW (CIR_IOCTL_BASE,  3, struct cir_ioctl_data)
-+#define CIR_SET_ENABLE_COMPARE                _IOW (CIR_IOCTL_BASE,  4, struct cir_ioctl_data)
-+#define CIR_SET_ENABLE_DEMOD          _IOW (CIR_IOCTL_BASE,  5, struct cir_ioctl_data)
-+#define CIR_SET_POWER_KEY                     _IOW (CIR_IOCTL_BASE,  6, struct cir_ioctl_data)
-+#define CIR_GET_BAUDRATE                      _IOR (CIR_IOCTL_BASE,  7, struct cir_ioctl_data)
-+#define CIR_GET_HIGH_PERIOD                   _IOR (CIR_IOCTL_BASE,  8 ,struct cir_ioctl_data)
-+#define CIR_GET_LOW_PERIOD                    _IOR (CIR_IOCTL_BASE,  9 ,struct cir_ioctl_data)
-+#define CIR_GET_PROTOCOL                      _IOR (CIR_IOCTL_BASE, 10, struct cir_ioctl_data)
-+#define CIR_GET_ENABLE_COMPARE                _IOR (CIR_IOCTL_BASE, 11, struct cir_ioctl_data)
-+#define CIR_GET_ENABLE_DEMOD          _IOR (CIR_IOCTL_BASE, 12, struct cir_ioctl_data)
-+#define CIR_GET_POWER_KEY                     _IOR (CIR_IOCTL_BASE, 13, struct cir_ioctl_data)
-+#define CIR_GET_DATA                          _IOWR (CIR_IOCTL_BASE, 14, struct cir_ioctl_data48)
-+#define CIR_WAIT_INT_DATA                     _IOWR (CIR_IOCTL_BASE, 15, struct cir_ioctl_data48)
-+
-+#endif //_ASM_ARCH_CIR_H
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/gemini_gpio.h
-@@ -0,0 +1,77 @@
-+/*
-+ * FILE NAME gemini_gpio.h
-+ *
-+ * BRIEF MODULE DESCRIPTION
-+ *    Generic Gemini GPIO
-+ *
-+ *  Author: Storlink Software [Device driver]
-+ *          Jason Lee <jason@storlink.com.tw>
-+ *
-+ * Copyright 2005 Storlink Inc.
-+ *
-+ *  This program is free software; you can redistribute  it and/or modify it
-+ *  under  the terms of  the GNU General  Public License as published by the
-+ *  Free Software Foundation;  either version 2 of the  License, or (at your
-+ *  option) any later version.
-+ *
-+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
-+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
-+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
-+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
-+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
-+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
-+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ *  You should have received a copy of the  GNU General Public License along
-+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
-+ *  675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#ifndef __GEMINI_GPIO_H
-+#define __GEMINI_GPIO_H
-+
-+#include <linux/ioctl.h>
-+
-+#define STATUS_HIGH   1
-+#define STATUS_LOW    0
-+#define DIRECT_OUT    1
-+#define DIRECT_IN     0
-+
-+#define EDGE_TRIG     0
-+#define RISING_EDGE   0
-+#define FALL_EDGE     1
-+#define SINGLE_EDGE   0
-+#define BOTH_EDGE     1
-+
-+#define LEVEL_TRIG    1
-+#define HIGH_ACTIVE   0
-+#define LOW_ACTIVE    1
-+
-+struct gemini_gpio_ioctl_data {
-+      __u32 pin;
-+      __u8 status;                    // status or pin direction
-+                                      // 0: status low or Input
-+                                      // 1: status high or Output
-+
-+      /* these member are used to config GPIO interrupt parameter */
-+      __u8    use_default;            // if not sure ,set this argument 1
-+      __u8    trig_type;              // 0/1:edge/level triger ?
-+      __u8    trig_polar;             // 0/1:rising/falling high/low active ?
-+      __u8    trig_both;              // 0/1:single/both detect both ?
-+};
-+
-+#define GEMINI_GPIO_IOCTL_BASE        'Z'
-+
-+#define GEMINI_SET_GPIO_PIN_DIR               _IOW (GEMINI_GPIO_IOCTL_BASE,16, struct gemini_gpio_ioctl_data)
-+#define       GEMINI_SET_GPIO_PIN_STATUS      _IOW (GEMINI_GPIO_IOCTL_BASE,17, struct gemini_gpio_ioctl_data)
-+#define       GEMINI_GET_GPIO_PIN_STATUS      _IOWR(GEMINI_GPIO_IOCTL_BASE,18, struct gemini_gpio_ioctl_data)
-+#define GEMINI_WAIT_GPIO_PIN_INT      _IOWR(GEMINI_GPIO_IOCTL_BASE,19, struct gemini_gpio_ioctl_data)
-+
-+
-+extern void init_gpio_int(__u32 pin,__u8 trig_type,__u8 trig_polar,__u8 trig_both);
-+extern int request_gpio_irq(int bit,void (*handler)(int),char level,char high,char both);
-+extern int free_gpio_irq(int bit);
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/gemini_i2s.h
-@@ -0,0 +1,169 @@
-+#ifndef __GEMINI_I2S_H__
-+#define __GEMINI_I2S_H__
-+#include <linux/ioctl.h>
-+#include <linux/types.h>
-+#include <asm/arch-sl2312/irqs.h>
-+
-+typedef __u16 UINT16;
-+typedef __u32 UINT32;
-+typedef __u8 UINT8;
-+typedef __u8 BOOL;
-+
-+/***************************************/
-+/* define GPIO module base address     */
-+/***************************************/
-+#define DMA_CONTROL_PHY_BASE  (IO_ADDRESS(SL2312_GENERAL_DMA_BASE))
-+#define DMA_CONTROL_SSP_BASE  (IO_ADDRESS(SL2312_SSP_CTRL_BASE))
-+#define SSP_INT                               IRQ_SSP
-+#define GPIO_BASE_ADDR      (IO_ADDRESS(SL2312_GPIO_BASE))
-+#define GPIO_BASE_ADDR1      (IO_ADDRESS(SL2312_GPIO_BASE1))
-+#define GLOBAL_BASE      (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+
-+/* define read/write register utility */
-+#define READ_SSP_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_SSP_BASE))
-+#define WRITE_SSP_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_SSP_BASE))
-+
-+#define READ_GPIO_REG(offset)                 (__raw_readl(offset+GPIO_BASE_ADDR))
-+#define WRITE_GPIO_REG(offset,val)    (__raw_writel(val,offset+GPIO_BASE_ADDR))
-+
-+#define READ_GPIO1_REG(offset)                        (__raw_readl(offset+GPIO_BASE_ADDR1))
-+#define WRITE_GPIO1_REG(offset,val)   (__raw_writel(val,offset+GPIO_BASE_ADDR1))
-+
-+#define READ_DMA_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_PHY_BASE))
-+#define WRITE_DMA_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_PHY_BASE))
-+
-+#define READ_GLOBAL_REG(offset)                       (__raw_readl(offset+GLOBAL_BASE))
-+#define WRITE_GLOBAL_REG(offset,val)  (__raw_writel(val,offset+GLOBAL_BASE))
-+
-+#define SSP_GPIO_INT          IRQ_GPIO
-+
-+#ifndef CONFIG_SL3516_ASIC
-+#define SSP_GPIO_INT_BIT    0x00000400                                //GPIO[10] : SLIC interrupt pin
-+
-+#define GPIO_EECK          0x00000040         /*   SCK: GPIO[06]   */
-+#define GPIO_EECS          0x00000080                 /*   SCS: GPIO[07]   */
-+#define GPIO_MISO          0x00000200         /*   SDO: GPIO[09]   receive from 6996*/
-+#define GPIO_MOSI          0x00000100         /*   SDI: GPIO[08]   send to 6996*/
-+#define GPIO_MISO_BIT  9
-+#else
-+#define SSP_GPIO_INT_BIT    0x00000001                                //GPIO[0] : SLIC interrupt pin
-+
-+//#if 0
-+//#define GPIO_EECK        0x80000000         /*   SCK: GPIO1[31]   */
-+//#define GPIO_EECS        0x40000000                 /*   SCS: GPIO1[30]   */
-+//#define GPIO_MISO        0x20000000         /*   SDO: GPIO1[29]   receive from 6996*/
-+//#define GPIO_MOSI        0x10000000         /*   SDI: GPIO1[28]   send to 6996*/
-+//#define GPIO_MISO_BIT       29
-+//#else
-+//#define GPIO_EECK        0x00000100         /*   SCK: GPIO1[08]   */
-+//#define GPIO_EECS        0x08000000                 /*   SCS: GPIO1[27]   */
-+//#define GPIO_MISO        0x00000080         /*   SDO: GPIO1[07]   receive from 6996*/
-+//#define GPIO_MOSI        0x00000200         /*   SDI: GPIO1[09]   send to 6996*/
-+//#define GPIO_MISO_BIT       7
-+//#endif
-+#endif
-+
-+
-+enum GPIO_REG
-+{
-+      GPIO_DATA_OUT           = 0x00,
-+      GPIO_DATA_IN            = 0x04,
-+      GPIO_PIN_DIR            = 0x08,
-+      GPIO_BY_PASS            = 0x0c,
-+      GPIO_DATA_SET           = 0x10,
-+      GPIO_DATA_CLEAR         = 0x14,
-+      GPIO_INT_ENABLE     = 0x20,
-+      GPIO_INT_RAWSTATE   = 0x24,
-+      GPIO_INT_MASKSTATE  = 0x28,
-+      GPIO_INT_MASK       = 0x2C,
-+      GPIO_INT_CLEAR      = 0x30,
-+      GPIO_INT_TRIGGER    = 0x34,
-+      GPIO_INT_BOTH       = 0x38,
-+      GPIO_INT_POLARITY   = 0x3C
-+};
-+
-+typedef struct
-+{
-+      UINT32 src_addr;
-+      UINT32 dst_addr;
-+      UINT32 llp;
-+      UINT32 ctrl_size;
-+      UINT32 owner;
-+}DMA_LLP_t;
-+
-+typedef struct
-+{
-+      UINT32 owner;
-+      UINT32 src_addr;
-+      UINT32 ctrl_size;
-+}IOCTL_LLP_t;
-+
-+typedef unsigned char byte;
-+typedef unsigned short word;
-+typedef unsigned long dword;
-+
-+/* DMA Registers */
-+#define       DMA_INT                                 0x00000000
-+#define       DMA_INT_TC                              0x00000004
-+#define       DMA_CFG                                 0x00000024
-+#define       DMA_INT_TC_CLR                          0x00000008
-+#define       DMA_TC                                          0x00000014
-+#define       DMA_CSR                                         0x00000024
-+#define       DMA_SYNC                                        0x00000028
-+
-+#define       DMA_CH2_CSR                             0x00000140
-+#define       DMA_CH2_CFG                             0x00000144
-+#define       DMA_CH2_SRC_ADDR                0x00000148
-+#define       DMA_CH2_DST_ADDR                0x0000014c
-+#define       DMA_CH2_LLP                             0x00000150
-+#define       DMA_CH2_SIZE                            0x00000154
-+
-+#define       DMA_CH3_CSR                             0x00000160
-+#define       DMA_CH3_CFG                             0x00000164
-+#define       DMA_CH3_SRC_ADDR                0x00000168
-+#define       DMA_CH3_DST_ADDR                0x0000016c
-+#define       DMA_CH3_LLP                             0x00000170
-+#define       DMA_CH3_SIZE                            0x00000174
-+
-+#define    SSP_DEVICE_ID                      0x00
-+#define    SSP_CTRL_STATUS                    0x04
-+#define          SSP_FRAME_CTRL           0x08
-+#define    SSP_BAUD_RATE            0x0c
-+#define    SSP_FRAME_CTRL2          0x10
-+#define    SSP_FIFO_CTRL            0x14
-+#define    SSP_TX_SLOT_VALID0       0x18
-+#define    SSP_TX_SLOT_VALID1       0x1c
-+#define    SSP_TX_SLOT_VALID2       0x20
-+#define    SSP_TX_SLOT_VALID3       0x24
-+#define    SSP_RX_SLOT_VALID0       0x28
-+#define    SSP_RX_SLOT_VALID1       0x2c
-+#define    SSP_RX_SLOT_VALID2       0x30
-+#define    SSP_RX_SLOT_VALID3       0x34
-+#define    SSP_SLOT_SIZE0           0x38
-+#define    SSP_SLOT_SIZE1           0x3c
-+#define    SSP_SLOT_SIZE2           0x40
-+#define    SSP_SLOT_SIZE3           0x44
-+#define    SSP_READ_PORT            0x48
-+#define    SSP_WRITE_PORT           0x4c
-+
-+
-+
-+#define SSP_I2S_INIT_BUF                      _IO  ('q', 0x00)
-+#define SSP_I2S_STOP_DMA                      _IO  ('q', 0x01)
-+#define SSP_I2S_FILE_LEN                      _IOW  ('q', 0x2, int)
-+/*
-+#define SSP_GET_HOOK_STATUS                   _IOR  ('q', 0xC0, int)
-+#define SSP_GET_LINEFEED                      _IOR  ('q', 0xC1, int)
-+#define SSP_SET_LINEFEED                      _IOW  ('q', 0xC2, int)
-+#define SSP_GET_REG                 _IOWR ('q', 0xC3, struct Ssp_reg *)
-+#define SSP_SET_REG                 _IOWR ('q', 0xC4, struct Ssp_reg *)
-+#define SSP_GEN_OFFHOOK_TONE          _IO   ('q', 0xC5)
-+#define SSP_GEN_BUSY_TONE                     _IO   ('q', 0xC6)
-+#define SSP_GEN_RINGBACK_TONE         _IO   ('q', 0xC7)
-+#define SSP_GEN_CONGESTION_TONE               _IO   ('q', 0xC8)
-+#define SSP_DISABLE_DIALTONE          _IO   ('q', 0xC9)
-+#define SSP_PHONE_RING_START          _IO   ('q', 0xCA)
-+*/
-+
-+
-+#endif //__GEMINI_I2S_H__
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/gemini_ssp.h
-@@ -0,0 +1,263 @@
-+/******************************************************************************
-+ *    gemini_ssp.h
-+ *
-+ *
-+ *****************************************************************************/
-+
-+#include <linux/types.h>
-+#include <asm/arch-sl2312/irqs.h>
-+#include <linux/phonedev.h>
-+#include <linux/telephony.h>
-+//#include "proslic.h"
-+
-+typedef __u16 UINT16;
-+typedef __u32 UINT32;
-+typedef __u8 UINT8;
-+typedef __u8 BOOL;
-+
-+#define TRUE 1
-+#define FALSE 0
-+
-+/***************************************/
-+/* define GPIO module base address     */
-+/***************************************/
-+#define DMA_CONTROL_PHY_BASE  (IO_ADDRESS(SL2312_GENERAL_DMA_BASE))
-+#define DMA_CONTROL_SSP_BASE  (IO_ADDRESS(SL2312_SSP_CTRL_BASE))
-+#define SSP_INT                               IRQ_SSP
-+#define GPIO_BASE_ADDR      (IO_ADDRESS(SL2312_GPIO_BASE))
-+#define GPIO_BASE_ADDR1      (IO_ADDRESS(SL2312_GPIO_BASE1))
-+#define GLOBAL_BASE      (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+
-+/* define read/write register utility */
-+#define READ_SSP_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_SSP_BASE))
-+#define WRITE_SSP_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_SSP_BASE))
-+
-+#define READ_GPIO_REG(offset)                 (__raw_readl(offset+GPIO_BASE_ADDR))
-+#define WRITE_GPIO_REG(offset,val)    (__raw_writel(val,offset+GPIO_BASE_ADDR))
-+
-+#define READ_GPIO1_REG(offset)                        (__raw_readl(offset+GPIO_BASE_ADDR1))
-+#define WRITE_GPIO1_REG(offset,val)   (__raw_writel(val,offset+GPIO_BASE_ADDR1))
-+
-+#define READ_DMA_REG(offset)                  (__raw_readl(offset+DMA_CONTROL_PHY_BASE))
-+#define WRITE_DMA_REG(offset,val)     (__raw_writel(val,offset+DMA_CONTROL_PHY_BASE))
-+
-+#define READ_GLOBAL_REG(offset)                       (__raw_readl(offset+GLOBAL_BASE))
-+#define WRITE_GLOBAL_REG(offset,val)  (__raw_writel(val,offset+GLOBAL_BASE))
-+
-+
-+#define SSP_GPIO_INT          IRQ_GPIO
-+
-+#ifndef CONFIG_SL3516_ASIC
-+#define SSP_GPIO_INT_BIT    0x00000400                                //GPIO[10] : SLIC interrupt pin
-+
-+#define GPIO_EECK          0x00000040         /*   SCK: GPIO[06]   */
-+#define GPIO_EECS          0x00000080                 /*   SCS: GPIO[07]   */
-+#define GPIO_MISO          0x00000200         /*   SDO: GPIO[09]   receive from 6996*/
-+#define GPIO_MOSI          0x00000100         /*   SDI: GPIO[08]   send to 6996*/
-+#define GPIO_MISO_BIT  9
-+#else
-+#define SSP_GPIO_INT_BIT    0x00000001                                //GPIO[0] : SLIC interrupt pin
-+
-+//#if 0
-+//#define GPIO_EECK        0x80000000         /*   SCK: GPIO1[31]   */
-+//#define GPIO_EECS        0x40000000                 /*   SCS: GPIO1[30]   */
-+//#define GPIO_MISO        0x20000000         /*   SDO: GPIO1[29]   receive from 6996*/
-+//#define GPIO_MOSI        0x10000000         /*   SDI: GPIO1[28]   send to 6996*/
-+//#define GPIO_MISO_BIT       29
-+//#else
-+//#define GPIO_EECK        0x00000100         /*   SCK: GPIO1[08]   */
-+//#define GPIO_EECS        0x08000000                 /*   SCS: GPIO1[27]   */
-+//#define GPIO_MISO        0x00000080         /*   SDO: GPIO1[07]   receive from 6996*/
-+//#define GPIO_MOSI        0x00000200         /*   SDI: GPIO1[09]   send to 6996*/
-+//#define GPIO_MISO_BIT       7
-+//#endif
-+#endif
-+
-+
-+enum GPIO_REG
-+{
-+      GPIO_DATA_OUT           = 0x00,
-+      GPIO_DATA_IN            = 0x04,
-+      GPIO_PIN_DIR            = 0x08,
-+      GPIO_BY_PASS            = 0x0c,
-+      GPIO_DATA_SET           = 0x10,
-+      GPIO_DATA_CLEAR         = 0x14,
-+      GPIO_INT_ENABLE     = 0x20,
-+      GPIO_INT_RAWSTATE   = 0x24,
-+      GPIO_INT_MASKSTATE  = 0x28,
-+      GPIO_INT_MASK       = 0x2C,
-+      GPIO_INT_CLEAR      = 0x30,
-+      GPIO_INT_TRIGGER    = 0x34,
-+      GPIO_INT_BOTH       = 0x38,
-+      GPIO_INT_POLARITY   = 0x3C
-+};
-+
-+
-+#define SPI_ADD_LEN        7                  // bits of Address
-+#define SPI_DAT_LEN        8                  // bits of Data
-+
-+
-+
-+//#ifdef MIDWAY_DIAG
-+#define       DAISY_MODE      1
-+#if (DAISY_MODE==1)
-+#define NUMBER_OF_CHAN        2
-+#else
-+#define NUMBER_OF_CHAN        1
-+#endif
-+#define LLP_SIZE   8
-+#define SBUF_SIZE  512 //0xff0 //2560
-+#define DBUF_SIZE  SBUF_SIZE*NUMBER_OF_CHAN //0xff0 //2560
-+#define TBUF_SIZE  (LLP_SIZE)*DBUF_SIZE
-+#define DESC_NUM   1
-+#define DTMF_NUM   20
-+
-+/* define owner bit of SSP */
-+//data into SSP and transfer to AP==> SSP_Rx
-+//data out of SSP and transfer to SLIC==> SSP_Tx
-+#define CPU           0
-+#define DMA           1
-+
-+#define DMA_DEMO   0
-+#define DMA_NDEMO  1
-+//#define DMA_NONE   2
-+
-+enum exceptions {
-+      PROSLICiNSANE,
-+      TIMEoUTpOWERuP,
-+      TIMEoUTpOWERdOWN,
-+      POWERlEAK,
-+      TIPoRrINGgROUNDsHORT,
-+      POWERaLARMQ1,
-+      POWERaLARMQ2,
-+      POWERaLARMQ3,
-+      POWERaLARMQ4,
-+      POWERaLARMQ5,
-+      OWERaLARMQ6,
-+      CM_CAL_ERR
-+};
-+
-+typedef struct
-+{
-+      UINT32 src_addr;
-+      UINT32 dst_addr;
-+      UINT32 llp;
-+      UINT32 ctrl_size;
-+}DMA_LLP_t;
-+
-+typedef struct {
-+      unsigned int own ;
-+      char  *tbuf;
-+      //UINT32 *LinkAddrT;
-+      DMA_LLP_t LLPT[LLP_SIZE];
-+}DMA_Tx_t;
-+
-+typedef struct {
-+      unsigned int own ;
-+      char  *rbuf;
-+      //UINT32 *LinkAddrR;
-+      DMA_LLP_t LLPR[LLP_SIZE];
-+}DMA_Rx_t;
-+
-+//typedef struct {
-+//    //UINT32 init_stat;
-+//    struct chipStruct chipData ; /* Represents a proslics state, cached information, and timers */
-+//    struct phone_device p;
-+//
-+//
-+//}SSP_SLIC;
-+
-+
-+
-+/* DMA Registers */
-+#define       DMA_INT                                 0x00000000
-+#define       DMA_INT_TC                              0x00000004
-+#define       DMA_CFG                                 0x00000024
-+#define       DMA_INT_TC_CLR                          0x00000008
-+#define       DMA_TC                                          0x00000014
-+#define       DMA_CSR                                         0x00000024
-+#define       DMA_SYNC                                        0x00000028
-+
-+#define       DMA_CH2_CSR                             0x00000140
-+#define       DMA_CH2_CFG                             0x00000144
-+#define       DMA_CH2_SRC_ADDR                0x00000148
-+#define       DMA_CH2_DST_ADDR                0x0000014c
-+#define       DMA_CH2_LLP                             0x00000150
-+#define       DMA_CH2_SIZE                            0x00000154
-+
-+#define       DMA_CH3_CSR                             0x00000160
-+#define       DMA_CH3_CFG                             0x00000164
-+#define       DMA_CH3_SRC_ADDR                0x00000168
-+#define       DMA_CH3_DST_ADDR                0x0000016c
-+#define       DMA_CH3_LLP                             0x00000170
-+#define       DMA_CH3_SIZE                            0x00000174
-+
-+#define    SSP_DEVICE_ID                      0x00
-+#define    SSP_CTRL_STATUS                    0x04
-+#define          SSP_FRAME_CTRL           0x08
-+#define    SSP_BAUD_RATE            0x0c
-+#define    SSP_FRAME_CTRL2          0x10
-+#define    SSP_FIFO_CTRL            0x14
-+#define    SSP_TX_SLOT_VALID0       0x18
-+#define    SSP_TX_SLOT_VALID1       0x1c
-+#define    SSP_TX_SLOT_VALID2       0x20
-+#define    SSP_TX_SLOT_VALID3       0x24
-+#define    SSP_RX_SLOT_VALID0       0x28
-+#define    SSP_RX_SLOT_VALID1       0x2c
-+#define    SSP_RX_SLOT_VALID2       0x30
-+#define    SSP_RX_SLOT_VALID3       0x34
-+#define    SSP_SLOT_SIZE0           0x38
-+#define    SSP_SLOT_SIZE1           0x3c
-+#define    SSP_SLOT_SIZE2           0x40
-+#define    SSP_SLOT_SIZE3           0x44
-+#define    SSP_READ_PORT            0x48
-+#define    SSP_WRITE_PORT           0x4c
-+
-+
-+void printFreq_Revision(int num);
-+void SLIC_SPI_write(int num, UINT8 ,UINT8);
-+UINT8 SLIC_SPI_read(int num, UINT8);
-+void SLIC_SPI_write_bit(char);
-+void SLIC_SPI_ind_write(int num, UINT8, UINT16);
-+UINT16 SLIC_SPI_ind_read(int num, UINT8);
-+void SLIC_SPI_CS_enable(UINT8);
-+unsigned int SLIC_SPI_read_bit(void);
-+void SLIC_SPI_pre_st(void);
-+UINT32 ssp_init(void);
-+UINT16 SLIC_SPI_get_identifier(int num);
-+int selfTest(int num);
-+void exception (int num, enum exceptions e);
-+int SLIC_init(int num);
-+UINT8 version(int num);
-+UINT8 chipType (int num);
-+void SLIC_init_ind_reg_set(int num);
-+UINT8 powerUp(int num);
-+UINT8 powerLeakTest(int num);
-+void SLIC_init_reg_set(int num);
-+int calibrate(int num);
-+void goActive(int num);
-+void clearInterrupts(int num);
-+void setState(int num, int);
-+UINT8 loopStatus(int num);
-+int verifyIndirectRegisters(int num);
-+int verifyIndirectReg(int num, UINT8 , UINT16);
-+void sendProSLICID(int num);
-+void disableOscillators(int num);
-+UINT8 checkSum(int num, char * string );
-+void fskInitialization (int num);
-+void fskByte(int num, UINT8 c);
-+void waitForInterrupt (int num);
-+//void findNumber(void);
-+UINT8 dtmfAction(int num);
-+UINT8 digit(int num);
-+void interrupt_init(void);
-+//void gemini_slic_isr (int );
-+int groundShort(int num);
-+void clearAlarmBits(int num);
-+void stopRinging(int num);
-+void activateRinging(int num);
-+void initializeLoopDebounceReg(int num);
-+void busyJapan(int num) ;
-+void ringBackJapan(int num) ;
-+void stateMachine(int num);
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/hardware.h
-@@ -0,0 +1,47 @@
-+/*
-+ *  linux/include/asm-arm/arch-epxa10/hardware.h
-+ *
-+ *  This file contains the hardware definitions of the Integrator.
-+ *
-+ *  Copyright (C) 1999 ARM Limited.
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __ASM_ARCH_HARDWARE_H
-+#define __ASM_ARCH_HARDWARE_H
-+
-+#include <asm/arch/platform.h>
-+
-+#define pcibios_assign_all_busses()   1
-+
-+/*
-+ * Where in virtual memory the IO devices (timers, system controllers
-+ * and so on)
-+ *
-+ * macro to get at IO space when running virtually
-+*/
-+
-+#define IO_ADDRESS(x)      (((x&0xfff00000)>>4)|(x & 0x000fffff)|0xF0000000)
-+#define FLASH_VBASE         0xFE000000
-+#define FLASH_SIZE 0x1000000// 8M
-+#define FLASH_START         SL2312_FLASH_BASE
-+#define FLASH_VADDR(x)      ((x & 0x00ffffff)|0xFE000000)       // flash virtual address
-+
-+#define PCIBIOS_MIN_IO                                        0x100           // 0x000-0x100 AHB reg and PCI config, data
-+#define PCIBIOS_MIN_MEM                                       0
-+
-+#endif
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/int_ctrl.h
-@@ -0,0 +1,171 @@
-+/*
-+ *
-+ *  This file contains the register definitions for the Excalibur
-+ *  Timer TIMER00.
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef __INT_CTRL_H
-+#define __INT_CTRL_H
-+
-+#define PCI_IRQ_OFFSET                          64    /* PCI start IRQ number */
-+#define FIQ_OFFSET                32
-+
-+#define IRQ_SOURCE(base_addr)   (INT_CTRL_TYPE(base_addr  + 0x00))
-+#define IRQ_MASK(base_addr)     (INT_CTRL_TYPE (base_addr  + 0x04 ))
-+#define IRQ_CLEAR(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x08 ))
-+#define IRQ_TMODE(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x0C ))
-+#define IRQ_TLEVEL(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x10 ))
-+#define IRQ_STATUS(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x14 ))
-+#define FIQ_SOURCE(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x20 ))
-+#define FIQ_MASK(base_addr)     (INT_CTRL_TYPE (base_addr  + 0x24 ))
-+#define FIQ_CLEAR(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x28 ))
-+#define FIQ_TMODE(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x2C ))
-+#define FIQ_LEVEL(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x30 ))
-+#define FIQ_STATUS(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x34 ))
-+
-+#ifdef CONFIG_SL3516_ASIC
-+#define       IRQ_SERIRQ0_OFFSET                      30
-+#define       IRQ_PCID_OFFSET                         29
-+#define       IRQ_PCIC_OFFSET                         28
-+#define       IRQ_PCIB_OFFSET                         27
-+#define IRQ_PWR_OFFSET                                        26
-+#define IRQ_CIR_OFFSET                                                25
-+#define       IRQ_GPIO2_OFFSET                        24
-+#define       IRQ_GPIO1_OFFSET                        23
-+#define       IRQ_GPIO_OFFSET                         22
-+#define       IRQ_SSP_OFFSET                          21
-+#define IRQ_LPC_OFFSET                      20
-+#define IRQ_LCD_OFFSET                      19
-+#define       IRQ_UART_OFFSET                         18
-+#define       IRQ_RTC_OFFSET                                  17
-+#define       IRQ_TIMER3_OFFSET                       16
-+#define       IRQ_TIMER2_OFFSET                       15
-+#define       IRQ_TIMER1_OFFSET                       14
-+#define IRQ_FLASH_OFFSET                                      12
-+#define       IRQ_USB1_OFFSET                         11
-+#define IRQ_USB0_OFFSET                                               10
-+#define       IRQ_DMA_OFFSET                          9
-+#define       IRQ_PCI_OFFSET                          8
-+#define       IRQ_IPSEC_OFFSET                        7
-+#define       IRQ_RAID_OFFSET                     6
-+#define       IRQ_IDE1_OFFSET                         5
-+#define       IRQ_IDE0_OFFSET                         4
-+#define       IRQ_WATCHDOG_OFFSET                 3
-+#define       IRQ_GMAC1_OFFSET                    2
-+#define IRQ_GMAC0_OFFSET                                      1
-+#define       IRQ_CPU0_IP_IRQ_OFFSET              0
-+
-+#define       IRQ_SERIRQ0_MASK                        (1<<30)
-+#define IRQ_PCID_MASK                                 (1<<29)
-+#define IRQ_PCIC_MASK                                 (1<<28)
-+#define IRQ_PCIB_MASK                                 (1<<27)
-+#define IRQ_PWR_MASK                                  (1<<26)
-+#define IRQ_CIR_MASK                                          (1<<25)
-+#define       IRQ_GPIO2_MASK                          (1<<24)
-+#define       IRQ_GPIO1_MASK                          (1<<23)
-+#define       IRQ_GPIO_MASK                       (1<<22)
-+#define       IRQ_SSP_MASK                        (1<<21)
-+#define IRQ_LPC_MASK                        (1<<20)
-+#define IRQ_LCD_MASK                        (1<<19)
-+#define       IRQ_UART_MASK                       (1<<18)
-+#define       IRQ_RTC_MASK                                (1<<17)
-+#define       IRQ_TIMER3_MASK                     (1<<16)
-+#define       IRQ_TIMER2_MASK                     (1<<15)
-+#define       IRQ_TIMER1_MASK                     (1<<14)
-+#define IRQ_FLASH_MASK                                            (1<<12)
-+#define       IRQ_USB1_MASK                       (1<<11)
-+#define IRQ_USB0_MASK                                     (1<<10)
-+#define       IRQ_DMA_MASK                        (1<< 9)
-+#define       IRQ_PCI_MASK                        (1<< 8)
-+#define       IRQ_IPSEC_MASK                              (1<< 7)
-+#define       IRQ_RAID_MASK                       (1<< 6)
-+#define       IRQ_IDE1_MASK                       (1<< 5)
-+#define       IRQ_IDE0_MASK                       (1<< 4)
-+#define       IRQ_WATCHDOG_MASK                   (1<< 3)
-+#define       IRQ_GMAC1_MASK                      (1<< 2)
-+#define IRQ_GMAC0_MASK                                            (1<< 1)
-+#define       IRQ_CPU0_IP_IRQ_MASK                (1<< 0)
-+#else
-+#define       IRQ_SERIRQ0_OFFSET                      30
-+#define       IRQ_PCID_OFFSET                         29
-+#define       IRQ_PCIC_OFFSET                         28
-+#define       IRQ_PCIB_OFFSET                         27
-+#define IRQ_PWR_OFFSET                                        26
-+#define IRQ_CIR_OFFSET                                                25
-+#define       IRQ_GPIO2_OFFSET                        24
-+#define       IRQ_GPIO1_OFFSET                        23
-+#define       IRQ_GPIO_OFFSET                         22
-+#define       IRQ_SSP_OFFSET                          21
-+#define IRQ_LPC_OFFSET                      20
-+#define IRQ_LCD_OFFSET                      19
-+#define       IRQ_UART_OFFSET                         18
-+#define       IRQ_RTC_OFFSET                                  17
-+#define       IRQ_TIMER3_OFFSET                       16
-+#define       IRQ_TIMER2_OFFSET                       15
-+#define       IRQ_TIMER1_OFFSET                       14
-+#define IRQ_FLASH_OFFSET                                      12
-+#define       IRQ_USB1_OFFSET                         11
-+#define IRQ_USB0_OFFSET                                               10
-+#define       IRQ_DMA_OFFSET                          9
-+#define       IRQ_PCI_OFFSET                          8
-+#define       IRQ_IPSEC_OFFSET                        7
-+#define       IRQ_RAID_OFFSET                     6
-+#define       IRQ_IDE1_OFFSET                         5
-+#define       IRQ_IDE0_OFFSET                         4
-+#define       IRQ_WATCHDOG_OFFSET                 3
-+#define       IRQ_GMAC1_OFFSET                    2
-+#define IRQ_GMAC0_OFFSET                                      1
-+#define       IRQ_CPU0_IP_IRQ_OFFSET              0
-+
-+#define       IRQ_SERIRQ0_MASK                        (1<<30)
-+#define IRQ_PCID_MASK                                 (1<<29)
-+#define IRQ_PCIC_MASK                                 (1<<28)
-+#define IRQ_PCIB_MASK                                 (1<<27)
-+#define IRQ_PWR_MASK                                  (1<<26)
-+#define IRQ_CIR_MASK                                          (1<<25)
-+#define       IRQ_GPIO2_MASK                          (1<<24)
-+#define       IRQ_GPIO1_MASK                          (1<<23)
-+#define       IRQ_GPIO_MASK                       (1<<22)
-+#define       IRQ_SSP_MASK                        (1<<21)
-+#define IRQ_LPC_MASK                        (1<<20)
-+#define IRQ_LCD_MASK                        (1<<19)
-+#define       IRQ_UART_MASK                       (1<<18)
-+#define       IRQ_RTC_MASK                                (1<<17)
-+#define       IRQ_TIMER3_MASK                     (1<<16)
-+#define       IRQ_TIMER2_MASK                     (1<<15)
-+#define       IRQ_TIMER1_MASK                     (1<<14)
-+#define IRQ_FLASH_MASK                                            (1<<12)
-+#define       IRQ_USB1_MASK                       (1<<11)
-+#define IRQ_USB0_MASK                                     (1<<10)
-+#define       IRQ_DMA_MASK                        (1<< 9)
-+#define       IRQ_PCI_MASK                        (1<< 8)
-+#define       IRQ_IPSEC_MASK                              (1<< 7)
-+#define       IRQ_RAID_MASK                       (1<< 6)
-+#define       IRQ_IDE1_MASK                       (1<< 5)
-+#define       IRQ_IDE0_MASK                       (1<< 4)
-+#define       IRQ_WATCHDOG_MASK                   (1<< 3)
-+#define       IRQ_GMAC1_MASK                      (1<< 2)
-+#define IRQ_GMAC0_MASK                                            (1<< 1)
-+#define       IRQ_CPU0_IP_IRQ_MASK                (1<< 0)
-+#endif
-+
-+
-+#endif /* __INT_CTRL_H */
-+
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/io.h
-@@ -0,0 +1,50 @@
-+/*
-+ *  linux/include/asm-arm/arch-epxa10db/io.h
-+ *
-+ *  Copyright (C) 1999 ARM Limited
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __ASM_ARM_ARCH_IO_H
-+#define __ASM_ARM_ARCH_IO_H
-+
-+#define IO_SPACE_LIMIT 0xffffffff
-+
-+
-+/*
-+ * Generic virtual read/write
-+ */
-+/*
-+#define __arch_getw(a)                (*(volatile unsigned short *)(a))
-+#define __arch_putw(v,a)      (*(volatile unsigned short *)(a) = (v))
-+*/
-+/*#define outsw   __arch_writesw
-+#define outsl   __arch_writesl
-+#define outsb   __arch_writesb
-+#define insb    __arch_readsb
-+#define insw    __arch_readsw
-+#define insl    __arch_readsl*/
-+
-+#define __io(a)                       (a)
-+#define __mem_pci(a)            (a)
-+/*
-+#define __arch_getw(a)                        (*(volatile unsigned short  *)(a))
-+#define __arch_putw(v,a)              (*(volatile unsigned short *)(a) = (v))
-+*/
-+#define iomem_valid_addr(off,size) (1)
-+#define iomem_to_phys(off) (off)
-+
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/ipi.h
-@@ -0,0 +1,189 @@
-+/*
-+ *  linux/include/asm-arm/arch-sl2312/system.h
-+ *
-+ *  Copyright (C) 1999 ARM Limited
-+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __ASM_ARCH_IPI_H
-+#define __ASM_ARCH_IPI_H
-+#include <asm/io.h>
-+
-+//#define spin_lock(x)        spin_lock_dt(x)
-+//#define spin_unlock(x)      spin_unlock_dt(x)
-+
-+#define SWAP_OFFSET                                                   0x400000
-+#define SWAP_SIZE                                                     0x400000
-+
-+#define SHARE_MEM_ADDR                                                0x2000000
-+#define SHARE_MEM_SIZE                                                1024*1024
-+
-+
-+//--> Add by jason for IPI testing
-+// memory layout for maste & slave bin
-+#define MASTERTEXT      0x8000
-+#define SLAVETEXT             0x108000
-+#define SHARESIZE             0x4000
-+#define SHAREADDR             SHARE_MEM_ADDR // starting 8M
-+
-+// CPU1 reset release
-+#define GLOBAL_BASE           IO_ADDRESS(0x40000000)
-+#define GLOBAL_SOFTRESET      (GLOBAL_BASE + 0x0C)
-+#define CPU1_RESET_BIT_MASK     0x40000000
-+
-+// IPI , need to redefine the folliwing,  bug
-+#define CPU0_STATUS                   (GLOBAL_BASE + 0x0038)
-+#define CPU1_STATUS                   (GLOBAL_BASE + 0x003C)
-+#define CPU_IPI_BIT_MASK    0x80000000
-+
-+/* Your basic SMP spinlocks, allowing only a single CPU anywhere
-+*/
-+typedef struct {
-+       volatile unsigned int lock;
-+} spinlock_dt;
-+
-+
-+#define         MASTER_BIT      0x01
-+#define         SLAVE_BIT       0x02
-+#define         HEART_BIT       0x04
-+#define         IPI0_IRQ_BIT    0x08
-+#define         IPI0_FIQ_BIT    0x10
-+#define         IPI1_IRQ_BIT    0x20
-+#define         IPI1_FIQ_BIT    0x40
-+
-+#define IRQ     0
-+#define FIQ     1
-+#define DONE    0xff
-+
-+#define         CPU0            0x0
-+#define         CPU1            0x1
-+
-+#define         MAXCHAR         128*1024
-+typedef struct  {
-+       int flag;
-+       int uart_flag;
-+       int cnt;
-+       spinlock_dt lk;
-+       char message[MAXCHAR];
-+}s_mailbox;
-+
-+// JScale proj definition
-+typedef struct {
-+      u16             type;                           // message Type
-+      u16             length;                         // message length, including message header
-+} IPC_MSG_HDR_T;
-+
-+typedef struct{
-+      IPC_MSG_HDR_T   hdr;
-+      u32                             input_location;
-+      u32                             input_size;
-+      u32                             output_location;
-+      u16                     ScaledImageWidth;
-+      u16                     ScaledImageHeight;
-+      u8                      ScaledImageQuality;
-+      u8                      MaintainResultionRatio;
-+      u8                      TwoStepScaling;
-+      u8                      InputFormat;
-+      u8                              verbose;
-+      u8                              reserved[3];
-+} JSCALE_REQ_T;
-+
-+typedef struct{
-+      IPC_MSG_HDR_T   hdr;
-+      u32                             status;
-+      u32                             code;
-+      u32                             output_size;
-+} JSCALE_RSP_T;
-+
-+#define IPC_JSCALE_REQ_MSG                    0       // JScale request from CPU-0 to CPU-1
-+#define IPC_JSCALE_RSP_MSG                    1       // JScale response from CPU-1 to CPU-0
-+
-+enum {
-+      JSCALE_STATUS_OK = 0,
-+      JSCALE_UNKNOWN_MSG_TYPE,
-+      JSCALE_FAILED_FILE_SIZE,
-+      JSCALE_FAILED_MALLOC,
-+      JSCALE_FAILED_FORMAT,
-+      JSCALE_DECODE_ERROR,
-+      JSCALE_BUSY,
-+};
-+// <-- JScale
-+
-+#define GEMINI_IPI_IOCTL_BASE 'Z'
-+#define GEMINI_IPI_JSCALE_REQ         _IOW (GEMINI_IPI_IOCTL_BASE,0,JSCALE_REQ_T)
-+#define GEMINI_IPI_JSCALE_STAT                _IOR (GEMINI_IPI_IOCTL_BASE,1,JSCALE_RSP_T)
-+
-+
-+/*
-+* Simple spin lock operations.
-+*
-+*/
-+
-+#define spin_is_locked_dt(x)((x)->lock != 0)
-+
-+static inline int test_and_set_dt(spinlock_dt *lock)
-+{
-+unsigned long tmp;
-+__asm__ __volatile__(
-+"swp     %0, %2, [%1]\n"
-+: "=&r" (tmp)
-+: "r" (&lock->lock), "r" (1)
-+: "cc", "memory");
-+
-+return tmp;
-+}
-+
-+static inline void spin_lock_dt(spinlock_dt *lock)
-+{
-+
-+unsigned long tmp;
-+__asm__ __volatile__(
-+"1:     ldr   %0, [%1]\n"
-+"teq     %0, #0\n"
-+"swpeq   %0, %2, [%1]\n"
-+"       teqeq   %0, #0\n"
-+"       bne     1b"
-+       : "=&r" (tmp)
-+       : "r" (&lock->lock), "r" (1)
-+       : "cc", "memory");
-+}
-+
-+static inline void spin_unlock_dt(spinlock_dt *lock)
-+{
-+       __asm__ __volatile__(
-+"       str     %1, [%0]"
-+       :
-+       : "r" (&lock->lock), "r" (0)
-+       : "cc", "memory");
-+}
-+
-+static inline int getcpuid(void)
-+{
-+       int cpuid;
-+
-+      __asm__(
-+"mrc p8, 0, r0, c0, c0, 0\n"
-+"mov %0, r0"
-+       :"=r"(cpuid)
-+       :
-+       :"r0");
-+       return (cpuid & 0x07);
-+}
-+
-+
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/irq.h
-@@ -0,0 +1,23 @@
-+/*
-+ *  linux/include/asm-arm/arch-sl2312/irq.h
-+ *
-+ *  Copyright (C) 1999 ARM Limited
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+ // Since we have PCI interrupt which the interrupt line is pseudo
-+ // we need do some fixup
-+int fixup_irq(int irq);
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/irqs.h
-@@ -0,0 +1,102 @@
-+/*
-+ *  linux/include/asm-arm/arch-camelot/irqs.h
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+/* Use the Excalibur chip definitions */
-+#define INT_CTRL_TYPE
-+#include "asm/arch/int_ctrl.h"
-+
-+#ifdef CONFIG_SL3516_ASIC
-+#define       IRQ_SERIRQ_MAX                                  31
-+#define       IRQ_SERIRQ1                                             31
-+#define       IRQ_SERIRQ0                     30
-+#define       IRQ_PCID                                29
-+#define       IRQ_PCIC                        28
-+#define       IRQ_PCIB                                27
-+#define IRQ_PWR                                                       26
-+#define IRQ_CIR                                                       25
-+#define       IRQ_GPIO2                       24
-+#define       IRQ_GPIO1                       23
-+#define       IRQ_GPIO                                22
-+#define       IRQ_SSP                         21
-+#define IRQ_LPC                         20
-+#define IRQ_LCD                         19
-+#define       IRQ_UART                                18
-+#define       IRQ_RTC                                 17
-+#define       IRQ_TIMER3                      16
-+#define       IRQ_TIMER2                      15
-+#define       IRQ_TIMER1                      14
-+#define IRQ_FLASH                                             12
-+#define       IRQ_USB1                        11
-+#define IRQ_USB0                                              10
-+#define       IRQ_DMA                         9
-+#define       IRQ_PCI                                 8
-+#define       IRQ_IPSEC                               7
-+#define       IRQ_RAID                        6
-+#define       IRQ_IDE1                        5
-+#define       IRQ_IDE0                                4
-+#define       IRQ_WATCHDOG                    3
-+#define       IRQ_GMAC1                       2
-+#define IRQ_GMAC0                                             1
-+#define       IRQ_CPU0_IP_IRQ                 0
-+#else
-+#define       IRQ_SERIRQ_MAX                                  31
-+#define       IRQ_SERIRQ1                                             31
-+#define       IRQ_SERIRQ0                     30
-+#define       IRQ_PCID                                29
-+#define       IRQ_PCIC                        28
-+#define       IRQ_PCIB                                27
-+#define IRQ_PWR                                                       26
-+#define IRQ_CIR                                                       25
-+#define       IRQ_GPIO2                       24
-+#define       IRQ_GPIO1                       23
-+#define       IRQ_GPIO                                22
-+#define       IRQ_SSP                         21
-+#define IRQ_LPC                         20
-+#define IRQ_LCD                         19
-+#define       IRQ_UART                                18
-+#define       IRQ_RTC                                 17
-+#define       IRQ_TIMER3                      16
-+#define       IRQ_TIMER2                      15
-+#define       IRQ_TIMER1                      14
-+#define IRQ_FLASH                                             12
-+#define       IRQ_USB1                        11
-+#define IRQ_USB0                                              10
-+#define       IRQ_DMA                         9
-+#define       IRQ_PCI                                 8
-+#define       IRQ_IPSEC                               7
-+#define       IRQ_RAID                        6
-+#define       IRQ_IDE1                        5
-+#define       IRQ_IDE0                                4
-+#define       IRQ_WATCHDOG                    3
-+#define       IRQ_GMAC1                       2
-+#define IRQ_GMAC0                                             1
-+#endif
-+
-+#define ARCH_TIMER_IRQ                               IRQ_TIMER2   /* for MV 4.0 */
-+
-+#define IRQ_PCI_INTA                                 PCI_IRQ_OFFSET + 0
-+#define IRQ_PCI_INTB                                 PCI_IRQ_OFFSET + 1
-+#define IRQ_PCI_INTC                                 PCI_IRQ_OFFSET + 2
-+#define IRQ_PCI_INTD                                 PCI_IRQ_OFFSET + 3
-+
-+#define NR_IRQS                           (IRQ_PCI_INTD + 4)
-+
-+
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/it8712.h
-@@ -0,0 +1,24 @@
-+
-+#ifndef __IT8712_H__
-+#define __IT8712_H__
-+
-+#include "asm/arch/sl2312.h"
-+
-+#define IT8712_IO_BASE                        SL2312_LPC_IO_BASE
-+// Device LDN
-+#define LDN_SERIAL1                           0x01
-+#define LDN_SERIAL2                           0x02
-+#define LDN_PARALLEL                  0x03
-+#define LDN_KEYBOARD                  0x05
-+#define LDN_MOUSE                             0x06
-+#define LDN_GPIO                              0x07
-+
-+#define IT8712_UART1_PORT             0x3F8
-+#define IT8712_UART2_PORT             0x2F8
-+
-+#define IT8712_GPIO_BASE              0x800   // 0x800-0x804 for GPIO set1-set5
-+
-+void LPCSetConfig(char LdnNumber, char Index, char data);
-+char LPCGetConfig(char LdnNumber, char Index);
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/memory.h
-@@ -0,0 +1,38 @@
-+/*
-+ *  linux/include/asm-arm/arch-sl2312/memory.h
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __ASM_ARCH_MMU_H
-+#define __ASM_ARCH_MMU_H
-+
-+/*
-+ * Physical DRAM offset.
-+ */
-+#define PHYS_OFFSET   UL(0x00000000)
-+
-+/*
-+ * Virtual view <-> DMA view memory address translations
-+ * virt_to_bus: Used to translate the virtual address to an
-+ *              address suitable to be passed to set_dma_addr
-+ * bus_to_virt: Used to convert an address for DMA operations
-+ *              to an address that the kernel can use.
-+ */
-+#define __virt_to_bus(x)      (x - PAGE_OFFSET + /*SDRAM_BASE*/0)
-+#define __bus_to_virt(x)      (x - /*SDRAM_BASE*/0 + PAGE_OFFSET)
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/param.h
-@@ -0,0 +1,20 @@
-+/*
-+ *  linux/include/asm-arm/arch-epxa10db/param.h
-+ *
-+ *  Copyright (C) 1999 ARM Limited
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/pci.h
-@@ -0,0 +1,18 @@
-+
-+#ifndef __SL2312_PCI_H__
-+#define __SL2312_PCI_H__
-+
-+#define SL2312_PCI_PMC                                0x40
-+#define SL2312_PCI_PMCSR                      0x44
-+#define SL2312_PCI_CTRL1                      0x48
-+#define SL2312_PCI_CTRL2                      0x4c
-+#define SL2312_PCI_MEM1_BASE_SIZE     0x50
-+#define SL2312_PCI_MEM2_BASE_SIZE     0x54
-+#define SL2312_PCI_MEM3_BASE_SIZE     0x58
-+
-+
-+void sl2312_pci_mask_irq(unsigned int irq);
-+void sl2312_pci_unmask_irq(unsigned int irq);
-+int sl2312_pci_get_int_src(void);
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/platform.h
-@@ -0,0 +1,7 @@
-+#ifndef PLATFORM_H
-+#define PLATFORM_H
-+#include "sl2312.h"
-+
-+#define MAXIRQNUM 68
-+#endif
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/preempt.h
-@@ -0,0 +1,63 @@
-+/*
-+ * include/asm-arm/arch-sl2312/preempt.h
-+ *
-+ * Timing support for preempt-stats, kfi, ilatency patches
-+ *
-+ * Author: dsingleton <dsingleton@mvista.com>
-+ *
-+ * 2001-2004 (c) MontaVista Software, Inc. This file is licensed under
-+ * the terms of the GNU General Public License version 2. This program
-+ * is licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ */
-+
-+#ifndef _ASM_ARCH_PREEMT_H
-+#define _ASM_ARCH_PREEMT_H
-+
-+#include <asm/arch/hardware.h>
-+#include <asm/arch/sl2312.h>
-+
-+static inline unsigned long clock_diff(unsigned long start, unsigned long stop)
-+{
-+        return (start - stop);
-+}
-+
-+static inline unsigned int readclock(void)
-+{
-+      unsigned int    x;
-+
-+      x = readl(IO_ADDRESS(SL2312_TIMER2_BASE));
-+      return x;
-+}
-+
-+static inline unsigned __ticks_per_usec(void)
-+{
-+#ifdef CONFIG_SL3516_ASIC
-+      unsigned int ahb_clock_rate_base=130;  /* unit = MHz*/
-+      unsigned int reg_v=0;
-+      unsigned int ticks_usec;
-+
-+      reg_v = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+4)));
-+      reg_v >>=15;
-+      ticks_usec = (ahb_clock_rate_base + (reg_v & 0x07)*10)>>2;
-+
-+#else
-+      unsigned int ticks_usec=20;
-+#endif
-+
-+    return ticks_usec;
-+}
-+
-+/*
-+ * timer 1 runs @ 6Mhz  6 ticks = 1 microsecond
-+ * and is configed as a count down timer.
-+ */
-+#define TICKS_PER_USEC                    __ticks_per_usec()
-+#define ARCH_PREDEFINES_TICKS_PER_USEC
-+
-+#define clock_to_usecs(x)         ((x) / TICKS_PER_USEC)
-+
-+#define INTERRUPTS_ENABLED(x)   (!(x & PSR_I_BIT))
-+
-+#endif
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/sl2312.h
-@@ -0,0 +1,254 @@
-+#ifndef __sl2312_h
-+#define __sl2312_h
-+
-+/****************************************************************************
-+ * Copyright  Storlink Corp 2002-2003.  All rights reserved.                *
-+ *--------------------------------------------------------------------------*
-+ * Name:board.s                                                             *
-+ * Description:  SL231x specfic define                                      *
-+ * Author: Plus Chen                                                        *
-+ * Version: 0.9 Create
-+ ****************************************************************************/
-+
-+/*
-+  CPE address map;
-+
-+               +====================================================
-+    0x00000000 | FLASH
-+    0x0FFFFFFF |
-+               |====================================================
-+    0x10000000 | SDRAM
-+    0x1FFFFFFF |
-+               |====================================================
-+    0x20000000 | Global Registers        0x20000000-0x20FFFFFF
-+               | EMAC and DMA            0x21000000-0x21FFFFFF
-+               | UART Module             0x22000000-0x22FFFFFF
-+               | Timer Module            0x23000000-0x23FFFFFF
-+               | Interrupt Module        0x24000000-0x24FFFFFF
-+               | RTC Module              0x25000000-0x25FFFFFF
-+               | LPC Host Controller     0x26000000-0x26FFFFFF
-+               | LPC Peripherial IO      0x27000000-0x27FFFFFF
-+               | WatchDog Timer          0x28000000-0x28FFFFFF
-+    0x2FFFFFFF | Reserved                0x29000000-0x29FFFFFF
-+               |=====================================================
-+    0x30000000 | PCI IO, Configuration Registers
-+    0x3FFFFFFF |
-+               |=====================================================
-+    0x40000000 | PCI Memory
-+    0x4FFFFFFF |
-+               |=====================================================
-+    0x50000000 | Ethernet MAC and DMA    0x50000000-0x50FFFFFF
-+               | Security and DMA        0x51000000-0x51FFFFFF
-+               | IDE Channel 0 Register  0x52000000-0x527FFFFF
-+               | IDE Channel 1 Register  0x52800000-0x52FFFFFF
-+               | USB Register            0x53000000-0x53FFFFFF
-+               | Flash Controller        0x54000000-0x54FFFFFF
-+               | DRAM Controller         0x55000000-0x55FFFFFF
-+    0x5FFFFFFF | Reserved                0x56000000-0x5FFFFFFF
-+               |=====================================================
-+    0x60000000 | Reserved
-+    0x6FFFFFFF |
-+               |=====================================================
-+    0x70000000 | FLASH shadow Memory
-+    0x7FFFFFFF |
-+               |=====================================================
-+    0x80000000 | Big Endian of memory    0x00000000-0x7FFFFFFF
-+    0xFFFFFFFF |
-+               +=====================================================
-+*/
-+
-+
-+
-+/*-------------------------------------------------------------------------------
-+ Memory Map definitions
-+-------------------------------------------------------------------------------- */
-+#define TEST          1
-+#if 0
-+
-+static inline int GETCPUID()
-+{
-+       int cpuid;
-+      __asm__(
-+"mrc p8, 0, r0, c0, c0, 0\n"
-+"mov %0, r0"
-+       :"=r"(cpuid)
-+       :
-+       :"r0");
-+       return (cpuid & 0x07);
-+}
-+#endif
-+#define SL2312_SRAM_BASE                0x70000000       //  SRAM base after remap
-+#define SL2312_DRAM_BASE                0x00000000       //  DRAM base after remap
-+#define SL2312_RAM_BASE                 0x10000000       //  RAM code base before remap
-+#define SL2312_FLASH_BASE                 0x30000000
-+#define SL2312_ROM_BASE                 0x30000000
-+#define SL2312_GLOBAL_BASE              0x40000000
-+#define SL2312_WAQTCHDOG_BASE           0x41000000
-+#define SL2312_UART_BASE                0x42000000
-+#define SL2312_TIMER_BASE               0x43000000
-+#define SL2312_LCD_BASE                 0x44000000
-+#define SL2312_RTC_BASE                 0x45000000
-+#define SL2312_SATA_BASE                0x46000000
-+#define SL2312_LPC_HOST_BASE            0x47000000
-+#define SL2312_LPC_IO_BASE              0x47800000
-+// #define SL2312_INTERRUPT_BASE           0x48000000
-+#define SL2312_INTERRUPT0_BASE          0x48000000
-+#define SL2312_INTERRUPT1_BASE          0x49000000
-+//#define SL2312_INTERRUPT_BASE               ((getcpuid()==0)?SL2312_INTERRUPT0_BASE:SL2312_INTERRUPT1_BASE)
-+#define SL2312_INTERRUPT_BASE             0x48000000
-+#define SL2312_SSP_CTRL_BASE            0x4A000000
-+#define SL2312_POWER_CTRL_BASE          0x4B000000
-+#define SL2312_CIR_BASE                 0x4C000000
-+#define SL2312_GPIO_BASE                0x4D000000
-+#define SL2312_GPIO_BASE1               0x4E000000
-+#define SL2312_GPIO_BASE2               0x4F000000
-+#define SL2312_PCI_IO_BASE              0x50000000
-+#define SL2312_PCI_MEM_BASE             0x58000000
-+#ifdef  CONFIG_NET_SL351X
-+#define SL2312_TOE_BASE                 0x60000000
-+#define SL2312_GMAC0_BASE               0x6000A000
-+#define SL2312_GMAC1_BASE               0x6000E000
-+#else
-+#define SL2312_GMAC0_BASE               0x60000000
-+#define SL2312_GMAC1_BASE               0x61000000
-+#endif
-+#define SL2312_SECURITY_BASE            0x62000000
-+#define SL2312_IDE0_BASE                0x63000000
-+#define SL2312_IDE1_BASE                      0x63400000
-+#define SL2312_RAID_BASE                0x64000000
-+#define SL2312_FLASH_CTRL_BASE          0x65000000
-+#define SL2312_DRAM_CTRL_BASE           0x66000000
-+#define SL2312_GENERAL_DMA_BASE         0x67000000
-+#define SL2312_USB_BASE                 0x68000000
-+#define SL2312_USB0_BASE                0x68000000
-+#define SL2312_USB1_BASE                0x69000000
-+#define SL2312_FLASH_SHADOW             0x30000000
-+#define SL2312_BIG_ENDIAN_BASE                        0x80000000
-+
-+#ifdef CONFIG_GEMINI_IPI
-+#define CPU_1_MEM_BASE                        0x4000000                               // 64 MB
-+#define CPU_1_DATA_OFFSET             0x4000000-0x300000              // Offset 61 MB
-+#endif
-+
-+#define SL2312_TIMER1_BASE              SL2312_TIMER_BASE
-+#define SL2312_TIMER2_BASE              (SL2312_TIMER_BASE + 0x10)
-+#define SL2312_TIMER3_BASE              (SL2312_TIMER_BASE + 0x20)
-+
-+#define SL2312_PCI_DMA_MEM1_BASE              0x00000000
-+#define SL2312_PCI_DMA_MEM2_BASE              0x00000000
-+#define SL2312_PCI_DMA_MEM3_BASE              0x00000000
-+#define SL2312_PCI_DMA_MEM1_SIZE              7
-+#define SL2312_PCI_DMA_MEM2_SIZE              6
-+#define SL2312_PCI_DMA_MEM3_SIZE              6
-+
-+/*-------------------------------------------------------------------------------
-+ Global Module
-+---------------------------------------------------------------------------------*/
-+#define GLOBAL_ID                       0x00
-+#define GLOBAL_CHIP_ID                  0x002311
-+#define GLOBAL_CHIP_REV                 0xA0
-+#define GLOBAL_STATUS                   0x04
-+#define GLOBAL_CONTROL                  0x1C
-+#define GLOBAL_REMAP_BIT                0x01
-+#define GLOBAL_RESET_REG              0x0C
-+#define GLOBAL_MISC_REG                                       0x30
-+#define PFLASH_SHARE_BIT                              0x02
-+
-+#define GLOBAL_RESET          (1<<31)
-+#define RESET_CPU1                    (1<<30)
-+#define RESET_SATA1                   (1<<27)
-+#define RESET_SATA0                   (1<<26)
-+#define RESET_CIR                     (1<<25)
-+#define RESET_EXT_DEV         (1<<24)
-+#define RESET_WD                      (1<<23)
-+#define RESET_GPIO2                   (1<<22)
-+#define RESET_GPIO1                   (1<<21)
-+#define RESET_GPIO0                   (1<<20)
-+#define RESET_SSP                     (1<<19)
-+#define RESET_UART                    (1<<18)
-+#define RESET_TIMER                   (1<<17)
-+#define RESET_RTC                     (1<<16)
-+#define RESET_INT0                    (1<<15)
-+#define RESET_INT1                    (1<<14)
-+#define RESET_LCD                     (1<<13)
-+#define RESET_LPC                     (1<<12)
-+#define RESET_APB                     (1<<11)
-+#define RESET_DMA                     (1<<10)
-+#define RESET_USB1                    (1<<9 )
-+#define RESET_USB0                    (1<<8 )
-+#define RESET_PCI                     (1<<7 )
-+#define RESET_GMAC1                   (1<<6 )
-+#define RESET_GMAC0                   (1<<5 )
-+#define RESET_IPSEC                   (1<<4 )
-+#define RESET_RAID                    (1<<3 )
-+#define RESET_IDE                     (1<<2 )
-+#define RESET_FLASH                   (1<<1 )
-+#define RESET_DRAM                    (1<<0 )
-+
-+
-+
-+
-+
-+
-+
-+
-+/*-------------------------------------------------------------------------------
-+ DRAM Module
-+---------------------------------------------------------------------------------*/
-+#define DRAM_SIZE_32M                   0x2000000
-+#define DRAM_SIZE_64M                   0x4000000
-+#define DRAM_SIZE_128M                  0x8000000
-+
-+#define DRAM_SIZE                       DRAM_SIZE_128M
-+
-+#define DRAM_SDRMR                      0x00
-+#define SDRMR_DISABLE_DLL               0x80010000
-+
-+/*------------------------------------------------------------------------------
-+ Share Pin Flag
-+--------------------------------------------------------------------------------*/
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+#define FLASH_SHARE_BIT                    0
-+#define UART_SHARE_BIT                     1
-+#define EMAC_SHARE_BIT                     2
-+#define IDE_RW_SHARE_BIT                   3
-+#define IDE_CMD_SHARE_BIT                  4
-+#endif
-+/*-------------------------------------------------------------------------------
-+ System Clock
-+---------------------------------------------------------------------------------*/
-+
-+#ifndef SYS_CLK
-+#ifdef CONFIG_SL3516_ASIC
-+#define SYS_CLK                         150000000
-+#else
-+#define SYS_CLK                       20000000
-+#endif
-+#endif
-+
-+#define AHB_CLK                       SYS_CLK
-+#define MAX_TIMER                     3
-+#ifndef APB_CLK
-+#ifdef CONFIG_SL3516_ASIC
-+#define APB_CLK                       (SYS_CLK / 6)
-+#else
-+#define APB_CLK                               SYS_CLK
-+#endif
-+#endif
-+
-+#ifdef CONFIG_SL3516_ASIC
-+#define UART_CLK                        48000000      // 30000000 for GeminiA chip, else 48000000
-+#else
-+#define UART_CLK                      48000000
-+#endif
-+
-+#define SL2312_BAUD_115200              (UART_CLK / 1843200)
-+#define SL2312_BAUD_57600               (UART_CLK / 921600)
-+#define SL2312_BAUD_38400                     (UART_CLK / 614400)
-+#define SL2312_BAUD_19200               (UART_CLK / 307200)
-+#define SL2312_BAUD_14400               (UART_CLK / 230400)
-+#define SL2312_BAUD_9600                (UART_CLK / 153600)
-+
-+#endif
-+
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/sl2312_ipsec.h
-@@ -0,0 +1,684 @@
-+#ifndef _IPSEC_DIAG_H
-+#define _IPSEC_DIAG_H
-+
-+#include <linux/scatterlist.h>
-+
-+#define BIG_ENDIAN    0
-+
-+#define IPSEC_TEST    0
-+#define ZERO_COPY     1
-+
-+#define UINT unsigned int
-+#define BYTE unsigned char
-+
-+/* define cipher algorithm */
-+enum CIPHER {
-+      DES_ECB_E       =20,
-+      TDES_ECB_E      =21,
-+      AES_ECB_E       =22,
-+      DES_CBC_E       =24,
-+      TDES_CBC_E      =25,
-+      AES_CBC_E       =26,
-+
-+      DES_ECB_D       =27,
-+      TDES_ECB_D      =28,
-+      AES_ECB_D       =29,
-+      DES_CBC_D       =31,
-+      TDES_CBC_D      =32,
-+      AES_CBC_D       =33,
-+      A_SHA1      =12,
-+      A_HMAC_SHA1 =13,
-+      A_MD5       =14,
-+      A_HMAC_MD5  =15,
-+};
-+
-+// opMode
-+#define CIPHER_ENC    0x1
-+#define CIPHER_DEC    0x3
-+#define AUTH          0x4
-+#define ENC_AUTH      0x5
-+#define AUTH_DEC      0x7
-+
-+// cipherAlgorithm
-+#define CBC_DES       0x4
-+#define CBC_3DES      0x5
-+#define CBC_AES       0x6
-+#define ECB_DES       0x0
-+#define ECB_3DES      0x1
-+#define ECB_AES       0x2
-+
-+// authAlgorithm
-+#define SHA1         0
-+#define MD5          1
-+#define HMAC_SHA1    2
-+#define HMAC_MD5     3
-+#define FCS          4
-+
-+//cipher mode
-+#define ECB          0
-+#define CBC          1
-+
-+// authMode
-+#define AUTH_APPEND  0
-+#define AUTH_CHKVAL  1
-+
-+/******************************************************/
-+/*          the offset of IPSEC DMA register          */
-+/******************************************************/
-+enum IPSEC_DMA_REGISTER {
-+      IPSEC_DMA_DEVICE_ID             = 0xff00,
-+      IPSEC_DMA_STATUS                = 0xff04,
-+      IPSEC_TXDMA_CTRL                = 0xff08,
-+      IPSEC_TXDMA_FIRST_DESC  = 0xff0c,
-+      IPSEC_TXDMA_CURR_DESC   = 0xff10,
-+      IPSEC_RXDMA_CTRL                = 0xff14,
-+      IPSEC_RXDMA_FIRST_DESC  = 0xff18,
-+      IPSEC_RXDMA_CURR_DESC   = 0xff1c,
-+      IPSEC_TXDMA_BUF_ADDR    = 0xff28,
-+      IPSEC_RXDMA_BUF_ADDR    = 0xff38,
-+      IPSEC_RXDMA_BUF_SIZE            = 0xff30,
-+};
-+
-+#define IPSEC_STATUS_REG    0x00a8
-+#define IPSEC_RAND_NUM_REG  0x00ac
-+
-+/******************************************************/
-+/* the field definition of IPSEC DMA Module Register  */
-+/******************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff00
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int p_wclk             :  4;   /* DMA_APB write clock period */
-+              unsigned int p_rclk             :  4;   /* DMA_APB read clock period */
-+              unsigned int                            :  8;
-+              unsigned int device_id          : 12;
-+              unsigned int revision_id        :  4;
-+#else
-+              unsigned int revision_id        :  4;
-+              unsigned int device_id          : 12;
-+              unsigned int                            :  8;
-+              unsigned int p_rclk             :  4;   /* DMA_APB read clock period */
-+              unsigned int p_wclk             :  4;   /* DMA_APB write clock period */
-+#endif
-+      } bits;
-+} IPSEC_DMA_DEVICE_ID_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff04
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int ts_finish          :  1;   /* finished tx interrupt */
-+              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
-+              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
-+              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
-+              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
-+              unsigned int rs_finish          :  1;   /* finished rx interrupt */
-+              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
-+              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
-+              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
-+              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
-+        unsigned int intr           :  8;   /* Peripheral interrupt */
-+              unsigned int dma_reset          :  1;   /* write 1 to this bit will cause DMA HClk domain soft reset */
-+              unsigned int peri_reset         :  1;   /* write 1 to this bit will cause DMA PClk domain soft reset */
-+              unsigned int                            :  3;
-+              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
-+        unsigned int intr_enable    :  8;   /* Peripheral Interrupt Enable */
-+#else
-+        unsigned int intr_enable    :  8;   /* Peripheral Interrupt Enable */
-+              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
-+              unsigned int                            :  3;
-+              unsigned int peri_reset         :  1;   /* write 1 to this bit will cause DMA PClk domain soft reset */
-+              unsigned int dma_reset          :  1;   /* write 1 to this bit will cause DMA HClk domain soft reset */
-+        unsigned int intr           :  8;   /* Peripheral interrupt */
-+              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
-+              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
-+              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
-+              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
-+              unsigned int rs_finish          :  1;   /* finished rx interrupt */
-+              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
-+              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
-+              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
-+              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
-+              unsigned int ts_finish          :  1;   /* finished tx interrupt */
-+#endif
-+      } bits;
-+} IPSEC_DMA_STATUS_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff08
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int td_start           :  1;   /* Start DMA transfer */
-+              unsigned int td_continue        :  1;   /* Continue DMA operation */
-+              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int                            :  1;
-+              unsigned int td_prot            :  4;   /* TxDMA protection control */
-+              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
-+              unsigned int td_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
-+              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int                            : 14;
-+#else
-+              unsigned int                            : 14;
-+              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int td_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
-+              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
-+              unsigned int td_prot            :  4;   /* TxDMA protection control */
-+              unsigned int                            :  1;
-+              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int td_continue        :  1;   /* Continue DMA operation */
-+              unsigned int td_start           :  1;   /* Start DMA transfer */
-+#endif
-+      } bits;
-+} IPSEC_TXDMA_CTRL_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff0c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
-+              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
-+              unsigned int                                    :  3;
-+#else
-+              unsigned int                                    :  3;
-+              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
-+              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
-+#endif
-+      } bits;
-+} IPSEC_TXDMA_FIRST_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff10
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
-+              unsigned int sof_eof            :  2;
-+#else
-+              unsigned int sof_eof            :  2;
-+              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+#endif
-+      } bits;
-+} IPSEC_TXDMA_CURR_DESC_T;
-+
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff14
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rd_start           :  1;   /* Start DMA transfer */
-+              unsigned int rd_continue        :  1;   /* Continue DMA operation */
-+              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int                            :  1;
-+              unsigned int rd_prot            :  4;   /* DMA protection control */
-+              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
-+              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
-+              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int                            : 14;
-+#else
-+              unsigned int                            : 14;
-+              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int rd_bus                 :  2;       /* peripheral bus width;0 - 8 bits;1 - 16 bits */
-+              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
-+              unsigned int rd_prot            :  4;   /* DMA protection control */
-+              unsigned int                            :  1;
-+              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int rd_continue        :  1;   /* Continue DMA operation */
-+              unsigned int rd_start           :  1;   /* Start DMA transfer */
-+#endif
-+      } bits;
-+} IPSEC_RXDMA_CTRL_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff18
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
-+              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
-+              unsigned int                                    :  3;
-+#else
-+              unsigned int                                    :  3;
-+              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
-+              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
-+#endif
-+      } bits;
-+} IPSEC_RXDMA_FIRST_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff1c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
-+              unsigned int sof_eof            :  2;
-+#else
-+              unsigned int sof_eof            :  2;
-+              unsigned int dec                        :  1;   /* AHB bus address increment(0)/decrement(1) */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+#endif
-+      } bits;
-+} IPSEC_RXDMA_CURR_DESC_T;
-+
-+
-+
-+/******************************************************/
-+/*    the field definition of IPSEC module Register   */
-+/******************************************************/
-+typedef union
-+{
-+      unsigned int id;
-+      struct bit_0000
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int device_id          : 28;
-+              unsigned int revision_id        :  4;
-+#else
-+              unsigned int revision_id        :  4;
-+              unsigned int device_id          : 28;
-+#endif
-+      } bits;
-+} IPSEC_ID_T;
-+
-+typedef union
-+{
-+    unsigned int control;
-+    struct bit_0004
-+    {
-+#if (BIG_ENDIAN==1)
-+        unsigned int op_mode            :  4; /* Operation Mode for the IPSec Module */
-+        unsigned int                    :  1;
-+        unsigned int cipher_algorithm   :  3;
-+        unsigned int aesnk              :  4; /* AES Key Size */
-+        unsigned int mix_key_sel        :  1; /* 0:use rCipherKey0-3  1:use Key Mixer */
-+        unsigned int                    :  2;
-+        unsigned int fcs_stream_copy    :  1; /* enable authentication stream copy */
-+        unsigned int auth_mode          :  1; /* 0-Append or 1-Check Authentication Result */
-+        unsigned int auth_algorithm     :  3;
-+        unsigned int                    :  1;
-+        unsigned int auth_check_len     :  3; /* Number of 32-bit words to be check or appended */
-+                                              /* by the authentication module */
-+        unsigned int process_id         :  8; /* Used to identify process.This number will be */
-+                                              /* copied to the descriptor status of received packet*/
-+#else
-+        unsigned int process_id         :  8; /* Used to identify process.This number will be */
-+                                              /* copied to the descriptor status of received packet*/
-+        unsigned int auth_check_len     :  3; /* Number of 32-bit words to be check or appended */
-+                                              /* by the authentication module */
-+        unsigned int                    :  1;
-+        unsigned int auth_algorithm     :  3;
-+        unsigned int auth_mode          :  1; /* 0-Append or 1-Check Authentication Result */
-+        unsigned int fcs_stream_copy    :  1; /* enable authentication stream copy */
-+        unsigned int                    :  2;
-+        unsigned int mix_key_sel        :  1; /* 0:use rCipherKey0-3  1:use Key Mixer */
-+        unsigned int aesnk              :  4; /* AES Key Size */
-+        unsigned int cipher_algorithm   :  3;
-+        unsigned int                    :  1;
-+        unsigned int op_mode            :  4; /* Operation Mode for the IPSec Module */
-+#endif
-+    } bits;
-+} IPSEC_CONTROL_T;
-+
-+
-+typedef union
-+{
-+    unsigned int cipher_packet;
-+    struct bit_0008
-+    {
-+#if (BIG_ENDIAN==1)
-+        unsigned int cipher_header_len    : 16; /* The header length to be skipped by the cipher */
-+        unsigned int cipher_algorithm_len : 16; /* The length of message body to be encrypted/decrypted */
-+#else
-+        unsigned int cipher_algorithm_len : 16; /* The length of message body to be encrypted/decrypted */
-+        unsigned int cipher_header_len    : 16; /* The header length to be skipped by the cipher */
-+#endif
-+    } bits;
-+} IPSEC_CIPHER_PACKET_T;
-+
-+typedef union
-+{
-+    unsigned int auth_packet;
-+    struct bit_000c
-+    {
-+#if (BIG_ENDIAN==1)
-+        unsigned int auth_header_len    : 16; /* The header length that is to be skipped by the authenticator */
-+        unsigned int auth_algorithm_len : 16; /* The length of message body that is to be authenticated */
-+#else
-+        unsigned int auth_algorithm_len : 16; /* The length of message body that is to be authenticated */
-+        unsigned int auth_header_len    : 16; /* The header length that is to be skipped by the authenticator */
-+#endif
-+    } bits;
-+} IPSEC_AUTH_PACKET_T;
-+
-+typedef union
-+{
-+    unsigned int status;
-+    struct bit_00a8
-+    {
-+#if (BIG_ENDIAN==1)
-+        unsigned int auth_cmp_rslt  :  1; /* Authentication Compare result */
-+        unsigned int wep_crc_ok     :  1; /* WEP ICV compare result */
-+        unsigned int tkip_mic_ok    :  1; /* TKIP Mic compare result */
-+        unsigned int ccm_mic_ok     :  1; /* CCM Mic compare result */
-+        unsigned int                : 16;
-+        unsigned int parser_err_code:  4; /* Authentication Compare result */
-+        unsigned int auth_err_code  :  4; /* Authentication module error code */
-+        unsigned int cipher_err_code:  4; /* Cipher module erroe code */
-+#else
-+        unsigned int cipher_err_code:  4; /* Cipher module erroe code */
-+        unsigned int auth_err_code  :  4; /* Authentication module error code */
-+        unsigned int parser_err_code:  4; /* Authentication Compare result */
-+        unsigned int                : 16;
-+        unsigned int ccm_mic_ok     :  1; /* CCM Mic compare result */
-+        unsigned int tkip_mic_ok    :  1; /* TKIP Mic compare result */
-+        unsigned int wep_crc_ok     :  1; /* WEP ICV compare result */
-+        unsigned int auth_cmp_rslt  :  1; /* Authentication Compare result */
-+#endif
-+    } bits;
-+} IPSEC_STATUS_T;
-+
-+
-+
-+/************************************************************************/
-+/*              IPSec Descriptor Format                                 */
-+/************************************************************************/
-+typedef struct descriptor_t
-+{
-+      union frame_control_t
-+      {
-+              unsigned int bits32;
-+              struct bits_0000
-+              {
-+#if (BIG_ENDIAN==1)
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int            : 1;    /* authentication compare result */
-+                      unsigned int            : 6;    /* checksum[15:8] */
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+#else
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int            : 6;    /* checksum[15:8] */
-+                      unsigned int            : 1;    /* authentication compare result */
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+#endif
-+              } bits;
-+      } frame_ctrl;
-+
-+      union flag_status_t
-+      {
-+              unsigned int bits32;
-+              struct bits_0004
-+              {
-+#if (BIG_ENDIAN==1)
-+//            unsigned int checksum   : 8; /* checksum[7:0] */
-+                      unsigned int            : 4;
-+                      unsigned int auth_result: 1;
-+                      unsigned int wep_crc_ok : 1;
-+                      unsigned int tkip_mic_ok: 1;
-+                      unsigned int ccmp_mic_ok: 1;
-+                      unsigned int process_id : 8;
-+                      unsigned int frame_count:16;
-+#else
-+                      unsigned int frame_count:16;
-+                      unsigned int process_id : 8;
-+                      unsigned int ccmp_mic_ok: 1;
-+                      unsigned int tkip_mic_ok: 1;
-+                      unsigned int wep_crc_ok : 1;
-+                      unsigned int auth_result: 1;
-+                      unsigned int            : 4;
-+//            unsigned int checksum   : 8; /* checksum[7:0] */
-+#endif
-+              } bits_rx_status;
-+
-+              struct bits_0005
-+              {
-+#if (BIG_ENDIAN==1)
-+            unsigned int            : 8;
-+                      unsigned int process_id : 8;
-+                      unsigned int frame_count:16;
-+#else
-+                      unsigned int frame_count:16;
-+                      unsigned int process_id : 8;
-+            unsigned int            : 8;
-+#endif
-+              } bits_tx_status;
-+
-+              struct bits_0006
-+              {
-+#if (BIG_ENDIAN==1)
-+                      unsigned int            :22;
-+                      unsigned int tqflag     :10;
-+#else
-+                      unsigned int tqflag     :10;
-+                      unsigned int            :22;
-+#endif
-+              } bits_tx_flag;
-+      } flag_status;
-+
-+      unsigned int buf_adr;   /* data buffer address */
-+
-+      union next_desc_t
-+      {
-+              unsigned int next_descriptor;
-+              struct bits_000c
-+              {
-+#if (BIG_ENDIAN==1)
-+                      unsigned int ndar               :28;    /* next descriptor address */
-+                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
-+                      unsigned int dec                : 1;    /* AHB bus address. 0-increment; 1-decrement */
-+                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
-+                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
-+#else
-+                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
-+                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
-+                      unsigned int dec                : 1;    /* AHB bus address. 0-increment; 1-decrement */
-+                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
-+                      unsigned int ndar               :28;    /* next descriptor address */
-+#endif
-+              } bits;
-+      } next_desc;
-+} IPSEC_DESCRIPTOR_T;
-+
-+
-+typedef struct IPSEC_S
-+{
-+    unsigned char       *tx_bufs;
-+    unsigned char       *rx_bufs;
-+      IPSEC_DESCRIPTOR_T      *tx_desc;           /* point to virtual TX descriptor address*/
-+      IPSEC_DESCRIPTOR_T      *rx_desc;           /* point to virtual RX descriptor address*/
-+      IPSEC_DESCRIPTOR_T      *tx_cur_desc;   /* point to current TX descriptor */
-+      IPSEC_DESCRIPTOR_T      *rx_cur_desc;   /* point to current RX descriptor */
-+      IPSEC_DESCRIPTOR_T  *tx_finished_desc;
-+      IPSEC_DESCRIPTOR_T  *rx_finished_desc;
-+      dma_addr_t          rx_desc_dma;        /* physical RX descriptor address */
-+      dma_addr_t          tx_desc_dma;    /* physical TX descriptor address */
-+      dma_addr_t          rx_bufs_dma;    /* physical RX descriptor address */
-+      dma_addr_t          tx_bufs_dma;    /* physical TX descriptor address */
-+} IPSEC_T;
-+
-+
-+/*=====================================================================================================*/
-+/*  Data Structure of IPSEC Control Packet  */
-+/*=====================================================================================================*/
-+typedef struct IPSEC_ECB_AUTH_S
-+{
-+    IPSEC_CONTROL_T         control; /* control parameter */
-+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
-+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
-+    unsigned char           cipher_key[8*4];
-+    unsigned char           auth_check_val[5*4];
-+} IPSEC_ECB_AUTH_T;
-+
-+typedef struct IPSEC_CBC_AUTH_S
-+{
-+    IPSEC_CONTROL_T         control; /* control parameter */
-+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
-+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
-+    unsigned char           cipher_iv[4*4];
-+    unsigned char           cipher_key[8*4];
-+    unsigned char           auth_check_val[5*4];
-+} IPSEC_CBC_AUTH_T;
-+
-+typedef struct IPSEC_ECB_HMAC_AUTH_S
-+{
-+    IPSEC_CONTROL_T         control; /* control parameter */
-+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
-+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
-+    unsigned char           cipher_key[8*4];
-+    unsigned char           auth_key[16*4];
-+    unsigned char           auth_check_val[5*4];
-+} IPSEC_ECB_AUTH_HMAC_T;
-+
-+typedef struct IPSEC_CBC_HMAC_AUTH_S
-+{
-+    IPSEC_CONTROL_T         control; /* control parameter */
-+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
-+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
-+    unsigned char           cipher_iv[4*4];
-+    unsigned char           cipher_key[8*4];
-+    unsigned char           auth_key[16*4];
-+    unsigned char           auth_check_val[5*4];
-+} IPSEC_CBC_AUTH_HMAC_T;
-+
-+typedef struct IPSEC_HMAC_AUTH_S
-+{
-+    IPSEC_CONTROL_T         control; /* control parameter */
-+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
-+    unsigned char           auth_key[16*4];
-+    unsigned char           auth_check_val[5*4];
-+} IPSEC_HMAC_AUTH_T;
-+
-+typedef union
-+{
-+    unsigned char auth_pkt[28];
-+
-+    struct IPSEC_AUTH_S
-+    {
-+        IPSEC_CONTROL_T         control; /* control parameter(4-byte) */
-+        IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter(4-byte) */
-+        unsigned char           auth_check_val[5*4];
-+    } var;
-+} IPSEC_AUTH_T;
-+
-+typedef struct IPSEC_CIPHER_CBC_S
-+{
-+    IPSEC_CONTROL_T         control; /* control parameter */
-+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
-+    unsigned char           cipher_iv[4*4];
-+    unsigned char           cipher_key[8*4];
-+} IPSEC_CIPHER_CBC_T;
-+
-+typedef struct IPSEC_CIPHER_ECB_S
-+{
-+    IPSEC_CONTROL_T         control; /* control parameter */
-+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
-+    unsigned char           cipher_key[8*4];
-+} IPSEC_CIPHER_ECB_T;
-+
-+
-+/****************************************************************************
-+ *                          Structure Definition                            *
-+ ****************************************************************************/
-+struct IPSEC_PACKET_S
-+{
-+    unsigned int    op_mode;            /* CIPHER_ENC(1),CIPHER_DEC(3),AUTH(4),ENC_AUTH(5),AUTH_DEC(7) */
-+    unsigned int    cipher_algorithm;   /* ECB_DES(0),ECB_3DES(1),ECB_AES(2),CBC_DES(4),CBC_3DES(5),CBC_AES(6) */
-+    unsigned int    auth_algorithm;     /* SHA1(0),MD5(1),HMAC_SHA1(2),HMAC_MD5(3),FCS(4) */
-+    unsigned int    auth_result_mode;   /* AUTH_APPEND(0),AUTH_CHKVAL(1) */
-+    unsigned int    process_id;         /* Used to identify the process */
-+    unsigned int    auth_header_len;    /* Header length to be skipped by the authenticator */
-+    unsigned int    auth_algorithm_len; /* Length of message body that is to be authenticated */
-+    unsigned int    cipher_header_len;  /* Header length to be skipped by the cipher */
-+    unsigned int    cipher_algorithm_len;   /* Length of message body to be encrypted or decrypted */
-+    unsigned char   iv[16];             /* Initial vector used for DES,3DES,AES */
-+    unsigned int    iv_size;            /* Initial vector size */
-+    unsigned char   auth_key[64];       /* authentication key */
-+    unsigned int    auth_key_size;      /* authentication key size */
-+    unsigned char   cipher_key[32];     /* cipher key */
-+    unsigned int    cipher_key_size;    /* cipher key size */
-+    struct scatterlist *in_packet;         /* input_packet buffer pointer */
-+    //unsigned char           *in_packet;         /* input_packet buffer pointer */
-+    unsigned int    pkt_len;            /* input total packet length */
-+    unsigned char   auth_checkval[20];  /* Authentication check value/FCS check value */
-+    struct IPSEC_PACKET_S *next,*prev;        /* pointer to next/previous operation to perform on buffer */
-+    void (*callback)(struct IPSEC_PACKET_S *); /* function to call when done authentication/cipher */
-+    unsigned char   *out_packet;        /* output_packet buffer pointer */
-+    //struct scatterlist *out_packet;        /* output_packet buffer pointer */
-+    unsigned int    out_pkt_len;        /* output total packet length */
-+    unsigned int    auth_cmp_result;    /* authentication compare result */
-+    unsigned int    checksum;           /* checksum value */
-+    unsigned int    status;             /* ipsec return status. 0:success, others:fail */
-+#if (IPSEC_TEST == 1)
-+    unsigned char    *sw_packet;         /* for test only */
-+    unsigned int    sw_pkt_len;         /* for test only */
-+#endif
-+} ;
-+
-+/*****************************************************************************
-+ * Function    : ipsec_crypto_hw_process
-+ * Description : This function processes H/W authentication and cipher.
-+ *       Input : op_info - the authentication and cipher information for IPSec module.
-+ *      Output : none.
-+ *      Return : 0 - success, others - failure.
-+ *****************************************************************************/
-+int ipsec_crypto_hw_process(struct IPSEC_PACKET_S  *op_info);
-+
-+int ipsec_get_cipher_algorithm(unsigned char *alg_name,unsigned int alg_mode);
-+int ipsec_get_auth_algorithm(unsigned char *alg_name,unsigned int alg_mode);
-+#if 0
-+void ipsec_sw_authentication(char *data,unsigned int data_len,char *authkey,char authAlgorithm,char *auth_result);
-+void ipsec_sw_cipher(unsigned char *pt,unsigned int pt_len, unsigned char *cipher_key, unsigned int key_size,
-+                            unsigned char *iv,unsigned int cipherAlgorithm,unsigned char *ct);
-+void ipsec_sw_auth_cipher(unsigned int op_mode,char *data,unsigned int data_len,
-+                                BYTE *auth_key,char authAlgorithm,char *auth_result,
-+                                char *pt, unsigned int pt_len,char *cipher_key, int key_size,
-+                                char *iv, char cipherAlgorithm,char *ct);
-+#endif
-+
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/sl_random.h
-@@ -0,0 +1,2 @@
-+#define RANDOM_ADD            (IO_ADDRESS (0x051000000) + 0x0AC)
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/system.h
-@@ -0,0 +1,54 @@
-+/*
-+ *  linux/include/asm-arm/arch-sl2312/system.h
-+ *
-+ *  Copyright (C) 1999 ARM Limited
-+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __ASM_ARCH_SYSTEM_H
-+#define __ASM_ARCH_SYSTEM_H
-+
-+#include <asm/arch/platform.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/arch/it8712.h>
-+#include <asm/io.h>
-+
-+static void arch_idle(void)
-+{
-+      /*
-+       * This should do all the clock switching
-+       * and wait for interrupt tricks
-+       */
-+      cpu_do_idle();
-+}
-+
-+extern __inline__ void arch_reset(char mode)
-+{
-+      __raw_writel( (int) GLOBAL_RESET|RESET_CPU1, IO_ADDRESS(SL2312_GLOBAL_BASE) + GLOBAL_RESET_REG);
-+}
-+
-+
-+void (*pm_power_off)(void);
-+//{
-+//    printk("arch_power_off\n");
-+
-+      // Power off
-+//    __raw_writel( (int) 0x00000001, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
-+
-+//}
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/timer.h
-@@ -0,0 +1,53 @@
-+/*
-+ *
-+ *  This file contains the register definitions for the Excalibur
-+ *  Timer TIMER00.
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __TIMER_H
-+#define __TIMER_H
-+
-+/*
-+ * Register definitions for the timers
-+ */
-+
-+#define TIMER_COUNT(BASE_ADDR)          (TIMER_TYPE (BASE_ADDR  + 0x00 ))
-+#define TIMER_LOAD(BASE_ADDR)           (TIMER_TYPE (BASE_ADDR  + 0x04 ))
-+#define TIMER_MATCH1(BASE_ADDR)         (TIMER_TYPE (BASE_ADDR  + 0x08 ))
-+#define TIMER_MATCH2(BASE_ADDR)         (TIMER_TYPE (BASE_ADDR  + 0x0C ))
-+#define TIMER_CR(BASE_ADDR)             (TIMER_TYPE (BASE_ADDR  + 0x30 ))
-+#define TIMER_1_CR_ENABLE_MSK                     (0x00000001)
-+#define TIMER_1_CR_ENABLE_OFST                    (0)
-+#define TIMER_1_CR_CLOCK_MSK                      (0x00000002)
-+#define TIMER_1_CR_CLOCK_OFST                     (1)
-+#define TIMER_1_CR_INT_MSK                    (0x00000004)
-+#define TIMER_1_CR_INT_OFST               (2)
-+#define TIMER_2_CR_ENABLE_MSK                     (0x00000008)
-+#define TIMER_2_CR_ENABLE_OFST                    (3)
-+#define TIMER_2_CR_CLOCK_MSK                      (0x00000010)
-+#define TIMER_2_CR_CLOCK_OFST                     (4)
-+#define TIMER_2_CR_INT_MSK                    (0x00000020)
-+#define TIMER_2_CR_INT_OFST               (5)
-+#define TIMER_3_CR_ENABLE_MSK                     (0x00000040)
-+#define TIMER_3_CR_ENABLE_OFST                    (6)
-+#define TIMER_3_CR_CLOCK_MSK                      (0x00000080)
-+#define TIMER_3_CR_CLOCK_OFST                     (7)
-+#define TIMER_3_CR_INT_MSK                    (0x00000100)
-+#define TIMER_3_CR_INT_OFST               (8)
-+
-+#endif /* __TIMER00_H */
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/timex.h
-@@ -0,0 +1,29 @@
-+/*
-+ *  linux/include/asm-arm/arch-epxa10db/timex.h
-+ *
-+ *  Excalibur timex specifications
-+ *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+/*
-+ * ??
-+ */
-+#include <asm/arch/sl2312.h>
-+
-+#define CLOCK_TICK_RATE               APB_CLK
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/uart.h
-@@ -0,0 +1,100 @@
-+/* *
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifndef __UART_H
-+#define __UART_H
-+
-+/*
-+ * Register definitions for the UART
-+ */
-+
-+#define UART_TX_FIFO_SIZE      (15)
-+
-+#define UART_RBR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x00))  // read
-+#define UART_THR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x00))  // write
-+#define UART_IER(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x04))
-+#define UART_IER_MS                                 (0x08)
-+#define UART_IER_RLS                                (0x04)
-+#define UART_IER_TE                                 (0x02)
-+#define UART_IER_DR                                 (0x01)
-+#define UART_IIR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x08))   // read
-+#define UART_IIR_NONE                             (0x01)      /* No interrupt pending */
-+#define UART_IIR_RLS                              (0x06)      /* Receive Line Status */
-+#define UART_IIR_DR                               (0x04)      /* Receive Data Ready */
-+#define UART_IIR_TIMEOUT                          (0x0c)      /* Receive Time Out */
-+#define UART_IIR_TE                               (0x02)      /* THR Empty */
-+#define UART_IIR_MODEM                            (0x00)      /* Modem Status */
-+#define UART_FCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x08))  // write
-+#define UART_FCR_FE                               (0x01)      /* FIFO Enable */
-+#define UART_FCR_RXFR                             (0x02)      /* Rx FIFO Reset */
-+#define UART_FCR_TXFR                             (0x04)      /* Tx FIFO Reset */
-+#define UART_FCR_FIFO_1C                            (0x00)
-+#define UART_FCR_FIFO_4C                            (0x40)
-+#define UART_FCR_FIFO_8C                            (0x80)
-+#define UART_FCR_FIFO_14C                           (0xC0)
-+#define UART_LCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x0C))
-+#define UART_LCR_MSK                                (0x03)
-+#define UART_LCR_LEN5                             (0x00)
-+#define UART_LCR_LEN6                             (0x01)
-+#define UART_LCR_LEN7                             (0x02)
-+#define UART_LCR_LEN8                             (0x03)
-+#define UART_LCR_STOP                             (0x04)
-+#define UART_LCR_EVEN                             (0x18)      /* Even Parity */
-+#define UART_LCR_ODD                              (0x08)      /* Odd Parity */
-+#define UART_LCR_PE                               (0x08)      /* Parity Enable */
-+#define UART_LCR_SETBREAK                         (0x40)      /* Set Break condition */
-+#define UART_LCR_STICKPARITY                      (0x20)      /* Stick Parity Enable */
-+#define UART_LCR_DLAB                             (0x80)      /* Divisor Latch Access Bit */
-+#define UART_MCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x10))
-+#define UART_MCR_DTR                              (0x1)       /* Data Terminal Ready */
-+#define UART_MCR_RTS                              (0x2)       /* Request to Send */
-+#define UART_MCR_OUT1                             (0x4)       /* output       1 */
-+#define UART_MCR_OUT2                             (0x8)       /* output2 or global interrupt enable */
-+#define UART_MCR_LPBK                             (0x10)      /* loopback mode */
-+#define UART_MCR_MASK                               (0xE3)
-+#define UART_LSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x14))
-+#define UART_LSR_DR                               (0x01)      /* Data Ready */
-+#define UART_LSR_OE                               (0x02)      /* Overrun Error */
-+#define UART_LSR_PE                               (0x04)      /* Parity Error */
-+#define UART_LSR_FE                               (0x08)      /* Framing Error */
-+#define UART_LSR_BI                                 (0x10)            /* Break Interrupt */
-+#define UART_LSR_THRE                               (0x20)            /* THR Empty */
-+#define UART_LSR_TE                                 (0x40)            /* Transmitte Empty */
-+#define UART_LSR_DE                                 (0x80)            /* FIFO Data Error */
-+#define UART_MSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x18))
-+#define UART_MSR_DELTACTS                         (0x01)      /* Delta CTS */
-+#define UART_MSR_DELTADSR                         (0x02)      /* Delta DSR */
-+#define UART_MSR_TERI                             (0x04)      /* Trailing Edge RI */
-+#define UART_MSR_DELTACD                          (0x08)      /* Delta CD */
-+#define UART_MSR_CTS                              (0x10)      /* Clear To Send */
-+#define UART_MSR_DSR                              (0x20)      /* Data Set Ready */
-+#define UART_MSR_RI                               (0x40)      /* Ring Indicator */
-+#define UART_MSR_DCD                              (0x80)      /* Data Carrier Detect */
-+#define UART_SPR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x1C))
-+#define UART_DIV_LO(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x0))
-+#define UART_DIV_HI(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x4))
-+#define UART_PSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x8))
-+#define UART_MDR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x20))
-+#define UART_MDR_SERIAL                             (0x0)
-+
-+#define UART_MSR_DDCD 0x08    /* Delta DCD */
-+#define UART_MSR_DDSR 0x02    /* Delta DSR */
-+#define UART_MSR_DCTS 0x01    /* Delta CTS */
-+#define UART_MSR_ANY_DELTA 0x0F       /* Any of the delta bits! */
-+
-+
-+#endif /* __UART_H */
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/uncompress.h
-@@ -0,0 +1,94 @@
-+/*
-+ *  linux/include/asm-arm/arch-epxa10db/uncompress.h
-+ *
-+ *  Copyright (C) 1999 ARM Limited
-+ *  Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include "asm/arch/platform.h"
-+#include "asm/arch/hardware.h"
-+#define UART_TYPE (volatile unsigned int*)
-+#ifndef CONFIG_SERIAL_IT8712
-+#include "asm/arch/uart.h"
-+#endif
-+extern unsigned int it8712_uart_base;
-+
-+/*
-+ * This does not append a newline
-+ */
-+static void putstr(const char *s)
-+{
-+
-+#ifdef CONFIG_SERIAL_IT8712
-+
-+      unsigned char *base,*status,stat;
-+      int i ;
-+
-+      status = (unsigned char*)it8712_uart_base + 5;
-+      base = (unsigned char*)it8712_uart_base ;
-+
-+      while (*s) {
-+
-+              stat = *status;
-+              while (!(stat&0x20)) {                          // check status
-+                      for(i=0;i<0x10;i++)     ;
-+                      status = (unsigned char*)it8712_uart_base + 5;
-+                      stat = *status ;
-+              }
-+
-+              *base = *s;
-+              barrier();
-+
-+              if (*s == '\n') {
-+                      stat = *status;
-+                      while (!(stat&0x20)) {                  // check status
-+                              for(i=0;i<0x10;i++)     ;
-+                              status = (unsigned char*)it8712_uart_base + 5;
-+                              stat = *status ;
-+              }
-+
-+                      barrier();
-+                      *base = '\r';
-+              }
-+              s++;
-+      }
-+
-+#else
-+      while (*s) {
-+              while (!(*UART_LSR(SL2312_UART_BASE) &
-+                       UART_LSR_THRE));
-+                     barrier();
-+
-+              *UART_THR(SL2312_UART_BASE) = *s;
-+
-+              if (*s == '\n') {
-+                      while (!(*UART_LSR(SL2312_UART_BASE) &
-+                               UART_LSR_THRE));
-+                              barrier();
-+
-+                      *UART_THR(SL2312_UART_BASE) = '\r';
-+              }
-+              s++;
-+      }
-+#endif
-+}
-+
-+/*
-+ * nothing to do
-+ */
-+#define arch_decomp_setup()
-+
-+#define arch_decomp_wdog()
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/vmalloc.h
-@@ -0,0 +1,36 @@
-+/*
-+ *  linux/include/asm-arm/arch-epxa10db/vmalloc.h
-+ *
-+ *  Copyright (C) 2000 Russell King.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+/*
-+ * Just any arbitrary offset to the start of the vmalloc VM area: the
-+ * current 8MB value just means that there will be a 8MB "hole" after the
-+ * physical memory until the kernel virtual memory starts.  That means that
-+ * any out-of-bounds memory accesses will hopefully be caught.
-+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
-+ * area for the same reason. ;)
-+ */
-+#define VMALLOC_OFFSET          (8*1024*1024)
-+#define VMALLOC_START   (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
-+
-+//#define MODULE_START    (PAGE_OFFSET - 16*1048576)
-+//#define MODULE_END      (PAGE_OFFSET)
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/watchdog.h
-@@ -0,0 +1,58 @@
-+#ifndef __WATCHDOG_H
-+#define __WATCHDOG_H
-+
-+#define WATCHDOG_BASE                   (IO_ADDRESS (SL2312_WAQTCHDOG_BASE))
-+#define WATCHDOG_COUNTER                  (WATCHDOG_BASE + 0x00)
-+#define WATCHDOG_LOAD                     (WATCHDOG_BASE + 0x04)
-+#define WATCHDOG_RESTART                  (WATCHDOG_BASE + 0x08)
-+#define WATCHDOG_CR                       (WATCHDOG_BASE + 0x0C)
-+#define WATCHDOG_STATUS                   (WATCHDOG_BASE + 0x10)
-+#define WATCHDOG_CLEAR                    (WATCHDOG_BASE + 0x14)
-+#define WATCHDOG_INTRLEN                  (WATCHDOG_BASE + 0x18)
-+
-+#define WATCHDOG_WDENABLE_MSK                   (0x00000001)
-+#define WATCHDOG_WDENABLE_OFST                  (0)
-+#define WATCHDOG_WDRST_MSK              (0x00000002)
-+#define WATCHDOG_WDRST_OFST             (1)
-+#define WATCHDOG_WDINTR_MSK             (0x00000004)
-+#define WATCHDOG_WDINTR_OFST            (2)
-+#define WATCHDOG_WDEXT_MSK              (0x00000008)
-+#define WATCHDOG_WDEXT_OFST             (3)
-+#define WATCHDOG_WDCLOCK_MSK            (0x00000010)
-+#define WATCHDOG_WDCLOCK_OFST                   (4)
-+#define WATCHDOG_CR_MASK                  (0x0000001F)
-+
-+#define WATCHDOG_CLEAR_STATUS             0x1
-+#define WATCHDOG_ENABLE                   1
-+#define WATCHDOG_DISABLE                  0
-+#define WATCHDOG_RESTART_VALUE            0x5AB9
-+
-+#define WATCHDOG_MINOR                          130
-+
-+#define WATCHDOG_IOCTRL_DISABLE                 0x01
-+#define WATCHDOG_IOCTRL_SETTIME                 0x02
-+#define WATCHDOG_IOCTRL_ENABLE                  0x03
-+#define WATCHDOG_IOCTRL_RESTART                 0x04
-+
-+#define WATCHDOG_TIMEOUT_SCALE            APB_CLK
-+#define WATCHDOG_TIMEOUT_MARGIN           30
-+#define WATCHDOG_DRIVER_OPEN              1
-+#define WATCHDOG_DRIVER_CLOSE             0
-+
-+
-+static void     watchdog_disable(void);
-+static void     watchdog_enable(void);
-+static int      watchdog_open(struct inode *, struct file *);
-+static int      watchdog_release(struct inode *, struct file *);
-+static ssize_t  watchdog_read(struct file *, char *, size_t, loff_t *);
-+static ssize_t  watchdog_write(struct file *, const char *, size_t, loff_t *);
-+static int      watchdog_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
-+#ifdef WATCHDOG_TEST
-+static void watchdog_fire(int, void *, struct pt_regs *);
-+#endif
-+
-+
-+
-+
-+
-+#endif
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/xor.h
-@@ -0,0 +1,29 @@
-+/*
-+ * include/asm-arm/arch-sl2312/xor.h
-+ *
-+ * Copyright (C) 2005 Storlink Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef _ASM_ARCH_XOR_H
-+#define _ASM_ARCH_XOR_H
-+
-+/*
-+ * Function prototypes
-+ */
-+void xor_gemini_2(unsigned long bytes, unsigned long *p1, unsigned long *p2);
-+
-+void xor_gemini_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+                           unsigned long *p3);
-+
-+void xor_gemini_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+                           unsigned long *p3, unsigned long *p4);
-+
-+void xor_gemini_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-+                           unsigned long *p3, unsigned long *p4, unsigned long *p5);
-+
-+#endif /* _ASM_ARCH_XOR_H */
-+
---- a/include/asm-arm/cacheflush.h
-+++ b/include/asm-arm/cacheflush.h
-@@ -46,6 +46,18 @@
- # define MULTI_CACHE 1
- #endif
-+/***********************************************************************
-+ *             Storlink SoC -- Cache
-+ ***********************************************************************/
-+#if defined(CONFIG_CPU_FA526)
-+# ifdef _CACHE
-+#  define MULTI_CACHE 1
-+# else
-+#  define _CACHE fa
-+# endif
-+#endif
-+/***********************************************************************/
-+
- #if defined(CONFIG_CPU_ARM926T)
- # ifdef _CACHE
- #  define MULTI_CACHE 1
---- a/include/asm-arm/page.h
-+++ b/include/asm-arm/page.h
-@@ -74,6 +74,18 @@
- # endif
- #endif
-+/***********************************************************************
-+ *             Storlink SoC -- flash
-+ ***********************************************************************/
-+#ifdef CONFIG_CPU_COPY_FA
-+# ifdef _USER
-+#  define MULTI_USER 1
-+# else
-+#  define _USER fa
-+# endif
-+#endif
-+/***********************************************************************/
-+
- #ifdef CONFIG_CPU_SA1100
- # ifdef _USER
- #  define MULTI_USER 1
---- a/include/asm-arm/proc-fns.h
-+++ b/include/asm-arm/proc-fns.h
-@@ -89,6 +89,14 @@
- #   define CPU_NAME cpu_arm922
- #  endif
- # endif
-+# ifdef CONFIG_CPU_FA526
-+#  ifdef CPU_NAME
-+#   undef  MULTI_CPU
-+#   define MULTI_CPU
-+#  else
-+#   define CPU_NAME cpu_fa526
-+#  endif
-+# endif
- # ifdef CONFIG_CPU_ARM925T
- #  ifdef CPU_NAME
- #   undef  MULTI_CPU
---- a/include/asm-arm/tlbflush.h
-+++ b/include/asm-arm/tlbflush.h
-@@ -39,6 +39,8 @@
- #define TLB_V6_D_ASID (1 << 17)
- #define TLB_V6_I_ASID (1 << 18)
-+#define TLB_DINVAL      (1 << 28)
-+#define TLB_BTB         (1 << 29)
- #define TLB_DCLEAN    (1 << 30)
- #define TLB_WB                (1 << 31)
-@@ -52,6 +54,7 @@
-  *      v4wb  - ARMv4 with write buffer without I TLB flush entry instruction
-  *      v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
-  *      v6wbi - ARMv6 with write buffer with I TLB flush entry instruction
-+ *    fa    - ARMv4 with write buffer with UTLB and branch target buffer (BTB)
-  */
- #undef _TLB
- #undef MULTI_TLB
-@@ -86,6 +89,44 @@
- # define v4_always_flags      (-1UL)
- #endif
-+#ifdef CONFIG_CPU_FA_BTB
-+#define __TLB_BTB      TLB_BTB
-+#else
-+#define __TLB_BTB      0
-+#endif
-+
-+#ifdef CONFIG_CPU_FA_WB_DISABLE
-+#define __TLB_WB       0
-+#else
-+#define __TLB_WB       TLB_WB
-+#endif
-+
-+/* Fix buggy CPU which doesn't invalidate Dcache properly */
-+#ifdef CONFIG_CPU_FA520
-+#define __TLB_DINVAL   TLB_DINVAL
-+#elif defined(CONFIG_CPU_FA526)
-+//#define __TLB_DINVAL   TLB_DINVAL
-+#define __TLB_DINVAL   0
-+#else
-+#define __TLB_DINVAL   0
-+#endif
-+
-+#define fa_tlb_flags  (__TLB_WB | __TLB_BTB | __TLB_DINVAL | TLB_DCLEAN | \
-+                         TLB_V4_U_FULL | TLB_V4_U_PAGE)
-+
-+#ifdef CONFIG_CPU_TLB_FA
-+# define fa_possible_flags    fa_tlb_flags
-+# define fa_always_flags      fa_tlb_flags
-+# ifdef _TLB
-+#  define MULTI_TLB 1
-+# else
-+#  define _TLB fa
-+# endif
-+#else
-+# define fa_possible_flags    0
-+# define fa_always_flags      (-1UL)
-+#endif
-+
- #define v4wbi_tlb_flags       (TLB_WB | TLB_DCLEAN | \
-                        TLB_V4_I_FULL | TLB_V4_D_FULL | \
-                        TLB_V4_I_PAGE | TLB_V4_D_PAGE)
-@@ -246,12 +287,14 @@
-                                v4_possible_flags | \
-                                v4wbi_possible_flags | \
-                                v4wb_possible_flags | \
-+                 fa_possible_flags | \
-                                v6wbi_possible_flags)
- #define always_tlb_flags      (v3_always_flags & \
-                                v4_always_flags & \
-                                v4wbi_always_flags & \
-                                v4wb_always_flags & \
-+                 fa_always_flags & \
-                                v6wbi_always_flags)
- #define tlb_flag(f)   ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
-@@ -261,6 +304,9 @@
-       const int zero = 0;
-       const unsigned int __tlb_flag = __cpu_tlb_flags;
-+      if (tlb_flag(TLB_DINVAL))
-+              asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
-+
-       if (tlb_flag(TLB_WB))
-               dsb();
-@@ -281,6 +327,13 @@
-               dsb();
-               isb();
-       }
-+
-+      if (tlb_flag(TLB_BTB))
-+      {
-+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
-+              asm("mov r0, r0" : : );
-+              asm("mov r0, r0" : : );
-+      }
- }
- static inline void local_flush_tlb_mm(struct mm_struct *mm)
-@@ -289,6 +342,9 @@
-       const int asid = ASID(mm);
-       const unsigned int __tlb_flag = __cpu_tlb_flags;
-+      if (tlb_flag(TLB_DINVAL))
-+              asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
-+
-       if (tlb_flag(TLB_WB))
-               dsb();
-@@ -317,6 +373,14 @@
-               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
-               dsb();
-       }
-+
-+      if (tlb_flag(TLB_BTB))
-+      {
-+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
-+              asm("mov r0, r0" : : );
-+              asm("mov r0, r0" : : );
-+      }
-+
- }
- static inline void
-@@ -327,6 +391,9 @@
-       uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
-+      if (tlb_flag(TLB_DINVAL))
-+        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero)); // clean & invalidate data cache all
-+
-       if (tlb_flag(TLB_WB))
-               dsb();
-@@ -357,6 +424,13 @@
-               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
-               dsb();
-       }
-+
-+      if (tlb_flag(TLB_BTB))
-+      {
-+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
-+              asm("mov r0, r0" : : );
-+              asm("mov r0, r0" : : );
-+      }
- }
- static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
-@@ -366,6 +440,9 @@
-       kaddr &= PAGE_MASK;
-+      if (tlb_flag(TLB_DINVAL))
-+        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
-+
-       if (tlb_flag(TLB_WB))
-               dsb();
-@@ -386,6 +463,12 @@
-               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V6_I_PAGE))
-               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
-+      if (tlb_flag(TLB_BTB))
-+      {
-+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
-+              asm("mov r0, r0" : : );
-+              asm("mov r0, r0" : : );
-+      }
-       if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
-                    TLB_V6_I_PAGE | TLB_V6_D_PAGE |
-@@ -412,6 +495,7 @@
-  */
- static inline void flush_pmd_entry(pmd_t *pmd)
- {
-+      const unsigned int zero = 0;
-       const unsigned int __tlb_flag = __cpu_tlb_flags;
-       if (tlb_flag(TLB_DCLEAN))
-@@ -419,15 +503,30 @@
-                       : : "r" (pmd) : "cc");
-       if (tlb_flag(TLB_WB))
-               dsb();
-+
-+      if (tlb_flag(TLB_BTB)) // Luke Lee 05/16/2005
-+      {
-+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
-+              asm("mov r0, r0" : : );
-+              asm("mov r0, r0" : : );
-+      }
- }
- static inline void clean_pmd_entry(pmd_t *pmd)
- {
-+    const unsigned int zero = 0; // Luke Lee 05/16/2005 ins 1
-       const unsigned int __tlb_flag = __cpu_tlb_flags;
-       if (tlb_flag(TLB_DCLEAN))
-               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
-                       : : "r" (pmd) : "cc");
-+
-+      if (tlb_flag(TLB_BTB)) // Luke Lee 05/16/2005
-+      {
-+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
-+              asm("mov r0, r0" : : );
-+              asm("mov r0, r0" : : );
-+      }
- }
- #undef tlb_flag
---- a/include/asm-arm/xor.h
-+++ b/include/asm-arm/xor.h
-@@ -139,3 +139,18 @@
-               xor_speed(&xor_block_8regs);    \
-               xor_speed(&xor_block_32regs);   \
-       } while (0)
-+
-+#ifdef CONFIG_GEMINI_XOR_ACCE
-+#include <asm/arch/xor.h>
-+static struct xor_block_template xor_block_gemini = {
-+      .name   = "gemini xor acceleration",
-+      .do_2   = xor_gemini_2,
-+      .do_3   = xor_gemini_3,
-+      .do_4   = xor_gemini_4,
-+      .do_5   = xor_gemini_5,};
-+#undef XOR_TRY_TEMPLATES
-+#define XOR_TRY_TEMPLATES                     \
-+      do {                                    \
-+      xor_speed(&xor_block_gemini); \
-+      } while (0)
-+#endif
---- a/include/linux/apm_bios.h
-+++ b/include/linux/apm_bios.h
-@@ -217,4 +217,24 @@
- #define APM_IOC_STANDBY               _IO('A', 1)
- #define APM_IOC_SUSPEND               _IO('A', 2)
-+// add by jason for power control
-+struct pwc_ioctl_data {
-+      unsigned int action;    // sword struct
-+      unsigned int data;      // stand shutdown time for PWC_SET_SHUT_TIME
-+                              // stand shutdown source for PWC_WAIT_BTN
-+};
-+
-+#define POWEROFF              0x01
-+#define RESTORE_DEFAULT       0x02
-+#define SYSTEM_REBOOT 0x04
-+
-+#define PWR_SRC_CIR           0x10
-+#define PWR_SRC_RTC           0x20
-+#define PWR_SRC_BTN           0x40
-+
-+#define       PWC_IOCTL_BASE                  'A'                             // use linux APM ioctl
-+#define PWC_SET_SHUT_TIME             _IOW('A', 16, struct pwc_ioctl_data)
-+#define PWC_WAIT_BTN                  _IOR('A', 17, struct pwc_ioctl_data)
-+#define PWC_SHUTDOWN                  _IO ('A', 18)
-+
- #endif        /* LINUX_APM_H */
---- a/kernel/time.c
-+++ b/kernel/time.c
-@@ -76,6 +76,7 @@
-  * why not move it into the appropriate arch directory (for those
-  * architectures that need it).
-  */
-+extern void rtc_set_time_second(unsigned int second);
-  
- asmlinkage long sys_stime(time_t __user *tptr)
- {
-@@ -87,6 +88,10 @@
-       tv.tv_nsec = 0;
-+#ifdef CONFIG_SL2312_RTC
-+    rtc_set_time_second(tv.tv_sec);
-+#endif
-+
-       err = security_settime(&tv, NULL);
-       if (err)
-               return err;
diff --git a/target/linux/storm/patches/1002-gmac.patch b/target/linux/storm/patches/1002-gmac.patch
deleted file mode 100644 (file)
index d6632ba..0000000
+++ /dev/null
@@ -1,18615 +0,0 @@
---- /dev/null
-+++ b/drivers/net/sl2312_emac.c
-@@ -0,0 +1,4604 @@
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/compiler.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/delay.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/completion.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/semaphore.h>
-+#include <asm/arch-sl2312/irqs.h>
-+#include <asm/arch/it8712.h>
-+#include <asm/arch/sl2312.h>
-+#include <linux/mtd/kvctl.h>
-+#include <linux/sysctl_storlink.h>
-+
-+#define BIG_ENDIAN    0
-+
-+#define GMAC_DEBUG      0
-+
-+#define GMAC_PHY_IF     2
-+
-+/* define PHY address */
-+#define HPHY_ADDR   0x01
-+#define GPHY_ADDR   0x02
-+
-+#define CONFIG_ADM_6999 1
-+/* define chip information */
-+#define DRV_NAME                      "SL2312"
-+#define DRV_VERSION                   "0.1.1"
-+#define SL2312_DRIVER_NAME  DRV_NAME " Fast Ethernet driver " DRV_VERSION
-+
-+/* define TX/RX descriptor parameter */
-+#define MAX_ETH_FRAME_SIZE    1920
-+#define TX_BUF_SIZE                   MAX_ETH_FRAME_SIZE
-+#define TX_DESC_NUM                   128
-+#define TX_BUF_TOT_LEN                (TX_BUF_SIZE * TX_DESC_NUM)
-+#define RX_BUF_SIZE                   MAX_ETH_FRAME_SIZE
-+#define RX_DESC_NUM                   256
-+#define RX_BUF_TOT_LEN                (RX_BUF_SIZE * RX_DESC_NUM)
-+#define MAX_ISR_WORK        20
-+
-+unsigned int int_status = 0;
-+
-+/* define GMAC base address */
-+#define GMAC_PHYSICAL_BASE_ADDR           (SL2312_GMAC_BASE)
-+#define GMAC_BASE_ADDR                            (IO_ADDRESS(GMAC_PHYSICAL_BASE_ADDR))
-+#define GMAC_GLOBAL_BASE_ADDR       (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+
-+#define GMAC0_BASE                  (IO_ADDRESS(SL2312_GMAC0_BASE))
-+#define GMAC1_BASE                  (IO_ADDRESS(SL2312_GMAC1_BASE))
-+
-+/* memory management utility */
-+#define DMA_MALLOC(size,handle)               pci_alloc_consistent(NULL,size,handle)
-+#define DMA_MFREE(mem,size,handle)    pci_free_consistent(NULL,size,mem,handle)
-+
-+//#define gmac_read_reg(offset)       (readl(GMAC_BASE_ADDR + offset))
-+//#define gmac_write_reg(offset,data,mask)  writel( (gmac_read_reg(offset)&~mask) |(data&mask),(GMAC_BASE_ADDR+offset))
-+
-+/* define owner bit */
-+#define CPU           0
-+#define DMA           1
-+
-+#define ACTIVE      1
-+#define NONACTIVE   0
-+
-+#define CONFIG_SL_NAPI
-+
-+#ifndef CONFIG_SL2312_MPAGE
-+#define CONFIG_SL2312_MPAGE
-+#endif
-+
-+#ifdef CONFIG_SL2312_MPAGE
-+#include <linux/skbuff.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#endif
-+
-+#ifndef CONFIG_TXINT_DISABLE
-+//#define CONFIG_TXINT_DISABLE
-+#endif
-+
-+enum phy_state
-+{
-+    LINK_DOWN   = 0,
-+    LINK_UP     = 1
-+};
-+
-+
-+/* transmit timeout value */
-+#define TX_TIMEOUT  (6*HZ)
-+
-+/***************************************/
-+/* the offset address of GMAC register */
-+/***************************************/
-+enum GMAC_REGISTER {
-+      GMAC_STA_ADD0   = 0x0000,
-+      GMAC_STA_ADD1   = 0x0004,
-+      GMAC_STA_ADD2   = 0x0008,
-+      GMAC_RX_FLTR    = 0x000c,
-+      GMAC_MCAST_FIL0 = 0x0010,
-+      GMAC_MCAST_FIL1 = 0x0014,
-+      GMAC_CONFIG0    = 0x0018,
-+      GMAC_CONFIG1    = 0x001c,
-+      GMAC_CONFIG2    = 0x0020,
-+      GMAC_BNCR               = 0x0024,
-+      GMAC_RBNR               = 0x0028,
-+      GMAC_STATUS             = 0x002c,
-+      GMAC_IN_DISCARDS= 0x0030,
-+      GMAC_IN_ERRORS  = 0x0034,
-+      GMAC_IN_MCAST   = 0x0038,
-+      GMAC_IN_BCAST   = 0x003c,
-+      GMAC_IN_MAC1    = 0x0040,
-+      GMAC_IN_MAC2    = 0x0044
-+};
-+
-+/*******************************************/
-+/* the offset address of GMAC DMA register */
-+/*******************************************/
-+enum GMAC_DMA_REGISTER {
-+      GMAC_DMA_DEVICE_ID              = 0xff00,
-+      GMAC_DMA_STATUS                 = 0xff04,
-+      GMAC_TXDMA_CTRL                 = 0xff08,
-+      GMAC_TXDMA_FIRST_DESC   = 0xff0c,
-+      GMAC_TXDMA_CURR_DESC    = 0xff10,
-+      GMAC_RXDMA_CTRL                 = 0xff14,
-+      GMAC_RXDMA_FIRST_DESC   = 0xff18,
-+      GMAC_RXDMA_CURR_DESC    = 0xff1c,
-+};
-+
-+/*******************************************/
-+/* the register structure of GMAC          */
-+/*******************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0004
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int sta_add2_l16       : 16;   /* station MAC address2 bits 15 to 0 */
-+              unsigned int sta_add1_h16       : 16;   /* station MAC address1 bits 47 to 32 */
-+#else
-+              unsigned int sta_add1_h16       : 16;   /* station MAC address1 bits 47 to 32 */
-+              unsigned int sta_add2_l16       : 16;   /* station MAC address2 bits 15 to 0 */
-+#endif
-+      } bits;
-+} GMAC_STA_ADD1_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_000c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 27;
-+              unsigned int error                      :  1;   /* enable receive of all error frames */
-+              unsigned int promiscuous        :  1;   /* enable receive of all frames */
-+              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
-+              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
-+              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
-+#else
-+              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
-+              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
-+              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
-+              unsigned int promiscuous        :  1;   /* enable receive of all frames */
-+              unsigned int error                      :  1;   /* enable receive of all error frames */
-+              unsigned int                            : 27;
-+#endif
-+      } bits;
-+} GMAC_RX_FLTR_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0018
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int : 10;
-+              unsigned int inv_rx_clk     : 1;        /* Inverse RX Clock */
-+              unsigned int rising_latch   : 1;
-+        unsigned int rx_tag_remove  :  1;   /* Remove Rx VLAN tag */
-+        unsigned int ipv6_tss_rx_en :  1;   /* IPv6 TSS RX enable */
-+        unsigned int ipv4_tss_rx_en :  1;   /* IPv4 TSS RX enable */
-+        unsigned int rgmii_en       :  1;   /* RGMII in-band status enable */
-+              unsigned int tx_fc_en           :  1;   /* TX flow control enable */
-+              unsigned int rx_fc_en           :  1;   /* RX flow control enable */
-+              unsigned int sim_test           :  1;   /* speed up timers in simulation */
-+              unsigned int dis_col            :  1;   /* disable 16 collisions abort function */
-+              unsigned int dis_bkoff          :  1;   /* disable back-off function */
-+              unsigned int max_len            :  3;   /* maximum receive frame length allowed */
-+              unsigned int adj_ifg            :  4;   /* adjust IFG from 96+/-56 */
-+        unsigned int                :  1;   /* reserved */
-+              unsigned int loop_back          :  1;   /* transmit data loopback enable */
-+              unsigned int dis_rx                     :  1;   /* disable receive */
-+              unsigned int dis_tx                     :  1;   /* disable transmit */
-+#else
-+              unsigned int dis_tx                     :  1;   /* disable transmit */
-+              unsigned int dis_rx                     :  1;   /* disable receive */
-+              unsigned int loop_back          :  1;   /* transmit data loopback enable */
-+        unsigned int                :  1;   /* reserved */
-+              unsigned int adj_ifg            :  4;   /* adjust IFG from 96+/-56 */
-+              unsigned int max_len            :  3;   /* maximum receive frame length allowed */
-+              unsigned int dis_bkoff          :  1;   /* disable back-off function */
-+              unsigned int dis_col            :  1;   /* disable 16 collisions abort function */
-+              unsigned int sim_test           :  1;   /* speed up timers in simulation */
-+              unsigned int rx_fc_en           :  1;   /* RX flow control enable */
-+              unsigned int tx_fc_en           :  1;   /* TX flow control enable */
-+        unsigned int rgmii_en       :  1;   /* RGMII in-band status enable */
-+        unsigned int ipv4_tss_rx_en :  1;   /* IPv4 TSS RX enable */
-+        unsigned int ipv6_tss_rx_en :  1;   /* IPv6 TSS RX enable */
-+        unsigned int rx_tag_remove  :  1;   /* Remove Rx VLAN tag */
-+              unsigned int rising_latch   :  1;
-+              unsigned int inv_rx_clk : 1;    /* Inverse RX Clock */
-+              unsigned int : 10;
-+#endif
-+      } bits;
-+} GMAC_CONFIG0_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_001c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 28;
-+              unsigned int buf_size           :  4;   /* per packet buffer size */
-+#else
-+              unsigned int buf_size           :  4;   /* per packet buffer size */
-+              unsigned int                            : 28;
-+#endif
-+      } bits;
-+} GMAC_CONFIG1_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0020
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rel_threshold      : 16;   /* flow control release threshold */
-+              unsigned int set_threshold      : 16;   /* flow control set threshold */
-+#else
-+              unsigned int set_threshold      : 16;   /* flow control set threshold */
-+              unsigned int rel_threshold      : 16;   /* flow control release threshold */
-+#endif
-+      } bits;
-+} GMAC_CONFIG2_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0024
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 16;
-+              unsigned int buf_num            : 16;   /* return buffer number from software */
-+#else
-+              unsigned int buf_num            : 16;   /* return buffer number from software */
-+              unsigned int                            : 16;
-+#endif
-+      } bits;
-+} GMAC_BNCR_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0028
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 16;
-+              unsigned int buf_remain         : 16;   /* remaining buffer number */
-+#else
-+              unsigned int buf_remain         : 16;   /* remaining buffer number */
-+              unsigned int                            : 16;
-+#endif
-+      } bits;
-+} GMAC_RBNR_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_002c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 25;
-+              unsigned int mii_rmii           :  2;   /* PHY interface type */
-+              unsigned int phy_mode           :  1;   /* PHY interface mode in 10M-bps */
-+              unsigned int duplex                     :  1;   /* duplex mode */
-+              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
-+              unsigned int link                       :  1;   /* link status */
-+#else
-+              unsigned int link                       :  1;   /* link status */
-+              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
-+              unsigned int duplex                     :  1;   /* duplex mode */
-+              unsigned int phy_mode           :  1;   /* PHY interface mode in 10M-bps */
-+              unsigned int mii_rmii           :  2;   /* PHY interface type */
-+              unsigned int                            : 25;
-+#endif
-+      } bits;
-+} GMAC_STATUS_T;
-+
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_009
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 10;
-+              unsigned int tx_fail            :  1;   /* Tx fail interrupt */
-+              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
-+              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
-+              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
-+              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
-+              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
-+              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
-+              unsigned int tx_underrun        :  1;   /* GMAC Tx FIFO underrun interrupt */
-+              unsigned int                            :  6;
-+              unsigned int m_tx_fail          :  1;   /* Tx fail interrupt mask */
-+              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
-+              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
-+              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
-+              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
-+              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
-+              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
-+              unsigned int m_tx_underrun      :  1;   /* GMAC Tx FIFO underrun interrupt mask */
-+#else
-+              unsigned int m_tx_underrun      :  1;   /* GMAC Tx FIFO underrun interrupt mask */
-+              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
-+              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
-+              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
-+              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
-+              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
-+              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
-+              unsigned int m_tx_fail          :  1;   /* Tx fail interrupt mask */
-+              unsigned int                            :  6;
-+              unsigned int tx_underrun        :  1;   /* GMAC Tx FIFO underrun interrupt */
-+              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
-+              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
-+              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
-+              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
-+              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
-+              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
-+              unsigned int tx_fail            :  1;   /* Tx fail interrupt */
-+              unsigned int                            : 10;
-+#endif
-+      } bits;
-+} GMAC_INT_MASK_T;
-+
-+
-+/*******************************************/
-+/* the register structure of GMAC DMA      */
-+/*******************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff00
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                :  7;   /* reserved */
-+              unsigned int s_ahb_err          :  1;   /* Slave AHB bus error */
-+              unsigned int tx_err_code    :  4;   /* TxDMA error code */
-+              unsigned int rx_err_code        :  4;   /* RxDMA error code */
-+              unsigned int device_id          : 12;
-+              unsigned int revision_id        :  4;
-+#else
-+              unsigned int revision_id        :  4;
-+              unsigned int device_id          : 12;
-+              unsigned int rx_err_code        :  4;   /* RxDMA error code */
-+              unsigned int tx_err_code    :  4;   /* TxDMA error code */
-+              unsigned int s_ahb_err          :  1;   /* Slave AHB bus error */
-+              unsigned int                :  7;   /* reserved */
-+#endif
-+      } bits;
-+} GMAC_DMA_DEVICE_ID_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff04
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int ts_finish          :  1;   /* finished tx interrupt */
-+              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
-+              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
-+              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
-+              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
-+              unsigned int rs_finish          :  1;   /* finished rx interrupt */
-+              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
-+              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
-+              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
-+              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
-+              unsigned int                    :  1;   /* Tx fail interrupt */
-+              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
-+              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
-+              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
-+              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
-+              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
-+              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
-+              unsigned int link_change        :  1;   /* GMAC link changed Interrupt for RGMII mode */
-+              unsigned int                    :  1;
-+              unsigned int                    :  1;
-+              unsigned int                            :  3;
-+              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
-+              unsigned int                    :  1;   /* Tx fail interrupt mask */
-+              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
-+              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
-+              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
-+              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
-+              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
-+              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
-+              unsigned int m_link_change      :  1;   /* GMAC link changed Interrupt mask for RGMII mode */
-+#else
-+              unsigned int m_link_change      :  1;   /* GMAC link changed Interrupt mask for RGMII mode */
-+              unsigned int m_rx_overrun       :  1;   /* GMAC Rx FIFO overrun interrupt mask */
-+              unsigned int m_tx_pause_off     :  1;   /* received pause off frame interrupt mask */
-+              unsigned int m_rx_pause_off :  1;       /* received pause off frame interrupt mask */
-+              unsigned int m_tx_pause_on  :  1;       /* transmit pause on frame interrupt mask */
-+              unsigned int m_rx_pause_on      :  1;   /* received pause on frame interrupt mask */
-+              unsigned int m_cnt_full         :  1;   /* MIB counters half full interrupt mask */
-+              unsigned int                    :  1;   /* Tx fail interrupt mask */
-+              unsigned int loop_back          :  1;   /* loopback TxDMA to RxDMA */
-+              unsigned int                            :  3;
-+              unsigned int                    :  1;
-+              unsigned int                    :  1;
-+              unsigned int link_change        :  1;   /* GMAC link changed Interrupt for RGMII mode */
-+              unsigned int rx_overrun         :  1;   /* GMAC Rx FIFO overrun interrupt */
-+              unsigned int tx_pause_off       :  1;   /* received pause off frame interrupt */
-+              unsigned int rx_pause_off   :  1;       /* received pause off frame interrupt */
-+              unsigned int tx_pause_on        :  1;   /* transmit pause on frame interrupt */
-+              unsigned int rx_pause_on        :  1;   /* received pause on frame interrupt */
-+              unsigned int cnt_full           :  1;   /* MIB counters half full interrupt */
-+              unsigned int                    :  1;   /* Tx fail interrupt */
-+              unsigned int rs_eofi            :  1;   /* RxDMA end of frame interrupt */
-+              unsigned int rs_eodi            :  1;   /* RxDMA end of descriptor interrupt */
-+              unsigned int rs_perr            :  1;   /* Rx Descriptor protocol error */
-+              unsigned int rs_derr            :  1;   /* AHB Bus Error while rx */
-+              unsigned int rs_finish          :  1;   /* finished rx interrupt */
-+              unsigned int ts_eofi            :  1;   /* TxDMA end of frame interrupt */
-+              unsigned int ts_eodi            :  1;   /* TxDMA end of descriptor interrupt */
-+              unsigned int ts_perr            :  1;   /* Tx Descriptor protocol error */
-+              unsigned int ts_derr            :  1;   /* AHB Bus Error while tx */
-+              unsigned int ts_finish          :  1;   /* finished tx interrupt */
-+#endif
-+      } bits;
-+} GMAC_DMA_STATUS_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff08
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int td_start           :  1;   /* Start DMA transfer */
-+              unsigned int td_continue        :  1;   /* Continue DMA operation */
-+              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int                            :  1;
-+              unsigned int td_prot            :  4;   /* TxDMA protection control */
-+              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
-+              unsigned int td_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
-+              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int                            : 14;
-+#else
-+              unsigned int                            : 14;
-+              unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int td_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int td_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int td_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int td_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
-+              unsigned int td_burst_size  :  2;       /* TxDMA max burst size for every AHB request */
-+              unsigned int td_prot            :  4;   /* TxDMA protection control */
-+              unsigned int                            :  1;
-+              unsigned int td_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int td_continue        :  1;   /* Continue DMA operation */
-+              unsigned int td_start           :  1;   /* Start DMA transfer */
-+#endif
-+      } bits;
-+} GMAC_TXDMA_CTRL_T;
-+
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff0c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
-+              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
-+              unsigned int                                    :  3;
-+#else
-+              unsigned int                                    :  3;
-+              unsigned int td_busy                    :  1;/* 1-TxDMA busy; 0-TxDMA idle */
-+              unsigned int td_first_des_ptr   : 28;/* first descriptor address */
-+#endif
-+      } bits;
-+} GMAC_TXDMA_FIRST_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff10
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int                            :  1;
-+              unsigned int sof_eof            :  2;
-+#else
-+              unsigned int sof_eof            :  2;
-+              unsigned int                            :  1;
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+#endif
-+      } bits;
-+} GMAC_TXDMA_CURR_DESC_T;
-+
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff14
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rd_start           :  1;   /* Start DMA transfer */
-+              unsigned int rd_continue        :  1;   /* Continue DMA operation */
-+              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int                            :  1;
-+              unsigned int rd_prot            :  4;   /* DMA protection control */
-+              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
-+              unsigned int rd_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
-+              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int                            : 14;
-+#else
-+              unsigned int                            : 14;
-+              unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_eod_en          :  1;   /* End of Descriptor interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_perr_en         :  1;   /* Protocol Failure Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_fail_en         :  1;   /* DMA Fail Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_finish_en   :  1;       /* DMA Finish Event Interrupt Enable;1-enable;0-mask */
-+              unsigned int rd_endian          :  1;   /* AHB Endian. 0-little endian; 1-big endian */
-+              unsigned int rd_bus                 :  2;       /* peripheral bus width;0x->8 bits,10->16 bits,11->32 bits */
-+              unsigned int rd_burst_size  :  2;       /* DMA max burst size for every AHB request */
-+              unsigned int rd_prot            :  4;   /* DMA protection control */
-+              unsigned int                            :  1;
-+              unsigned int rd_chain_mode      :  1;   /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
-+              unsigned int rd_continue        :  1;   /* Continue DMA operation */
-+              unsigned int rd_start           :  1;   /* Start DMA transfer */
-+#endif
-+      } bits;
-+} GMAC_RXDMA_CTRL_T;
-+
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff18
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
-+              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
-+              unsigned int                                    :  3;
-+#else
-+              unsigned int                                    :  3;
-+              unsigned int rd_busy                    :  1;/* 1-RxDMA busy; 0-RxDMA idle */
-+              unsigned int rd_first_des_ptr   : 28;/* first descriptor address */
-+#endif
-+      } bits;
-+} GMAC_RXDMA_FIRST_DESC_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit2_ff1c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int                            :  1;
-+              unsigned int sof_eof            :  2;
-+#else
-+              unsigned int sof_eof            :  2;
-+              unsigned int                            :  1;
-+              unsigned int eofie                      :  1;   /* end of frame interrupt enable */
-+              unsigned int ndar                       : 28;   /* next descriptor address */
-+#endif
-+      } bits;
-+} GMAC_RXDMA_CURR_DESC_T;
-+
-+
-+/********************************************/
-+/*          Descriptor Format               */
-+/********************************************/
-+
-+typedef struct descriptor_t
-+{
-+      union frame_control_t
-+      {
-+              unsigned int bits32;
-+              struct bits_0000
-+              {
-+#if (BIG_ENDIAN==1)
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int csum_state : 3;    /* checksum error status */
-+                      unsigned int vlan_tag   : 1;    /* 802.1q vlan tag packet */
-+                      unsigned int frame_state: 3;    /* reference Rx Status1 */
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+#else
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int frame_state: 3;    /* reference Rx Status1 */
-+                      unsigned int vlan_tag   : 1;    /* 802.1q vlan tag packet */
-+                      unsigned int csum_state : 3;    /* checksum error status */
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+#endif
-+              } bits_rx;
-+
-+              struct bits_0001
-+              {
-+#if (BIG_ENDIAN==1)
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int            : 6;
-+                      unsigned int success_tx : 1;    /* successful transmitted */
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+#else
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int success_tx : 1;    /* successful transmitted */
-+                      unsigned int            : 6;
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+#endif
-+        } bits_tx_in;
-+
-+              struct bits_0002
-+              {
-+#if (BIG_ENDIAN==1)
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int            : 2;
-+                      unsigned int udp_csum_en: 1;    /* TSS UDP checksum enable */
-+                      unsigned int tcp_csum_en: 1;    /* TSS TCP checksum enable */
-+                      unsigned int ipv6_tx_en : 1;    /* TSS IPv6 TX enable */
-+                      unsigned int ip_csum_en : 1;    /* TSS IPv4 IP Header checksum enable */
-+                      unsigned int vlan_enable: 1;    /* VLAN TIC insertion enable */
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+#else
-+                      unsigned int buffer_size:16;    /* transfer buffer size associated with current description*/
-+                      unsigned int desc_count : 6;    /* number of descriptors used for the current frame */
-+                      unsigned int vlan_enable: 1;    /* VLAN TIC insertion enable */
-+                      unsigned int ip_csum_en : 1;    /* TSS IPv4 IP Header checksum enable */
-+                      unsigned int ipv6_tx_en : 1;    /* TSS IPv6 TX enable */
-+                      unsigned int tcp_csum_en: 1;    /* TSS TCP checksum enable */
-+                      unsigned int udp_csum_en: 1;    /* TSS UDP checksum enable */
-+                      unsigned int            : 2;
-+                      unsigned int perr               : 1;    /* protocol error during processing this descriptor */
-+                      unsigned int derr               : 1;    /* data error during processing this descriptor */
-+                      unsigned int own                : 1;    /* owner bit. 0-CPU, 1-DMA */
-+#endif
-+        } bits_tx_out;
-+
-+      } frame_ctrl;
-+
-+      union flag_status_t
-+      {
-+              unsigned int bits32;
-+              struct bits_0004
-+              {
-+#if (BIG_ENDIAN==1)
-+            unsigned int priority   : 3;    /* user priority extracted from receiving frame*/
-+            unsigned int cfi        : 1;      /* cfi extracted from receiving frame*/
-+                      unsigned int vlan_id    :12;    /* VLAN ID extracted from receiving frame */
-+                      unsigned int frame_count:16;    /* received frame byte count,include CRC,not include VLAN TIC */
-+#else
-+                      unsigned int frame_count:16;    /* received frame byte count,include CRC,not include VLAN TIC */
-+                      unsigned int vlan_id    :12;    /* VLAN ID extracted from receiving frame */
-+            unsigned int cfi        : 1;      /* cfi extracted from receiving frame*/
-+            unsigned int priority   : 3;    /* user priority extracted from receiving frame*/
-+#endif
-+              } bits_rx_status;
-+
-+              struct bits_0005
-+              {
-+#if (BIG_ENDIAN==1)
-+            unsigned int priority   : 3;    /* user priority to transmit*/
-+            unsigned int cfi        : 1;      /* cfi to transmit*/
-+                      unsigned int vlan_id    :12;    /* VLAN ID to transmit */
-+                      unsigned int frame_count:16;    /* total tx frame byte count */
-+#else
-+                      unsigned int frame_count:16;    /* total tx frame byte count */
-+                      unsigned int vlan_id    :12;    /* VLAN ID to transmit */
-+            unsigned int cfi        : 1;      /* cfi to transmit*/
-+            unsigned int priority   : 3;    /* user priority to transmit*/
-+#endif
-+              } bits_tx_flag;
-+      } flag_status;
-+
-+      unsigned int buf_adr;   /* data buffer address */
-+
-+      union next_desc_t
-+      {
-+              unsigned int next_descriptor;
-+              struct bits_000c
-+              {
-+#if (BIG_ENDIAN==1)
-+                      unsigned int ndar               :28;    /* next descriptor address */
-+                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
-+                      unsigned int                    : 1;
-+                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
-+                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
-+#else
-+                      unsigned int sof_eof    : 2;    /* 00-the linking descriptor   01-the last descriptor of a frame*/
-+                                                      /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
-+                      unsigned int                    : 1;
-+                      unsigned int eofie              : 1;    /* end of frame interrupt enable */
-+                      unsigned int ndar               :28;    /* next descriptor address */
-+#endif
-+              } bits;
-+      } next_desc;
-+} GMAC_DESCRIPTOR_T;
-+
-+typedef struct gmac_conf {
-+      struct net_device *dev;
-+      int portmap;
-+      int vid;
-+      int flag;     /* 1: active  0: non-active */
-+} sys_gmac_conf;
-+
-+struct gmac_private {
-+      unsigned char       *tx_bufs;   /* Tx bounce buffer region. */
-+      unsigned char       *rx_bufs;
-+      GMAC_DESCRIPTOR_T       *tx_desc;       /* point to virtual TX descriptor address*/
-+      GMAC_DESCRIPTOR_T       *rx_desc;       /* point to virtual RX descriptor address*/
-+      GMAC_DESCRIPTOR_T       *tx_cur_desc;   /* point to current TX descriptor */
-+      GMAC_DESCRIPTOR_T       *rx_cur_desc;   /* point to current RX descriptor */
-+      GMAC_DESCRIPTOR_T   *tx_finished_desc;
-+      GMAC_DESCRIPTOR_T   *rx_finished_desc;
-+      unsigned long       cur_tx;
-+      unsigned int        cur_rx;     /* Index into the Rx buffer of next Rx pkt. */
-+      unsigned int        tx_flag;
-+      unsigned long       dirty_tx;
-+      unsigned char       *tx_buf[TX_DESC_NUM];       /* Tx bounce buffers */
-+      dma_addr_t          tx_desc_dma; /* physical TX descriptor address */
-+      dma_addr_t          rx_desc_dma;        /* physical RX descriptor address */
-+      dma_addr_t          tx_bufs_dma; /* physical TX descriptor address */
-+      dma_addr_t          rx_bufs_dma; /* physical RX descriptor address */
-+    struct net_device_stats  stats;
-+      pid_t               thr_pid;
-+      wait_queue_head_t   thr_wait;
-+      struct completion   thr_exited;
-+    spinlock_t          lock;
-+    int                 time_to_die;
-+      unsigned int            tx_desc_hdr[GMAC_PHY_IF];       /* the descriptor which sw can fill */
-+      unsigned int            tx_desc_tail[GMAC_PHY_IF];      /* the descriptor which is not cleaned yet */
-+};
-+
-+
-+struct reg_ioctl_data {
-+    unsigned int    reg_addr;   /* the register address */
-+    unsigned int    val_in;     /* data write to the register */
-+    unsigned int    val_out;    /* data read from the register */
-+};
-+
-+#ifdef CONFIG_SL2312_MPAGE
-+typedef struct tx_data_t {
-+      int     freeable; // 1 when it's skb. it can be freed in tx interrupt handler
-+      struct sk_buff* skb; // skb
-+      int     desc_in_use; // 1 when the desc is in use. 0 when desc is available.
-+      long end_seq; // to find out packets are in seq.
-+      // so this value is the seq of next packet.
-+} tx_data;
-+#endif
-+
-+/*************************************************************
-+ *         Global Variable
-+ *************************************************************/
-+struct semaphore        sem_gmac;   /* semaphore for share pins issue */
-+
-+/*************************************************************
-+ *        Static Global Variable
-+ *************************************************************/
-+// static unsigned int     MAC_BASE_ADDR = GMAC0_BASE;
-+static unsigned int     gmac_base_addr[GMAC_PHY_IF] = {GMAC0_BASE,GMAC1_BASE};
-+static unsigned int     gmac_irq[GMAC_PHY_IF] = {IRQ_GMAC0,IRQ_GMAC1};
-+static struct net_device *gmac_dev[GMAC_PHY_IF];
-+
-+static unsigned int     FLAG_SWITCH=0;        /* if 1-->switch chip presented. if 0-->switch chip unpresented */
-+static unsigned int     flow_control_enable[GMAC_PHY_IF] = {1,1};
-+static unsigned int     pre_phy_status[GMAC_PHY_IF] = {LINK_DOWN,LINK_DOWN};
-+static unsigned int     tx_desc_virtual_base[GMAC_PHY_IF];
-+static unsigned int     rx_desc_virtual_base[GMAC_PHY_IF];
-+static unsigned int     full_duplex = 1;
-+static unsigned int     speed = 1;
-+#ifdef CONFIG_SL2312_MPAGE
-+static tx_data                    tx_skb[GMAC_PHY_IF][TX_DESC_NUM];
-+#else
-+static struct sk_buff   *tx_skb[GMAC_PHY_IF][TX_DESC_NUM];
-+#endif
-+static struct sk_buff   *rx_skb[GMAC_PHY_IF][RX_DESC_NUM];
-+static unsigned int     tx_desc_start_adr[GMAC_PHY_IF];
-+static unsigned int     rx_desc_start_adr[GMAC_PHY_IF];
-+static unsigned char    eth0_mac[6]= {0x00,0x50,0xc2,0x2b,0xd3,0x25};
-+static unsigned char    eth1_mac[6]= {0x00,0x50,0xc2,0x2b,0xdf,0xfe};
-+static unsigned int     next_tick = 3 * HZ;
-+
-+static unsigned int     phy_addr[GMAC_PHY_IF] = {0x01,0x02};  /* define PHY address */
-+
-+DECLARE_WAIT_QUEUE_HEAD(gmac_queue);
-+//static      wait_queue_t    wait;
-+
-+struct gmac_conf VLAN_conf[] = {
-+#ifdef CONFIG_ADM_6999
-+      { (struct net_device *)0,0x7F,1 },
-+      { (struct net_device *)0,0x80,2 }
-+#endif
-+#ifdef CONFIG_ADM_6996
-+      { (struct net_device *)0,0x0F,1 },
-+      { (struct net_device *)0,0x10,2 }
-+#endif
-+};
-+
-+#define NUM_VLAN_IF   (sizeof(VLAN_conf)/sizeof(struct gmac_conf))
-+
-+
-+/************************************************/
-+/*            GMAC function declare             */
-+/************************************************/
-+
-+unsigned int mii_read(unsigned char phyad,unsigned char regad);
-+void mii_write(unsigned char phyad,unsigned char regad,unsigned int value);
-+static void gmac_set_phy_status(struct net_device *dev);
-+static void gmac_get_phy_status(struct net_device *dev);
-+static int gmac_phy_thread (void *data);
-+static int gmac_set_mac_address(struct net_device *dev, void *addr);
-+static void gmac_tx_timeout(struct net_device *dev);
-+static void gmac_tx_packet_complete(struct net_device *dev);
-+static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev);
-+static void gmac_set_rx_mode(struct net_device *dev);
-+static void gmac_rx_packet(struct net_device *dev);
-+static int gmac_open (struct net_device *dev);
-+static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-+
-+static unsigned int gmac_get_dev_index(struct net_device *dev);
-+static unsigned int gmac_select_interface(struct net_device *dev);
-+
-+#ifdef CONFIG_SL2312_MPAGE
-+int printk_all(int dev_index, struct gmac_private* tp);
-+#endif
-+
-+/****************************************/
-+/*    SPI Function Declare            */
-+/****************************************/
-+void SPI_write(unsigned char addr,unsigned int value);
-+unsigned int SPI_read(unsigned char table,unsigned char addr);
-+void SPI_write_bit(char bit_EEDO);
-+unsigned int SPI_read_bit(void);
-+void SPI_default(void);
-+void SPI_reset(unsigned char rstype,unsigned char port_cnt);
-+void SPI_pre_st(void);
-+void SPI_CS_enable(unsigned char enable);
-+void SPI_Set_VLAN(unsigned char LAN,unsigned int port_mask);
-+void SPI_Set_tag(unsigned int port,unsigned tag);
-+void SPI_Set_PVID(unsigned int PVID,unsigned int port_mask);
-+unsigned int SPI_Get_PVID(unsigned int port);
-+void SPI_mac_lock(unsigned int port, unsigned char lock);
-+void SPI_get_port_state(unsigned int port);
-+void SPI_port_enable(unsigned int port,unsigned char enable);
-+unsigned int SPI_get_identifier(void);
-+void SPI_get_status(unsigned int port);
-+
-+/****************************************/
-+/*    VLAN Function Declare                   */
-+/****************************************/
-+int getVLANfromdev (struct net_device *dev );
-+struct net_device * getdevfromVLAN( int VID);
-+
-+
-+
-+/************************************************/
-+/*                 function body                */
-+/************************************************/
-+#if 0
-+void hw_memcpy(void *to,const void *from,unsigned long n)
-+{
-+    writel(from,SL2312_DRAM_CTRL_BASE+0x20);  /* set source address */
-+    writel(to,SL2312_DRAM_CTRL_BASE+0x24);    /* set destination address */
-+    writel(n,SL2312_DRAM_CTRL_BASE+0x28);     /* set byte count */
-+    writel(0x00000001,SL2312_DRAM_CTRL_BASE+0x2c);
-+    while (readl(SL2312_DRAM_CTRL_BASE+0x2c));
-+}
-+#endif
-+
-+static unsigned int gmac_read_reg(unsigned int addr)
-+{
-+    unsigned int    reg_val;
-+//    unsigned int    flags;
-+//    spinlock_t     lock;
-+
-+//    spin_lock_irqsave(&lock, flags);
-+    reg_val = readl(addr);    // Gary Chen
-+//    spin_unlock_irqrestore(&lock, flags);
-+      return (reg_val);
-+}
-+
-+static void gmac_write_reg(unsigned int addr,unsigned int data,unsigned int bit_mask)
-+{
-+      unsigned int    reg_val;
-+    //unsigned int    *addr;
-+//    unsigned int    flags;
-+//    spinlock_t     lock;
-+
-+//    spin_lock_irqsave(&lock, flags);
-+      reg_val = ( gmac_read_reg(addr) & (~bit_mask) ) | (data & bit_mask);
-+    writel(reg_val,addr);
-+//    spin_unlock_irqrestore(&lock, flags);
-+      return;
-+}
-+
-+
-+static void gmac_sw_reset(struct net_device *dev)
-+{
-+    unsigned int    index;
-+    unsigned int    reg_val;
-+
-+    index = gmac_get_dev_index(dev);
-+    if (index==0)
-+        reg_val = readl(GMAC_GLOBAL_BASE_ADDR+0x0c) | 0x00000020;   /* GMAC0 S/W reset */
-+    else
-+        reg_val = readl(GMAC_GLOBAL_BASE_ADDR+0x0c) | 0x00000040;   /* GMAC1 S/W reset */
-+
-+    writel(reg_val,GMAC_GLOBAL_BASE_ADDR+0x0c);
-+    return;
-+}
-+
-+static void gmac_get_mac_address(void)
-+{
-+#ifdef CONFIG_MTD
-+      extern int get_vlaninfo(vlaninfo* vlan);
-+    static vlaninfo    vlan[2];
-+
-+    if (get_vlaninfo(&vlan[0]))
-+    {
-+        memcpy(eth0_mac,vlan[0].mac,6);
-+        VLAN_conf[0].vid = vlan[0].vlanid;
-+        VLAN_conf[0].portmap = vlan[0].vlanmap;
-+        memcpy(eth1_mac,vlan[1].mac,6);
-+        VLAN_conf[1].vid = vlan[1].vlanid;
-+        VLAN_conf[1].portmap = vlan[1].vlanmap;
-+    }
-+#else
-+    unsigned int reg_val;
-+
-+    reg_val = readl(IO_ADDRESS(SL2312_SECURITY_BASE)+0xac);
-+    eth0_mac[4] = (reg_val & 0xff00) >> 8;
-+    eth0_mac[5] = reg_val & 0x00ff;
-+    reg_val = readl(IO_ADDRESS(SL2312_SECURITY_BASE)+0xac);
-+    eth1_mac[4] = (reg_val & 0xff00) >> 8;
-+    eth1_mac[5] = reg_val & 0x00ff;
-+#endif
-+    return;
-+}
-+
-+static unsigned int gmac_get_dev_index(struct net_device *dev)
-+{
-+    unsigned int    i;
-+
-+    /* get device index number */
-+    for (i=0;i<GMAC_PHY_IF;i++)
-+    {
-+        if (gmac_dev[i]==dev)
-+        {
-+            return(i);
-+        }
-+    }
-+    return (0xff);
-+}
-+
-+static unsigned int gmac_select_interface(struct net_device *dev)
-+{
-+    unsigned int    index;
-+
-+    index = gmac_get_dev_index(dev);
-+    // MAC_BASE_ADDR = gmac_base_addr[index]; // Gary Chen
-+    return (index);
-+}
-+
-+
-+static void gmac_dump_register(struct net_device *dev)
-+{
-+#if 0
-+    unsigned int   i,val,index;
-+
-+    index = gmac_select_interface(dev);
-+
-+    printk("========== GMAC%d ==========\n",index);
-+    for (i=0;i<=0x7c;i=i+4)
-+    {
-+        val = gmac_read_reg(gmac_base_addr[index] + i);
-+        printk("offset = %08x   value = %08x\n",i,val);
-+    }
-+    for (i=0xff00;i<=0xff7c;i=i+4)
-+    {
-+        val = gmac_read_reg(gmac_base_addr[index] + i);
-+        printk("offset = %08x   value = %08x\n",i,val);
-+    }
-+#endif
-+}
-+
-+static int gmac_init_chip(struct net_device *dev)
-+{
-+      GMAC_RBNR_T             rbnr_val,rbnr_mask;
-+      GMAC_CONFIG2_T  config2_val;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+      GMAC_CONFIG1_T  config1;
-+      struct sockaddr sock;
-+      unsigned int    status;
-+      unsigned int    phy_mode;
-+      unsigned int    index;
-+
-+    index = gmac_get_dev_index(dev);
-+
-+    /* set GMAC RMII mode */
-+    if (index==0)
-+        phy_mode = 0;   /* 0->MII 1->GMII 2->RGMII(10/100) 3->RGMII(1000) */
-+    else
-+        phy_mode = 2;   /* 0->MII 1->GMII 2->RGMII(10/100) 3->RGMII(1000) */
-+
-+    /* set PHY operation mode */
-+    status = (phy_mode<<5) | 0x11 | (full_duplex<<3) | (speed<<1);
-+    gmac_write_reg(gmac_base_addr[index] + GMAC_STATUS,status ,0x0000007f);
-+
-+      /* set station MAC address1 and address2 */
-+      if (index==0)
-+          memcpy(&sock.sa_data[0],&eth0_mac[0],6);
-+    else
-+          memcpy(&sock.sa_data[0],&eth1_mac[0],6);
-+    gmac_set_mac_address(dev,(void *)&sock);
-+
-+    /* set RX_FLTR register to receive all multicast packet */
-+    gmac_write_reg(gmac_base_addr[index] + GMAC_RX_FLTR,0x0000001F,0x0000001f);
-+    //gmac_write_reg(gmac_base_addr[index] + GMAC_RX_FLTR,0x00000007,0x0000001f);
-+
-+      /* set per packet buffer size */
-+      config1.bits32 = 0;
-+    config1.bits.buf_size = 11; /* buffer size = 2048-byte */
-+    gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG1,config1.bits32,0x0000000f);
-+
-+      /* set flow control threshold */
-+      config2_val.bits32 = 0;
-+      config2_val.bits.set_threshold = RX_DESC_NUM/4;
-+      config2_val.bits.rel_threshold = RX_DESC_NUM*3/4;
-+      gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG2,config2_val.bits32,0xffffffff);
-+
-+      /* init remaining buffer number register */
-+      rbnr_val.bits32 = 0;
-+      rbnr_val.bits.buf_remain = RX_DESC_NUM;
-+      rbnr_mask.bits32 = 0;
-+      rbnr_mask.bits.buf_remain = 0xffff;
-+      gmac_write_reg(gmac_base_addr[index] + GMAC_RBNR,rbnr_val.bits32,rbnr_mask.bits32);
-+
-+    /* disable TX/RX and disable internal loop back */
-+    config0.bits32 = 0;
-+    config0_mask.bits32 = 0;
-+    config0.bits.max_len = 2;
-+    if (flow_control_enable[index]==1)
-+    {
-+        config0.bits.tx_fc_en = 1; /* enable tx flow control */
-+        config0.bits.rx_fc_en = 1; /* enable rx flow control */
-+        printk("Enable MAC Flow Control...\n");
-+    }
-+    else
-+    {
-+        config0.bits.tx_fc_en = 0; /* disable tx flow control */
-+        config0.bits.rx_fc_en = 0; /* disable rx flow control */
-+        printk("Disable MAC Flow Control...\n");
-+    }
-+    config0.bits.dis_rx = 1;  /* disable rx */
-+    config0.bits.dis_tx = 1;  /* disable tx */
-+    config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
-+      config0.bits.inv_rx_clk = 0;
-+      config0.bits.rising_latch = 1;
-+      config0.bits.ipv4_tss_rx_en = 1;  /* enable H/W to check ip checksum */
-+      config0.bits.ipv6_tss_rx_en = 1;  /* enable H/W to check ip checksum */
-+
-+    config0_mask.bits.max_len = 7;
-+    config0_mask.bits.tx_fc_en = 1;
-+    config0_mask.bits.rx_fc_en = 1;
-+    config0_mask.bits.dis_rx = 1;
-+    config0_mask.bits.dis_tx = 1;
-+    config0_mask.bits.loop_back = 1;
-+    config0_mask.bits.inv_rx_clk = 1;
-+      config0_mask.bits.rising_latch = 1;
-+      config0_mask.bits.ipv4_tss_rx_en = 1;
-+      config0_mask.bits.ipv6_tss_rx_en = 1;
-+    gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+
-+      return (0);
-+}
-+
-+static void gmac_enable_tx_rx(struct net_device *dev)
-+{
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+      int                             dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+    /* enable TX/RX */
-+    config0.bits32 = 0;
-+    config0_mask.bits32 = 0;
-+    config0.bits.dis_rx = 0;  /* enable rx */
-+    config0.bits.dis_tx = 0;  /* enable tx */
-+    config0_mask.bits.dis_rx = 1;
-+    config0_mask.bits.dis_tx = 1;
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+}
-+
-+static void gmac_disable_tx_rx(struct net_device *dev)
-+{
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+      int                             dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+    /* enable TX/RX */
-+    config0.bits32 = 0;
-+    config0_mask.bits32 = 0;
-+    config0.bits.dis_rx = 1;  /* disable rx */
-+    config0.bits.dis_tx = 1;  /* disable tx */
-+    config0_mask.bits.dis_rx = 1;
-+    config0_mask.bits.dis_tx = 1;
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+}
-+
-+#ifdef CONFIG_SL_NAPI
-+static int gmac_rx_poll_ga(struct net_device *dev, int *budget)
-+{
-+      struct gmac_private *tp = dev->priv;
-+      struct sk_buff          *skb;
-+    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
-+      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
-+    GMAC_DESCRIPTOR_T   *rx_desc;
-+      unsigned int            pkt_size;
-+      unsigned int        desc_count;
-+    unsigned int        vid;
-+//    unsigned int        priority;
-+      unsigned int        own;
-+      unsigned int        good_frame = 0;
-+      unsigned int        index;
-+      unsigned int        dev_index;
-+      int                 work = 0;
-+      int                 work_done = 0;
-+      int                 quota = min(dev->quota, *budget);
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      for (;;)
-+      {
-+        own = tp->rx_cur_desc->frame_ctrl.bits32 >> 31;
-+        if (own == CPU) /* check owner bit */
-+        {
-+              rx_desc = tp->rx_cur_desc;
-+#if (GMAC_DEBUG==1)
-+              /* check error interrupt */
-+              if ( (rx_desc->frame_ctrl.bits_rx.derr==1)||(rx_desc->frame_ctrl.bits_rx.perr==1) )
-+              {
-+              printk("%s::Rx Descriptor Processing Error !!!\n",__func__);
-+          }
-+#endif
-+          /* get frame information from the first descriptor of the frame */
-+              pkt_size = rx_desc->flag_status.bits_rx_status.frame_count - 4;  /*total byte count in a frame*/
-+#if (GMAC_DEBUG==1)
-+            priority = rx_desc->flag_status.bits_rx_status.priority;    /* 802.1p priority */
-+#endif
-+            vid = rx_desc->flag_status.bits_rx_status.vlan_id;          /* 802.1q vlan id */
-+            if (vid == 0)
-+            {
-+                vid = 1;    /* default vlan */
-+            }
-+              desc_count = rx_desc->frame_ctrl.bits_rx.desc_count; /* get descriptor count per frame */
-+
-+              if (rx_desc->frame_ctrl.bits_rx.frame_state == 0x000) /* good frame */
-+              {
-+                      tp->stats.rx_bytes += pkt_size;
-+                      tp->stats.rx_packets++;
-+                      good_frame = 1;
-+              }
-+              else
-+              {
-+                      tp->stats.rx_errors++;
-+                      good_frame = 0;
-+                      printk("RX status: 0x%x\n",rx_desc->frame_ctrl.bits_rx.frame_state);
-+              }
-+      }
-+      else
-+      {
-+          work_done = 1;
-+          break;  /* Rx process is completed */
-+      }
-+
-+        if (good_frame == 1)
-+        {
-+            /* get rx skb buffer index */
-+            index = ((unsigned int)tp->rx_cur_desc - rx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+            if (rx_skb[dev_index][index])
-+            {
-+                skb_reserve (rx_skb[dev_index][index], 2);    /* 16 byte align the IP fields. */
-+                rx_skb[dev_index][index]->dev = dev;
-+                rx_skb[dev_index][index]->ip_summed = CHECKSUM_UNNECESSARY;
-+                          skb_put(rx_skb[dev_index][index],pkt_size);
-+                          rx_skb[dev_index][index]->protocol = eth_type_trans(rx_skb[dev_index][index],dev); /* set skb protocol */
-+                          netif_rx(rx_skb[dev_index][index]);  /* socket rx */
-+                          dev->last_rx = jiffies;
-+
-+                          /* allocate rx skb buffer */
-+                if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-+                {
-+                    printk("%s::skb buffer allocation fail !\n",__func__);
-+                }
-+                rx_skb[dev_index][index] = skb;
-+                tp->rx_cur_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
-+            }
-+            else
-+            {
-+                printk("%s::rx skb index error !\n",__func__);
-+            }
-+        }
-+
-+          tp->rx_cur_desc->frame_ctrl.bits_rx.own = DMA; /* release rx descriptor to DMA */
-+        /* point to next rx descriptor */
-+        tp->rx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->rx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+rx_desc_virtual_base[dev_index]);
-+
-+        /* release buffer to Remaining Buffer Number Register */
-+        if (flow_control_enable[dev_index] ==1)
-+        {
-+//            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_BNCR,desc_count,0x0000ffff);
-+            writel(desc_count,(unsigned int *)(gmac_base_addr[dev_index] + GMAC_BNCR));
-+        }
-+
-+              if (work++ >= quota )
-+              {
-+                      break;
-+              }
-+    }
-+
-+    /* if RX DMA process is stoped , restart it */
-+      rxdma_busy.bits.rd_first_des_ptr = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC);
-+      if (rxdma_busy.bits.rd_busy == 0)
-+      {
-+          rxdma_ctrl.bits32 = 0;
-+      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
-+          rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
-+          rxdma_ctrl_mask.bits32 = 0;
-+      rxdma_ctrl_mask.bits.rd_start = 1;
-+          rxdma_ctrl_mask.bits.rd_continue = 1;
-+          gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
-+    }
-+
-+      dev->quota -= work;
-+      *budget -= work;
-+      if (work_done==1)
-+      {
-+          /* Receive descriptor is empty now */
-+        netif_rx_complete(dev);
-+        /* enable receive interrupt */
-+        gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,0x0007c000,0x0007c000);   /* enable rx interrupt */
-+        return 0;
-+    }
-+    else
-+    {
-+        return -1;
-+    }
-+}
-+
-+static int gmac_rx_poll_gb(struct net_device *dev, int *budget)
-+{
-+      struct gmac_private *tp = dev->priv;
-+      struct sk_buff          *skb;
-+    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
-+      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
-+    GMAC_DESCRIPTOR_T   *rx_desc;
-+      unsigned int            pkt_size;
-+      unsigned int        desc_count;
-+    unsigned int        vid;
-+//    unsigned int        priority;
-+      unsigned int        own;
-+      unsigned int        good_frame = 0;
-+      unsigned int        index;
-+      unsigned int        dev_index;
-+      int                 work = 0;
-+      int                 work_done = 0;
-+      int                 quota = min(dev->quota, *budget);
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      for (;;)
-+      {
-+        own = tp->rx_cur_desc->frame_ctrl.bits32 >> 31;
-+        if (own == CPU) /* check owner bit */
-+        {
-+              rx_desc = tp->rx_cur_desc;
-+#if (GMAC_DEBUG==1)
-+              /* check error interrupt */
-+              if ( (rx_desc->frame_ctrl.bits_rx.derr==1)||(rx_desc->frame_ctrl.bits_rx.perr==1) )
-+              {
-+              printk("%s::Rx Descriptor Processing Error !!!\n",__func__);
-+          }
-+#endif
-+          /* get frame information from the first descriptor of the frame */
-+              pkt_size = rx_desc->flag_status.bits_rx_status.frame_count - 4;  /*total byte count in a frame*/
-+#if (GMAC_DEBUG==1)
-+            priority = rx_desc->flag_status.bits_rx_status.priority;    /* 802.1p priority */
-+#endif
-+            vid = rx_desc->flag_status.bits_rx_status.vlan_id;          /* 802.1q vlan id */
-+            if (vid == 0)
-+            {
-+                vid = 1;    /* default vlan */
-+            }
-+              desc_count = rx_desc->frame_ctrl.bits_rx.desc_count; /* get descriptor count per frame */
-+
-+              if (rx_desc->frame_ctrl.bits_rx.frame_state == 0x000) /* good frame */
-+              {
-+                      tp->stats.rx_bytes += pkt_size;
-+                      tp->stats.rx_packets++;
-+                      good_frame = 1;
-+              }
-+              else
-+              {
-+                      tp->stats.rx_errors++;
-+                      good_frame = 0;
-+                      printk("RX status: 0x%x\n",rx_desc->frame_ctrl.bits_rx.frame_state);
-+              }
-+      }
-+      else
-+      {
-+          work_done = 1;
-+          break;  /* Rx process is completed */
-+      }
-+
-+        if (good_frame == 1)
-+        {
-+            /* get rx skb buffer index */
-+            index = ((unsigned int)tp->rx_cur_desc - rx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+            if (rx_skb[dev_index][index])
-+            {
-+                skb_reserve (rx_skb[dev_index][index], 2);    /* 16 byte align the IP fields. */
-+                rx_skb[dev_index][index]->dev = dev;
-+                rx_skb[dev_index][index]->ip_summed = CHECKSUM_UNNECESSARY;
-+                          skb_put(rx_skb[dev_index][index],pkt_size);
-+                          rx_skb[dev_index][index]->protocol = eth_type_trans(rx_skb[dev_index][index],dev); /* set skb protocol */
-+                          netif_rx(rx_skb[dev_index][index]);  /* socket rx */
-+                          dev->last_rx = jiffies;
-+
-+                          /* allocate rx skb buffer */
-+                if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-+                {
-+                    printk("%s::skb buffer allocation fail !\n",__func__);
-+                }
-+                rx_skb[dev_index][index] = skb;
-+                tp->rx_cur_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
-+            }
-+            else
-+            {
-+                printk("%s::rx skb index error !\n",__func__);
-+            }
-+        }
-+
-+          tp->rx_cur_desc->frame_ctrl.bits_rx.own = DMA; /* release rx descriptor to DMA */
-+        /* point to next rx descriptor */
-+        tp->rx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->rx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+rx_desc_virtual_base[dev_index]);
-+
-+        /* release buffer to Remaining Buffer Number Register */
-+        if (flow_control_enable[dev_index] ==1)
-+        {
-+//            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_BNCR,desc_count,0x0000ffff);
-+            writel(desc_count,(unsigned int *)(gmac_base_addr[dev_index] + GMAC_BNCR));
-+        }
-+
-+              if (work++ >= quota )
-+              {
-+                      break;
-+              }
-+    }
-+
-+    /* if RX DMA process is stoped , restart it */
-+      rxdma_busy.bits.rd_first_des_ptr = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC);
-+      if (rxdma_busy.bits.rd_busy == 0)
-+      {
-+          rxdma_ctrl.bits32 = 0;
-+      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
-+          rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
-+          rxdma_ctrl_mask.bits32 = 0;
-+      rxdma_ctrl_mask.bits.rd_start = 1;
-+          rxdma_ctrl_mask.bits.rd_continue = 1;
-+          gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
-+    }
-+
-+      dev->quota -= work;
-+      *budget -= work;
-+      if (work_done==1)
-+      {
-+          /* Receive descriptor is empty now */
-+        netif_rx_complete(dev);
-+        /* enable receive interrupt */
-+        gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,0x0007c000,0x0007c000);   /* enable rx interrupt */
-+        return 0;
-+    }
-+    else
-+    {
-+        return -1;
-+    }
-+}
-+
-+#endif
-+
-+static void gmac_rx_packet(struct net_device *dev)
-+{
-+      struct gmac_private *tp = dev->priv;
-+      struct sk_buff          *skb;
-+    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
-+      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
-+    GMAC_DESCRIPTOR_T   *rx_desc;
-+      unsigned int            pkt_size;
-+      unsigned int        desc_count;
-+    unsigned int        vid;
-+//    unsigned int        priority;
-+      unsigned int        own;
-+      unsigned int        good_frame = 0;
-+      unsigned int        i,index;
-+      unsigned int        dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      for (i=0;i<256;i++)
-+      {
-+        own = tp->rx_cur_desc->frame_ctrl.bits32 >> 31;
-+        if (own == CPU) /* check owner bit */
-+        {
-+              rx_desc = tp->rx_cur_desc;
-+#if (GMAC_DEBUG==1)
-+              /* check error interrupt */
-+              if ( (rx_desc->frame_ctrl.bits_rx.derr==1)||(rx_desc->frame_ctrl.bits_rx.perr==1) )
-+              {
-+              printk("%s::Rx Descriptor Processing Error !!!\n",__func__);
-+          }
-+#endif
-+          /* get frame information from the first descriptor of the frame */
-+              pkt_size = rx_desc->flag_status.bits_rx_status.frame_count - 4;  /*total byte count in a frame*/
-+#if (GMAC_DEBUG==1)
-+            priority = rx_desc->flag_status.bits_rx_status.priority;    /* 802.1p priority */
-+#endif
-+            vid = rx_desc->flag_status.bits_rx_status.vlan_id;          /* 802.1q vlan id */
-+            if (vid == 0)
-+            {
-+                vid = 1;    /* default vlan */
-+            }
-+              desc_count = rx_desc->frame_ctrl.bits_rx.desc_count; /* get descriptor count per frame */
-+
-+              if (rx_desc->frame_ctrl.bits_rx.frame_state == 0x000) /* good frame */
-+              {
-+                      tp->stats.rx_bytes += pkt_size;
-+                      tp->stats.rx_packets++;
-+                      good_frame = 1;
-+              }
-+              else
-+              {
-+                      tp->stats.rx_errors++;
-+                      good_frame = 0;
-+                      printk("RX status: 0x%x\n",rx_desc->frame_ctrl.bits_rx.frame_state);
-+              }
-+      }
-+      else
-+      {
-+          break;  /* Rx process is completed */
-+      }
-+
-+        if (good_frame == 1)
-+        {
-+            /* get rx skb buffer index */
-+            index = ((unsigned int)tp->rx_cur_desc - rx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+            if (rx_skb[dev_index][index])
-+            {
-+                skb_reserve (rx_skb[dev_index][index], 2);    /* 16 byte align the IP fields. */
-+                rx_skb[dev_index][index]->dev = dev;
-+                rx_skb[dev_index][index]->ip_summed = CHECKSUM_UNNECESSARY;
-+                          skb_put(rx_skb[dev_index][index],pkt_size);
-+                          rx_skb[dev_index][index]->protocol = eth_type_trans(rx_skb[dev_index][index],dev); /* set skb protocol */
-+                          netif_rx(rx_skb[dev_index][index]);  /* socket rx */
-+                          dev->last_rx = jiffies;
-+
-+                          /* allocate rx skb buffer */
-+                if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-+                {
-+                    printk("%s::skb buffer allocation fail !\n",__func__);
-+                }
-+                rx_skb[dev_index][index] = skb;
-+                tp->rx_cur_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
-+            }
-+            else
-+            {
-+                printk("%s::rx skb index error !\n",__func__);
-+            }
-+        }
-+
-+          tp->rx_cur_desc->frame_ctrl.bits_rx.own = DMA; /* release rx descriptor to DMA */
-+        /* point to next rx descriptor */
-+        tp->rx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->rx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+rx_desc_virtual_base[dev_index]);
-+
-+        /* release buffer to Remaining Buffer Number Register */
-+        if (flow_control_enable[dev_index] ==1)
-+        {
-+            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_BNCR,desc_count,0x0000ffff);
-+        }
-+    }
-+
-+    /* if RX DMA process is stoped , restart it */
-+      rxdma_busy.bits.rd_first_des_ptr = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC);
-+      if (rxdma_busy.bits.rd_busy == 0)
-+      {
-+          rxdma_ctrl.bits32 = 0;
-+      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
-+          rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
-+          rxdma_ctrl_mask.bits32 = 0;
-+      rxdma_ctrl_mask.bits.rd_start = 1;
-+          rxdma_ctrl_mask.bits.rd_continue = 1;
-+          gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
-+    }
-+}
-+
-+#ifdef CONFIG_SL2312_MPAGE
-+static inline void free_tx_buf(int dev_index, int desc_index)
-+{
-+      if (tx_skb[dev_index][desc_index].freeable &&
-+          tx_skb[dev_index][desc_index].skb) {
-+              struct sk_buff* skb = tx_skb[dev_index][desc_index].skb;
-+              //printk("free_skb %x, len %d\n", skb, skb->len);
-+#ifdef CONFIG_TXINT_DISABLE
-+              dev_kfree_skb(skb);
-+#else
-+              dev_kfree_skb_irq(skb);
-+#endif
-+              tx_skb[dev_index][desc_index].skb = 0;
-+      }
-+}
-+
-+#ifdef CONFIG_TXINT_DISABLE
-+static void gmac_tx_packet_complete(struct net_device *dev)
-+{
-+      struct gmac_private     *tp = dev->priv;
-+    GMAC_DESCRIPTOR_T     *tx_hw_complete_desc, *next_desc;
-+    unsigned int desc_cnt=0;
-+    unsigned int i,index,dev_index;
-+    unsigned int tx_current_descriptor = 0;
-+      // int own_dma = 0;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+      if (tx_skb[dev_index][index].desc_in_use && tp->tx_finished_desc->frame_ctrl.bits_tx_in.own == CPU) {
-+              free_tx_buf(dev_index, index);
-+              tx_skb[dev_index][index].desc_in_use = 0;
-+      }
-+      next_desc = (GMAC_DESCRIPTOR_T*)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
-+
-+      for (;;) {
-+              tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
-+              if (next_desc == tx_hw_complete_desc)
-+                      break;
-+              if (next_desc->frame_ctrl.bits_tx_in.own == CPU) {
-+                      if (next_desc->frame_ctrl.bits_tx_in.success_tx == 1) {
-+                              tp->stats.tx_bytes += next_desc->flag_status.bits_tx_flag.frame_count;
-+                              tp->stats.tx_packets ++;
-+                      } else {
-+                              tp->stats.tx_errors++;
-+                      }
-+                      desc_cnt = next_desc->frame_ctrl.bits_tx_in.desc_count;
-+                      for (i=1; i<desc_cnt; i++) {
-+                              /* get tx skb buffer index */
-+                              index = ((unsigned int)next_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+                              next_desc->frame_ctrl.bits_tx_in.own = CPU;
-+                              free_tx_buf(dev_index, index);
-+                              tx_skb[dev_index][index].desc_in_use = 0;
-+                              tp->tx_desc_tail[dev_index] = (tp->tx_desc_tail[dev_index] +1) & (TX_DESC_NUM-1);
-+                              /* release Tx descriptor to CPU */
-+                              next_desc = (GMAC_DESCRIPTOR_T *)((next_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
-+                      }
-+                      /* get tx skb buffer index */
-+                      index = ((unsigned int)next_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+                      /* free skb buffer */
-+                      next_desc->frame_ctrl.bits_tx_in.own = CPU;
-+                      free_tx_buf(dev_index, index);
-+                      tx_skb[dev_index][index].desc_in_use = 0;
-+                      tp->tx_desc_tail[dev_index] = (tp->tx_desc_tail[dev_index] +1) & (TX_DESC_NUM-1);
-+                      tp->tx_finished_desc = next_desc;
-+//                    printk("finish tx_desc index %d\n", index);
-+                      next_desc = (GMAC_DESCRIPTOR_T *)((next_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
-+              }
-+              else
-+                      break;
-+      }
-+      if (netif_queue_stopped(dev))
-+      {
-+              netif_wake_queue(dev);
-+      }
-+
-+}
-+#else
-+static void gmac_tx_packet_complete(struct net_device *dev)
-+{
-+      struct gmac_private     *tp = dev->priv;
-+      GMAC_DESCRIPTOR_T           *tx_hw_complete_desc;
-+      unsigned int desc_cnt=0;
-+      unsigned int i,index,dev_index;
-+      unsigned int tx_current_descriptor = 0;
-+      // int own_dma = 0;
-+
-+      dev_index = gmac_select_interface(dev);
-+
-+      index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+
-+      /* check tx status and accumulate tx statistics */
-+      for (;;)
-+      {
-+
-+        for (i=0;i<1000;i++)
-+        {
-+            tx_current_descriptor = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC);
-+            if ( ((tx_current_descriptor & 0x00000003)==0x00000003) ||  /* only one descriptor */
-+                 ((tx_current_descriptor & 0x00000003)==0x00000001) )   /* the last descriptor */
-+            {
-+                break;
-+            }
-+            udelay(1);
-+        }
-+        if (i==1000)
-+        {
-+//            gmac_dump_register(dev);
-+//            printk("%s: tx current descriptor = %x \n",__func__,tx_current_descriptor);
-+//            printk_all(dev_index, tp);
-+            continue;
-+        }
-+
-+          /* get tx H/W completed descriptor virtual address */
-+      tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((tx_current_descriptor & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
-+//            tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
-+          if (tp->tx_finished_desc == tx_hw_complete_desc ) // ||
-+                  //tx_skb[dev_index][index].desc_in_use )   /* complete tx processing */
-+              {
-+                      break;
-+              }
-+
-+        for (;;)
-+        {
-+              if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.own == CPU)
-+              {
-+    #if (GMAC_DEBUG==1)
-+                      if ( (tp->tx_finished_desc->frame_ctrl.bits_tx_in.derr) ||
-+                         (tp->tx_finished_desc->frame_ctrl.bits_tx_in.perr) )
-+                      {
-+                              printk("%s::Descriptor Processing Error !!!\n",__func__);
-+                      }
-+    #endif
-+                      if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.success_tx == 1)
-+                      {
-+                              tp->stats.tx_bytes += tp->tx_finished_desc->flag_status.bits_tx_flag.frame_count;
-+                              tp->stats.tx_packets ++;
-+                      }
-+                      else
-+                      {
-+                              tp->stats.tx_errors++;
-+                      }
-+                      desc_cnt = tp->tx_finished_desc->frame_ctrl.bits_tx_in.desc_count;
-+                      for (i=1; i<desc_cnt; i++)  /* multi-descriptor in one packet */
-+                      {
-+                              /* get tx skb buffer index */
-+                              index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+                              tp->tx_finished_desc->frame_ctrl.bits_tx_in.own = CPU;
-+                              free_tx_buf(dev_index, index);
-+                              tx_skb[dev_index][index].desc_in_use = 0;
-+                              /* release Tx descriptor to CPU */
-+                              tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
-+                      }
-+                      /* get tx skb buffer index */
-+                      index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+                      /* free skb buffer */
-+                      tp->tx_finished_desc->frame_ctrl.bits_tx_in.own = CPU;
-+                      free_tx_buf(dev_index, index);
-+                      tx_skb[dev_index][index].desc_in_use = 0;
-+                      tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
-+
-+                  if (tp->tx_finished_desc == tx_hw_complete_desc )
-+                      {
-+                              break;
-+                      }
-+            }
-+              else
-+              {
-+                      break;
-+                      }
-+              }
-+      }
-+
-+      if (netif_queue_stopped(dev))
-+      {
-+              netif_wake_queue(dev);
-+      }
-+
-+}
-+#endif
-+#else
-+
-+static void gmac_tx_packet_complete(struct net_device *dev)
-+{
-+      struct gmac_private     *tp = dev->priv;
-+    GMAC_DESCRIPTOR_T     *tx_hw_complete_desc;
-+    unsigned int desc_cnt=0;
-+    unsigned int i,index,dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      /* get tx H/W completed descriptor virtual address */
-+      tx_hw_complete_desc = (GMAC_DESCRIPTOR_T *)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0)+ tx_desc_virtual_base[dev_index]);
-+      /* check tx status and accumulate tx statistics */
-+    for (;;)
-+    {
-+        if (tp->tx_finished_desc == tx_hw_complete_desc)   /* complete tx processing */
-+        {
-+            break;
-+        }
-+      if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.own == CPU)
-+      {
-+#if (GMAC_DEBUG==1)
-+          if ( (tp->tx_finished_desc->frame_ctrl.bits_tx_in.derr) ||
-+               (tp->tx_finished_desc->frame_ctrl.bits_tx_in.perr) )
-+          {
-+              printk("%s::Descriptor Processing Error !!!\n",__func__);
-+          }
-+#endif
-+            if (tp->tx_finished_desc->frame_ctrl.bits_tx_in.success_tx == 1)
-+            {
-+                tp->stats.tx_bytes += tp->tx_finished_desc->flag_status.bits_tx_flag.frame_count;
-+                tp->stats.tx_packets ++;
-+            }
-+            else
-+            {
-+                tp->stats.tx_errors++;
-+            }
-+            desc_cnt = tp->tx_finished_desc->frame_ctrl.bits_tx_in.desc_count;
-+              for (i=1; i<desc_cnt; i++)  /* multi-descriptor in one packet */
-+              {
-+                /* get tx skb buffer index */
-+                index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+                /* free skb buffer */
-+                if (tx_skb[dev_index][index])
-+                {
-+                          dev_kfree_skb_irq(tx_skb[dev_index][index]);
-+                      }
-+                  /* release Tx descriptor to CPU */
-+                tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
-+                tp->tx_finished_desc->frame_ctrl.bits_tx_in.own = CPU;
-+              }
-+            /* get tx skb buffer index */
-+            index = ((unsigned int)tp->tx_finished_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+            /* free skb buffer */
-+            if (tx_skb[dev_index][index])
-+            {
-+                  dev_kfree_skb_irq(tx_skb[dev_index][index]);
-+              }
-+            tp->tx_finished_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
-+      }
-+    }
-+
-+      if (netif_queue_stopped(dev))
-+      {
-+          netif_wake_queue(dev);
-+      }
-+
-+}
-+
-+
-+#endif
-+
-+#if 0
-+static void gmac_weird_interrupt(struct net_device *dev)
-+{
-+    gmac_dump_register(dev);
-+}
-+#endif
-+
-+/* The interrupt handler does all of the Rx thread work and cleans up
-+   after the Tx thread. */
-+static irqreturn_t gmac_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
-+{
-+      struct net_device       *dev = (struct net_device *)dev_instance;
-+      GMAC_RXDMA_FIRST_DESC_T rxdma_busy;
-+//    GMAC_TXDMA_FIRST_DESC_T txdma_busy;
-+//    GMAC_TXDMA_CTRL_T       txdma_ctrl,txdma_ctrl_mask;
-+    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
-+      GMAC_DMA_STATUS_T           status;
-+    unsigned int            i,dev_index;
-+      int                     handled = 0;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      handled = 1;
-+
-+#ifdef CONFIG_SL_NAPI
-+      disable_irq(gmac_irq[dev_index]);   /* disable GMAC interrupt */
-+
-+    status.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS);        /* read DMA status */
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS,status.bits32,status.bits32);    /* clear DMA status */
-+
-+    if (status.bits.rx_overrun == 1)
-+    {
-+              printk("%s::RX Overrun !!!%d\n",__func__,gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RBNR));
-+         gmac_dump_register(dev);
-+        /* if RX DMA process is stoped , restart it */
-+        rxdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC) ;
-+        if (rxdma_busy.bits.rd_busy == 0)
-+        {
-+            /* restart Rx DMA process */
-+              rxdma_ctrl.bits32 = 0;
-+              rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
-+            rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
-+            rxdma_ctrl_mask.bits32 = 0;
-+              rxdma_ctrl_mask.bits.rd_start = 1;
-+            rxdma_ctrl_mask.bits.rd_continue = 1;
-+            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
-+        }
-+    }
-+
-+    /* process rx packet */
-+      if (netif_running(dev) && ((status.bits.rs_eofi==1)||(status.bits.rs_finish==1)))
-+      {
-+        if (likely(netif_rx_schedule_prep(dev)))
-+        {
-+            gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,0,0x0007c000);   /* disable rx interrupt */
-+            __netif_rx_schedule(dev);
-+        }
-+    }
-+#ifndef CONFIG_TXINT_DISABLE
-+    /* process tx packet */
-+      if (netif_running(dev) && ((status.bits.ts_eofi==1)||(status.bits.ts_finish==1)))
-+      {
-+              gmac_tx_packet_complete(dev);
-+      }
-+#endif
-+
-+      enable_irq(gmac_irq[dev_index]);    /* enable GMAC interrupt */
-+    return IRQ_RETVAL(handled);
-+#endif
-+
-+   /* disable GMAC interrupt */
-+      disable_irq(gmac_irq[dev_index]);
-+    for (i=0;i<MAX_ISR_WORK;i++)
-+    {
-+        /* read DMA status */
-+          status.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS);
-+int_status = status.bits32;
-+          /* clear DMA status */
-+        gmac_write_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS,status.bits32,status.bits32);
-+
-+        if ((status.bits32 & 0xffffc000)==0)
-+        {
-+            break;
-+        }
-+
-+          if (status.bits.rx_overrun == 1)
-+          {
-+                      printk("%s::RX Overrun !!!%d\n",__func__,gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RBNR));
-+              gmac_dump_register(dev);
-+            /* if RX DMA process is stoped , restart it */
-+              rxdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_FIRST_DESC) ;
-+              if (rxdma_busy.bits.rd_busy == 0)
-+              {
-+                  /* restart Rx DMA process */
-+              rxdma_ctrl.bits32 = 0;
-+              rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
-+                  rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
-+                  rxdma_ctrl_mask.bits32 = 0;
-+              rxdma_ctrl_mask.bits.rd_start = 1;
-+                  rxdma_ctrl_mask.bits.rd_continue = 1;
-+                  gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
-+            }
-+          }
-+
-+        /* receive rx interrupt */
-+      if (netif_running(dev) && ((status.bits.rs_eofi==1)||(status.bits.rs_finish==1)))
-+      {
-+              gmac_rx_packet(dev);
-+//                    gmac_tx_packet_complete(dev);
-+        }
-+
-+        /* receive tx interrupt */
-+      // if (netif_running(dev) && (status.bits.ts_finish==1))
-+#ifndef CONFIG_TXINT_DISABLE
-+      if (netif_running(dev) && ((status.bits.ts_eofi==1)||
-+                         (status.bits.ts_finish==1)))
-+      {
-+              gmac_tx_packet_complete(dev);
-+      }
-+#endif
-+      /* check uncommon events */
-+/*        if ((status.bits32 & 0x632fc000)!=0)
-+        {
-+            printk("%s::DMA Status = %08x \n",__func__,status.bits32);
-+            gmac_weird_interrupt(dev);
-+        }
-+*/
-+      }
-+
-+    /* enable GMAC interrupt */
-+      enable_irq(gmac_irq[dev_index]);
-+      //printk("gmac_interrupt complete!\n\n");
-+      return IRQ_RETVAL(handled);
-+}
-+
-+static void gmac_hw_start(struct net_device *dev)
-+{
-+      struct gmac_private     *tp = dev->priv;
-+      GMAC_TXDMA_CURR_DESC_T  tx_desc;
-+      GMAC_RXDMA_CURR_DESC_T  rx_desc;
-+    GMAC_TXDMA_CTRL_T       txdma_ctrl,txdma_ctrl_mask;
-+    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
-+      GMAC_DMA_STATUS_T       dma_status,dma_status_mask;
-+      int                                             dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      /* program TxDMA Current Descriptor Address register for first descriptor */
-+      tx_desc.bits32 = (unsigned int)(tp->tx_desc_dma);
-+      tx_desc.bits.eofie = 1;
-+      tx_desc.bits.sof_eof = 0x03;
-+      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC,tx_desc.bits32,0xffffffff);
-+      gmac_write_reg(gmac_base_addr[dev_index] + 0xff2c,tx_desc.bits32,0xffffffff);   /* tx next descriptor address */
-+
-+      /* program RxDMA Current Descriptor Address register for first descriptor */
-+      rx_desc.bits32 = (unsigned int)(tp->rx_desc_dma);
-+      rx_desc.bits.eofie = 1;
-+      rx_desc.bits.sof_eof = 0x03;
-+      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CURR_DESC,rx_desc.bits32,0xffffffff);
-+      gmac_write_reg(gmac_base_addr[dev_index] + 0xff3c,rx_desc.bits32,0xffffffff);   /* rx next descriptor address */
-+
-+      /* enable GMAC interrupt & disable loopback */
-+      dma_status.bits32 = 0;
-+      dma_status.bits.loop_back = 0;  /* disable DMA loop-back mode */
-+//    dma_status.bits.m_tx_fail = 1;
-+      dma_status.bits.m_cnt_full = 1;
-+      dma_status.bits.m_rx_pause_on = 1;
-+      dma_status.bits.m_tx_pause_on = 1;
-+      dma_status.bits.m_rx_pause_off = 1;
-+      dma_status.bits.m_tx_pause_off = 1;
-+      dma_status.bits.m_rx_overrun = 1;
-+      dma_status.bits.m_link_change = 1;
-+      dma_status_mask.bits32 = 0;
-+      dma_status_mask.bits.loop_back = 1;
-+//    dma_status_mask.bits.m_tx_fail = 1;
-+      dma_status_mask.bits.m_cnt_full = 1;
-+      dma_status_mask.bits.m_rx_pause_on = 1;
-+      dma_status_mask.bits.m_tx_pause_on = 1;
-+      dma_status_mask.bits.m_rx_pause_off = 1;
-+      dma_status_mask.bits.m_tx_pause_off = 1;
-+      dma_status_mask.bits.m_rx_overrun = 1;
-+      dma_status_mask.bits.m_link_change = 1;
-+      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_DMA_STATUS,dma_status.bits32,dma_status_mask.bits32);
-+
-+    /* program tx dma control register */
-+      txdma_ctrl.bits32 = 0;
-+      txdma_ctrl.bits.td_start = 0;    /* start TX DMA transfer */
-+      txdma_ctrl.bits.td_continue = 0; /* continue Tx DMA operation */
-+      txdma_ctrl.bits.td_chain_mode = 1;  /* chain mode */
-+      txdma_ctrl.bits.td_prot = 0;
-+      txdma_ctrl.bits.td_burst_size = 2;  /* DMA burst size for every AHB request */
-+      txdma_ctrl.bits.td_bus = 2;         /* peripheral bus width */
-+      txdma_ctrl.bits.td_endian = 0;      /* little endian */
-+#ifdef CONFIG_TXINT_DISABLE
-+      txdma_ctrl.bits.td_finish_en = 0;   /* DMA finish event interrupt disable */
-+#else
-+      txdma_ctrl.bits.td_finish_en = 1;   /* DMA finish event interrupt enable */
-+#endif
-+      txdma_ctrl.bits.td_fail_en = 1;     /* DMA fail interrupt enable */
-+      txdma_ctrl.bits.td_perr_en = 1;     /* protocol failure interrupt enable */
-+      txdma_ctrl.bits.td_eod_en = 0;      /* disable Tx End of Descriptor Interrupt */
-+      //txdma_ctrl.bits.td_eod_en = 0;      /* disable Tx End of Descriptor Interrupt */
-+#ifdef CONFIG_TXINT_DISABLE
-+      txdma_ctrl.bits.td_eof_en = 0;      /* end of frame interrupt disable */
-+#else
-+      txdma_ctrl.bits.td_eof_en = 1;      /* end of frame interrupt enable */
-+#endif
-+      txdma_ctrl_mask.bits32 = 0;
-+      txdma_ctrl_mask.bits.td_start = 1;
-+      txdma_ctrl_mask.bits.td_continue = 1;
-+      txdma_ctrl_mask.bits.td_chain_mode = 1;
-+      txdma_ctrl_mask.bits.td_prot = 15;
-+      txdma_ctrl_mask.bits.td_burst_size = 3;
-+      txdma_ctrl_mask.bits.td_bus = 3;
-+      txdma_ctrl_mask.bits.td_endian = 1;
-+      txdma_ctrl_mask.bits.td_finish_en = 1;
-+      txdma_ctrl_mask.bits.td_fail_en = 1;
-+      txdma_ctrl_mask.bits.td_perr_en = 1;
-+      txdma_ctrl_mask.bits.td_eod_en = 1;
-+      //txdma_ctrl_mask.bits.td_eod_en = 1;
-+      txdma_ctrl_mask.bits.td_eof_en = 1;
-+      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,txdma_ctrl.bits32,txdma_ctrl_mask.bits32);
-+
-+    /* program rx dma control register */
-+      rxdma_ctrl.bits32 = 0;
-+      rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */
-+      rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */
-+      rxdma_ctrl.bits.rd_chain_mode = 1;  /* chain mode */
-+      rxdma_ctrl.bits.rd_prot = 0;
-+      rxdma_ctrl.bits.rd_burst_size = 2;  /* DMA burst size for every AHB request */
-+      rxdma_ctrl.bits.rd_bus = 2;         /* peripheral bus width */
-+      rxdma_ctrl.bits.rd_endian = 0;      /* little endian */
-+      rxdma_ctrl.bits.rd_finish_en = 1;   /* DMA finish event interrupt enable */
-+      rxdma_ctrl.bits.rd_fail_en = 1;     /* DMA fail interrupt enable */
-+      rxdma_ctrl.bits.rd_perr_en = 1;     /* protocol failure interrupt enable */
-+      rxdma_ctrl.bits.rd_eod_en = 0;      /* disable Rx End of Descriptor Interrupt */
-+      rxdma_ctrl.bits.rd_eof_en = 1;      /* end of frame interrupt enable */
-+      rxdma_ctrl_mask.bits32 = 0;
-+      rxdma_ctrl_mask.bits.rd_start = 1;
-+      rxdma_ctrl_mask.bits.rd_continue = 1;
-+      rxdma_ctrl_mask.bits.rd_chain_mode = 1;
-+      rxdma_ctrl_mask.bits.rd_prot = 15;
-+      rxdma_ctrl_mask.bits.rd_burst_size = 3;
-+      rxdma_ctrl_mask.bits.rd_bus = 3;
-+      rxdma_ctrl_mask.bits.rd_endian = 1;
-+      rxdma_ctrl_mask.bits.rd_finish_en = 1;
-+      rxdma_ctrl_mask.bits.rd_fail_en = 1;
-+      rxdma_ctrl_mask.bits.rd_perr_en = 1;
-+      rxdma_ctrl_mask.bits.rd_eod_en = 1;
-+      rxdma_ctrl_mask.bits.rd_eof_en = 1;
-+      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
-+    return;
-+}
-+
-+static void gmac_hw_stop(struct net_device *dev)
-+{
-+    GMAC_TXDMA_CTRL_T       txdma_ctrl,txdma_ctrl_mask;
-+    GMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;
-+      int                                     dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+    /* program tx dma control register */
-+      txdma_ctrl.bits32 = 0;
-+      txdma_ctrl.bits.td_start = 0;
-+      txdma_ctrl.bits.td_continue = 0;
-+      txdma_ctrl_mask.bits32 = 0;
-+      txdma_ctrl_mask.bits.td_start = 1;
-+      txdma_ctrl_mask.bits.td_continue = 1;
-+      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,txdma_ctrl.bits32,txdma_ctrl_mask.bits32);
-+    /* program rx dma control register */
-+      rxdma_ctrl.bits32 = 0;
-+      rxdma_ctrl.bits.rd_start = 0;    /* stop RX DMA transfer */
-+      rxdma_ctrl.bits.rd_continue = 0; /* stop continue RX DMA operation */
-+      rxdma_ctrl_mask.bits32 = 0;
-+      rxdma_ctrl_mask.bits.rd_start = 1;
-+      rxdma_ctrl_mask.bits.rd_continue = 1;
-+      gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);
-+}
-+
-+static int gmac_init_desc_buf(struct net_device *dev)
-+{
-+      struct gmac_private *tp = dev->priv;
-+      struct sk_buff          *skb;
-+      dma_addr_t          tx_first_desc_dma=0;
-+      dma_addr_t          rx_first_desc_dma=0;
-+      dma_addr_t          rx_first_buf_dma=0;
-+      unsigned int        i,index;
-+
-+    printk("Descriptor buffer init......\n");
-+
-+    /* get device index number */
-+    index = gmac_get_dev_index(dev);
-+#ifdef CONFIG_SL2312_MPAGE
-+      for (i=0; i<TX_DESC_NUM; i++) {
-+              tx_skb[index][i].freeable = 0;
-+              tx_skb[index][i].skb = 0;
-+              tx_skb[index][i].desc_in_use = 0;
-+              tx_skb[index][i].end_seq = 0;
-+      }
-+#else
-+    for (i=0;i<TX_DESC_NUM;i++)
-+    {
-+        tx_skb[index][i] = NULL;
-+    }
-+#endif
-+    for (i=0;i<RX_DESC_NUM;i++)
-+    {
-+        rx_skb[index][i] = NULL;
-+    }
-+
-+      /* allocates TX/RX descriptors */
-+      tp->tx_desc = DMA_MALLOC(TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(dma_addr_t *)&tp->tx_desc_dma);
-+    tx_desc_virtual_base[index] = (unsigned int)tp->tx_desc - (unsigned int)tp->tx_desc_dma;
-+    memset(tp->tx_desc,0x00,TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T));
-+      tp->rx_desc = DMA_MALLOC(RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(dma_addr_t *)&tp->rx_desc_dma);
-+    rx_desc_virtual_base[index] = (unsigned int)tp->rx_desc - (unsigned int)tp->rx_desc_dma;
-+    memset(tp->rx_desc,0x00,RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T));
-+    tx_desc_start_adr[index] = (unsigned int)tp->tx_desc;   /* for tx skb index calculation */
-+    rx_desc_start_adr[index] = (unsigned int)tp->rx_desc;   /* for rx skb index calculation */
-+    printk("tx_desc = %08x\n",(unsigned int)tp->tx_desc);
-+    printk("rx_desc = %08x\n",(unsigned int)tp->rx_desc);
-+      printk("tx_desc_dma = %08x\n",tp->tx_desc_dma);
-+      printk("rx_desc_dma = %08x\n",tp->rx_desc_dma);
-+
-+      if (tp->tx_desc==0x00 || tp->rx_desc==0x00)
-+      {
-+              free_irq(dev->irq, dev);
-+
-+              if (tp->tx_desc)
-+                      DMA_MFREE(tp->tx_desc, TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),tp->tx_desc_dma);
-+              if (tp->rx_desc)
-+                      DMA_MFREE(tp->rx_desc, RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),tp->rx_desc_dma);
-+              return -ENOMEM;
-+      }
-+
-+      /* TX descriptors initial */
-+      tp->tx_cur_desc = tp->tx_desc;  /* virtual address */
-+      tp->tx_finished_desc = tp->tx_desc; /* virtual address */
-+      tx_first_desc_dma = tp->tx_desc_dma; /* physical address */
-+      for (i = 1; i < TX_DESC_NUM; i++)
-+      {
-+              tp->tx_desc->frame_ctrl.bits_tx_out.own = CPU; /* set owner to CPU */
-+              tp->tx_desc->frame_ctrl.bits_tx_out.buffer_size = TX_BUF_SIZE;  /* set tx buffer size for descriptor */
-+              tp->tx_desc_dma = tp->tx_desc_dma + sizeof(GMAC_DESCRIPTOR_T); /* next tx descriptor DMA address */
-+              tp->tx_desc->next_desc.next_descriptor = tp->tx_desc_dma | 0x0000000b;
-+              tp->tx_desc = &tp->tx_desc[1] ; /* next tx descriptor virtual address */
-+      }
-+      /* the last descriptor will point back to first descriptor */
-+      tp->tx_desc->frame_ctrl.bits_tx_out.own = CPU;
-+      tp->tx_desc->frame_ctrl.bits_tx_out.buffer_size = TX_BUF_SIZE;
-+      tp->tx_desc->next_desc.next_descriptor = tx_first_desc_dma | 0x0000000b;
-+      tp->tx_desc = tp->tx_cur_desc;
-+      tp->tx_desc_dma = tx_first_desc_dma;
-+
-+      /* RX descriptors initial */
-+      tp->rx_cur_desc = tp->rx_desc;  /* virtual address */
-+      rx_first_desc_dma = tp->rx_desc_dma; /* physical address */
-+      for (i = 1; i < RX_DESC_NUM; i++)
-+      {
-+        if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-+        {
-+            printk("%s::skb buffer allocation fail !\n",__func__);
-+        }
-+        rx_skb[index][i-1] = skb;
-+        tp->rx_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
-+              tp->rx_desc->frame_ctrl.bits_rx.own = DMA;  /* set owner bit to DMA */
-+              tp->rx_desc->frame_ctrl.bits_rx.buffer_size = RX_BUF_SIZE; /* set rx buffer size for descriptor */
-+              tp->rx_bufs_dma = tp->rx_bufs_dma + RX_BUF_SIZE;    /* point to next buffer address */
-+              tp->rx_desc_dma = tp->rx_desc_dma + sizeof(GMAC_DESCRIPTOR_T); /* next rx descriptor DMA address */
-+              tp->rx_desc->next_desc.next_descriptor = tp->rx_desc_dma | 0x0000000b;
-+              tp->rx_desc = &tp->rx_desc[1]; /* next rx descriptor virtual address */
-+      }
-+      /* the last descriptor will point back to first descriptor */
-+    if ( (skb = dev_alloc_skb(RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-+    {
-+        printk("%s::skb buffer allocation fail !\n",__func__);
-+    }
-+    rx_skb[index][i-1] = skb;
-+    tp->rx_desc->buf_adr = (unsigned int)__pa(skb->data) | 0x02;    /* insert two bytes in the beginning of rx data */
-+      tp->rx_desc->frame_ctrl.bits_rx.own = DMA;
-+      tp->rx_desc->frame_ctrl.bits_rx.buffer_size = RX_BUF_SIZE;
-+      tp->rx_desc->next_desc.next_descriptor = rx_first_desc_dma | 0x0000000b;
-+      tp->rx_desc = tp->rx_cur_desc;
-+      tp->rx_desc_dma = rx_first_desc_dma;
-+      tp->rx_bufs_dma = rx_first_buf_dma;
-+
-+      for (i=0; i<GMAC_PHY_IF; i++) {
-+              tp->tx_desc_hdr[i] = 0;
-+              tp->tx_desc_tail[i] = 0;
-+      }
-+      return (0);
-+}
-+
-+static int gmac_clear_counter (struct net_device *dev)
-+{
-+      struct gmac_private *tp = dev->priv;
-+      unsigned int    dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+//    tp = gmac_dev[index]->priv;
-+    /* clear counter */
-+    gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_DISCARDS);
-+    gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_ERRORS);
-+    tp->stats.tx_bytes = 0;
-+    tp->stats.tx_packets = 0;
-+      tp->stats.tx_errors = 0;
-+    tp->stats.rx_bytes = 0;
-+      tp->stats.rx_packets = 0;
-+      tp->stats.rx_errors = 0;
-+    tp->stats.rx_dropped = 0;
-+      return (0);
-+}
-+
-+static int gmac_open (struct net_device *dev)
-+{
-+      struct gmac_private     *tp = dev->priv;
-+      int    retval;
-+
-+    gmac_select_interface(dev);
-+
-+      /* chip reset */
-+      gmac_sw_reset(dev);
-+
-+    /* allocates tx/rx descriptor and buffer memory */
-+    gmac_init_desc_buf(dev);
-+
-+    /* get mac address from FLASH */
-+    gmac_get_mac_address();
-+
-+    /* set PHY register to start autonegition process */
-+    gmac_set_phy_status(dev);
-+
-+      /* GMAC initialization */
-+      if (gmac_init_chip(dev))
-+      {
-+              printk (KERN_ERR "GMAC init fail\n");
-+      }
-+
-+    /* start DMA process */
-+      gmac_hw_start(dev);
-+
-+    /* enable tx/rx register */
-+    gmac_enable_tx_rx(dev);
-+
-+    /* clear statistic counter */
-+    gmac_clear_counter(dev);
-+
-+      netif_start_queue (dev);
-+
-+    /* hook ISR */
-+      retval = request_irq (dev->irq, gmac_interrupt, SA_INTERRUPT, dev->name, dev);
-+      if (retval)
-+              return retval;
-+
-+      if(!FLAG_SWITCH)
-+      {
-+      init_waitqueue_head (&tp->thr_wait);
-+      init_completion(&tp->thr_exited);
-+
-+      tp->time_to_die = 0;
-+      tp->thr_pid = kernel_thread (gmac_phy_thread, dev, CLONE_FS | CLONE_FILES);
-+      if (tp->thr_pid < 0)
-+      {
-+              printk (KERN_WARNING "%s: unable to start kernel thread\n",dev->name);
-+      }
-+    }
-+      return (0);
-+}
-+
-+static int gmac_close(struct net_device *dev)
-+{
-+    struct gmac_private *tp = dev->priv;
-+    unsigned int        i,dev_index;
-+    unsigned int        ret;
-+
-+    dev_index = gmac_get_dev_index(dev);
-+
-+    /* stop tx/rx packet */
-+    gmac_disable_tx_rx(dev);
-+
-+    /* stop the chip's Tx and Rx DMA processes */
-+      gmac_hw_stop(dev);
-+
-+    netif_stop_queue(dev);
-+
-+    /* disable interrupts by clearing the interrupt mask */
-+    synchronize_irq();
-+    free_irq(dev->irq,dev);
-+
-+      DMA_MFREE(tp->tx_desc, TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(unsigned int)tp->tx_desc_dma);
-+      DMA_MFREE(tp->rx_desc, RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T),(unsigned int)tp->rx_desc_dma);
-+
-+#ifdef CONFIG_SL2312_MPAGE
-+//    kfree(tx_skb);
-+#endif
-+
-+    for (i=0;i<RX_DESC_NUM;i++)
-+    {
-+        if (rx_skb[dev_index][i])
-+        {
-+            dev_kfree_skb(rx_skb[dev_index][i]);
-+        }
-+    }
-+      if(!FLAG_SWITCH)
-+      {
-+      if (tp->thr_pid >= 0)
-+      {
-+                  tp->time_to_die = 1;
-+              wmb();
-+              ret = kill_proc (tp->thr_pid, SIGTERM, 1);
-+              if (ret)
-+              {
-+                      printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
-+                      return ret;
-+              }
-+//                    wait_for_completion (&tp->thr_exited);
-+      }
-+    }
-+
-+    return (0);
-+}
-+
-+#ifdef CONFIG_SL2312_MPAGE
-+int printk_all(int dev_index, struct gmac_private* tp)
-+{
-+      int i=0;
-+    unsigned int tx_current_descriptor = 0;
-+    int hw_index;
-+    int fi;
-+    GMAC_DESCRIPTOR_T* tmp_desc;
-+
-+      GMAC_DESCRIPTOR_T* cur_desc=tp->tx_cur_desc;
-+      fi = ((unsigned int)cur_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+      printk("tmp_desc %x, id %d\n", (int)cur_desc, fi);
-+
-+      tmp_desc = (GMAC_DESCRIPTOR_T*)((gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC) & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
-+      hw_index = ((unsigned int)tmp_desc - tx_desc_start_adr[dev_index])/ sizeof(GMAC_DESCRIPTOR_T);
-+      printk("hd_desc %x, ind %d, fin desc %x\n",(int)tmp_desc, hw_index, (int)tp->tx_finished_desc);
-+
-+      for (i=0; i<TX_DESC_NUM; i++) {
-+              printk("**id %4d, hw_index %4d ==> ", fi, hw_index);
-+              printk("fc %8x ", tmp_desc->frame_ctrl.bits32);
-+              printk("fs %8x ", tmp_desc->flag_status.bits32);
-+              printk("fb %8x ", tmp_desc->buf_adr);
-+              printk("fd %8x\n",  tmp_desc->next_desc.next_descriptor);
-+              tmp_desc = (GMAC_DESCRIPTOR_T*)((tmp_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
-+              fi = ((unsigned int)tmp_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+      }
-+    tx_current_descriptor = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CURR_DESC);
-+    printk("%s: tx current descriptor = %x \n",__func__,tx_current_descriptor);
-+    printk("%s: interrupt status = %x \n",__func__,int_status);
-+    return 0;
-+}
-+
-+int cleanup_desc(int dev_index, struct gmac_private* tp)
-+{
-+      int i=0;
-+      int index = ((unsigned int)tp->tx_cur_desc - tx_desc_start_adr[dev_index])/sizeof(GMAC_DESCRIPTOR_T);
-+      GMAC_DESCRIPTOR_T* fill_desc = tp->tx_cur_desc;
-+
-+      for (i=0; i< TX_DESC_NUM; i++)
-+      {
-+              fill_desc->frame_ctrl.bits_tx_out.own = CPU;
-+              fill_desc->frame_ctrl.bits_tx_out.buffer_size = TX_BUF_SIZE;
-+              tx_skb[dev_index][index].desc_in_use = 0;
-+              free_tx_buf(dev_index, index);
-+              printk("cleanup di %d\n", index);
-+              fill_desc = (GMAC_DESCRIPTOR_T*)((fill_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
-+              index++;
-+              if (index > TX_DESC_NUM)
-+                      index = 0;
-+      }
-+      return 1;
-+}
-+
-+size_t get_available_tx_desc(struct net_device* dev, int dev_index)
-+{
-+      struct gmac_private *tp = dev->priv;
-+      unsigned int desc_hdr = tp->tx_desc_hdr[dev_index];
-+      unsigned int desc_tail = tp->tx_desc_tail[dev_index];
-+      int available_desc_num = (TX_DESC_NUM - desc_hdr + desc_tail) & (TX_DESC_NUM-1);
-+      if (!available_desc_num) {
-+              if (tx_skb[dev_index][desc_hdr].desc_in_use)
-+                      return 0;
-+              else
-+                      return TX_DESC_NUM;
-+      }
-+      return available_desc_num;
-+}
-+
-+int check_free_tx_desc(int dev_index, int n, GMAC_DESCRIPTOR_T* desc)
-+{
-+      int i,index;
-+      GMAC_DESCRIPTOR_T* tmp_desc = desc;
-+
-+      if (n > TX_DESC_NUM)
-+              return 0;
-+
-+      index = ((unsigned int)tmp_desc - tx_desc_start_adr[dev_index])/sizeof(GMAC_DESCRIPTOR_T);
-+      for (i=0; i<n; i++)
-+      {
-+              if (tx_skb[dev_index][index].desc_in_use)
-+              {
-+                      printk("sw desc %d is in use\n", index);
-+                      /* cleanup all the descriptors to check if DMA still running */
-+                      return 0;
-+              }
-+              index++;
-+              if (index == TX_DESC_NUM)
-+                      index = 0;
-+      }
-+      return 1;
-+}
-+
-+#define TCPHDRLEN(tcp_hdr)  ((ntohs(*((__u16 *)tcp_hdr + 6)) >> 12) & 0x000F)
-+
-+inline int fill_in_desc(int dev_index, GMAC_DESCRIPTOR_T *desc, char* data, int len, int total_len, int sof, int freeable, int ownership, struct sk_buff* skb)
-+{
-+      int index = ((unsigned int)desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+
-+      if (desc->frame_ctrl.bits_tx_in.own == CPU)
-+      {
-+              tx_skb[dev_index][index].freeable = freeable;
-+              if ((sof & 0x01) && skb) {
-+                      tx_skb[dev_index][index].skb = skb;
-+              }
-+              else
-+                      tx_skb[dev_index][index].skb = 0;
-+
-+              if (sof != 2)
-+                      tx_skb[dev_index][index].desc_in_use = 1;
-+              else
-+                      tx_skb[dev_index][index].desc_in_use = 0;
-+
-+              consistent_sync(data, len, PCI_DMA_TODEVICE);
-+              desc->buf_adr = (unsigned int)__pa(data);
-+              desc->frame_ctrl.bits_tx_out.buffer_size = len;
-+              desc->flag_status.bits_tx_flag.frame_count = total_len;
-+              desc->next_desc.bits.eofie = 1;
-+              desc->next_desc.bits.sof_eof = sof;
-+              desc->frame_ctrl.bits_tx_out.vlan_enable = 0;
-+              desc->frame_ctrl.bits_tx_out.ip_csum_en = 1;     /* TSS IPv4 IP header checksum enable */
-+              desc->frame_ctrl.bits_tx_out.ipv6_tx_en = 1;    /* TSS IPv6 tx enable */
-+              desc->frame_ctrl.bits_tx_out.tcp_csum_en = 1;    /* TSS TCP checksum enable */
-+              desc->frame_ctrl.bits_tx_out.udp_csum_en = 1;    /* TSS UDP checksum enable */
-+        wmb();
-+              desc->frame_ctrl.bits_tx_out.own = ownership;
-+//            consistent_sync(desc, sizeof(GMAC_DESCRIPTOR_T), PCI_DMA_TODEVICE);
-+      }
-+      return 0;
-+}
-+#endif
-+
-+static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct gmac_private     *tp = dev->priv;
-+      GMAC_TXDMA_CTRL_T               tx_ctrl,tx_ctrl_mask;
-+      GMAC_TXDMA_FIRST_DESC_T txdma_busy;
-+      unsigned int            len = skb->len;
-+      unsigned int            dev_index;
-+      static unsigned int     pcount = 0;
-+#ifdef CONFIG_SL2312_MPAGE
-+    GMAC_DESCRIPTOR_T *fill_desc;
-+      int snd_pages = skb_shinfo(skb)->nr_frags;  /* get number of descriptor */
-+      int desc_needed = 1; // for jumbo packet, one descriptor is enough.
-+      int header_len = skb->len;
-+    struct iphdr      *ip_hdr;
-+    struct tcphdr     *tcp_hdr;
-+    int             tcp_hdr_len;
-+    int             data_len;
-+    int             prv_index;
-+    long            seq_num;
-+    int             first_desc_index;
-+    int             ownership, freeable;
-+    int             eof;
-+      int             i=0;
-+#endif
-+#ifdef CONFIG_TXINT_DISABLE
-+      int                             available_desc_cnt = 0;
-+#endif
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+#ifdef CONFIG_TXINT_DISABLE
-+      available_desc_cnt = get_available_tx_desc(dev, dev_index);
-+
-+      if (available_desc_cnt < (TX_DESC_NUM >> 2)) {
-+              gmac_tx_packet_complete(dev);
-+      }
-+#endif
-+
-+#ifdef CONFIG_SL2312_MPAGE
-+
-+      fill_desc = tp->tx_cur_desc;
-+      if(!fill_desc) {
-+              printk("cur_desc is NULL!\n");
-+              return -1;
-+      }
-+
-+      if (storlink_ctl.recvfile==2)
-+      {
-+          printk("snd_pages=%d skb->len=%d\n",snd_pages,skb->len);
-+      }
-+
-+      if (snd_pages)
-+              desc_needed += snd_pages;   /* decriptors needed for this large packet */
-+
-+      if (!check_free_tx_desc(dev_index, desc_needed, fill_desc)) {
-+              printk("no available desc!\n");
-+        gmac_dump_register(dev);
-+              printk_all(dev_index, tp);
-+              tp->stats.tx_dropped++;
-+              if (pcount++ > 10)
-+              {
-+                  for (;;);
-+              }
-+              return -1;
-+      }
-+
-+      first_desc_index = ((unsigned int)fill_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+
-+      /* check if the tcp packet is in order*/
-+      ip_hdr = (struct iphdr*) &(skb->data[14]);
-+      tcp_hdr = (struct tcphdr*) &(skb->data[14+ip_hdr->ihl * 4]);
-+      tcp_hdr_len = TCPHDRLEN(tcp_hdr) * 4;
-+      data_len = skb->len - 14 - ip_hdr->ihl *4 - tcp_hdr_len;
-+
-+      prv_index = first_desc_index-1;
-+      if (prv_index <0)
-+          prv_index += TX_DESC_NUM;
-+      seq_num = ntohl(tcp_hdr->seq);
-+
-+      if (snd_pages)
-+      {
-+              // calculate header length
-+              // check fragment total length and header len = skb len - frag len
-+              // or parse the header.
-+              for (i=0; i<snd_pages; i++) {
-+                      skb_frag_t* frag = &skb_shinfo(skb)->frags[i];
-+                      header_len -= frag->size;
-+              }
-+              ownership = CPU;
-+              freeable = 0;
-+              /* fill header into first descriptor */
-+              fill_in_desc(dev_index, fill_desc, skb->data, header_len, len, 2, freeable, ownership, 0);
-+              fill_desc = (GMAC_DESCRIPTOR_T*)((fill_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
-+              tx_skb[dev_index][first_desc_index].end_seq = seq_num + data_len;
-+
-+              eof = 0;
-+              ownership = DMA;
-+              for (i=0; i<snd_pages; i++)
-+              {
-+                      skb_frag_t* frag = &skb_shinfo(skb)->frags[i];
-+                      int start_pos = frag->page_offset;
-+                      char* data_buf = page_address(frag->page);
-+                      int data_size = frag->size;
-+                      int cur_index;
-+
-+                      if (i == snd_pages-1)
-+                      {
-+                              eof=1;
-+                              freeable = 1;
-+                      }
-+                      fill_in_desc(dev_index, fill_desc, data_buf+(start_pos), data_size,
-+                                   len, eof, freeable, ownership, skb);
-+                      cur_index = ((unsigned int)fill_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+
-+                      fill_desc = (GMAC_DESCRIPTOR_T*)((fill_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
-+              }
-+              /* pass the ownership of the first descriptor to hardware */
-+//        disable_irq(gmac_irq[dev_index]);
-+              tx_skb[dev_index][first_desc_index].desc_in_use = 1;
-+        wmb();
-+              tp->tx_cur_desc->frame_ctrl.bits_tx_out.own = DMA;
-+//            consistent_sync(tp->tx_cur_desc, sizeof(GMAC_DESCRIPTOR_T), PCI_DMA_TODEVICE);
-+              tp->tx_cur_desc = fill_desc;
-+              dev->trans_start = jiffies;
-+//        enable_irq(gmac_irq[dev_index]);
-+      }
-+      else if ( tp->tx_cur_desc->frame_ctrl.bits_tx_out.own == CPU )
-+      {
-+//            tx_skb[dev_index][first_desc_index].end_seq = seq_num + data_len;
-+//        disable_irq(gmac_irq[dev_index]);
-+              fill_in_desc(dev_index, tp->tx_cur_desc, skb->data, skb->len, skb->len, 3, 1, DMA, skb);
-+//        enable_irq(gmac_irq[dev_index]);
-+              //consistent_sync(tp->tx_cur_desc, sizeof(GMAC_DESCRIPTOR_T), PCI_DMA_TODEVICE);
-+              tp->tx_cur_desc = (GMAC_DESCRIPTOR_T*)((tp->tx_cur_desc->next_desc.next_descriptor & 0xfffffff0) + tx_desc_virtual_base[dev_index]);
-+              dev->trans_start = jiffies;
-+      }
-+      else
-+      {
-+              printk("gmac tx drop!\n");
-+              tp->stats.tx_dropped++;
-+              return -1;
-+      }
-+
-+#ifdef CONFIG_TXINT_DISABLE
-+      tp->tx_desc_hdr[dev_index] = (tp->tx_desc_hdr[dev_index] + desc_needed) & (TX_DESC_NUM-1);
-+#endif
-+
-+#else
-+    if ((tp->tx_cur_desc->frame_ctrl.bits_tx_out.own == CPU) && (len < TX_BUF_SIZE))
-+      {
-+        index = ((unsigned int)tp->tx_cur_desc - tx_desc_start_adr[dev_index]) / sizeof(GMAC_DESCRIPTOR_T);
-+        tx_skb[dev_index][index] = skb;
-+        consistent_sync(skb->data,skb->len,PCI_DMA_TODEVICE);
-+        tp->tx_cur_desc->buf_adr = (unsigned int)__pa(skb->data);
-+      tp->tx_cur_desc->flag_status.bits_tx_flag.frame_count = len;    /* total frame byte count */
-+      tp->tx_cur_desc->next_desc.bits.sof_eof = 0x03;                 /*only one descriptor*/
-+              tp->tx_cur_desc->frame_ctrl.bits_tx_out.buffer_size = len;      /* descriptor byte count */
-+        tp->tx_cur_desc->frame_ctrl.bits_tx_out.vlan_enable = 0;
-+        tp->tx_cur_desc->frame_ctrl.bits_tx_out.ip_csum_en = 0;     /* TSS IPv4 IP header checksum enable */
-+        tp->tx_cur_desc->frame_ctrl.bits_tx_out.ipv6_tx_en = 0 ;    /* TSS IPv6 tx enable */
-+        tp->tx_cur_desc->frame_ctrl.bits_tx_out.tcp_csum_en = 0;    /* TSS TCP checksum enable */
-+        tp->tx_cur_desc->frame_ctrl.bits_tx_out.udp_csum_en = 0;    /* TSS UDP checksum enable */
-+        wmb();
-+      tp->tx_cur_desc->frame_ctrl.bits_tx_out.own = DMA;              /* set owner bit */
-+      tp->tx_cur_desc = (GMAC_DESCRIPTOR_T *)((tp->tx_cur_desc->next_desc.next_descriptor & 0xfffffff0)+tx_desc_virtual_base[dev_index]);
-+      dev->trans_start = jiffies;
-+      }
-+      else
-+      {
-+              /* no free tx descriptor */
-+              dev_kfree_skb(skb);
-+          netif_stop_queue(dev);
-+              tp->stats.tx_dropped++;
-+              return (-1);
-+      }
-+#endif
-+      /* if TX DMA process is stoped , restart it */
-+      txdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_FIRST_DESC);
-+      if (txdma_busy.bits.td_busy == 0)
-+      {
-+              /* restart DMA process */
-+              tx_ctrl.bits32 = 0;
-+              tx_ctrl.bits.td_start = 1;
-+              tx_ctrl.bits.td_continue = 1;
-+              tx_ctrl_mask.bits32 = 0;
-+              tx_ctrl_mask.bits.td_start = 1;
-+              tx_ctrl_mask.bits.td_continue = 1;
-+              gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,tx_ctrl.bits32,tx_ctrl_mask.bits32);
-+      }
-+      return (0);
-+}
-+
-+
-+struct net_device_stats * gmac_get_stats(struct net_device *dev)
-+{
-+    struct gmac_private *tp = dev->priv;
-+    unsigned long       flags;
-+    unsigned int        pkt_drop;
-+    unsigned int        pkt_error;
-+    unsigned int        dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+//    if (storlink_ctl.recvfile==3)
-+//    {
-+//        printk("GMAC_GLOBAL_BASE_ADDR=%x\n", readl(GMAC_GLOBAL_BASE_ADDR+0x30));
-+//        gmac_dump_register(dev);
-+//        printk_all(0, dev);
-+//    }
-+
-+    if (netif_running(dev))
-+    {
-+        /* read H/W counter */
-+        spin_lock_irqsave(&tp->lock,flags);
-+        pkt_drop = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_DISCARDS);
-+        pkt_error = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_IN_ERRORS);
-+        tp->stats.rx_dropped = tp->stats.rx_dropped + pkt_drop;
-+        tp->stats.rx_errors = tp->stats.rx_errors + pkt_error;
-+        spin_unlock_irqrestore(&tp->lock,flags);
-+    }
-+    return &tp->stats;
-+}
-+
-+static unsigned const ethernet_polynomial = 0x04c11db7U;
-+static inline u32 ether_crc (int length, unsigned char *data)
-+{
-+      int crc = -1;
-+      unsigned int i;
-+      unsigned int crc_val=0;
-+
-+      while (--length >= 0) {
-+              unsigned char current_octet = *data++;
-+              int bit;
-+              for (bit = 0; bit < 8; bit++, current_octet >>= 1)
-+                      crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ?
-+                           ethernet_polynomial : 0);
-+      }
-+      crc = ~crc;
-+      for (i=0;i<32;i++)
-+      {
-+              crc_val = crc_val + (((crc << i) & 0x80000000) >> (31-i));
-+      }
-+      return crc_val;
-+}
-+
-+static void gmac_set_rx_mode(struct net_device *dev)
-+{
-+    GMAC_RX_FLTR_T      filter;
-+      unsigned int        mc_filter[2];       /* Multicast hash filter */
-+    int                 bit_nr;
-+      unsigned int        i, dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+//    printk("%s : dev->flags = %x \n",__func__,dev->flags);
-+//    dev->flags |= IFF_ALLMULTI;  /* temp */
-+    filter.bits32 = 0;
-+    filter.bits.error = 0;
-+      if (dev->flags & IFF_PROMISC)
-+      {
-+          filter.bits.error = 1;
-+        filter.bits.promiscuous = 1;
-+        filter.bits.broadcast = 1;
-+        filter.bits.multicast = 1;
-+        filter.bits.unicast = 1;
-+              mc_filter[1] = mc_filter[0] = 0xffffffff;
-+      }
-+      else if (dev->flags & IFF_ALLMULTI)
-+      {
-+        filter.bits.promiscuous = 1;
-+        filter.bits.broadcast = 1;
-+        filter.bits.multicast = 1;
-+        filter.bits.unicast = 1;
-+              mc_filter[1] = mc_filter[0] = 0xffffffff;
-+      }
-+      else
-+      {
-+              struct dev_mc_list *mclist;
-+
-+        filter.bits.promiscuous = 1;
-+        filter.bits.broadcast = 1;
-+        filter.bits.multicast = 1;
-+        filter.bits.unicast = 1;
-+              mc_filter[1] = mc_filter[0] = 0;
-+              for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;i++, mclist = mclist->next)
-+              {
-+            bit_nr = ether_crc(ETH_ALEN,mclist->dmi_addr) & 0x0000003f;
-+            if (bit_nr < 32)
-+            {
-+                mc_filter[0] = mc_filter[0] | (1<<bit_nr);
-+            }
-+            else
-+            {
-+                mc_filter[1] = mc_filter[1] | (1<<(bit_nr-32));
-+            }
-+              }
-+      }
-+    filter.bits32 = 0x1f;
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_RX_FLTR,filter.bits32,0xffffffff);
-+
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_MCAST_FIL0,mc_filter[0],0xffffffff);
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_MCAST_FIL1,mc_filter[1],0xffffffff);
-+    return;
-+}
-+
-+static int gmac_set_mac_address(struct net_device *dev, void *addr)
-+{
-+      struct sockaddr *sock;
-+      unsigned int    reg_val;
-+      unsigned int    dev_index;
-+    unsigned int    i;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+      sock = (struct sockaddr *) addr;
-+      for (i = 0; i < 6; i++)
-+      {
-+              dev->dev_addr[i] = sock->sa_data[i];
-+      }
-+
-+    reg_val = dev->dev_addr[0] + (dev->dev_addr[1]<<8) + (dev->dev_addr[2]<<16) + (dev->dev_addr[3]<<24);
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_STA_ADD0,reg_val,0xffffffff);
-+    reg_val = dev->dev_addr[4] + (dev->dev_addr[5]<<8) ;
-+    gmac_write_reg(gmac_base_addr[dev_index] + GMAC_STA_ADD1,reg_val,0x0000ffff);
-+    memcpy(&eth0_mac[0],&dev->dev_addr[0],6);
-+    printk("Storlink %s address = ",dev->name);
-+    printk("%02x",dev->dev_addr[0]);
-+    printk("%02x",dev->dev_addr[1]);
-+    printk("%02x",dev->dev_addr[2]);
-+    printk("%02x",dev->dev_addr[3]);
-+    printk("%02x",dev->dev_addr[4]);
-+    printk("%02x\n",dev->dev_addr[5]);
-+
-+    return (0);
-+}
-+
-+static void gmac_tx_timeout(struct net_device *dev)
-+{
-+      GMAC_TXDMA_CTRL_T               tx_ctrl,tx_ctrl_mask;
-+    GMAC_TXDMA_FIRST_DESC_T     txdma_busy;
-+    int                                                       dev_index;
-+
-+    dev_index = gmac_select_interface(dev);
-+
-+    /* if TX DMA process is stoped , restart it */
-+      txdma_busy.bits32 = gmac_read_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_FIRST_DESC);
-+      if (txdma_busy.bits.td_busy == 0)
-+      {
-+              /* restart DMA process */
-+              tx_ctrl.bits32 = 0;
-+              tx_ctrl.bits.td_start = 1;
-+              tx_ctrl.bits.td_continue = 1;
-+              tx_ctrl_mask.bits32 = 0;
-+              tx_ctrl_mask.bits.td_start = 1;
-+              tx_ctrl_mask.bits.td_continue = 1;
-+              gmac_write_reg(gmac_base_addr[dev_index] + GMAC_TXDMA_CTRL,tx_ctrl.bits32,tx_ctrl_mask.bits32);
-+      }
-+      netif_wake_queue(dev);
-+    return;
-+}
-+
-+static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+      int rc = 0;
-+    unsigned char *hwa = rq->ifr_ifru.ifru_hwaddr.sa_data;
-+
-+      if (!netif_running(dev))
-+      {
-+          printk("Before changing the H/W address,please down the device.\n");
-+              return -EINVAL;
-+    }
-+
-+      switch (cmd) {
-+      case SIOCETHTOOL:
-+        break;
-+
-+    case SIOCSIFHWADDR:
-+        gmac_set_mac_address(dev,hwa);
-+        break;
-+
-+      case SIOCGMIIPHY:       /* Get the address of the PHY in use. */
-+      case SIOCDEVPRIVATE:    /* binary compat, remove in 2.5 */
-+        break;
-+
-+      case SIOCGMIIREG:       /* Read the specified MII register. */
-+      case SIOCDEVPRIVATE+1:
-+              break;
-+
-+      case SIOCSMIIREG:       /* Write the specified MII register */
-+      case SIOCDEVPRIVATE+2:
-+              break;
-+
-+      default:
-+              rc = -EOPNOTSUPP;
-+              break;
-+      }
-+
-+      return rc;
-+}
-+
-+static void gmac_cleanup_module(void)
-+{
-+    int i;
-+
-+    for (i=0;i<GMAC_PHY_IF;i++)
-+    {
-+        unregister_netdev(gmac_dev[i]);
-+    }
-+      return ;
-+}
-+
-+static int __init gmac_init_module(void)
-+{
-+      struct gmac_private *tp;
-+      struct net_device *dev[GMAC_PHY_IF];
-+      unsigned int i;
-+
-+#ifdef MODULE
-+      printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
-+#endif
-+//    init_waitqueue_entry(&wait, current);
-+
-+      printk("GMAC Init......\n");
-+      for(i = 0; i<GMAC_PHY_IF; i++)
-+      {
-+              dev[i] = alloc_etherdev(sizeof(struct gmac_private));
-+              if (dev[i] == NULL)
-+              {
-+                      printk (KERN_ERR "Can't allocate ethernet device #%d .\n",i);
-+                      return -ENOMEM;
-+              }
-+        gmac_dev[i] = dev[i];
-+
-+              SET_MODULE_OWNER(dev[i]);
-+
-+              tp = dev[i]->priv;
-+
-+              dev[i]->base_addr = gmac_base_addr[i];
-+              dev[i]->irq = gmac_irq[i];
-+          dev[i]->open = gmac_open;
-+          dev[i]->stop = gmac_close;
-+              dev[i]->hard_start_xmit = gmac_start_xmit;
-+              dev[i]->get_stats = gmac_get_stats;
-+              dev[i]->set_multicast_list = gmac_set_rx_mode;
-+              dev[i]->set_mac_address = gmac_set_mac_address;
-+              dev[i]->do_ioctl = gmac_netdev_ioctl;
-+              dev[i]->tx_timeout = gmac_tx_timeout;
-+              dev[i]->watchdog_timeo = TX_TIMEOUT;
-+              dev[i]->features |= NETIF_F_SG|NETIF_F_HW_CSUM|NETIF_F_TSO;
-+#ifdef CONFIG_SL_NAPI
-+        printk("NAPI driver is enabled.\n");
-+        if (i==0)
-+        {
-+              dev[i]->poll = gmac_rx_poll_ga;
-+              dev[i]->weight = 64;
-+          }
-+          else
-+          {
-+              dev[i]->poll = gmac_rx_poll_gb;
-+              dev[i]->weight = 64;
-+          }
-+#endif
-+
-+              if (register_netdev(dev[i]))
-+              {
-+                      gmac_cleanup_module();
-+                      return(-1);
-+              }
-+      }
-+
-+#ifdef CONFIG_SL3516_ASIC
-+{
-+    unsigned int    val;
-+
-+    /* set GMAC global register */
-+    val = readl(GMAC_GLOBAL_BASE_ADDR+0x10);
-+    val = val | 0x005a0000;
-+    writel(val,GMAC_GLOBAL_BASE_ADDR+0x10);
-+    writel(0x07f007f0,GMAC_GLOBAL_BASE_ADDR+0x1c);
-+    writel(0x77770000,GMAC_GLOBAL_BASE_ADDR+0x20);
-+    writel(0x77770000,GMAC_GLOBAL_BASE_ADDR+0x24);
-+      val = readl(GMAC_GLOBAL_BASE_ADDR+0x04);
-+      if((val&(1<<20))==0){           // GMAC1 enable
-+              val = readl(GMAC_GLOBAL_BASE_ADDR+0x30);
-+              val = (val & 0xe7ffffff) | 0x08000000;
-+              writel(val,GMAC_GLOBAL_BASE_ADDR+0x30);
-+      }
-+
-+}
-+#endif
-+
-+//    printk("%s: dev0=%x  dev1=%x \n",__func__,dev[0],dev[1]);
-+//    FLAG_SWITCH = 0 ;
-+//    FLAG_SWITCH = SPI_get_identifier();
-+//    if(FLAG_SWITCH)
-+//    {
-+//            printk("Configure ADM699X...\n");
-+//            SPI_default();  //Add by jason for ADM699X configuration
-+//    }
-+      return (0);
-+}
-+
-+
-+module_init(gmac_init_module);
-+module_exit(gmac_cleanup_module);
-+
-+static int gmac_phy_thread (void *data)
-+{
-+      struct net_device   *dev = data;
-+      struct gmac_private *tp = dev->priv;
-+      unsigned long       timeout;
-+
-+    daemonize("%s", dev->name);
-+      allow_signal(SIGTERM);
-+//    reparent_to_init();
-+//    spin_lock_irq(&current->sigmask_lock);
-+//    sigemptyset(&current->blocked);
-+//    recalc_sigpending(current);
-+//    spin_unlock_irq(&current->sigmask_lock);
-+//    strncpy (current->comm, dev->name, sizeof(current->comm) - 1);
-+//    current->comm[sizeof(current->comm) - 1] = '\0';
-+
-+      while (1)
-+      {
-+          timeout = next_tick;
-+              do
-+              {
-+                      timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
-+              } while (!signal_pending (current) && (timeout > 0));
-+
-+              if (signal_pending (current))
-+              {
-+//                    spin_lock_irq(&current->sigmask_lock);
-+                      flush_signals(current);
-+//                    spin_unlock_irq(&current->sigmask_lock);
-+              }
-+
-+              if (tp->time_to_die)
-+                      break;
-+
-+//        printk("%s : Polling PHY Status...%x\n",__func__,dev);
-+              rtnl_lock ();
-+        gmac_get_phy_status(dev);
-+              rtnl_unlock ();
-+      }
-+      complete_and_exit (&tp->thr_exited, 0);
-+}
-+
-+static void gmac_set_phy_status(struct net_device *dev)
-+{
-+    GMAC_STATUS_T   status;
-+    unsigned int    reg_val;
-+    unsigned int    i = 0;
-+    unsigned int    index;
-+
-+    if (FLAG_SWITCH==1)
-+    {
-+        return; /* GMAC connects to a switch chip, not PHY */
-+    }
-+
-+    index = gmac_get_dev_index(dev);
-+
-+    if (index == 0)
-+    {
-+//            mii_write(phy_addr[index],0x04,0x0461); /* advertisement 10M full duplex, pause capable on */
-+//            mii_write(phy_addr[index],0x04,0x0421); /* advertisement 10M half duplex, pause capable on */
-+      mii_write(phy_addr[index],0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
-+//            mii_write(phy_addr[index],0x04,0x04a1); /* advertisement 100M half duplex, pause capable on */
-+#ifdef CONFIG_SL3516_ASIC
-+      mii_write(phy_addr[index],0x09,0x0300); /* advertisement 1000M full duplex, pause capable on */
-+//            mii_write(phy_addr[index],0x09,0x0000); /* advertisement 1000M full duplex, pause capable on */
-+#endif
-+    }
-+    else
-+    {
-+//            mii_write(phy_addr[index],0x04,0x0461); /* advertisement 10M full duplex, pause capable on */
-+//            mii_write(phy_addr[index],0x04,0x0421); /* advertisement 10M half duplex, pause capable on */
-+      mii_write(phy_addr[index],0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
-+//            mii_write(phy_addr[index],0x04,0x04a1); /* advertisement 100M half duplex, pause capable on */
-+#ifdef CONFIG_SL3516_ASIC
-+//            mii_write(phy_addr[index],0x09,0x0000); /* advertisement no 1000M */
-+      mii_write(phy_addr[index],0x09,0x0300); /* advertisement 1000M full duplex, pause capable on */
-+#endif
-+      }
-+
-+    mii_write(phy_addr[index],0x00,0x1200); /* Enable and Restart Auto-Negotiation */
-+    mii_write(phy_addr[index],0x18,0x0041); /* Enable Active led */
-+    while (((reg_val=mii_read(phy_addr[index],0x01)) & 0x00000004)!=0x04)
-+    {
-+        i++;
-+        if (i > 30)
-+        {
-+            break;
-+        }
-+      msleep(100);
-+    }
-+    if (i>30)
-+    {
-+        pre_phy_status[index] = LINK_DOWN;
-+              clear_bit(__LINK_STATE_START, &dev->state);
-+        netif_stop_queue(dev);
-+        storlink_ctl.link = 0;
-+        printk("Link Down (%04x) ",reg_val);
-+    }
-+    else
-+    {
-+        pre_phy_status[index] = LINK_UP;
-+              set_bit(__LINK_STATE_START, &dev->state);
-+        netif_wake_queue(dev);
-+        storlink_ctl.link = 1;
-+        printk("Link Up (%04x) ",reg_val);
-+    }
-+
-+    status.bits32 = 0;
-+    reg_val = mii_read(phy_addr[index],10);
-+    printk("reg_val0 = %x \n",reg_val);
-+    if ((reg_val & 0x0800) == 0x0800)
-+    {
-+        status.bits.duplex = 1;
-+        status.bits.speed = 2;
-+        printk(" 1000M/Full \n");
-+    }
-+    else if ((reg_val & 0x0400) == 0x0400)
-+    {
-+        status.bits.duplex = 0;
-+        status.bits.speed = 2;
-+        printk(" 1000M/Half \n");
-+    }
-+    else
-+    {
-+        reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
-+        printk("reg_val1 = %x \n",reg_val);
-+        if ((reg_val & 0x08)==0x08) /* 100M full duplex */
-+        {
-+                status.bits.duplex = 1;
-+                status.bits.speed = 1;
-+                printk(" 100M/Full \n");
-+        }
-+        else if ((reg_val & 0x04)==0x04) /* 100M half duplex */
-+        {
-+                status.bits.duplex = 0;
-+                status.bits.speed = 1;
-+                printk(" 100M/Half \n");
-+        }
-+        else if ((reg_val & 0x02)==0x02) /* 10M full duplex */
-+        {
-+                status.bits.duplex = 1;
-+                status.bits.speed = 0;
-+                printk(" 10M/Full \n");
-+        }
-+        else if ((reg_val & 0x01)==0x01) /* 10M half duplex */
-+        {
-+                status.bits.duplex = 0;
-+                status.bits.speed = 0;
-+                printk(" 100M/Half \n");
-+        }
-+    }
-+
-+    reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
-+    if ((reg_val & 0x20)==0x20)
-+    {
-+        flow_control_enable[index] = 1;
-+        printk("Flow Control Enable. \n");
-+    }
-+    else
-+    {
-+        flow_control_enable[index] = 0;
-+        printk("Flow Control Disable. \n");
-+    }
-+    full_duplex = status.bits.duplex;
-+    speed = status.bits.speed;
-+}
-+
-+static void gmac_get_phy_status(struct net_device *dev)
-+{
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+    GMAC_STATUS_T   status;
-+    unsigned int    reg_val;
-+    unsigned int    index;
-+
-+    index = gmac_select_interface(dev);
-+
-+    status.bits32 = 0;
-+    status.bits.phy_mode = 1;
-+
-+#ifdef CONFIG_SL3516_ASIC
-+    status.bits.mii_rmii = 2;   /* default value for ASIC version */
-+//    status.bits.speed = 1;
-+#else
-+    if (index==0)
-+        status.bits.mii_rmii = 0;
-+    else
-+        status.bits.mii_rmii = 2;
-+#endif
-+
-+    /* read PHY status register */
-+    reg_val = mii_read(phy_addr[index],0x01);
-+    if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */
-+    {
-+        /* read PHY Auto-Negotiation Link Partner Ability Register */
-+        reg_val = mii_read(phy_addr[index],10);
-+        if ((reg_val & 0x0800) == 0x0800)
-+        {
-+            status.bits.mii_rmii = 3;  /* RGMII 1000Mbps mode */
-+            status.bits.duplex = 1;
-+            status.bits.speed = 2;
-+        }
-+        else if ((reg_val & 0x0400) == 0x0400)
-+        {
-+            status.bits.mii_rmii = 3;  /* RGMII 1000Mbps mode */
-+            status.bits.duplex = 0;
-+            status.bits.speed = 2;
-+        }
-+        else
-+        {
-+            reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
-+            if ((reg_val & 0x08)==0x08) /* 100M full duplex */
-+            {
-+                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
-+                    status.bits.duplex = 1;
-+                    status.bits.speed = 1;
-+            }
-+            else if ((reg_val & 0x04)==0x04) /* 100M half duplex */
-+            {
-+                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
-+                    status.bits.duplex = 0;
-+                    status.bits.speed = 1;
-+            }
-+            else if ((reg_val & 0x02)==0x02) /* 10M full duplex */
-+            {
-+                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
-+                    status.bits.duplex = 1;
-+                    status.bits.speed = 0;
-+            }
-+            else if ((reg_val & 0x01)==0x01) /* 10M half duplex */
-+            {
-+                    status.bits.mii_rmii = 2;  /* RGMII 10/100Mbps mode */
-+                    status.bits.duplex = 0;
-+                    status.bits.speed = 0;
-+            }
-+        }
-+        status.bits.link = LINK_UP; /* link up */
-+        netif_wake_queue(dev);
-+
-+        reg_val = (mii_read(phy_addr[index],0x05) & 0x05E0) >> 5;
-+        if ((reg_val & 0x20)==0x20)
-+        {
-+            if (flow_control_enable[index] == 0)
-+            {
-+                config0.bits32 = 0;
-+                config0_mask.bits32 = 0;
-+                config0.bits.tx_fc_en = 1; /* enable tx flow control */
-+                config0.bits.rx_fc_en = 1; /* enable rx flow control */
-+                config0_mask.bits.tx_fc_en = 1;
-+                config0_mask.bits.rx_fc_en = 1;
-+                gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+//                printk("eth%d Flow Control Enable. \n",index);
-+            }
-+            flow_control_enable[index] = 1;
-+        }
-+        else
-+        {
-+            if (flow_control_enable[index] == 1)
-+            {
-+                config0.bits32 = 0;
-+                config0_mask.bits32 = 0;
-+                config0.bits.tx_fc_en = 0; /* disable tx flow control */
-+                config0.bits.rx_fc_en = 0; /* disable rx flow control */
-+                config0_mask.bits.tx_fc_en = 1;
-+                config0_mask.bits.rx_fc_en = 1;
-+                gmac_write_reg(gmac_base_addr[index] + GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+//                printk("eth%d Flow Control Disable. \n",index);
-+            }
-+            flow_control_enable[index] = 0;
-+        }
-+
-+        if (pre_phy_status[index] == LINK_DOWN)
-+        {
-+            gmac_enable_tx_rx(dev);
-+            pre_phy_status[index] = LINK_UP;
-+                      set_bit(__LINK_STATE_START, &dev->state);
-+                      storlink_ctl.link = 1;
-+//                    printk("eth%d Link Up ...\n",index);
-+        }
-+    }
-+    else
-+    {
-+        status.bits.link = LINK_DOWN; /* link down */
-+        netif_stop_queue(dev);
-+        flow_control_enable[index] = 0;
-+        storlink_ctl.link = 0;
-+        if (pre_phy_status[index] == LINK_UP)
-+        {
-+            gmac_disable_tx_rx(dev);
-+            pre_phy_status[index] = LINK_DOWN;
-+                      clear_bit(__LINK_STATE_START, &dev->state);
-+//                    printk("eth%d Link Down ...\n",index);
-+      }
-+
-+    }
-+
-+    reg_val = gmac_read_reg(gmac_base_addr[index] + GMAC_STATUS);
-+    if (reg_val != status.bits32)
-+    {
-+        gmac_write_reg(gmac_base_addr[index] + GMAC_STATUS,status.bits32,0x0000007f);
-+    }
-+}
-+
-+/***************************************/
-+/* define GPIO module base address     */
-+/***************************************/
-+#define GPIO_BASE_ADDR  (IO_ADDRESS(SL2312_GPIO_BASE))
-+
-+/* define GPIO pin for MDC/MDIO */
-+
-+// for gemini ASIC
-+#ifdef CONFIG_SL3516_ASIC
-+#define H_MDC_PIN           22
-+#define H_MDIO_PIN          21
-+#define G_MDC_PIN           22
-+#define G_MDIO_PIN          21
-+#else
-+#define H_MDC_PIN           3
-+#define H_MDIO_PIN          2
-+#define G_MDC_PIN           0
-+#define G_MDIO_PIN          1
-+#endif
-+
-+//#define GPIO_MDC             0x80000000
-+//#define GPIO_MDIO            0x00400000
-+
-+static unsigned int GPIO_MDC = 0;
-+static unsigned int GPIO_MDIO = 0;
-+static unsigned int GPIO_MDC_PIN = 0;
-+static unsigned int GPIO_MDIO_PIN = 0;
-+
-+// For PHY test definition!!
-+#define LPC_EECK              0x02
-+#define LPC_EDIO              0x04
-+#define LPC_GPIO_SET          3
-+#define LPC_BASE_ADDR         IO_ADDRESS(IT8712_IO_BASE)
-+#define inb_gpio(x)           inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
-+#define outb_gpio(x, y)               outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
-+
-+enum GPIO_REG
-+{
-+    GPIO_DATA_OUT   = 0x00,
-+    GPIO_DATA_IN    = 0x04,
-+    GPIO_PIN_DIR    = 0x08,
-+    GPIO_BY_PASS    = 0x0c,
-+    GPIO_DATA_SET   = 0x10,
-+    GPIO_DATA_CLEAR = 0x14,
-+};
-+/***********************/
-+/*    MDC : GPIO[31]   */
-+/*    MDIO: GPIO[22]   */
-+/***********************/
-+
-+/***************************************************
-+* All the commands should have the frame structure:
-+*<PRE><ST><OP><PHYAD><REGAD><TA><DATA><IDLE>
-+****************************************************/
-+
-+/*****************************************************************
-+* Inject a bit to NWay register through CSR9_MDC,MDIO
-+*******************************************************************/
-+void mii_serial_write(char bit_MDO) // write data into mii PHY
-+{
-+#if 0 //def CONFIG_SL2312_LPC_IT8712
-+      unsigned char iomode,status;
-+
-+      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
-+      iomode |= (LPC_EECK|LPC_EDIO) ;                         // Set EECK,EDIO,EECS output
-+      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
-+
-+      if(bit_MDO)
-+      {
-+              status = inb_gpio( LPC_GPIO_SET);
-+              status |= LPC_EDIO ;            //EDIO high
-+              outb_gpio(LPC_GPIO_SET, status);
-+      }
-+      else
-+      {
-+              status = inb_gpio( LPC_GPIO_SET);
-+              status &= ~(LPC_EDIO) ;         //EDIO low
-+              outb_gpio(LPC_GPIO_SET, status);
-+      }
-+
-+      status |= LPC_EECK ;            //EECK high
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      status &= ~(LPC_EECK) ;         //EECK low
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+#else
-+    unsigned int addr;
-+    unsigned int value;
-+
-+    addr = GPIO_BASE_ADDR + GPIO_PIN_DIR;
-+    value = readl(addr) | GPIO_MDC | GPIO_MDIO; /* set MDC/MDIO Pin to output */
-+    writel(value,addr);
-+    if(bit_MDO)
-+    {
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+        writel(GPIO_MDIO,addr); /* set MDIO to 1 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+        writel(GPIO_MDC,addr); /* set MDC to 1 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+        writel(GPIO_MDC,addr); /* set MDC to 0 */
-+    }
-+    else
-+    {
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+        writel(GPIO_MDIO,addr); /* set MDIO to 0 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+        writel(GPIO_MDC,addr); /* set MDC to 1 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+        writel(GPIO_MDC,addr); /* set MDC to 0 */
-+    }
-+
-+#endif
-+}
-+
-+/**********************************************************************
-+* read a bit from NWay register through CSR9_MDC,MDIO
-+***********************************************************************/
-+unsigned int mii_serial_read(void) // read data from mii PHY
-+{
-+#if 0 //def CONFIG_SL2312_LPC_IT8712
-+      unsigned char iomode,status;
-+      unsigned int value ;
-+
-+      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
-+      iomode &= ~(LPC_EDIO) ;         // Set EDIO input
-+      iomode |= (LPC_EECK) ;          // Set EECK,EECS output
-+      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
-+
-+      status = inb_gpio( LPC_GPIO_SET);
-+      status |= LPC_EECK ;            //EECK high
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      status &= ~(LPC_EECK) ;         //EECK low
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      value = inb_gpio( LPC_GPIO_SET);
-+
-+      value = value>>2 ;
-+      value &= 0x01;
-+
-+      return value ;
-+
-+#else
-+    unsigned int *addr;
-+    unsigned int value;
-+
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_PIN_DIR);
-+    value = readl(addr) & ~GPIO_MDIO; //0xffbfffff;   /* set MDC to output and MDIO to input */
-+    writel(value,addr);
-+
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);
-+    writel(GPIO_MDC,addr); /* set MDC to 1 */
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+    writel(GPIO_MDC,addr); /* set MDC to 0 */
-+
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_IN);
-+    value = readl(addr);
-+    value = (value & (1<<GPIO_MDIO_PIN)) >> GPIO_MDIO_PIN;
-+    return(value);
-+
-+#endif
-+}
-+
-+/***************************************
-+* preamble + ST
-+***************************************/
-+void mii_pre_st(void)
-+{
-+    unsigned char i;
-+
-+    for(i=0;i<32;i++) // PREAMBLE
-+        mii_serial_write(1);
-+    mii_serial_write(0); // ST
-+    mii_serial_write(1);
-+}
-+
-+
-+/******************************************
-+* Read MII register
-+* phyad -> physical address
-+* regad -> register address
-+***************************************** */
-+unsigned int mii_read(unsigned char phyad,unsigned char regad)
-+{
-+    unsigned int i,value;
-+    unsigned int bit;
-+
-+    if (phyad == GPHY_ADDR)
-+    {
-+        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
-+        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
-+    }
-+    else
-+    {
-+        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
-+        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
-+    }
-+    GPIO_MDC = (1<<GPIO_MDC_PIN);
-+    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
-+
-+    mii_pre_st(); // PRE+ST
-+    mii_serial_write(1); // OP
-+    mii_serial_write(0);
-+
-+    for (i=0;i<5;i++) { // PHYAD
-+        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+
-+    for (i=0;i<5;i++) { // REGAD
-+        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+
-+    mii_serial_read(); // TA_Z
-+//    if((bit=mii_serial_read()) !=0 ) // TA_0
-+//    {
-+//        return(0);
-+//    }
-+    value=0;
-+    for (i=0;i<16;i++) { // READ DATA
-+        bit=mii_serial_read();
-+        value += (bit<<(15-i)) ;
-+    }
-+
-+    mii_serial_write(0); // dumy clock
-+    mii_serial_write(0); // dumy clock
-+//printk("%s: phy_addr=%x reg_addr=%x value=%x \n",__func__,phyad,regad,value);
-+    return(value);
-+}
-+
-+/******************************************
-+* Write MII register
-+* phyad -> physical address
-+* regad -> register address
-+* value -> value to be write
-+***************************************** */
-+void mii_write(unsigned char phyad,unsigned char regad,unsigned int value)
-+{
-+    unsigned int i;
-+    char bit;
-+
-+printk("%s: phy_addr=%x reg_addr=%x value=%x \n",__func__,phyad,regad,value);
-+    if (phyad == GPHY_ADDR)
-+    {
-+        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
-+        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
-+    }
-+    else
-+    {
-+        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
-+        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
-+    }
-+    GPIO_MDC = (1<<GPIO_MDC_PIN);
-+    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
-+
-+    mii_pre_st(); // PRE+ST
-+    mii_serial_write(0); // OP
-+    mii_serial_write(1);
-+    for (i=0;i<5;i++) { // PHYAD
-+        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+
-+    for (i=0;i<5;i++) { // REGAD
-+        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+    mii_serial_write(1); // TA_1
-+    mii_serial_write(0); // TA_0
-+
-+    for (i=0;i<16;i++) { // OUT DATA
-+        bit= ((value>>(15-i)) & 0x01) ? 1 : 0 ;
-+        mii_serial_write(bit);
-+    }
-+    mii_serial_write(0); // dumy clock
-+    mii_serial_write(0); // dumy clock
-+}
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+/*                            NOTES
-+ *   The instruction set of the 93C66/56/46/26/06 chips are as follows:
-+ *
-+ *               Start  OP        *
-+ *     Function   Bit  Code  Address**  Data     Description
-+ *     -------------------------------------------------------------------
-+ *     READ        1    10   A7 - A0             Reads data stored in memory,
-+ *                                               starting at specified address
-+ *     EWEN        1    00   11XXXXXX            Write enable must precede
-+ *                                               all programming modes
-+ *     ERASE       1    11   A7 - A0             Erase register A7A6A5A4A3A2A1A0
-+ *     WRITE       1    01   A7 - A0   D15 - D0  Writes register
-+ *     ERAL        1    00   10XXXXXX            Erase all registers
-+ *     WRAL        1    00   01XXXXXX  D15 - D0  Writes to all registers
-+ *     EWDS        1    00   00XXXXXX            Disables all programming
-+ *                                               instructions
-+ *    *Note: A value of X for address is a don't care condition.
-+ *    **Note: There are 8 address bits for the 93C56/66 chips unlike
-+ *          the 93C46/26/06 chips which have 6 address bits.
-+ *
-+ *   The 93Cx6 has a four wire interface: clock, chip select, data in, and
-+ *   data out.While the ADM6996 uning three interface: clock, chip select,and data line.
-+ *   The input and output are the same pin. ADM6996 can only recognize the write cmd.
-+ *   In order to perform above functions, you need
-+ *   1. to enable the chip select .
-+ *   2. send one clock of dummy clock
-+ *   3. send start bit and opcode
-+ *   4. send 8 bits address and 16 bits data
-+ *   5. to disable the chip select.
-+ *                                                    Jason Lee 2003/07/30
-+ */
-+
-+/***************************************/
-+/* define GPIO module base address     */
-+/***************************************/
-+#define GPIO_EECS          0x00400000         /*   EECS: GPIO[22]   */
-+//#define GPIO_MOSI        0x20000000         /*   EEDO: GPIO[29]   send to 6996*/
-+#define GPIO_MISO          0x40000000         /*   EEDI: GPIO[30]   receive from 6996*/
-+#define GPIO_EECK          0x80000000         /*   EECK: GPIO[31]   */
-+
-+#define ADM_EECS              0x01
-+#define ADM_EECK              0x02
-+#define ADM_EDIO              0x04
-+/*************************************************************
-+* SPI protocol for ADM6996 control
-+**************************************************************/
-+#define SPI_OP_LEN         0x03               // the length of start bit and opcode
-+#define SPI_OPWRITE        0X05               // write
-+#define SPI_OPREAD         0X06               // read
-+#define SPI_OPERASE        0X07               // erase
-+#define SPI_OPWTEN         0X04               // write enable
-+#define SPI_OPWTDIS        0X04               // write disable
-+#define SPI_OPERSALL       0X04               // erase all
-+#define SPI_OPWTALL        0X04               // write all
-+
-+#define SPI_ADD_LEN        8                  // bits of Address
-+#define SPI_DAT_LEN        16                 // bits of Data
-+#define ADM6996_PORT_NO            6                  // the port number of ADM6996
-+#define ADM6999_PORT_NO            9                  // the port number of ADM6999
-+#ifdef CONFIG_ADM_6996
-+      #define ADM699X_PORT_NO         ADM6996_PORT_NO
-+#endif
-+#ifdef CONFIG_ADM_6999
-+      #define ADM699X_PORT_NO         ADM6999_PORT_NO
-+#endif
-+#define LPC_GPIO_SET          3
-+#define LPC_BASE_ADDR                 IO_ADDRESS(IT8712_IO_BASE)
-+
-+extern int it8712_exist;
-+
-+#define inb_gpio(x)                   inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
-+#define outb_gpio(x, y)               outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
-+
-+/****************************************/
-+/*    Function Declare                */
-+/****************************************/
-+/*
-+void SPI_write(unsigned char addr,unsigned int value);
-+unsigned int SPI_read(unsigned char table,unsigned char addr);
-+void SPI_write_bit(char bit_EEDO);
-+unsigned int SPI_read_bit(void);
-+void SPI_default(void);
-+void SPI_reset(unsigned char rstype,unsigned char port_cnt);
-+void SPI_pre_st(void);
-+void SPI_CS_enable(unsigned char enable);
-+void SPI_Set_VLAN(unsigned char LAN,unsigned int port_mask);
-+void SPI_Set_tag(unsigned int port,unsigned tag);
-+void SPI_Set_PVID(unsigned int PVID,unsigned int port_mask);
-+void SPI_mac_lock(unsigned int port, unsigned char lock);
-+void SPI_get_port_state(unsigned int port);
-+void SPI_port_enable(unsigned int port,unsigned char enable);
-+
-+void SPI_get_status(unsigned int port);
-+*/
-+
-+struct PORT_CONFIG
-+{
-+      unsigned char auto_negotiation; // 0:Disable    1:Enable
-+      unsigned char speed;            // 0:10M        1:100M
-+      unsigned char duplex;           // 0:Half       1:Full duplex
-+      unsigned char Tag;              // 0:Untag      1:Tag
-+      unsigned char port_disable;     // 0:port enable        1:disable
-+      unsigned char pvid;             // port VLAN ID 0001
-+      unsigned char mdix;             // Crossover judgement. 0:Disable 1:Enable
-+      unsigned char mac_lock;         // MAC address Lock 0:Disable 1:Enable
-+};
-+
-+struct PORT_STATUS
-+{
-+      unsigned char link;             // 0:not link   1:link established
-+      unsigned char speed;            // 0:10M        1:100M
-+      unsigned char duplex;           // 0:Half       1:Full duplex
-+      unsigned char flow_ctl;         // 0:flow control disable 1:enable
-+      unsigned char mac_lock;         // MAC address Lock 0:Disable 1:Enable
-+      unsigned char port_disable;     // 0:port enable        1:disable
-+
-+      // Serial Management
-+      unsigned long rx_pac_count;             //receive packet count
-+      unsigned long rx_pac_byte;              //receive packet byte count
-+      unsigned long tx_pac_count;             //transmit packet count
-+      unsigned long tx_pac_byte;              //transmit packet byte count
-+      unsigned long collision_count;          //error count
-+      unsigned long error_count ;
-+
-+      unsigned long rx_pac_count_overflow;            //overflow flag
-+      unsigned long rx_pac_byte_overflow;
-+      unsigned long tx_pac_count_overflow;
-+      unsigned long tx_pac_byte_overflow;
-+      unsigned long collision_count_overflow;
-+      unsigned long error_count_overflow;
-+};
-+
-+struct PORT_CONFIG port_config[ADM699X_PORT_NO];      // 0~3:LAN , 4:WAN , 5:MII
-+static struct PORT_STATUS port_state[ADM699X_PORT_NO];
-+
-+/******************************************
-+* SPI_write
-+* addr -> Write Address
-+* value -> value to be write
-+***************************************** */
-+void SPI_write(unsigned char addr,unsigned int value)
-+{
-+      int     i;
-+      char    bit;
-+#ifdef CONFIG_IT8712_GPIO
-+      char    status;
-+#else
-+    int     ad1;
-+#endif
-+
-+#ifdef CONFIG_IT8712_GPIO
-+      status = inb_gpio(LPC_GPIO_SET);
-+      status &= ~(ADM_EDIO) ;         //EDIO low
-+      outb_gpio(LPC_GPIO_SET, status);
-+#else
-+      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+      writel(GPIO_MISO,ad1); /* set MISO to 0 */
-+#endif
-+      SPI_CS_enable(1);
-+
-+      SPI_write_bit(0);       //dummy clock
-+
-+      //send write command (0x05)
-+      for(i=SPI_OP_LEN-1;i>=0;i--)
-+      {
-+              bit = (SPI_OPWRITE>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+      // send 8 bits address (MSB first, LSB last)
-+      for(i=SPI_ADD_LEN-1;i>=0;i--)
-+      {
-+              bit = (addr>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+      // send 16 bits data (MSB first, LSB last)
-+      for(i=SPI_DAT_LEN-1;i>=0;i--)
-+      {
-+              bit = (value>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+
-+      SPI_CS_enable(0);       // CS low
-+
-+      for(i=0;i<0xFFF;i++) ;
-+#ifdef CONFIG_IT8712_GPIO
-+      status = inb_gpio(LPC_GPIO_SET);
-+      status &= ~(ADM_EDIO) ;         //EDIO low
-+      outb_gpio(LPC_GPIO_SET, status);
-+#else
-+      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+      writel(GPIO_MISO,ad1); /* set MISO to 0 */
-+#endif
-+}
-+
-+
-+/************************************
-+* SPI_write_bit
-+* bit_EEDO -> 1 or 0 to be written
-+************************************/
-+void SPI_write_bit(char bit_EEDO)
-+{
-+#ifdef CONFIG_IT8712_GPIO
-+      unsigned char iomode,status;
-+
-+      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
-+      iomode |= (ADM_EECK|ADM_EDIO|ADM_EECS) ;                                // Set EECK,EDIO,EECS output
-+      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
-+
-+      if(bit_EEDO)
-+      {
-+              status = inb_gpio( LPC_GPIO_SET);
-+              status |= ADM_EDIO ;            //EDIO high
-+              outb_gpio(LPC_GPIO_SET, status);
-+      }
-+      else
-+      {
-+              status = inb_gpio( LPC_GPIO_SET);
-+              status &= ~(ADM_EDIO) ;         //EDIO low
-+              outb_gpio(LPC_GPIO_SET, status);
-+      }
-+
-+      status |= ADM_EECK ;            //EECK high
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      status &= ~(ADM_EECK) ;         //EECK low
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+#else
-+      unsigned int addr;
-+      unsigned int value;
-+
-+      addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);
-+      value = readl(addr) |GPIO_EECK |GPIO_MISO ;   /* set EECK/MISO Pin to output */
-+      writel(value,addr);
-+      if(bit_EEDO)
-+      {
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+              writel(GPIO_MISO,addr); /* set MISO to 1 */
-+              writel(GPIO_EECK,addr); /* set EECK to 1 */
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+              writel(GPIO_EECK,addr); /* set EECK to 0 */
-+      }
-+      else
-+      {
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+              writel(GPIO_MISO,addr); /* set MISO to 0 */
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+              writel(GPIO_EECK,addr); /* set EECK to 1 */
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+              writel(GPIO_EECK,addr); /* set EECK to 0 */
-+      }
-+
-+      return ;
-+#endif
-+}
-+
-+/**********************************************************************
-+* read a bit from ADM6996 register
-+***********************************************************************/
-+unsigned int SPI_read_bit(void) // read data from
-+{
-+#ifdef CONFIG_IT8712_GPIO
-+      unsigned char iomode,status;
-+      unsigned int value ;
-+
-+      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
-+      iomode &= ~(ADM_EDIO) ;         // Set EDIO input
-+      iomode |= (ADM_EECS|ADM_EECK) ;         // Set EECK,EECS output
-+      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
-+
-+      status = inb_gpio( LPC_GPIO_SET);
-+      status |= ADM_EECK ;            //EECK high
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      status &= ~(ADM_EECK) ;         //EECK low
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      value = inb_gpio( LPC_GPIO_SET);
-+
-+      value = value>>2 ;
-+      value &= 0x01;
-+
-+      return value ;
-+#else
-+      unsigned int addr;
-+      unsigned int value;
-+
-+      addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);
-+      value = readl(addr) & (~GPIO_MISO);   // set EECK to output and MISO to input
-+      writel(value,addr);
-+
-+      addr =(GPIO_BASE_ADDR + GPIO_DATA_SET);
-+      writel(GPIO_EECK,addr); // set EECK to 1
-+      addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+      writel(GPIO_EECK,addr); // set EECK to 0
-+
-+      addr = (GPIO_BASE_ADDR + GPIO_DATA_IN);
-+      value = readl(addr) ;
-+      value = value >> 30;
-+      return value ;
-+#endif
-+}
-+
-+/******************************************
-+* SPI_default
-+* EEPROM content default value
-+*******************************************/
-+void SPI_default(void)
-+{
-+      int i;
-+#ifdef CONFIG_ADM_6999
-+      SPI_write(0x11,0xFF30);
-+      for(i=1;i<8;i++)
-+              SPI_write(i,0x840F);
-+
-+      SPI_write(0x08,0x880F);                 //port 8 Untag, PVID=2
-+      SPI_write(0x09,0x881D);                 //port 9 Tag, PVID=2 ,10M
-+      SPI_write(0x14,0x017F);                 //Group 0~6,8 as VLAN 1
-+      SPI_write(0x15,0x0180);                 //Group 7,8 as VLAN 2
-+#endif
-+
-+#ifdef CONFIG_ADM_6996
-+      SPI_write(0x11,0xFF30);
-+      SPI_write(0x01,0x840F);                 //port 0~3 Untag ,PVID=1 ,100M ,duplex
-+      SPI_write(0x03,0x840F);
-+      SPI_write(0x05,0x840F);
-+      SPI_write(0x07,0x840F);
-+      SPI_write(0x08,0x880F);                 //port 4 Untag, PVID=2
-+      SPI_write(0x09,0x881D);                 //port 5 Tag, PVID=2 ,10M
-+      SPI_write(0x14,0x0155);                 //Group 0~3,5 as VLAN 1
-+      SPI_write(0x15,0x0180);                 //Group 4,5 as VLAN 2
-+
-+#endif
-+
-+      for(i=0x16;i<=0x22;i++)
-+              SPI_write((unsigned char)i,0x0000);             // clean VLAN¡@map 3~15
-+
-+      for (i=0;i<NUM_VLAN_IF;i++)                             // Set VLAN ID map 1,2
-+              SPI_Set_PVID( VLAN_conf[i].vid,  VLAN_conf[i].portmap);
-+
-+      for(i=0;i<ADM699X_PORT_NO;i++)                          // reset count
-+              SPI_reset(0,i);
-+}
-+
-+/*************************************************
-+* SPI_reset
-+* rstype -> reset type
-+*         0:reset all count for 'port_cnt' port
-+*         1:reset specified count 'port_cnt'
-+* port_cnt   ->  port number or counter index
-+***************************************************/
-+void SPI_reset(unsigned char rstype,unsigned char port_cnt)
-+{
-+
-+      int i;
-+#ifdef CONFIG_IT8712_GPIO
-+    char status;
-+#else
-+      int ad1;
-+#endif
-+      char bit;
-+
-+#ifdef CONFIG_IT8712_GPIO
-+      status = inb_gpio(LPC_GPIO_SET);
-+      status &= ~(ADM_EDIO) ;         //EDIO low
-+      outb_gpio(LPC_GPIO_SET, status);
-+#else
-+      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+      writel(GPIO_MISO,ad1); /* set MISO to 0 */
-+#endif
-+
-+      SPI_CS_enable(0);       // CS low
-+
-+      SPI_pre_st(); // PRE+ST
-+      SPI_write_bit(0); // OP
-+      SPI_write_bit(1);
-+
-+      SPI_write_bit(1);               // Table select, must be 1 -> reset Counter
-+
-+      SPI_write_bit(0);               // Device Address
-+      SPI_write_bit(0);
-+
-+      rstype &= 0x01;
-+      SPI_write_bit(rstype);          // Reset type 0:clear dedicate port's all counters 1:clear dedicate counter
-+
-+      for (i=5;i>=0;i--)              // port or cnt index
-+      {
-+              bit = port_cnt >> i ;
-+              bit &= 0x01 ;
-+              SPI_write_bit(bit);
-+      }
-+
-+      SPI_write_bit(0);               // dumy clock
-+      SPI_write_bit(0);               // dumy clock
-+
-+#ifdef CONFIG_IT8712_GPIO
-+      status = inb_gpio(LPC_GPIO_SET);
-+      status &= ~(ADM_EDIO) ;         //EDIO low
-+      outb_gpio(LPC_GPIO_SET, status);
-+#else
-+      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+      writel(GPIO_MISO,ad1); /* set MISO to 0 */
-+#endif
-+}
-+
-+/*****************************************************
-+* SPI_pre_st
-+* preambler: 32 bits '1'   start bit: '01'
-+*****************************************************/
-+void SPI_pre_st(void)
-+{
-+      int i;
-+
-+      for(i=0;i<32;i++) // PREAMBLE
-+              SPI_write_bit(1);
-+      SPI_write_bit(0); // ST
-+      SPI_write_bit(1);
-+}
-+
-+
-+/***********************************************************
-+* SPI_CS_enable
-+* before access ,you have to enable Chip Select. (pull high)
-+* When fisish, you should pull low !!
-+*************************************************************/
-+void SPI_CS_enable(unsigned char enable)
-+{
-+#ifdef CONFIG_IT8712_GPIO
-+
-+      unsigned char iomode,status;
-+
-+      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
-+      iomode |= (ADM_EECK|ADM_EDIO|ADM_EECS) ;                                // Set EECK,EDIO,EECS output
-+      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
-+
-+
-+      status = inb_gpio( LPC_GPIO_SET);
-+      if(enable)
-+              status |= ADM_EECS ;            //EECS high
-+      else
-+              status &= ~(ADM_EECS) ; //EECS low
-+
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+
-+      status |= ADM_EECK ;            //EECK high
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      status &= ~(ADM_EECK) ;         //EECK low
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+#else
-+      unsigned int addr,value;
-+
-+      addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);
-+      value = readl(addr) |GPIO_EECS |GPIO_EECK;   /* set EECS/EECK Pin to output */
-+      writel(value,addr);
-+
-+      if(enable)
-+      {
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+              writel(GPIO_EECS,addr); /* set EECS to 1 */
-+
-+      }
-+      else
-+      {
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+              writel(GPIO_EECS,addr); /* set EECS to 0 */
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+              writel(GPIO_EECK,addr); /* set EECK to 1 */     // at least one clock after CS low
-+              addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+              writel(GPIO_EECK,addr); /* set EECK to 0 */
-+      }
-+#endif
-+}
-+
-+/*********************************************************
-+* SPI_Set_VLAN: group ports as VLAN
-+* LAN  -> VLAN number : 0~16
-+* port_mask -> ports which would group as LAN
-+*            ex. 0x03 = 0000 0011
-+*                     port 0 and port 1
-+*********************************************************/
-+void SPI_Set_VLAN(unsigned char LAN,unsigned int port_mask)
-+{
-+      unsigned int i,value=0;
-+      unsigned reg_add = 0x13 + LAN ;
-+
-+      for(i=0;i<ADM6996_PORT_NO;i++)
-+      {       if(port_mask&0x01)
-+              {
-+                      switch(i)
-+                      {
-+                              case 0: value|=0x0001;  break;  //port0:bit[0]
-+                              case 1: value|=0x0004;  break;  //port1:bit[2]
-+                              case 2: value|=0x0010;  break;  //port2:bit[4]
-+                              case 3: value|=0x0040;  break;  //port3:bit[6]
-+                              case 4: value|=0x0080;  break;  //port4:bit[7]
-+                              case 5: value|=0x0100;  break;  //port5:bit[8]
-+                      }
-+              }
-+              port_mask >>= 1;
-+      }
-+
-+      SPI_write(reg_add,value);
-+}
-+
-+
-+/*******************************************
-+* SPI_Set_tag
-+* port -> port number to set tag or untag
-+* tag  -> 0/set untag,  1/set tag
-+* In general, tag is for MII port. LAN and
-+* WAN port is configed as untag!!
-+********************************************/
-+void SPI_Set_tag(unsigned int port,unsigned tag)
-+{
-+      unsigned int regadd,value;
-+
-+      // mapping port's register !! (0,1,2,3,4,5) ==> (1,3,5,7,8,9)
-+      if(port<=3)
-+              regadd=2*port+1;
-+      else if(port==4) regadd = 8 ;
-+      else regadd = 9 ;
-+
-+
-+      value = SPI_read(0,regadd);             //read original setting
-+
-+      if(tag)
-+              value |= 0x0010 ;               // set tag
-+      else
-+              value &= 0xFFEF ;               // set untag
-+
-+      SPI_write(regadd,value);                // write back!!
-+}
-+
-+/************************************************
-+* SPI_Set_PVID
-+* PVID -> PVID number :
-+* port_mask -> ports which would group as LAN
-+*            ex. 0x0F = 0000 1111 ==> port 0~3
-+************************************************/
-+void SPI_Set_PVID(unsigned int PVID,unsigned int port_mask)
-+{
-+      unsigned int i,value=0;
-+
-+      PVID &= 0x000F ;
-+
-+      for(i=0;i<ADM699X_PORT_NO;i++)
-+      {       if(port_mask&0x01)
-+              {
-+#ifdef CONFIG_ADM_6996
-+                      switch(i)
-+                      {
-+                              case 0:
-+                                      value = SPI_read(0,0x01);       // read original value
-+                                      value &= 0xC3FF ;                       //set PVIC column as 0 first
-+                                      value |= PVID << 10 ;           //Set PVID column as PVID
-+                                      SPI_write(0x01,value);          //write back
-+                                      break;
-+                              case 1:
-+                                      value = SPI_read(0,0x03);
-+                                      value &= 0xC3FF ;
-+                                      value |= PVID << 10 ;
-+                                      SPI_write(0x03,value);
-+                                      break;
-+                              case 2:
-+                                      value = SPI_read(0,0x05);
-+                                      value &= 0xC3FF ;
-+                                      value |= PVID << 10 ;
-+                                      SPI_write(0x05,value);
-+                                      break;
-+                              case 3:
-+                                      value = SPI_read(0,0x07);
-+                                      value &= 0xC3FF ;
-+                                      value |= PVID << 10 ;
-+                                      SPI_write(0x07,value);
-+                                      break;
-+                              case 4:
-+                                      value = SPI_read(0,0x08);
-+                                      value &= 0xC3FF ;
-+                                      value |= PVID << 10 ;
-+                                      SPI_write(0x08,value);
-+                                      break;
-+                              case 5:
-+                                      value = SPI_read(0,0x09);
-+                                      value &= 0xC3FF ;
-+                                      value |= PVID << 10 ;
-+                                      SPI_write(0x09,value);
-+                                      break;
-+                      }
-+#endif
-+#ifdef CONFIG_ADM_6999
-+                      value = SPI_read(0,(unsigned char)i+1);
-+                      value &= 0xC3FF ;
-+                      value |= PVID << 10 ;
-+                      SPI_write((unsigned char)i+1,value);
-+#endif
-+              }
-+              port_mask >>= 1;
-+      }
-+}
-+
-+
-+/************************************************
-+* SPI_get_PVID
-+* port -> which ports to VID
-+************************************************/
-+unsigned int SPI_Get_PVID(unsigned int port)
-+{
-+      unsigned int value=0;
-+
-+      if (port>=ADM6996_PORT_NO)
-+              return 0;
-+
-+      switch(port)
-+      {
-+              case 0:
-+                      value = SPI_read(0,0x01);       // read original value
-+                      value &= 0x3C00 ;               // get VID
-+                      value = value >> 10 ;           // Shift
-+                      break;
-+              case 1:
-+                      value = SPI_read(0,0x03);
-+                      value &= 0x3C00 ;
-+                      value = value >> 10 ;
-+                      break;
-+              case 2:
-+                      value = SPI_read(0,0x05);
-+                      value &= 0x3C00 ;
-+                      value = value >> 10 ;
-+                      break;
-+              case 3:
-+                      value = SPI_read(0,0x07);
-+                      value &= 0x3C00 ;
-+                      value = value >> 10 ;
-+                      break;
-+              case 4:
-+                      value = SPI_read(0,0x08);
-+                      value &= 0x3C00 ;
-+                      value = value >> 10 ;
-+                      break;
-+              case 5:
-+                      value = SPI_read(0,0x09);
-+                      value &= 0x3C00 ;
-+                      value = value >> 10 ;
-+                      break;
-+      }
-+      return value ;
-+}
-+
-+
-+/**********************************************
-+* SPI_mac_clone
-+* port -> the port which will lock or unlock
-+* lock -> 0/the port will be unlock
-+*       1/the port will be locked
-+**********************************************/
-+void SPI_mac_lock(unsigned int port, unsigned char lock)
-+{
-+      unsigned int i,value=0;
-+
-+      value = SPI_read(0,0x12);               // read original
-+
-+      for(i=0;i<ADM6996_PORT_NO;i++)
-+      {       if(lock)                                // lock port
-+              {
-+                      switch(port)
-+                      {
-+                              case 0: value|=0x0001;  break;  //port0:bit[0]
-+                              case 1: value|=0x0004;  break;  //port1:bit[2]
-+                              case 2: value|=0x0010;  break;  //port2:bit[4]
-+                              case 3: value|=0x0040;  break;  //port3:bit[6]
-+                              case 4: value|=0x0080;  break;  //port4:bit[7]
-+                              case 5: value|=0x0100;  break;  //port5:bit[8]
-+                      }
-+              }
-+              else
-+              {
-+                      switch(i)                       // unlock port
-+                      {
-+                              case 0: value&=0xFFFE;  break;
-+                              case 1: value&=0xFFFB;  break;
-+                              case 2: value&=0xFFEF;  break;
-+                              case 3: value&=0xFFBF;  break;
-+                              case 4: value&=0xFF7F;  break;
-+                              case 5: value&=0xFEFF;  break;
-+                      }
-+              }
-+      }
-+
-+      SPI_write(0x12,value);
-+}
-+
-+
-+/***************************************************
-+* SPI_learn_pause
-+* pause = 01-80-c2-00-00-01
-+* DA=distination address
-+* forward -> 0: if DA == pause then drop and stop mac learning
-+*          1: if DA == pause ,then forward it
-+***************************************************/
-+void SPI_pause_cmd_forward(unsigned char forward)
-+{
-+      unsigned int value=0;
-+
-+      value = SPI_read(0,0x2C);               // read original setting
-+      if(forward)
-+              value |= 0x2000;                // set bit[13] '1'
-+      else
-+              value &= 0xDFFF;                // set bit[13] '0'
-+
-+      SPI_write(0x2C,value);
-+
-+}
-+
-+
-+/************************************************
-+* SPI_read
-+* table -> which table to be read: 1/count  0/EEPROM
-+* addr  -> Address to be read
-+* return : Value of the register
-+*************************************************/
-+unsigned int SPI_read(unsigned char table,unsigned char addr)
-+{
-+      int i ;
-+      unsigned int value=0;
-+      unsigned int bit;
-+#ifdef CONFIG_IT8712_GPIO
-+      unsigned char status;
-+#else
-+    unsigned int ad1;
-+#endif
-+
-+#ifdef CONFIG_IT8712_GPIO
-+      status = inb_gpio(LPC_GPIO_SET);
-+      status &= ~(ADM_EDIO) ;         //EDIO low
-+      outb_gpio(LPC_GPIO_SET, status);
-+#else
-+      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+      writel(GPIO_MISO,ad1); /* set MISO to 0 */
-+#endif
-+
-+      SPI_CS_enable(0);
-+
-+      SPI_pre_st(); // PRE+ST
-+      SPI_write_bit(1); // OPCODE '10' for read
-+      SPI_write_bit(0);
-+
-+      (table==1) ? SPI_write_bit(1) : SPI_write_bit(0) ;      // table select
-+
-+      SPI_write_bit(0);               // Device Address
-+      SPI_write_bit(0);
-+
-+
-+      // send 7 bits address to be read
-+      for (i=6;i>=0;i--) {
-+              bit= ((addr>>i) & 0x01) ? 1 :0 ;
-+              SPI_write_bit(bit);
-+      }
-+
-+
-+      // turn around
-+      SPI_read_bit(); // TA_Z
-+
-+      value=0;
-+      for (i=31;i>=0;i--) { // READ DATA
-+              bit=SPI_read_bit();
-+              value |= bit << i ;
-+      }
-+
-+      SPI_read_bit(); // dumy clock
-+      SPI_read_bit(); // dumy clock
-+
-+      if(!table)                                      // EEPROM, only fetch 16 bits data
-+      {
-+          if(addr&0x01)                               // odd number content (register,register-1)
-+                  value >>= 16 ;                      // so we remove the rear 16bits
-+          else                                        // even number content (register+1,register),
-+                  value &= 0x0000FFFF ;               // so we keep the rear 16 bits
-+      }
-+
-+
-+      SPI_CS_enable(0);
-+
-+#ifdef CONFIG_IT8712_GPIO
-+      status = inb_gpio(LPC_GPIO_SET);
-+      status &= ~(ADM_EDIO) ;         //EDIO low
-+      outb_gpio(LPC_GPIO_SET, status);
-+#else
-+      ad1 = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+      writel(GPIO_MISO,ad1); /* set MISO to 0 */
-+#endif
-+
-+      return(value);
-+
-+}
-+
-+
-+
-+/**************************************************
-+* SPI_port_en
-+* port -> Number of port to config
-+* enable -> 1/ enable this port
-+*         0/ disable this port
-+**************************************************/
-+void SPI_port_enable(unsigned int port,unsigned char enable)
-+{
-+      unsigned int reg_val ;
-+      unsigned char reg_add ;
-+
-+      if(port<=3)
-+              reg_add=2*port+1;
-+      else if(port==4) reg_add = 8 ;
-+      else reg_add = 9 ;
-+
-+      reg_val = SPI_read(0,reg_add);
-+      if(enable)
-+      {
-+              reg_val &= 0xFFDF ;
-+              SPI_write(reg_add,reg_val);
-+      }
-+      else
-+      {
-+              reg_val |= 0x0020 ;
-+              SPI_write(reg_add,reg_val);
-+      }
-+}
-+
-+/********************************************************
-+* get port status
-+* port -> specify the port number to get configuration
-+*********************************************************/
-+void SPI_get_status(unsigned int port)
-+{
-+/*    unsigned int reg_val,add_offset[6];
-+      struct PORT_STATUS *status;
-+      status = &port_state[port];
-+
-+      if(port>(ADM6996_PORT_NO-1))
-+              return ;
-+
-+      // Link estabilish , speed, deplex, flow control ?
-+      if(port < 5 )
-+      {
-+              reg_val = SPI_read(1, 1) ;
-+              if(port < 4)
-+                      reg_val >>= port*8 ;
-+              else
-+                      reg_val >>=28 ;
-+              status->link = reg_val & 0x00000001 ;
-+              status->speed = reg_val  & 0x00000002 ;
-+              status->duplex = reg_val & 0x00000004 ;
-+              status->flow_ctl = reg_val & 0x00000008 ;
-+      }
-+      else if(port ==5 )
-+      {
-+              reg_val = SPI_read(1, 2) ;
-+              status->link = reg_val & 0x00000001 ;
-+              status->speed = reg_val  & 0x00000002 ;
-+              status->duplex = reg_val & 0x00000008 ;
-+              status->flow_ctl = reg_val & 0x00000010 ;
-+      }
-+
-+      //   Mac Lock ?
-+      reg_val = SPI_read(0,0x12);
-+      switch(port)
-+      {
-+              case 0: status->mac_lock = reg_val & 0x00000001;
-+              case 1: status->mac_lock = reg_val & 0x00000004;
-+              case 2: status->mac_lock = reg_val & 0x00000010;
-+              case 3: status->mac_lock = reg_val & 0x00000040;
-+              case 4: status->mac_lock = reg_val & 0x00000080;
-+              case 5: status->mac_lock = reg_val & 0x00000100;
-+      }
-+
-+      // port enable ?
-+      add_offset[0] = 0x01 ;          add_offset[1] = 0x03 ;
-+      add_offset[2] = 0x05 ;          add_offset[3] = 0x07 ;
-+      add_offset[4] = 0x08 ;          add_offset[5] = 0x09 ;
-+      reg_val = SPI_read(0,add_offset[port]);
-+      status->port_disable = reg_val & 0x0020;
-+
-+
-+      //  Packet Count ...
-+      add_offset[0] = 0x04 ;          add_offset[1] = 0x06 ;
-+      add_offset[2] = 0x08 ;          add_offset[3] = 0x0a ;
-+      add_offset[4] = 0x0b ;          add_offset[5] = 0x0c ;
-+
-+      reg_val = SPI_read(1,add_offset[port]);
-+      status->rx_pac_count = reg_val ;
-+      reg_val = SPI_read(1,add_offset[port]+9);
-+      status->rx_pac_byte = reg_val ;
-+      reg_val = SPI_read(1,add_offset[port]+18);
-+      status->tx_pac_count = reg_val ;
-+      reg_val = SPI_read(1,add_offset[port]+27);
-+      status->tx_pac_byte = reg_val ;
-+      reg_val = SPI_read(1,add_offset[port]+36);
-+      status->collision_count = reg_val ;
-+      reg_val = SPI_read(1,add_offset[port]+45);
-+      status->error_count = reg_val ;
-+      reg_val = SPI_read(1, 0x3A);
-+      switch(port)
-+      {
-+              case 0: status->rx_pac_count_overflow = reg_val & 0x00000001;
-+                      status->rx_pac_byte_overflow = reg_val & 0x00000200 ;
-+              case 1: status->rx_pac_count_overflow = reg_val & 0x00000004;
-+                      status->rx_pac_byte_overflow = reg_val & 0x00000800 ;
-+              case 2: status->rx_pac_count_overflow = reg_val & 0x00000010;
-+                      status->rx_pac_byte_overflow = reg_val & 0x00002000 ;
-+              case 3: status->rx_pac_count_overflow = reg_val & 0x00000040;;
-+                      status->rx_pac_byte_overflow = reg_val & 0x00008000 ;
-+              case 4: status->rx_pac_count_overflow = reg_val & 0x00000080;
-+                      status->rx_pac_byte_overflow = reg_val & 0x00010000 ;
-+              case 5: status->rx_pac_count_overflow = reg_val & 0x00000100;
-+                      status->rx_pac_byte_overflow = reg_val & 0x00020000 ;
-+      }
-+
-+      reg_val = SPI_read(1, 0x3B);
-+      switch(port)
-+      {
-+              case 0: status->tx_pac_count_overflow = reg_val & 0x00000001;
-+                      status->tx_pac_byte_overflow  = reg_val & 0x00000200 ;
-+              case 1: status->tx_pac_count_overflow  = reg_val & 0x00000004;
-+                      status->tx_pac_byte_overflow  = reg_val & 0x00000800 ;
-+              case 2: status->tx_pac_count_overflow  = reg_val & 0x00000010;
-+                      status->tx_pac_byte_overflow  = reg_val & 0x00002000 ;
-+              case 3: status->tx_pac_count_overflow  = reg_val & 0x00000040;;
-+                      status->tx_pac_byte_overflow  = reg_val & 0x00008000 ;
-+              case 4: status->tx_pac_count_overflow  = reg_val & 0x00000080;
-+                      status->tx_pac_byte_overflow  = reg_val & 0x00010000 ;
-+              case 5: status->tx_pac_count_overflow  = reg_val & 0x00000100;
-+                      status->tx_pac_byte_overflow  = reg_val & 0x00020000 ;
-+      }
-+*/
-+
-+      unsigned int reg_val;
-+      struct PORT_STATUS *status;
-+      status = &port_state[port];
-+
-+      if(port>=ADM6999_PORT_NO)
-+              return ;
-+
-+      // Link estabilish , speed, deplex, flow control ?
-+      if(port < ADM6999_PORT_NO-1 )
-+      {
-+              reg_val = SPI_read(1, 0x01) ;
-+              reg_val = reg_val >> port*4 ;
-+              status->link = reg_val & 0x00000001 ;
-+              status->speed = reg_val  & 0x00000002 ;
-+              status->duplex = reg_val & 0x00000004 ;
-+              status->flow_ctl = reg_val & 0x00000008 ;
-+      }
-+      else if(port == (ADM6999_PORT_NO-1) )
-+      {
-+              reg_val = SPI_read(1, 0x02) ;
-+              status->link = reg_val & 0x00000001 ;
-+              status->speed = reg_val  & 0x00000002 ;
-+              status->duplex = reg_val & 0x00000008 ;
-+              status->flow_ctl = reg_val & 0x00000010 ;
-+      }
-+
-+      // Mac Lock ?
-+      reg_val = SPI_read(0,0x12);
-+      reg_val = reg_val >> port ;
-+      reg_val = reg_val & 0x01 ;
-+      status->mac_lock = reg_val ? 0x01:0x00 ;
-+
-+      // port enable ?
-+      reg_val = SPI_read(0,(unsigned char)port+1);
-+      status->port_disable = reg_val & 0x0020;
-+
-+      //  Packet Count ...
-+      reg_val = SPI_read(1,(unsigned char)port+0x04);
-+      status->rx_pac_count = reg_val ;
-+      reg_val = SPI_read(1,(unsigned char)port+0x0D);
-+      status->rx_pac_byte = reg_val ;
-+      reg_val = SPI_read(1,(unsigned char)port+0x16);
-+      status->tx_pac_count = reg_val ;
-+      reg_val = SPI_read(1,(unsigned char)port+0x1F);
-+      status->tx_pac_byte = reg_val ;
-+      reg_val = SPI_read(1,(unsigned char)port+0x28);
-+      status->collision_count = reg_val ;
-+      reg_val = SPI_read(1,(unsigned char)port+0x31);
-+      status->error_count = reg_val ;
-+      reg_val = SPI_read(1, 0x3A);
-+      reg_val = reg_val >> port ;
-+      status->rx_pac_count_overflow = reg_val & 0x00000001;
-+      reg_val = reg_val >> 0x09 ;
-+      status->rx_pac_byte_overflow = reg_val & 0x00000001 ;
-+
-+      reg_val = SPI_read(1, 0x3B);
-+      reg_val = reg_val >> port ;
-+      status->tx_pac_count_overflow = reg_val & 0x00000001;
-+      reg_val = reg_val >> 0x09 ;
-+      status->tx_pac_byte_overflow  = reg_val & 0x00000001 ;
-+
-+      reg_val = SPI_read(1, 0x3C);
-+      reg_val = reg_val >> port ;
-+      status->collision_count_overflow = reg_val & 0x00000001;
-+      reg_val = reg_val >> 0x09 ;
-+      status->error_count_overflow  = reg_val & 0x00000001 ;
-+
-+}
-+
-+unsigned int SPI_get_identifier(void)
-+{
-+      unsigned int flag=0;
-+
-+#ifdef CONFIG_IT8712_GPIO
-+
-+      if (!it8712_exist) {
-+              return -ENODEV;
-+      }
-+      printk("it8712_gpio init\n");
-+
-+      /* initialize registers */
-+      // switch all multi-function pins to GPIO
-+      LPCSetConfig(LDN_GPIO, 0x28, 0xff);
-+
-+      // set simple I/O base address
-+      LPCSetConfig(LDN_GPIO, 0x62, IT8712_GPIO_BASE >> 8);
-+      LPCSetConfig(LDN_GPIO, 0x63, (unsigned char) IT8712_GPIO_BASE >> 8);
-+
-+      // select GPIO to simple I/O
-+      LPCSetConfig(LDN_GPIO, 0xc3, 0xff);
-+
-+      // enable internal pull-up
-+      LPCSetConfig(LDN_GPIO, 0xbb, 0xff);
-+
-+#endif
-+
-+      flag = SPI_read(1,0x00);
-+      printk("Get ADM identifier %6x\n",flag);
-+      if ((flag & 0xFFFF0) == 0x21120) {
-+              printk("ADM699X Found\n");
-+              return 1;
-+      }
-+      else {
-+              printk("ADM699X not Found\n");
-+              return 0;
-+      }
-+}
-+
---- /dev/null
-+++ b/drivers/net/sl351x_crc16.c
-@@ -0,0 +1,93 @@
-+/****************************************************************************
-+* Name                        : sl351x_crc16.c
-+* Description :
-+*             Implement CRC16
-+*             refer to RFC1662
-+* History
-+*
-+*     Date            Writer          Description
-+*     -----------     -----------     -------------------------------------------------
-+*     09/14/2005      Gary Chen       Create
-+*
-+****************************************************************************/
-+
-+#define INITFCS16             0xffff  /* Initial FCS value */
-+#define GOODFCS16             0xf0b8  /* Good final FCS value */
-+#define SWAP_WORD(x)  (unsigned short)((((unsigned short)x & 0x00FF) << 8) |  \
-+                                                                               (((unsigned short)x & 0xFF00) >> 8))
-+
-+/*----------------------------------------------------------------------
-+*     x**0 + x**5 + x**12 + x**16
-+*----------------------------------------------------------------------*/
-+static const unsigned short crc16_tbl[256] = {
-+      0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
-+      0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
-+      0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
-+      0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
-+      0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
-+      0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
-+      0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
-+      0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
-+      0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
-+      0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
-+      0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
-+      0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
-+      0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
-+      0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
-+      0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
-+      0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
-+      0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
-+      0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
-+      0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
-+      0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
-+      0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
-+      0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
-+      0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
-+      0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
-+      0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
-+      0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
-+      0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
-+      0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
-+      0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
-+      0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
-+      0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
-+      0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-+};
-+
-+/*----------------------------------------------------------------------
-+* hash_crc16
-+*----------------------------------------------------------------------*/
-+unsigned short hash_crc16(unsigned short crc, unsigned char *datap, unsigned long len)
-+{
-+    while (len--)
-+    {
-+        crc = (crc >> 8) ^ crc16_tbl[(crc ^ (*datap++)) & 0xff];
-+    }
-+
-+    return (crc);
-+
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_check_crc16
-+*----------------------------------------------------------------------*/
-+unsigned long hash_check_crc16(unsigned char *datap, unsigned long len)
-+{
-+    unsigned short crc;
-+
-+    crc = hash_crc16(INITFCS16, datap, len );
-+    return (crc == GOODFCS16) ?  0 : 1;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_gen_crc16
-+*----------------------------------------------------------------------*/
-+unsigned short hash_gen_crc16(unsigned char *datap, unsigned long len)
-+{
-+    unsigned short crc;
-+
-+    crc = hash_crc16(INITFCS16, datap, len);
-+    crc ^= 0xffff;
-+
-+    return(SWAP_WORD(crc));
-+}
---- /dev/null
-+++ b/drivers/net/sl351x_gmac.c
-@@ -0,0 +1,5622 @@
-+/**************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
-+*--------------------------------------------------------------------------
-+* Name                        : sl351x_gmac.c
-+* Description :
-+*             Ethernet device driver for Storlink SL351x FPGA
-+*
-+* History
-+*
-+*     Date            Writer          Description
-+*     -----------     -----------     -------------------------------------------------
-+*     08/22/2005      Gary Chen       Create and implement
-+*   27/10/2005  CH Hsu      Porting to Linux
-+*
-+****************************************************************************/
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/mm.h>
-+#include <linux/compiler.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/delay.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/completion.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/semaphore.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/arch/it8712.h>
-+#include <linux/mtd/kvctl.h>
-+#include <linux/skbuff.h>
-+#include <linux/in.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <linux/udp.h>
-+
-+#include <linux/mtd/kvctl.h>
-+
-+#define        MIDWAY
-+#define        SL_LEPUS
-+#define VITESSE_G5SWITCH      1
-+
-+#ifndef CONFIG_SL351x_RXTOE
-+//#define CONFIG_SL351x_RXTOE 1
-+#endif
-+#undef CONFIG_SL351x_RXTOE
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/sl351x_gmac.h>
-+#include <asm/arch/sl351x_hash_cfg.h>
-+#include <asm/arch/sl351x_nat_cfg.h>
-+
-+#ifdef CONFIG_SL351x_SYSCTL
-+#include <linux/sysctl_storlink.h>
-+#endif
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+#include <asm/arch/sl351x_toe.h>
-+#include <net/tcp.h>
-+#include <linux/tcp.h>
-+#include <linux/ip.h>
-+#endif
-+
-+// #define SL351x_TEST_WORKAROUND
-+#ifdef CONFIG_SL351x_NAT
-+#define CONFIG_SL_NAPI                                        1
-+#endif
-+#define GMAX_TX_INTR_DISABLED                 1
-+#define DO_HW_CHKSUM                                  1
-+#define ENABLE_TSO                                            1
-+#define GMAC_USE_TXQ0                                 1
-+// #define NAT_WORKAROUND_BY_RESET_GMAC       1
-+// #define HW_RXBUF_BY_KMALLOC                        1
-+//#define _DUMP_TX_TCP_CONTENT        1
-+#define       br_if_ioctl                                             1
-+#define GMAC_LEN_1_2_ISSUE                            1
-+
-+#define GMAC_EXISTED_FLAG                     0x5566abcd
-+#define CONFIG_MAC_NUM                                GMAC_NUM
-+#define GMAC0_BASE                                    TOE_GMAC0_BASE
-+#define GMAC1_BASE                                    TOE_GMAC1_BASE
-+#define PAUSE_SET_HW_FREEQ                    (TOE_HW_FREEQ_DESC_NUM / 2)
-+#define PAUSE_REL_HW_FREEQ                    ((TOE_HW_FREEQ_DESC_NUM / 2) + 10)
-+#define DEFAULT_RXQ_MAX_CNT                   256
-+#ifdef        L2_jumbo_frame
-+#define TCPHDRLEN(tcp_hdr)  ((ntohs(*((__u16 *)tcp_hdr + 6)) >> 12) & 0x000F)
-+#endif
-+
-+/* define chip information */
-+#define DRV_NAME                                      "SL351x"
-+#define DRV_VERSION                                   "0.1.4"
-+#define SL351x_DRIVER_NAME            DRV_NAME " Giga Ethernet driver " DRV_VERSION
-+
-+#define toe_gmac_enable_interrupt(irq)        enable_irq(irq)
-+#define toe_gmac_disable_interrupt(irq)       disable_irq(irq)
-+
-+#ifdef SL351x_GMAC_WORKAROUND
-+#define GMAC_SHORT_FRAME_THRESHOLD            10
-+static struct timer_list gmac_workround_timer_obj;
-+void sl351x_poll_gmac_hanged_status(u32 data);
-+#ifdef CONFIG_SL351x_NAT
-+//#define IxscriptMate_1518                           1
-+      void sl351x_nat_workaround_init(void);
-+      #ifndef NAT_WORKAROUND_BY_RESET_GMAC
-+              static void sl351x_nat_workaround_handler(void);
-+      #endif
-+#endif
-+#endif
-+
-+#ifdef GMAC_LEN_1_2_ISSUE
-+      #define _DEBUG_PREFETCH_NUM     256
-+static        int     _debug_prefetch_cnt;
-+static        char _debug_prefetch_buf[_DEBUG_PREFETCH_NUM][4] __attribute__((aligned(4)));
-+#endif
-+/*************************************************************
-+ *         Global Variable
-+ *************************************************************/
-+static int    gmac_initialized = 0;
-+TOE_INFO_T toe_private_data;
-+//static int          do_again = 0;
-+spinlock_t gmac_fq_lock;
-+unsigned int FLAG_SWITCH;
-+
-+static unsigned int           next_tick = 3 * HZ;
-+static unsigned char          eth_mac[CONFIG_MAC_NUM][6]= {{0x00,0x11,0x11,0x87,0x87,0x87}, {0x00,0x22,0x22,0xab,0xab,0xab}};
-+
-+#undef CONFIG_SL351x_RXTOE
-+extern NAT_CFG_T nat_cfg;
-+
-+/************************************************/
-+/*                 function declare             */
-+/************************************************/
-+static int gmac_set_mac_address(struct net_device *dev, void *addr);
-+static unsigned int gmac_get_phy_vendor(int phy_addr);
-+static void gmac_set_phy_status(struct net_device *dev);
-+void gmac_get_phy_status(struct net_device *dev);
-+static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-+static void gmac_tx_timeout(struct net_device *dev);
-+static int gmac_phy_thread (void *data);
-+struct net_device_stats * gmac_get_stats(struct net_device *dev);
-+static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev);
-+static void gmac_set_rx_mode(struct net_device *dev);
-+static irqreturn_t toe_gmac_interrupt (int irq, void *dev_instance);
-+static void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp);
-+unsigned int mii_read(unsigned char phyad,unsigned char regad);
-+void mii_write(unsigned char phyad,unsigned char regad,unsigned int value);
-+void mac_init_drv(void);
-+
-+static void toe_init_free_queue(void);
-+static void toe_init_swtx_queue(void);
-+static void toe_init_default_queue(void);
-+#ifdef CONFIG_SL351x_RXTOE
-+static void toe_init_interrupt_queue(void);
-+#endif
-+static void toe_init_interrupt_config(void);
-+static void toe_gmac_sw_reset(void);
-+static int toe_gmac_init_chip(struct net_device *dev);
-+static void toe_gmac_enable_tx_rx(struct net_device* dev);
-+static void toe_gmac_disable_tx_rx(struct net_device *dev);
-+static void toe_gmac_hw_start(struct net_device *dev);
-+static void toe_gmac_hw_stop(struct net_device *dev);
-+static int toe_gmac_clear_counter(struct net_device *dev);
-+static void toe_init_gmac(struct net_device *dev);
-+static  void toe_gmac_tx_complete(GMAC_INFO_T *tp, unsigned int tx_qid, struct net_device *dev, int interrupt);
-+#ifdef CONFIG_SL_NAPI
-+static int gmac_rx_poll(struct net_device *dev, int *budget);
-+// static void toe_gmac_disable_rx(struct net_device *dev);
-+// static void toe_gmac_enable_rx(struct net_device *dev);
-+#endif
-+
-+u32 mac_read_dma_reg(int mac, unsigned int offset);
-+void mac_write_dma_reg(int mac, unsigned int offset, u32 data);
-+void mac_stop_txdma(struct net_device *dev);
-+void mac_get_sw_tx_weight(struct net_device *dev, char *weight);
-+void mac_set_sw_tx_weight(struct net_device *dev, char *weight);
-+void mac_get_hw_tx_weight(struct net_device *dev, char *weight);
-+void mac_set_hw_tx_weight(struct net_device *dev, char *weight);
-+static inline void toe_gmac_fill_free_q(void);
-+
-+#ifdef VITESSE_G5SWITCH
-+extern int Get_Set_port_status(void);
-+extern int SPI_default(void);
-+extern unsigned int SPI_get_identifier(void);
-+void gmac_get_switch_status(struct net_device *dev);
-+unsigned int Giga_switch=0;
-+unsigned int switch_port_no=0;
-+unsigned int ever_dwon=0;
-+#endif
-+
-+/************************************************/
-+/*            GMAC function declare             */
-+/************************************************/
-+static int gmac_open (struct net_device *dev);
-+static int gmac_close (struct net_device *dev);
-+static void gmac_cleanup_module(void);
-+static void gmac_get_mac_address(void);
-+
-+#ifdef CONFIG_SL351x_NAT
-+static void toe_init_hwtx_queue(void);
-+extern void sl351x_nat_init(void);
-+extern void sl351x_nat_input(struct sk_buff *skb, int port, void *l3off, void *l4off);
-+extern int sl351x_nat_output(struct sk_buff *skb, int port);
-+extern int sl351x_nat_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-+#endif
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+extern void set_toeq_hdr(struct toe_conn* connection, TOE_INFO_T* toe, struct net_device *dev);
-+extern void sl351x_toe_init(void);
-+extern void toe_gmac_handle_toeq(struct net_device *dev, GMAC_INFO_T* tp, __u32 status);
-+extern struct toe_conn* init_toeq(int ipver, void* iph, struct tcphdr* tcp_hdr, TOE_INFO_T* toe, unsigned char* l2hdr);
-+#endif
-+
-+int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2);
-+void mac_set_rule_enable_bit(int mac, int rule, int data);
-+int mac_set_rule_action(int mac, int rule, int data);
-+int mac_get_MRxCRx(int mac, int rule, int ctrlreg);
-+void mac_set_MRxCRx(int mac, int rule, int ctrlreg, u32 data);
-+
-+/*----------------------------------------------------------------------
-+*     Ethernet Driver init
-+*----------------------------------------------------------------------*/
-+
-+static int __init gmac_init_module(void)
-+{
-+      GMAC_INFO_T             *tp;
-+      struct net_device       *dev;
-+      int             i,j;
-+      unsigned int    chip_id;
-+//    unsigned int chip_version;
-+
-+#ifdef CONFIG_SL3516_ASIC
-+{
-+    unsigned int    val;
-+    /* set GMAC global register */
-+    val = readl(GMAC_GLOBAL_BASE_ADDR+0x10);
-+    val = val | 0x005f0000;
-+    writel(val,GMAC_GLOBAL_BASE_ADDR+0x10);
-+//    writel(0xb737b737,GMAC_GLOBAL_BASE_ADDR+0x1c); //For Socket Board
-+    writel(0x77777777,GMAC_GLOBAL_BASE_ADDR+0x20);
-+//    writel(0xa737b747,GMAC_GLOBAL_BASE_ADDR+0x1c);//For Mounting Board
-+
-+      //debug_Aaron
-+    //writel(0xa7f0a7f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For Mounting Board
-+    writel(0xa7f0b7f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For Mounting Board
-+
-+    writel(0x77777777,GMAC_GLOBAL_BASE_ADDR+0x24);
-+      writel(0x09200030,GMAC_GLOBAL_BASE_ADDR+0x2C);
-+      val = readl(GMAC_GLOBAL_BASE_ADDR+0x04);
-+      if((val&(1<<20))==0){           // GMAC1 enable
-+              val = readl(GMAC_GLOBAL_BASE_ADDR+0x30);
-+              val = (val & 0xe7ffffff) | 0x08000000;
-+              writel(val,GMAC_GLOBAL_BASE_ADDR+0x30);
-+      }
-+}
-+#endif
-+
-+#ifdef VITESSE_G5SWITCH
-+      Giga_switch = SPI_get_identifier();
-+      if(Giga_switch)
-+              switch_port_no = SPI_default();
-+#endif
-+
-+      chip_id = readl(GMAC_GLOBAL_BASE_ADDR+0x0);
-+      if (chip_id == 0x3512C1)
-+      {
-+              writel(0x5787a5f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For 3512 Switch Board
-+              writel(0x55557777,GMAC_GLOBAL_BASE_ADDR+0x20);//For 3512 Switch Board
-+      }
-+//#endif
-+
-+      mac_init_drv();
-+
-+      printk (KERN_INFO SL351x_DRIVER_NAME " built at %s %s\n", __DATE__, __TIME__);
-+
-+//    init_waitqueue_entry(&wait, current);
-+
-+      // printk("GMAC Init......\n");
-+
-+      i = 0;
-+      for(j = 0; i<CONFIG_MAC_NUM; j++)
-+      {
-+              i=j;
-+              if(Giga_switch){                // if gswitch present, swap eth0/1
-+                      if(j==0)
-+                              i=1;
-+                      else if(j==1)
-+                              i=0;
-+              }
-+
-+              tp = (GMAC_INFO_T *)&toe_private_data.gmac[i];
-+              tp->dev = NULL;
-+              if (tp->existed != GMAC_EXISTED_FLAG) continue;
-+
-+              dev = alloc_etherdev(0);
-+              if (dev == NULL)
-+              {
-+                      printk (KERN_ERR "Can't allocate ethernet device #%d .\n",i);
-+                      return -ENOMEM;
-+              }
-+
-+              dev->priv=tp;
-+              tp->dev = dev;
-+
-+              SET_MODULE_OWNER(dev);
-+
-+              // spin_lock_init(&tp->lock);
-+              spin_lock_init(&gmac_fq_lock);
-+              dev->base_addr = tp->base_addr;
-+              dev->irq = tp->irq;
-+          dev->open = gmac_open;
-+          dev->stop = gmac_close;
-+              dev->hard_start_xmit = gmac_start_xmit;
-+              dev->get_stats = gmac_get_stats;
-+              dev->set_multicast_list = gmac_set_rx_mode;
-+              dev->set_mac_address = gmac_set_mac_address;
-+              dev->do_ioctl = gmac_netdev_ioctl;
-+              dev->tx_timeout = gmac_tx_timeout;
-+              dev->watchdog_timeo = GMAC_DEV_TX_TIMEOUT;
-+#ifdef        L2_jumbo_frame
-+              dev->mtu = 2018; //2002  ,2018
-+#endif
-+              if (tp->port_id == 0)
-+                      dev->tx_queue_len = TOE_GMAC0_SWTXQ_DESC_NUM;
-+              else
-+                      dev->tx_queue_len = TOE_GMAC1_SWTXQ_DESC_NUM;
-+
-+#ifdef DO_HW_CHKSUM
-+              dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
-+#ifdef ENABLE_TSO
-+              dev->features |= NETIF_F_TSO;
-+#endif
-+#endif
-+#ifdef CONFIG_SL_NAPI
-+        dev->poll = gmac_rx_poll;
-+        dev->weight = 64;
-+#endif
-+
-+              if (register_netdev(dev))
-+              {
-+                      gmac_cleanup_module();
-+                      return(-1);
-+              }
-+      }
-+
-+
-+//    FLAG_SWITCH = 0 ;
-+//    FLAG_SWITCH = SPI_get_identifier();
-+//    if(FLAG_SWITCH)
-+//    {
-+//            printk("Configure ADM699X...\n");
-+//            SPI_default();  //Add by jason for ADM699X configuration
-+//    }
-+      return (0);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     gmac_cleanup_module
-+*----------------------------------------------------------------------*/
-+
-+static void gmac_cleanup_module(void)
-+{
-+    int i;
-+
-+#ifdef SL351x_GMAC_WORKAROUND
-+      del_timer(&gmac_workround_timer_obj);
-+#endif
-+
-+    for (i=0;i<CONFIG_MAC_NUM;i++)
-+    {
-+      if (toe_private_data.gmac[i].dev)
-+      {
-+              unregister_netdev(toe_private_data.gmac[i].dev);
-+              toe_private_data.gmac[i].dev = NULL;
-+        }
-+    }
-+      return ;
-+}
-+
-+module_init(gmac_init_module);
-+module_exit(gmac_cleanup_module);
-+
-+
-+/*----------------------------------------------------------------------
-+*     gmac_read_reg
-+*----------------------------------------------------------------------*/
-+static inline unsigned int gmac_read_reg(unsigned int base, unsigned int offset)
-+//static unsigned int gmac_read_reg(unsigned int base, unsigned int offset)
-+{
-+    volatile unsigned int reg_val;
-+
-+    reg_val = readl(base + offset);
-+      return (reg_val);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     gmac_write_reg
-+*----------------------------------------------------------------------*/
-+static inline void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask)
-+//static void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask)
-+{
-+      volatile unsigned int reg_val;
-+    unsigned int *addr;
-+
-+      reg_val = ( gmac_read_reg(base, offset) & (~bit_mask) ) | (data & bit_mask);
-+      addr = (unsigned int *)(base + offset);
-+    writel(reg_val,addr);
-+      return;
-+}
-+
-+/*----------------------------------------------------------------------
-+*     mac_init_drv
-+*----------------------------------------------------------------------*/
-+void mac_init_drv(void)
-+{
-+      TOE_INFO_T                      *toe;
-+      int                                     i;
-+      QUEUE_THRESHOLD_T       threshold;
-+      u32                                     *destp;
-+      unsigned int            chip_id,chip_version;
-+
-+      chip_id = readl(GMAC_GLOBAL_BASE_ADDR+0x0);
-+      chip_version = chip_id & 0x1 ;
-+
-+      if (!gmac_initialized)
-+      {
-+              gmac_initialized = 1;
-+
-+              // clear non TOE Queue Header Area
-+              destp = (u32 *)TOE_NONTOE_QUE_HDR_BASE;
-+              for (; destp < (u32 *)NONTOE_Q_HDR_AREA_END; destp++)
-+                      *destp = 0x00;
-+
-+              // clear TOE Queue Header Area
-+              destp = (u32 *)TOE_TOE_QUE_HDR_BASE;
-+              for (; destp < (u32 *)TOE_Q_HDR_AREA_END; destp++)
-+                      *destp = 0x00;
-+
-+              // init private data
-+              toe = (TOE_INFO_T *)&toe_private_data;
-+              memset((void *)toe, 0, sizeof(TOE_INFO_T));
-+              toe->gmac[0].base_addr = GMAC0_BASE;
-+              toe->gmac[1].base_addr = GMAC1_BASE;
-+              toe->gmac[0].dma_base_addr = TOE_GMAC0_DMA_BASE;
-+              toe->gmac[1].dma_base_addr = TOE_GMAC1_DMA_BASE;
-+        toe->gmac[0].auto_nego_cfg = 1;
-+        toe->gmac[1].auto_nego_cfg = 1;
-+#ifdef CONFIG_SL3516_ASIC
-+        toe->gmac[0].speed_cfg = GMAC_SPEED_1000;
-+        toe->gmac[1].speed_cfg = GMAC_SPEED_1000;
-+#else
-+              toe->gmac[0].speed_cfg = GMAC_SPEED_100;
-+        toe->gmac[1].speed_cfg = GMAC_SPEED_100;
-+#endif
-+        toe->gmac[0].full_duplex_cfg = 1;
-+        toe->gmac[1].full_duplex_cfg = 1;
-+#ifdef CONFIG_SL3516_ASIC
-+        toe->gmac[0].phy_mode = GMAC_PHY_RGMII_1000;
-+        toe->gmac[1].phy_mode = GMAC_PHY_RGMII_1000;
-+#else
-+              toe->gmac[0].phy_mode = GMAC_PHY_RGMII_100;
-+        toe->gmac[1].phy_mode = GMAC_PHY_RGMII_100;
-+#endif
-+        toe->gmac[0].port_id = GMAC_PORT0;
-+        toe->gmac[1].port_id = GMAC_PORT1;
-+        toe->gmac[0].phy_addr = 0x1;
-+        toe->gmac[1].phy_addr = 2;
-+//      toe->gmac[0].irq = SL2312_INTERRUPT_GMAC0;
-+              toe->gmac[0].irq =1;
-+//      toe->gmac[1].irq = SL2312_INTERRUPT_GMAC1;
-+              toe->gmac[1].irq =2;
-+        toe->gmac[0].mac_addr1 = &eth_mac[0][0];
-+        toe->gmac[1].mac_addr1 = &eth_mac[1][0];
-+
-+              for (i=0; i<CONFIG_MAC_NUM; i++)
-+              {
-+                      unsigned int data, phy_vendor;
-+                      gmac_write_reg(toe->gmac[i].base_addr, GMAC_STA_ADD2, 0x55aa55aa, 0xffffffff);
-+                      data = gmac_read_reg(toe->gmac[i].base_addr, GMAC_STA_ADD2);
-+                      if (data == 0x55aa55aa)
-+                      {
-+#ifdef VITESSE_G5SWITCH
-+                              if(Giga_switch && (i==1)){
-+                                      toe->gmac[i].existed = GMAC_EXISTED_FLAG;
-+                                      break;
-+                              }
-+#endif
-+                              phy_vendor = gmac_get_phy_vendor(toe->gmac[i].phy_addr);
-+                              if (phy_vendor != 0 && phy_vendor != 0xffffffff)
-+                                      toe->gmac[i].existed = GMAC_EXISTED_FLAG;
-+                      }
-+              }
-+
-+              // Write GLOBAL_QUEUE_THRESHOLD_REG
-+              threshold.bits32 = 0;
-+              threshold.bits.swfq_empty = (TOE_SW_FREEQ_DESC_NUM > 256) ? 255 :
-+                                                      TOE_SW_FREEQ_DESC_NUM/2;
-+              threshold.bits.hwfq_empty = (TOE_HW_FREEQ_DESC_NUM > 256) ? 256/4 :
-+                                                      TOE_HW_FREEQ_DESC_NUM/4;
-+              threshold.bits.toe_class = (TOE_TOE_DESC_NUM > 256) ? 256/4 :
-+                                                      TOE_TOE_DESC_NUM/4;
-+              threshold.bits.intrq = (TOE_INTR_DESC_NUM > 256) ? 256/4 :
-+                                                      TOE_INTR_DESC_NUM/4;
-+              writel(threshold.bits32, TOE_GLOBAL_BASE + GLOBAL_QUEUE_THRESHOLD_REG);
-+
-+              FLAG_SWITCH = 0;
-+              toe_gmac_sw_reset();
-+              toe_init_free_queue();
-+              toe_init_swtx_queue();
-+#ifdef CONFIG_SL351x_NAT
-+              toe_init_hwtx_queue();
-+#endif
-+              toe_init_default_queue();
-+#ifdef CONFIG_SL351x_RXTOE
-+              toe_init_interrupt_queue();
-+#endif
-+              toe_init_interrupt_config();
-+
-+#if defined(CONFIG_SL351x_NAT) || defined(CONFIG_SL351x_RXTOE)
-+              sl351x_hash_init();
-+#else
-+      {
-+              volatile u32 *dp1, *dp2, dword;
-+
-+              dp1 = (volatile u32 *) TOE_V_BIT_BASE;
-+              dp2 = (volatile u32 *) TOE_A_BIT_BASE;
-+
-+              for (i=0; i<HASH_TOTAL_ENTRIES/32; i++)
-+              {
-+                      *dp1++ = 0;
-+                      dword = *dp2++; // read-clear
-+              }
-+      }
-+#endif
-+      }
-+
-+#ifdef SL351x_GMAC_WORKAROUND
-+#ifdef CONFIG_SL351x_NAT
-+      sl351x_nat_workaround_init();
-+#endif
-+      init_timer(&gmac_workround_timer_obj);
-+      if (chip_version == 1)
-+      {
-+              gmac_workround_timer_obj.expires = jiffies * 50;
-+      }
-+      else
-+      {
-+              gmac_workround_timer_obj.expires = jiffies + 2;
-+      }
-+      gmac_workround_timer_obj.data = (unsigned long)&gmac_workround_timer_obj;
-+      gmac_workround_timer_obj.function = (void *)&sl351x_poll_gmac_hanged_status;
-+      add_timer(&gmac_workround_timer_obj);
-+#endif
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_init_free_queue
-+*     (1) Initialize the Free Queue Descriptor Base Address & size
-+*             Register: TOE_GLOBAL_BASE + 0x0004
-+*     (2) Initialize DMA Read/Write pointer for
-+*             SW Free Queue and HW Free Queue
-+*     (3)     Initialize DMA Descriptors for
-+*             SW Free Queue and HW Free Queue,
-+*----------------------------------------------------------------------*/
-+static void toe_init_free_queue(void)
-+{
-+      int                             i;
-+      TOE_INFO_T                      *toe;
-+      DMA_RWPTR_T                     rwptr_reg;
-+//    unsigned int            rwptr_addr;
-+      unsigned int            desc_buf;
-+      GMAC_RXDESC_T           *sw_desc_ptr;
-+      struct sk_buff          *skb;
-+#ifdef CONFIG_SL351x_NAT
-+      GMAC_RXDESC_T           *desc_ptr;
-+      unsigned int            buf_ptr;
-+#endif
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      desc_buf = (unsigned int)DMA_MALLOC((TOE_SW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T)),
-+                                              (dma_addr_t *)&toe->sw_freeq_desc_base_dma) ;
-+      sw_desc_ptr = (GMAC_RXDESC_T *)desc_buf;
-+      if (!desc_buf)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return;
-+      }
-+      memset((void *)desc_buf, 0, TOE_SW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T));
-+
-+      // DMA Queue Base & Size
-+      writel((toe->sw_freeq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_SW_FREEQ_DESC_POWER,
-+                      TOE_GLOBAL_BASE + GLOBAL_SW_FREEQ_BASE_SIZE_REG);
-+
-+      // init descriptor base
-+      toe->swfq_desc_base = desc_buf;
-+
-+      // SW Free Queue Read/Write Pointer
-+      rwptr_reg.bits.wptr = TOE_SW_FREEQ_DESC_NUM - 1;
-+      rwptr_reg.bits.rptr = 0;
-+      toe->fq_rx_rwptr.bits32 = rwptr_reg.bits32;
-+      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+
-+      // SW Free Queue Descriptors
-+      for (i=0; i<TOE_SW_FREEQ_DESC_NUM; i++)
-+      {
-+              sw_desc_ptr->word0.bits.buffer_size = SW_RX_BUF_SIZE;
-+              sw_desc_ptr->word1.bits.sw_id = i;      // used to locate skb
-+              if ( (skb = dev_alloc_skb(SW_RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-+              {
-+                      printk("%s::skb buffer allocation fail !\n",__func__); while(1);
-+              }
-+              REG32(skb->data) = (unsigned int)skb;
-+              skb_reserve(skb, SKB_RESERVE_BYTES);
-+              // toe->rx_skb[i] = skb;
-+              sw_desc_ptr->word2.buf_adr = (unsigned int)__pa(skb->data);
-+//            consistent_sync((unsigned int)desc_ptr, sizeof(GMAC_RXDESC_T), PCI_DMA_TODEVICE);
-+              sw_desc_ptr++;
-+      }
-+
-+#ifdef CONFIG_SL351x_NAT
-+      if (sizeof(skb->cb) < 64)
-+      {
-+                      printk("==> %s:: sk structure is incorrect -->Change to cb[64] !\n",__func__); while(1);
-+      }
-+      // init hardware free queues
-+      desc_buf = (unsigned int)DMA_MALLOC((TOE_HW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T)),
-+                                              (dma_addr_t *)&toe->hw_freeq_desc_base_dma) ;
-+      desc_ptr = (GMAC_RXDESC_T *)desc_buf;
-+      if (!desc_buf)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return;
-+      }
-+      memset((void *)desc_buf, 0, TOE_HW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T));
-+
-+      // DMA Queue Base & Size
-+      writel((toe->hw_freeq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_HW_FREEQ_DESC_POWER,
-+                      TOE_GLOBAL_BASE + GLOBAL_HW_FREEQ_BASE_SIZE_REG);
-+
-+      // init descriptor base
-+      toe->hwfq_desc_base = desc_buf;
-+
-+      // HW Free Queue Read/Write Pointer
-+      rwptr_reg.bits.wptr = TOE_HW_FREEQ_DESC_NUM - 1;
-+      rwptr_reg.bits.rptr = 0;
-+      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
-+#ifndef HW_RXBUF_BY_KMALLOC
-+      buf_ptr = (unsigned int)DMA_MALLOC(TOE_HW_FREEQ_DESC_NUM * HW_RX_BUF_SIZE,
-+                                              (dma_addr_t *)&toe->hwfq_buf_base_dma);
-+#else
-+      buf_ptr = (unsigned int)kmalloc(TOE_HW_FREEQ_DESC_NUM * HW_RX_BUF_SIZE, GFP_KERNEL);
-+      toe->hwfq_buf_base_dma = __pa(buf_ptr);
-+#endif
-+      if (!buf_ptr)
-+      {
-+              printk("===> %s::Failed to allocate HW TxQ Buffers!\n",__func__);
-+              while(1);       // could not be happened, if happened, adjust the buffer descriptor number
-+              return;
-+      }
-+
-+      toe->hwfq_buf_base = buf_ptr;
-+      toe->hwfq_buf_end_dma = toe->hwfq_buf_base_dma + (TOE_HW_FREEQ_DESC_NUM * HW_RX_BUF_SIZE);
-+      buf_ptr = (unsigned int)toe->hwfq_buf_base_dma;
-+      for (i=0; i<TOE_HW_FREEQ_DESC_NUM; i++)
-+      {
-+              desc_ptr->word0.bits.buffer_size = HW_RX_BUF_SIZE;
-+              desc_ptr->word1.bits.sw_id = i;
-+              desc_ptr->word2.buf_adr = (unsigned int)buf_ptr;
-+//            consistent_sync((unsigned int)desc_ptr, sizeof(GMAC_RXDESC_T), PCI_DMA_TODEVICE);
-+              // consistent_sync((unsigned int)buf_ptr, HW_RX_BUF_SIZE, PCI_DMA_TODEVICE);
-+              desc_ptr++;
-+              buf_ptr += HW_RX_BUF_SIZE;
-+      }
-+#else
-+      // DMA Queue Base & Size
-+      writel((0) | TOE_SW_FREEQ_DESC_POWER,
-+                      TOE_GLOBAL_BASE + GLOBAL_HW_FREEQ_BASE_SIZE_REG);
-+      rwptr_reg.bits.wptr = TOE_HW_FREEQ_DESC_NUM - 1;
-+      rwptr_reg.bits.rptr = 0;
-+      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
-+
-+#endif
-+}
-+/*----------------------------------------------------------------------
-+*     toe_init_swtx_queue
-+*     (2) Initialize the GMAC 0/1 SW TXQ Queue Descriptor Base Address & sizeup
-+*             GMAC_SW_TX_QUEUE_BASE_REG(0x0050)
-+*     (2) Initialize DMA Read/Write pointer for
-+*             GMAC 0/1 SW TX Q0-5
-+*----------------------------------------------------------------------*/
-+static void toe_init_swtx_queue(void)
-+{
-+      int                             i;
-+      TOE_INFO_T                      *toe;
-+      DMA_RWPTR_T                     rwptr_reg;
-+      unsigned int            rwptr_addr;
-+      unsigned int            desc_buf;
-+
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+
-+      // GMAC-0, SW-TXQ
-+      // The GMAC-0 and GMAC-0 maybe have different descriptor number
-+      // so, not use for instruction
-+      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
-+                                              (dma_addr_t *)&toe->gmac[0].swtxq_desc_base_dma) ;
-+      toe->gmac[0].swtxq_desc_base = desc_buf;
-+      if (!desc_buf)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return  ;
-+      }
-+      memset((void *)desc_buf, 0,     TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
-+      writel((toe->gmac[0].swtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC0_SWTXQ_DESC_POWER,
-+                      TOE_GMAC0_DMA_BASE+ GMAC_SW_TX_QUEUE_BASE_REG);
-+
-+      // GMAC0 SW TX Q0-Q5
-+      rwptr_reg.bits.wptr = 0;
-+      rwptr_reg.bits.rptr = 0;
-+      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_SW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_SW_TXQ_NUM; i++)
-+      {
-+              toe->gmac[0].swtxq[i].rwptr_reg = rwptr_addr;
-+              toe->gmac[0].swtxq[i].desc_base = desc_buf;
-+              toe->gmac[0].swtxq[i].total_desc_num = TOE_GMAC0_SWTXQ_DESC_NUM;
-+              desc_buf += TOE_GMAC0_SWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
-+              writel(rwptr_reg.bits32, rwptr_addr);
-+              rwptr_addr+=4;
-+      }
-+
-+      // GMAC-1, SW-TXQ
-+      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC1_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
-+                                              (dma_addr_t *)&toe->gmac[1].swtxq_desc_base_dma) ;
-+      toe->gmac[1].swtxq_desc_base = desc_buf;
-+      if (!desc_buf)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return  ;
-+      }
-+      memset((void *)desc_buf, 0,     TOE_GMAC1_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
-+      writel((toe->gmac[1].swtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC1_SWTXQ_DESC_POWER,
-+                      TOE_GMAC1_DMA_BASE+ GMAC_SW_TX_QUEUE_BASE_REG);
-+
-+
-+      // GMAC1 SW TX Q0-Q5
-+      rwptr_reg.bits.wptr = 0;
-+      rwptr_reg.bits.rptr = 0;
-+      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_SW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_SW_TXQ_NUM; i++)
-+      {
-+              toe->gmac[1].swtxq[i].rwptr_reg = rwptr_addr;
-+              toe->gmac[1].swtxq[i].desc_base = desc_buf;
-+              toe->gmac[1].swtxq[i].total_desc_num = TOE_GMAC1_SWTXQ_DESC_NUM;
-+              desc_buf += TOE_GMAC1_SWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
-+              writel(rwptr_reg.bits32, rwptr_addr);
-+              rwptr_addr+=4;
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_init_hwtx_queue
-+*     (2) Initialize the GMAC 0/1 HW TXQ Queue Descriptor Base Address & size
-+*             GMAC_HW_TX_QUEUE_BASE_REG(0x0054)
-+*     (2) Initialize DMA Read/Write pointer for
-+*             GMAC 0/1 HW TX Q0-5
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static void toe_init_hwtx_queue(void)
-+{
-+      int                             i;
-+      TOE_INFO_T                      *toe;
-+      DMA_RWPTR_T                     rwptr_reg;
-+      unsigned int            rwptr_addr;
-+      unsigned int            desc_buf;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      // GMAC-0, HW-TXQ
-+      // The GMAC-0 and GMAC-0 maybe have different descriptor number
-+      // so, not use for instruction
-+      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC0_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
-+                                              (dma_addr_t *)&toe->gmac[0].hwtxq_desc_base_dma) ;
-+      toe->gmac[0].hwtxq_desc_base = desc_buf;
-+      if (!desc_buf)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return  ;
-+      }
-+      memset((void *)desc_buf, 0,     TOE_GMAC0_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
-+      writel((toe->gmac[0].hwtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC0_HWTXQ_DESC_POWER,
-+                      TOE_GMAC0_DMA_BASE+ GMAC_HW_TX_QUEUE_BASE_REG);
-+
-+      // GMAC0 HW TX Q0-Q5
-+      rwptr_reg.bits.wptr = 0;
-+      rwptr_reg.bits.rptr = 0;
-+      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              toe->gmac[0].hwtxq[i].desc_base = desc_buf;
-+              desc_buf += TOE_GMAC0_HWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
-+              writel(rwptr_reg.bits32, rwptr_addr);
-+              rwptr_addr+=4;
-+      }
-+
-+      // GMAC-1, HW-TXQ
-+      desc_buf = (unsigned int)DMA_MALLOC((TOE_GMAC1_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T)),
-+                                              (dma_addr_t *)&toe->gmac[1].hwtxq_desc_base_dma) ;
-+      toe->gmac[1].hwtxq_desc_base = desc_buf;
-+      if (!desc_buf)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return  ;
-+      }
-+      memset((void *)desc_buf, 0,     TOE_GMAC1_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T));
-+      writel((toe->gmac[1].hwtxq_desc_base_dma & DMA_Q_BASE_MASK) | TOE_GMAC1_HWTXQ_DESC_POWER,
-+                      TOE_GMAC1_DMA_BASE+ GMAC_HW_TX_QUEUE_BASE_REG);
-+
-+      // GMAC1 HW TX Q0-Q5
-+      rwptr_reg.bits.wptr = 0;
-+      rwptr_reg.bits.rptr = 0;
-+      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              toe->gmac[1].hwtxq[i].desc_base = desc_buf;
-+              desc_buf += TOE_GMAC1_HWTXQ_DESC_NUM * sizeof(GMAC_TXDESC_T);
-+              writel(rwptr_reg.bits32, rwptr_addr);
-+              rwptr_addr+=4;
-+      }
-+}
-+#endif
-+
-+/*----------------------------------------------------------------------
-+*     toe_init_default_queue
-+*     (1) Initialize the default 0/1 Queue Header
-+*             Register: TOE_DEFAULT_Q0_HDR_BASE (0x60002000)
-+*                               TOE_DEFAULT_Q1_HDR_BASE (0x60002008)
-+*     (2)     Initialize Descriptors of Default Queue 0/1
-+*----------------------------------------------------------------------*/
-+static void toe_init_default_queue(void)
-+{
-+      TOE_INFO_T                              *toe;
-+      volatile NONTOE_QHDR_T  *qhdr;
-+      GMAC_RXDESC_T                   *desc_ptr;
-+      DMA_SKB_SIZE_T                  skb_size;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T)),
-+                                                                                      (dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
-+      if (!desc_ptr)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return  ;
-+      }
-+      memset((void *)desc_ptr, 0, TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T));
-+      toe->gmac[0].default_desc_base = (unsigned int)desc_ptr;
-+      toe->gmac[0].default_desc_num = TOE_DEFAULT_Q0_DESC_NUM;
-+      qhdr = (volatile NONTOE_QHDR_T *)TOE_DEFAULT_Q0_HDR_BASE;
-+      qhdr->word0.base_size = ((unsigned int)toe->gmac[0].default_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_DEFAULT_Q0_DESC_POWER;
-+      qhdr->word1.bits32 = 0;
-+      toe->gmac[0].rx_rwptr.bits32 = 0;
-+      toe->gmac[0].default_qhdr = (NONTOE_QHDR_T *)qhdr;
-+      desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q1_DESC_NUM * sizeof(GMAC_RXDESC_T)),
-+                                                                                      (dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
-+      if (!desc_ptr)
-+      {
-+              printk("%s::DMA_MALLOC fail !\n",__func__);
-+              return  ;
-+      }
-+      memset((void *)desc_ptr, 0, TOE_DEFAULT_Q1_DESC_NUM * sizeof(GMAC_RXDESC_T));
-+      toe->gmac[1].default_desc_base = (unsigned int)desc_ptr;
-+      toe->gmac[1].default_desc_num = TOE_DEFAULT_Q1_DESC_NUM;
-+      qhdr = (volatile NONTOE_QHDR_T *)TOE_DEFAULT_Q1_HDR_BASE;
-+      qhdr->word0.base_size = ((unsigned int)toe->gmac[1].default_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_DEFAULT_Q1_DESC_POWER;
-+      qhdr->word1.bits32 = 0;
-+      toe->gmac[1].rx_rwptr.bits32 = 0;
-+      toe->gmac[1].default_qhdr = (NONTOE_QHDR_T *)qhdr;
-+
-+      skb_size.bits.hw_skb_size = HW_RX_BUF_SIZE;
-+      skb_size.bits.sw_skb_size = SW_RX_BUF_SIZE;
-+      writel(skb_size.bits32, TOE_GLOBAL_BASE + GLOBAL_DMA_SKB_SIZE_REG);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_init_interrupt_queue
-+*     (1) Initialize the Interrupt Queue Header
-+*             Register: TOE_INTR_Q_HDR_BASE (0x60002080)
-+*     (2)     Initialize Descriptors of Interrupt Queues
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_RXTOE
-+static void toe_init_interrupt_queue(void)
-+{
-+      TOE_INFO_T                              *toe;
-+      volatile NONTOE_QHDR_T  *qhdr;
-+      INTR_QHDR_T                             *desc_ptr;
-+      // unsigned int                 desc_buf_addr;
-+      int                                             i;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      desc_ptr = (INTR_QHDR_T *)DMA_MALLOC((TOE_INTR_QUEUE_NUM * TOE_INTR_DESC_NUM * sizeof(INTR_QHDR_T)),
-+                                                                                      (dma_addr_t *)&toe->intr_desc_base_dma);
-+      if (!desc_ptr)
-+      {
-+              printk("%s::DMA_MALLOC interrupt queue fail !\n",__func__);
-+              return  ;
-+      }
-+      /*
-+      desc_buf_addr = (unsigned int)DMA_MALLOC((TOE_INTR_DESC_NUM * sizeof(TOE_QHDR_T)),
-+                                                                                              (dma_addr_t *)&toe->intr_buf_base_dma);
-+      if (!desc_buf_addr)
-+      {
-+              printk("%s::DMA_MALLOC interrupt desc fail !\n",__func__);
-+              return  ;
-+      }*/
-+      printk("#### %s::Intr Q desc %x\n", __func__, (u32)desc_ptr);
-+
-+      memset((void *)desc_ptr, 0, TOE_INTR_QUEUE_NUM * TOE_INTR_DESC_NUM * sizeof(INTR_QHDR_T));
-+//    memset((void *)desc_buf_addr, 0, TOE_INTR_DESC_NUM * sizeof(TOE_QHDR_T));
-+      toe->intr_desc_base = (unsigned int)desc_ptr;
-+      toe->intr_desc_num = TOE_INTR_DESC_NUM;
-+
-+      qhdr = (volatile NONTOE_QHDR_T *)TOE_INTR_Q_HDR_BASE;
-+//    intrq = (INTRQ_INFO_T*) &toe->intrq[0];
-+      for (i=0; i<TOE_INTR_QUEUE_NUM; i++, qhdr++)
-+      {
-+              qhdr->word0.base_size = ((unsigned int)toe->intr_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_INTR_DESC_POWER;
-+              qhdr->word1.bits32 = 0;
-+              desc_ptr += TOE_INTR_DESC_NUM;
-+      }
-+}
-+
-+#endif
-+
-+/*----------------------------------------------------------------------
-+*     toe_init_interrupt_config
-+*     Interrupt Select Registers are used to map interrupt to int0 or int1
-+*     Int0 and int1 are wired to CPU 0/1 GMAC 0/1
-+*     Interrupt Device Inteface data are used to pass device info to
-+*             upper device deiver or store status/statistics
-+*     ISR handler
-+*             (1) If status bit ON but masked, the prinf error message (bug issue)
-+*             (2) If select bits are for me, handle it, else skip to let
-+*                     the other ISR handles it.
-+*  Notes:
-+*             GMACx init routine (for eCOS) or open routine (for Linux)
-+*       enable the interrupt bits only which are selected for him.
-+*
-+*     Default Setting:
-+*             GMAC0 intr bits ------> int0 ----> eth0
-+*             GMAC1 intr bits ------> int1 ----> eth1
-+*             TOE intr -------------> int0 ----> eth0
-+*             Classification Intr --> int0 ----> eth0
-+*             Default Q0 -----------> int0 ----> eth0
-+*             Default Q1 -----------> int1 ----> eth1
-+*----------------------------------------------------------------------*/
-+static void toe_init_interrupt_config(void)
-+{
-+      // clear all status bits
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+
-+      // Init select registers
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+
-+      // disable all interrupt
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_0_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_2_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_3_REG);
-+      writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_init_gmac
-+*----------------------------------------------------------------------*/
-+static void toe_init_gmac(struct net_device *dev)
-+{
-+      GMAC_INFO_T             *tp = dev->priv;
-+      TOE_INFO_T              *toe;
-+      u32                     data;
-+
-+      if (!gmac_initialized)
-+              return ;
-+
-+      if (!tp->existed)
-+              return;
-+
-+      tp->dev = dev;
-+      tp->flow_control_enable = 1;
-+      tp->pre_phy_status = LINK_DOWN;
-+      tp->full_duplex_status = tp->full_duplex_cfg;
-+      tp->speed_status = tp->speed_status;
-+
-+#if 0
-+   /* get mac address from FLASH */
-+    gmac_get_mac_address();
-+#endif
-+
-+    /* set PHY register to start autonegition process */
-+    gmac_set_phy_status(dev);
-+
-+      /* GMAC initialization */
-+      if ( toe_gmac_init_chip(dev) )
-+      {
-+              printk ("GMAC %d init fail\n", tp->port_id);
-+      }
-+
-+    /* clear statistic counter */
-+    toe_gmac_clear_counter(dev);
-+
-+      memset((void *)&tp->ifStatics, 0, sizeof(struct net_device_stats));
-+
-+      /* -----------------------------------------------------------
-+      Enable GMAC interrupt & disable loopback
-+      Notes:
-+              GMACx init routine (for eCOS) or open routine (for Linux)
-+              enable the interrupt bits only which are selected for him.
-+      --------------------------------------------------------------*/
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+
-+      // Enable Interrupt Bits
-+      if (tp->port_id == 0)
-+      {
-+              tp->intr0_selected =    GMAC0_TXDERR_INT_BIT     | GMAC0_TXPERR_INT_BIT         |
-+                                      GMAC0_RXDERR_INT_BIT     | GMAC0_RXPERR_INT_BIT         |
-+                                  GMAC0_SWTQ05_FIN_INT_BIT | GMAC0_SWTQ05_EOF_INT_BIT |
-+                                  GMAC0_SWTQ04_FIN_INT_BIT | GMAC0_SWTQ04_EOF_INT_BIT |
-+                                  GMAC0_SWTQ03_FIN_INT_BIT | GMAC0_SWTQ03_EOF_INT_BIT |
-+                                  GMAC0_SWTQ02_FIN_INT_BIT | GMAC0_SWTQ02_EOF_INT_BIT |
-+                                  GMAC0_SWTQ01_FIN_INT_BIT | GMAC0_SWTQ01_EOF_INT_BIT |
-+                                  GMAC0_SWTQ00_FIN_INT_BIT | GMAC0_SWTQ00_EOF_INT_BIT;
-+
-+#ifdef GMAX_TX_INTR_DISABLED
-+          tp->intr0_enabled =         0;
-+#else
-+          tp->intr0_enabled =         GMAC0_SWTQ00_FIN_INT_BIT | GMAC0_SWTQ00_EOF_INT_BIT;
-+#endif
-+
-+          tp->intr1_selected =        TOE_IQ_ALL_BITS                  | TOE_CLASS_RX_INT_BITS        |
-+                                                      GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT |
-+                                                      GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT |
-+                                                      DEFAULT_Q0_INT_BIT;
-+          tp->intr1_enabled =         DEFAULT_Q0_INT_BIT | TOE_IQ_ALL_BITS;
-+          tp->intr2_selected =        0xffffffff;      // TOE Queue 32-63 FUUL Intr
-+          tp->intr2_enabled =         0xffffffff;
-+          tp->intr3_selected =        0xffffffff;      // TOE Queue 0-31 FUUL Intr
-+          tp->intr3_enabled =         0xffffffff;
-+          tp->intr4_selected =        GMAC0_INT_BITS | CLASS_RX_FULL_INT_BITS |
-+                                                      HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
-+          tp->intr4_enabled =         GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT;
-+
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) & ~tp->intr0_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG) & ~tp->intr1_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG) & ~tp->intr2_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG) & ~tp->intr3_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG) & ~tp->intr4_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+      }
-+      else
-+      {
-+              tp->intr0_selected =    GMAC1_TXDERR_INT_BIT     | GMAC1_TXPERR_INT_BIT         |
-+                                      GMAC1_RXDERR_INT_BIT     | GMAC1_RXPERR_INT_BIT         |
-+                                  GMAC1_SWTQ15_FIN_INT_BIT | GMAC1_SWTQ15_EOF_INT_BIT |
-+                                  GMAC1_SWTQ14_FIN_INT_BIT | GMAC1_SWTQ14_EOF_INT_BIT |
-+                                  GMAC1_SWTQ13_FIN_INT_BIT | GMAC1_SWTQ13_EOF_INT_BIT |
-+                                  GMAC1_SWTQ12_FIN_INT_BIT | GMAC1_SWTQ12_EOF_INT_BIT |
-+                                  GMAC1_SWTQ11_FIN_INT_BIT | GMAC1_SWTQ11_EOF_INT_BIT |
-+                                  GMAC1_SWTQ10_FIN_INT_BIT | GMAC1_SWTQ10_EOF_INT_BIT;
-+#ifdef GMAX_TX_INTR_DISABLED
-+          tp->intr0_enabled =         0;
-+#else
-+          tp->intr0_enabled =         GMAC1_SWTQ10_FIN_INT_BIT | GMAC1_SWTQ10_EOF_INT_BIT;
-+#endif
-+
-+          tp->intr1_selected =        DEFAULT_Q1_INT_BIT;
-+          tp->intr1_enabled =         DEFAULT_Q1_INT_BIT | TOE_IQ_ALL_BITS;
-+          tp->intr2_selected =        0;       // TOE Queue 32-63 FUUL Intr
-+          tp->intr2_enabled =         0;
-+          tp->intr3_selected =        0;       // TOE Queue 0-31 FUUL Intr
-+          tp->intr3_enabled =         0;
-+          tp->intr4_selected =        GMAC1_INT_BITS;
-+          tp->intr4_enabled =         GMAC1_INT_BITS;
-+
-+          if (toe->gmac[0].existed != GMAC_EXISTED_FLAG)
-+          {
-+              tp->intr1_selected      |=      TOE_IQ_ALL_BITS | TOE_CLASS_RX_INT_BITS |
-+                                                              GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT |
-+                                                              GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT;
-+              tp->intr1_enabled       |=      TOE_IQ_ALL_BITS;
-+              tp->intr2_selected      |=      0xffffffff;      // TOE Queue 32-63 FUUL Intr
-+              tp->intr2_enabled       |=      0xffffffff;
-+              tp->intr3_selected      |=      0xffffffff;      // TOE Queue 0-31 FUUL Intr
-+              tp->intr3_enabled       |=      0xffffffff;
-+              tp->intr4_selected      |=      CLASS_RX_FULL_INT_BITS |
-+                                                              HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
-+              tp->intr4_enabled       |=      SWFQ_EMPTY_INT_BIT;
-+              }
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) | tp->intr0_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG) | tp->intr1_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG) | tp->intr2_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG) | tp->intr3_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
-+          data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG) | tp->intr4_selected;
-+          writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+      }
-+
-+      // enable only selected bits
-+      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_0_REG,
-+                                      tp->intr0_enabled, tp->intr0_selected);
-+      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_1_REG,
-+                                      tp->intr1_enabled, tp->intr1_selected);
-+      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_2_REG,
-+                                      tp->intr2_enabled, tp->intr2_selected);
-+      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_3_REG,
-+                                      tp->intr3_enabled, tp->intr3_selected);
-+      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
-+                                      tp->intr4_enabled, tp->intr4_selected);
-+
-+    /* start DMA process */
-+      toe_gmac_hw_start(dev);
-+
-+    /* enable tx/rx register */
-+    toe_gmac_enable_tx_rx(dev);
-+
-+//    toe_gmac_enable_interrupt(tp->irq);
-+
-+    return ;
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* toe_gmac_sw_reset
-+*----------------------------------------------------------------------*/
-+static void toe_gmac_sw_reset(void)
-+{
-+      unsigned int    reg_val;
-+      reg_val = readl(GMAC_GLOBAL_BASE_ADDR+GLOBAL_RESET_REG) | 0x00000060;   /* GMAC0 S/W reset */
-+    writel(reg_val,GMAC_GLOBAL_BASE_ADDR+GLOBAL_RESET_REG);
-+    udelay(100);
-+    return;
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_gmac_init_chip
-+*----------------------------------------------------------------------*/
-+static int toe_gmac_init_chip(struct net_device *dev)
-+{
-+      GMAC_INFO_T     *tp = dev->priv;
-+      GMAC_CONFIG2_T  config2_val;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+      GMAC_CONFIG1_T  config1;
-+      #ifdef CONFIG_SL351x_NAT
-+      GMAC_CONFIG3_T  config3_val;
-+      #endif
-+      GMAC_TX_WCR0_T  hw_weigh;
-+      GMAC_TX_WCR1_T  sw_weigh;
-+//    GMAC_HASH_ENABLE_REG0_T hash_ctrl;
-+//
-+#if 0 /* mac address will be set in late_initcall */
-+      struct sockaddr sock;
-+      // GMAC_AHB_WEIGHT_T    ahb_weight, ahb_weight_mask;
-+
-+
-+      /* set station MAC address1 and address2 */
-+      memcpy(&sock.sa_data[0],&eth_mac[tp->port_id][0],6);
-+      gmac_set_mac_address(dev,(void *)&sock);
-+#endif
-+
-+      /* set RX_FLTR register to receive all multicast packet */
-+      gmac_write_reg(tp->base_addr, GMAC_RX_FLTR, 0x00000007,0x0000001f);
-+      //    gmac_write_reg(tp->base_addr, GMAC_RX_FLTR, 0x00000007,0x0000001f);
-+      //gmac_write_reg(tp->base_addr, GMAC_RX_FLTR,0x00000007,0x0000001f);
-+
-+      /* set per packet buffer size */
-+      //      config1.bits32 = 0x002004;      //next version
-+      /* set flow control threshold */
-+      config1.bits32 = 0;
-+      config1.bits.set_threshold = 32 / 2;
-+      config1.bits.rel_threshold = 32 / 4 * 3;
-+      gmac_write_reg(tp->base_addr, GMAC_CONFIG1, config1.bits32, 0xffffffff);
-+
-+      /* set flow control threshold */
-+      config2_val.bits32 = 0;
-+      config2_val.bits.set_threshold = TOE_SW_FREEQ_DESC_NUM/2;
-+      config2_val.bits.rel_threshold = TOE_SW_FREEQ_DESC_NUM*3/4;
-+      gmac_write_reg(tp->base_addr, GMAC_CONFIG2, config2_val.bits32,0xffffffff);
-+
-+      #ifdef CONFIG_SL351x_NAT
-+      /* set HW free queue flow control threshold */
-+      config3_val.bits32 = 0;
-+      config3_val.bits.set_threshold = PAUSE_SET_HW_FREEQ;
-+      config3_val.bits.rel_threshold = PAUSE_REL_HW_FREEQ;
-+      gmac_write_reg(tp->base_addr, GMAC_CONFIG3, config3_val.bits32,0xffffffff);
-+      #endif
-+      /* set_mcast_filter mask*/
-+      //      gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL0,0x0,0xffffffff);
-+      //  gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL1,0x0,0xffffffff);
-+
-+      /* disable TX/RX and disable internal loop back */
-+      config0.bits32 = 0;
-+      config0_mask.bits32 = 0;
-+
-+      //debug_Aaron
-+#ifdef        L2_jumbo_frame
-+      config0.bits.max_len = 5;
-+#else
-+      config0.bits.max_len = 2;
-+#endif
-+
-+      if (tp->flow_control_enable==1)
-+      {
-+              config0.bits.tx_fc_en = 1; /* enable tx flow control */
-+              config0.bits.rx_fc_en = 1; /* enable rx flow control */
-+              printk("Enable MAC Flow Control...\n");
-+      }
-+      else
-+      {
-+              config0.bits.tx_fc_en = 0; /* disable tx flow control */
-+              config0.bits.rx_fc_en = 0; /* disable rx flow control */
-+              printk("Disable MAC Flow Control...\n");
-+      }
-+      config0.bits.dis_rx = 1;  /* disable rx */
-+      config0.bits.dis_tx = 1;  /* disable tx */
-+      config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
-+      config0.bits.rx_err_detect = 1;
-+      config0.bits.rgmii_en = 0;
-+      config0.bits.rgmm_edge = 1;
-+      config0.bits.rxc_inv = 0;
-+      config0.bits.ipv4_rx_chksum = 1;  /* enable H/W to check ip checksum */
-+      config0.bits.ipv6_rx_chksum = 1;  /* enable H/W to check ip checksum */
-+      config0.bits.port0_chk_hwq = 1; // GaryChen 3/24/2006 2:26PM
-+      config0.bits.port1_chk_hwq = 1; // GaryChen 3/24/2006 2:26PM
-+      config0.bits.port0_chk_toeq = 1;
-+      config0.bits.port1_chk_toeq = 1;
-+      config0.bits.port0_chk_classq = 1;
-+      config0.bits.port1_chk_classq = 1;
-+
-+      config0_mask.bits.max_len = 7;
-+      config0_mask.bits.tx_fc_en = 1;
-+      config0_mask.bits.rx_fc_en = 1;
-+      config0_mask.bits.dis_rx = 1;
-+      config0_mask.bits.dis_tx = 1;
-+      config0_mask.bits.loop_back = 1;
-+      config0_mask.bits.rgmii_en = 1;
-+      config0_mask.bits.rgmm_edge = 1;
-+      config0_mask.bits.rxc_inv = 1;
-+      config0_mask.bits.ipv4_rx_chksum = 1;
-+      config0_mask.bits.ipv6_rx_chksum = 1;
-+      config0_mask.bits.port0_chk_hwq = 1;
-+      config0_mask.bits.port1_chk_hwq = 1;
-+      config0_mask.bits.port0_chk_toeq = 1;
-+      config0_mask.bits.port1_chk_toeq = 1;
-+      config0_mask.bits.port0_chk_classq = 1;
-+      config0_mask.bits.port1_chk_classq = 1;
-+      config0_mask.bits.rx_err_detect = 1;
-+
-+      #if 0
-+      config0.bits.dis_rx = 1;  /* disable rx */
-+      config0.bits.dis_tx = 1;  /* disable tx */
-+      config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
-+      config0.bits.txc_inv = 0;
-+      config0.bits.rgmii_en = 0;
-+      config0.bits.rgmm_edge = 1;
-+      config0.bits.rxc_inv = 1;
-+      config0.bits.ipv4_tss_rx_en = 1;  /* enable H/W to check ip checksum */
-+      config0.bits.ipv6_tss_rx_en = 1;  /* enable H/W to check ip checksum */
-+
-+      config0_mask.bits.max_len = 3;
-+      config0_mask.bits.tx_fc_en = 1;
-+      config0_mask.bits.rx_fc_en = 1;
-+      config0_mask.bits.dis_rx = 1;
-+      config0_mask.bits.dis_tx = 1;
-+      config0_mask.bits.loop_back = 1;
-+      config0_mask.bits.rgmii_en = 1;
-+      config0_mask.bits.rgmm_edge = 1;
-+      config0_mask.bits.txc_inv = 1;
-+      config0_mask.bits.rxc_inv = 1;
-+      config0_mask.bits.ipv4_tss_rx_en = 1;
-+      config0_mask.bits.ipv6_tss_rx_en = 1;
-+      #endif
-+
-+      gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
-+
-+      #if 1
-+      hw_weigh.bits32 = 0;
-+      hw_weigh.bits.hw_tq3 = 1;
-+      hw_weigh.bits.hw_tq2 = 1;
-+      hw_weigh.bits.hw_tq1 = 1;
-+      hw_weigh.bits.hw_tq0 = 1;
-+      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_0_REG, hw_weigh.bits32, 0xffffffff);
-+
-+      sw_weigh.bits32 = 0;
-+      sw_weigh.bits.sw_tq5 = 1;
-+      sw_weigh.bits.sw_tq4 = 1;
-+      sw_weigh.bits.sw_tq3 = 1;
-+      sw_weigh.bits.sw_tq2 = 1;
-+      sw_weigh.bits.sw_tq1 = 1;
-+      sw_weigh.bits.sw_tq0 = 1;
-+      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_1_REG, sw_weigh.bits32, 0xffffffff);
-+      #endif
-+
-+      #if 0
-+      ahb_weight.bits32 = 0;
-+      ahb_weight_mask.bits32 = 0;
-+      ahb_weight.bits.rx_weight = 1;
-+      ahb_weight.bits.tx_weight = 1;
-+      ahb_weight.bits.hash_weight = 1;
-+      ahb_weight.bits.pre_req = 0x1f;
-+      ahb_weight.bits.tqDV_threshold = 0;
-+      ahb_weight_mask.bits.rx_weight = 0x1f;
-+      ahb_weight_mask.bits.tx_weight = 0x1f;
-+      ahb_weight_mask.bits.hash_weight = 0x1f;
-+      ahb_weight_mask.bits.pre_req = 0x1f;
-+      ahb_weight_mask.bits.tqDV_threshold = 0x1f;
-+      gmac_write_reg(tp->dma_base_addr, GMAC_AHB_WEIGHT_REG, ahb_weight.bits32, ahb_weight_mask.bits32);
-+      #endif
-+
-+      #if defined(CONFIG_SL351x_NAT) || defined(CONFIG_SL351x_RXTOE)
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR0, IPPROTO_TCP, 0xffffffff);
-+      #endif
-+      #ifdef CONFIG_SL351x_NAT
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR1, IPPROTO_UDP, 0xffffffff);
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR2, IPPROTO_GRE, 0xffffffff);
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR3, 0xff, 0xffffffff);
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR4, 0xff, 0xffffffff);
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR5, 0xff, 0xffffffff);
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR6, 0xff, 0xffffffff);
-+      gmac_write_reg(tp->dma_base_addr, GMAC_SPR7, 0xff, 0xffffffff);
-+
-+      sl351x_nat_init();
-+      #endif
-+
-+      #ifdef CONFIG_SL351x_RXTOE
-+      /* setup matching rule to TOE */
-+      sl351x_toe_init();
-+      #endif
-+
-+      // for A1 ASIC version
-+//    hash_ctrl.bits32 = 0;
-+//    hash_ctrl.bits.timing = 6;
-+//    gmac_write_reg(tp->dma_base_addr, GMAC_HASH_ENGINE_REG0, hash_ctrl.bits32, 0xffffffff);
-+
-+      return (0);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_gmac_enable_tx_rx
-+*----------------------------------------------------------------------*/
-+static void toe_gmac_enable_tx_rx(struct net_device *dev)
-+{
-+      GMAC_INFO_T             *tp = dev->priv;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+
-+    /* enable TX/RX */
-+    config0.bits32 = 0;
-+    config0_mask.bits32 = 0;
-+    config0.bits.dis_rx = 0;  /* enable rx */
-+    config0.bits.dis_tx = 0;  /* enable tx */
-+    config0_mask.bits.dis_rx = 1;
-+    config0_mask.bits.dis_tx = 1;
-+    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
-+}
-+/*----------------------------------------------------------------------
-+*     toe_gmac_disable_rx
-+*----------------------------------------------------------------------*/
-+#if 0
-+static void toe_gmac_disable_rx(struct net_device *dev)
-+{
-+      GMAC_INFO_T             *tp = dev->priv;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+
-+    /* enable TX/RX */
-+    config0.bits32 = 0;
-+    config0_mask.bits32 = 0;
-+    config0.bits.dis_rx = 1;  /* disable rx */
-+//    config0.bits.dis_tx = 1;  /* disable tx */
-+    config0_mask.bits.dis_rx = 1;
-+//     config0_mask.bits.dis_tx = 1;
-+    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+*     toe_gmac_enable_rx
-+*----------------------------------------------------------------------*/
-+#if 0
-+static void toe_gmac_enable_rx(struct net_device *dev)
-+{
-+      GMAC_INFO_T             *tp = dev->priv;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+
-+    /* enable TX/RX */
-+    config0.bits32 = 0;
-+    config0_mask.bits32 = 0;
-+    config0.bits.dis_rx = 0;  /* enable rx */
-+//    config0.bits.dis_tx = 0;  /* enable tx */
-+    config0_mask.bits.dis_rx = 1;
-+//    config0_mask.bits.dis_tx = 1;
-+    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+*     toe_gmac_disable_tx_rx
-+*----------------------------------------------------------------------*/
-+static void toe_gmac_disable_tx_rx(struct net_device *dev)
-+{
-+      GMAC_INFO_T             *tp = dev->priv;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+
-+    /* enable TX/RX */
-+    config0.bits32 = 0;
-+    config0_mask.bits32 = 0;
-+    config0.bits.dis_rx = 1;  /* disable rx */
-+    config0.bits.dis_tx = 1;  /* disable tx */
-+    config0_mask.bits.dis_rx = 1;
-+    config0_mask.bits.dis_tx = 1;
-+    gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_gmac_hw_start
-+*----------------------------------------------------------------------*/
-+static void toe_gmac_hw_start(struct net_device *dev)
-+{
-+      GMAC_INFO_T                             *tp = (GMAC_INFO_T *)dev->priv;
-+      GMAC_DMA_CTRL_T                 dma_ctrl, dma_ctrl_mask;
-+
-+
-+    /* program dma control register */
-+      dma_ctrl.bits32 = 0;
-+      dma_ctrl.bits.rd_enable = 1;
-+      dma_ctrl.bits.td_enable = 1;
-+      dma_ctrl.bits.loopback = 0;
-+      dma_ctrl.bits.drop_small_ack = 0;
-+      dma_ctrl.bits.rd_prot = 0;
-+      dma_ctrl.bits.rd_burst_size = 3;
-+      dma_ctrl.bits.rd_insert_bytes = RX_INSERT_BYTES;
-+      dma_ctrl.bits.rd_bus = 3;
-+      dma_ctrl.bits.td_prot = 0;
-+      dma_ctrl.bits.td_burst_size = 3;
-+      dma_ctrl.bits.td_bus = 3;
-+
-+      dma_ctrl_mask.bits32 = 0;
-+      dma_ctrl_mask.bits.rd_enable = 1;
-+      dma_ctrl_mask.bits.td_enable = 1;
-+      dma_ctrl_mask.bits.loopback = 1;
-+      dma_ctrl_mask.bits.drop_small_ack = 1;
-+      dma_ctrl_mask.bits.rd_prot = 3;
-+      dma_ctrl_mask.bits.rd_burst_size = 3;
-+      dma_ctrl_mask.bits.rd_insert_bytes = 3;
-+      dma_ctrl_mask.bits.rd_bus = 3;
-+      dma_ctrl_mask.bits.td_prot = 0x0f;
-+      dma_ctrl_mask.bits.td_burst_size = 3;
-+      dma_ctrl_mask.bits.td_bus = 3;
-+
-+      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+
-+    return;
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_gmac_hw_stop
-+*----------------------------------------------------------------------*/
-+static void toe_gmac_hw_stop(struct net_device *dev)
-+{
-+      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
-+      GMAC_DMA_CTRL_T         dma_ctrl, dma_ctrl_mask;
-+
-+    /* program dma control register */
-+      dma_ctrl.bits32 = 0;
-+      dma_ctrl.bits.rd_enable = 0;
-+      dma_ctrl.bits.td_enable = 0;
-+
-+      dma_ctrl_mask.bits32 = 0;
-+      dma_ctrl_mask.bits.rd_enable = 1;
-+      dma_ctrl_mask.bits.td_enable = 1;
-+
-+      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_gmac_clear_counter
-+*----------------------------------------------------------------------*/
-+static int toe_gmac_clear_counter (struct net_device *dev)
-+{
-+      GMAC_INFO_T     *tp = (GMAC_INFO_T *)dev->priv;
-+
-+    /* clear counter */
-+    gmac_read_reg(tp->base_addr, GMAC_IN_DISCARDS);
-+    gmac_read_reg(tp->base_addr, GMAC_IN_ERRORS);
-+    gmac_read_reg(tp->base_addr, GMAC_IN_MCAST);
-+    gmac_read_reg(tp->base_addr, GMAC_IN_BCAST);
-+    gmac_read_reg(tp->base_addr, GMAC_IN_MAC1);
-+    gmac_read_reg(tp->base_addr, GMAC_IN_MAC2);
-+              tp->ifStatics.tx_bytes = 0;
-+              tp->ifStatics.tx_packets = 0;
-+              tp->ifStatics.tx_errors = 0;
-+              tp->ifStatics.rx_bytes = 0;
-+              tp->ifStatics.rx_packets = 0;
-+              tp->ifStatics.rx_errors = 0;
-+              tp->ifStatics.rx_dropped = 0;
-+      return (0);
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+*     toe_gmac_tx_complete
-+*----------------------------------------------------------------------*/
-+static  void toe_gmac_tx_complete(GMAC_INFO_T *tp, unsigned int tx_qid,
-+                                                                              struct net_device *dev, int interrupt)
-+{
-+      volatile GMAC_TXDESC_T  *curr_desc;
-+      GMAC_TXDESC_0_T                 word0;
-+      GMAC_TXDESC_1_T                 word1;
-+      unsigned int                    desc_count;
-+//    struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
-+      GMAC_SWTXQ_T                    *swtxq;
-+      DMA_RWPTR_T                             rwptr;
-+
-+      /* get tx H/W completed descriptor virtual address */
-+      /* check tx status and accumulate tx statistics */
-+      swtxq = &tp->swtxq[tx_qid];
-+      swtxq->intr_cnt++;
-+      for (;;)
-+      {
-+              rwptr.bits32 = readl(swtxq->rwptr_reg);
-+              if (rwptr.bits.rptr == swtxq->finished_idx)
-+                      break;
-+      curr_desc = (volatile GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
-+//            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_FROMDEVICE);
-+              word0.bits32 = curr_desc->word0.bits32;
-+              word1.bits32 = curr_desc->word1.bits32;
-+
-+              if (word0.bits.status_tx_ok)
-+              {
-+                      tp->ifStatics.tx_bytes += word1.bits.byte_count;
-+                      desc_count = word0.bits.desc_count;
-+                      if (desc_count==0)
-+                      {
-+                              printk("%s::Desc 0x%x = 0x%x, desc_count=%d\n",__func__, (u32)curr_desc, word0.bits32, desc_count);
-+                              while(1);
-+                      }
-+                      while (--desc_count)
-+                      {
-+                              word0.bits.status_tx_ok = 0;
-+                              curr_desc->word0.bits32 = word0.bits32;
-+                              swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
-+                              curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
-+                              word0.bits32 = curr_desc->word0.bits32;
-+#ifdef _DUMP_TX_TCP_CONTENT
-+                              if (curr_desc->word0.bits.buffer_size < 16)
-+                              {
-+                                      int a;
-+                                      char *datap;
-+                                      printk("\t Tx Finished Desc 0x%x Len %d Addr 0x%08x: ", (u32)curr_desc, curr_desc->word0.bits.buffer_size, curr_desc->word2.buf_adr);
-+                                      datap = (char *)__va(curr_desc->word2.buf_adr);
-+                                      for (a=0; a<8 && a<curr_desc->word0.bits.buffer_size; a++, datap++)
-+                                      {
-+                                              printk("0x%02x ", *datap);
-+                                      }
-+                                      printk("\n");
-+                              }
-+#endif
-+                      }
-+
-+                      word0.bits.status_tx_ok = 0;
-+                      if (swtxq->tx_skb[swtxq->finished_idx])
-+                      {
-+                              if (interrupt)
-+                                      dev_kfree_skb_irq(swtxq->tx_skb[swtxq->finished_idx]);
-+                              else
-+                                      dev_kfree_skb(swtxq->tx_skb[swtxq->finished_idx]);
-+                              swtxq->tx_skb[swtxq->finished_idx] = NULL;
-+                      }
-+                      curr_desc->word0.bits32 = word0.bits32;
-+                      swtxq->curr_finished_desc = (GMAC_TXDESC_T *)curr_desc;
-+                      swtxq->total_finished++;
-+                      tp->ifStatics.tx_packets++;
-+                      swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
-+              }
-+              else
-+              {
-+                      // tp->ifStatics.tx_errors++;
-+                      // printk("%s::Tx Descriptor is !!!\n",__func__);
-+                      // wait ready by breaking
-+                      break;
-+              }
-+      }
-+
-+      if (netif_queue_stopped(dev))
-+      {
-+              netif_wake_queue(dev);
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+*     gmac_start_xmit
-+*----------------------------------------------------------------------*/
-+static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      GMAC_INFO_T                     *tp= dev->priv;
-+//    static unsigned int     pcount = 0;
-+//    unsigned int                    tx_qid;
-+    DMA_RWPTR_T                               rwptr;
-+      volatile GMAC_TXDESC_T  *curr_desc;
-+      int                                     snd_pages = skb_shinfo(skb)->nr_frags + 1;  /* get number of descriptor */
-+      int                                     frag_id = 0;
-+      int                                     len, total_len = skb->len;
-+      struct net_device_stats *isPtr;
-+      unsigned int                    free_desc;
-+      GMAC_SWTXQ_T                    *swtxq;
-+      register unsigned long  word0, word1, word2, word3;
-+      unsigned short                  wptr, rptr;
-+#ifdef        L2_jumbo_frame
-+      int header_len = skb->len;
-+      struct iphdr    *ip_hdr;
-+    struct tcphdr     *tcp_hdr;
-+    int             tcp_hdr_len;
-+    unsigned char     *ptr;
-+    int             data_len,a;
-+    unsigned int    val;
-+#endif
-+
-+#ifdef GMAC_LEN_1_2_ISSUE
-+      int                                             total_pages;
-+      total_pages = snd_pages;
-+#endif
-+
-+      isPtr = (struct net_device_stats *)&tp->ifStatics;
-+#if 1
-+      if (skb->len >= 0x10000)
-+      {
-+//            spin_unlock(&tp->tx_mutex);
-+              isPtr->tx_dropped++;
-+              printk("%s::[GMAC %d] skb->len %d >= 64K\n", __func__, tp->port_id, skb->len);
-+              netif_stop_queue(dev);
-+              return 1;
-+    }
-+#endif
-+
-+#if 0
-+      if (storlink_ctl.recvfile==2)
-+      {
-+          printk("snd_pages=%d skb->len=%d\n",snd_pages,skb->len);
-+      }
-+#endif
-+
-+#ifdef GMAC_USE_TXQ0
-+      #define tx_qid  0
-+#endif
-+
-+      swtxq = &tp->swtxq[tx_qid];
-+
-+//    spin_lock(&tp->tx_mutex);
-+    rwptr.bits32 = readl(swtxq->rwptr_reg);
-+      wptr = rwptr.bits.wptr;
-+      rptr = rwptr.bits.rptr;
-+
-+      // check finished desc or empty BD
-+      // cannot check by read ptr of RW PTR register,
-+      // because the HW complete to send but the SW may NOT handle it
-+#ifndef       GMAX_TX_INTR_DISABLED
-+      if (wptr >= swtxq->finished_idx)
-+              free_desc = swtxq->total_desc_num - wptr - 1 + swtxq->finished_idx;
-+      else
-+              free_desc = swtxq->finished_idx - wptr - 1;
-+
-+      if (free_desc < snd_pages)
-+      {
-+//            spin_unlock(&tp->tx_mutex);
-+              isPtr->tx_dropped++;
-+//            printk("GMAC %d No available descriptor!\n", tp->port_id);
-+              netif_stop_queue(dev);
-+              return 1;
-+    }
-+#else
-+      toe_gmac_tx_complete(tp, tx_qid, dev, 0);
-+
-+      if (wptr >= swtxq->finished_idx)
-+              free_desc = swtxq->total_desc_num - wptr - 1 + swtxq->finished_idx;
-+      else
-+              free_desc = swtxq->finished_idx - wptr - 1;
-+      if (free_desc < snd_pages)
-+      {
-+//            spin_unlock(&tp->tx_mutex);
-+              isPtr->tx_dropped++;
-+//            printk("GMAC %d No available descriptor!\n", tp->port_id);
-+              netif_stop_queue(dev);
-+              return 1;
-+    }
-+
-+#if 0
-+      printk("1: free_desc=%d, wptr=%d, finished_idx=%d\n", free_desc, wptr, swtxq->finished_idx);
-+      if ((free_desc < (snd_pages << 2)) ||
-+          (free_desc < (swtxq->total_desc_num >> 2)))
-+      {
-+              printk("2: free_desc = %d\n", free_desc);
-+              toe_gmac_tx_complete(tp, tx_qid, dev, 0);
-+              rwptr.bits32 = readl(swtxq->rwptr_reg);
-+              wptr = rwptr.bits.wptr;
-+              if (wptr>= swtxq->finished_idx)
-+                      free_desc = swtxq->total_desc_num - wptr -1 + swtxq->finished_idx;
-+              else
-+                      free_desc = swtxq->finished_idx - wptr - 1;
-+      }
-+#endif
-+#endif
-+
-+#ifdef        L2_jumbo_frame
-+//            data_len = skb->len - 14 - ip_hdr->ihl *4 - tcp_hdr_len;
-+//            if ((skb->nh.iph->protocol == __constant_htons(ETH_P_IP)) && ((skb->nh.iph->protocol & 0x00ff)  == IPPROTO_TCP))
-+//            if (skb->nh.iph->protocol == 0x006 && (skb->nh.iph->protocol == __constant_htons(ETH_P_IP)))
-+              if (((skb->nh.iph->protocol & 0x00ff)  == IPPROTO_TCP))
-+              {
-+                              ip_hdr = (struct iphdr*)(skb->nh.iph);
-+                              tcp_hdr = (struct tcphdr*)(skb->h.th);
-+                              tcp_hdr_len = TCPHDRLEN(tcp_hdr) * 4;
-+                              tcp_hdr_len = TCPHDRLEN(tcp_hdr) * 4;
-+
-+                              if ((skb->h.th->syn) && (tcp_hdr_len > 20))
-+                              {
-+                                      ptr = (unsigned char *)(tcp_hdr+1);
-+                                      if ((ptr[0] == 0x02) && (ptr[1] == 0x04) && (ptr[2] == 0x07) && (ptr[3] == 0xba)) // 0x07 aa=2016-54=1962  ,0x07ba=2032-54=1978
-+                                      {
-+                                              ptr[2]=0x20;    //23
-+                                              ptr[3]=0x00;    //00
-+                                              printk("-----> Change MSS to 8K \n" );
-+                                      }
-+                              }
-+              }
-+//            if ((ip_hdr->protocol & 0x00ff) != IPPROTO_TCP)
-+//            if ((tcp_hdr_len > 20) && (skb->h.th->syn))
-+#endif
-+
-+
-+#if 0
-+      if (snd_pages > 1)
-+              printk("-----> snd_pages=%d\n", snd_pages);
-+      if (total_len > 1514)
-+      {
-+              printk("-----> total_len=%d\n", total_len);
-+      }
-+#endif
-+
-+    while (snd_pages)
-+    {
-+      char *pkt_datap;
-+
-+      curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + wptr;
-+//            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_FROMDEVICE);
-+#if 0
-+//#if (GMAC_DEBUG==1)
-+      // if curr_desc->word2.buf_adr !=0 means that the ISR does NOT handle it
-+      // if (curr_desc->word2.buf_adr)
-+      if (swtxq->tx_skb[wptr])
-+      {
-+              printk("Error! Stop due to TX descriptor's buffer is not freed!\n");
-+              while(1);
-+              dev_kfree_skb(swtxq->tx_skb[wptr]);
-+              swtxq->tx_skb[wptr] = NULL;
-+              }
-+#endif
-+
-+              if (frag_id == 0)
-+              {
-+#if 0
-+                      int i;
-+                      pkt_datap = skb->data;
-+                      len = total_len;
-+                      for (i=0; i<skb_shinfo(skb)->nr_frags; i++)
-+                      {
-+                              skb_frag_t* frag = &skb_shinfo(skb)->frags[i];
-+                              len -= frag->size;
-+                      }
-+#else
-+                      pkt_datap = skb->data;
-+                      len = total_len - skb->data_len;
-+#endif
-+              }
-+              else
-+              {
-+                      skb_frag_t* frag = &skb_shinfo(skb)->frags[frag_id-1];
-+                      pkt_datap = page_address(frag->page) + frag->page_offset;
-+                      len = frag->size;
-+                      if (len > total_len)
-+                      {
-+                              printk("===> Fatal Error! Send Frag size %d > Total Size %d!!!!!\n",
-+                                      len, total_len);
-+                      }
-+              }
-+
-+              /* set TX descriptor */
-+              /* copy packet to descriptor buffer address */
-+              // curr_desc->word0.bits32 = len;    /* total frame byte count */
-+              word0 = len;
-+#ifdef        L2_jumbo_frame
-+              word3 = (dev->mtu+14) | EOFIE_BIT;  //2016 ,2032
-+#else
-+              word3 = 1514 | EOFIE_BIT;
-+#endif
-+
-+#ifdef DO_HW_CHKSUM
-+#ifdef        L2_jumbo_frame
-+              if (total_len >= (dev->mtu+14) && (skb->nh.iph->protocol == 0x011) && skb->nh.iph && (skb->nh.iph->frag_off & __constant_htons(0x3fff)))
-+#else
-+              if (total_len <= 1514 && ip_hdr(skb) && (ip_hdr(skb)->frag_off & __constant_htons(0x3fff)))
-+#endif
-+                      word1  = total_len |
-+                                      TSS_IP_CHKSUM_BIT  |
-+                                      TSS_IPV6_ENABLE_BIT |
-+                                      TSS_MTU_ENABLE_BIT;
-+              else
-+                      word1 = total_len |
-+                                      TSS_UDP_CHKSUM_BIT |
-+                                      TSS_TCP_CHKSUM_BIT |
-+                                      TSS_IP_CHKSUM_BIT  |
-+                                      TSS_IPV6_ENABLE_BIT |
-+                                      TSS_MTU_ENABLE_BIT;
-+#else
-+              word1 = total_len | TSS_MTU_ENABLE_BIT;
-+#endif
-+              word2 = (unsigned long)__pa(pkt_datap);
-+
-+              if (frag_id == 0)
-+              {
-+                      word3 |= SOF_BIT;       // SOF
-+              }
-+
-+              if (snd_pages == 1)
-+              {
-+                      word3 |= EOF_BIT;       // EOF
-+                      swtxq->tx_skb[wptr] = skb;
-+#ifdef CONFIG_SL351x_NAT
-+                      if (nat_cfg.enabled && sl351x_nat_output(skb, tp->port_id))
-+                              word1 |= TSS_IP_FIXED_LEN_BIT;
-+#endif
-+              }
-+              else
-+                      swtxq->tx_skb[wptr] = NULL;
-+              // word1 |= TSS_IP_FIXED_LEN_BIT;
-+#if 1
-+#ifdef CONFIG_SL351x_RXTOE
-+              // check if this frame has the mission to enable toe hash entry..
-+              // if rx_max_pktsize ==0, do not enable RXTOE
-+              if (TCP_SKB_CB(skb)->connection && storlink_ctl.rx_max_pktsize) {
-+                      set_toeq_hdr(TCP_SKB_CB(skb)->connection, &toe_private_data, dev);
-+              }
-+#endif
-+#endif
-+#ifdef _DUMP_TX_TCP_CONTENT
-+              if (len < 16 && frag_id && skb->h.th && (skb->h.th->source == __constant_htons(445) || skb->h.th->source == __constant_htons(139)))
-+              {
-+                      int a;
-+                      char *datap;
-+                      printk("Tx Desc 0x%x Frag %d Len %d [IP-ID 0x%x] 0x%08x: ", (u32)curr_desc, frag_id, len, htons(skb->nh.iph->id), (u32)pkt_datap);
-+                      datap = (char *)pkt_datap;
-+                      for (a=0; a<8 && a<len; a++, datap++)
-+                      {
-+                              printk("0x%02x ", *datap);
-+                      }
-+                      printk("\n");
-+              }
-+#endif
-+
-+#ifdef GMAC_LEN_1_2_ISSUE
-+              if ((total_pages!=snd_pages) && (len == 1 || len == 2 ) && ((u32)pkt_datap & 0x03))
-+              {
-+                      memcpy((void *)&_debug_prefetch_buf[_debug_prefetch_cnt][0], pkt_datap, len);
-+                      pkt_datap = (char *)&_debug_prefetch_buf[_debug_prefetch_cnt][0];
-+                      word2 = (unsigned long)__pa(pkt_datap);
-+                      _debug_prefetch_cnt++;
-+                      if (_debug_prefetch_cnt >= _DEBUG_PREFETCH_NUM)
-+                              _debug_prefetch_cnt = 0;
-+              }
-+#endif
-+
-+              consistent_sync((void *)pkt_datap, len, PCI_DMA_TODEVICE);
-+              wmb();
-+              curr_desc->word0.bits32 = word0;
-+              curr_desc->word1.bits32 = word1;
-+              curr_desc->word2.bits32 = word2;
-+              curr_desc->word3.bits32 = word3;
-+              swtxq->curr_tx_desc = (GMAC_TXDESC_T *)curr_desc;
-+//            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_TODEVICE);
-+#ifdef _DUMP_TX_TCP_CONTENT
-+              if (len < 16 && frag_id && skb->h.th && (skb->h.th->source == __constant_htons(445) || skb->h.th->source == __constant_htons(139)))
-+              {
-+                      int a;
-+                      char *datap;
-+                      printk("\t 0x%08x: ", (u32)pkt_datap);
-+                      datap = (char *)pkt_datap;
-+                      for (a=0; a<8 && a<len; a++, datap++)
-+                      {
-+                              printk("0x%02x ", *datap);
-+                      }
-+                      printk("\n");
-+              }
-+#endif
-+              free_desc--;
-+              wmb();
-+              wptr = RWPTR_ADVANCE_ONE(wptr, swtxq->total_desc_num);
-+              frag_id++;
-+              snd_pages--;
-+      }
-+
-+    swtxq->total_sent++;
-+      SET_WPTR(swtxq->rwptr_reg, wptr);
-+      dev->trans_start = jiffies;
-+
-+
-+      // printk("MAC %d Qid %d rwptr = 0x%x, curr_desc=0x%x\n", skb->tx_port_id, tx_qid, rwptr.bits32, curr_desc);
-+//#ifdef      GMAX_TX_INTR_DISABLED
-+//            toe_gmac_tx_complete(tp, tx_qid, dev, 0);
-+//#endif
-+      return (0);
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_set_mac_address
-+*----------------------------------------------------------------------*/
-+
-+static int gmac_set_mac_address(struct net_device *dev, void *addr)
-+{
-+      GMAC_INFO_T             *tp= dev->priv;
-+      struct sockaddr *sock;
-+      unsigned int    reg_val;
-+    unsigned int    i;
-+
-+      sock = (struct sockaddr *) addr;
-+      for (i = 0; i < 6; i++)
-+      {
-+              dev->dev_addr[i] = sock->sa_data[i];
-+      }
-+
-+    reg_val = dev->dev_addr[0] + (dev->dev_addr[1]<<8) + (dev->dev_addr[2]<<16) + (dev->dev_addr[3]<<24);
-+    gmac_write_reg(tp->base_addr,GMAC_STA_ADD0,reg_val,0xffffffff);
-+    reg_val = dev->dev_addr[4] + (dev->dev_addr[5]<<8);
-+    gmac_write_reg(tp->base_addr,GMAC_STA_ADD1,reg_val,0x0000ffff);
-+      memcpy(&eth_mac[tp->port_id][0],&dev->dev_addr[0],6);
-+
-+    printk("Storlink %s address = ",dev->name);
-+    printk("%02x",dev->dev_addr[0]);
-+    printk("%02x",dev->dev_addr[1]);
-+    printk("%02x",dev->dev_addr[2]);
-+    printk("%02x",dev->dev_addr[3]);
-+    printk("%02x",dev->dev_addr[4]);
-+    printk("%02x\n",dev->dev_addr[5]);
-+
-+    return (0);
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_get_mac_address
-+*     get mac address from FLASH
-+*----------------------------------------------------------------------*/
-+static void gmac_get_mac_address(void)
-+{
-+#ifdef CONFIG_MTD
-+      extern int get_vlaninfo(vlaninfo* vlan);
-+    static vlaninfo    vlan[2];
-+
-+    if (get_vlaninfo(&vlan[0]))
-+    {
-+        memcpy((void *)&eth_mac[0][0],vlan[0].mac,6);
-+        // VLAN_conf[0].vid = vlan[0].vlanid;
-+        // VLAN_conf[0].portmap = vlan[0].vlanmap;
-+        memcpy((void *)&eth_mac[1][0],vlan[1].mac,6);
-+        // VLAN_conf[1].vid = vlan[1].vlanid;
-+        // VLAN_conf[1].portmap = vlan[1].vlanmap;
-+    }
-+#else
-+    unsigned int reg_val;
-+
-+    reg_val = readl(IO_ADDRESS(TOE_GMAC0_BASE)+0xac);
-+    eth_mac[0][4] = (reg_val & 0xff00) >> 8;
-+    eth_mac[0][5] = reg_val & 0x00ff;
-+    reg_val = readl(IO_ADDRESS(SL2312_SECURITY_BASE)+0xac);
-+    eth_mac[1][4] = (reg_val & 0xff00) >> 8;
-+    eth_mac[1][5] = reg_val & 0x00ff;
-+#endif
-+    return;
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* mac_stop_txdma
-+*----------------------------------------------------------------------*/
-+void mac_stop_txdma(struct net_device *dev)
-+{
-+      GMAC_INFO_T                             *tp = (GMAC_INFO_T *)dev->priv;
-+      GMAC_DMA_CTRL_T                 dma_ctrl, dma_ctrl_mask;
-+      GMAC_TXDMA_FIRST_DESC_T txdma_busy;
-+
-+      // wait idle
-+      do
-+      {
-+              txdma_busy.bits32 = gmac_read_reg(tp->dma_base_addr, GMAC_DMA_TX_FIRST_DESC_REG);
-+      } while (txdma_busy.bits.td_busy);
-+
-+    /* program dma control register */
-+      dma_ctrl.bits32 = 0;
-+      dma_ctrl.bits.rd_enable = 0;
-+      dma_ctrl.bits.td_enable = 0;
-+
-+      dma_ctrl_mask.bits32 = 0;
-+      dma_ctrl_mask.bits.rd_enable = 1;
-+      dma_ctrl_mask.bits.td_enable = 1;
-+
-+      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_start_txdma
-+*----------------------------------------------------------------------*/
-+void mac_start_txdma(struct net_device *dev)
-+{
-+      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
-+      GMAC_DMA_CTRL_T         dma_ctrl, dma_ctrl_mask;
-+
-+    /* program dma control register */
-+      dma_ctrl.bits32 = 0;
-+      dma_ctrl.bits.rd_enable = 1;
-+      dma_ctrl.bits.td_enable = 1;
-+
-+      dma_ctrl_mask.bits32 = 0;
-+      dma_ctrl_mask.bits.rd_enable = 1;
-+      dma_ctrl_mask.bits.td_enable = 1;
-+
-+      gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* gmac_get_stats
-+*----------------------------------------------------------------------*/
-+
-+struct net_device_stats * gmac_get_stats(struct net_device *dev)
-+{
-+    GMAC_INFO_T *tp = (GMAC_INFO_T *)dev->priv;
-+    // unsigned int        flags;
-+    unsigned int        pkt_drop;
-+    unsigned int        pkt_error;
-+
-+    if (netif_running(dev))
-+    {
-+        /* read H/W counter */
-+        // spin_lock_irqsave(&tp->lock,flags);
-+        pkt_drop = gmac_read_reg(tp->base_addr,GMAC_IN_DISCARDS);
-+        pkt_error = gmac_read_reg(tp->base_addr,GMAC_IN_ERRORS);
-+        tp->ifStatics.rx_dropped = tp->ifStatics.rx_dropped + pkt_drop;
-+        tp->ifStatics.rx_errors = tp->ifStatics.rx_errors + pkt_error;
-+        // spin_unlock_irqrestore(&tp->lock,flags);
-+    }
-+    return &tp->ifStatics;
-+}
-+
-+
-+
-+/*----------------------------------------------------------------------
-+* mac_get_sw_tx_weight
-+*----------------------------------------------------------------------*/
-+void mac_get_sw_tx_weight(struct net_device *dev, char *weight)
-+{
-+      GMAC_TX_WCR1_T  sw_weigh;
-+    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
-+
-+      sw_weigh.bits32 = gmac_read_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_1_REG);
-+
-+      weight[0] = sw_weigh.bits.sw_tq0;
-+      weight[1] = sw_weigh.bits.sw_tq1;
-+      weight[2] = sw_weigh.bits.sw_tq2;
-+      weight[3] = sw_weigh.bits.sw_tq3;
-+      weight[4] = sw_weigh.bits.sw_tq4;
-+      weight[5] = sw_weigh.bits.sw_tq5;
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_set_sw_tx_weight
-+*----------------------------------------------------------------------*/
-+void mac_set_sw_tx_weight(struct net_device *dev, char *weight)
-+{
-+      GMAC_TX_WCR1_T  sw_weigh;
-+    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
-+
-+      sw_weigh.bits32 = 0;
-+      sw_weigh.bits.sw_tq0 = weight[0];
-+      sw_weigh.bits.sw_tq1 = weight[1];
-+      sw_weigh.bits.sw_tq2 = weight[2];
-+      sw_weigh.bits.sw_tq3 = weight[3];
-+      sw_weigh.bits.sw_tq4 = weight[4];
-+      sw_weigh.bits.sw_tq5 = weight[5];
-+
-+      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_1_REG, sw_weigh.bits32, 0xffffffff);
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_get_hw_tx_weight
-+*----------------------------------------------------------------------*/
-+void mac_get_hw_tx_weight(struct net_device *dev, char *weight)
-+{
-+      GMAC_TX_WCR0_T  hw_weigh;
-+    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
-+
-+      hw_weigh.bits32 = gmac_read_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_0_REG);
-+
-+      weight[0] = hw_weigh.bits.hw_tq0;
-+      weight[1] = hw_weigh.bits.hw_tq1;
-+      weight[2] = hw_weigh.bits.hw_tq2;
-+      weight[3] = hw_weigh.bits.hw_tq3;
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_set_hw_tx_weight
-+*----------------------------------------------------------------------*/
-+void mac_set_hw_tx_weight(struct net_device *dev, char *weight)
-+{
-+      GMAC_TX_WCR0_T  hw_weigh;
-+    GMAC_INFO_T               *tp = (GMAC_INFO_T *)dev->priv;
-+
-+      hw_weigh.bits32 = 0;
-+      hw_weigh.bits.hw_tq0 = weight[0];
-+      hw_weigh.bits.hw_tq1 = weight[1];
-+      hw_weigh.bits.hw_tq2 = weight[2];
-+      hw_weigh.bits.hw_tq3 = weight[3];
-+
-+      gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_0_REG, hw_weigh.bits32, 0xffffffff);
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_start_tx_dma
-+*----------------------------------------------------------------------*/
-+int mac_start_tx_dma(int mac)
-+{
-+      GMAC_DMA_CTRL_T dma_ctrl, dma_ctrl_mask;
-+
-+      dma_ctrl.bits32 = 0;
-+      dma_ctrl.bits.td_enable = 1;
-+
-+      dma_ctrl_mask.bits32 = 0;
-+      dma_ctrl_mask.bits.td_enable = 1;
-+
-+      if (mac == 0)
-+      gmac_write_reg(TOE_GMAC0_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+      else
-+      gmac_write_reg(TOE_GMAC1_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+      return  1;
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_stop_tx_dma
-+*----------------------------------------------------------------------*/
-+int mac_stop_tx_dma(int mac)
-+{
-+      GMAC_DMA_CTRL_T dma_ctrl, dma_ctrl_mask;
-+
-+      dma_ctrl.bits32 = 0;
-+      dma_ctrl.bits.td_enable = 0;
-+
-+      dma_ctrl_mask.bits32 = 0;
-+      dma_ctrl_mask.bits.td_enable = 1;
-+
-+      if (mac == 0)
-+      gmac_write_reg(TOE_GMAC0_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+      else
-+      gmac_write_reg(TOE_GMAC1_DMA_BASE, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);
-+      return  1;
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_read_reg(int mac, unsigned int offset)
-+*----------------------------------------------------------------------*/
-+unsigned int mac_read_reg(int mac, unsigned int offset)
-+{
-+      switch (mac)
-+      {
-+              case 0:
-+                      return gmac_read_reg(TOE_GMAC0_BASE, offset);
-+              case 1:
-+                      return gmac_read_reg(TOE_GMAC1_BASE, offset);
-+              default:
-+                      return 0;
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_write_reg
-+*----------------------------------------------------------------------*/
-+void mac_write_reg(int mac, unsigned int offset, unsigned data)
-+{
-+      switch (mac)
-+      {
-+              case 0:
-+                      gmac_write_reg(GMAC0_BASE, offset, data, 0xffffffff);
-+                      break;
-+              case 1:
-+                      gmac_write_reg(GMAC1_BASE, offset, data, 0xffffffff);
-+                      break;
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_read_dma_reg(int mac, unsigned int offset)
-+*----------------------------------------------------------------------*/
-+u32 mac_read_dma_reg(int mac, unsigned int offset)
-+{
-+      switch (mac)
-+      {
-+              case 0:
-+                      return gmac_read_reg(TOE_GMAC0_DMA_BASE, offset);
-+              case 1:
-+                      return gmac_read_reg(TOE_GMAC1_DMA_BASE, offset);
-+              default:
-+                      return 0;
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_write_dma_reg
-+*----------------------------------------------------------------------*/
-+void mac_write_dma_reg(int mac, unsigned int offset, u32 data)
-+{
-+      switch (mac)
-+      {
-+              case 0:
-+                      gmac_write_reg(TOE_GMAC0_DMA_BASE, offset, data, 0xffffffff);
-+                      break;
-+              case 1:
-+                      gmac_write_reg(TOE_GMAC1_DMA_BASE, offset, data, 0xffffffff);
-+                      break;
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* ether_crc
-+*----------------------------------------------------------------------*/
-+static unsigned const ethernet_polynomial = 0x04c11db7U;
-+static unsigned int ether_crc (int length, unsigned char *data)
-+{
-+      int crc = -1;
-+      unsigned int i;
-+      unsigned int crc_val=0;
-+
-+      while (--length >= 0) {
-+              unsigned char current_octet = *data++;
-+              int bit;
-+              for (bit = 0; bit < 8; bit++, current_octet >>= 1)
-+                      crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ?
-+                           ethernet_polynomial : 0);
-+      }
-+      crc = ~crc;
-+      for (i=0;i<32;i++)
-+      {
-+              crc_val = crc_val + (((crc << i) & 0x80000000) >> (31-i));
-+      }
-+      return crc_val;
-+}
-+
-+
-+
-+/*----------------------------------------------------------------------
-+* mac_set_rx_mode
-+*----------------------------------------------------------------------*/
-+void mac_set_rx_mode(int pid, unsigned int data)
-+{
-+      unsigned int    base;
-+
-+      base = (pid == 0) ? GMAC0_BASE : GMAC1_BASE;
-+
-+    gmac_write_reg(base, GMAC_RX_FLTR, data, 0x0000001f);
-+    return;
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* gmac_open
-+*----------------------------------------------------------------------*/
-+
-+static int gmac_open (struct net_device *dev)
-+{
-+      GMAC_INFO_T  *tp = (GMAC_INFO_T *)dev->priv;
-+      int                                     retval;
-+      TOE_INFO_T                              *toe;
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+
-+    /* hook ISR */
-+      retval = request_irq (dev->irq, toe_gmac_interrupt, IRQF_DISABLED, dev->name, dev);
-+      if (retval)
-+              return retval;
-+
-+      toe_init_gmac(dev);
-+
-+      if(!FLAG_SWITCH)
-+      {
-+      init_waitqueue_head (&tp->thr_wait);
-+      init_completion(&tp->thr_exited);
-+
-+      tp->time_to_die = 0;
-+      tp->thr_pid = kernel_thread (gmac_phy_thread, dev, CLONE_FS | CLONE_FILES);
-+      if (tp->thr_pid < 0)
-+      {
-+              printk (KERN_WARNING "%s: unable to start kernel thread\n",dev->name);
-+      }
-+    }
-+
-+      tp->operation = 1;
-+
-+      netif_start_queue (dev);
-+
-+      return (0);
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_close
-+*----------------------------------------------------------------------*/
-+static int gmac_close(struct net_device *dev)
-+{
-+    TOE_INFO_T                        *toe;
-+//    GMAC_RXDESC_T           *sw_desc_ptr,*desc_ptr;
-+//    unsigned int            buf_ptr;
-+      GMAC_INFO_T     *tp = dev->priv;
-+      unsigned int            ret;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+
-+      tp->operation = 0;
-+
-+    netif_stop_queue(dev);
-+    mdelay(20);
-+
-+    /* stop tx/rx packet */
-+    toe_gmac_disable_tx_rx(dev);
-+    mdelay(20);
-+
-+    /* stop the chip's Tx and Rx DMA processes */
-+      toe_gmac_hw_stop(dev);
-+
-+      toe_gmac_disable_interrupt(tp->irq);
-+
-+    /* disable interrupts by clearing the interrupt mask */
-+    synchronize_irq();
-+    free_irq(dev->irq,dev);
-+
-+//    DMA_MFREE(sw_desc_ptr, (TOE_SW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T),(dma_addr_t *)&toe->sw_freeq_desc_base_dma);
-+//    DMA_MFREE(desc_ptr, TOE_HW_FREEQ_DESC_NUM * sizeof(GMAC_RXDESC_T),(dma_addr_t *)&toe->hw_freeq_desc_base_dma);
-+//    DMA_MFREE(buf_ptr, TOE_HW_FREEQ_DESC_NUM) * HW_RX_BUF_SIZE),(dma_addr_t *)&toe->hwfq_buf_base_dma);
-+//    DMA_MFREE(toe->gmac[0].swtxq_desc_base , TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[0].swtxq_desc_base_dma);
-+//    DMA_MFREE(toe->gmac[1].swtxq_desc_base , TOE_GMAC0_SWTXQ_DESC_NUM * TOE_SW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[1].swtxq_desc_base_dma);
-+//    DMA_MFREE(toe->gmac[0].hwtxq_desc_base_dma , TOE_GMAC0_HWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[0].hwtxq_desc_base_dma);
-+//    DMA_MFREE(toe->gmac[1].hwtxq_desc_base_dma , TOE_GMAC0_SWTXQ_DESC_NUM * TOE_HW_TXQ_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[1].hwtxq_desc_base_dma);
-+//    DMA_MFREE(toe->gmac[0].default_desc_base_dma ,TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
-+//    DMA_MFREE(toe->gmac[1].default_desc_base_dma , TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_TXDESC_T),(dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
-+//    DMA_MFREE(toe->intr_desc_base_dma , TOE_INTR_QUEUE_NUM * TOE_INTR_DESC_NUM * sizeof(GMAC_RXDESC_T),(dma_addr_t *)&toe->intr_desc_base_dma);
-+//    DMA_MFREE(toe->intr_buf_base_dma , TOE_INTR_DESC_NUM * sizeof(TOE_QHDR_T),(dma_addr_t *)&toe->intr_buf_base_dma);
-+
-+      if(!FLAG_SWITCH)
-+      {
-+      if (tp->thr_pid >= 0)
-+      {
-+                  tp->time_to_die = 1;
-+              wmb();
-+              ret = kill_proc (tp->thr_pid, SIGTERM, 1);
-+              if (ret)
-+              {
-+                      printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
-+                      return ret;
-+              }
-+//                    wait_for_completion (&tp->thr_exited);
-+      }
-+    }
-+
-+    return (0);
-+}
-+
-+/*----------------------------------------------------------------------
-+* toe_gmac_fill_free_q
-+* allocate buffers for free queue.
-+*----------------------------------------------------------------------*/
-+static inline void toe_gmac_fill_free_q(void)
-+{
-+      struct sk_buff  *skb;
-+      volatile DMA_RWPTR_T    fq_rwptr;
-+      volatile GMAC_RXDESC_T  *fq_desc;
-+      unsigned long   flags;
-+      // unsigned short max_cnt=TOE_SW_FREEQ_DESC_NUM>>1;
-+
-+      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+      spin_lock_irqsave(&gmac_fq_lock, flags);
-+      //while ((max_cnt--) && (unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
-+      //                              TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
-+      while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
-+                                      TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
-+              if ((skb = dev_alloc_skb(SW_RX_BUF_SIZE)) == NULL) {
-+                      printk("%s::skb allocation fail!\n", __func__);
-+                      //while(1);
-+                      break;
-+              }
-+              REG32(skb->data) = (unsigned int)skb;
-+              skb_reserve(skb, SKB_RESERVE_BYTES);
-+              // fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
-+                      TOE_SW_FREEQ_DESC_NUM);
-+              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base+fq_rwptr.bits.wptr;
-+              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
-+              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
-+              toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
-+      }
-+      spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+}
-+// EXPORT_SYMBOL(toe_gmac_fill_free_q);
-+
-+/*----------------------------------------------------------------------
-+* toe_gmac_interrupt
-+*----------------------------------------------------------------------*/
-+static irqreturn_t toe_gmac_interrupt (int irq, void *dev_instance)
-+{
-+      struct net_device   *dev = (struct net_device *)dev_instance;
-+      TOE_INFO_T                      *toe;
-+      GMAC_INFO_T             *tp = (GMAC_INFO_T *)dev->priv;
-+      unsigned int            status0;
-+      unsigned int            status1;
-+      unsigned int            status2;
-+      unsigned int            status3;
-+      unsigned int            status4;
-+
-+//    struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+//    handle NAPI
-+#ifdef CONFIG_SL_NAPI
-+if (storlink_ctl.pauseoff == 1)
-+{
-+/* disable GMAC interrupt */
-+    //toe_gmac_disable_interrupt(tp->irq);
-+
-+//    isPtr->interrupts++;
-+      /* read Interrupt status */
-+      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
-+      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
-+      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
-+      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+      // prompt warning if status bit ON but not enabled
-+#if 0
-+      if (status0 & ~tp->intr0_enabled)
-+              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status0, tp->intr0_enabled);
-+      if (status1 & ~tp->intr1_enabled)
-+              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status1, tp->intr1_enabled);
-+      if (status2 & ~tp->intr2_enabled)
-+              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status2, tp->intr2_enabled);
-+      if (status3 & ~tp->intr3_enabled)
-+              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status3, tp->intr3_enabled);
-+      if (status4 & ~tp->intr4_enabled)
-+              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status4, tp->intr4_enabled);
-+#endif
-+
-+      if (status0)
-+              writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
-+      if (status1)
-+              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
-+      if (status2)
-+              writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
-+      if (status3)
-+              writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
-+      if (status4)
-+              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-+#if 0
-+      /* handle freeq interrupt first */
-+      if (status4 & tp->intr4_enabled) {
-+              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
-+              {
-+                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
-+                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
-+
-+                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
-+                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
-+                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
-+                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
-+                      printk("\nfreeq int\n");
-+                      toe_gmac_fill_free_q();
-+                      tp->sw_fq_empty_cnt++;
-+
-+              }
-+      }
-+#endif
-+      // Interrupt Status 1
-+      if (status1 & tp->intr1_enabled)
-+      {
-+              #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
-+              #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
-+              // Handle GMAC 0/1 HW Tx queue 0-3 EOF events
-+              // Only count
-+              // TOE, Classification, and default queues interrupts are handled by ISR
-+              // because they should pass packets to upper layer
-+              if (tp->port_id == 0)
-+              {
-+                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
-+                      {
-+                              if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
-+                                      tp->hwtxq[3].eof_cnt++;
-+                              if (status1 & GMAC0_HWTQ02_EOF_INT_BIT)
-+                                      tp->hwtxq[2].eof_cnt++;
-+                              if (status1 & GMAC0_HWTQ01_EOF_INT_BIT)
-+                                      tp->hwtxq[1].eof_cnt++;
-+                              if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
-+                                      tp->hwtxq[0].eof_cnt++;
-+                      }
-+                              if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
-+                              {
-+                                      if (likely(netif_rx_schedule_prep(dev)))
-+                              {
-+                                      unsigned int data32;
-+                                      // disable GMAC-0 rx interrupt
-+                                      // class-Q & TOE-Q are implemented in future
-+                                      //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                      //data32 &= ~DEFAULT_Q0_INT_BIT;
-+                                              //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                              //printk("\%s: DEFAULT_Q0_INT_BIT===================>>>>>>>>>>>>\n",__func__);
-+                                              writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                              //tp->total_q_cnt_napi=0;
-+                                              //rx_time = jiffies;
-+                                              //rx_old_bytes = isPtr->rx_bytes;
-+                              __netif_rx_schedule(dev);
-+                              }
-+                      }
-+              }
-+              else if (tp->port_id == 1)
-+              {
-+                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
-+                      {
-+                              if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
-+                                      tp->hwtxq[3].eof_cnt++;
-+                              if (status1 & GMAC1_HWTQ12_EOF_INT_BIT)
-+                                      tp->hwtxq[2].eof_cnt++;
-+                              if (status1 & GMAC1_HWTQ11_EOF_INT_BIT)
-+                                      tp->hwtxq[1].eof_cnt++;
-+                              if (status1 & GMAC1_HWTQ10_EOF_INT_BIT)
-+                                      tp->hwtxq[0].eof_cnt++;
-+                      }
-+
-+                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
-+                      {
-+                              if (likely(netif_rx_schedule_prep(dev)))
-+                      {
-+                              unsigned int data32;
-+                              // disable GMAC-0 rx interrupt
-+                              // class-Q & TOE-Q are implemented in future
-+                              //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                              //data32 &= ~DEFAULT_Q1_INT_BIT;
-+                                      //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                      //printk("\%s: 1111111111--->DEFAULT_Q1_INT_BIT===================>>>>>>>>>>>>\n",__func__);
-+                                      writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                      //tp->total_q_cnt_napi=0;
-+                                      //rx_time = jiffies;
-+                                      //rx_old_bytes = isPtr->rx_bytes;
-+                              __netif_rx_schedule(dev);
-+                      }
-+                      }
-+              }
-+      }
-+
-+      // Interrupt Status 0
-+      if (status0 & tp->intr0_enabled)
-+      {
-+              #define ERR_INTR_BITS   (GMAC0_TXDERR_INT_BIT | GMAC0_TXPERR_INT_BIT |  \
-+                                                               GMAC1_TXDERR_INT_BIT | GMAC1_TXPERR_INT_BIT |  \
-+                                                               GMAC0_RXDERR_INT_BIT | GMAC0_RXPERR_INT_BIT |  \
-+                                                               GMAC1_RXDERR_INT_BIT | GMAC1_RXPERR_INT_BIT)
-+
-+              if (status0 &  ERR_INTR_BITS)
-+              {
-+                      if ((status0 & GMAC0_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXDERR_INT_BIT))
-+                      {
-+                              tp->txDerr_cnt[0]++;
-+                              printk("GMAC0 TX AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC0_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXPERR_INT_BIT))
-+                      {
-+                              tp->txPerr_cnt[0]++;
-+                              printk("GMAC0 Tx Descriptor Protocol Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXDERR_INT_BIT))
-+                      {
-+                              tp->txDerr_cnt[1]++;
-+                              printk("GMAC1 Tx AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXPERR_INT_BIT))
-+                      {
-+                              tp->txPerr_cnt[1]++;
-+                              printk("GMAC1 Tx Descriptor Protocol Error!\n");
-+                      }
-+
-+                      if ((status0 & GMAC0_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXDERR_INT_BIT))
-+                      {
-+                              tp->RxDerr_cnt[0]++;
-+                              printk("GMAC0 Rx AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC0_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXPERR_INT_BIT))
-+                      {
-+                              tp->RxPerr_cnt[0]++;
-+                              printk("GMAC0 Rx Descriptor Protocol Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXDERR_INT_BIT))
-+                      {
-+                              tp->RxDerr_cnt[1]++;
-+                              printk("GMAC1 Rx AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXPERR_INT_BIT))
-+                      {
-+                              tp->RxPerr_cnt[1]++;
-+                              printk("GMAC1 Rx Descriptor Protocol Error!\n");
-+                      }
-+              }
-+
-+#ifndef       GMAX_TX_INTR_DISABLED
-+              if (tp->port_id == 1 && netif_running(dev) &&
-+                      (((status0 & GMAC1_SWTQ10_FIN_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_FIN_INT_BIT))
-+                      ||
-+                      ((status0 & GMAC1_SWTQ10_EOF_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_EOF_INT_BIT))))
-+              {
-+                      toe_gmac_tx_complete(&toe_private_data.gmac[1], 0, dev, 1);
-+              }
-+
-+              if (tp->port_id == 0 && netif_running(dev) &&
-+                      (((status0 & GMAC0_SWTQ00_FIN_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_FIN_INT_BIT))
-+                      ||
-+                      ((status0 & GMAC0_SWTQ00_EOF_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_EOF_INT_BIT))))
-+              {
-+                      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
-+              }
-+#endif
-+      }
-+      // Interrupt Status 4
-+      if (status4 & tp->intr4_enabled)
-+      {
-+              #define G1_INTR4_BITS           (0xff000000)
-+              #define G0_INTR4_BITS           (0x00ff0000)
-+
-+              if (tp->port_id == 0)
-+              {
-+                      if ((status4 & G0_INTR4_BITS) && (tp->intr4_enabled & G0_INTR4_BITS))
-+                      {
-+                              if (status4 & GMAC0_RESERVED_INT_BIT)
-+                                      printk("GMAC0_RESERVED_INT_BIT is ON\n");
-+                              if (status4 & GMAC0_MIB_INT_BIT)
-+                                      tp->mib_full_cnt++;
-+                              if (status4 & GMAC0_RX_PAUSE_ON_INT_BIT)
-+                                      tp->rx_pause_on_cnt++;
-+                              if (status4 & GMAC0_TX_PAUSE_ON_INT_BIT)
-+                                      tp->tx_pause_on_cnt++;
-+                              if (status4 & GMAC0_RX_PAUSE_OFF_INT_BIT)
-+                                      tp->rx_pause_off_cnt++;
-+                              if (status4 & GMAC0_TX_PAUSE_OFF_INT_BIT)
-+                                      tp->rx_pause_off_cnt++;
-+                              if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
-+                                      tp->rx_overrun_cnt++;
-+                              if (status4 & GMAC0_STATUS_CHANGE_INT_BIT)
-+                                      tp->status_changed_cnt++;
-+                      }
-+              }
-+              else if (tp->port_id == 1)
-+              {
-+                      if ((status4 & G1_INTR4_BITS) && (tp->intr4_enabled & G1_INTR4_BITS))
-+                      {
-+                              if (status4 & GMAC1_RESERVED_INT_BIT)
-+                                      printk("GMAC1_RESERVED_INT_BIT is ON\n");
-+                              if (status4 & GMAC1_MIB_INT_BIT)
-+                                      tp->mib_full_cnt++;
-+                              if (status4 & GMAC1_RX_PAUSE_ON_INT_BIT)
-+                              {
-+                                      printk("Gmac pause on\n");
-+                                      tp->rx_pause_on_cnt++;
-+                              }
-+                              if (status4 & GMAC1_TX_PAUSE_ON_INT_BIT)
-+                              {
-+                                      printk("Gmac pause on\n");
-+                                      tp->tx_pause_on_cnt++;
-+                              }
-+                              if (status4 & GMAC1_RX_PAUSE_OFF_INT_BIT)
-+                              {
-+                                      printk("Gmac pause off\n");
-+                                      tp->rx_pause_off_cnt++;
-+                              }
-+                              if (status4 & GMAC1_TX_PAUSE_OFF_INT_BIT)
-+                              {
-+                                      printk("Gmac pause off\n");
-+                                      tp->rx_pause_off_cnt++;
-+                              }
-+                              if (status4 & GMAC1_RX_OVERRUN_INT_BIT)
-+                              {
-+                                      //printk("Gmac Rx Overrun \n");
-+                                      tp->rx_overrun_cnt++;
-+                              }
-+                              if (status4 & GMAC1_STATUS_CHANGE_INT_BIT)
-+                                      tp->status_changed_cnt++;
-+                      }
-+              }
-+      }
-+
-+      //toe_gmac_enable_interrupt(tp->irq);
-+#ifdef IxscriptMate_1518
-+      if (storlink_ctl.pauseoff == 1)
-+      {
-+              GMAC_CONFIG0_T config0;
-+              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              config0.bits.dis_rx = 0;
-+              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+              config0.bits.dis_rx = 0;
-+              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+      }
-+#endif
-+//     enable_irq(gmac_irq[dev_index]);
-+      //printk("gmac_interrupt complete!\n\n");
-+//    return IRQ_RETVAL(handled);
-+      return  IRQ_RETVAL(1);
-+}
-+else
-+{
-+#endif        //endif NAPI
-+
-+
-+      /* disable GMAC interrupt */
-+    toe_gmac_disable_interrupt(tp->irq);
-+
-+//    isPtr->interrupts++;
-+      /* read Interrupt status */
-+      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
-+      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
-+      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
-+      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+      // prompt warning if status bit ON but not enabled
-+#if 0
-+      if (status0 & ~tp->intr0_enabled)
-+              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status0, tp->intr0_enabled);
-+      if (status1 & ~tp->intr1_enabled)
-+              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status1, tp->intr1_enabled);
-+      if (status2 & ~tp->intr2_enabled)
-+              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status2, tp->intr2_enabled);
-+      if (status3 & ~tp->intr3_enabled)
-+              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status3, tp->intr3_enabled);
-+      if (status4 & ~tp->intr4_enabled)
-+              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
-+                              status4, tp->intr4_enabled);
-+#endif
-+#define       INTERRUPT_SELECT                        1
-+      if (status0)
-+              writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
-+      if (status1)
-+              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
-+      if (status2)
-+              writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
-+      if (status3)
-+              writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
-+      if (status4)
-+              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-+
-+      /* handle freeq interrupt first */
-+      if (status4 & tp->intr4_enabled) {
-+              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
-+              {
-+                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
-+                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
-+
-+                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
-+                      //      SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
-+                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
-+                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
-+                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
-+                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
-+                      printk("\nfreeq int\n");
-+                      toe_gmac_fill_free_q();
-+                      tp->sw_fq_empty_cnt++;
-+
-+                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
-+                              SWFQ_EMPTY_INT_BIT);
-+              }
-+      }
-+
-+      // Interrupt Status 1
-+      if (status1 & tp->intr1_enabled)
-+      {
-+              #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
-+              #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
-+              // Handle GMAC 0/1 HW Tx queue 0-3 EOF events
-+              // Only count
-+              // TOE, Classification, and default queues interrupts are handled by ISR
-+              // because they should pass packets to upper layer
-+              if (tp->port_id == 0)
-+              {
-+#ifndef       INTERRUPT_SELECT
-+                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
-+                      {
-+                              if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
-+                                      tp->hwtxq[3].eof_cnt++;
-+                              if (status1 & GMAC0_HWTQ02_EOF_INT_BIT)
-+                                      tp->hwtxq[2].eof_cnt++;
-+                              if (status1 & GMAC0_HWTQ01_EOF_INT_BIT)
-+                                      tp->hwtxq[1].eof_cnt++;
-+                              if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
-+                                      tp->hwtxq[0].eof_cnt++;
-+#endif        //INTERRUPT_SELECT
-+#ifndef       INTERRUPT_SELECT
-+                      }
-+#endif        //INTERRUPT_SELECT
-+                      if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
-+                      {
-+                              tp->default_q_intr_cnt++;
-+                              toe_gmac_handle_default_rxq(dev, tp);
-+                      }
-+#ifdef CONFIG_SL351x_RXTOE
-+                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
-+                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
-+                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
-+                              toe_gmac_handle_toeq(dev, tp, status1);
-+                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
-+                      }
-+#endif
-+              }
-+              else if (tp->port_id == 1)
-+              {
-+#ifndef       INTERRUPT_SELECT
-+                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
-+                      {
-+                              if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
-+                                      tp->hwtxq[3].eof_cnt++;
-+                              if (status1 & GMAC1_HWTQ12_EOF_INT_BIT)
-+                                      tp->hwtxq[2].eof_cnt++;
-+                              if (status1 & GMAC1_HWTQ11_EOF_INT_BIT)
-+                                      tp->hwtxq[1].eof_cnt++;
-+                              if (status1 & GMAC1_HWTQ10_EOF_INT_BIT)
-+                                      tp->hwtxq[0].eof_cnt++;
-+#endif        //INTERRUPT_SELECT
-+#ifndef       INTERRUPT_SELECT
-+                      }
-+#endif        //INTERRUPT_SELECT
-+                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
-+                      {
-+                              tp->default_q_intr_cnt++;
-+                              toe_gmac_handle_default_rxq(dev, tp);
-+                      }
-+#ifdef CONFIG_SL351x_RXTOE
-+                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
-+                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
-+                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
-+                              toe_gmac_handle_toeq(dev, tp, status1);
-+                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
-+                      }
-+#endif
-+              }
-+      }
-+
-+
-+      // Interrupt Status 0
-+      if (status0 & tp->intr0_enabled)
-+      {
-+
-+              #define ERR_INTR_BITS   (GMAC0_TXDERR_INT_BIT | GMAC0_TXPERR_INT_BIT |  \
-+                                                               GMAC1_TXDERR_INT_BIT | GMAC1_TXPERR_INT_BIT |  \
-+                                                               GMAC0_RXDERR_INT_BIT | GMAC0_RXPERR_INT_BIT |  \
-+                                                               GMAC1_RXDERR_INT_BIT | GMAC1_RXPERR_INT_BIT)
-+#ifndef       INTERRUPT_SELECT
-+              if (status0 &  ERR_INTR_BITS)
-+              {
-+                      if ((status0 & GMAC0_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXDERR_INT_BIT))
-+                      {
-+                              tp->txDerr_cnt[0]++;
-+                              printk("GMAC0 TX AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC0_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXPERR_INT_BIT))
-+                      {
-+                              tp->txPerr_cnt[0]++;
-+                              printk("GMAC0 Tx Descriptor Protocol Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXDERR_INT_BIT))
-+                      {
-+                              tp->txDerr_cnt[1]++;
-+                              printk("GMAC1 Tx AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXPERR_INT_BIT))
-+                      {
-+                              tp->txPerr_cnt[1]++;
-+                              printk("GMAC1 Tx Descriptor Protocol Error!\n");
-+                      }
-+
-+                      if ((status0 & GMAC0_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXDERR_INT_BIT))
-+                      {
-+                              tp->RxDerr_cnt[0]++;
-+                              printk("GMAC0 Rx AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC0_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXPERR_INT_BIT))
-+                      {
-+                              tp->RxPerr_cnt[0]++;
-+                              printk("GMAC0 Rx Descriptor Protocol Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXDERR_INT_BIT))
-+                      {
-+                              tp->RxDerr_cnt[1]++;
-+                              printk("GMAC1 Rx AHB Bus Error!\n");
-+                      }
-+                      if ((status0 & GMAC1_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXPERR_INT_BIT))
-+                      {
-+                              tp->RxPerr_cnt[1]++;
-+                              printk("GMAC1 Rx Descriptor Protocol Error!\n");
-+                      }
-+              }
-+#endif        //INTERRUPT_SELECT
-+#ifndef       GMAX_TX_INTR_DISABLED
-+              if (tp->port_id == 1 && netif_running(dev) &&
-+                      (((status0 & GMAC1_SWTQ10_FIN_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_FIN_INT_BIT))
-+                      ||
-+                      ((status0 & GMAC1_SWTQ10_EOF_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_EOF_INT_BIT))))
-+              {
-+                      toe_gmac_tx_complete(&toe_private_data.gmac[1], 0, dev, 1);
-+              }
-+
-+              if (tp->port_id == 0 && netif_running(dev) &&
-+                      (((status0 & GMAC0_SWTQ00_FIN_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_FIN_INT_BIT))
-+                      ||
-+                      ((status0 & GMAC0_SWTQ00_EOF_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_EOF_INT_BIT))))
-+              {
-+                      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
-+              }
-+#endif
-+              // clear enabled status bits
-+      }
-+      // Interrupt Status 4
-+#ifndef       INTERRUPT_SELECT
-+      if (status4 & tp->intr4_enabled)
-+      {
-+              #define G1_INTR4_BITS           (0xff000000)
-+              #define G0_INTR4_BITS           (0x00ff0000)
-+
-+              if (tp->port_id == 0)
-+              {
-+                      if ((status4 & G0_INTR4_BITS) && (tp->intr4_enabled & G0_INTR4_BITS))
-+                      {
-+                              if (status4 & GMAC0_RESERVED_INT_BIT)
-+                                      printk("GMAC0_RESERVED_INT_BIT is ON\n");
-+                              if (status4 & GMAC0_MIB_INT_BIT)
-+                                      tp->mib_full_cnt++;
-+                              if (status4 & GMAC0_RX_PAUSE_ON_INT_BIT)
-+                                      tp->rx_pause_on_cnt++;
-+                              if (status4 & GMAC0_TX_PAUSE_ON_INT_BIT)
-+                                      tp->tx_pause_on_cnt++;
-+                              if (status4 & GMAC0_RX_PAUSE_OFF_INT_BIT)
-+                                      tp->rx_pause_off_cnt++;
-+                              if (status4 & GMAC0_TX_PAUSE_OFF_INT_BIT)
-+                                      tp->rx_pause_off_cnt++;
-+                              if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
-+                                      tp->rx_overrun_cnt++;
-+                              if (status4 & GMAC0_STATUS_CHANGE_INT_BIT)
-+                                      tp->status_changed_cnt++;
-+                      }
-+              }
-+              else if (tp->port_id == 1)
-+              {
-+                      if ((status4 & G1_INTR4_BITS) && (tp->intr4_enabled & G1_INTR4_BITS))
-+                      {
-+                              if (status4 & GMAC1_RESERVED_INT_BIT)
-+                                      printk("GMAC1_RESERVED_INT_BIT is ON\n");
-+                              if (status4 & GMAC1_MIB_INT_BIT)
-+                                      tp->mib_full_cnt++;
-+                              if (status4 & GMAC1_RX_PAUSE_ON_INT_BIT)
-+                              {
-+                                      //printk("Gmac pause on\n");
-+                                      tp->rx_pause_on_cnt++;
-+                              }
-+                              if (status4 & GMAC1_TX_PAUSE_ON_INT_BIT)
-+                              {
-+                                      //printk("Gmac pause on\n");
-+                                      tp->tx_pause_on_cnt++;
-+                              }
-+                              if (status4 & GMAC1_RX_PAUSE_OFF_INT_BIT)
-+                              {
-+                                      //printk("Gmac pause off\n");
-+                                      tp->rx_pause_off_cnt++;
-+                              }
-+                              if (status4 & GMAC1_TX_PAUSE_OFF_INT_BIT)
-+                              {
-+                                      //printk("Gmac pause off\n");
-+                                      tp->rx_pause_off_cnt++;
-+                              }
-+                              if (status4 & GMAC1_RX_OVERRUN_INT_BIT)
-+                              {
-+                                      //printk("Gmac Rx Overrun \n");
-+                                      tp->rx_overrun_cnt++;
-+                              }
-+                              if (status4 & GMAC1_STATUS_CHANGE_INT_BIT)
-+                                      tp->status_changed_cnt++;
-+                      }
-+              }
-+#if 0
-+              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
-+              {
-+                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+//                    mac_stop_rxdma(tp->sc);
-+                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
-+                              tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
-+
-+                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
-+                              SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
-+                      toe_gmac_fill_free_q();
-+                      tp->sw_fq_empty_cnt++;
-+
-+                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
-+                              SWFQ_EMPTY_INT_BIT);
-+//#if 0
-+/*                    if (netif_running(dev))
-+                              toe_gmac_handle_default_rxq(dev, tp);
-+                      printk("SWFQ_EMPTY_INT_BIT is ON!\n");  // should not be happened */
-+//#endif
-+              }
-+#endif
-+      }
-+#endif        //INTERRUPT_SELECT
-+      toe_gmac_enable_interrupt(tp->irq);
-+//enable gmac rx function when do RFC 2544
-+#ifdef IxscriptMate_1518
-+      if (storlink_ctl.pauseoff == 1)
-+      {
-+              GMAC_CONFIG0_T config0;
-+              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              config0.bits.dis_rx = 0;
-+              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+              config0.bits.dis_rx = 0;
-+              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+      }
-+#endif
-+      //printk("gmac_interrupt complete!\n\n");
-+//    return IRQ_RETVAL(handled);
-+      return  IRQ_RETVAL(1);
-+#ifdef CONFIG_SL_NAPI
-+}
-+#endif
-+}
-+
-+/*----------------------------------------------------------------------
-+*     toe_gmac_handle_default_rxq
-+*     (1) Get rx Buffer for default Rx queue
-+*     (2) notify or call upper-routine to handle it
-+*     (3) get a new buffer and insert it into SW free queue
-+*     (4) Note: The SW free queue Read-Write Pointer should be locked when accessing
-+*----------------------------------------------------------------------*/
-+//static inline void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
-+static void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
-+{
-+      TOE_INFO_T                      *toe;
-+    GMAC_RXDESC_T     *curr_desc;
-+      struct sk_buff          *skb;
-+    DMA_RWPTR_T                       rwptr;
-+      unsigned int            pkt_size;
-+      int                                     max_cnt;
-+      unsigned int        desc_count;
-+      unsigned int        good_frame, chksum_status, rx_status;
-+      struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
-+
-+//when do ixia RFC 2544 test and packet size is select 1518 bytes,disable gmace rx function immediately after one interrupt come in.
-+#ifdef IxscriptMate_1518
-+      if (storlink_ctl.pauseoff == 1)
-+      {
-+              GMAC_CONFIG0_T config0;
-+              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              config0.bits.dis_rx = 1;
-+              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+              config0.bits.dis_rx = 1;
-+              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+      }
-+#endif
-+      rwptr.bits32 = readl(&tp->default_qhdr->word1);
-+#if 0
-+      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
-+      {
-+              mac_stop_txdma((struct net_device *)tp->dev);
-+              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
-+                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
-+              while(1);
-+      }
-+#endif
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      max_cnt = DEFAULT_RXQ_MAX_CNT;
-+      while ((--max_cnt) && rwptr.bits.rptr != rwptr.bits.wptr)
-+//    while (rwptr.bits.rptr != rwptr.bits.wptr)
-+      {
-+//if packet size is not 1518 for RFC 2544,enable gmac rx function.The other packet size have RX workaround.
-+#ifdef IxscriptMate_1518
-+      if (storlink_ctl.pauseoff == 1)
-+              {
-+                      if (pkt_size != 1514)
-+                      {
-+                                              GMAC_CONFIG0_T config0;
-+                                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                                              config0.bits.dis_rx = 0;
-+                                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                                              config0.bits.dis_rx = 0;
-+                                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                      }
-+              }
-+#endif
-+      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
-+//            consistent_sync(curr_desc, sizeof(GMAC_RXDESC_T), PCI_DMA_FROMDEVICE);
-+              tp->default_q_cnt++;
-+      tp->rx_curr_desc = (unsigned int)curr_desc;
-+      rx_status = curr_desc->word0.bits.status;
-+      chksum_status = curr_desc->word0.bits.chksum_status;
-+      tp->rx_status_cnt[rx_status]++;
-+      tp->rx_chksum_cnt[chksum_status]++;
-+        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
-+              desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
-+              good_frame=1;
-+              if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
-+                      || (pkt_size < 60)
-+                  || (chksum_status & 0x4)
-+                      || rx_status)
-+              {
-+                      good_frame = 0;
-+                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
-+                              printk("%s::derr (GMAC-%d)!!!\n", __func__, tp->port_id);
-+                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_perr)
-+                              printk("%s::perr (GMAC-%d)!!!\n", __func__, tp->port_id);
-+                      if (rx_status)
-+                      {
-+                              if (rx_status == 4 || rx_status == 7)
-+                                      isPtr->rx_crc_errors++;
-+//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
-+                      }
-+#ifdef SL351x_GMAC_WORKAROUND
-+                      else if (pkt_size < 60)
-+                      {
-+                              if (tp->short_frames_cnt < GMAC_SHORT_FRAME_THRESHOLD)
-+                                      tp->short_frames_cnt++;
-+                              if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
-+                              {
-+                                      GMAC_CONFIG0_T config0;
-+                                      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                                      config0.bits.dis_rx = 1;
-+                                      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                                      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                                      config0.bits.dis_rx = 1;
-+                                      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                              }
-+                      }
-+#endif
-+//                    if (chksum_status)
-+//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
-+                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-+                      dev_kfree_skb_irq(skb);
-+              }
-+              if (good_frame)
-+              {
-+                      if (curr_desc->word0.bits.drop)
-+                              printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
-+//                    if (chksum_status)
-+//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
-+
-+              /* get frame information from the first descriptor of the frame */
-+#ifdef SL351x_GMAC_WORKAROUND
-+                      if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
-+                      {
-+                              GMAC_CONFIG0_T config0;
-+                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                              config0.bits.dis_rx = 0;
-+                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                              config0.bits.dis_rx = 0;
-+                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                      }
-+                      tp->short_frames_cnt = 0;
-+#endif
-+                      isPtr->rx_packets++;
-+                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr - SKB_RESERVE_BYTES)));
-+                      if (!skb)
-+                      {
-+                              printk("Fatal Error!!skb==NULL\n");
-+                              goto next_rx;
-+                      }
-+                      tp->curr_rx_skb = skb;
-+                      // consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
-+
-+      //              curr_desc->word2.buf_adr = 0;
-+
-+                      skb_reserve (skb, RX_INSERT_BYTES);     /* 16 byte align the IP fields. */
-+                      skb_put(skb, pkt_size);
-+                      skb->dev = dev;
-+                      if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
-+                      {
-+                              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+#ifdef CONFIG_SL351x_NAT
-+                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
-+                              {
-+                                      struct iphdr    *ip_hdr;
-+                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
-+                                      sl351x_nat_input(skb,
-+                                                                      tp->port_id,
-+                                                                      (void *)curr_desc->word3.bits.l3_offset,
-+                                                                      (void *)curr_desc->word3.bits.l4_offset);
-+                              }
-+#endif
-+                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-+#if 0
-+#ifdef CONFIG_SL351x_RXTOE
-+                              if (storlink_ctl.rx_max_pktsize) {
-+                                      struct iphdr    *ip_hdr;
-+                                      struct tcphdr   *tcp_hdr;
-+                                      int ip_hdrlen;
-+
-+                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
-+                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
-+                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
-+                                              ip_hdrlen = ip_hdr->ihl << 2;
-+                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
-+                                              if (tcp_hdr->syn) {
-+                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
-+                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
-+                                                      TCP_SKB_CB(skb)->connection = connection;
-+                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
-+                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
-+                                                      //                      __func__, skb->data, connection, connection->mode);
-+                                              }
-+                                      }
-+                              }
-+#endif
-+#endif
-+                      }
-+                      else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
-+                      {
-+                              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+#ifdef CONFIG_SL351x_NAT
-+                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
-+                              {
-+                                      struct iphdr            *ip_hdr;
-+                                      //struct tcphdr         *tcp_hdr;
-+                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
-+                                      //tcp_hdr = (struct tcphdr *)&(skb->data[curr_desc->word3.bits.l4_offset]);
-+                                      if (ip_hdr->protocol == IPPROTO_UDP)
-+                                      {
-+                                              sl351x_nat_input(skb,
-+                                                                              tp->port_id,
-+                                                                              (void *)curr_desc->word3.bits.l3_offset,
-+                                                                              (void *)curr_desc->word3.bits.l4_offset);
-+                                      }
-+                                      else if (ip_hdr->protocol == IPPROTO_GRE)
-+                                      {
-+                                              sl351x_nat_input(skb,
-+                                                                      tp->port_id,
-+                                                                      (void *)curr_desc->word3.bits.l3_offset,
-+                                                                      (void *)curr_desc->word3.bits.l4_offset);
-+                                      }
-+                              }
-+#endif
-+                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-+                      }
-+                      else
-+                      {
-+                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-+                      }
-+
-+                      netif_rx(skb);  /* socket rx */
-+                      dev->last_rx = jiffies;
-+
-+                      isPtr->rx_bytes += pkt_size;
-+
-+        }
-+
-+next_rx:
-+              // advance one for Rx default Q 0/1
-+              rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
-+              SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
-+      tp->rx_rwptr.bits32 = rwptr.bits32;
-+
-+              toe_gmac_fill_free_q();
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_get_phy_vendor
-+*----------------------------------------------------------------------*/
-+static unsigned int gmac_get_phy_vendor(int phy_addr)
-+{
-+    unsigned int      reg_val;
-+    reg_val=(mii_read(phy_addr,0x02) << 16) + mii_read(phy_addr,0x03);
-+    return reg_val;
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_set_phy_status
-+*----------------------------------------------------------------------*/
-+void gmac_set_phy_status(struct net_device *dev)
-+{
-+      GMAC_INFO_T *tp = dev->priv;
-+      GMAC_STATUS_T   status;
-+      unsigned int    reg_val, ability,wan_port_id;
-+      unsigned int    i = 0;
-+
-+#ifdef VITESSE_G5SWITCH
-+      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1)){
-+#if 0
-+              rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
-+              rcv_mask |= 0x4F;
-+              for(i=0;i<4;i++){
-+                      reg_val = BIT(26)|(i<<21)|(10<<16);
-+                      SPI_write(3,0,1,reg_val);
-+                      msleep(10);
-+                      reg_val = SPI_read(3,0,2);
-+                      if(reg_val & 0x0c00){
-+                              printk("Port%d:Giga mode\n",i);
-+                              SPI_write(1,i,0x00,0x300701B1);
-+                              SPI_write(1,i,0x00,0x10070181);
-+                              switch_pre_link[i]=LINK_UP;
-+                              switch_pre_speed[i]=GMAC_SPEED_1000;
-+                      }
-+                      else{
-+                              reg_val = BIT(26)|(i<<21)|(5<<16);
-+                              SPI_write(3,0,1,reg_val);
-+                              msleep(10);
-+                              ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5;
-+                              if ((ability & 0x0C)) /* 100M full duplex */
-+                              {
-+                                      SPI_write(1,i,0x00,0x30050472);
-+                                      SPI_write(1,i,0x00,0x10050442);
-+                                      printk("Port%d:100M\n",i);
-+                                      switch_pre_link[i]=LINK_UP;
-+                              switch_pre_speed[i]=GMAC_SPEED_100;
-+                              }
-+                              else if((ability & 0x03)) /* 10M full duplex */
-+                              {
-+                                      SPI_write(1,i,0x00,0x30050473);
-+                                      SPI_write(1,i,0x00,0x10050443);
-+                                      printk("Port%d:10M\n",i);
-+                                      switch_pre_link[i]=LINK_UP;
-+                                      switch_pre_speed[i]=GMAC_SPEED_10;
-+                              }
-+                              else{
-+                                      SPI_write(1,i,0x00,BIT(16));                    // disable RX
-+                                      SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
-+                                      while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
-+                                              msleep(1);
-+
-+                                      SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
-+                                      switch_pre_link[i]=LINK_DOWN;
-+                                      switch_pre_speed[i]=GMAC_SPEED_10;
-+                                      rcv_mask &= ~BIT(i);
-+                                      SPI_write(2,0,0x10,rcv_mask);                   // Disable Receive
-+                              }
-+                      }
-+              }
-+#endif
-+              gmac_get_switch_status(dev);
-+              gmac_write_reg(tp->base_addr, GMAC_STATUS, 0x7d, 0x0000007f);
-+//            SPI_write(2,0,0x10,rcv_mask);                   // Enable Receive
-+              return ;
-+      }
-+#endif
-+
-+      reg_val = gmac_get_phy_vendor(tp->phy_addr);
-+      printk("GMAC-%d Addr %d Vendor ID: 0x%08x\n", tp->port_id, tp->phy_addr, reg_val);
-+
-+      switch (tp->phy_mode)
-+      {
-+              case GMAC_PHY_GMII:
-+              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
-+              #ifdef CONFIG_SL3516_ASIC
-+              mii_write(tp->phy_addr,0x09,0x0300); /* advertise 1000M full/half duplex */
-+              #else
-+              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M full/half duplex */
-+              #endif
-+              break;
-+              case GMAC_PHY_RGMII_100:
-+              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
-+              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M */
-+              break;
-+              case GMAC_PHY_RGMII_1000:
-+              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
-+              #ifdef CONFIG_SL3516_ASIC
-+              mii_write(tp->phy_addr,0x09,0x0300); /* advertise 1000M full/half duplex */
-+              #else
-+              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M full/half duplex */
-+              #endif
-+              break;
-+              case GMAC_PHY_MII:
-+              default:
-+              mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
-+              mii_write(tp->phy_addr,0x09,0x0000); /* advertise no 1000M */
-+              break;
-+      }
-+
-+      mii_write(tp->phy_addr,0x18,0x0041);    // Phy active led
-+      if (tp->auto_nego_cfg)
-+      {
-+              reg_val = 0x1200 | (1 << 15);
-+              mii_write(tp->phy_addr,0x00,reg_val); /* Enable and Restart Auto-Negotiation */
-+              mdelay(500);
-+              reg_val &= ~(1 << 15);
-+              mii_write(tp->phy_addr, 0x00, reg_val);
-+      }
-+      else
-+      {
-+              reg_val = 0;
-+              reg_val |= (tp->full_duplex_cfg) ? (1 << 8) : 0;
-+              reg_val |= (tp->speed_cfg == GMAC_SPEED_1000) ? (1 << 6) : 0;
-+              reg_val |= (tp->speed_cfg == GMAC_SPEED_100) ? (1 << 13) : 0;
-+              mii_write(tp->phy_addr, 0x00, reg_val);
-+              mdelay(100);
-+
-+              reg_val |= (1 << 15);   // Reset PHY;
-+              mii_write(tp->phy_addr, 0x00, reg_val);
-+      }
-+
-+      status.bits32 = 0;
-+      /* set PHY operation mode */
-+      status.bits.mii_rmii = tp->phy_mode;
-+      status.bits.reserved = 1;
-+      mdelay(100);
-+      while (((reg_val=mii_read(tp->phy_addr,0x01)) & 0x00000004)!=0x04)
-+      {
-+              msleep(100);
-+              i++;
-+              if (i > 30)
-+              break;
-+      }
-+      if (i>30)
-+      {
-+              tp->pre_phy_status = LINK_DOWN;
-+              status.bits.link = LINK_DOWN;
-+              //              clear_bit(__LINK_STATE_START, &dev->state);
-+              printk("Link Down (0x%04x) ", reg_val);
-+              if(Giga_switch == 1)
-+              {
-+                              wan_port_id = 1;
-+#ifdef CONFIG_SL351x_SYSCTL
-+                              storlink_ctl.link[ wan_port_id] = 0;
-+#endif
-+              }
-+              else
-+              {
-+#ifdef CONFIG_SL351x_SYSCTL
-+                              storlink_ctl.link[ tp->port_id] = 0;
-+#endif
-+              }
-+      }
-+      else
-+      {
-+              tp->pre_phy_status = LINK_UP;
-+              status.bits.link = LINK_UP;
-+              //              set_bit(__LINK_STATE_START, &dev->state);
-+              printk("Link Up (0x%04x) ",reg_val);
-+              if(Giga_switch == 1)
-+              {
-+                              wan_port_id = 1;
-+#ifdef CONFIG_SL351x_SYSCTL
-+                              storlink_ctl.link[ wan_port_id] = 1;
-+#endif
-+              }
-+              else
-+              {
-+#ifdef CONFIG_SL351x_SYSCTL
-+                              storlink_ctl.link[ tp->port_id] = 1;
-+#endif
-+              }
-+      }
-+      //    value = mii_read(PHY_ADDR,0x05);
-+
-+      ability = (mii_read(tp->phy_addr,0x05) & 0x05E0) >> 5;
-+
-+      //#ifdef CONFIG_SL3516_ASIC
-+      reg_val = mii_read(tp->phy_addr,10);
-+      printk("MII REG 10 = 0x%x\n",reg_val);
-+
-+      if ((reg_val & 0x0800) == 0x0800)
-+      {
-+              status.bits.duplex = 1;
-+              status.bits.speed = 2;
-+              if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
-+              status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
-+
-+              printk(" 1000M/Full \n");
-+      }
-+      else if ((reg_val & 0x0400) == 0x0400)
-+      {
-+              status.bits.duplex = 0;
-+              status.bits.speed = 2;
-+              if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
-+              status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
-+
-+              printk(" 1000M/Half \n");
-+      }
-+      //#endif
-+      else
-+      {
-+              #ifdef CONFIG_SL3516_ASIC
-+              if (status.bits.mii_rmii == GMAC_PHY_RGMII_1000)
-+              status.bits.mii_rmii = GMAC_PHY_RGMII_100;
-+              #endif
-+              printk("MII REG 5 (bit 5:15) = 0x%x\n", ability);
-+              if ((ability & 0x08)==0x08) /* 100M full duplex */
-+              {
-+                      status.bits.duplex = 1;
-+                      status.bits.speed = 1;
-+                      printk(" 100M/Full\n");
-+
-+              }
-+              else if ((ability & 0x04)==0x04) /* 100M half duplex */
-+              {
-+                      status.bits.duplex = 0;
-+                      status.bits.speed = 1;
-+                      printk(" 100M/Half\n");
-+
-+              }
-+              else if ((ability & 0x02)==0x02) /* 10M full duplex */
-+              {
-+                      status.bits.duplex = 1;
-+                      status.bits.speed = 0;
-+                      printk(" 10M/Full\n");
-+
-+              }
-+              else if ((ability & 0x01)==0x01) /* 10M half duplex */
-+              {
-+                      status.bits.duplex = 0;
-+                      status.bits.speed = 0;
-+                      printk(" 10M/Half\n");
-+
-+              }
-+      }
-+      if ((ability & 0x20)==0x20)
-+      {
-+              tp->flow_control_enable = 1;
-+              printk("Flow Control Enable.\n");
-+      }
-+      else
-+      {
-+              tp->flow_control_enable = 0;
-+              printk("Flow Control Disable.\n");
-+      }
-+      tp->full_duplex_status = status.bits.duplex;
-+      tp->speed_status = status.bits.speed;
-+      if (!tp->auto_nego_cfg)
-+      {
-+              status.bits.duplex = tp->full_duplex_cfg;
-+              status.bits.speed = tp->speed_cfg;
-+      }
-+      toe_gmac_disable_tx_rx(dev);
-+      mdelay(10);
-+      gmac_write_reg(tp->base_addr, GMAC_STATUS, status.bits32, 0x0000007f);
-+      toe_gmac_enable_tx_rx(dev);
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_phy_thread
-+*----------------------------------------------------------------------*/
-+static int gmac_phy_thread (void *data)
-+{
-+      struct net_device   *dev = data;
-+      GMAC_INFO_T *tp = dev->priv;
-+      unsigned long       timeout;
-+
-+    daemonize("%s", dev->name);
-+      allow_signal(SIGTERM);
-+//    reparent_to_init();
-+//    spin_lock_irq(&current->sigmask_lock);
-+//    sigemptyset(&current->blocked);
-+//    recalc_sigpending(current);
-+//    spin_unlock_irq(&current->sigmask_lock);
-+//    strncpy (current->comm, dev->name, sizeof(current->comm) - 1);
-+//    current->comm[sizeof(current->comm) - 1] = '\0';
-+
-+      while (1)
-+      {
-+          timeout = next_tick;
-+              do
-+              {
-+                      timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
-+              } while (!signal_pending (current) && (timeout > 0));
-+
-+              if (signal_pending (current))
-+              {
-+//                    spin_lock_irq(&current->sigmask_lock);
-+                      flush_signals(current);
-+//                    spin_unlock_irq(&current->sigmask_lock);
-+              }
-+
-+              if (tp->time_to_die)
-+                      break;
-+
-+              // printk("%s : Polling MAC %d PHY Status...\n",__func__, tp->port_id);
-+              rtnl_lock ();
-+              if (tp->auto_nego_cfg){
-+#ifdef VITESSE_G5SWITCH
-+                      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1))
-+                              gmac_get_switch_status(dev);
-+                      else
-+#endif
-+                              gmac_get_phy_status(dev); //temp remove
-+              }
-+              rtnl_unlock ();
-+      }
-+      complete_and_exit (&tp->thr_exited, 0);
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_get_switch_status
-+*----------------------------------------------------------------------*/
-+#ifdef VITESSE_G5SWITCH
-+void gmac_get_switch_status(struct net_device *dev)
-+{
-+      GMAC_INFO_T *tp = dev->priv;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+      unsigned int    switch_port_id;
-+      int get_link=0;
-+
-+      get_link = Get_Set_port_status();
-+      if(get_link){                           // link
-+              if(ever_dwon){
-+                      ever_dwon = 0;
-+                      toe_gmac_enable_tx_rx(dev);
-+                      netif_wake_queue(dev);
-+                      set_bit(__LINK_STATE_START, &dev->state);
-+              }
-+      }
-+      else{                                   // all down
-+              //printk("All link down\n");
-+              ever_dwon=1;
-+              netif_stop_queue(dev);
-+              toe_gmac_disable_tx_rx(dev);
-+              clear_bit(__LINK_STATE_START, &dev->state);
-+      }
-+
-+      if ( tp->port_id == 1 )
-+              switch_port_id = 0;
-+#ifdef CONFIG_SL351x_SYSCTL
-+      if (get_link)
-+      {
-+              storlink_ctl.link[switch_port_id] = 1;
-+      }
-+      else
-+      {
-+              storlink_ctl.link[switch_port_id] = 0;
-+      }
-+      if (storlink_ctl.pauseoff == 1)
-+              {
-+                      if (tp->flow_control_enable == 1)
-+                      {
-+                              config0.bits32 = 0;
-+                              config0_mask.bits32 = 0;
-+                              config0.bits.tx_fc_en = 0; /* disable tx flow control */
-+                              config0.bits.rx_fc_en = 0; /* disable rx flow control */
-+                              config0_mask.bits.tx_fc_en = 1;
-+                              config0_mask.bits.rx_fc_en = 1;
-+                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+                              printk("Disable SWITCH Flow Control...\n");
-+                      }
-+                              tp->flow_control_enable = 0;
-+              }
-+              else
-+#endif
-+              {
-+                      if (tp->flow_control_enable == 0)
-+                      {
-+                              config0.bits32 = 0;
-+                              config0_mask.bits32 = 0;
-+                              config0.bits.tx_fc_en = 1; /* enable tx flow control */
-+                              config0.bits.rx_fc_en = 1; /* enable rx flow control */
-+                              config0_mask.bits.tx_fc_en = 1;
-+                              config0_mask.bits.rx_fc_en = 1;
-+                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+                              printk("Enable SWITCH Flow Control...\n");
-+                      }
-+                      tp->flow_control_enable = 1;
-+              }
-+      return ;
-+
-+}
-+#endif
-+
-+/*----------------------------------------------------------------------
-+* gmac_get_phy_status
-+*----------------------------------------------------------------------*/
-+void gmac_get_phy_status(struct net_device *dev)
-+{
-+      GMAC_INFO_T *tp = dev->priv;
-+      GMAC_CONFIG0_T  config0,config0_mask;
-+      GMAC_STATUS_T   status, old_status;
-+      unsigned int    reg_val,ability,wan_port_id;
-+
-+      old_status.bits32 = status.bits32 = gmac_read_reg(tp->base_addr, GMAC_STATUS);
-+
-+
-+      /* read PHY status register */
-+      reg_val = mii_read(tp->phy_addr,0x01);
-+      if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */
-+      {
-+              ability = (mii_read(tp->phy_addr,0x05) & 0x05E0) >> 5;
-+              /* read PHY Auto-Negotiation Link Partner Ability Register */
-+              #ifdef CONFIG_SL3516_ASIC
-+              reg_val = mii_read(tp->phy_addr,10);
-+              if ((reg_val & 0x0800) == 0x0800)
-+              {
-+                      status.bits.duplex = 1;
-+                      status.bits.speed = 2;
-+                      if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
-+                      status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
-+              }
-+              else if ((reg_val & 0x0400) == 0x0400)
-+              {
-+                      status.bits.duplex = 0;
-+                      status.bits.speed = 2;
-+                      if (status.bits.mii_rmii == GMAC_PHY_RGMII_100)
-+                      status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
-+              }
-+              else
-+              #endif
-+              {
-+                      #ifdef CONFIG_SL3516_ASIC
-+                      if (status.bits.mii_rmii == GMAC_PHY_RGMII_1000)
-+                      status.bits.mii_rmii = GMAC_PHY_RGMII_100;
-+                      #endif
-+                      if ((ability & 0x08)==0x08) /* 100M full duplex */
-+                      {
-+                              status.bits.duplex = 1;
-+                              status.bits.speed = 1;
-+                      }
-+                      else if ((ability & 0x04)==0x04) /* 100M half duplex */
-+                      {
-+                              status.bits.duplex = 0;
-+                              status.bits.speed = 1;
-+                      }
-+                      else if ((ability & 0x02)==0x02) /* 10M full duplex */
-+                      {
-+                              status.bits.duplex = 1;
-+                              status.bits.speed = 0;
-+                      }
-+                      else if ((ability & 0x01)==0x01) /* 10M half duplex */
-+                      {
-+                              status.bits.duplex = 0;
-+                              status.bits.speed = 0;
-+                      }
-+              }
-+              status.bits.link = LINK_UP; /* link up */
-+              if(Giga_switch==1)
-+              {
-+                              wan_port_id = 1;
-+#ifdef CONFIG_SL351x_SYSCTL
-+                              storlink_ctl.link[ wan_port_id] = 1;
-+              }
-+              else
-+              {
-+                              storlink_ctl.link[ tp->port_id] = 1;
-+#endif
-+              }
-+              if ((ability & 0x20)==0x20)
-+              {
-+                      if (tp->flow_control_enable == 0)
-+                      {
-+                              config0.bits32 = 0;
-+                              config0_mask.bits32 = 0;
-+                              config0.bits.tx_fc_en = 1; /* enable tx flow control */
-+                              config0.bits.rx_fc_en = 1; /* enable rx flow control */
-+                              config0_mask.bits.tx_fc_en = 1;
-+                              config0_mask.bits.rx_fc_en = 1;
-+                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+                              printk("GMAC-%d Flow Control Enable.\n", tp->port_id);
-+                      }
-+                      tp->flow_control_enable = 1;
-+              }
-+              else
-+              {
-+                      if (tp->flow_control_enable == 1)
-+                      {
-+                              config0.bits32 = 0;
-+                              config0_mask.bits32 = 0;
-+                              config0.bits.tx_fc_en = 0; /* disable tx flow control */
-+                              config0.bits.rx_fc_en = 0; /* disable rx flow control */
-+                              config0_mask.bits.tx_fc_en = 1;
-+                              config0_mask.bits.rx_fc_en = 1;
-+                              gmac_write_reg(tp->base_addr, GMAC_CONFIG0,config0.bits32,config0_mask.bits32);
-+                              printk("GMAC-%d Flow Control Disable.\n", tp->port_id);
-+                      }
-+                      tp->flow_control_enable = 0;
-+              }
-+
-+              if (tp->pre_phy_status == LINK_DOWN)
-+              {
-+                      printk("GMAC-%d LINK_UP......\n",tp->port_id);
-+                      tp->pre_phy_status = LINK_UP;
-+              }
-+      }
-+      else
-+      {
-+              status.bits.link = LINK_DOWN; /* link down */
-+              if(Giga_switch == 1)
-+              {
-+                              wan_port_id = 1;
-+#ifdef CONFIG_SL351x_SYSCTL
-+                              storlink_ctl.link[ wan_port_id] = 0;
-+              }
-+              else
-+              {
-+                              storlink_ctl.link[ tp->port_id] = 0;
-+#endif
-+              }
-+              if (tp->pre_phy_status == LINK_UP)
-+              {
-+                      printk("GMAC-%d LINK_Down......\n",tp->port_id);
-+                      tp->pre_phy_status = LINK_DOWN;
-+              }
-+      }
-+
-+      tp->full_duplex_status = status.bits.duplex;
-+      tp->speed_status = status.bits.speed;
-+      if (!tp->auto_nego_cfg)
-+      {
-+              status.bits.duplex = tp->full_duplex_cfg;
-+              status.bits.speed = tp->speed_cfg;
-+      }
-+
-+      if (old_status.bits32 != status.bits32)
-+      {
-+              netif_stop_queue(dev);
-+              toe_gmac_disable_tx_rx(dev);
-+              clear_bit(__LINK_STATE_START, &dev->state);
-+              printk("GMAC-%d Change Status Bits 0x%x-->0x%x\n",tp->port_id, old_status.bits32, status.bits32);
-+              mdelay(10); // let GMAC consume packet
-+              gmac_write_reg(tp->base_addr, GMAC_STATUS, status.bits32, 0x0000007f);
-+              if (status.bits.link == LINK_UP)
-+              {
-+                      toe_gmac_enable_tx_rx(dev);
-+                      netif_wake_queue(dev);
-+                      set_bit(__LINK_STATE_START, &dev->state);
-+              }
-+      }
-+}
-+
-+/***************************************/
-+/* define GPIO module base address     */
-+/***************************************/
-+#define GPIO_BASE_ADDR  (IO_ADDRESS(SL2312_GPIO_BASE))
-+#define GPIO_BASE_ADDR1  (IO_ADDRESS(SL2312_GPIO_BASE1))
-+
-+/* define GPIO pin for MDC/MDIO */
-+#ifdef CONFIG_SL3516_ASIC
-+#define H_MDC_PIN           22
-+#define H_MDIO_PIN          21
-+#define G_MDC_PIN           22
-+#define G_MDIO_PIN          21
-+#else
-+#define H_MDC_PIN           3
-+#define H_MDIO_PIN          2
-+#define G_MDC_PIN           0
-+#define G_MDIO_PIN          1
-+#endif
-+
-+//#define GPIO_MDC             0x80000000
-+//#define GPIO_MDIO            0x00400000
-+
-+static unsigned int GPIO_MDC = 0;
-+static unsigned int GPIO_MDIO = 0;
-+static unsigned int GPIO_MDC_PIN = 0;
-+static unsigned int GPIO_MDIO_PIN = 0;
-+
-+// For PHY test definition!!
-+#define LPC_EECK              0x02
-+#define LPC_EDIO              0x04
-+#define LPC_GPIO_SET          3
-+#define LPC_BASE_ADDR         IO_ADDRESS(IT8712_IO_BASE)
-+#define inb_gpio(x)           inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
-+#define outb_gpio(x, y)               outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)
-+
-+enum GPIO_REG
-+{
-+    GPIO_DATA_OUT   = 0x00,
-+    GPIO_DATA_IN    = 0x04,
-+    GPIO_PIN_DIR    = 0x08,
-+    GPIO_BY_PASS    = 0x0c,
-+    GPIO_DATA_SET   = 0x10,
-+    GPIO_DATA_CLEAR = 0x14,
-+};
-+/***********************/
-+/*    MDC : GPIO[31]   */
-+/*    MDIO: GPIO[22]   */
-+/***********************/
-+
-+/***************************************************
-+* All the commands should have the frame structure:
-+*<PRE><ST><OP><PHYAD><REGAD><TA><DATA><IDLE>
-+****************************************************/
-+
-+/*****************************************************************
-+* Inject a bit to NWay register through CSR9_MDC,MDIO
-+*******************************************************************/
-+void mii_serial_write(char bit_MDO) // write data into mii PHY
-+{
-+#ifdef CONFIG_SL2312_LPC_IT8712
-+      unsigned char iomode,status;
-+
-+      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
-+      iomode |= (LPC_EECK|LPC_EDIO) ;                         // Set EECK,EDIO,EECS output
-+      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
-+
-+      if(bit_MDO)
-+      {
-+              status = inb_gpio( LPC_GPIO_SET);
-+              status |= LPC_EDIO ;            //EDIO high
-+              outb_gpio(LPC_GPIO_SET, status);
-+      }
-+      else
-+      {
-+              status = inb_gpio( LPC_GPIO_SET);
-+              status &= ~(LPC_EDIO) ;         //EDIO low
-+              outb_gpio(LPC_GPIO_SET, status);
-+      }
-+
-+      status |= LPC_EECK ;            //EECK high
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      status &= ~(LPC_EECK) ;         //EECK low
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+#else
-+    unsigned int addr;
-+    unsigned int value;
-+
-+    addr = GPIO_BASE_ADDR + GPIO_PIN_DIR;
-+    value = readl(addr) | GPIO_MDC | GPIO_MDIO; /* set MDC/MDIO Pin to output */
-+    writel(value,addr);
-+    if(bit_MDO)
-+    {
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+        writel(GPIO_MDIO,addr); /* set MDIO to 1 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+        writel(GPIO_MDC,addr); /* set MDC to 1 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+        writel(GPIO_MDC,addr); /* set MDC to 0 */
-+    }
-+    else
-+    {
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+        writel(GPIO_MDIO,addr); /* set MDIO to 0 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);
-+        writel(GPIO_MDC,addr); /* set MDC to 1 */
-+        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+        writel(GPIO_MDC,addr); /* set MDC to 0 */
-+    }
-+
-+#endif
-+}
-+
-+/**********************************************************************
-+* read a bit from NWay register through CSR9_MDC,MDIO
-+***********************************************************************/
-+unsigned int mii_serial_read(void) // read data from mii PHY
-+{
-+#ifdef CONFIG_SL2312_LPC_IT8712
-+      unsigned char iomode,status;
-+      unsigned int value ;
-+
-+      iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET);
-+      iomode &= ~(LPC_EDIO) ;         // Set EDIO input
-+      iomode |= (LPC_EECK) ;          // Set EECK,EECS output
-+      LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode);
-+
-+      status = inb_gpio( LPC_GPIO_SET);
-+      status |= LPC_EECK ;            //EECK high
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      status &= ~(LPC_EECK) ;         //EECK low
-+      outb_gpio(LPC_GPIO_SET, status);
-+
-+      value = inb_gpio( LPC_GPIO_SET);
-+
-+      value = value>>2 ;
-+      value &= 0x01;
-+
-+      return value ;
-+
-+#else
-+    unsigned int *addr;
-+    unsigned int value;
-+
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_PIN_DIR);
-+    value = readl(addr) & ~GPIO_MDIO; //0xffbfffff;   /* set MDC to output and MDIO to input */
-+    writel(value,addr);
-+
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);
-+    writel(GPIO_MDC,addr); /* set MDC to 1 */
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);
-+    writel(GPIO_MDC,addr); /* set MDC to 0 */
-+
-+    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_IN);
-+    value = readl(addr);
-+    value = (value & (1<<GPIO_MDIO_PIN)) >> GPIO_MDIO_PIN;
-+    return(value);
-+
-+#endif
-+}
-+
-+/***************************************
-+* preamble + ST
-+***************************************/
-+void mii_pre_st(void)
-+{
-+    unsigned char i;
-+
-+    for(i=0;i<32;i++) // PREAMBLE
-+        mii_serial_write(1);
-+    mii_serial_write(0); // ST
-+    mii_serial_write(1);
-+}
-+
-+
-+/******************************************
-+* Read MII register
-+* phyad -> physical address
-+* regad -> register address
-+***************************************** */
-+unsigned int mii_read(unsigned char phyad,unsigned char regad)
-+{
-+    unsigned int i,value;
-+    unsigned int bit;
-+
-+    if (phyad == GPHY_ADDR)
-+    {
-+        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
-+        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
-+    }
-+    else
-+    {
-+        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
-+        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
-+    }
-+    GPIO_MDC = (1<<GPIO_MDC_PIN);
-+    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
-+
-+    mii_pre_st(); // PRE+ST
-+    mii_serial_write(1); // OP
-+    mii_serial_write(0);
-+
-+    for (i=0;i<5;i++) { // PHYAD
-+        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+
-+    for (i=0;i<5;i++) { // REGAD
-+        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+
-+    mii_serial_read(); // TA_Z
-+//    if((bit=mii_serial_read()) !=0 ) // TA_0
-+//    {
-+//        return(0);
-+//    }
-+    value=0;
-+    for (i=0;i<16;i++) { // READ DATA
-+        bit=mii_serial_read();
-+        value += (bit<<(15-i)) ;
-+    }
-+
-+    mii_serial_write(0); // dumy clock
-+    mii_serial_write(0); // dumy clock
-+
-+      //printk("%s: phy_addr=0x%x reg_addr=0x%x value=0x%x \n",__func__,phyad,regad,value);
-+    return(value);
-+}
-+
-+/******************************************
-+* Write MII register
-+* phyad -> physical address
-+* regad -> register address
-+* value -> value to be write
-+***************************************** */
-+void mii_write(unsigned char phyad,unsigned char regad,unsigned int value)
-+{
-+    unsigned int i;
-+    char bit;
-+
-+      printk("%s: phy_addr=0x%x reg_addr=0x%x value=0x%x \n",__func__,phyad,regad,value);
-+    if (phyad == GPHY_ADDR)
-+    {
-+        GPIO_MDC_PIN = G_MDC_PIN;   /* assigned MDC pin for giga PHY */
-+        GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */
-+    }
-+    else
-+    {
-+        GPIO_MDC_PIN = H_MDC_PIN;   /* assigned MDC pin for 10/100 PHY */
-+        GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */
-+    }
-+    GPIO_MDC = (1<<GPIO_MDC_PIN);
-+    GPIO_MDIO = (1<<GPIO_MDIO_PIN);
-+
-+    mii_pre_st(); // PRE+ST
-+    mii_serial_write(0); // OP
-+    mii_serial_write(1);
-+    for (i=0;i<5;i++) { // PHYAD
-+        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+
-+    for (i=0;i<5;i++) { // REGAD
-+        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;
-+        mii_serial_write(bit);
-+    }
-+    mii_serial_write(1); // TA_1
-+    mii_serial_write(0); // TA_0
-+
-+    for (i=0;i<16;i++) { // OUT DATA
-+        bit= ((value>>(15-i)) & 0x01) ? 1 : 0 ;
-+        mii_serial_write(bit);
-+    }
-+    mii_serial_write(0); // dumy clock
-+    mii_serial_write(0); // dumy clock
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_set_rx_mode
-+*----------------------------------------------------------------------*/
-+static void gmac_set_rx_mode(struct net_device *dev)
-+{
-+    GMAC_RX_FLTR_T      filter;
-+      unsigned int        mc_filter[2];       /* Multicast hash filter */
-+    int                 bit_nr;
-+      unsigned int        i;
-+      GMAC_INFO_T             *tp = dev->priv;
-+
-+//    printk("%s : dev->flags = %x \n",__func__,dev->flags);
-+//    dev->flags |= IFF_ALLMULTI;  /* temp */
-+    filter.bits32 = 0;
-+    filter.bits.error = 0;
-+      if (dev->flags & IFF_PROMISC)
-+      {
-+          filter.bits.error = 1;
-+        filter.bits.promiscuous = 1;
-+        filter.bits.broadcast = 1;
-+        filter.bits.multicast = 1;
-+        filter.bits.unicast = 1;
-+              mc_filter[1] = mc_filter[0] = 0xffffffff;
-+      }
-+      else if (dev->flags & IFF_ALLMULTI)
-+      {
-+//        filter.bits.promiscuous = 1;
-+        filter.bits.broadcast = 1;
-+        filter.bits.multicast = 1;
-+        filter.bits.unicast = 1;
-+              mc_filter[1] = mc_filter[0] = 0xffffffff;
-+      }
-+      else
-+      {
-+              struct dev_mc_list *mclist;
-+
-+//        filter.bits.promiscuous = 1;
-+        filter.bits.broadcast = 1;
-+        filter.bits.multicast = 1;
-+        filter.bits.unicast = 1;
-+              mc_filter[1] = mc_filter[0] = 0;
-+              for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;i++, mclist = mclist->next)
-+              {
-+            bit_nr = ether_crc(ETH_ALEN,mclist->dmi_addr) & 0x0000003f;
-+            if (bit_nr < 32)
-+            {
-+                mc_filter[0] = mc_filter[0] | (1<<bit_nr);
-+            }
-+            else
-+            {
-+                mc_filter[1] = mc_filter[1] | (1<<(bit_nr-32));
-+            }
-+              }
-+      }
-+    gmac_write_reg(tp->base_addr,GMAC_RX_FLTR,filter.bits32,0xffffffff);  //chech base address!!!
-+    gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL0,mc_filter[0],0xffffffff);
-+    gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL1,mc_filter[1],0xffffffff);
-+    return;
-+}
-+
-+#ifdef CONFIG_SL_NAPI
-+/*----------------------------------------------------------------------
-+* gmac_rx_poll
-+*----------------------------------------------------------------------*/
-+static int gmac_rx_poll(struct net_device *dev, int *budget)
-+{
-+      TOE_INFO_T                      *toe;
-+    GMAC_RXDESC_T     *curr_desc;
-+      struct sk_buff          *skb;
-+    DMA_RWPTR_T                       rwptr;
-+      unsigned int            pkt_size;
-+      unsigned int        desc_count;
-+      unsigned int        good_frame, chksum_status, rx_status;
-+      int                 rx_pkts_num = 0;
-+      int                 quota = min(dev->quota, *budget);
-+      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
-+      unsigned int            status4;
-+      volatile DMA_RWPTR_T    fq_rwptr;
-+      int                                     max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
-+      //unsigned long         rx_old_bytes;
-+      struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
-+      //unsigned long long    rx_time;
-+
-+
-+
-+#if 1
-+      if (do_again)
-+      {
-+                      toe_gmac_fill_free_q();
-+                      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+                      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                      //printk("\n%s:: do_again toe_gmac_fill_free_q =======>status4=0x%x =====fq_rwptr =0x%8x======>JKJKJKJKJKJKJKJKJ \n", __func__,status4,fq_rwptr.bits32);
-+                      if (fq_rwptr.bits.wptr != fq_rwptr.bits.rptr)
-+                      {
-+                                              //status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+                                              do_again =0;
-+                                              //netif_rx_complete(dev);
-+                                              gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4, 0x1);
-+                                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                                              rwptr.bits32 = readl(&tp->default_qhdr->word1);
-+                      }
-+                      else
-+                              return 1;
-+      }
-+#endif
-+      rwptr.bits32 = readl(&tp->default_qhdr->word1);
-+#if 0
-+      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
-+      {
-+              mac_stop_txdma((struct net_device *)tp->dev);
-+              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
-+                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
-+              while(1);
-+      }
-+#endif
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+
-+      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+      //printk("%s:---Before-------------->Default Queue HW RW ptr (0x%8x),   fq_rwptr =0x%8x \n",__func__,rwptr.bits32,fq_rwptr.bits32 );
-+      //printk("%s:---Before while   rx_pkts_num=%d------rx_finished_idx=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rx_finished_idx,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
-+//    while ((--max_cnt) && (rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
-+
-+      while ((rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
-+      {
-+
-+      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
-+              tp->default_q_cnt++;
-+      tp->rx_curr_desc = (unsigned int)curr_desc;
-+      rx_status = curr_desc->word0.bits.status;
-+      chksum_status = curr_desc->word0.bits.chksum_status;
-+      tp->rx_status_cnt[rx_status]++;
-+      tp->rx_chksum_cnt[chksum_status]++;
-+        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
-+              desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
-+              good_frame=1;
-+              if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
-+                      || (pkt_size < 60)
-+                  || (chksum_status & 0x4)
-+                  || rx_status )
-+//                    || rx_status || (rwptr.bits.rptr > rwptr.bits.wptr ))
-+              {
-+                      good_frame = 0;
-+                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
-+                              printk("%s::derr (GMAC-%d)!!!\n", __func__, tp->port_id);
-+                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_perr)
-+                              printk("%s::perr (GMAC-%d)!!!\n", __func__, tp->port_id);
-+                      if (rx_status)
-+                      {
-+                              if (rx_status == 4 || rx_status == 7)
-+                                      isPtr->rx_crc_errors++;
-+//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
-+                      }
-+#ifdef SL351x_GMAC_WORKAROUND
-+                      else if (pkt_size < 60)
-+                      {
-+                              if (tp->short_frames_cnt < GMAC_SHORT_FRAME_THRESHOLD)
-+                                      tp->short_frames_cnt++;
-+                              if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
-+                              {
-+                                      GMAC_CONFIG0_T config0;
-+                                      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                                      config0.bits.dis_rx = 1;
-+                                      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                                      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                                      config0.bits.dis_rx = 1;
-+                                      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                              }
-+                      }
-+#endif
-+//                    if (chksum_status)
-+//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
-+                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-+                      dev_kfree_skb_irq(skb);
-+              }
-+              if (good_frame)
-+              {
-+                      if (curr_desc->word0.bits.drop)
-+                              printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
-+//                    if (chksum_status)
-+//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
-+
-+#ifdef SL351x_GMAC_WORKAROUND
-+                      if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
-+                      {
-+                              GMAC_CONFIG0_T config0;
-+                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                              config0.bits.dis_rx = 0;
-+                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                              config0.bits.dis_rx = 0;
-+                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                      }
-+                      tp->short_frames_cnt = 0;
-+#endif
-+              /* get frame information from the first descriptor of the frame */
-+                      isPtr->rx_packets++;
-+                      //consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
-+                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-+                      tp->curr_rx_skb = skb;
-+      //              curr_desc->word2.buf_adr = 0;
-+
-+                  //skb_reserve (skb, SKB_RESERVE_BYTES);
-+                      skb_reserve (skb, RX_INSERT_BYTES);     /* 2 byte align the IP fields. */
-+                      //if ((skb->tail+pkt_size) > skb->end )
-+                      //printk("%s::------------->Here skb->len=%d,pkt_size= %d,skb->head=0x%x,skb->tail= 0x%x, skb->end= 0x%x\n", __func__, skb->len, pkt_size,skb->head,skb->tail,skb->end);
-+                      skb_put(skb, pkt_size);
-+
-+
-+                      skb->dev = dev;
-+                      if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
-+                      {
-+                              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+#ifdef CONFIG_SL351x_NAT
-+                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
-+                              {
-+                                      struct iphdr    *ip_hdr;
-+                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
-+                                      sl351x_nat_input(skb,
-+                                                                      tp->port_id,
-+                                                                      (void *)curr_desc->word3.bits.l3_offset,
-+                                                                      (void *)curr_desc->word3.bits.l4_offset);
-+                              }
-+#endif
-+                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-+#if 0
-+#ifdef CONFIG_SL351x_RXTOE
-+                              if (storlink_ctl.rx_max_pktsize) {
-+                                      struct iphdr    *ip_hdr;
-+                                      struct tcphdr   *tcp_hdr;
-+                                      int ip_hdrlen;
-+
-+                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
-+                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
-+                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
-+                                              ip_hdrlen = ip_hdr->ihl << 2;
-+                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
-+                                              if (tcp_hdr->syn) {
-+                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
-+                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
-+                                                      TCP_SKB_CB(skb)->connection = connection;
-+                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
-+                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
-+                                                      //                      __func__, skb->data, connection, connection->mode);
-+                                              }
-+                                      }
-+                              }
-+#endif
-+#endif
-+                      }
-+                      else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
-+                      {
-+                              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+#ifdef CONFIG_SL351x_NAT
-+                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
-+                              {
-+                                      struct iphdr    *ip_hdr;
-+                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
-+                                      if (ip_hdr->protocol == IPPROTO_UDP)
-+                                      {
-+                                              sl351x_nat_input(skb,
-+                                                                              tp->port_id,
-+                                                                              (void *)curr_desc->word3.bits.l3_offset,
-+                                                                              (void *)curr_desc->word3.bits.l4_offset);
-+                                      }
-+                                      else if (ip_hdr->protocol == IPPROTO_GRE)
-+                                      {
-+                                              sl351x_nat_input(skb,
-+                                                                      tp->port_id,
-+                                                                      (void *)curr_desc->word3.bits.l3_offset,
-+                                                                      (void *)curr_desc->word3.bits.l4_offset);
-+                                      }
-+                              }
-+#endif
-+                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-+                      }
-+                      else
-+                      {
-+                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-+                      }
-+                      //netif_rx(skb);  /* socket rx */
-+                      netif_receive_skb(skb); //For NAPI
-+                      dev->last_rx = jiffies;
-+
-+                      isPtr->rx_bytes += pkt_size;
-+                      //printk("------------------->isPtr->rx_bytes = %d\n",isPtr->rx_bytes);
-+
-+
-+        }
-+              // advance one for Rx default Q 0/1
-+              rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
-+              SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
-+      tp->rx_rwptr.bits32 = rwptr.bits32;
-+              rx_pkts_num++;
-+              //rwptr.bits32 = readl(&tp->default_qhdr->word1);//try read default_qhdr again
-+              //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+              //printk("%s:---Loop  -------->rx_pkts_num=%d------------>Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits32,fq_rwptr.bits32 );
-+#if 0
-+              if ((status4 & 0x1) == 0)
-+              {
-+                      //if (!((dev->last_rx <= (rx_time + 2)) &&  (isPtr->rx_bytes > (rx_old_bytes + 1000000 ))))
-+                      if (tp->total_q_cnt_napi < 1024)
-+                      {
-+                              tp->total_q_cnt_napi++;
-+                              toe_gmac_fill_free_q();  //for iperf test disable
-+                      }
-+                      //else
-+                              //printk("%s:---isPtr->rx_bytes =%u , rx_old_bytes =%u\n",__func__,isPtr->rx_bytes,rx_old_bytes );
-+
-+              }
-+#endif
-+              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
-+              //printk("%s:---Loop  -------->rx_pkts_num=%d----rwptr.bits.rptr=0x%x-------->Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits32,fq_rwptr.bits32 );
-+              //printk("%s:---Loop  rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
-+      }
-+      // advance one for Rx default Q 0/1
-+
-+              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
-+              //SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
-+      //tp->rx_rwptr.bits32 = rwptr.bits32;
-+      //rwptr.bits.rptr = rwptr.bits.rptr;
-+
-+      dev->quota -= rx_pkts_num;
-+      *budget -= rx_pkts_num;
-+
-+      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);//try read SWFQ empty again
-+      //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+      rwptr.bits32 = readl(&tp->default_qhdr->word1); //try read default_qhdr again
-+      //printk("%s:---After    rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
-+//    if (rwptr.bits.rptr > rwptr.bits.wptr )
-+//                    {
-+                              //toe_gmac_disable_rx(dev);
-+                              //wait_event_interruptible_timeout(freeq_wait,
-+                                      //(rx_pkts_num == 100), CMTP_INTEROP_TIMEOUT);
-+                              //printk("\n%s:: return 22222=======> rx_pkts_num =%d,   rwptr.bits.rptr=%d,   rwptr.bits.wptr = %d ====---------=======>JKJKJKJKJK\n",
-+                                      //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
-+//                            return 1;
-+//                    }
-+
-+      if (rwptr.bits.rptr == rwptr.bits.wptr)
-+      {
-+              unsigned int data32;
-+                      //printk("%s:---[rwptr.bits.rptr == rwptr.bits.wptr]   rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
-+
-+          /* Receive descriptor is empty now */
-+#if 1
-+     if (status4 & 0x1)
-+                      {
-+                              do_again =1;
-+                              //writel(0x40400000, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_4_REG); //disable SWFQ empty interrupt
-+                              //toe_gmac_disable_interrupt(tp->irq);
-+                              tp->sw_fq_empty_cnt++;
-+                              //toe_gmac_disable_rx(dev);
-+                              writel(0x07960202, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+                              writel(0x07960202, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+                              //printk("\n%s ::  freeq int-----tp->sw_fq_empty_cnt  =%d---------====================----------------->\n",__func__,tp->sw_fq_empty_cnt);
-+                              //while ((fq_rwptr.bits.wptr >= (fq_rwptr.bits.rptr+256)) || (fq_rwptr.bits.wptr <= (fq_rwptr.bits.rptr+256)))
-+                              //{
-+                                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
-+                                      //0x1);
-+                              //printk("\n%s::fq_rwptr.wrptr = %x =======> ===========>here \n", __func__,fq_rwptr.bits32);
-+                              //if ((status4 & 0x1) == 0)
-+                                      //break;
-+                               return 1;
-+                              //}
-+
-+                      }
-+#endif
-+        //toe_gmac_fill_free_q();
-+        netif_rx_complete(dev);
-+        // enable GMAC-0 rx interrupt
-+        // class-Q & TOE-Q are implemented in future
-+        //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+        //if (tp->port_id == 0)
-+              //data32 |= DEFAULT_Q0_INT_BIT;
-+        //else
-+              //data32 |= DEFAULT_Q1_INT_BIT;
-+        //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+              writel(0x3, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
-+              //printk("\n%s::netif_rx_complete-->  rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x ====---------=======>JKJKJKJKJK\n",
-+              //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
-+        writel(0x07960200, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              writel(0x07960200, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+        return 0;
-+    }
-+    else
-+    {
-+        //printk("\n%s:: return 1 -->status4= 0x%x,rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x  ======> \n", __func__,status4,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
-+        return 1;
-+    }
-+}
-+#endif
-+
-+/*----------------------------------------------------------------------
-+* gmac_tx_timeout
-+*----------------------------------------------------------------------*/
-+void gmac_tx_timeout(struct net_device *dev)
-+{
-+      GMAC_INFO_T                             *tp = (GMAC_INFO_T *)dev->priv;
-+
-+#ifdef CONFIG_SL351x_SYSCTL
-+      if (tp->operation && storlink_ctl.link[tp->port_id])
-+#else
-+      if (tp->operation)
-+#endif
-+      {
-+              netif_wake_queue(dev);
-+      }
-+}
-+
-+
-+
-+/*----------------------------------------------------------------------
-+* mac_set_rule_reg
-+*----------------------------------------------------------------------*/
-+int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2)
-+{
-+      int             total_key_dwords;
-+
-+      total_key_dwords = 1;
-+
-+      if (reg0 & MR_L2_BIT)
-+      {
-+              if (reg0 & MR_DA_BIT) total_key_dwords += 2;
-+              if (reg0 & MR_SA_BIT) total_key_dwords += 2;
-+              if ((reg0 & MR_DA_BIT) && ( reg0 & MR_SA_BIT)) total_key_dwords--;
-+              if (reg0 & (MR_PPPOE_BIT | MR_VLAN_BIT)) total_key_dwords++;
-+      }
-+      if (reg0 & MR_L3_BIT)
-+      {
-+              if (reg0 & (MR_IP_HDR_LEN_BIT | MR_TOS_TRAFFIC_BIT | MR_SPR_BITS))
-+                      total_key_dwords++;
-+              if (reg0 & MR_FLOW_LABLE_BIT) total_key_dwords++;
-+              if ((reg0 & MR_IP_VER_BIT) == 0) // IPv4
-+              {
-+                      if (reg1 & 0xff000000) total_key_dwords += 1;
-+                      if (reg1 & 0x00ff0000) total_key_dwords += 1;
-+              }
-+              else
-+              {
-+                      if (reg1 & 0xff000000) total_key_dwords += 4;
-+                      if (reg1 & 0x00ff0000) total_key_dwords += 4;
-+              }
-+      }
-+      if (reg0 & MR_L4_BIT)
-+      {
-+              if (reg1 & 0x0000f000) total_key_dwords += 1;
-+              if (reg1 & 0x00000f00) total_key_dwords += 1;
-+              if (reg1 & 0x000000f0) total_key_dwords += 1;
-+              if (reg1 & 0x0000000f) total_key_dwords += 1;
-+              if (reg2 & 0xf0000000) total_key_dwords += 1;
-+              if (reg2 & 0x0f000000) total_key_dwords += 1;
-+      }
-+      if (reg0 & MR_L7_BIT)
-+      {
-+              if (reg2 & 0x00f00000) total_key_dwords += 1;
-+              if (reg2 & 0x000f0000) total_key_dwords += 1;
-+              if (reg2 & 0x0000f000) total_key_dwords += 1;
-+              if (reg2 & 0x00000f00) total_key_dwords += 1;
-+              if (reg2 & 0x000000f0) total_key_dwords += 1;
-+              if (reg2 & 0x0000000f) total_key_dwords += 1;
-+      }
-+
-+      if (total_key_dwords > HASH_MAX_KEY_DWORD)
-+              return -1;
-+
-+      if (total_key_dwords == 0 && enabled)
-+              return -2;
-+
-+      mac_set_rule_enable_bit(mac, rule, 0);
-+      if (enabled)
-+      {
-+              mac_set_MRxCRx(mac, rule, 0, reg0);
-+              mac_set_MRxCRx(mac, rule, 1, reg1);
-+              mac_set_MRxCRx(mac, rule, 2, reg2);
-+              mac_set_rule_action(mac, rule, total_key_dwords);
-+              mac_set_rule_enable_bit(mac, rule, enabled);
-+      }
-+      else
-+      {
-+              mac_set_rule_action(mac, rule, 0);
-+      }
-+      return total_key_dwords;
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_get_rule_enable_bit
-+*----------------------------------------------------------------------*/
-+int mac_get_rule_enable_bit(int mac, int rule)
-+{
-+      switch (rule)
-+      {
-+              case 0: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) >> 15) & 1);
-+              case 1: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) >> 31) & 1);
-+              case 2: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) >> 15) & 1);
-+              case 3: return ((mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) >> 31) & 1);
-+              default: return 0;
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_set_rule_enable_bit
-+*----------------------------------------------------------------------*/
-+void mac_set_rule_enable_bit(int mac, int rule, int data)
-+{
-+      u32 reg;
-+
-+      if (data & ~1)
-+              return;
-+
-+      switch (rule)
-+      {
-+              case 0:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(1<<15)) | (data << 15);
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg);
-+                      break;
-+              case 1:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(1<<31)) | (data << 31);
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg);
-+                      break;
-+              case 2:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(1<<15)) | (data << 15);
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1, reg);
-+                      break;
-+              case 3:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(1<<31)) | (data << 31);
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1, reg);
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_set_rule_action
-+*----------------------------------------------------------------------*/
-+int mac_set_rule_action(int mac, int rule, int data)
-+{
-+      u32 reg;
-+
-+      if (data > 32)
-+              return -1;
-+
-+      if (data)
-+              data = (data << 6) | (data + HASH_ACTION_DWORDS);
-+      switch (rule)
-+      {
-+              case 0:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(0x7ff));
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg | data);
-+                      break;
-+              case 1:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG0) & ~(0x7ff<<16));
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG0, reg | (data << 16));
-+                      break;
-+              case 2:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(0x7ff));
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1,  reg | data);
-+                      break;
-+              case 3:
-+                      reg = (mac_read_dma_reg(mac, GMAC_HASH_ENGINE_REG1) & ~(0x7ff<<16));
-+                      mac_write_dma_reg(mac, GMAC_HASH_ENGINE_REG1, reg | (data << 16));
-+                      break;
-+              default:
-+                      return -1;
-+      }
-+
-+      return 0;
-+}
-+/*----------------------------------------------------------------------
-+* mac_get_MRxCRx
-+*----------------------------------------------------------------------*/
-+int mac_get_MRxCRx(int mac, int rule, int ctrlreg)
-+{
-+      int reg;
-+
-+      switch (rule)
-+      {
-+              case 0: reg = GMAC_MR0CR0 + ctrlreg * 4; break;
-+              case 1: reg = GMAC_MR1CR0 + ctrlreg * 4; break;
-+              case 2: reg = GMAC_MR2CR0 + ctrlreg * 4; break;
-+              case 3: reg = GMAC_MR3CR0 + ctrlreg * 4; break;
-+              default: return 0;
-+      }
-+      return mac_read_dma_reg(mac, reg);
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_set_MRxCRx
-+*----------------------------------------------------------------------*/
-+void mac_set_MRxCRx(int mac, int rule, int ctrlreg, u32 data)
-+{
-+      int reg;
-+
-+      switch (rule)
-+      {
-+              case 0: reg = GMAC_MR0CR0 + ctrlreg * 4; break;
-+              case 1: reg = GMAC_MR1CR0 + ctrlreg * 4; break;
-+              case 2: reg = GMAC_MR2CR0 + ctrlreg * 4; break;
-+              case 3: reg = GMAC_MR3CR0 + ctrlreg * 4; break;
-+              default: return;
-+      }
-+      mac_write_dma_reg(mac, reg, data);
-+}
-+
-+/*----------------------------------------------------------------------
-+* mac_set_rule_priority
-+*----------------------------------------------------------------------*/
-+void mac_set_rule_priority(int mac, int p0, int p1, int p2, int p3)
-+{
-+      int                     i;
-+      GMAC_MRxCR0_T   reg[4];
-+
-+      for (i=0; i<4; i++)
-+              reg[i].bits32 = mac_get_MRxCRx(mac, i, 0);
-+
-+      reg[0].bits.priority = p0;
-+      reg[1].bits.priority = p1;
-+      reg[2].bits.priority = p2;
-+      reg[3].bits.priority = p3;
-+
-+      for (i=0; i<4; i++)
-+              mac_set_MRxCRx(mac, i, 0, reg[i].bits32);
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_netdev_ioctl
-+*----------------------------------------------------------------------*/
-+static int gmac_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+      int                             rc = 0;
-+    unsigned char             *hwa = rq->ifr_ifru.ifru_hwaddr.sa_data;
-+
-+#ifdef br_if_ioctl
-+    struct                            ethtool_cmd ecmd;       //br_if.c will call this ioctl
-+      GMAC_INFO_T             *tp = dev->priv;
-+#endif
-+
-+#ifdef        CONFIG_SL351x_NAT
-+      if (cmd == SIOCDEVPRIVATE)
-+              return sl351x_nat_ioctl(dev, rq, cmd);
-+#endif
-+
-+      switch (cmd) {
-+      case SIOCETHTOOL:
-+#ifdef br_if_ioctl    //br_if.c will call this ioctl
-+              if (!netif_running(dev))
-+              {
-+                      printk("Before changing the H/W address,please down the device.\n");
-+                      return -EINVAL;
-+              }
-+              memset((void *) &ecmd, 0, sizeof (ecmd));
-+                  ecmd.supported =
-+                      SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
-+                    SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
-+                    SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
-+                          ecmd.port = PORT_TP;
-+                  ecmd.transceiver = XCVR_EXTERNAL;
-+                  ecmd.phy_address = tp->phy_addr;
-+                  switch (tp->speed_status)
-+                  {
-+                  case GMAC_SPEED_10: ecmd.speed = SPEED_10; break;
-+                  case GMAC_SPEED_100: ecmd.speed = SPEED_100; break;
-+                  case GMAC_SPEED_1000: ecmd.speed = SPEED_1000; break;
-+                  default: ecmd.speed = SPEED_10; break;
-+                 }
-+                  ecmd.duplex = tp->full_duplex_status ? DUPLEX_FULL : DUPLEX_HALF;
-+                  ecmd.advertising = ADVERTISED_TP;
-+                  ecmd.advertising |= ADVERTISED_Autoneg;
-+                  ecmd.autoneg = AUTONEG_ENABLE;
-+                    if (copy_to_user(rq->ifr_data, &ecmd, sizeof (ecmd)))
-+                      return -EFAULT;
-+#endif
-+
-+        break;
-+
-+    case SIOCSIFHWADDR:
-+              if (!netif_running(dev))
-+              {
-+                      printk("Before changing the H/W address,please down the device.\n");
-+                      return -EINVAL;
-+              }
-+        gmac_set_mac_address(dev,hwa);
-+        break;
-+
-+      case SIOCGMIIPHY:       /* Get the address of the PHY in use. */
-+        break;
-+
-+      case SIOCGMIIREG:       /* Read the specified MII register. */
-+              break;
-+
-+      case SIOCSMIIREG:       /* Write the specified MII register */
-+              break;
-+
-+      default:
-+              rc = -EOPNOTSUPP;
-+              break;
-+      }
-+
-+      return rc;
-+}
-+
-+#ifdef SL351x_GMAC_WORKAROUND
-+
-+#define GMAC_TX_STATE_OFFSET  0x60
-+#define GMAC_RX_STATE_OFFSET  0x64
-+#define GMAC_POLL_HANGED_NUM  200
-+#define GMAC_RX_HANGED_STATE  0x4b2000
-+#define GMAC_RX_HANGED_MASK           0xdff000
-+#define GMAC_TX_HANGED_STATE  0x34012
-+#define GMAC_TX_HANGED_MASK           0xfffff
-+#define TOE_GLOBAL_REG_SIZE           (0x78/sizeof(u32))
-+#define TOE_DMA_REG_SIZE              (0xd0/sizeof(u32))
-+#define TOE_GMAC_REG_SIZE             (0x30/sizeof(u32))
-+#define GMAC0_RX_HANG_BIT             (1 << 0)
-+#define GMAC0_TX_HANG_BIT             (1 << 1)
-+#define GMAC1_RX_HANG_BIT             (1 << 2)
-+#define GMAC1_TX_HANG_BIT             (1 << 3)
-+
-+int           gmac_in_do_workaround;
-+#if 0
-+int           debug_cnt, poll_max_cnt;
-+#endif
-+u32           gmac_workaround_cnt[4];
-+u32           toe_global_reg[TOE_GLOBAL_REG_SIZE];
-+u32           toe_dma_reg[GMAC_NUM][TOE_DMA_REG_SIZE];
-+u32           toe_gmac_reg[GMAC_NUM][TOE_GMAC_REG_SIZE];
-+u32           gmac_short_frame_workaround_cnt[2];
-+
-+static void sl351x_gmac_release_buffers(void);
-+static void sl351x_gmac_release_swtx_q(void);
-+static void sl351x_gmac_release_rx_q(void);
-+#ifdef _TOEQ_CLASSQ_READY_
-+static void sl351x_gmac_release_class_q(void);
-+static void sl351x_gmac_release_toe_q(void);
-+static void sl351x_gmac_release_intr_q(void);
-+#endif
-+static void sl351x_gmac_release_sw_free_q(void);
-+static void sl351x_gmac_release_hw_free_q(void);
-+#ifdef CONFIG_SL351x_NAT
-+static int get_free_desc_cnt(unsigned long rwptr, int total);
-+static void sl351x_gmac_release_hwtx_q(void);
-+u32     sl351x_nat_workaround_cnt;
-+#endif
-+void sl351x_gmac_save_reg(void);
-+void sl351x_gmac_restore_reg(void);
-+
-+
-+/*----------------------------------------------------------------------
-+*     sl351x_poll_gmac_hanged_status
-+*     - Called by timer routine, period 10ms
-+*     - If (state != 0 && state == prev state && )
-+*----------------------------------------------------------------------*/
-+void sl351x_poll_gmac_hanged_status(u32 data)
-+{
-+      int                     i;
-+      u32                     state;
-+      TOE_INFO_T              *toe;
-+      GMAC_INFO_T             *tp;
-+      u32                             hanged_state;
-+      // int                          old_operation[GMAC_NUM];
-+#ifdef CONFIG_SL351x_NAT
-+      u32                             hw_free_cnt;
-+#endif
-+
-+      if (gmac_in_do_workaround)
-+              return;
-+
-+      gmac_in_do_workaround = 1;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      hanged_state = 0;
-+
-+#ifdef SL351x_TEST_WORKAROUND
-+      if (toe->gmac[0].operation || toe->gmac[1].operation)
-+      {
-+              debug_cnt++;
-+              if (debug_cnt == (30 * HZ))
-+              {
-+                      debug_cnt = 0;
-+                      hanged_state = GMAC0_RX_HANG_BIT;
-+                      goto do_workaround;
-+              }
-+      }
-+#endif
-+      if (toe->gmac[0].operation)
-+              hanged_state |= GMAC0_RX_HANG_BIT | GMAC0_TX_HANG_BIT;
-+
-+#if (GMAC_NUM > 1)
-+      if (toe->gmac[1].operation)
-+              hanged_state |= GMAC1_RX_HANG_BIT | GMAC1_TX_HANG_BIT;
-+#endif
-+
-+      for (i=0; i<GMAC_POLL_HANGED_NUM; i++)
-+      {
-+              if (hanged_state & GMAC0_RX_HANG_BIT)
-+              {
-+                      state = readl(TOE_GMAC0_BASE + GMAC_RX_STATE_OFFSET) & GMAC_RX_HANGED_MASK;
-+                      if (state != GMAC_RX_HANGED_STATE)
-+                              hanged_state &= ~GMAC0_RX_HANG_BIT;
-+              }
-+              if (hanged_state & GMAC0_TX_HANG_BIT)
-+              {
-+                      state = readl(TOE_GMAC0_BASE + GMAC_TX_STATE_OFFSET) & GMAC_TX_HANGED_MASK;
-+                      if (state != GMAC_TX_HANGED_STATE)
-+                              hanged_state &= ~GMAC0_TX_HANG_BIT;
-+              }
-+#if (GMAC_NUM > 1)
-+              if (hanged_state & GMAC1_RX_HANG_BIT)
-+              {
-+                      state = readl(TOE_GMAC1_BASE + GMAC_RX_STATE_OFFSET) & GMAC_RX_HANGED_MASK;
-+                      if (state != GMAC_RX_HANGED_STATE)
-+                              hanged_state &= ~GMAC1_RX_HANG_BIT;
-+              }
-+              if (hanged_state & GMAC1_TX_HANG_BIT)
-+              {
-+                      state = readl(TOE_GMAC1_BASE + GMAC_TX_STATE_OFFSET) & GMAC_TX_HANGED_MASK;
-+                      if (state != GMAC_TX_HANGED_STATE)
-+                              hanged_state &= ~GMAC1_TX_HANG_BIT;
-+              }
-+#endif
-+              if (!hanged_state)
-+              {
-+#if 0
-+                      if (i < poll_max_cnt)
-+                              poll_max_cnt = i;
-+#endif
-+                      if (toe->gmac[0].short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
-+                      {
-+                              gmac_short_frame_workaround_cnt[0]++;
-+                              toe->gmac[0].short_frames_cnt = 0;
-+                              goto do_workaround;
-+                      }
-+#if (GMAC_NUM > 1)
-+                      if (toe->gmac[1].short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
-+                      {
-+                              gmac_short_frame_workaround_cnt[1]++;
-+                              toe->gmac[1].short_frames_cnt = 0;
-+                              goto do_workaround;
-+                      }
-+#endif
-+
-+#ifdef CONFIG_SL351x_NAT
-+                      hw_free_cnt = readl(TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
-+                      hw_free_cnt = get_free_desc_cnt(hw_free_cnt, TOE_HW_FREEQ_DESC_NUM);
-+#ifdef NAT_WORKAROUND_BY_RESET_GMAC
-+                      if (readl(TOE_GLOBAL_BASE + 0x4084) && (hw_free_cnt <= PAUSE_SET_HW_FREEQ))
-+                      {
-+                              sl351x_nat_workaround_cnt++;
-+                              goto do_workaround;
-+                      }
-+#else
-+                      if (readl(TOE_GLOBAL_BASE + 0x4084) && (hw_free_cnt <= (PAUSE_SET_HW_FREEQ*2)))
-+                      {
-+                              sl351x_nat_workaround_cnt++;
-+                              sl351x_nat_workaround_handler();
-+                      }
-+#endif
-+#endif
-+                      gmac_in_do_workaround = 0;
-+                      add_timer(&gmac_workround_timer_obj);
-+                      return;
-+              }
-+      }
-+
-+do_workaround:
-+
-+      gmac_initialized = 0;
-+      if (hanged_state)
-+      {
-+              if (hanged_state & GMAC0_RX_HANG_BIT) gmac_workaround_cnt[0]++;
-+              if (hanged_state & GMAC0_TX_HANG_BIT) gmac_workaround_cnt[1]++;
-+              if (hanged_state & GMAC1_RX_HANG_BIT) gmac_workaround_cnt[2]++;
-+              if (hanged_state & GMAC1_TX_HANG_BIT) gmac_workaround_cnt[3]++;
-+      }
-+
-+      for (i=0; i<GMAC_NUM; i++)
-+      {
-+              tp=(GMAC_INFO_T *)&toe->gmac[i];
-+              // old_operation[i] = tp->operation;
-+              if (tp->operation)
-+              {
-+                      netif_stop_queue(tp->dev);
-+                      clear_bit(__LINK_STATE_START, &tp->dev->state);
-+                      toe_gmac_disable_interrupt(tp->irq);
-+                      toe_gmac_disable_tx_rx(tp->dev);
-+                      toe_gmac_hw_stop(tp->dev);
-+              }
-+      }
-+
-+      // clear all status bits
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
-+      writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+
-+#if 0
-+      if ((hanged_state & GMAC0_RX_HANG_BIT) &&
-+              (readl(TOE_GMAC0_DMA_BASE + 0xdc) & 0xf0))
-+      {
-+              struct sk_buff *skb;
-+              unsigned int buf;
-+              buf = readl(TOE_GMAC0_DMA_BASE + 0x68) & ~3;
-+#ifdef CONFIG_SL351x_NAT
-+              if (buf < toe->hwfq_buf_base_dma || buf > toe->hwfq_buf_end_dma)
-+#endif
-+              {
-+                      skb = (struct sk_buff *)(REG32(buf - SKB_RESERVE_BYTES));
-+                      printk("GMAC-0 free a loss SKB 0x%x\n", (u32)skb);
-+                      dev_kfree_skb(skb);
-+              }
-+      }
-+      if ((hanged_state & GMAC1_RX_HANG_BIT)  &&
-+              (readl(TOE_GMAC1_DMA_BASE + 0xdc) & 0xf0))
-+      {
-+              struct sk_buff *skb;
-+              unsigned int buf;
-+              buf = readl(TOE_GMAC1_DMA_BASE + 0x68) & ~3;
-+#ifdef CONFIG_SL351x_NAT
-+              if (buf < toe->hwfq_buf_base_dma || buf > toe->hwfq_buf_end_dma)
-+#endif
-+              {
-+                      skb = (struct sk_buff *)(REG32(buf - SKB_RESERVE_BYTES));
-+                      printk("GMAC-1 free a loss SKB 0x%x\n", (u32)skb);
-+                      dev_kfree_skb(skb);
-+              }
-+      }
-+#endif
-+
-+      sl351x_gmac_release_buffers();
-+      sl351x_gmac_save_reg();
-+      toe_gmac_sw_reset();
-+      sl351x_gmac_restore_reg();
-+
-+      if (toe->gmac[0].default_qhdr->word1.bits32)
-+      {
-+              // printk("===> toe->gmac[0].default_qhdr->word1 = 0x%x\n", toe->gmac[0].default_qhdr->word1);
-+              sl351x_gmac_release_rx_q();
-+              writel(0, &toe->gmac[0].default_qhdr->word1);
-+      }
-+      if (toe->gmac[1].default_qhdr->word1.bits32)
-+      {
-+              // printk("===> toe->gmac[1].default_qhdr->word1 = 0x%x\n", toe->gmac[1].default_qhdr->word1);
-+              sl351x_gmac_release_rx_q();
-+              writel(0, &toe->gmac[1].default_qhdr->word1);
-+      }
-+
-+      gmac_initialized = 1;
-+
-+#ifdef        CONFIG_SL351x_NAT
-+      writel(0, TOE_GLOBAL_BASE + 0x4084);
-+#endif
-+
-+      for (i=0; i<GMAC_NUM; i++)
-+      {
-+              tp=(GMAC_INFO_T *)&toe->gmac[i];
-+              if (tp->operation)
-+              {
-+                      toe_gmac_enable_interrupt(tp->irq);
-+                      toe_gmac_hw_start(tp->dev);
-+                      toe_gmac_enable_tx_rx(tp->dev);
-+                      netif_wake_queue(tp->dev);
-+                      set_bit(__LINK_STATE_START, &tp->dev->state);
-+              }
-+      }
-+
-+      gmac_in_do_workaround = 0;
-+      add_timer(&gmac_workround_timer_obj);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     get_free_desc_cnt
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static int get_free_desc_cnt(unsigned long rwptr, int total)
-+{
-+      unsigned short wptr = rwptr & 0xffff;
-+      unsigned short rptr = rwptr >> 16;
-+
-+      if (wptr >= rptr)
-+              return (total - wptr + rptr);
-+      else
-+              return (rptr - wptr);
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_buffers
-+*----------------------------------------------------------------------*/
-+static void sl351x_gmac_release_buffers(void)
-+{
-+      // Free buffers & Descriptors in all SW Tx Queues
-+      sl351x_gmac_release_swtx_q();
-+
-+      // Free buffers in Default Rx Queues
-+      sl351x_gmac_release_rx_q();
-+
-+#ifdef _TOEQ_CLASSQ_READY_
-+      // Free buffers in Classification Queues
-+      sl351x_gmac_release_class_q();
-+
-+      // Free buffers in TOE Queues
-+      sl351x_gmac_release_toe_q();
-+
-+      // Free buffers in Interrupt Queues
-+      sl351x_gmac_release_intr_q();
-+#endif
-+
-+      // Free buffers & descriptors in SW free queue
-+      sl351x_gmac_release_sw_free_q();
-+
-+      // Free buffers & descriptors in HW free queue
-+      sl351x_gmac_release_hw_free_q();
-+
-+#ifdef CONFIG_SL351x_NAT
-+      // Free buffers & descriptors in HW free queue
-+      sl351x_gmac_release_hwtx_q();
-+#endif
-+}
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_swtx_q
-+*----------------------------------------------------------------------*/
-+static void sl351x_gmac_release_swtx_q(void)
-+{
-+      int                             i, j;
-+      GMAC_TXDESC_T   *curr_desc;
-+      unsigned int    desc_count;
-+      TOE_INFO_T              *toe;
-+      GMAC_INFO_T             *tp;
-+      GMAC_SWTXQ_T    *swtxq;
-+      DMA_RWPTR_T             rwptr;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      tp = (GMAC_INFO_T *)&toe->gmac[0];
-+      for (i=0; i<GMAC_NUM; i++, tp++)
-+      {
-+              if (!tp->existed) continue;
-+              swtxq = (GMAC_SWTXQ_T *)&tp->swtxq[0];
-+              for (j=0; j<TOE_SW_TXQ_NUM; j++, swtxq++)
-+              {
-+                      for (;;)
-+                      {
-+                              rwptr.bits32 = readl(swtxq->rwptr_reg);
-+                              if (rwptr.bits.rptr == swtxq->finished_idx)
-+                              break;
-+                              curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
-+                              // if (curr_desc->word0.bits.status_tx_ok)
-+                              {
-+                                      desc_count = curr_desc->word0.bits.desc_count;
-+                                      while (--desc_count)
-+                                      {
-+                                              curr_desc->word0.bits.status_tx_ok = 0;
-+                                              swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
-+                                              curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
-+                                      }
-+
-+                                      curr_desc->word0.bits.status_tx_ok = 0;
-+                                      if (swtxq->tx_skb[swtxq->finished_idx])
-+                                      {
-+                                              dev_kfree_skb_irq(swtxq->tx_skb[swtxq->finished_idx]);
-+                                              swtxq->tx_skb[swtxq->finished_idx] = NULL;
-+                                      }
-+                              }
-+                              swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
-+                      }
-+                      writel(0, swtxq->rwptr_reg);
-+                      swtxq->finished_idx = 0;
-+              }
-+      }
-+
-+}
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_rx_q
-+*----------------------------------------------------------------------*/
-+static void sl351x_gmac_release_rx_q(void)
-+{
-+      int                             i;
-+      TOE_INFO_T              *toe;
-+      GMAC_INFO_T             *tp;
-+      DMA_RWPTR_T             rwptr;
-+      volatile GMAC_RXDESC_T  *curr_desc;
-+      struct sk_buff                  *skb;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      tp = (GMAC_INFO_T *)&toe->gmac[0];
-+      for (i=0; i<GMAC_NUM; i++, tp++)
-+      {
-+              if (!tp->existed) continue;
-+              rwptr.bits32 = readl(&tp->default_qhdr->word1);
-+              while (rwptr.bits.rptr != rwptr.bits.wptr)
-+              {
-+                      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
-+                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-+                      dev_kfree_skb_irq(skb);
-+                      rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
-+                      SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
-+                      rwptr.bits32 = readl(&tp->default_qhdr->word1);
-+              }  // while
-+              writel(0, &tp->default_qhdr->word1);
-+              tp->rx_rwptr.bits32 = 0;
-+      } // for
-+
-+}
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_class_q
-+*----------------------------------------------------------------------*/
-+#ifdef _TOEQ_CLASSQ_READY_
-+static void sl351x_gmac_release_class_q(void)
-+{
-+      int                             i;
-+      TOE_INFO_T              *toe;
-+      CLASSQ_INFO_T   *classq;
-+      DMA_RWPTR_T             rwptr;
-+      volatile GMAC_RXDESC_T  *curr_desc;
-+      struct sk_buff                  *skb;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      classq = (CLASSQ_INFO_T *)&toe->classq[0];
-+      for (i=0; i<TOE_CLASS_QUEUE_NUM; i++, classq++)
-+      {
-+              rwptr.bits32 = readl(&classq->qhdr->word1);
-+              while (rwptr.bits.rptr != rwptr.bits.wptr)
-+              {
-+                      curr_desc = (GMAC_RXDESC_T *)classq->desc_base + rwptr.bits.rptr;
-+                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-+                      dev_kfree_skb_irq(skb);
-+                      rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, classq->desc_num);
-+                      SET_RPTR(&classq->qhdr->word1, rwptr.bits.rptr);
-+                      rwptr.bits32 = readl(&classq->qhdr->word1);
-+              }  // while
-+              writel(0, &classq->qhdr->word1);
-+              classq->rwptr.bits32 = 0;
-+      } // for
-+
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_toe_q
-+*----------------------------------------------------------------------*/
-+#ifdef _TOEQ_CLASSQ_READY_
-+static void sl351x_gmac_release_toe_q(void)
-+{
-+      int                             i;
-+      TOE_INFO_T              *toe;
-+      TOEQ_INFO_T             *toeq_info;
-+      TOE_QHDR_T              *toe_qhdr;
-+      DMA_RWPTR_T             rwptr;
-+      volatile GMAC_RXDESC_T  *curr_desc;
-+      unsigned int    rptr, wptr;
-+      GMAC_RXDESC_T   *toe_curr_desc;
-+      struct sk_buff                  *skb;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      toe_qhdr = (TOE_QHDR_T *)TOE_TOE_QUE_HDR_BASE;
-+      for (i=0; i<TOE_TOE_QUEUE_NUM; i++, toe_qhdr++)
-+      {
-+              toeq_info = (TOEQ_INFO_T *)&toe->toeq[i];
-+              wptr = toe_qhdr->word1.bits.wptr;
-+              rptr = toe_qhdr->word1.bits.rptr;
-+              while (rptr != wptr)
-+              {
-+                      toe_curr_desc = (GMAC_RXDESC_T *)toeq_info->desc_base + rptr;
-+                      skb = (struct sk_buff *)(REG32(__va(toe_curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-+                      dev_kfree_skb_irq(skb);
-+                      rptr = RWPTR_ADVANCE_ONE(rptr, toeq_info->desc_num);
-+                      SET_RPTR(&toe_qhdr->word1.bits32, rptr);
-+                      wptr = toe_qhdr->word1.bits.wptr;
-+                      rptr = toe_qhdr->word1.bits.rptr;
-+              }
-+              toe_qhdr->word1.bits32 = 0;
-+              toeq_info->rwptr.bits32 = 0;
-+      }
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_intr_q
-+*----------------------------------------------------------------------*/
-+#ifdef _TOEQ_CLASSQ_READY_
-+static void sl351x_gmac_release_intr_q(void)
-+{
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_sw_free_q
-+*----------------------------------------------------------------------*/
-+static void sl351x_gmac_release_sw_free_q(void)
-+{
-+      TOE_INFO_T                              *toe;
-+      volatile DMA_RWPTR_T    fq_rwptr;
-+      volatile GMAC_RXDESC_T  *fq_desc;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+
-+      while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr)
-+      {
-+              struct sk_buff *skb;
-+              if ((skb = dev_alloc_skb(SW_RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-+              {
-+                      printk("%s::skb buffer allocation fail !\n",__func__); while(1);
-+              }
-+              // *(unsigned int *)(skb->data) = (unsigned int)skb;
-+              REG32(skb->data) = (unsigned long)skb;
-+              skb_reserve(skb, SKB_RESERVE_BYTES);
-+
-+              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
-+              fq_desc = (volatile GMAC_RXDESC_T *)toe->swfq_desc_base + fq_rwptr.bits.wptr;
-+              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
-+              SET_WPTR(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
-+              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+      }
-+
-+      toe->fq_rx_rwptr.bits.wptr = TOE_SW_FREEQ_DESC_NUM - 1;
-+      toe->fq_rx_rwptr.bits.rptr = 0;
-+      writel(toe->fq_rx_rwptr.bits32, TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+
-+}
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_hw_free_q
-+*----------------------------------------------------------------------*/
-+static void sl351x_gmac_release_hw_free_q(void)
-+{
-+      DMA_RWPTR_T                     rwptr_reg;
-+
-+#ifdef CONFIG_SL351x_NAT
-+      int                                     i;
-+      TOE_INFO_T                      *toe;
-+      GMAC_RXDESC_T           *desc_ptr;
-+      unsigned int            buf_ptr;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+      desc_ptr = (GMAC_RXDESC_T *)toe->hwfq_desc_base;
-+      buf_ptr = (unsigned int)toe->hwfq_buf_base_dma;
-+      for (i=0; i<TOE_HW_FREEQ_DESC_NUM; i++)
-+      {
-+              desc_ptr->word0.bits.buffer_size = HW_RX_BUF_SIZE;
-+              desc_ptr->word1.bits.sw_id = i;
-+              desc_ptr->word2.buf_adr = (unsigned int)buf_ptr;
-+              desc_ptr++;
-+              buf_ptr += HW_RX_BUF_SIZE;
-+      }
-+#endif
-+      rwptr_reg.bits.wptr = TOE_HW_FREEQ_DESC_NUM - 1;
-+      rwptr_reg.bits.rptr = 0;
-+      writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_release_hw_free_q
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static void sl351x_gmac_release_hwtx_q(void)
-+{
-+      int                             i;
-+      unsigned int    rwptr_addr;
-+
-+      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              writel(0, rwptr_addr);
-+              rwptr_addr+=4;
-+      }
-+      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              writel(0, rwptr_addr);
-+              rwptr_addr+=4;
-+      }
-+}
-+#endif
-+
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_save_reg
-+*----------------------------------------------------------------------*/
-+void sl351x_gmac_save_reg(void)
-+{
-+      int     i;
-+      volatile u32    *destp;
-+      unsigned int    srce_addr;
-+
-+      srce_addr = TOE_GLOBAL_BASE;
-+      destp = (volatile u32 *)toe_global_reg;
-+      for (i=0; i<TOE_GLOBAL_REG_SIZE; i++, destp++, srce_addr+=4)
-+              *destp = readl(srce_addr);
-+
-+      srce_addr = TOE_GMAC0_DMA_BASE;
-+      destp = (volatile u32 *)&toe_dma_reg[0][0];
-+      for (i=0; i<TOE_DMA_REG_SIZE; i++, destp++, srce_addr+=4)
-+      {
-+              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x38))
-+                      srce_addr = (TOE_GMAC0_DMA_BASE+0x50);
-+              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x58))
-+                      srce_addr = (TOE_GMAC0_DMA_BASE+0x70);
-+
-+              *destp = readl(srce_addr);
-+      }
-+      srce_addr = TOE_GMAC1_DMA_BASE;
-+      destp = (volatile u32 *)&toe_dma_reg[1][0];
-+      for (i=0; i<TOE_DMA_REG_SIZE; i++, destp++, srce_addr+=4)
-+      {
-+              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x38))
-+                      srce_addr = (TOE_GMAC0_DMA_BASE+0x50);
-+              if (srce_addr ==  (TOE_GMAC0_DMA_BASE+0x58))
-+                      srce_addr = (TOE_GMAC0_DMA_BASE+0x70);
-+
-+              *destp = readl(srce_addr);
-+      }
-+
-+      srce_addr = TOE_GMAC0_BASE;
-+      destp = (volatile u32 *)&toe_gmac_reg[0][0];
-+      for (i=0; i<TOE_GMAC_REG_SIZE; i++, destp++, srce_addr+=4)
-+              *destp = readl(srce_addr);
-+
-+      srce_addr = TOE_GMAC1_BASE;
-+      destp = (volatile u32 *)&toe_gmac_reg[1][0];
-+      for (i=0; i<TOE_GMAC_REG_SIZE; i++, destp++, srce_addr+=4)
-+              *destp = readl(srce_addr);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     sl351x_gmac_restore_reg
-+*----------------------------------------------------------------------*/
-+void sl351x_gmac_restore_reg(void)
-+{
-+      int     i;
-+      volatile u32    *srcep;
-+      unsigned int    dest_addr;
-+
-+      srcep = (volatile u32 *)&toe_dma_reg[0][0];
-+      dest_addr = TOE_GMAC0_DMA_BASE;
-+      for (i=0; i<TOE_DMA_REG_SIZE; i++, dest_addr+=4, srcep++)
-+      {
-+              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x38))
-+                      dest_addr = (TOE_GMAC0_DMA_BASE+0x50);
-+              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x58))
-+                      dest_addr = (TOE_GMAC0_DMA_BASE+0x70);
-+
-+              writel(*srcep, dest_addr);
-+              // gmac_write_reg(dest_addr, 0, *srcep, 0xffffffff);
-+      }
-+      srcep = (volatile u32 *)&toe_dma_reg[1][0];
-+      dest_addr = TOE_GMAC1_DMA_BASE;
-+      for (i=0; i<TOE_DMA_REG_SIZE; i++, dest_addr+=4, srcep++)
-+      {
-+              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x38))
-+                      dest_addr = (TOE_GMAC0_DMA_BASE+0x50);
-+              if (dest_addr == (TOE_GMAC0_DMA_BASE+0x58))
-+                      dest_addr = (TOE_GMAC0_DMA_BASE+0x70);
-+
-+              writel(*srcep, dest_addr);
-+              // gmac_write_reg(dest_addr, 0, *srcep, 0xffffffff);
-+      }
-+
-+      srcep = (volatile u32 *)&toe_gmac_reg[0][0];
-+      dest_addr = TOE_GMAC0_BASE;
-+      for (i=0; i<TOE_GMAC_REG_SIZE; i++, dest_addr+=4, srcep++)
-+              writel(*srcep, dest_addr);
-+
-+      srcep = (volatile u32 *)&toe_gmac_reg[1][0];
-+      dest_addr = TOE_GMAC1_BASE;
-+      for (i=0; i<TOE_GMAC_REG_SIZE; i++, dest_addr+=4, srcep++)
-+              writel(*srcep, dest_addr);
-+
-+      srcep = (volatile u32 *)toe_global_reg;
-+      dest_addr = TOE_GLOBAL_BASE;
-+      for (i=0; i<TOE_GLOBAL_REG_SIZE; i++, dest_addr+=4, srcep++)
-+              writel(*srcep, dest_addr);
-+
-+}
-+
-+#ifdef CONFIG_SL351x_NAT
-+/*----------------------------------------------------------------------
-+*     sl351x_nat_workaround_init
-+*----------------------------------------------------------------------*/
-+#define NAT_WORAROUND_DESC_POWER      (6)
-+#define NAT_WORAROUND_DESC_NUM                (2 << NAT_WORAROUND_DESC_POWER)
-+dma_addr_t sl351x_nat_workaround_desc_dma;
-+void sl351x_nat_workaround_init(void)
-+{
-+      unsigned int    desc_buf;
-+
-+      desc_buf = (unsigned int)DMA_MALLOC((NAT_WORAROUND_DESC_NUM * sizeof(GMAC_RXDESC_T)),
-+                                              (dma_addr_t *)&sl351x_nat_workaround_desc_dma) ;
-+      memset((void *)desc_buf, 0, NAT_WORAROUND_DESC_NUM * sizeof(GMAC_RXDESC_T));
-+
-+      // DMA Queue Base & Size
-+      writel((sl351x_nat_workaround_desc_dma & DMA_Q_BASE_MASK) | NAT_WORAROUND_DESC_POWER,
-+                      TOE_GLOBAL_BASE + 0x4080);
-+      writel(0, TOE_GLOBAL_BASE + 0x4084);
-+}
-+
-+/*----------------------------------------------------------------------
-+*     sl351x_nat_workaround_handler
-+*----------------------------------------------------------------------*/
-+#ifndef NAT_WORKAROUND_BY_RESET_GMAC
-+static void sl351x_nat_workaround_handler(void)
-+{
-+      int                                     i;
-+      DMA_RWPTR_T                     rwptr;
-+      GMAC_RXDESC_T           *desc_ptr;
-+      unsigned int            buf_ptr;
-+      TOE_INFO_T                      *toe;
-+      GMAC_CONFIG0_T          config0;
-+      unsigned int            rwptr_addr;
-+
-+      toe = (TOE_INFO_T *)&toe_private_data;
-+
-+      // disable Rx of GMAC-0 & 1
-+      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+      config0.bits.dis_rx = 1;
-+      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+      config0.bits.dis_rx = 1;
-+      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+
-+      // wait GMAC-0 HW Tx finished
-+      rwptr_addr = TOE_GMAC0_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              rwptr.bits32 = readl(rwptr_addr);
-+              if (rwptr.bits.rptr != rwptr.bits.wptr)
-+                      return; // wait the HW to send packets and release buffers
-+              rwptr_addr+=4;
-+      }
-+      rwptr_addr = TOE_GMAC1_DMA_BASE + GMAC_HW_TX_QUEUE0_PTR_REG;
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              rwptr.bits32 = readl(rwptr_addr);
-+              if (rwptr.bits.rptr != rwptr.bits.wptr)
-+                      return; // wait the HW to send packets and release buffers
-+              rwptr_addr+=4;
-+      }
-+
-+      // printk("sl351x_nat_workaround_handler %d\n", sl351x_nat_workaround_cnt);
-+      desc_ptr = (GMAC_RXDESC_T *)toe->hwfq_desc_base;
-+      buf_ptr = (unsigned int)toe->hwfq_buf_base_dma;
-+      for (i=0; i<TOE_HW_FREEQ_DESC_NUM; i++)
-+      {
-+              desc_ptr->word0.bits.buffer_size = HW_RX_BUF_SIZE;
-+              desc_ptr->word1.bits.sw_id = i;
-+              desc_ptr->word2.buf_adr = (unsigned int)buf_ptr;
-+              desc_ptr++;
-+              buf_ptr += HW_RX_BUF_SIZE;
-+      }
-+      rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
-+      rwptr.bits.wptr = RWPTR_RECEDE_ONE(rwptr.bits.rptr, TOE_HW_FREEQ_DESC_NUM);
-+      writel(rwptr.bits32, TOE_GLOBAL_BASE + GLOBAL_HWFQ_RWPTR_REG);
-+      writel(0, TOE_GLOBAL_BASE + 0x4084);
-+
-+      // Enable Rx of GMAC-0 & 1
-+      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
-+      config0.bits.dis_rx = 0;
-+      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
-+      config0.bits.dis_rx = 0;
-+      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
-+}
-+#endif
-+#endif // CONFIG_SL351x_NAT
-+
-+#endif // SL351x_GMAC_WORKAROUND
-+
-+/* get the mac addresses from flash
-+ *can't do this in module_init because mtd driver is initialized after ethernet
-+ */
-+static __init int sl351x_mac_address_init(void)
-+{
-+      GMAC_INFO_T             *tp;
-+      struct sockaddr sock;
-+      int i;
-+
-+      /* get mac address from FLASH */
-+      gmac_get_mac_address();
-+
-+      for (i = 0; i < GMAC_NUM; i++) {
-+              tp = (GMAC_INFO_T *)&toe_private_data.gmac[i];
-+              memcpy(&sock.sa_data[0],&eth_mac[tp->port_id][0],6);
-+              gmac_set_mac_address(tp->dev,(void *)&sock);
-+      }
-+
-+        return 0;
-+}
-+late_initcall(sl351x_mac_address_init);
-+
-+
---- /dev/null
-+++ b/drivers/net/sl351x_hash.c
-@@ -0,0 +1,713 @@
-+/**************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
-+*--------------------------------------------------------------------------
-+* Name                        : sl351x_hash.c
-+* Description :
-+*             Handle Storlink SL351x Hash Functions
-+*
-+* History
-+*
-+*     Date            Writer          Description
-+*----------------------------------------------------------------------------
-+*     03/13/2006      Gary Chen       Create and implement
-+*
-+****************************************************************************/
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/compiler.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/delay.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/completion.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/semaphore.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/arch/it8712.h>
-+#include <linux/mtd/kvctl.h>
-+#include <linux/skbuff.h>
-+#include <linux/in.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <linux/list.h>
-+#define        MIDWAY
-+#define        SL_LEPUS
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/sl351x_gmac.h>
-+#include <asm/arch/sl351x_hash_cfg.h>
-+
-+#ifndef RXTOE_DEBUG
-+#define RXTOE_DEBUG
-+#endif
-+#undef RXTOE_DEBUG
-+
-+/*----------------------------------------------------------------------
-+* Definition
-+*----------------------------------------------------------------------*/
-+#define       hash_printf                             printk
-+
-+#define HASH_TIMER_PERIOD             (30)    // seconds
-+#define HASH_ILLEGAL_INDEX            0xffff
-+
-+/*----------------------------------------------------------------------
-+* Variables
-+*----------------------------------------------------------------------*/
-+u32                                   hash_nat_owner_bits[HASH_TOTAL_ENTRIES/32];
-+char                          hash_tables[HASH_TOTAL_ENTRIES][HASH_MAX_BYTES] __attribute__ ((aligned(16)));
-+static struct timer_list hash_timer_obj;
-+LIST_HEAD(hash_timeout_list);
-+
-+/*----------------------------------------------------------------------
-+* Functions
-+*----------------------------------------------------------------------*/
-+void dm_long(u32 location, int length);
-+static void hash_timer_func(u32 data);
-+
-+/*----------------------------------------------------------------------
-+* hash_init
-+*----------------------------------------------------------------------*/
-+void sl351x_hash_init(void)
-+{
-+      int i;
-+      volatile u32 *dp1, *dp2, dword;
-+
-+      dp1 = (volatile u32 *) TOE_V_BIT_BASE;
-+      dp2 = (volatile u32 *) TOE_A_BIT_BASE;
-+
-+      for (i=0; i<HASH_TOTAL_ENTRIES/32; i++)
-+      {
-+              *dp1++ = 0;
-+              dword = *dp2++; // read-clear
-+      }
-+      memset((void *)&hash_nat_owner_bits, 0, sizeof(hash_nat_owner_bits));
-+      memset((void *)&hash_tables, 0, sizeof(hash_tables));
-+
-+      init_timer(&hash_timer_obj);
-+      hash_timer_obj.expires = jiffies + (HASH_TIMER_PERIOD * HZ);
-+      hash_timer_obj.data = (unsigned long)&hash_timer_obj;
-+      hash_timer_obj.function = (void *)&hash_timer_func;
-+      add_timer(&hash_timer_obj);
-+
-+#if (HASH_MAX_BYTES == 128)
-+      writel((unsigned long)__pa(&hash_tables) | 3,   // 32 words
-+                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
-+#elif (HASH_MAX_BYTES == 64)
-+      writel((unsigned long)__pa(&hash_tables) | 2,   // 16 words
-+                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
-+#else
-+      #error Incorrect setting for HASH_MAX_BYTES
-+#endif
-+
-+}
-+/*----------------------------------------------------------------------
-+* hash_add_entry
-+*----------------------------------------------------------------------*/
-+int hash_add_entry(HASH_ENTRY_T *entry)
-+{
-+      int     rc;
-+      u32     key[HASH_MAX_DWORDS];
-+      rc = hash_build_keys((u32 *)&key, entry);
-+      if (rc < 0)
-+              return -1;
-+      hash_write_entry(entry, (unsigned char*) &key[0]);
-+//    hash_set_valid_flag(entry->index, 1);
-+//    printk("Dump hash key!\n");
-+//    dump_hash_key(entry);
-+      return entry->index;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_set_valid_flag
-+*----------------------------------------------------------------------*/
-+void hash_set_valid_flag(int index, int valid)
-+{
-+      register u32 reg32;
-+
-+      reg32 = TOE_V_BIT_BASE + (index/32) * 4;
-+
-+      if (valid)
-+      {
-+              writel(readl(reg32) | (1 << (index%32)), reg32);
-+      }
-+      else
-+      {
-+              writel(readl(reg32) & ~(1 << (index%32)), reg32);
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_set_nat_owner_flag
-+*----------------------------------------------------------------------*/
-+void hash_set_nat_owner_flag(int index, int valid)
-+{
-+      if (valid)
-+      {
-+              hash_nat_owner_bits[index/32] |= (1 << (index % 32));
-+      }
-+      else
-+      {
-+              hash_nat_owner_bits[index/32] &= ~(1 << (index % 32));
-+      }
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* hash_build_keys
-+*----------------------------------------------------------------------*/
-+int hash_build_keys(u32 *destp, HASH_ENTRY_T *entry)
-+{
-+      u32     data;
-+      unsigned char   *cp;
-+      int                             i, j;
-+      unsigned short  index;
-+      int                     total;
-+
-+      memset((void *)destp, 0, HASH_MAX_BYTES);
-+      cp = (unsigned char *)destp;
-+
-+      if (entry->key_present.port || entry->key_present.Ethertype)
-+      {
-+              HASH_PUSH_WORD(cp, entry->key.Ethertype);               // word 0
-+              HASH_PUSH_BYTE(cp, entry->key.port);                    // Byte 2
-+              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
-+      }
-+      else
-+      {
-+              HASH_PUSH_DWORD(cp, 0);
-+      }
-+
-+      if (entry->key_present.da || entry->key_present.sa)
-+      {
-+              unsigned char mac[4];
-+              if (entry->key_present.da)
-+              {
-+                      for (i=0; i<4; i++)
-+                              HASH_PUSH_BYTE(cp, entry->key.da[i]);
-+              }
-+              mac[0] = (entry->key_present.da) ? entry->key.da[4] : 0;
-+              mac[1] = (entry->key_present.da) ? entry->key.da[5] : 0;
-+              mac[2] = (entry->key_present.sa) ? entry->key.sa[0] : 0;
-+              mac[3] = (entry->key_present.sa) ? entry->key.sa[1] : 0;
-+              data = mac[0] + (mac[1]<<8) + (mac[2]<<16) + (mac[3]<<24);
-+              HASH_PUSH_DWORD(cp, data);
-+              if (entry->key_present.sa)
-+              {
-+                      for (i=2; i<6; i++)
-+                              HASH_PUSH_BYTE(cp, entry->key.sa[i]);
-+              }
-+      }
-+
-+      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
-+      {
-+              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
-+              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
-+      }
-+      if (entry->key_present.ipv4_hdrlen || entry->key_present.ip_tos || entry->key_present.ip_protocol)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.ip_protocol);             // Byte 0
-+              HASH_PUSH_BYTE(cp, entry->key.ip_tos);                  // Byte 1
-+              HASH_PUSH_BYTE(cp, entry->key.ipv4_hdrlen);             // Byte 2
-+              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
-+      }
-+
-+      if (entry->key_present.ipv6_flow_label)
-+      {
-+              HASH_PUSH_DWORD(cp, entry->key.ipv6_flow_label);        // low word
-+      }
-+      if (entry->key_present.sip)
-+      {
-+              // input (entry->key.sip[i]) is network-oriented
-+              // output (hash key) is host-oriented
-+              for (i=3; i>=0; i--)
-+                      HASH_PUSH_BYTE(cp, entry->key.sip[i]);
-+              if (entry->key.ipv6)
-+              {
-+                      for (i=4; i<16; i+=4)
-+                      {
-+                              for (j=i+3; j>=i; j--)
-+                                      HASH_PUSH_BYTE(cp, entry->key.sip[j]);
-+                      }
-+              }
-+      }
-+      if (entry->key_present.dip)
-+      {
-+              // input (entry->key.sip[i]) is network-oriented
-+              // output (hash key) is host-oriented
-+              for (i=3; i>=0; i--)
-+                      HASH_PUSH_BYTE(cp, entry->key.dip[i]);
-+              if (entry->key.ipv6)
-+              {
-+                      for (i=4; i<16; i+=4)
-+                      {
-+                              for (j=i+3; j>=i; j--)
-+                                      HASH_PUSH_BYTE(cp, entry->key.dip[j]);
-+                      }
-+              }
-+      }
-+
-+      if (entry->key_present.l4_bytes_0_3)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
-+      }
-+      if (entry->key_present.l4_bytes_4_7)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[4]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[5]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[6]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[7]);
-+      }
-+      if (entry->key_present.l4_bytes_8_11)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[8]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[9]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[10]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[11]);
-+      }
-+      if (entry->key_present.l4_bytes_12_15)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[12]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[13]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[14]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[15]);
-+      }
-+      if (entry->key_present.l4_bytes_16_19)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[16]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[17]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[18]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[19]);
-+      }
-+      if (entry->key_present.l4_bytes_20_23)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[20]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[21]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[22]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[23]);
-+      }
-+      if (entry->key_present.l7_bytes_0_3)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[0]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[1]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[2]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[3]);
-+      }
-+      if (entry->key_present.l7_bytes_4_7)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[4]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[5]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[6]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[7]);
-+      }
-+      if (entry->key_present.l7_bytes_8_11)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[8]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[9]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[10]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[11]);
-+      }
-+      if (entry->key_present.l7_bytes_12_15)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[12]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[13]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[14]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[15]);
-+      }
-+      if (entry->key_present.l7_bytes_16_19)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[16]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[17]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[18]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[19]);
-+      }
-+      if (entry->key_present.l7_bytes_20_23)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[20]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[21]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[22]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[23]);
-+      }
-+
-+      // get hash index
-+      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
-+
-+      if (total > HASH_MAX_KEY_DWORD)
-+      {
-+              //hash_printf("Total key words (%d) is too large (> %d)!\n",
-+              //                              total, HASH_MAX_KEY_DWORD);
-+              return -1;
-+      }
-+
-+      if (entry->key_present.port || entry->key_present.Ethertype)
-+              index = hash_gen_crc16((unsigned char *)destp, total * 4);
-+      else
-+      {
-+              if (total == 1)
-+              {
-+                      hash_printf("No key is assigned!\n");
-+                      return -1;
-+              }
-+
-+              index = hash_gen_crc16((unsigned char *)(destp+1), (total-1) * 4);
-+      }
-+
-+      entry->index = index & HASH_BITS_MASK;
-+
-+      //hash_printf("Total key words = %d, Hash Index= %d\n",
-+      //                              total, entry->index);
-+
-+      cp = (unsigned char *)destp;
-+      cp+=3;
-+      HASH_PUSH_BYTE(cp, entry->rule);        // rule
-+
-+      entry->total_dwords = total;
-+
-+      return total;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_build_nat_keys
-+*----------------------------------------------------------------------*/
-+void hash_build_nat_keys(u32 *destp, HASH_ENTRY_T *entry)
-+{
-+      unsigned char   *cp;
-+      int                             i;
-+      unsigned short  index;
-+      int                     total;
-+
-+      memset((void *)destp, 0, HASH_MAX_BYTES);
-+
-+      cp = (unsigned char *)destp + 2;
-+      HASH_PUSH_BYTE(cp, entry->key.port);
-+      cp++;
-+
-+      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
-+      {
-+              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
-+              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
-+      }
-+
-+      HASH_PUSH_BYTE(cp, entry->key.ip_protocol);
-+      cp+=3;
-+
-+      // input (entry->key.sip[i]) is network-oriented
-+      // output (hash key) is host-oriented
-+      for (i=3; i>=0; i--)
-+              HASH_PUSH_BYTE(cp, entry->key.sip[i]);
-+
-+      // input (entry->key.sip[i]) is network-oriented
-+      // output (hash key) is host-oriented
-+      for (i=3; i>=0; i--)
-+              HASH_PUSH_BYTE(cp, entry->key.dip[i]);
-+
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
-+
-+      // get hash index
-+      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
-+
-+      index = hash_gen_crc16((unsigned char *)destp, total * 4);
-+      entry->index = index & ((1 << HASH_BITS) - 1);
-+
-+      cp = (unsigned char *)destp;
-+      cp+=3;
-+      HASH_PUSH_BYTE(cp, entry->rule);        // rule
-+
-+      entry->total_dwords = total;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_build_toe_keys
-+*----------------------------------------------------------------------*/
-+int hash_build_toe_keys(u32 *destp, HASH_ENTRY_T *entry)
-+{
-+      unsigned long   data;
-+      unsigned char   *cp;
-+      unsigned short  index;
-+      int     i;
-+      int total;
-+      //printk("%s\n", __func__);
-+      memset((void*)destp, 0, HASH_MAX_BYTES);
-+      cp = (unsigned char*)destp;
-+
-+      if(entry->key_present.port || entry->key_present.Ethertype) {
-+              data = (entry->key.port << 16) + entry->key.Ethertype;
-+              HASH_PUSH_DWORD(cp, data);
-+      } else
-+              HASH_PUSH_DWORD(cp, 0);
-+
-+      if (entry->key_present.da || entry->key_present.sa) {
-+              unsigned char   mac[4];
-+              if (entry->key_present.da) {
-+                      data = (entry->key.da[0]) + (entry->key.da[1] << 8) +
-+                                 (entry->key.da[2] << 16) + (entry->key.da[3] <<24);
-+                      HASH_PUSH_DWORD(cp, data);
-+              }
-+              mac[0] = (entry->key_present.da) ? entry->key.da[4] : 0;
-+              mac[1] = (entry->key_present.da) ? entry->key.da[5] : 0;
-+              mac[2] = (entry->key_present.sa) ? entry->key.sa[0] : 0;
-+              mac[3] = (entry->key_present.sa) ? entry->key.sa[1] : 0;
-+              data = mac[0] + (mac[1]<<8) + (mac[2]<<16) + (mac[3]<<24);
-+              HASH_PUSH_DWORD(cp, data);
-+              if (entry->key_present.sa) {
-+                      data = (entry->key.sa[2]) + (entry->key.sa[3] << 8) +
-+                                 (entry->key.sa[4] << 16) + (entry->key.sa[5] <<24);
-+                      HASH_PUSH_DWORD(cp, data);
-+              }
-+      }
-+
-+      if (entry->key_present.ip_protocol) {
-+              unsigned char ip_protocol;
-+              ip_protocol = entry->key.ip_protocol;
-+              data = ip_protocol;
-+              HASH_PUSH_DWORD(cp, data);
-+      }
-+
-+      if (entry->key_present.ipv6_flow_label) {
-+              unsigned long flow_label;
-+              flow_label  = entry->key.ipv6_flow_label;
-+              data = flow_label & 0xfffff;
-+              HASH_PUSH_DWORD(cp, data);
-+      }
-+
-+      if (entry->key_present.sip)     {
-+              {
-+                      data = IPIV(entry->key.sip[0], entry->key.sip[1],
-+                                      entry->key.sip[2], entry->key.sip[3]);
-+                      HASH_PUSH_DWORD(cp, data);
-+                      if (entry->key.ipv6) {
-+                              for (i=4; i<16; i+=4) {
-+                                      data = IPIV(entry->key.sip[i+0], entry->key.sip[i+1],
-+                                                      entry->key.sip[i+2], entry->key.sip[i+3]);
-+                                      HASH_PUSH_DWORD(cp, data);
-+                              }
-+                      }
-+              }
-+      }
-+
-+      if (entry->key_present.dip)     {
-+              {
-+                      data = IPIV(entry->key.dip[0], entry->key.dip[1],
-+                                              entry->key.dip[2], entry->key.dip[3]);
-+                      HASH_PUSH_DWORD(cp, data);
-+                      if (entry->key.ipv6) {
-+                              for (i=4; i<16; i+=4) {
-+                                      data = IPIV(entry->key.dip[i+0], entry->key.dip[i+1],
-+                                                              entry->key.dip[i+2], entry->key.dip[i+3]);
-+                                      HASH_PUSH_DWORD(cp, data);
-+                              }
-+                      }
-+              }
-+      }
-+      if (entry->key_present.l4_bytes_0_3)
-+      {
-+              unsigned char *datap;
-+              datap = &entry->key.l4_bytes[0];
-+              data =  datap[0] +      (datap[1] << 8) + (datap[2] << 16) + (datap[3] << 24);
-+              HASH_PUSH_DWORD(cp, data);
-+      }
-+      if (entry->key_present.l7_bytes_0_3)
-+      {
-+              unsigned char *datap;
-+              datap = &entry->key.l7_bytes[0];
-+              data =  datap[0] +      (datap[1] << 8) + (datap[2] << 16) + (datap[3] << 24);
-+              HASH_PUSH_DWORD(cp, data);
-+      }
-+      if (entry->key_present.l7_bytes_4_7)
-+      {
-+              unsigned char *datap;
-+              datap = &entry->key.l7_bytes[4];
-+              data =  datap[0] +      (datap[1] << 8) + (datap[2] << 16) + (datap[3] << 24);
-+              HASH_PUSH_DWORD(cp, data);
-+      }
-+
-+      total = (unsigned long)((unsigned long)cp - (unsigned long)destp) / (sizeof(u32));
-+      if (total > HASH_MAX_KEY_DWORD) {
-+              //printf("Total key words (%d) is too large (> %d)!\n",
-+              //              total, HASH_MAX_KEY_DWORD);
-+              return -1;
-+      }
-+      index = hash_gen_crc16((unsigned char*)(destp + 1), (total-1)*4);
-+      entry->index = index & ((1 << HASH_BITS)-1);
-+
-+      cp = (unsigned char*) destp;
-+      cp += 3;
-+      HASH_PUSH_BYTE(cp, entry->rule);
-+      entry->total_dwords = total;
-+      return total;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_add_toe_entry
-+*----------------------------------------------------------------------*/
-+int hash_add_toe_entry(HASH_ENTRY_T *entry)
-+{
-+      int     rc;
-+      u32     key[HASH_MAX_DWORDS];
-+
-+      rc = hash_build_toe_keys((u32 *)&key, entry);
-+      if (rc < 0)
-+              return -1;
-+      hash_write_entry(entry, (unsigned char*) &key[0]);
-+      //hash_dump_entry(entry->index);
-+//    hash_set_valid_flag(entry->index, 1);
-+//    printk("Dump hash key!\n");
-+//    dump_hash_key(entry);
-+      return entry->index;
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* hash_write_entry
-+*----------------------------------------------------------------------*/
-+int hash_write_entry(HASH_ENTRY_T *entry, unsigned char *key)
-+{
-+      int             i;
-+      u32             *srcep, *destp, *destp2;
-+
-+      srcep = (u32 *)key;
-+      destp2 = destp = (u32 *)&hash_tables[entry->index][0];
-+
-+      for (i=0; i<(entry->total_dwords); i++, srcep++, destp++)
-+              *destp = *srcep;
-+
-+      srcep = (u32 *)&entry->action;
-+      *destp++ = *srcep;
-+
-+      srcep = (u32 *)&entry->param;
-+      for (i=0; i<(sizeof(ENTRY_PARAM_T)/sizeof(*destp)); i++, srcep++, destp++)
-+              *destp = *srcep;
-+
-+      memset(destp, 0, (HASH_MAX_DWORDS-entry->total_dwords-HASH_ACTION_DWORDS) * sizeof(u32));
-+
-+      consistent_sync(destp2, (entry->total_dwords+HASH_ACTION_DWORDS) * 4, PCI_DMA_TODEVICE);
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_timer_func
-+*----------------------------------------------------------------------*/
-+static void hash_timer_func(u32 data)
-+{
-+      int                                     i, j, idx;
-+      volatile u32            *own_p, *valid_p;
-+      u32                                     own_bits, a_bits;
-+      int                                     period = HASH_TIMER_PERIOD;
-+
-+      valid_p = (volatile u32 *)TOE_V_BIT_BASE;
-+      own_p = (volatile u32 *)hash_nat_owner_bits;
-+      for (i=0, idx=0; i<(HASH_TOTAL_ENTRIES/32); i++, own_p++, valid_p++, idx+=32)
-+      {
-+              a_bits = readl(TOE_A_BIT_BASE + (i*4));
-+              own_bits = *own_p;
-+              if (own_bits)
-+              {
-+                      for (j=0; own_bits && j<32; j++)
-+                      {
-+                              if (own_bits & 1)
-+                              {
-+                                      short *counter_p, *interval_p;
-+                                      NAT_HASH_ENTRY_T        *nat_entry;
-+                                      GRE_HASH_ENTRY_T        *gre_entry;
-+                                      nat_entry = (NAT_HASH_ENTRY_T *)hash_get_entry(idx+j);
-+                                      gre_entry = (GRE_HASH_ENTRY_T *)nat_entry;
-+                                      if (nat_entry->key.ip_protocol == IPPROTO_GRE)
-+                                      {
-+                                              counter_p = (short *)&gre_entry->tmo.counter;
-+                                              interval_p = (short *)&gre_entry->tmo.interval;
-+                                      }
-+                                      else
-+                                      {
-+                                              counter_p = (short *)&nat_entry->tmo.counter;
-+                                              interval_p = (short *)&nat_entry->tmo.interval;
-+                                      }
-+                                      if (a_bits & 1)
-+                                      {
-+                                              *counter_p = *interval_p;
-+                                      }
-+                                      else
-+                                      {
-+                                              *counter_p -= HASH_TIMER_PERIOD;
-+                                              if (*counter_p <= 0)
-+                                              {
-+                                                      *valid_p &= ~(1 << j);          // invalidate it
-+                                                      *own_p &= ~(1 << j);            // release ownership for NAT
-+                                                      *counter_p = 0;
-+                                                      // hash_printf("%lu %s: Clear hash index: %d\n", jiffies/HZ, __func__, i*32+j);
-+                                              }
-+                                              else if (period > *counter_p)
-+                                              {
-+                                                      period = *counter_p;
-+                                              }
-+                                      }
-+                              }
-+                              a_bits >>= 1;
-+                              own_bits >>=1;
-+                      }
-+              }
-+      }
-+
-+      hash_timer_obj.expires = jiffies + (period * HZ);
-+      add_timer((struct timer_list *)data);
-+}
-+
-+/*----------------------------------------------------------------------
-+* dm_long
-+*----------------------------------------------------------------------*/
-+void dm_long(u32 location, int length)
-+{
-+      u32             *start_p, *curr_p, *end_p;
-+      u32             *datap, data;
-+      int             i;
-+
-+      //if (length > 1024)
-+      //      length = 1024;
-+
-+      start_p = (u32 *)location;
-+      end_p = (u32 *)location + length;
-+      curr_p = (u32 *)((u32)location & 0xfffffff0);
-+      datap = (u32 *)location;
-+      while (curr_p < end_p)
-+      {
-+              hash_printf("0x%08x: ",(u32)curr_p & 0xfffffff0);
-+              for (i=0; i<4; i++)
-+              {
-+                      if (curr_p < start_p || curr_p >= end_p)
-+               hash_printf("         ");
-+                      else
-+                      {
-+                              data = *datap;
-+                              hash_printf("%08X ", data);
-+                      }
-+                      if (i==1)
-+              hash_printf("- ");
-+
-+                      curr_p++;
-+                      datap++;
-+              }
-+        hash_printf("\n");
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_dump_entry
-+*----------------------------------------------------------------------*/
-+void hash_dump_entry(int index)
-+{
-+      hash_printf("Hash Index %d:\n", index);
-+      dm_long((u32)&hash_tables[index][0], HASH_MAX_DWORDS);
-+}
-+
-+
---- /dev/null
-+++ b/drivers/net/sl351x_nat.c
-@@ -0,0 +1,1736 @@
-+/****************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
-+*----------------------------------------------------------------------------
-+* Name                        : sl351x_nat.c
-+* Description :
-+*             Handle Storlink SL351x NAT Functions
-+*
-+*
-+* Packet Flow:
-+*
-+*            (xmit)+<--- SW NAT -->+(xmit)
-+*                  |       ^^      |
-+*                  |       ||      |
-+*                  |       ||      |
-+*   Client <---> GMAC-x  HW-NAT  GMAC-y  <---> Server
-+*
-+*
-+* History
-+*
-+*     Date            Writer          Description
-+*----------------------------------------------------------------------------
-+*     03/13/2006      Gary Chen       Create and implement
-+*
-+*
-+****************************************************************************/
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/compiler.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/delay.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/completion.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/semaphore.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/arch/it8712.h>
-+#include <linux/mtd/kvctl.h>
-+#include <linux/skbuff.h>
-+#include <linux/if_ether.h>
-+#include <linux/if_pppox.h>
-+#include <linux/in.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <linux/udp.h>
-+#include <linux/ppp_defs.h>
-+
-+#define        MIDWAY
-+#define        SL_LEPUS
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/sl351x_gmac.h>
-+#include <asm/arch/sl351x_hash_cfg.h>
-+#include <asm/arch/sl351x_nat_cfg.h>
-+#ifdef CONFIG_NETFILTER
-+// #include <linux/netfilter/nf_conntrack.h>
-+#include <linux/netfilter/nf_conntrack_tcp.h>
-+#endif
-+
-+//#define NAT_DEBUG_MSG               1
-+#define _NOT_CHECK_SIP_DIP
-+//#define     SL351x_NAT_TEST_BY_SMARTBITS            1       // Initialize 32 hash entries and test by SmartBITS
-+#define VITESSE_G5SWITCH      1
-+
-+#ifdef CONFIG_SL351x_NAT
-+
-+/*----------------------------------------------------------------------
-+* Definition
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL3516_ASIC
-+#define CONFIG_SL351x_NAT_TCP_UDP
-+#define CONFIG_SL351x_NAT_GRE
-+#define CONFIG_SL351x_TCP_UDP_RULE_ID 0
-+#define CONFIG_SL351x_GRE_RULE_ID             1
-+#else
-+#define CONFIG_SL351x_NAT_TCP_UDP
-+//#define CONFIG_SL351x_NAT_GRE
-+#define CONFIG_SL351x_TCP_UDP_RULE_ID 0
-+#define CONFIG_SL351x_GRE_RULE_ID             0
-+#endif
-+
-+#define       nat_printf                                      printk
-+#define NAT_FTP_CTRL_PORT                     (21)    // TCP
-+#define NAT_H323_PORT                         (1720)  // TCP
-+#define NAT_T120_PORT                         (1503)  // TCP
-+#define NAT_PPTP_PORT                         (1723)  // TCP
-+#define NAT_TFTP_PORT                                 (69)    // UDP
-+#define NAT_DNS_PORT                          (53)    // UDP
-+#define NAT_NTP_PORT                          (123)   // UDP
-+#define NAT_RAS_PORT                          (1719)  // UDP
-+#define NAT_BOOTP67_PORT                      (67)    // UDP
-+#define NAT_BOOTP68_PORT                      (68)    // UDP
-+
-+#define NAT_TCP_PORT_MAX                      64
-+#define NAT_UDP_PORT_MAX                      64
-+
-+#define GRE_PROTOCOL                          (0x880b)
-+#define GRE_PROTOCOL_SWAP                     __constant_htons(0x880b)
-+
-+#ifdef VITESSE_G5SWITCH
-+extern int Giga_switch;
-+#endif
-+
-+typedef struct
-+{
-+      u16             flags_ver;
-+      u16             protocol;
-+      u16             payload_length;
-+      u16             call_id;
-+      u32             seq;
-+      u32             ack;
-+} GRE_PKTHDR_T;
-+
-+/*----------------------------------------------------------------------
-+* NAT Configuration
-+*
-+* Note: Any change for network setting, the NAT configuration should
-+*       be changed also.
-+*     cfg->lan_port   0 if GMAC-0, 1: if GMAC-1
-+*     cfg->wan_port   0 if GMAC-0, 1: if GMAC-1
-+*     cfg->lan_ipaddr, cfg->lan_gateway, cfg->lan_netmask
-+*     cfg->wan_ipaddr, cfg->wan_gateway, cfg->wan_netmask
-+*
-+*----------------------------------------------------------------------*/
-+NAT_CFG_T             nat_cfg;
-+static int            nat_initialized;
-+u32                   nat_collision;
-+
-+#ifdef CONFIG_SL351x_NAT_TCP_UDP
-+static u16            fixed_tcp_port_list[]={NAT_FTP_CTRL_PORT,
-+                                                                              NAT_H323_PORT,
-+                                                                              // NAT_T120_PORT,
-+                                                                              NAT_PPTP_PORT,
-+                                                                              0};
-+static u16            fixed_udp_port_list[]={NAT_DNS_PORT,
-+                                                                              NAT_NTP_PORT,
-+                                                                              NAT_TFTP_PORT,
-+                                                                              NAT_RAS_PORT,
-+                                                                              NAT_BOOTP67_PORT,
-+                                                                              NAT_BOOTP68_PORT,
-+                                                                              0};
-+#endif
-+
-+// #define _HAVE_DYNAMIC_PORT_LIST
-+#ifdef _HAVE_DYNAMIC_PORT_LIST
-+static u16            dynamic_tcp_port_list[NAT_TCP_PORT_MAX+1];
-+static u16            dynamic_udp_port_list[NAT_UDP_PORT_MAX+1]};
-+#endif
-+
-+/*----------------------------------------------------------------------
-+* Functions
-+*----------------------------------------------------------------------*/
-+int sl351x_nat_tcp_udp_output(struct sk_buff *skb, int port);
-+int sl351x_nat_udp_output(struct sk_buff *skb, int port);
-+int sl351x_nat_gre_output(struct sk_buff *skb, int port);
-+
-+extern int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2);
-+extern void hash_dump_entry(int index);
-+extern void mac_get_hw_tx_weight(struct net_device *dev, char *weight);
-+extern void mac_set_hw_tx_weight(struct net_device *dev, char *weight);
-+
-+#ifdef SL351x_NAT_TEST_BY_SMARTBITS
-+static void nat_init_test_entry(void);
-+#endif
-+/*----------------------------------------------------------------------
-+* sl351x_nat_init
-+*     initialize a NAT matching rule
-+*     Called by SL351x Driver
-+*             key             : port, protocol, Sip, Dip, Sport, Dport
-+*             Action  : Srce Q: HW Free Queue,
-+*                               Dest Q: HW TxQ
-+*                               Change DA
-+*                               Change SA
-+*                 Change Sip or Dip
-+*                       Change Sport or Dport
-+*----------------------------------------------------------------------*/
-+void sl351x_nat_init(void)
-+{
-+      int                                     rc;
-+      GMAC_MRxCR0_T           mrxcr0;
-+      GMAC_MRxCR1_T           mrxcr1;
-+      GMAC_MRxCR2_T           mrxcr2;
-+      NAT_CFG_T                       *cfg;
-+
-+      if (nat_initialized)
-+              return;
-+
-+      nat_initialized = 1;
-+
-+      if ((sizeof(NAT_HASH_ENTRY_T) > HASH_MAX_BYTES) ||
-+              (sizeof(GRE_HASH_ENTRY_T) > HASH_MAX_BYTES))
-+      {
-+              nat_printf("NAT_HASH_ENTRY_T structure Size is too larger!\n");
-+              while(1);
-+      }
-+
-+      cfg = (NAT_CFG_T *)&nat_cfg;
-+      memset((void *)cfg, 0, sizeof(NAT_CFG_T));
-+#ifdef _HAVE_DYNAMIC_PORT_LIST
-+      memset((void *)dynamic_tcp_port_list, 0, sizeof(dynamic_tcp_port_list));
-+      memset((void *)dynamic_udp_port_list, 0, sizeof(dynamic_udp_port_list));
-+#endif
-+
-+#ifdef VITESSE_G5SWITCH
-+      if(Giga_switch)
-+      {
-+              cfg->enabled                    = 1;
-+              cfg->tcp_udp_rule_id    = CONFIG_SL351x_TCP_UDP_RULE_ID;
-+              cfg->gre_rule_id                = CONFIG_SL351x_GRE_RULE_ID;
-+              cfg->lan_port                   = 1;
-+              cfg->wan_port                   = 0;
-+              cfg->default_hw_txq     = 3;
-+              cfg->tcp_tmo_interval   = 60;
-+              cfg->udp_tmo_interval   = 180;
-+              cfg->gre_tmo_interval   = 60;
-+      }
-+      else
-+      {
-+              cfg->enabled                    = 1;
-+              cfg->tcp_udp_rule_id    = CONFIG_SL351x_TCP_UDP_RULE_ID;
-+              cfg->gre_rule_id                = CONFIG_SL351x_GRE_RULE_ID;
-+              cfg->lan_port                   = 0;
-+              cfg->wan_port                   = 1;
-+              cfg->default_hw_txq     = 3;
-+              cfg->tcp_tmo_interval   = 60;
-+              cfg->udp_tmo_interval   = 180;
-+              cfg->gre_tmo_interval   = 60;
-+
-+      }
-+#endif
-+
-+#if 1 //      debug purpose
-+      cfg->ipcfg[0].total                             = 1;
-+      cfg->ipcfg[0].entry[0].ipaddr   = IPIV(192,168,2,92);
-+      cfg->ipcfg[0].entry[0].netmask  = IPIV(255,255,255,0);
-+      cfg->ipcfg[1].total                             = 1;
-+      cfg->ipcfg[1].entry[0].ipaddr   = IPIV(192,168,1,200);
-+      cfg->ipcfg[1].entry[0].netmask  = IPIV(255,255,255,0);
-+#endif
-+
-+#if 1
-+      cfg->xport.total = 0;
-+#else
-+      cfg->xport.total = 4;
-+
-+      // H.323/H.225 Call setup
-+      cfg->xport.entry[0].protocol = IPPROTO_TCP;
-+      cfg->xport.entry[0].sport_start = 0;
-+      cfg->xport.entry[0].sport_end = 0;
-+      cfg->xport.entry[0].dport_start = 1720;
-+      cfg->xport.entry[0].dport_end = 1720;
-+      cfg->xport.entry[1].protocol = IPPROTO_TCP;
-+      cfg->xport.entry[1].sport_start = 1720;
-+      cfg->xport.entry[1].sport_end = 1720;
-+      cfg->xport.entry[1].dport_start = 0;
-+      cfg->xport.entry[1].dport_end = 0;
-+
-+      // RAS Setup
-+      cfg->xport.entry[2].protocol = IPPROTO_UDP;
-+      cfg->xport.entry[2].sport_start = 0;
-+      cfg->xport.entry[2].sport_end = 0;
-+      cfg->xport.entry[2].dport_start = 1719;
-+      cfg->xport.entry[2].dport_end = 1719;
-+      cfg->xport.entry[3].protocol = IPPROTO_UDP;
-+      cfg->xport.entry[3].sport_start = 1719;
-+      cfg->xport.entry[3].sport_end = 1719;
-+      cfg->xport.entry[3].dport_start = 0;
-+      cfg->xport.entry[3].dport_end = 0;
-+#endif
-+
-+#ifdef CONFIG_SL351x_NAT_TCP_UDP
-+      mrxcr0.bits32 = 0;
-+      mrxcr1.bits32 = 0;
-+      mrxcr2.bits32 = 0;
-+      mrxcr0.bits.port = 1;
-+      mrxcr0.bits.l3 = 1;
-+      mrxcr0.bits.l4 = 1;
-+      mrxcr1.bits.sip = 1;
-+      mrxcr1.bits.dip = 1;
-+      mrxcr1.bits.l4_byte0_15 = 0x0f; // Byte 0-3
-+      mrxcr0.bits.sprx = 3;
-+
-+      rc = mac_set_rule_reg(cfg->lan_port, cfg->tcp_udp_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
-+      if (rc < 0)
-+      {
-+              nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->lan_port, cfg->tcp_udp_rule_id);
-+      }
-+
-+      if (cfg->lan_port != cfg->wan_port)
-+      {
-+              rc = mac_set_rule_reg(cfg->wan_port, cfg->tcp_udp_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
-+              if (rc < 0)
-+              {
-+                      nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->wan_port, cfg->tcp_udp_rule_id);
-+              }
-+      }
-+#endif
-+
-+#ifdef CONFIG_SL351x_NAT_GRE
-+      mrxcr0.bits32 = 0;
-+      mrxcr1.bits32 = 0;
-+      mrxcr2.bits32 = 0;
-+      mrxcr0.bits.port = 1;
-+      mrxcr0.bits.l3 = 1;
-+      mrxcr0.bits.l4 = 1;
-+      mrxcr1.bits.sip = 1;
-+      mrxcr1.bits.dip = 1;
-+      mrxcr1.bits.l4_byte0_15 = 0xcc; // Byte 2, 3, 6, 7
-+      mrxcr0.bits.sprx = 4;                   // see GMAC driver about SPR
-+
-+      rc = mac_set_rule_reg(cfg->lan_port, cfg->gre_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
-+      if (rc < 0)
-+      {
-+              nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->lan_port, cfg->gre_rule_id);
-+      }
-+
-+      if (cfg->lan_port != cfg->wan_port)
-+      {
-+              rc = mac_set_rule_reg(cfg->wan_port, cfg->gre_rule_id, 1, mrxcr0.bits32, mrxcr1.bits32, mrxcr2.bits32);
-+              if (rc < 0)
-+              {
-+                      nat_printf("NAT Failed to set MAC-%d Rule %d!\n", cfg->wan_port, cfg->gre_rule_id);
-+              }
-+      }
-+#endif
-+
-+#ifdef SL351x_NAT_TEST_BY_SMARTBITS
-+      nat_init_test_entry();
-+#endif
-+}
-+
-+/*----------------------------------------------------------------------
-+* nat_build_keys
-+*     Note: To call this routine, the key->rule_id MUST be zero
-+*----------------------------------------------------------------------*/
-+static inline int nat_build_keys(NAT_KEY_T *key)
-+{
-+      return hash_gen_crc16((unsigned char *)key, NAT_KEY_SIZE) & HASH_BITS_MASK;
-+}
-+
-+/*----------------------------------------------------------------------
-+* gre_build_keys
-+*     Note: To call this routine, the key->rule_id MUST be zero
-+*----------------------------------------------------------------------*/
-+static inline int gre_build_keys(GRE_KEY_T *key)
-+{
-+      return hash_gen_crc16((unsigned char *)key, GRE_KEY_SIZE) & HASH_BITS_MASK;
-+}
-+
-+/*----------------------------------------------------------------------
-+* nat_write_hash_entry
-+*----------------------------------------------------------------------*/
-+static inline int nat_write_hash_entry(int index, void *hash_entry)
-+{
-+      int             i;
-+      u32             *srcep, *destp, *destp2;
-+
-+      srcep = (u32 *)hash_entry;
-+      destp = destp2 = (u32 *)&hash_tables[index][0];
-+
-+      for (i=0; i<(NAT_HASH_ENTRY_SIZE/sizeof(u32)); i++)
-+              *destp++ = *srcep++;
-+
-+      consistent_sync(destp2, NAT_HASH_ENTRY_SIZE, PCI_DMA_TODEVICE);
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+* gre_write_hash_entry
-+*----------------------------------------------------------------------*/
-+static inline int gre_write_hash_entry(int index, void *hash_entry)
-+{
-+      int             i;
-+      u32             *srcep, *destp, *destp2;
-+
-+      srcep = (u32 *)hash_entry;
-+      destp = destp2 = (u32 *)&hash_tables[index][0];
-+
-+      for (i=0; i<(GRE_HASH_ENTRY_SIZE/sizeof(u32)); i++)
-+              *destp++ = *srcep++;
-+
-+      consistent_sync(destp2, GRE_HASH_ENTRY_SIZE, PCI_DMA_TODEVICE);
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+* sl351x_nat_find_ipcfg
-+*     return NULL if not found
-+*----------------------------------------------------------------------*/
-+static NAT_IP_ENTRY_T *sl351x_nat_find_ipcfg(u32 ipaddr, int port)
-+{
-+      int                             i;
-+      NAT_IP_ENTRY_T  *ipcfg;
-+
-+      ipcfg = (NAT_IP_ENTRY_T *)&nat_cfg.ipcfg[port].entry[0];
-+      for (i=0; i<nat_cfg.ipcfg[port].total; i++, ipcfg++)
-+      {
-+              if (ipaddr == ipcfg->ipaddr)
-+              {
-+                      return ipcfg;
-+              }
-+      }
-+      return NULL;
-+}
-+
-+/*----------------------------------------------------------------------
-+* sl351x_nat_assign_qid
-+*----------------------------------------------------------------------*/
-+static int sl351x_nat_assign_qid(u8 proto, u32 sip, u32 dip, u16 sport, u16 dport)
-+{
-+      int                             i, total, qid;
-+      NAT_WRULE_ENTRY_T       *entry;
-+
-+      for (qid = 0; qid<CONFIG_NAT_TXQ_NUM; qid++)
-+      {
-+              if (qid == nat_cfg.default_hw_txq)
-+                      continue;
-+
-+              entry = (NAT_WRULE_ENTRY_T *)&nat_cfg.wrule[qid].entry[0];
-+              total = nat_cfg.wrule[qid].total;
-+              for (i=0; i<total; i++, entry++)
-+              {
-+                      if (!entry->protocol || entry->protocol==proto)
-+                      {
-+                              //if (!entry->sip_start && !entry->dip_start && !entry->sport_start && !entry->dport_start)
-+                              //      continue; // UI take care
-+                              if (entry->sip_start && !((sip >= entry->sip_start) &&
-+                                                                         (sip <= entry->sip_end)))
-+                                      continue;
-+                              if (entry->dip_start && !((dip >= entry->dip_start) &&
-+                                                                         (dip <= entry->dip_end)))
-+                                      continue;
-+                              if (entry->sport_start && !((sport >= entry->sport_start) &&
-+                                                                         (sport <= entry->sport_end)))
-+                                      continue;
-+                              if (entry->dport_start && !((dport >= entry->dport_start)
-+                                                                     && (dport <= entry->dport_end)))
-+                                      continue;
-+                              return qid;
-+                      }
-+              }
-+      }
-+      return nat_cfg.default_hw_txq;
-+}
-+
-+/*----------------------------------------------------------------------
-+* sl351x_nat_input
-+*     Handle NAT input frames
-+*     Called by SL351x Driver - Handle Default Rx Queue
-+*     Notes: The caller must make sure that the l3off & l4offset should not be zero.
-+*     SL351x NAT Frames should meet the following conditions:
-+*     1. TCP or UDP frame
-+*     2. Cannot be special ALGs ports which TCP/UDP data is updated
-+*     3. LAN-IN Frames:
-+*             Source IP is in the LAN subnet and Destination is not in the LAN subnet
-+*     4. WAN-IN Frames
-+*             Destination IP is in the WAN port IP
-+*
-+*     Example Ports
-+*     1. TCP/UDP data is updated
-+*             (a) FTP Control Packet
-+*             (b) VoIP Packets
-+*             (c) etc. (add in future)
-+*     2. UDP Low packet rate, not worth
-+*             (b) TFTP Destination Port is 69
-+*             (b) DNS  53
-+*             (c) NTP  123
-+*             (d) etc. (add in future)
-+*----------------------------------------------------------------------*/
-+void sl351x_nat_input(struct sk_buff *skb, int port, void *l3off, void *l4off)
-+{
-+      int                             i, found;
-+      u32                                     sip, dip;
-+      u16                                     sport, dport;
-+      struct ethhdr           *ether_hdr;
-+      struct iphdr            *ip_hdr;
-+      struct tcphdr           *tcp_hdr;
-+      struct pppoe_hdr        *pppoe_hdr;
-+      NAT_CB_T                        *nat_cb;
-+      u8                                      proto, pppoe_frame=0;
-+      NAT_CFG_T                       *cfg;
-+      u16                                     ppp_proto;
-+      NAT_IP_ENTRY_T          *ipcfg;
-+      NAT_XPORT_ENTRY_T       *xentry;
-+      GRE_PKTHDR_T            *gre_hdr;
-+#ifdef CONFIG_SL351x_NAT_TCP_UDP
-+      u16                             *port_ptr;
-+#endif
-+
-+      cfg = (NAT_CFG_T *)&nat_cfg;
-+      if (!cfg->enabled || !cfg->ipcfg[port].total)
-+              return;
-+
-+      ip_hdr = (struct iphdr *)&(skb->data[(u32)l3off]);
-+      proto = ip_hdr->protocol;
-+
-+      tcp_hdr = (struct tcphdr *)&(skb->data[(u32)l4off]);
-+      gre_hdr = (GRE_PKTHDR_T *)tcp_hdr;
-+      sport = ntohs(tcp_hdr->source);
-+      dport = ntohs(tcp_hdr->dest);
-+
-+      sip = ntohl(ip_hdr->saddr);
-+      dip = ntohl(ip_hdr->daddr);
-+
-+      if (dip == IPIV(255,255,255,255))
-+              return;
-+
-+      if (port == cfg->lan_port)
-+      {
-+              ipcfg = (NAT_IP_ENTRY_T *)&cfg->ipcfg[port].entry[0];
-+              for (i=0, found=0; i<cfg->ipcfg[port].total; i++, ipcfg++)
-+              {
-+                      u32 subnet = ipcfg->ipaddr & ipcfg->netmask;
-+                      if (((sip & ipcfg->netmask) == subnet) &&
-+                              ((dip & ipcfg->netmask) != subnet))
-+                      {
-+                              found = 1;
-+                              break;
-+                      }
-+              }
-+              if (!found)
-+                      return;
-+      }
-+      else
-+      {
-+#ifndef _NOT_CHECK_SIP_DIP    // enable it if know and get the wan ip address
-+              if (!sl351x_nat_find_ipcfg(dip, port))
-+              {
-+                      printk("WAN->LAN Incorrect Dip %d.%d.%d.%d\n", HIPQUAD(dip));
-+                      return;
-+              }
-+#endif
-+              ether_hdr = (struct ethhdr *)skb->data;
-+              pppoe_hdr = (struct pppoe_hdr *)(ether_hdr + 1);
-+              ppp_proto = *(u16 *)&pppoe_hdr->tag[0];
-+              if (ether_hdr->h_proto == __constant_htons(ETH_P_PPP_SES)       // 0x8864
-+                      && ppp_proto == __constant_htons(PPP_IP) )                              // 0x21
-+              {
-+                      pppoe_frame = 1;
-+              }
-+      }
-+
-+#ifdef CONFIG_SL351x_NAT_TCP_UDP
-+      if (proto == IPPROTO_TCP)
-+      {
-+#ifdef        NAT_DEBUG_MSG
-+              nat_printf("From   GMAC-%d: 0x%-4X TCP %d.%d.%d.%d [%d] --> %d.%d.%d.%d [%d]",
-+                              port, ntohs(ip_hdr->id),
-+                              NIPQUAD(ip_hdr->saddr), sport,
-+                              NIPQUAD(ip_hdr->daddr), dport);
-+              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_SYN) nat_printf(" SYN");
-+              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_FIN) nat_printf(" FIN");
-+              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_RST) nat_printf(" RST");
-+              if (tcp_flag_word(tcp_hdr) & TCP_FLAG_ACK) nat_printf(" ACK");
-+              nat_printf("\n");
-+#endif
-+              // if (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN | TCP_FLAG_FIN | TCP_FLAG_RST))
-+              if (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN))
-+              {
-+                      return;
-+              }
-+              port_ptr = fixed_tcp_port_list;
-+              for (i=0; *port_ptr; i++, port_ptr++)
-+              {
-+                      if (sport == *port_ptr || dport == *port_ptr)
-+                              return;
-+              }
-+#ifdef _HAVE_DYNAMIC_PORT_LIST
-+              port_ptr = dynamic_tcp_port_list;
-+              for (i=0; *port_ptr; i++, port_ptr++)
-+              {
-+                      if (sport == *port_ptr || dport == *port_ptr)
-+                              return;
-+              }
-+#endif
-+      }
-+      else if (proto == IPPROTO_UDP)
-+      {
-+#ifdef        NAT_DEBUG_MSG
-+              nat_printf("From   GMAC-%d: 0x%-4X UDP %d.%d.%d.%d [%d] --> %d.%d.%d.%d [%d]",
-+                              port, ntohs(ip_hdr->id),
-+                              NIPQUAD(ip_hdr->saddr), sport,
-+                              NIPQUAD(ip_hdr->daddr), dport);
-+              nat_printf("\n");
-+#endif
-+              port_ptr = fixed_udp_port_list;
-+              for (i=0; *port_ptr; i++, port_ptr++)
-+              {
-+                      if (sport == *port_ptr || dport == *port_ptr)
-+                              return;
-+              }
-+#ifdef _HAVE_DYNAMIC_PORT_LIST
-+              port_ptr = dynamic_udp_port_list;
-+              for (i=0; *port_ptr; i++, port_ptr++)
-+              {
-+                      if (sport == *port_ptr || dport == *port_ptr)
-+                              return;
-+              }
-+#endif
-+      }
-+      else
-+#endif        // CONFIG_SL351x_NAT_TCP_UDP
-+#ifdef CONFIG_SL351x_NAT_GRE
-+      if (proto == IPPROTO_GRE)
-+      {
-+              if (gre_hdr->protocol != GRE_PROTOCOL_SWAP)
-+                      return;
-+#ifdef        NAT_DEBUG_MSG
-+              nat_printf("From   GMAC-%d: 0x%-4X GRE %d.%d.%d.%d [%d] --> %d.%d.%d.%d",
-+                              port, ntohs(ip_hdr->id),
-+                              NIPQUAD(ip_hdr->saddr), ntohs(gre_hdr->call_id),
-+                              NIPQUAD(ip_hdr->daddr));
-+              nat_printf("\n");
-+#endif
-+      }
-+      else
-+#endif
-+              return;
-+
-+
-+      // check xport list
-+      xentry = (NAT_XPORT_ENTRY_T *)&cfg->xport.entry[0];
-+      for (i=0; i<cfg->xport.total; i++, xentry++)
-+      {
-+              if (!xentry->protocol || xentry->protocol == proto)
-+              {
-+                      //if (!xentry->sport_start && !xentry->dport_start) // UI take care
-+                      //      continue;
-+                      if (xentry->sport_start && !((sport >= xentry->sport_start) &&
-+                                                                         (sport <= xentry->sport_end)))
-+                              continue;
-+                      if (xentry->dport_start && !((dport >= xentry->dport_start)
-+                                                                     && (dport <= xentry->dport_end)))
-+                              continue;
-+                      return;
-+              }
-+      }
-+
-+      nat_cb = NAT_SKB_CB(skb);
-+      if (((u32)nat_cb & 3))
-+      {
-+              nat_printf("%s ERROR! nat_cb is not alignment!!!!!!\n", __func__);
-+              return;
-+      }
-+      nat_cb->tag = NAT_CB_TAG;
-+      memcpy(nat_cb->sa, skb->data+6, 6);
-+      nat_cb->sip = ip_hdr->saddr;
-+      nat_cb->dip = ip_hdr->daddr;
-+      if (proto == IPPROTO_GRE)
-+      {
-+              nat_cb->sport = gre_hdr->protocol;
-+              nat_cb->dport = gre_hdr->call_id;
-+      }
-+      else
-+      {
-+              nat_cb->sport = tcp_hdr->source;
-+              nat_cb->dport = tcp_hdr->dest;
-+      }
-+      nat_cb->pppoe_frame = pppoe_frame;
-+}
-+
-+/*----------------------------------------------------------------------
-+* sl351x_nat_output
-+*     Handle NAT output frames
-+*     Called by SL351x Driver - Transmit
-+*
-+*     1. If not SL351x NAT frames, return FALSE
-+*     2. LAN-to-WAN frames
-+*             (1) Sip must be WAN IP
-+*     3. If TCP SY/RST/FIN frame, return
-+*     4. Build the hash key and get the hash index
-+*     5. If V-Bit is ON, return.
-+*     6. Write hash entry and validate it
-+*
-+*----------------------------------------------------------------------*/
-+int sl351x_nat_output(struct sk_buff *skb, int port)
-+{
-+      struct iphdr            *ip_hdr;
-+      u8                                      proto;
-+      NAT_CB_T                        *nat_cb;
-+
-+      nat_cb = NAT_SKB_CB(skb);
-+      if (nat_cb->tag != NAT_CB_TAG)
-+              return 0;
-+
-+      if (((u32)nat_cb & 3))
-+      {
-+              nat_printf("%s ERROR! nat_cb is not alignment!!!!!!\n", __func__);
-+              return 0;
-+      }
-+      ip_hdr = (struct iphdr *)skb->h.ipiph;
-+      proto = ip_hdr->protocol;
-+
-+      switch (proto)
-+      {
-+              case IPPROTO_TCP:
-+              case IPPROTO_UDP:
-+                      return sl351x_nat_tcp_udp_output(skb, port);
-+              case IPPROTO_GRE:
-+                      return sl351x_nat_gre_output(skb, port);
-+      }
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+* sl351x_nat_tcp_udp_output
-+*     Handle NAT TCP/UDP output frames
-+*----------------------------------------------------------------------*/
-+int sl351x_nat_tcp_udp_output(struct sk_buff *skb, int port)
-+{
-+      u32                                     sip, dip;
-+      struct ethhdr           *ether_hdr;
-+      struct iphdr            *ip_hdr;
-+      struct tcphdr           *tcp_hdr;
-+      struct pppoe_hdr        *pppoe_hdr;
-+      NAT_CB_T                        *nat_cb;
-+      NAT_CFG_T                       *cfg;
-+      u8                                      proto;
-+      u16                                     sport, dport, ppp_proto;
-+      u32                                     hash_data[HASH_MAX_DWORDS];
-+      NAT_HASH_ENTRY_T        *hash_entry;
-+      int                                     hash_index;
-+      struct ip_conntrack *nat_ip_conntrack;
-+      enum ip_conntrack_info ctinfo;
-+
-+      nat_cb = NAT_SKB_CB(skb);
-+      cfg = (NAT_CFG_T *)&nat_cfg;
-+
-+      ether_hdr = (struct ethhdr *)skb->data;
-+      ip_hdr = (struct iphdr *)skb->h.ipiph;
-+      tcp_hdr = (struct tcphdr *)((u32)ip_hdr + (ip_hdr->ihl<<2));
-+      sip = ntohl(ip_hdr->saddr);
-+      dip = ntohl(ip_hdr->daddr);
-+      proto = ip_hdr->protocol;
-+      sport = ntohs(tcp_hdr->source);
-+      dport = ntohs(tcp_hdr->dest);
-+
-+#ifdef        NAT_DEBUG_MSG
-+      {
-+              nat_printf("To   GMAC-%d: 0x%-4X [%d] %d.%d.%d.%d [%d] --> %d.%d.%d.%d [%d]",
-+                              port, ntohs(ip_hdr->id), proto,
-+                              NIPQUAD(ip_hdr->saddr), sport,
-+                              NIPQUAD(ip_hdr->daddr), dport);
-+              if (proto == IPPROTO_TCP)
-+              {
-+                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_SYN) nat_printf(" SYN");
-+                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_FIN) nat_printf(" FIN");
-+                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_RST) nat_printf(" RST");
-+                      if (tcp_flag_word(tcp_hdr) & TCP_FLAG_ACK) nat_printf(" ACK");
-+              }
-+              nat_printf("\n");
-+      }
-+#endif
-+      nat_ip_conntrack = ip_conntrack_get(skb, &ctinfo);
-+      if (!nat_ip_conntrack)
-+      {
-+              nat_printf("IP conntrack info is not found!\n");
-+              return 0;
-+      }
-+      // nat_printf("nat_ip_conntrack = 0x%x, status=0x%lx, ctinfo=%d\n", (u32)nat_ip_conntrack, nat_ip_conntrack->status, ctinfo);
-+      // if (nat_ip_conntrack->master || nat_ip_conntrack->helper)
-+      if (nat_ip_conntrack->helper)
-+      {
-+              nat_printf("Sport=%d Dport=%d master=0x%x, helper=0x%x\n", sport, dport, (u32)nat_ip_conntrack->master, (u32)nat_ip_conntrack->helper);
-+              return 0;
-+      }
-+
-+      //if (proto == IPPROTO_TCP && !(nat_ip_conntrack->status & IPS_ASSURED))
-+      //      return 0;
-+
-+#ifdef        NAT_DEBUG_MSG
-+      nat_printf("nat_ip_conntrack=0x%x, nat_cb->state=%d\n", (u32)nat_ip_conntrack, nat_cb->state);
-+      nat_printf("lan2wan_hash_index=%d,  wan2lan_hash_index=%d\n", nat_ip_conntrack->lan2wan_hash_index, nat_ip_conntrack->wan2lan_hash_index);
-+      nat_printf("lan2wan_collision=%d, wan2lan_collision=%d\n", nat_ip_conntrack->lan2wan_collision, nat_ip_conntrack->wan2lan_collision);
-+#endif
-+      if (proto == IPPROTO_TCP)
-+      {
-+              if (nat_cb->state >= TCP_CONNTRACK_FIN_WAIT && nat_cb->state <= TCP_CONNTRACK_CLOSE)
-+              {
-+                      if      (nat_ip_conntrack->lan2wan_hash_index)
-+                      {
-+#ifdef        NAT_DEBUG_MSG
-+                              nat_printf("Invalidate LAN->WAN hash entry %d\n", nat_ip_conntrack->lan2wan_hash_index - 1);
-+#endif
-+                              hash_nat_disable_owner(nat_ip_conntrack->lan2wan_hash_index - 1);
-+                              hash_invalidate_entry(nat_ip_conntrack->lan2wan_hash_index - 1);
-+                              nat_ip_conntrack->lan2wan_hash_index = 0;
-+                      }
-+                      if      (nat_ip_conntrack->wan2lan_hash_index)
-+                      {
-+#ifdef        NAT_DEBUG_MSG
-+                              nat_printf("Invalidate WAN->LAN hash entry %d\n", nat_ip_conntrack->wan2lan_hash_index - 1);
-+#endif
-+                              hash_nat_disable_owner(nat_ip_conntrack->wan2lan_hash_index - 1);
-+                              hash_invalidate_entry(nat_ip_conntrack->wan2lan_hash_index - 1);
-+                              nat_ip_conntrack->wan2lan_hash_index = 0;
-+                      }
-+                      return 0;
-+
-+              }
-+              else if (nat_cb->state != TCP_CONNTRACK_ESTABLISHED)
-+              {
-+                      return 0;
-+              }
-+      }
-+      if (proto == IPPROTO_TCP && (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN | TCP_FLAG_FIN | TCP_FLAG_RST)))
-+      // if (proto == IPPROTO_TCP &&  (tcp_flag_word(tcp_hdr) & (TCP_FLAG_SYN)))
-+              return 0;
-+
-+      hash_entry = (NAT_HASH_ENTRY_T *)&hash_data;
-+      if (port == cfg->wan_port)      // LAN-to-WAN
-+      {
-+              if (nat_ip_conntrack->lan2wan_hash_index || nat_ip_conntrack->lan2wan_collision)
-+                      return 0;
-+#ifndef _NOT_CHECK_SIP_DIP    // enable it if know and get the wan ip address
-+              if (!sl351x_nat_find_ipcfg(sip, port))
-+              {
-+                      printk("LAN->WAN Incorrect Sip %d.%d.%d.%d\n", HIPQUAD(sip));
-+                      return 0;
-+              }
-+#endif
-+              // Note: unused fields (including rule_id) MUST be zero
-+              hash_entry->key.Ethertype       = 0;
-+              hash_entry->key.port_id         = cfg->lan_port;
-+              hash_entry->key.rule_id         = 0;
-+              hash_entry->key.ip_protocol = proto;
-+              hash_entry->key.reserved1       = 0;
-+              hash_entry->key.reserved2       = 0;
-+              hash_entry->key.sip             = ntohl(nat_cb->sip);
-+              hash_entry->key.dip             = ntohl(nat_cb->dip);
-+              hash_entry->key.sport           = nat_cb->sport;
-+              hash_entry->key.dport           = nat_cb->dport;
-+
-+              hash_index = nat_build_keys(&hash_entry->key);
-+
-+#ifdef NAT_DEBUG_LAN_HASH_TIMEOUT
-+              if (hash_get_nat_owner_flag(hash_index))
-+                      return 0;
-+#endif
-+              if (hash_get_valid_flag(hash_index))
-+              {
-+                      nat_ip_conntrack->lan2wan_collision = 1;
-+                      nat_collision++;
-+#if 0
-+                      if (proto == IPPROTO_TCP && (tcp_flag_word(tcp_hdr) & (TCP_FLAG_FIN | TCP_FLAG_RST)))
-+                      {
-+                              if (memcmp((void *)&hash_entry->key, hash_get_entry(hash_index), sizeof(NAT_KEY_T)) == 0)
-+                              {
-+                                      hash_nat_disable_owner(hash_index);
-+                                      hash_invalidate_entry(hash_index); // Must last one, else HW Tx fast SW
-+                                      // nat_printf("Invalidate nat hash entry %d\n", hash_index);
-+                              }
-+                      }
-+#endif
-+                      return 0;
-+              }
-+
-+              // write hash entry
-+              hash_entry->key.rule_id = cfg->tcp_udp_rule_id;
-+              memcpy(hash_entry->param.da, skb->data, 6);
-+              memcpy(hash_entry->param.sa, skb->data+6, 6);
-+              hash_entry->param.Sip = sip;
-+              hash_entry->param.Dip = dip;
-+              hash_entry->param.Sport = sport;
-+              hash_entry->param.Dport = dport;
-+              hash_entry->param.vlan = 0;
-+              hash_entry->param.sw_id = 0;
-+              hash_entry->param.mtu = 0;
-+              // check PPPoE
-+              pppoe_hdr = (struct pppoe_hdr *)(ether_hdr + 1);
-+              ppp_proto = *(u16 *)&pppoe_hdr->tag[0];
-+              if (ether_hdr->h_proto == __constant_htons(ETH_P_PPP_SES)       // 0x8864
-+                      && ppp_proto == __constant_htons(PPP_IP) )                              // 0x21
-+              {
-+                      hash_entry->action.dword = NAT_PPPOE_LAN2WAN_ACTIONS;
-+                      hash_entry->param.pppoe = htons(pppoe_hdr->sid);
-+              }
-+              else
-+              {
-+                      hash_entry->action.dword = NAT_LAN2WAN_ACTIONS;
-+                      hash_entry->param.pppoe = 0;
-+              }
-+              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(proto, sip, dip, sport, dport);
-+              hash_entry->action.bits.dest_qid +=     (cfg->wan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
-+              hash_entry->tmo.counter = hash_entry->tmo.interval =
-+                                              (proto == IPPROTO_TCP) ? cfg->tcp_tmo_interval : cfg->udp_tmo_interval;
-+              nat_write_hash_entry(hash_index, hash_entry);
-+              // nat_printf("%lu Validate a LAN hash entry %d\n", jiffies/HZ, hash_index);
-+              // hash_dump_entry(hash_index);
-+              hash_nat_enable_owner(hash_index);
-+              hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
-+              nat_ip_conntrack->lan2wan_hash_index = hash_index + 1;
-+              nat_ip_conntrack->hw_nat |= 1;
-+              return 0;
-+      }
-+      else // WAN-to-LAN
-+      {
-+              if (nat_ip_conntrack->wan2lan_hash_index || nat_ip_conntrack->wan2lan_collision)
-+                      return 0;
-+
-+              // Note: unused fields (including rule_id) MUST be zero
-+              hash_entry->key.Ethertype       = 0;
-+              hash_entry->key.port_id         = cfg->wan_port;
-+              hash_entry->key.rule_id         = 0;
-+              hash_entry->key.ip_protocol = proto;
-+              hash_entry->key.reserved1       = 0;
-+              hash_entry->key.reserved2       = 0;
-+              hash_entry->key.sip             = ntohl(nat_cb->sip);
-+              hash_entry->key.dip             = ntohl(nat_cb->dip);
-+              hash_entry->key.sport           = nat_cb->sport;
-+              hash_entry->key.dport           = nat_cb->dport;
-+
-+              hash_index = nat_build_keys(&hash_entry->key);
-+
-+#ifdef NAT_DEBUG_WAN_HASH_TIMEOUT
-+              if (hash_get_nat_owner_flag(hash_index))
-+                      return 0;
-+#endif
-+              if (hash_get_valid_flag(hash_index))
-+              {
-+                      nat_ip_conntrack->wan2lan_collision = 1;
-+                      nat_collision++;
-+#if 0
-+                      if (proto == IPPROTO_TCP && (tcp_flag_word(tcp_hdr) & (TCP_FLAG_FIN | TCP_FLAG_RST)))
-+                      {
-+                              if (memcmp((void *)&hash_entry->key, hash_get_entry(hash_index), sizeof(NAT_KEY_T)) == 0)
-+                              {
-+                                      hash_nat_disable_owner(hash_index);
-+                                      hash_invalidate_entry(hash_index); // Must last one, else HW Tx fast SW
-+                                      // nat_printf("Invalidate nat hash entry %d\n", hash_index);
-+                              }
-+                      }
-+#endif
-+                      return 0;
-+              }
-+
-+              // write hash entry
-+              hash_entry->key.rule_id = cfg->tcp_udp_rule_id;
-+              memcpy(hash_entry->param.da, skb->data, 6);
-+              memcpy(hash_entry->param.sa, skb->data+6, 6);
-+              hash_entry->param.Sip = sip;
-+              hash_entry->param.Dip = dip;
-+              hash_entry->param.Sport = sport;
-+              hash_entry->param.Dport = dport;
-+              hash_entry->param.vlan = 0;
-+              hash_entry->param.pppoe = 0;
-+              hash_entry->param.sw_id = 0;
-+              hash_entry->param.mtu = 0;
-+              hash_entry->action.dword = (nat_cb->pppoe_frame) ? NAT_PPPOE_WAN2LAN_ACTIONS : NAT_WAN2LAN_ACTIONS;
-+              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(proto, sip, dip, sport, dport);
-+              hash_entry->action.bits.dest_qid += (cfg->lan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;;
-+              hash_entry->tmo.counter = hash_entry->tmo.interval =
-+                                              (proto == IPPROTO_TCP) ? cfg->tcp_tmo_interval : cfg->udp_tmo_interval;
-+              nat_write_hash_entry(hash_index, hash_entry);
-+
-+              // nat_printf("%lu Validate a WAN hash entry %d\n", jiffies/HZ, hash_index);
-+              // hash_dump_entry(hash_index);
-+              hash_nat_enable_owner(hash_index);
-+              hash_validate_entry(hash_index); // Must last one, else HW Tx fast SW
-+              nat_ip_conntrack->wan2lan_hash_index = hash_index + 1;
-+              nat_ip_conntrack->hw_nat |= 2;
-+              return 0;
-+      }
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+* sl351x_nat_gre_output
-+*     Handle NAT GRE output frames
-+*----------------------------------------------------------------------*/
-+int sl351x_nat_gre_output(struct sk_buff *skb, int port)
-+{
-+      u32                                     sip, dip;
-+      struct ethhdr           *ether_hdr;
-+      struct iphdr            *ip_hdr;
-+      struct pppoe_hdr        *pppoe_hdr;
-+      GRE_PKTHDR_T            *gre_hdr;
-+      NAT_CB_T                        *nat_cb;
-+      NAT_CFG_T                       *cfg;
-+      u16                                     ppp_proto;
-+      u32                                     hash_data[HASH_MAX_DWORDS];
-+      GRE_HASH_ENTRY_T        *hash_entry;
-+      int                                     hash_index;
-+      struct ip_conntrack *nat_ip_conntrack;
-+      enum ip_conntrack_info ctinfo;
-+
-+      nat_cb = NAT_SKB_CB(skb);
-+      cfg = (NAT_CFG_T *)&nat_cfg;
-+
-+      ether_hdr = (struct ethhdr *)skb->data;
-+      ip_hdr = (struct iphdr *)skb->h.ipiph;
-+      gre_hdr = (GRE_PKTHDR_T *)((u32)ip_hdr + (ip_hdr->ihl<<2));
-+      sip = ntohl(ip_hdr->saddr);
-+      dip = ntohl(ip_hdr->daddr);
-+
-+#ifdef        NAT_DEBUG_MSG
-+      {
-+              nat_printf("To   GMAC-%d: 0x%-4X GRE %d.%d.%d.%d [%d] --> %d.%d.%d.%d",
-+                              port, ntohs(ip_hdr->id),
-+                              NIPQUAD(ip_hdr->saddr), ntohs(gre_hdr->call_id),
-+                              NIPQUAD(ip_hdr->daddr));
-+              nat_printf("\n");
-+      }
-+#endif
-+      nat_ip_conntrack = ip_conntrack_get(skb, &ctinfo);
-+      if (nat_ip_conntrack)
-+      {
-+              // if (nat_ip_conntrack->master || nat_ip_conntrack->helper)
-+              if (nat_ip_conntrack->helper)
-+              {
-+                      nat_printf("GRE Call-ID=%d, master=0x%x, helper=0x%x\n", ntohs(gre_hdr->call_id), (u32)nat_ip_conntrack->master, (u32)nat_ip_conntrack->helper);
-+                      return 0;
-+              }
-+              if (!(nat_ip_conntrack->status & IPS_ASSURED))
-+                      return 0;
-+      }
-+
-+      hash_entry = (GRE_HASH_ENTRY_T *)&hash_data;
-+      if (port == cfg->wan_port)      // LAN-to-WAN
-+      {
-+#ifdef _NOT_CHECK_SIP_DIP     // enable it if know and get the wan ip address
-+              if (!sl351x_nat_find_ipcfg(sip, port))
-+              {
-+                      printk("LAN->WAN Incorrect Sip %d.%d.%d.%d\n", HIPQUAD(sip));
-+                      return 0;
-+              }
-+#endif
-+              // Note: unused fields (including rule_id) MUST be zero
-+              hash_entry->key.Ethertype       = 0;
-+              hash_entry->key.port_id         = cfg->lan_port;
-+              hash_entry->key.rule_id         = 0;
-+              hash_entry->key.ip_protocol = IPPROTO_GRE;
-+              hash_entry->key.reserved1       = 0;
-+              hash_entry->key.reserved2       = 0;
-+              hash_entry->key.reserved3       = 0;
-+              hash_entry->key.reserved4       = 0;
-+              hash_entry->key.sip             = ntohl(nat_cb->sip);
-+              hash_entry->key.dip             = ntohl(nat_cb->dip);
-+              hash_entry->key.protocol        = nat_cb->sport;
-+              hash_entry->key.call_id         = nat_cb->dport;
-+
-+              hash_index = gre_build_keys(&hash_entry->key);
-+
-+#ifdef NAT_DEBUG_LAN_HASH_TIMEOUT
-+              if (hash_get_nat_owner_flag(hash_index))
-+                      return 0;
-+#endif
-+              if (hash_get_valid_flag(hash_index))
-+              {
-+                      return 0;
-+              }
-+
-+              // write hash entry
-+              hash_entry->key.rule_id = cfg->gre_rule_id;
-+              memcpy(hash_entry->param.da, skb->data, 6);
-+              memcpy(hash_entry->param.sa, skb->data+6, 6);
-+              hash_entry->param.Sip = sip;
-+              hash_entry->param.Dip = dip;
-+              hash_entry->param.Sport = 0;
-+              hash_entry->param.Dport = ntohs(gre_hdr->call_id);
-+              hash_entry->param.vlan = 0;
-+              hash_entry->param.sw_id = 0;
-+              hash_entry->param.mtu = 0;
-+              // check PPPoE
-+              pppoe_hdr = (struct pppoe_hdr *)(ether_hdr + 1);
-+              ppp_proto = *(u16 *)&pppoe_hdr->tag[0];
-+              if (ether_hdr->h_proto == __constant_htons(ETH_P_PPP_SES)       // 0x8864
-+                      && ppp_proto == __constant_htons(PPP_IP) )                              // 0x21
-+              {
-+                      hash_entry->action.dword = NAT_PPPOE_PPTP_LAN2WAN_ACTIONS;
-+                      hash_entry->param.pppoe = htons(pppoe_hdr->sid);
-+              }
-+              else
-+              {
-+                      hash_entry->action.dword = NAT_PPTP_LAN2WAN_ACTIONS;
-+                      hash_entry->param.pppoe = 0;
-+              }
-+              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(IPPROTO_GRE, sip, dip, 0, ntohs(gre_hdr->call_id));
-+              hash_entry->action.bits.dest_qid +=     (cfg->wan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
-+              hash_entry->tmo.counter = hash_entry->tmo.interval = cfg->gre_tmo_interval;
-+              gre_write_hash_entry(hash_index, hash_entry);
-+              // nat_printf("%lu Validate a LAN hash entry %d\n", jiffies/HZ, hash_index);
-+              // hash_dump_entry(hash_index);
-+              hash_nat_enable_owner(hash_index);
-+              hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
-+              return 0;
-+      }
-+      else // WAN-to-LAN
-+      {
-+              // Note: unused fields (including rule_id) MUST be zero
-+              hash_entry->key.Ethertype       = 0;
-+              hash_entry->key.port_id         = cfg->wan_port;
-+              hash_entry->key.rule_id         = 0;
-+              hash_entry->key.ip_protocol = IPPROTO_GRE;
-+              hash_entry->key.reserved1       = 0;
-+              hash_entry->key.reserved2       = 0;
-+              hash_entry->key.reserved3       = 0;
-+              hash_entry->key.reserved4       = 0;
-+              hash_entry->key.sip             = ntohl(nat_cb->sip);
-+              hash_entry->key.dip             = ntohl(nat_cb->dip);
-+              hash_entry->key.protocol        = nat_cb->sport;
-+              hash_entry->key.call_id         = nat_cb->dport;
-+
-+              hash_index = gre_build_keys(&hash_entry->key);
-+
-+#ifdef NAT_DEBUG_WAN_HASH_TIMEOUT
-+              if (hash_get_nat_owner_flag(hash_index))
-+                      return 0;
-+#endif
-+              if (hash_get_valid_flag(hash_index))
-+              {
-+                      return 0;
-+              }
-+
-+              // write hash entry
-+              hash_entry->key.rule_id = cfg->gre_rule_id;
-+              memcpy(hash_entry->param.da, skb->data, 6);
-+              memcpy(hash_entry->param.sa, skb->data+6, 6);
-+              hash_entry->param.Sip = sip;
-+              hash_entry->param.Dip = dip;
-+              hash_entry->param.Sport = 0;
-+              hash_entry->param.Dport = ntohs(gre_hdr->call_id);
-+              hash_entry->param.vlan = 0;
-+              hash_entry->param.pppoe = 0;
-+              hash_entry->param.sw_id = 0;
-+              hash_entry->param.mtu = 0;
-+              hash_entry->action.dword = (nat_cb->pppoe_frame) ? NAT_PPPOE_PPTP_WAN2LAN_ACTIONS : NAT_PPTP_WAN2LAN_ACTIONS;
-+              hash_entry->action.bits.dest_qid = sl351x_nat_assign_qid(IPPROTO_GRE, sip, dip, 0, ntohs(gre_hdr->call_id));
-+              hash_entry->action.bits.dest_qid += (cfg->lan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;;
-+              hash_entry->tmo.counter = hash_entry->tmo.interval = cfg->gre_tmo_interval;
-+              gre_write_hash_entry(hash_index, hash_entry);
-+
-+              // nat_printf("%lu Validate a WAN hash entry %d\n", jiffies/HZ, hash_index);
-+              // hash_dump_entry(hash_index);
-+              hash_nat_enable_owner(hash_index);
-+              hash_validate_entry(hash_index); // Must last one, else HW Tx fast SW
-+              return 0;
-+      }
-+      return 0;
-+}
-+
-+
-+#ifdef _HAVE_DYNAMIC_PORT_LIST
-+/*----------------------------------------------------------------------
-+* sl_nat_add_port
-+*----------------------------------------------------------------------*/
-+void sl_nat_add_port(u8 protocol, u16 port)
-+{
-+      int     i;
-+      u16             *port_ptr;
-+
-+      if (protocol == IPPROTO_TCP)
-+              port_ptr = dynamic_tcp_port_list;
-+      else if (protocol == IPPROTO_UDP)
-+              port_ptr = dynamic_udp_port_list;
-+      else
-+              return;
-+
-+      for (i=0; *port_ptr; i++)
-+      {
-+              if (port == *port_ptr)
-+                      return;
-+              port_ptr++;
-+      }
-+      port_ptr++;
-+      *port_ptr = port;
-+}
-+
-+/*----------------------------------------------------------------------
-+* sl_nat_remove_port
-+*----------------------------------------------------------------------*/
-+void sl_nat_remove_port(u8 protocol, u16 port)
-+{
-+      int     i, j;
-+      u16             *port_ptr, *next;
-+
-+      if (protocol == IPPROTO_TCP)
-+              port_ptr = dynamic_tcp_port_list;
-+      else if (protocol == IPPROTO_UDP)
-+              port_ptr = dynamic_udp_port_list;
-+      else
-+              return;
-+
-+      for (i=0; *port_ptr; i++, port_ptr++)
-+      {
-+              if (port == *port_ptr)
-+              {
-+                      port_next = port_ptr + 1;
-+                      for (j=i+1; *port_next; i++, j++)
-+                              *port_ptr++ = *port_next++;
-+                      *port_ptr = 0;
-+                      return;
-+              }
-+      }
-+}
-+#endif
-+
-+/*----------------------------------------------------------------------
-+* sl351x_nat_ioctl
-+*----------------------------------------------------------------------*/
-+int sl351x_nat_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+      GMAC_INFO_T             *tp = (GMAC_INFO_T *)dev->priv;
-+      int                             i, j, port_id;
-+    NATCMD_HDR_T              nat_hdr;
-+    NAT_REQ_E                 ctrl;
-+      unsigned char           *req_datap;
-+      NAT_IP_ENTRY_T          *ipcfg;
-+      NAT_XPORT_ENTRY_T       *xport_entry;
-+      NAT_WRULE_ENTRY_T       *wrule_entry;
-+      unsigned int            qid;
-+
-+      if (copy_from_user((void *)&nat_hdr, rq->ifr_data, sizeof(nat_hdr)))
-+              return -EFAULT;
-+      req_datap = (unsigned char *)rq->ifr_data + sizeof(nat_hdr);
-+      port_id = tp->port_id;
-+      switch (nat_hdr.cmd) {
-+      case NATSSTATUS:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_STATUS_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&ctrl.status, req_datap, sizeof(ctrl.status)))
-+                      return -EFAULT;
-+              if (ctrl.status.enable != 0 && ctrl.status.enable != 1)
-+                      return -EPERM;
-+              // sl351x_nat_set_enabled_flag(ctrl.status.enable);
-+              if (nat_cfg.enabled && (ctrl.status.enable == 0))
-+              {
-+                      for (i=0; i<HASH_TOTAL_ENTRIES; i++)
-+                      {
-+                              if (hash_get_nat_owner_flag(i))
-+                              {
-+                                      hash_nat_disable_owner(i);
-+                                      hash_invalidate_entry(i);
-+                              }
-+                      }
-+              }
-+              nat_cfg.enabled = ctrl.status.enable;
-+              break;
-+      case NATGSTATUS:
-+              if (nat_hdr.len != sizeof(NAT_STATUS_T))
-+                      return -EPERM;
-+              ctrl.status.enable = nat_cfg.enabled;
-+              if (copy_to_user(req_datap, (void *)&ctrl.status, sizeof(ctrl.status)))
-+                      return -EFAULT;
-+              break;
-+      case NATSETPORT:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_PORTCFG_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&ctrl.portcfg, req_datap, sizeof(ctrl.portcfg)))
-+                      return -EFAULT;
-+              if (ctrl.portcfg.portmap == 0)
-+                      nat_cfg.lan_port = port_id;
-+              else if (ctrl.portcfg.portmap == 1)
-+                      nat_cfg.wan_port = port_id;
-+              else
-+                      return -EPERM;
-+              break;
-+      case NATGETPORT:
-+              if (nat_hdr.len != sizeof(NAT_PORTCFG_T))
-+                      return -EPERM;
-+              if (nat_cfg.lan_port == port_id)
-+                      ctrl.portcfg.portmap = 0;
-+              else if (nat_cfg.wan_port == port_id)
-+                      ctrl.portcfg.portmap = 1;
-+              else
-+                      return -EPERM;
-+              if (copy_to_user(req_datap, (void *)&ctrl.portcfg, sizeof(ctrl.portcfg)))
-+                      return -EFAULT;
-+              break;
-+      case NATADDIP:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_IPCFG_T))
-+                      return -EPERM;
-+              i = nat_cfg.ipcfg[port_id].total;
-+              if (i >= CONFIG_NAT_MAX_IP_NUM)
-+                      return -E2BIG;
-+              if (copy_from_user((void *)&nat_cfg.ipcfg[port_id].entry[i], req_datap, sizeof(NAT_IPCFG_T)))
-+                      return -EFAULT;
-+              nat_cfg.ipcfg[port_id].total++;
-+              break;
-+      case NATDELIP:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_IPCFG_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&ctrl.ipcfg, req_datap, sizeof(ctrl.ipcfg)))
-+                      return -EFAULT;
-+              ipcfg = (NAT_IP_ENTRY_T *)&nat_cfg.ipcfg[port_id].entry[0];
-+              for (i=0; i<nat_cfg.ipcfg[port_id].total; i++, ipcfg++)
-+              {
-+                      if (ipcfg->ipaddr == ctrl.ipcfg.entry.ipaddr)
-+                      {
-+                              NAT_IP_ENTRY_T *ipcfg_next;
-+                              ipcfg_next = ipcfg + 1;
-+                              for (j=i+1; j < nat_cfg.ipcfg[port_id].total; i++, j++)
-+                              {
-+                                      memcpy((void *)ipcfg, (void *)ipcfg_next, sizeof(NAT_IP_ENTRY_T));
-+                                      ipcfg++;
-+                                      ipcfg_next++;
-+                              }
-+                              ipcfg->ipaddr = 0;
-+                              ipcfg->netmask = 0;
-+                              nat_cfg.ipcfg[port_id].total--;
-+                              return 0;
-+                      }
-+              }
-+              return -ENOENT;
-+      case NATGETIP:
-+              if (nat_hdr.len != sizeof(NAT_IPCFG_ALL_T))
-+                      return -EPERM;
-+              if (copy_to_user(req_datap, (void *)&nat_cfg.ipcfg[port_id], sizeof(NAT_IPCFG_ALL_T)))
-+                      return -EFAULT;
-+              break;
-+      case NATAXPORT:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_XPORT_T))
-+                      return -EPERM;
-+              i = nat_cfg.xport.total;
-+              if (i >= CONFIG_NAT_MAX_XPORT)
-+                      return -E2BIG;
-+              if (copy_from_user((void *)&nat_cfg.xport.entry[i], req_datap, sizeof(NAT_XPORT_T)))
-+                      return -EFAULT;
-+              nat_cfg.xport.total++;
-+              break;
-+      case NATDXPORT:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_XPORT_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&ctrl.xport, req_datap, sizeof(NAT_XPORT_T)))
-+                      return -EFAULT;
-+              xport_entry = (NAT_XPORT_ENTRY_T *)&nat_cfg.xport.entry[0];
-+              for (i=0; i<nat_cfg.xport.total; i++, xport_entry++)
-+              {
-+                      if (memcmp((void *)xport_entry, (void *)&ctrl.xport, sizeof(NAT_XPORT_ENTRY_T)) == 0)
-+                      {
-+                              NAT_XPORT_ENTRY_T *xport_next;
-+                              xport_next = xport_entry + 1;
-+                              for (j=i+1; j < nat_cfg.xport.total; i++, j++)
-+                              {
-+                                      memcpy((void *)xport_entry, (void *)xport_next, sizeof(NAT_XPORT_ENTRY_T));
-+                                      xport_entry++;
-+                                      xport_next++;
-+                              }
-+                              memset((void *)xport_entry, 0, sizeof(NAT_XPORT_ENTRY_T));
-+                              nat_cfg.xport.total--;
-+                              return 0;
-+                      }
-+              }
-+              return -ENOENT;
-+      case NATGXPORT:
-+              if (nat_hdr.len != sizeof(NAT_XPORT_ALL_T))
-+                      return -EPERM;
-+              if (copy_to_user(req_datap, (void *)&nat_cfg.xport, sizeof(NAT_XPORT_ALL_T)))
-+                      return -EFAULT;
-+              break;
-+      case NATSWEIGHT:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_WEIGHT_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&nat_cfg.weight, req_datap, sizeof(NAT_WEIGHT_T)))
-+                      return -EFAULT;
-+              mac_set_hw_tx_weight(dev, (char *)&nat_cfg.weight);
-+              break;
-+      case NATGWEIGHT:
-+              if (nat_hdr.len != sizeof(NAT_WEIGHT_T))
-+                      return -EPERM;
-+              mac_get_hw_tx_weight(dev, (char *)&nat_cfg.weight);
-+              if (copy_to_user(req_datap, (void *)&nat_cfg.weight, sizeof(NAT_WEIGHT_T)))
-+                      return -EFAULT;
-+              break;
-+      case NATAWRULE:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_WRULE_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&qid, req_datap, sizeof(qid)))
-+                      return -EFAULT;
-+              if (qid > CONFIG_NAT_TXQ_NUM)
-+                      return -EPERM;
-+              i = nat_cfg.wrule[qid].total;
-+              if (i >= CONFIG_NAT_MAX_WRULE)
-+                      return -E2BIG;
-+              if (copy_from_user((void *)&nat_cfg.wrule[qid].entry[i], req_datap+sizeof(qid), sizeof(NAT_WRULE_T)))
-+                      return -EFAULT;
-+              nat_cfg.wrule[qid].total++;
-+              break;
-+      case NATDWRULE:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_WRULE_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&ctrl.wrule, req_datap, sizeof(NAT_WRULE_T)))
-+                      return -EFAULT;
-+              qid = ctrl.wrule.qid;
-+              if (qid >= CONFIG_NAT_TXQ_NUM)
-+                      return -EPERM;
-+              wrule_entry = (NAT_WRULE_ENTRY_T *)&nat_cfg.wrule[qid].entry[0];
-+              for (i=0; i<nat_cfg.wrule[qid].total; i++, wrule_entry++)
-+              {
-+                      if (memcmp((void *)wrule_entry, (void *)&ctrl.wrule.entry, sizeof(NAT_WRULE_ENTRY_T)) == 0)
-+                      {
-+                              NAT_WRULE_ENTRY_T *wrule_next;
-+                              wrule_next = wrule_entry + 1;
-+                              for (j=i+1; j < nat_cfg.wrule[qid].total; i++, j++)
-+                              {
-+                                      memcpy((void *)wrule_entry, (void *)wrule_next, sizeof(NAT_WRULE_ENTRY_T));
-+                                      wrule_entry++;
-+                                      wrule_next++;
-+                              }
-+                              memset((void *)wrule_entry, 0, sizeof(NAT_WRULE_ENTRY_T));
-+                              nat_cfg.wrule[qid].total--;
-+                              return 0;
-+                      }
-+              }
-+              return -ENOENT;
-+      case NATGWRULE:
-+              if (nat_hdr.len != sizeof(NAT_WRULE_ALL_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&qid, req_datap, sizeof(qid)))
-+                      return -EFAULT;
-+              if (qid >= CONFIG_NAT_TXQ_NUM)
-+                      return -EPERM;
-+              if (copy_to_user(req_datap, (void *)&nat_cfg.wrule[qid], sizeof(NAT_WRULE_ALL_T)))
-+                      return -EFAULT;
-+              break;
-+      case NATSDEFQ:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_QUEUE_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&nat_cfg.default_hw_txq, req_datap, sizeof(u32)))
-+                      return -EFAULT;
-+              break;
-+      case NATGDEFQ:
-+              if (nat_hdr.len != sizeof(NAT_QUEUE_T))
-+                      return -EPERM;
-+              if (copy_to_user(req_datap, (void *)&nat_cfg.default_hw_txq, sizeof(u32)))
-+                      return -EFAULT;
-+      case NATRMIPCFG:
-+              nat_cfg.ipcfg[port_id].total = 0;
-+              break;
-+      case NATTESTENTRY:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              if (nat_hdr.len != sizeof(NAT_TESTENTRY_T))
-+                      return -EPERM;
-+              if (copy_from_user((void *)&ctrl.init_entry, req_datap, sizeof(ctrl.init_entry)))
-+                      return -EFAULT;
-+              if (ctrl.init_entry.init_enable != 0 && ctrl.init_entry.init_enable != 1)
-+                      return -EPERM;
-+              nat_cfg.init_enabled = ctrl.init_entry.init_enable;
-+              break;
-+
-+      default:
-+              return -EPERM;
-+      }
-+
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+*     nat_init_test_entry
-+*     Initialize NAT test hash entries
-+*
-+*     SmartBits P1  -----> Lepus GMAC 0 --------------+
-+*                                                                                                     |
-+*                                                                                                     |
-+*             P3  <----- Lepus GMAC 1 -- HW TxQ0 <--+
-+*                                                                       -- HW TxQ1 <--+
-+*                                                                       -- HW TxQ2 <--+
-+*                                                                       -- HW TxQ3 <--+
-+*
-+*     SmartBits P1  <----- Lepus GMAC 0 -- HW TxQ0 <--+
-+*                                                                       -- HW TxQ1 <--+
-+*                                     -- HW TxQ2 <--+
-+*                                                                       -- HW TxQ3 <--+
-+*                                                                                                     |
-+*                                                                                                     |
-+*             P3  -----> Lepus GMAC 1 --------------+
-+*
-+*   LAN GMAC0 <--------------------------------------------> GMAC1 WAN
-+*     192.168.[x].[y]:50 --> 168.95.[x].[y]:80 ---TXQ[y-1]---> 192.168.2.254:200[y] --> 168.95.[x].[y]:80
-+*     192.168.[x].[y]:50 <-- 168.95.[x].[y]:80 <--TXQ[y-1]---- 192.168.2.254:200[y] <-- 168.95.[x].[y]:80
-+*   where:
-+*             [x] : Packet Type
-+*             [y] : Tx Queue, 1 for TxQ0, 2 for TxQ1, 3 for TxQ2, 4 for TxQ3,
-+*
-+*
-+* Packet Type:
-+* 1. TCP Frames <---> TCP Frames
-+*   LAN GMAC0 <--------------------------------> GMAC1 WAN
-+*     192.168.1.1:50 --> 168.95.1.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.1.1:80
-+*     192.168.1.1:50 <-- 168.95.1.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.1.1:80
-+*
-+*     192.168.1.2:50 --> 168.95.1.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.1.2:80
-+*     192.168.1.2:50 <-- 168.95.1.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.1.2:80
-+*
-+*     192.168.1.3:50 --> 168.95.1.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.1.3:80
-+*     192.168.1.3:50 <-- 168.95.1.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.1.3:80
-+*
-+*     192.168.1.4:50 --> 168.95.1.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.1.4:80
-+*     192.168.1.4:50 <-- 168.95.1.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.1.4:80
-+*
-+* 2 TCP Frames <----> PPPoE + TCP Frames
-+*   LAN GMAC0 <--------------------------------> GMAC1 WAN
-+*     192.168.2.1:50 --> 168.95.2.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.2.1:80
-+*     192.168.2.1:50 <-- 168.95.2.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.2.1:80
-+*
-+*     192.168.2.2:50 --> 168.95.2.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.2.2:80
-+*     192.168.2.2:50 <-- 168.95.2.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.2.2:80
-+*
-+*     192.168.2.3:50 --> 168.95.2.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.2.3:80
-+*     192.168.2.3:50 <-- 168.95.2.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.2.3:80
-+*
-+*     192.168.2.4:50 --> 168.95.2.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.2.4:80
-+*     192.168.2.4:50 <-- 168.95.2.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.2.4:80
-+*
-+* 3 TCP Frames <----> VLAN + PPPoE + TCP Frames
-+*   LAN GMAC0 <--------------------------------> GMAC1 WAN
-+*     192.168.3.1:50 --> 168.95.3.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.3.1:80
-+*     192.168.3.1:50 <-- 168.95.3.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.3.1:80
-+*
-+*     192.168.3.2:50 --> 168.95.3.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.3.2:80
-+*     192.168.3.2:50 <-- 168.95.3.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.3.2:80
-+*
-+*     192.168.3.3:50 --> 168.95.3.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.3.3:80
-+*     192.168.3.3:50 <-- 168.95.3.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.3.3:80
-+*
-+*     192.168.3.4:50 --> 168.95.3.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.3.4:80
-+*     192.168.3.4:50 <-- 168.95.3.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.3.4:80
-+*
-+* 4 VLAN-A + TCP Frames <----> VLAN-B + PPPoE + TCP Frames
-+*   LAN GMAC0 <--------------------------------> GMAC1 WAN
-+*     192.168.4.1:50 --> 168.95.4.1:80 ---TXQ0---> 192.168.2.254:2001 --> 168.95.4.1:80
-+*     192.168.4.1:50 <-- 168.95.4.1:80 <--TXQ0---- 192.168.2.254:2001 <-- 168.95.4.1:80
-+*
-+*     192.168.4.2:50 --> 168.95.4.2:80 ---TXQ1---> 192.168.2.254:2002 --> 168.95.4.2:80
-+*     192.168.4.2:50 <-- 168.95.4.2:80 <--TXQ1---- 192.168.2.254:2002 <-- 168.95.4.2:80
-+*
-+*     192.168.4.3:50 --> 168.95.4.3:80 ---TXQ2---> 192.168.2.254:2003 --> 168.95.4.3:80
-+*     192.168.4.3:50 <-- 168.95.4.3:80 <--TXQ2---- 192.168.2.254:2003 <-- 168.95.4.3:80
-+*
-+*     192.168.4.4:50 --> 168.95.4.4:80 ---TXQ3---> 192.168.2.254:2004 --> 168.95.4.4:80
-+*     192.168.4.4:50 <-- 168.95.4.4:80 <--TXQ3---- 192.168.2.254:2004 <-- 168.95.4.4:80
-+*
-+*
-+*
-+*----------------------------------------------------------------------*/
-+#ifdef SL351x_NAT_TEST_BY_SMARTBITS
-+#define       NAT_IPIV(a,b,c,d)                       ((a<<24)+(b<<16)+(c<<8)+d)
-+#define     NAT_TEST_CLIENT_IP                        NAT_IPIV(192,168,1,1)
-+#define     NAT_TEST_SERVER_IP                        NAT_IPIV(168,95,1,1)
-+#define               NAT_TEST_LAN_IP                         NAT_IPIV(192,168,1,254)
-+#define               NAT_TEST_WAN_IP                         NAT_IPIV(192,168,2,254)
-+#define     NAT_TEST_MAP_PORT_BASE            2001
-+#define     NAT_TEST_SPORT                            50
-+#define     NAT_TEST_DPORT                            80
-+#define     NAT_TEST_PROTOCOL                 6
-+u8                    nat_test_lan_target_da[6]={0x00,0x11,0x22,0x33,0x44,0x55};
-+u8                    nat_test_wan_target_da[6]={0x00,0xaa,0xbb,0xcc,0xdd,0xee};
-+u8                    nat_test_lan_my_da[6]={0x00,0x11,0x11,0x11,0x11,0x11};
-+u8                    nat_test_wan_my_da[6]={0x00,0x22,0x22,0x22,0x22,0x22};
-+static void nat_init_test_entry(void)
-+{
-+      int                             i, j ;
-+      NAT_HASH_ENTRY_T        *hash_entry;
-+      u32                                     sip, dip;
-+      u32                                     hash_data[HASH_MAX_DWORDS];
-+      NAT_CFG_T                       *cfg;
-+      int                                     hash_index;
-+
-+      cfg = (NAT_CFG_T *)&nat_cfg;
-+      hash_entry = (NAT_HASH_ENTRY_T *)&hash_data;
-+      hash_entry->key.Ethertype       = 0;
-+      hash_entry->key.rule_id         = 0;
-+      hash_entry->key.ip_protocol = IPPROTO_TCP;
-+      hash_entry->key.reserved1       = 0;
-+      hash_entry->key.reserved2       = 0;
-+      // hash_entry->key.sip          = NAT_TEST_CLIENT_IP;
-+      // hash_entry->key.dip          = NAT_TEST_SERVER_IP;
-+      hash_entry->key.sport           = htons(NAT_TEST_SPORT);
-+      hash_entry->key.dport           = htons(NAT_TEST_DPORT);
-+      hash_entry->key.rule_id = cfg->tcp_udp_rule_id;
-+      hash_entry->action.dword = NAT_LAN2WAN_ACTIONS;
-+
-+      sip = NAT_TEST_CLIENT_IP;
-+      dip = NAT_TEST_SERVER_IP;
-+
-+      // Init TCP <------> TCP hash entries
-+      // LAN --> WAN
-+      // (1) TCP --> TCP
-+      // (2) TCP --> PPPoE + TCP
-+      // (3) TCP --> VLAN-B + PPPoE + TCP
-+      // (4) TCP + VLAN-A --> VLAN-B + PPPoE + TCP
-+      memcpy(hash_entry->param.da, nat_test_wan_target_da, 6);
-+      memcpy(hash_entry->param.sa, nat_test_wan_my_da, 6);
-+      hash_entry->key.port_id = cfg->lan_port;
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              if (i < 2)
-+              {
-+                      hash_entry->action.bits.dest_qid = i+2;
-+              }
-+              else
-+              {
-+                      hash_entry->action.bits.dest_qid = i;
-+              }
-+              hash_entry->action.bits.dest_qid += (cfg->wan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
-+              hash_entry->param.Sport = NAT_TEST_MAP_PORT_BASE+i;
-+              hash_entry->param.Dport = NAT_TEST_DPORT;
-+              for (j=0; j<4; j++)
-+              {
-+                      hash_entry->key.sip = sip + i + j*0x100;
-+                      hash_entry->key.dip = dip + i + j*0x100;
-+                      hash_entry->param.Dip = hash_entry->key.dip;
-+                      hash_entry->param.Sip = NAT_TEST_WAN_IP;
-+                      switch (j)
-+                      {
-+                      case 0:
-+                              hash_entry->action.bits.pppoe = 0;
-+                              hash_entry->param.pppoe = 0;
-+                              hash_entry->action.bits.vlan = 0;
-+                              hash_entry->param.vlan = 0;
-+                              break;
-+                      case 1:
-+                              hash_entry->action.bits.pppoe = 1;
-+                              hash_entry->param.pppoe = i+1;
-+                              hash_entry->action.bits.vlan = 0;
-+                              hash_entry->param.vlan = 0;
-+                              break;
-+                      case 2:
-+                              hash_entry->action.bits.pppoe = 1;
-+                              hash_entry->param.pppoe = i+1;
-+                              hash_entry->action.bits.vlan = 1;
-+                              hash_entry->param.vlan = i+10;
-+                              break;
-+                      case 3:
-+                              hash_entry->action.bits.pppoe = 1;
-+                              hash_entry->param.pppoe = i+1;
-+                              hash_entry->action.bits.vlan = 1;
-+                              hash_entry->param.vlan = i+10;
-+                              break;
-+                      }
-+                      hash_entry->tmo.counter = hash_entry->tmo.interval = 0x7fff;
-+                      hash_index = nat_build_keys(&hash_entry->key);
-+                      nat_write_hash_entry(hash_index, hash_entry);
-+                      hash_nat_enable_owner(hash_index);
-+                      hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
-+              }
-+      }
-+
-+
-+      // WAN --> LAN
-+      hash_entry->key.port_id         = cfg->wan_port;
-+      hash_entry->key.sport           = htons(NAT_TEST_DPORT);
-+      hash_entry->key.dport           = htons(NAT_TEST_DPORT);
-+      hash_entry->key.rule_id         = cfg->tcp_udp_rule_id;
-+      hash_entry->action.dword        = NAT_WAN2LAN_ACTIONS;
-+      hash_entry->key.sport           = htons(NAT_TEST_DPORT);
-+      memcpy(hash_entry->param.da, nat_test_lan_target_da, 6);
-+      memcpy(hash_entry->param.sa, nat_test_lan_my_da, 6);
-+      for (i=0; i<TOE_HW_TXQ_NUM; i++)
-+      {
-+              hash_entry->key.dport = htons(NAT_TEST_MAP_PORT_BASE + i);
-+              if (i < 2)
-+              {
-+                      hash_entry->action.bits.dest_qid = i+2;
-+              }
-+              else
-+              {
-+                      hash_entry->action.bits.dest_qid = i;
-+              }
-+              hash_entry->action.bits.dest_qid += (cfg->lan_port==0) ? TOE_GMAC0_HW_TXQ0_QID : TOE_GMAC1_HW_TXQ0_QID;
-+              hash_entry->param.Dport = NAT_TEST_SPORT;
-+              hash_entry->param.Sport = NAT_TEST_DPORT;
-+              hash_entry->param.da[5] = i;
-+              for (j=0; j<4; j++)
-+              {
-+                      hash_entry->key.sip = (dip + i + j*0x100);
-+                      hash_entry->key.dip = (NAT_TEST_WAN_IP);
-+                      hash_entry->param.Sip = hash_entry->key.sip;
-+                      hash_entry->param.Dip = sip + i + j*0x100;
-+                      switch (j)
-+                      {
-+                      case 0:
-+                              hash_entry->action.bits.pppoe = 0;
-+                              hash_entry->param.pppoe = 0;
-+                              hash_entry->action.bits.vlan = 0;
-+                              hash_entry->param.vlan = 0;
-+                              break;
-+                      case 1:
-+                              hash_entry->action.bits.pppoe = 2;
-+                              hash_entry->param.pppoe = i+1;
-+                              hash_entry->action.bits.vlan = 0;
-+                              hash_entry->param.vlan = 0;
-+                              break;
-+                      case 2:
-+                              hash_entry->action.bits.pppoe = 2;
-+                              hash_entry->param.pppoe = i+1;
-+                              hash_entry->action.bits.vlan = 2;
-+                              hash_entry->param.vlan = i+5;
-+                              break;
-+                      case 3:
-+                              hash_entry->action.bits.pppoe = 1;
-+                              hash_entry->param.pppoe = i+1;
-+                              hash_entry->action.bits.vlan = 1;
-+                              hash_entry->param.vlan = i+5;
-+                              break;
-+                      }
-+                      hash_entry->tmo.counter = hash_entry->tmo.interval = 0x7fff;
-+                      hash_index = nat_build_keys(&hash_entry->key);
-+                      nat_write_hash_entry(hash_index, hash_entry);
-+                      hash_nat_enable_owner(hash_index);
-+                      hash_validate_entry(hash_index); // Must last one, else HW Tx fast than SW
-+              }
-+      }
-+}
-+#endif        // SL351x_NAT_TEST_BY_SMARTBITS
-+
-+#endif // CONFIG_SL351x_NAT
-+
---- /dev/null
-+++ b/drivers/net/sl351x_proc.c
-@@ -0,0 +1,578 @@
-+/****************************************************************************
-+* Copyright 2006 Storlink Corp.  All rights reserved.
-+*----------------------------------------------------------------------------
-+* Name                        : sl351x_proc.c
-+* Description :
-+*             Handle Proc Routines for Storlink SL351x Platform
-+*
-+* History
-+*
-+*     Date            Writer          Description
-+*----------------------------------------------------------------------------
-+*     04/13/2006      Gary Chen       Create and implement
-+*
-+*
-+****************************************************************************/
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/compiler.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/delay.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/completion.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/semaphore.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/arch/it8712.h>
-+#include <linux/mtd/kvctl.h>
-+#include <linux/skbuff.h>
-+#include <linux/if_ether.h>
-+#include <linux/if_pppox.h>
-+#include <linux/in.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <linux/ppp_defs.h>
-+#ifdef CONFIG_NETFILTER
-+// #include <linux/netfilter_ipv4/ip_conntrack.h>
-+#endif
-+#include <linux/proc_fs.h>
-+#include <linux/seq_file.h>
-+#include <linux/percpu.h>
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif
-+
-+#define        MIDWAY
-+#define        SL_LEPUS
-+
-+// #define PROC_DEBUG_MSG     1
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/sl351x_gmac.h>
-+#include <asm/arch/sl351x_hash_cfg.h>
-+#include <asm/arch/sl351x_nat_cfg.h>
-+#include <asm/arch/sl351x_toe.h>
-+
-+#ifdef CONFIG_PROC_FS
-+/*----------------------------------------------------------------------
-+* Definition
-+*----------------------------------------------------------------------*/
-+#define       proc_printf                                     printk
-+#define SL351x_GMAC_PROC_NAME         "sl351x_gmac"
-+#define SL351x_NAT_PROC_NAME          "sl351x_nat"
-+#define SL351x_TOE_PROC_NAME          "sl351x_toe"
-+
-+/*----------------------------------------------------------------------
-+* Function Definition
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static int nat_ct_open(struct inode *inode, struct file *file);
-+static void *nat_ct_seq_start(struct seq_file *s, loff_t *pos);
-+static void nat_ct_seq_stop(struct seq_file *s, void *v);
-+static void *nat_ct_seq_next(struct seq_file *s, void *v, loff_t *pos);
-+static int nat_ct_seq_show(struct seq_file *s, void *v);
-+#endif
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+static int toe_ct_open(struct inode *inode, struct file *file);
-+static void *toe_ct_seq_start(struct seq_file *s, loff_t *pos);
-+static void toe_ct_seq_stop(struct seq_file *s, void *v);
-+static void *toe_ct_seq_next(struct seq_file *s, void *v, loff_t *pos);
-+static int toe_ct_seq_show(struct seq_file *s, void *v);
-+extern int sl351x_get_toe_conn_flag(int index);
-+extern struct toe_conn * sl351x_get_toe_conn_info(int index);
-+#endif
-+
-+static int gmac_ct_open(struct inode *inode, struct file *file);
-+static void *gmac_ct_seq_start(struct seq_file *s, loff_t *pos);
-+static void gmac_ct_seq_stop(struct seq_file *s, void *v);
-+static void *gmac_ct_seq_next(struct seq_file *s, void *v, loff_t *pos);
-+static int gmac_ct_seq_show(struct seq_file *s, void *v);
-+
-+
-+/*----------------------------------------------------------------------
-+* Data
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SYSCTL
-+// static struct ctl_table_header *nat_ct_sysctl_header;
-+#endif
-+
-+#ifdef CONFIG_SL351x_NAT
-+static struct seq_operations nat_ct_seq_ops = {
-+      .start = nat_ct_seq_start,
-+      .next  = nat_ct_seq_next,
-+      .stop  = nat_ct_seq_stop,
-+      .show  = nat_ct_seq_show
-+};
-+
-+static struct file_operations nat_file_ops= {
-+      .owner   = THIS_MODULE,
-+      .open    = nat_ct_open,
-+      .read    = seq_read,
-+      .llseek  = seq_lseek,
-+      .release = seq_release
-+};
-+#endif // CONFIG_SL351x_NAT
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+static struct seq_operations toe_ct_seq_ops = {
-+      .start = toe_ct_seq_start,
-+      .next  = toe_ct_seq_next,
-+      .stop  = toe_ct_seq_stop,
-+      .show  = toe_ct_seq_show
-+};
-+
-+static struct file_operations toe_file_ops= {
-+      .owner   = THIS_MODULE,
-+      .open    = toe_ct_open,
-+      .read    = seq_read,
-+      .llseek  = seq_lseek,
-+      .release = seq_release
-+};
-+#endif
-+
-+static struct seq_operations gmac_ct_seq_ops = {
-+      .start = gmac_ct_seq_start,
-+      .next  = gmac_ct_seq_next,
-+      .stop  = gmac_ct_seq_stop,
-+      .show  = gmac_ct_seq_show
-+};
-+
-+static struct file_operations gmac_file_ops= {
-+      .owner   = THIS_MODULE,
-+      .open    = gmac_ct_open,
-+      .read    = seq_read,
-+      .llseek  = seq_lseek,
-+      .release = seq_release
-+};
-+
-+#ifdef SL351x_GMAC_WORKAROUND
-+extern u32 gmac_workaround_cnt[4];
-+extern u32 gmac_short_frame_workaround_cnt[2];
-+#ifdef CONFIG_SL351x_NAT
-+      extern u32 sl351x_nat_workaround_cnt;
-+#endif
-+#endif
-+/*----------------------------------------------------------------------
-+* nat_ct_open
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static int nat_ct_open(struct inode *inode, struct file *file)
-+{
-+      return seq_open(file, &nat_ct_seq_ops);
-+}
-+#endif // CONFIG_SL351x_NAT
-+/*----------------------------------------------------------------------
-+* nat_ct_seq_start
-+* find the first
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static void *nat_ct_seq_start(struct seq_file *s, loff_t *pos)
-+{
-+      int i;
-+
-+      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
-+      for (i=*pos; i<HASH_TOTAL_ENTRIES; i++)
-+      {
-+              if (hash_get_nat_owner_flag(i))
-+              {
-+                      *pos = i;
-+                      return (void *)(i+1);
-+              }
-+      }
-+      return NULL;
-+}
-+#endif // CONFIG_SL351x_NAT
-+/*----------------------------------------------------------------------
-+* nat_ct_seq_stop
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static void nat_ct_seq_stop(struct seq_file *s, void *v)
-+{
-+}
-+#endif // CONFIG_SL351x_NAT
-+/*----------------------------------------------------------------------
-+* nat_ct_seq_next
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static void *nat_ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
-+{
-+      int i;
-+
-+      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
-+      (*pos)++;
-+      for (i=*pos; i<HASH_TOTAL_ENTRIES; i++)
-+      {
-+              if (hash_get_nat_owner_flag(i))
-+              {
-+                      *pos = i;
-+                      return (void *)(i+1);
-+              }
-+      }
-+      return NULL;
-+}
-+#endif // CONFIG_SL351x_NAT
-+/*----------------------------------------------------------------------
-+* nat_ct_seq_show
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_NAT
-+static int nat_ct_seq_show(struct seq_file *s, void *v)
-+{
-+      int                             idx;
-+      NAT_HASH_ENTRY_T        *nat_entry;
-+      GRE_HASH_ENTRY_T        *gre_entry;
-+
-+      idx = (int)v;
-+      if (idx<=0 || idx >HASH_TOTAL_ENTRIES)
-+              return -ENOSPC;
-+
-+      idx--;
-+      nat_entry = (NAT_HASH_ENTRY_T *)&hash_tables[idx];
-+      gre_entry = (GRE_HASH_ENTRY_T *)nat_entry;
-+      if (nat_entry->key.ip_protocol == IPPROTO_GRE)
-+      {
-+              if (seq_printf(s, "%4d: KEY MAC-%d [%d] %u.%u.%u.%u [%u]-->%u.%u.%u.%u\n",
-+                                      idx, gre_entry->key.port_id, gre_entry->key.ip_protocol,
-+                                      HIPQUAD(gre_entry->key.sip), ntohs(gre_entry->key.call_id),
-+                                      HIPQUAD(gre_entry->key.dip)))
-+                      return -ENOSPC;
-+              if (seq_printf(s, "      PARAMETER: %u.%u.%u.%u -->%u.%u.%u.%u [%u] Timeout:%ds\n",
-+                                      HIPQUAD(gre_entry->param.Sip),
-+                                      HIPQUAD(gre_entry->param.Dip), gre_entry->param.Dport,
-+                                      gre_entry->tmo.counter))
-+                      return -ENOSPC;
-+      }
-+      else
-+      {
-+              if (seq_printf(s, "%4d: KEY MAC-%d [%d] %u.%u.%u.%u [%u]-->%u.%u.%u.%u [%u]\n",
-+                                      idx, nat_entry->key.port_id, nat_entry->key.ip_protocol,
-+                                      HIPQUAD(nat_entry->key.sip), ntohs(nat_entry->key.sport),
-+                                      HIPQUAD(nat_entry->key.dip), ntohs(nat_entry->key.dport)))
-+                      return -ENOSPC;
-+              if (seq_printf(s, "      PARAMETER: %u.%u.%u.%u [%u]-->%u.%u.%u.%u [%u] Timeout:%ds\n",
-+                                      HIPQUAD(nat_entry->param.Sip), nat_entry->param.Sport,
-+                                      HIPQUAD(nat_entry->param.Dip), nat_entry->param.Dport,
-+                                      nat_entry->tmo.counter))
-+                      return -ENOSPC;
-+      }
-+      return 0;
-+}
-+#endif // CONFIG_SL351x_NAT
-+
-+/*----------------------------------------------------------------------
-+* toe_ct_open
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_RXTOE
-+static int toe_ct_open(struct inode *inode, struct file *file)
-+{
-+      return seq_open(file, &toe_ct_seq_ops);
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+* toe_ct_seq_start
-+* find the first
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_RXTOE
-+static void *toe_ct_seq_start(struct seq_file *s, loff_t *pos)
-+{
-+      int i;
-+
-+      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
-+      for (i=*pos; i<TOE_TOE_QUEUE_NUM; i++)
-+      {
-+              if (sl351x_get_toe_conn_flag(i))
-+              {
-+                      *pos = i;
-+                      return (void *)(i+1);
-+              }
-+      }
-+      return NULL;
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+* toe_ct_seq_stop
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_RXTOE
-+static void toe_ct_seq_stop(struct seq_file *s, void *v)
-+{
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+* toe_ct_seq_next
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_RXTOE
-+static void *toe_ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
-+{
-+      int i;
-+
-+      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
-+      (*pos)++;
-+      for (i=*pos; i<TOE_TOE_QUEUE_NUM; i++)
-+      {
-+              if (sl351x_get_toe_conn_flag(i))
-+              {
-+                      *pos = i;
-+                      return (void *)(i+1);
-+              }
-+      }
-+      return NULL;
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+* toe_ct_seq_show
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_SL351x_RXTOE
-+static int toe_ct_seq_show(struct seq_file *s, void *v)
-+{
-+      int                             idx;
-+      struct toe_conn         *toe_entry;
-+
-+      idx = (int)v;
-+      if (idx<=0 || idx >TOE_TOE_QUEUE_NUM)
-+              return -ENOSPC;
-+
-+      idx--;
-+      toe_entry = (struct toe_conn *)sl351x_get_toe_conn_info(idx);
-+      if (!toe_entry)
-+              return -ENOSPC;
-+
-+      if (seq_printf(s, "%4d: Qid %d MAC-%d TCP %u.%u.%u.%u [%u]-->%u.%u.%u.%u [%u]\n",
-+                              idx, toe_entry->qid, toe_entry->gmac->port_id,
-+                              NIPQUAD(toe_entry->saddr[0]), ntohs(toe_entry->source),
-+                              NIPQUAD(toe_entry->daddr[0]), ntohs(toe_entry->dest)))
-+                      return -ENOSPC;
-+      return 0;
-+}
-+#endif
-+/*----------------------------------------------------------------------
-+* gmac_ct_open
-+*----------------------------------------------------------------------*/
-+static int gmac_ct_open(struct inode *inode, struct file *file)
-+{
-+      return seq_open(file, &gmac_ct_seq_ops);
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_ct_seq_start
-+* find the first
-+*----------------------------------------------------------------------*/
-+static void *gmac_ct_seq_start(struct seq_file *s, loff_t *pos)
-+{
-+      int i;
-+      i = (int)*pos + 1;;
-+
-+      if (i > 9)
-+              return NULL;
-+      else
-+              return (void *)i;
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_ct_seq_stop
-+*----------------------------------------------------------------------*/
-+static void gmac_ct_seq_stop(struct seq_file *s, void *v)
-+{
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_ct_seq_next
-+*----------------------------------------------------------------------*/
-+static void *gmac_ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
-+{
-+      int i;
-+
-+      // proc_printf("%s: *pos=%d\n", __func__, (int)*pos);
-+
-+      (*pos)++;
-+      i = (int)*pos + 1;;
-+
-+      if (i > 9)
-+              return NULL;
-+      else
-+              return (void *)i;
-+}
-+
-+/*----------------------------------------------------------------------
-+* seq_dm_long
-+*----------------------------------------------------------------------*/
-+static void seq_dm_long(struct seq_file *s, u32 location, int length)
-+{
-+      u32             *start_p, *curr_p, *end_p;
-+      u32             *datap, data;
-+      int             i;
-+
-+      //if (length > 1024)
-+      //      length = 1024;
-+
-+      start_p = (u32 *)location;
-+      end_p = (u32 *)location + length;
-+      curr_p = (u32 *)((u32)location & 0xfffffff0);
-+      datap = (u32 *)location;
-+      while (curr_p < end_p)
-+      {
-+              cond_resched();
-+              seq_printf(s, "0x%08x: ",(u32)curr_p & 0xfffffff0);
-+              for (i=0; i<4; i++)
-+              {
-+                      if (curr_p < start_p || curr_p >= end_p)
-+               seq_printf(s, "         ");
-+                      else
-+                      {
-+                              data = *datap;
-+                              seq_printf(s, "%08X ", data);
-+                      }
-+                      if (i==1)
-+              seq_printf(s, "- ");
-+
-+                      curr_p++;
-+                      datap++;
-+              }
-+        seq_printf(s, "\n");
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* gmac_ct_seq_show
-+*----------------------------------------------------------------------*/
-+static int gmac_ct_seq_show(struct seq_file *s, void *v)
-+{
-+      switch ((int)v)
-+      {
-+              case 1:
-+                      seq_printf(s, "\nGMAC Global Registers\n");
-+                      seq_dm_long(s, TOE_GLOBAL_BASE, 32);
-+                      break;
-+              case 2:
-+                      seq_printf(s, "\nGMAC Non-TOE Queue Header\n");
-+                      seq_dm_long(s, TOE_NONTOE_QUE_HDR_BASE, 12);
-+                      break;
-+              case 3:
-+                      seq_printf(s, "\nGMAC TOE Queue Header\n");
-+                      seq_dm_long(s, TOE_TOE_QUE_HDR_BASE, 12);
-+                      break;
-+              case 4:
-+                      seq_printf(s, "\nGMAC-0 DMA Registers\n");
-+                      seq_dm_long(s, TOE_GMAC0_DMA_BASE, 52);
-+                      break;
-+              case 5:
-+                      seq_printf(s, "\nGMAC-0 Registers\n");
-+                      seq_dm_long(s, TOE_GMAC0_BASE, 32);
-+                      break;
-+              case 6:
-+                      seq_printf(s, "\nGMAC-1 DMA Registers\n");
-+                      seq_dm_long(s, TOE_GMAC1_DMA_BASE, 52);
-+                      break;
-+              case 7:
-+                      seq_printf(s, "\nGMAC-1 Registers\n");
-+                      seq_dm_long(s, TOE_GMAC1_BASE, 32);
-+                      break;
-+              case 8:
-+                      seq_printf(s, "\nGLOBAL Registers\n");
-+                      seq_dm_long(s, GMAC_GLOBAL_BASE_ADDR, 16);
-+                      break;
-+              case 9:
-+#ifdef SL351x_GMAC_WORKAROUND
-+                      seq_printf(s, "\nGMAC-0 Rx/Tx/Short Workaround: %u, %u, %u\n", gmac_workaround_cnt[0], gmac_workaround_cnt[1], gmac_short_frame_workaround_cnt[0]);
-+                      seq_printf(s, "GMAC-1 Rx/Tx/Short Workaround: %u, %u, %u\n", gmac_workaround_cnt[2], gmac_workaround_cnt[3], gmac_short_frame_workaround_cnt[1]);
-+#ifdef CONFIG_SL351x_NAT
-+                      seq_printf(s, "NAT Workaround: %u\n", sl351x_nat_workaround_cnt);
-+#endif
-+#endif
-+                      break;
-+              default:
-+                      return -ENOSPC;
-+      }
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+* init
-+*----------------------------------------------------------------------*/
-+static int __init init(void)
-+{
-+      struct proc_dir_entry *proc_gmac=NULL;
-+
-+#ifdef CONFIG_SL351x_NAT
-+      struct proc_dir_entry *proc_nat=NULL;
-+#endif
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+      struct proc_dir_entry *proc_toe=NULL;
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+      // nat_ct_sysctl_header = NULL;
-+#endif
-+      proc_gmac = proc_net_fops_create(SL351x_GMAC_PROC_NAME, 0440, &gmac_file_ops);
-+      if (!proc_gmac) goto init_bad;
-+
-+#ifdef CONFIG_SL351x_NAT
-+      proc_nat = proc_net_fops_create(SL351x_NAT_PROC_NAME, 0440, &nat_file_ops);
-+      if (!proc_nat) goto init_bad;
-+#endif // CONFIG_SL351x_NAT
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+      proc_toe = proc_net_fops_create(SL351x_TOE_PROC_NAME, 0440, &toe_file_ops);
-+      if (!proc_toe) goto init_bad;
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+      // nat_ct_sysctl_header = register_sysctl_table(nat_ct_net_table, 0);
-+      // if (!nat_ct_sysctl_header) goto init_bad;
-+#endif
-+
-+      return 0;
-+
-+init_bad:
-+      if (proc_gmac) proc_net_remove(SL351x_GMAC_PROC_NAME);
-+
-+#ifdef CONFIG_SL351x_NAT
-+      if (proc_nat) proc_net_remove(SL351x_NAT_PROC_NAME);
-+#endif
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+      if (proc_toe) proc_net_remove(SL351x_NAT_PROC_NAME);
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+      // if (nat_ct_sysctl_header) unregister_sysctl_table(nat_ct_sysctl_header);
-+#endif
-+      proc_printf("SL351x NAT Proc: can't create proc or register sysctl.\n");
-+      return -ENOMEM;
-+}
-+
-+/*----------------------------------------------------------------------
-+* fini
-+*----------------------------------------------------------------------*/
-+static void __exit fini(void)
-+{
-+      proc_net_remove(SL351x_GMAC_PROC_NAME);
-+
-+#ifdef CONFIG_SL351x_NAT
-+      proc_net_remove(SL351x_NAT_PROC_NAME);
-+#endif
-+
-+#ifdef CONFIG_SL351x_RXTOE
-+      proc_net_remove(SL351x_TOE_PROC_NAME);
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+      // unregister_sysctl_table(nat_ct_sysctl_header);
-+#endif
-+}
-+
-+/*----------------------------------------------------------------------
-+* module
-+*----------------------------------------------------------------------*/
-+module_init(init);
-+module_exit(fini);
-+
-+#endif        // CONFIG_PROC_FS
---- /dev/null
-+++ b/drivers/net/sl351x_toe.c
-@@ -0,0 +1,1083 @@
-+/**************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
-+*--------------------------------------------------------------------------
-+* Name                        : sl351x_toe.c
-+* Description :
-+*             Provide TOE routines for SL351x
-+*
-+* History
-+*
-+*     Date            Writer          Description
-+*----------------------------------------------------------------------------
-+*                             Xiaochong
-+*
-+****************************************************************************/
-+
-+#include <linux/pci.h>
-+#include <linux/ip.h>
-+#include <linux/ipv6.h>
-+#include <linux/tcp.h>
-+#include <linux/slab.h>
-+#include <linux/etherdevice.h>
-+#include <asm/io.h>
-+#include <linux/sysctl_storlink.h>
-+#include <net/tcp.h>
-+#include <linux/if_ether.h>
-+#include <asm/arch/sl351x_gmac.h>
-+#include <asm/arch/sl351x_toe.h>
-+#include <asm/arch/sl351x_hash_cfg.h>
-+#include <asm/arch/sl351x_nat_cfg.h>
-+
-+static int in_toe_isr;
-+static int toe_initialized=0;
-+
-+static struct toe_conn        toe_connections[TOE_TOE_QUEUE_NUM];
-+EXPORT_SYMBOL(toe_connections);
-+static __u32 toe_connection_bits[TOE_TOE_QUEUE_NUM/32] __attribute__ ((aligned(16)));
-+struct sk_buff* gen_pure_ack(struct toe_conn* connection, TOE_QHDR_T* toe_qhdr, INTR_QHDR_T *intr_curr_desc);
-+
-+extern struct storlink_sysctl storlink_ctl;
-+extern TOE_INFO_T toe_private_data;
-+extern spinlock_t gmac_fq_lock;
-+extern void mac_write_dma_reg(int mac, unsigned int offset, u32 data);
-+extern int mac_set_rule_reg(int mac, int rule, int enabled, u32 reg0, u32 reg1, u32 reg2);
-+extern int hash_add_toe_entry(HASH_ENTRY_T *entry);
-+extern void toe_gmac_fill_free_q(void);
-+
-+#define _DEBUG_SKB_           1
-+#ifdef _DEBUG_SKB_
-+/*---------------------------------------------------------------------------
-+ * _debug_skb
-+ *-------------------------------------------------------------------------*/
-+static inline void _debug_skb(struct sk_buff *skb, GMAC_RXDESC_T *toe_curr_desc, u32 data)
-+{
-+      if ((u32)skb < 0x1000)
-+      {
-+              printk("%s skb=%x\n", __func__, (u32)skb);
-+              while(1);
-+      }
-+      REG32(__va(toe_curr_desc->word2.buf_adr)-SKB_RESERVE_BYTES) = data;
-+}
-+#else
-+#define _debug_skb(x, y, z)
-+#endif
-+
-+/*---------------------------------------------------------------------------
-+ * get_connection_seq_num
-+ *-------------------------------------------------------------------------*/
-+u32 get_connection_seq_num(unsigned short qid)
-+{
-+      TOE_QHDR_T      *toe_qhdr;
-+
-+      toe_qhdr = (TOE_QHDR_T*)TOE_TOE_QUE_HDR_BASE;
-+      toe_qhdr += qid;
-+      return (u32)toe_qhdr->word3.seq_num;
-+}
-+EXPORT_SYMBOL(get_connection_seq_num);
-+
-+/*---------------------------------------------------------------------------
-+ * get_connection_ack_num
-+ *-------------------------------------------------------------------------*/
-+u32 get_connection_ack_num(unsigned short qid)
-+{
-+      TOE_QHDR_T      *toe_qhdr;
-+
-+      toe_qhdr = (TOE_QHDR_T*)TOE_TOE_QUE_HDR_BASE;
-+      toe_qhdr += qid;
-+      return (u32)toe_qhdr->word4.ack_num;
-+}
-+EXPORT_SYMBOL(get_connection_ack_num);
-+
-+/*---------------------------------------------------------------------------
-+ * dump_toe_qhdr
-+ *-------------------------------------------------------------------------*/
-+void dump_toe_qhdr(TOE_QHDR_T *toe_qhdr)
-+{
-+      printk("TOE w1 %x, w2 %x, w3 %x\n", toe_qhdr->word1.bits32,
-+              toe_qhdr->word2.bits32, toe_qhdr->word3.bits32);
-+      printk("w4 %x, w5 %x, w6 %x\n", toe_qhdr->word4.bits32,
-+              toe_qhdr->word5.bits32, toe_qhdr->word6.bits32);
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * dump_intrq_desc
-+ *-------------------------------------------------------------------------*/
-+void dump_intrq_desc(INTR_QHDR_T *intr_curr_desc)
-+{
-+      printk("INTR w0 %x, w1 %x, seq %x\n", intr_curr_desc->word0.bits32,
-+              intr_curr_desc->word1.bits32, intr_curr_desc->word2.bits32);
-+      printk("ack %x, w4 %x\n", intr_curr_desc->word3.bits32,
-+              intr_curr_desc->word4.bits32);
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * This routine will initialize a TOE matching rule
-+ * called by SL351x GMAC driver.
-+ *-------------------------------------------------------------------------*/
-+void sl351x_toe_init(void)
-+{
-+      GMAC_MRxCR0_T   mrxcr0;
-+      GMAC_MRxCR1_T   mrxcr1;
-+      GMAC_MRxCR2_T   mrxcr2;
-+      int     rule, rc;
-+
-+      if (toe_initialized)
-+              return;
-+
-+      toe_initialized = 1;
-+
-+#ifndef CONFIG_SL351x_NAT
-+      mrxcr0.bits32 = 0;
-+      mrxcr1.bits32 = 0;
-+      mrxcr2.bits32 = 0;
-+      mrxcr0.bits.l3 = 1;
-+      mrxcr0.bits.l4 = 1;
-+      mrxcr1.bits.sip = 1;
-+      mrxcr1.bits.dip = 1;
-+      mrxcr1.bits.l4_byte0_15 = 0x0f;
-+      mrxcr0.bits.sprx = 1;
-+      rule = 0;
-+      rc = mac_set_rule_reg(0, rule, 1, mrxcr0.bits32, mrxcr1.bits32,
-+                                              mrxcr2.bits32);
-+      if (rc<0) {
-+              printk("%s::Set MAC 0 rule fail!\n", __func__);
-+      }
-+      rc = mac_set_rule_reg(1, rule, 1, mrxcr0.bits32, mrxcr1.bits32,
-+                                              mrxcr2.bits32);
-+      if (rc<0) {
-+              printk("%s::Set MAC 1 rule fail!\n", __func__);
-+      }
-+#endif // CONFIG_SL351x_NAT
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * dump_intrq_desc
-+ * assign an interrupt queue number to a give tcp queue
-+ *-------------------------------------------------------------------------*/
-+int get_interrupt_queue_id(int tcp_qid)
-+{
-+      return (int)(tcp_qid & 0x0003);
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * reset_connection_index
-+ * reset the connection bit by given index
-+ *-------------------------------------------------------------------------*/
-+void reset_connection_index(__u8 index)
-+{
-+      __u32 mask = ~(0xffffffff & (1<< (index&0x1f)));
-+      toe_connection_bits[index>>5] = toe_connection_bits[index>>5] & mask;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * update_timer
-+ *-------------------------------------------------------------------------*/
-+void update_timer(struct toe_conn* connection)
-+{
-+//    if (time_before(jiffies, connection->last_rx_jiffies+3))
-+//    if ((jiffies + 0xffffffff - connection->last_rx_jiffies) & 0x3)
-+//    if (connection->last_rx_jiffies > jiffies)
-+//            printk("%s::jif %g, last_rx_jif %g\n", __func__, jiffies, connection->last_rx_jiffies);
-+/*    if ((long)(jiffies + 2)< 3) { // overflow...
-+              printk("%s::jiffies %x\n", __func__, jiffies);
-+      } */
-+//    if ((long)(jiffies - connection->last_rx_jiffies)< 2)
-+//            return;
-+      connection->last_rx_jiffies = jiffies;
-+      // gary chen mod_timer(&connection->rx_timer, jiffies+2);
-+      connection->rx_timer.expires = jiffies + 2;
-+      add_timer(&connection->rx_timer);
-+//    printk("%s::nt %x, lj %x\n", __func__, (jiffies+2), connection->last_rx_jiffies);
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * gen_pure_ack
-+ *-------------------------------------------------------------------------*/
-+struct sk_buff* gen_pure_ack(struct toe_conn* connection, TOE_QHDR_T* toe_qhdr,
-+INTR_QHDR_T *intr_curr_desc)
-+{
-+      struct sk_buff  *skb;
-+      struct iphdr    *ip_hdr;
-+      struct tcphdr   *tcp_hdr;
-+      struct ethhdr   *eth_hdr;
-+
-+      if ((skb= dev_alloc_skb(RX_BUF_SIZE))==NULL) {
-+              printk("%s::alloc pure ack fail!\n", __func__);
-+              return NULL;
-+      }
-+      skb_reserve(skb, RX_INSERT_BYTES);
-+      memset(skb->data, 0, 60);
-+
-+      eth_hdr = (struct ethhdr*)&(skb->data[0]);
-+      memcpy(eth_hdr, &connection->l2_hdr, sizeof(struct ethhdr));
-+
-+      ip_hdr = (struct iphdr*)&(skb->data[14]);
-+      ip_hdr->version = connection->ip_ver;
-+      ip_hdr->ihl = 20>>2;
-+      ip_hdr->tot_len = ntohs(40);
-+      ip_hdr->frag_off = htons(IP_DF);
-+      ip_hdr->ttl = 128;
-+      ip_hdr->protocol = 0x06;
-+      ip_hdr->saddr = connection->saddr[0];
-+      ip_hdr->daddr = connection->daddr[0];
-+//    printk("%s ip sa %x, da %x\n",
-+//            __func__, ntohl(ip_hdr->saddr), ntohl(ip_hdr->daddr));
-+
-+      tcp_hdr = (struct tcphdr*)&(skb->data[34]);
-+      tcp_hdr->source = connection->source;
-+      tcp_hdr->dest = connection->dest;
-+      if (intr_curr_desc) {
-+              tcp_hdr->seq = htonl(intr_curr_desc->word2.seq_num);
-+              tcp_hdr->ack_seq = htonl(intr_curr_desc->word3.ack_num);
-+              tcp_hdr->window = htons(intr_curr_desc->word0.bits.win_size);
-+      } else {
-+              tcp_hdr->seq = htonl(toe_qhdr->word3.seq_num);
-+              tcp_hdr->ack_seq = htonl(toe_qhdr->word4.ack_num);
-+              tcp_hdr->window = htons(toe_qhdr->word6.bits.WinSize);
-+      }
-+      tcp_hdr->ack = 1;
-+      tcp_hdr->doff = 20 >> 2;
-+#if 0
-+      if (!intr_curr_desc) {
-+              unsigned char byte;
-+              for (i=0; i<20; i++) {
-+                      byte = skb->data[34+i];
-+                      printk("%x ", byte);
-+              }
-+              printk("\n");
-+      }
-+#endif
-+      TCP_SKB_CB(skb)->connection = connection;
-+      return skb;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * connection_rx_timer
-+ *-------------------------------------------------------------------------*/
-+void connection_rx_timer(unsigned long *data)
-+{
-+      struct toe_conn *connection = (struct toe_conn*)data;
-+      unsigned int    tcp_qid, toeq_wptr;
-+      unsigned int    pkt_size, desc_count;
-+      struct sk_buff  *skb;
-+      GMAC_RXDESC_T   *toe_curr_desc;
-+      TOE_QHDR_T      *toe_qhdr;
-+      struct net_device       *dev;
-+      unsigned long   conn_flags;
-+      DMA_RWPTR_T             toeq_rwptr;
-+      unsigned short  timeout_descs;
-+
-+      if (in_toe_isr)
-+              printk("%s::in_toe_isr=%d!\n", __func__, in_toe_isr);
-+
-+      if (connection) {
-+              /* should we disable gmac interrupt first? */
-+              if (!connection->gmac)
-+                      printk("%s::conn gmac %x!\n", __func__, (u32)connection->gmac);
-+              local_irq_save(conn_flags);
-+              if (!spin_trylock(&connection->conn_lock)) {
-+                      local_irq_restore(conn_flags);
-+                      // timer should be updated by the toeq isr. So no need to update here.
-+                      printk("%s::conn_lock is held by ISR!\n", __func__);
-+                      return;
-+              }
-+              disable_irq(connection->gmac->irq);
-+
-+              /* disable hash entry and get toeq desc. */
-+              hash_set_valid_flag(connection->hash_entry_index, 0);
-+              do{} while(0);  /* wait until HW finish */
-+
-+              dev = connection->dev;
-+              if (!dev)
-+                      printk("%s::conn dev NULL!\n", __func__);
-+              tcp_qid = connection->qid;
-+              toe_qhdr = (TOE_QHDR_T *)(TOE_TOE_QUE_HDR_BASE +
-+                            tcp_qid * sizeof(TOE_QHDR_T));
-+              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
-+              toeq_wptr = toe_qhdr->word1.bits.wptr;
-+              timeout_descs = toeq_wptr - toeq_rwptr.bits.rptr;
-+
-+              if (toeq_rwptr.bits.rptr == toeq_wptr) {
-+                      if (toe_qhdr->word5.bits32) {
-+                              // shall we check toe_qhdr->word2.bits?
-+                              skb = gen_pure_ack(connection, toe_qhdr, (INTR_QHDR_T *)NULL);
-+                              skb_put(skb, 54);
-+                              skb->dev = connection->dev;
-+                              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+                              skb->protocol = eth_type_trans(skb, connection->dev);
-+                              netif_rx(skb);
-+                              connection->dev->last_rx = jiffies;
-+                      }
-+              } else {
-+                      while (toeq_rwptr.bits.rptr != toeq_rwptr.bits.wptr) {
-+                              /* we just simply send those packets to tcp? */
-+                              toe_curr_desc = (GMAC_RXDESC_T*)(toe_private_data.toe_desc_base[tcp_qid]
-+                                      + toeq_rwptr.bits.rptr * sizeof(GMAC_RXDESC_T));
-+                              connection->curr_desc = toe_curr_desc;
-+                              if (toe_curr_desc->word3.bits.ctrl_flag) {
-+                                      printk("%s::ctrl flag! %x, conn rptr %d, to %d, jif %x, conn_jif %x\n",
-+                                              __func__, toe_curr_desc->word3.bits32,
-+                                              connection->toeq_rwptr.bits.rptr, timeout_descs,
-+                                              (u32)jiffies, (u32)connection->last_rx_jiffies);
-+                              }
-+                              desc_count = toe_curr_desc->word0.bits.desc_count;
-+                              pkt_size = toe_curr_desc->word1.bits.byte_count;
-+                              consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
-+                                      PCI_DMA_FROMDEVICE);
-+                              skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr)-
-+                                      SKB_RESERVE_BYTES));
-+                              _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x02);
-+                              connection->curr_rx_skb = skb;
-+                              skb_reserve(skb, RX_INSERT_BYTES);
-+                              skb_put(skb, pkt_size);
-+                              skb->dev = dev;
-+                              skb->protocol = eth_type_trans(skb, dev);
-+                              {
-+                                      struct iphdr* ip_hdr = (struct iphdr*)&(skb->data[0]);
-+                                      if (toe_curr_desc->word3.bits.ctrl_flag)
-+                                              printk("%s::ip id %x\n", __func__, ntohs(ip_hdr->id));
-+                              }
-+                              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+
-+                              netif_rx(skb);
-+                              dev->last_rx = jiffies;
-+#if 0
-+                              if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
-+                                      printk("%s::alloc buf fail!\n", __func__);
-+                              }
-+                              *(unsigned int*)(skb->data) = (unsigned int)skb;
-+                              connection->curr_rx_skb = skb;
-+                              skb_reserve(skb, SKB_RESERVE_BYTES);
-+                              spin_lock_irqsave(&connection->gmac->rx_mutex, flags);
-+                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                              if (toe_private_data.fq_rx_rwptr.bits.wptr != fq_rwptr.bits.wptr) {
-+                                      mac_stop_txdma((struct net_device*)connection->dev);
-+                                      spin_unlock_irqrestore(&connection->gmac->rx_mutex, flags);
-+                                      while(1);
-+                              }
-+                              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base + fq_rwptr.bits.wptr;
-+                              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
-+                              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
-+                              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
-+                              toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
-+                              spin_unlock_irqrestore(&connection->gmac->rx_mutex, flags);
-+#endif
-+//                            spin_lock_irqsave(&connection->gmac->rx_mutex, flags);
-+                              toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
-+                              SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
-+//                            spin_unlock_irqrestore(&connection->gmac->rx_mutex, flags);
-+                              connection->toeq_rwptr.bits32 = toeq_rwptr.bits32;
-+                      }
-+                      toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
-+//                    toe_gmac_fill_free_q();
-+              }
-+              connection->last_rx_jiffies = jiffies;
-+              if (connection->status != TCP_CONN_CLOSED)
-+                      mod_timer(&connection->rx_timer, jiffies+2);
-+              if (connection->status != TCP_CONN_ESTABLISHED)
-+                      printk("%s::conn status %x\n", __func__, connection->status);
-+              hash_set_valid_flag(connection->hash_entry_index, 1);
-+              enable_irq(connection->gmac->irq);
-+              // Gary Chen spin_unlock_irqrestore(&connection->conn_lock, conn_flags);
-+      }
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * free_toeq_descs
-+ *-------------------------------------------------------------------------*/
-+void free_toeq_descs(int qid, TOE_INFO_T *toe)
-+{
-+      void    *desc_ptr;
-+
-+      desc_ptr = (void*)toe->toe_desc_base[qid];
-+      pci_free_consistent(NULL, TOE_TOE_DESC_NUM*sizeof(GMAC_RXDESC_T), desc_ptr,
-+         (dma_addr_t)toe->toe_desc_base_dma[qid]);
-+      toe->toe_desc_base[qid] = 0;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * set_toeq_hdr
-+ *-------------------------------------------------------------------------*/
-+void set_toeq_hdr(struct toe_conn*    connection, TOE_INFO_T* toe, struct net_device *dev)
-+{
-+      volatile TOE_QHDR_T     *toe_qhdr;
-+      volatile unsigned int   toeq_wptr; // toeq_rptr
-+      volatile GMAC_RXDESC_T  *toe_curr_desc;
-+      struct sk_buff  *skb;
-+      unsigned int    pkt_size;
-+      DMA_RWPTR_T     toeq_rwptr;
-+
-+      if (connection->status == TCP_CONN_CLOSING) {
-+              connection->status = TCP_CONN_CLOSED;
-+              hash_set_valid_flag(connection->hash_entry_index, 0);
-+              // remove timer first.
-+              // del_timer_sync(&(connection->rx_timer));
-+              // check if any queued frames last time.
-+              toe_qhdr = (volatile TOE_QHDR_T*)TOE_TOE_QUE_HDR_BASE;
-+              toe_qhdr += connection->qid;
-+              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
-+
-+              //toeq_rptr = toe_qhdr->word1.bits.rptr;
-+              toeq_wptr = toe_qhdr->word1.bits.wptr;
-+              while (toeq_rwptr.bits.rptr != toeq_wptr) {
-+                      printk("%s::pending frames in TOE Queue before closing!\n", __func__);
-+                      toe_curr_desc = (GMAC_RXDESC_T*)(toe->toe_desc_base[connection->qid] +
-+                              toe_qhdr->word1.bits.rptr*sizeof(GMAC_RXDESC_T));
-+                      connection->curr_desc = (GMAC_RXDESC_T *)toe_curr_desc;
-+                      pkt_size = toe_curr_desc->word1.bits.byte_count;
-+                      consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
-+                              PCI_DMA_FROMDEVICE);
-+                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr) -
-+                              SKB_RESERVE_BYTES));
-+                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x03);
-+                      connection->curr_rx_skb = skb;
-+                      skb_reserve(skb, RX_INSERT_BYTES);
-+                      skb_put(skb, pkt_size);
-+                      skb->dev = connection->dev;
-+                      skb->protocol = eth_type_trans(skb, connection->dev);
-+                      skb->ip_summed = CHECKSUM_UNNECESSARY;
-+                      netif_rx(skb);
-+                      connection->dev->last_rx = jiffies;
-+
-+                      toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
-+                      SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
-+              }
-+              free_toeq_descs(connection->qid, toe);
-+              // shall we re-fill free queue?
-+
-+              reset_connection_index(connection->qid);
-+              //memset(connection, 0, sizeof(struct toe_conn));
-+              printk(" del timer and close connection %x, qid %d\n", (u32)connection, connection->qid);
-+              return;
-+      }
-+      /* enable or setup toe queue header */
-+      if (connection->status == TCP_CONN_CONNECTING && storlink_ctl.rx_max_pktsize) {
-+              volatile TOE_QHDR_T     *qhdr;
-+              int iq_id;
-+              connection->status = TCP_CONN_ESTABLISHED;
-+              qhdr = (volatile TOE_QHDR_T*)((unsigned int)TOE_TOE_QUE_HDR_BASE +
-+                             connection->qid * sizeof(TOE_QHDR_T));
-+
-+              iq_id = get_interrupt_queue_id(connection->qid);
-+              connection->dev = dev;
-+              connection->gmac = dev->priv;
-+              connection->toeq_rwptr.bits32 = 0;
-+
-+//            qhdr->word6.bits.iq_num = iq_id;
-+              qhdr->word6.bits.MaxPktSize = (connection->max_pktsize)>>2; // in word.
-+              qhdr->word7.bits.AckThreshold = connection->ack_threshold;
-+              qhdr->word7.bits.SeqThreshold = connection->seq_threshold;
-+
-+              // init timer.
-+#if 1
-+              init_timer(&connection->rx_timer);
-+              connection->rx_timer.expires = jiffies + 5;
-+              connection->rx_timer.data = (unsigned long)connection;
-+              connection->rx_timer.function = (void *)&connection_rx_timer;
-+              add_timer(&connection->rx_timer);
-+              connection->last_rx_jiffies = jiffies;
-+              printk("init_timer %x\n", (u32)jiffies);
-+#endif
-+              hash_set_valid_flag(connection->hash_entry_index, 1);
-+              return;
-+      } else {
-+              printk("%s::conn status %x, rx_pktsize %d\n",
-+                      __func__, connection->status, storlink_ctl.rx_max_pktsize);
-+      }
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * get_connection_index
-+ * get_connection_index will find an available index for the connection,
-+ * when allocate a new connection is needed.
-+ * we find available Qid from AV bits and write to hash_table, so that when RxTOE
-+ * packet is received, sw_id from ToeQ descriptor is also the Qid of conneciton Q.
-+ *-------------------------------------------------------------------------*/
-+int get_connection_index(void)
-+{
-+      int i=0, j=0, index=-1;
-+      __u32   connection_bits;
-+
-+      for (i = 0; i< TOE_TOE_QUEUE_NUM/32; i++) {
-+              connection_bits = ~(toe_connection_bits[i]);
-+              if (connection_bits == 0)
-+                      // all 32 bits are used.
-+                      continue;
-+
-+              for (j=0; j<32; j++) {
-+                      if (connection_bits & 0x01) {
-+                              index = i*32 + j;
-+                              return index;
-+                      }
-+                      connection_bits = connection_bits >> 1;
-+              }
-+      }
-+      return index;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * set_toe_connection
-+ *-------------------------------------------------------------------------*/
-+void set_toe_connection(int index, int val)
-+{
-+      if (val) {
-+              toe_connection_bits[index/32] |= (1<<(index%32));
-+      } else {
-+              toe_connection_bits[index/32] &= (~(1<<(index%32)));
-+      }
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * sl351x_get_toe_conn_flag
-+ *-------------------------------------------------------------------------*/
-+int sl351x_get_toe_conn_flag(int index)
-+{
-+      if (index < TOE_TOE_QUEUE_NUM)
-+              return (toe_connection_bits[index/32] & (1 << (index %32)));
-+      else
-+              return 0;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * sl351x_get_toe_conn_info
-+ *-------------------------------------------------------------------------*/
-+struct toe_conn * sl351x_get_toe_conn_info(int index)
-+{
-+      if (index < TOE_TOE_QUEUE_NUM)
-+              return (struct toe_conn *)&toe_connections[index];
-+      else
-+              return NULL;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * create_sw_toe_connection
-+ *-------------------------------------------------------------------------*/
-+struct toe_conn* create_sw_toe_connection(int qid, int ip_ver, void* ip_hdr,
-+      struct tcphdr* tcp_hdr)
-+{
-+      struct toe_conn*        connection =  &(toe_connections[qid]);
-+
-+      connection->ip_ver = (__u8)ip_ver;
-+      connection->qid = (__u8)qid;
-+      connection->source = (__u16)tcp_hdr->source;
-+      connection->dest = (__u16)tcp_hdr->dest;
-+      if (ip_ver == 4) {
-+              struct iphdr* iph = (struct iphdr*) ip_hdr;
-+              connection->saddr[0] = (__u32)iph->saddr;
-+              connection->daddr[0] = (__u32)iph->daddr;
-+//            printk("%s::saddr %x, daddr %x\n", __func__,
-+//                    ntohl(connection->saddr[0]), ntohl(connection->daddr[0]));
-+      } else if (ip_ver == 6) {
-+              struct ipv6hdr *iph = (struct ipv6hdr*)ip_hdr;
-+              int i=0;
-+              for (i=0; i<4; i++) {
-+                      connection->saddr[i] = (__u32)iph->saddr.in6_u.u6_addr32[i];
-+                      connection->daddr[i] = (__u32)iph->daddr.in6_u.u6_addr32[i];
-+              }
-+      }
-+      connection->status = TCP_CONN_CREATION;
-+      return connection;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * fill_toeq_buf
-+ *-------------------------------------------------------------------------*/
-+int fill_toeq_buf(int index, TOE_INFO_T* toe)
-+{
-+      volatile TOE_QHDR_T     *qhdr;
-+      //struct toe_conn* connection;
-+      GMAC_RXDESC_T   *desc_ptr;
-+
-+      if (!toe->toe_desc_base[index]) {
-+              // first time. init.
-+              desc_ptr = (GMAC_RXDESC_T*)(pci_alloc_consistent(NULL, TOE_TOE_DESC_NUM
-+                          *sizeof(GMAC_RXDESC_T), (dma_addr_t*)&toe->toe_desc_base_dma[index]));
-+
-+              toe->toe_desc_num = TOE_TOE_DESC_NUM;
-+              toe->toe_desc_base[index] = (unsigned int)desc_ptr;
-+      }
-+      qhdr = (volatile TOE_QHDR_T*)((unsigned int)TOE_TOE_QUE_HDR_BASE +
-+                                                                      index*sizeof(TOE_QHDR_T));
-+      //connection = (struct toe_conn*)&(toe_connections[index]);
-+
-+      qhdr->word0.base_size = ((unsigned int)toe->toe_desc_base_dma[index]&TOE_QHDR0_BASE_MASK)
-+                                      | TOE_TOE_DESC_POWER;
-+      qhdr->word1.bits32 = 0;
-+      qhdr->word2.bits32 = 0;
-+      qhdr->word3.bits32 = 0;
-+      qhdr->word4.bits32 = 0;
-+      qhdr->word5.bits32 = 0;
-+      return 1;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * create_toe_hash_entry_smb
-+ * add SMB header in hash entry.
-+ *-------------------------------------------------------------------------*/
-+int create_toe_hash_entry_smb(int ip_ver, void* ip_hdr, struct tcphdr* tcp_hdr,
-+      int sw_id)
-+{
-+      HASH_ENTRY_T    hash_entry, *entry;
-+      int     hash_entry_index;
-+      int i;
-+
-+      entry = (HASH_ENTRY_T*)&hash_entry;
-+      memset((void*)entry, 0, sizeof(HASH_ENTRY_T));
-+      entry->rule = 0;
-+
-+      /* enable fields of hash key */
-+      entry->key_present.ip_protocol = 1;
-+      entry->key_present.sip = 1;
-+      entry->key_present.dip = 1;
-+      entry->key_present.l4_bytes_0_3 = 1;    // src port and dest port
-+      entry->key_present.l7_bytes_0_3 = 0;    // do we need to enable NETBIOS? how?
-+      entry->key_present.l7_bytes_4_7 = 1;    // "SMB" header
-+
-+      /* hash key */
-+      entry->key.ip_protocol = IPPROTO_TCP;
-+      if (ip_ver == 4) {
-+              struct iphdr *iph = (struct iphdr*)ip_hdr;
-+              memcpy(entry->key.sip, &iph->saddr, 4);
-+              memcpy(entry->key.dip, &iph->daddr, 4);
-+      } else if (ip_ver == 6) {
-+              struct ipv6hdr *iph = (struct ipv6hdr*)ip_hdr;
-+              for (i=0; i<4; i++) {
-+                      memcpy(&(entry->key.sip[i*4]), &(iph->saddr.in6_u.u6_addr32[i]), 4);
-+                      memcpy(&(entry->key.dip[i*4]), &(iph->daddr.in6_u.u6_addr32[i]), 4);
-+              }
-+      }
-+      *(__u16*)&entry->key.l4_bytes[0] = tcp_hdr->source;
-+      *(__u16*)&entry->key.l4_bytes[2] = tcp_hdr->dest;
-+
-+      entry->key.l7_bytes[4] = 0xff;
-+      entry->key.l7_bytes[5] = 0x53;
-+      entry->key.l7_bytes[6] = 0x4d;
-+      entry->key.l7_bytes[7] = 0x42;
-+
-+      /* action of hash entry match */
-+      entry->action.sw_id = 1;
-+      entry->action.dest_qid = (__u8)TOE_TOE_QID(sw_id);
-+      entry->action.srce_qid = 0;
-+      hash_entry_index = hash_add_toe_entry(entry);
-+
-+      return hash_entry_index;
-+}
-+
-+// best performance of tcp streaming.
-+/*---------------------------------------------------------------------------
-+ * create_toe_hash_entry_smb
-+ * add SMB header in hash entry.
-+ *-------------------------------------------------------------------------*/
-+int create_toe_hash_entry_ftp(int ip_ver, void* ip_hdr, struct tcphdr* tcphdr)
-+{
-+      return 0;
-+}
-+
-+// is hash entry for nfs needed?
-+
-+/*
-+ * Create a TOE hash entry by given ip addresses and tcp port numbers.
-+ * hash entry index will be saved in sw connection.
-+ */
-+/*---------------------------------------------------------------------------
-+ * create_toe_hash_entry
-+ *-------------------------------------------------------------------------*/
-+int create_toe_hash_entry(int ip_ver, void* ip_hdr, struct tcphdr* tcp_hdr, int sw_id)
-+{
-+      HASH_ENTRY_T    hash_entry, *entry;
-+//    unsigned long   hash_key[HASH_MAX_DWORDS];
-+      int     hash_entry_index;
-+
-+      entry = (HASH_ENTRY_T*) &hash_entry;
-+      memset((void*)entry, 0, sizeof(HASH_ENTRY_T));
-+      entry->rule = 0;
-+      /* enable fields of hash key */
-+      entry->key_present.ip_protocol = 1;
-+      entry->key_present.sip = 1;
-+      entry->key_present.dip = 1;
-+      entry->key_present.l4_bytes_0_3 = 1;    // src port and dest port
-+
-+      /* hash key */
-+      entry->key.ip_protocol = IPPROTO_TCP;
-+      if (ip_ver == 4) {
-+              // key of ipv4
-+              struct iphdr* iph = (struct iphdr*)ip_hdr;
-+              memcpy(entry->key.sip, &iph->saddr, 4);
-+              memcpy(entry->key.dip, &iph->daddr, 4);
-+      } else if (ip_ver == 6) {
-+              // key of ipv6
-+              int i=0;
-+              struct ipv6hdr *iph = (struct ipv6hdr*)ip_hdr;
-+              for (i=0; i<4; i++) {
-+                      memcpy(&(entry->key.sip[i*4]), &(iph->saddr.in6_u.u6_addr32[i]), 4);
-+                      memcpy(&(entry->key.dip[i*4]), &(iph->daddr.in6_u.u6_addr32[i]), 4);
-+              }
-+      }
-+      *(__u16*)&entry->key.l4_bytes[0] = tcp_hdr->source;
-+      *(__u16*)&entry->key.l4_bytes[2] = tcp_hdr->dest;
-+      // is it necessary to write ip version to hash key?
-+
-+      /* action of hash entry match */
-+      entry->action.sw_id = 1;
-+      entry->action.dest_qid = (__u8)TOE_TOE_QID(sw_id);
-+      entry->action.srce_qid = 0;     // 0 for SW FreeQ. 1 for HW FreeQ.
-+      hash_entry_index = hash_add_toe_entry(entry);
-+//    printk("\n%s. sw_id %d, hash_entry index %x\n",
-+//            __func__, TOE_TOE_QID(sw_id), hash_entry_index);
-+      return hash_entry_index;
-+}
-+
-+/*---------------------------------------------------------------------------
-+ * init_toeq
-+ * 1. Reserve a TOE Queue id first, to get the sw toe_connection.
-+ * 2. Setup the hash entry with given iphdr and tcphdr, save hash entry index
-+ *    in sw toe_connection.
-+ * 3. Prepare sw toe_connection and allocate buffers.
-+ * 4. Validate hash entry.
-+ *-------------------------------------------------------------------------*/
-+struct toe_conn* init_toeq(int ipver, void* iph, struct tcphdr* tcp_hdr,
-+      TOE_INFO_T* toe, unsigned char* l2hdr)
-+{
-+//    printk("\t*** %s, ipver %d\n", __func__, ipver);
-+      int qid=-1;
-+      struct toe_conn* connection;
-+      int hash_entry_index;
-+      // int i=0;
-+      unsigned short  dest_port = ntohs(tcp_hdr->dest);
-+
-+      if (dest_port == 445) {
-+              printk("%s::SMB/CIFS connection\n", __func__);
-+      } else if (dest_port == 20) {
-+              printk("%s::ftp-data connection\n", __func__);
-+      } else if (dest_port == 2049) {
-+              printk("%s::nfs daemon connection\n", __func__);
-+      }
-+      qid = get_connection_index();
-+      if (qid<0)
-+              return 0;       // setup toeq failure
-+      set_toe_connection(qid, 1); // reserve this sw toeq.
-+
-+      //connection = (struct toe_conn*)&(toe_connections[qid]);
-+      hash_entry_index = create_toe_hash_entry(ipver, iph, tcp_hdr, qid);
-+      if (hash_entry_index <0) {
-+              printk("%s::release toe hash entry!\n", __func__);
-+              set_toe_connection(qid, 0); // release this sw toeq.
-+              return 0;
-+      }
-+      connection = create_sw_toe_connection(qid, ipver, iph, tcp_hdr);
-+      connection->hash_entry_index = (__u16) hash_entry_index;
-+
-+      fill_toeq_buf(qid, toe);
-+      memcpy(&connection->l2_hdr, l2hdr, sizeof(struct ethhdr));
-+      spin_lock_init(&connection->conn_lock);
-+
-+      return connection;
-+}
-+
-+#if 0
-+/*----------------------------------------------------------------------
-+*   toe_init_toe_queue
-+*   (1) Initialize the TOE Queue Header
-+*       Register: TOE_TOE_QUE_HDR_BASE (0x60003000)
-+*   (2) Initialize Descriptors of TOE Queues
-+*----------------------------------------------------------------------*/
-+void toe_init_toe_queue(TOE_INFO_T* toe)
-+{
-+}
-+EXPORT_SYMBOL(toe_init_toe_queue);
-+#endif
-+
-+/*---------------------------------------------------------------------------
-+ * dump_jumbo_skb
-+ *-------------------------------------------------------------------------*/
-+void dump_jumbo_skb(struct jumbo_frame *jumbo_skb)
-+{
-+      if (jumbo_skb->skb0) {
-+//            printk("%s. jumbo skb %x, len %d\n",
-+//                    __func__, jumbo_skb->skb0->data, jumbo_skb->skb0->len);
-+              netif_rx(jumbo_skb->skb0);
-+      }
-+      jumbo_skb->skb0 = 0;
-+      jumbo_skb->tail = 0;
-+      jumbo_skb->iphdr0 = 0;
-+      jumbo_skb->tcphdr0 = 0;
-+}
-+
-+/* ---------------------------------------------------------------------
-+ * Append skb to skb0. skb0 is the jumbo frame that will be passed to
-+ * kernel tcp.
-+ * --------------------------------------------------------------------*/
-+void rx_append_skb(struct jumbo_frame *jumbo_skb, struct sk_buff* skb, int payload_len)
-+{
-+      struct iphdr* iphdr0 = (struct iphdr*)&(skb->data[0]);
-+      int ip_hdrlen = iphdr0->ihl << 2;
-+      struct tcphdr* tcphdr0 = (struct tcphdr*)&(skb->data[ip_hdrlen]);
-+
-+      if (!jumbo_skb->skb0) {
-+              // head of the jumbo frame.
-+              jumbo_skb->skb0 = skb;
-+              jumbo_skb->tail = 0;
-+              jumbo_skb->iphdr0 = iphdr0;
-+              jumbo_skb->tcphdr0 = tcphdr0;
-+      } else {
-+              if (!jumbo_skb->tail)
-+                      skb_shinfo(jumbo_skb->skb0)->frag_list = skb;
-+              else
-+                      (jumbo_skb->tail)->next = skb;
-+              jumbo_skb->tail = skb;
-+
-+              // do we need to change truesize as well?
-+              jumbo_skb->skb0->len += payload_len;
-+              jumbo_skb->skb0->data_len += payload_len;
-+
-+              jumbo_skb->iphdr0->tot_len = htons(ntohs(jumbo_skb->iphdr0->tot_len)+payload_len);
-+              jumbo_skb->tcphdr0->ack_seq = tcphdr0->ack_seq;
-+              jumbo_skb->tcphdr0->window = tcphdr0->window;
-+
-+              skb->len += payload_len;
-+              skb->data_len = 0;
-+              skb->data += ntohs(iphdr0->tot_len) - payload_len;
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* toe_gmac_handle_toeq
-+* (1) read interrupt Queue to get TOE Q.
-+* (2) get packet fro TOE Q and send to upper layer handler.
-+* (3) allocate new buffers and put to TOE Q. Intr Q buffer is recycled.
-+*----------------------------------------------------------------------*/
-+void toe_gmac_handle_toeq(struct net_device *dev, GMAC_INFO_T* tp, __u32 status)
-+{
-+      //volatile INTRQ_INFO_T *intrq_info;
-+      //TOEQ_INFO_T           *toeq_info;
-+      volatile NONTOE_QHDR_T  *intr_qhdr;
-+      volatile TOE_QHDR_T             *toe_qhdr;
-+      volatile INTR_QHDR_T    *intr_curr_desc;
-+      TOE_INFO_T      *toe = &toe_private_data;
-+
-+      volatile GMAC_RXDESC_T  *toe_curr_desc; // , *fq_desc;// *tmp_desc;
-+      volatile DMA_RWPTR_T    intr_rwptr, toeq_rwptr;  // fq_rwptr;
-+
-+      unsigned int    pkt_size, desc_count, tcp_qid;
-+      volatile unsigned int   toeq_wptr;
-+      struct toe_conn*                connection;
-+      int             i, frag_id = 0;
-+      // unsigned long        toeq_flags;
-+      struct jumbo_frame      jumbo_skb;
-+      struct sk_buff  *skb;
-+      __u32   interrupt_status;
-+
-+      in_toe_isr++;
-+
-+      interrupt_status = status >> 24;
-+      // get interrupt queue header
-+      intr_qhdr = (volatile NONTOE_QHDR_T*)TOE_INTR_Q_HDR_BASE;
-+      memset(&jumbo_skb, 0, sizeof(struct jumbo_frame));
-+
-+      for (i=0; i<TOE_INTR_QUEUE_NUM; i++, intr_qhdr++) {
-+              if (!(interrupt_status & 0x0001)) {
-+                      // no interrupt of this IntQ
-+                      interrupt_status = interrupt_status >> 1;
-+                      continue;
-+              }
-+              interrupt_status = interrupt_status >> 1;
-+              intr_rwptr.bits32 = readl(&intr_qhdr->word1);
-+
-+              while ( intr_rwptr.bits.rptr != intr_rwptr.bits.wptr) {
-+                      int max_pktsize = 1;
-+                      // get interrupt queue descriptor.
-+                      intr_curr_desc = (INTR_QHDR_T*)toe->intr_desc_base +
-+                              i* TOE_INTR_DESC_NUM + intr_rwptr.bits.rptr;
-+//                    printk("%s::int %x\n", __func__, intr_curr_desc->word1.bits32);
-+                      // get toeq id
-+                      tcp_qid = (u8)intr_curr_desc->word1.bits.tcp_qid - (u8)TOE_TOE_QID(0);
-+                      // get toeq queue header
-+                      toe_qhdr = (volatile TOE_QHDR_T*) TOE_TOE_QUE_HDR_BASE;
-+                      toe_qhdr += tcp_qid;
-+                      connection = &toe_connections[tcp_qid];
-+                      del_timer(&connection->rx_timer);
-+                      // Gary Chen spin_lock_irqsave(&connection->conn_lock, toeq_flags);
-+                      // handling interrupts of this TOE Q.
-+                      if (intr_curr_desc->word1.bits.ctl || intr_curr_desc->word1.bits.osq ||
-+                              intr_curr_desc->word1.bits.abn)
-+                              max_pktsize = 0;
-+                      if (!max_pktsize || intr_curr_desc->word1.bits.TotalPktSize) {
-+                              desc_count=0;
-+                              // wptr in intl queue is where this TOE interrupt should stop.
-+                              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
-+                              toeq_wptr = intr_curr_desc->word0.bits.wptr;
-+                              if (connection->toeq_rwptr.bits.rptr != toeq_rwptr.bits.rptr)
-+                                      printk("conn rptr %d, hw rptr %d\n",
-+                                              connection->toeq_rwptr.bits.rptr, toeq_rwptr.bits.rptr);
-+
-+                              if (intr_curr_desc->word1.bits.ctl &&
-+                                      (toeq_rwptr.bits.rptr == toeq_wptr)) {
-+                                      printk("\nctrl frame, but not in TOE queue! conn rptr %d, hw wptr %d\n",
-+                                              connection->toeq_rwptr.bits.rptr, toeq_wptr);
-+//                                    dump_toe_qhdr(toe_qhdr);
-+//                                    dump_intrq_desc(intr_curr_desc);
-+                              }
-+                              // while (toeq_rwptr.bits.rptr != intr_curr_desc->word0.bits.wptr) {
-+                              while (toe_qhdr->word1.bits.rptr != intr_curr_desc->word0.bits.wptr) {
-+                                      frag_id++;
-+                                      toe_curr_desc = (volatile GMAC_RXDESC_T *)(toe->toe_desc_base[tcp_qid]
-+                                              + toe_qhdr->word1.bits.rptr *sizeof(GMAC_RXDESC_T));
-+                                      connection->curr_desc = (GMAC_RXDESC_T *)toe_curr_desc;
-+                                      desc_count = toe_curr_desc->word0.bits.desc_count;
-+                                      pkt_size = toe_curr_desc->word1.bits.byte_count;
-+                                      consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
-+                                              PCI_DMA_FROMDEVICE);
-+                                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr)-
-+                                              SKB_RESERVE_BYTES));
-+                                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x01);
-+                                      connection->curr_rx_skb = skb;
-+                                      skb_reserve(skb, RX_INSERT_BYTES);
-+                                      if ((skb->len + pkt_size) > (1514+16))
-+                                      {
-+                                              printk("skb->len=%d, pkt_size=%d\n",skb->len, pkt_size);
-+                                              while(1);
-+                                      }
-+
-+                                      skb_put(skb, pkt_size);
-+                                      skb->dev = dev;
-+                                      skb->protocol = eth_type_trans(skb, dev);
-+                                      skb->ip_summed = CHECKSUM_UNNECESSARY;
-+
-+                                      if (toe_curr_desc->word3.bits32 & 0x1b000000)
-+                                              dump_jumbo_skb(&jumbo_skb);
-+
-+                                      rx_append_skb(&jumbo_skb, skb, pkt_size-toe_curr_desc->word3.bits.l7_offset);
-+//                                    spin_lock_irqsave(&gmac_fq_lock, flags);
-+                                      toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
-+                                      SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
-+//                                    spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+                                      if (storlink_ctl.fqint_threshold)
-+                                              continue;
-+#if 0
-+//#if (HANDLE_FREEQ_METHOD == HANDLE_FREEQ_INDIVIDUAL)
-+                                      if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
-+                                              printk("%s::toe queue alloc buffer ", __func__);
-+                                      }
-+                                      *(unsigned int*)(skb->data) = (unsigned int)skb;
-+                                      connection->curr_rx_skb = skb;
-+                                      skb_reserve(skb, SKB_RESERVE_BYTES);
-+
-+                                      spin_lock_irqsave(&gmac_fq_lock, flags);
-+                                      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                                      if (toe->fq_rx_rwptr.bits.wptr != fq_rwptr.bits.wptr) {
-+                                              printk("%s::fq_rx_rwptr %x\n", __func__, toe->fq_rx_rwptr.bits32);
-+                                              mac_stop_txdma((struct net_device*) tp->dev);
-+                                              spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+                                              while(1);
-+                                      }
-+                                      fq_desc = (GMAC_RXDESC_T*)toe->swfq_desc_base + fq_rwptr.bits.wptr;
-+                                      fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
-+
-+                                      fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
-+                                      SET_WPTR(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
-+                                      toe->fq_rx_rwptr.bits32 = fq_rwptr.bits32;
-+                                      spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+#endif
-+                              } // end of this multi-desc.
-+                              dump_jumbo_skb(&jumbo_skb);
-+                              dev->last_rx = jiffies;
-+                              connection->toeq_rwptr.bits32 = toeq_rwptr.bits32;
-+                      } else if (intr_curr_desc->word1.bits.sat) {
-+                              toeq_rwptr.bits32 = readl(&toe_qhdr->word1);
-+                              toeq_wptr = intr_curr_desc->word0.bits.wptr;
-+                              if (connection->toeq_rwptr.bits.rptr != toeq_rwptr.bits.rptr)
-+                                      printk("SAT. conn rptr %d, hw rptr %d\n",
-+                                              connection->toeq_rwptr.bits.rptr, toeq_rwptr.bits.rptr);
-+/*
-+                                      printk("%s::SAT int!, ackcnt %x, seqcnt %x, rptr %d, wptr %d, ack %x, qhack %x\n",
-+                                              __func__, intr_curr_desc->word4.bits.AckCnt, intr_curr_desc->word4.bits.SeqCnt,
-+                                              toeq_rptr, toeq_wptr, intr_curr_desc->word3.ack_num, toe_qhdr->word4.ack_num);*/
-+                              /* pure ack */
-+                              if (toeq_rwptr.bits.rptr == toeq_wptr) {
-+                                      if (intr_curr_desc->word4.bits32) {
-+                                              skb = gen_pure_ack(connection, (TOE_QHDR_T *)toe_qhdr, (INTR_QHDR_T *)intr_curr_desc);
-+                                              skb_put(skb, 60);
-+                                              skb->dev = connection->dev;
-+                                              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+                                              skb->protocol = eth_type_trans(skb, connection->dev);
-+                                              netif_rx(skb);
-+                                      } else
-+                                              printk("%s::SAT Interrupt!. But cnt is 0!\n", __func__);
-+                              } else {
-+                                      // while (toeq_rwptr.bits.rptr != toeq_wptr) {
-+                                      while (toe_qhdr->word1.bits.rptr != intr_curr_desc->word0.bits.wptr) {
-+                                              toe_curr_desc = (volatile GMAC_RXDESC_T*)(toe->toe_desc_base[tcp_qid]
-+                                                      + toe_qhdr->word1.bits.rptr * sizeof(GMAC_RXDESC_T));
-+                                              connection->curr_desc = (GMAC_RXDESC_T *)toe_curr_desc;
-+                                              desc_count = toe_curr_desc->word0.bits.desc_count;
-+                                              pkt_size = toe_curr_desc->word1.bits.byte_count;
-+                                              consistent_sync((void*)__va(toe_curr_desc->word2.buf_adr), pkt_size,
-+                                                      PCI_DMA_FROMDEVICE);
-+                                              // if ( ((toeq_rwptr.bits.rptr +1)&(TOE_TOE_DESC_NUM-1)) == toeq_wptr) {
-+                                              if ( RWPTR_ADVANCE_ONE(toe_qhdr->word1.bits.rptr, TOE_TOE_DESC_NUM) == toeq_wptr) {
-+                                                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr) -
-+                                                              SKB_RESERVE_BYTES));
-+                                                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x04);
-+                                                      connection->curr_rx_skb = skb;
-+                                                      skb_reserve(skb, RX_INSERT_BYTES);
-+                                                      skb_put(skb, pkt_size);
-+                                                      skb->dev = dev;
-+                                                      skb->protocol = eth_type_trans(skb, dev);
-+                                                      skb->ip_summed = CHECKSUM_UNNECESSARY;
-+                                                      // printk("toeq_rptr %d, wptr %d\n", toeq_rptr, toeq_wptr);
-+                                                      netif_rx(skb);
-+                                                      dev->last_rx = jiffies;
-+/*
-+                                                      if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
-+
-+                                                      }
-+                                                      *(unsigned int*)(skb->data) = (unsigned int) skb;
-+                                                      skb_reserve(skb, SKB_RESERVE_BYTES); */
-+                                              } else {
-+                                                      // reuse this skb, append to free queue..
-+                                                      skb = (struct sk_buff*)(REG32(__va(toe_curr_desc->word2.buf_adr)-
-+                                                              SKB_RESERVE_BYTES));
-+                                                      _debug_skb(skb, (GMAC_RXDESC_T *)toe_curr_desc, 0x05);
-+                                                      connection->curr_rx_skb = skb;
-+                                                      dev_kfree_skb_irq(skb);
-+                                              }
-+#if 0
-+                                              spin_lock_irqsave(&gmac_fq_lock, flags);
-+                                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+/*                                            if (toe->fq_rx_rwptr.bits.wptr != fq_rwptr.bits.wptr) {
-+                                                      printk("%s::fq_rx_rwptr %x\n", __func__, toe->fq_rx_rwptr.bits32);
-+                                                      mac_stop_txdma((struct net_device*) tp->dev);
-+                                                      spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+                                                      while(1);
-+                                              } */
-+                                              fq_desc = (GMAC_RXDESC_T*)toe->swfq_desc_base + fq_rwptr.bits.wptr;
-+                                              fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
-+
-+                                              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM);
-+                                              SET_WPTR(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
-+                                              toe->fq_rx_rwptr.bits32 = fq_rwptr.bits32;
-+      //                                      spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+#endif
-+//                                            spin_lock_irqsave(&gmac_fq_lock, flags);
-+                                              toeq_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(toeq_rwptr.bits.rptr, TOE_TOE_DESC_NUM);
-+                                              SET_RPTR(&toe_qhdr->word1, toeq_rwptr.bits.rptr);
-+//                                            spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+                                      }
-+                              } // end of ACK with options.
-+                              connection->toeq_rwptr.bits32 = toeq_rwptr.bits32;
-+                              // Gary Chen spin_unlock_irqrestore(&connection->conn_lock, toeq_flags);
-+//                            }
-+                      };
-+                      update_timer(connection);
-+                      // any protection against interrupt queue header?
-+                      intr_rwptr.bits.rptr = RWPTR_ADVANCE_ONE(intr_rwptr.bits.rptr, TOE_INTR_DESC_NUM);
-+                      SET_RPTR(&intr_qhdr->word1, intr_rwptr.bits.rptr);
-+                      intr_rwptr.bits32 = readl(&intr_qhdr->word1);
-+                      toe_gmac_fill_free_q();
-+              } // end of this interrupt Queue processing.
-+      } // end of all interrupt Queues.
-+
-+      in_toe_isr = 0;
-+}
-+
-+
---- /dev/null
-+++ b/drivers/net/sl_lepus_hash.c
-@@ -0,0 +1,553 @@
-+/**************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
-+*--------------------------------------------------------------------------
-+* Name                        : sl_lepus_hash.c
-+* Description :
-+*             Handle Storlink Lepus Hash Functions
-+*
-+* History
-+*
-+*     Date            Writer          Description
-+*----------------------------------------------------------------------------
-+*     03/13/2006      Gary Chen       Create and implement
-+*
-+****************************************************************************/
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/compiler.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/delay.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/completion.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/semaphore.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/arch/it8712.h>
-+#include <linux/mtd/kvctl.h>
-+#include <linux/skbuff.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <linux/list.h>
-+#define        MIDWAY
-+#define        SL_LEPUS
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/sl_lepus_gmac.h>
-+#include <asm/arch/sl_hash_cfg.h>
-+
-+#ifndef RXTOE_DEBUG
-+#define RXTOE_DEBUG
-+#endif
-+#undef RXTOE_DEBUG
-+
-+/*----------------------------------------------------------------------
-+* Definition
-+*----------------------------------------------------------------------*/
-+#define       hash_printf                             printk
-+
-+#define HASH_TIMER_PERIOD             (60*HZ) // seconds
-+#define HASH_ILLEGAL_INDEX            0xffff
-+
-+/*----------------------------------------------------------------------
-+* Variables
-+*----------------------------------------------------------------------*/
-+u32                                   hash_activate_bits[HASH_TOTAL_ENTRIES/32];
-+u32                                   hash_nat_owner_bits[HASH_TOTAL_ENTRIES/32];
-+char                          hash_tables[HASH_TOTAL_ENTRIES][HASH_MAX_BYTES] __attribute__ ((aligned(16)));
-+static struct timer_list hash_timer_obj;
-+LIST_HEAD(hash_timeout_list);
-+
-+/*----------------------------------------------------------------------
-+* Functions
-+*----------------------------------------------------------------------*/
-+void dm_long(u32 location, int length);
-+static void hash_timer_func(u32 data);
-+
-+/*----------------------------------------------------------------------
-+* hash_init
-+*----------------------------------------------------------------------*/
-+void hash_init(void)
-+{
-+      int i;
-+      volatile u32 *dp1, *dp2, dword;
-+
-+      dp1 = (volatile u32 *) TOE_V_BIT_BASE;
-+      dp2 = (volatile u32 *) TOE_A_BIT_BASE;
-+
-+      for (i=0; i<HASH_TOTAL_ENTRIES/32; i++)
-+      {
-+              *dp1++ = 0;
-+              dword = *dp2++; // read-clear
-+      }
-+      memset((void *)&hash_nat_owner_bits, 0, sizeof(hash_nat_owner_bits));
-+      memset((void *)&hash_tables, 0, sizeof(hash_tables));
-+
-+      init_timer(&hash_timer_obj);
-+      hash_timer_obj.expires = jiffies + HASH_TIMER_PERIOD;
-+      hash_timer_obj.data = (unsigned long)&hash_timer_obj;
-+      hash_timer_obj.function = (void *)&hash_timer_func;
-+      add_timer(&hash_timer_obj);
-+
-+#if (HASH_MAX_BYTES == 128)
-+      writel((unsigned long)__pa(&hash_tables) | 3,   // 32 words
-+                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
-+#elif (HASH_MAX_BYTES == 64)
-+      writel((unsigned long)__pa(&hash_tables) | 2,   // 16 words
-+                      TOE_GLOBAL_BASE + GLOBAL_HASH_TABLE_BASE_REG);
-+#else
-+      #error Incorrect setting for HASH_MAX_BYTES
-+#endif
-+
-+}
-+/*----------------------------------------------------------------------
-+* hash_add_entry
-+*----------------------------------------------------------------------*/
-+int hash_add_entry(HASH_ENTRY_T *entry)
-+{
-+      int     rc;
-+      u32     key[HASH_MAX_DWORDS];
-+      rc = hash_build_keys((u32 *)&key, entry);
-+      if (rc < 0)
-+              return -1;
-+      hash_write_entry(entry, (unsigned char*) &key[0]);
-+//    hash_set_valid_flag(entry->index, 1);
-+//    printk("Dump hash key!\n");
-+//    dump_hash_key(entry);
-+      return entry->index;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_set_valid_flag
-+*----------------------------------------------------------------------*/
-+void hash_set_valid_flag(int index, int valid)
-+{
-+      register u32 reg32;
-+
-+      reg32 = TOE_V_BIT_BASE + (index/32) * 4;
-+
-+      if (valid)
-+      {
-+              writel(readl(reg32) | (1 << (index%32)), reg32);
-+      }
-+      else
-+      {
-+              writel(readl(reg32) & ~(1 << (index%32)), reg32);
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_set_nat_owner_flag
-+*----------------------------------------------------------------------*/
-+void hash_set_nat_owner_flag(int index, int valid)
-+{
-+      if (valid)
-+      {
-+              hash_nat_owner_bits[index/32] |= (1 << (index % 32));
-+      }
-+      else
-+      {
-+              hash_nat_owner_bits[index/32] &= ~(1 << (index % 32));
-+      }
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* hash_build_keys
-+*----------------------------------------------------------------------*/
-+int hash_build_keys(u32 *destp, HASH_ENTRY_T *entry)
-+{
-+      u32     data;
-+      unsigned char   *cp;
-+      int                             i, j;
-+      unsigned short  index;
-+      int                     total;
-+
-+      memset((void *)destp, 0, HASH_MAX_BYTES);
-+      cp = (unsigned char *)destp;
-+
-+      if (entry->key_present.port || entry->key_present.Ethertype)
-+      {
-+              HASH_PUSH_WORD(cp, entry->key.Ethertype);               // word 0
-+              HASH_PUSH_BYTE(cp, entry->key.port);                    // Byte 2
-+              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
-+      }
-+      else
-+      {
-+              HASH_PUSH_DWORD(cp, 0);
-+      }
-+
-+      if (entry->key_present.da || entry->key_present.sa)
-+      {
-+              unsigned char mac[4];
-+              if (entry->key_present.da)
-+              {
-+                      for (i=0; i<4; i++)
-+                              HASH_PUSH_BYTE(cp, entry->key.da[i]);
-+              }
-+              mac[0] = (entry->key_present.da) ? entry->key.da[4] : 0;
-+              mac[1] = (entry->key_present.da) ? entry->key.da[5] : 0;
-+              mac[2] = (entry->key_present.sa) ? entry->key.sa[0] : 0;
-+              mac[3] = (entry->key_present.sa) ? entry->key.sa[1] : 0;
-+              data = mac[0] + (mac[1]<<8) + (mac[2]<<16) + (mac[3]<<24);
-+              HASH_PUSH_DWORD(cp, data);
-+              if (entry->key_present.sa)
-+              {
-+                      for (i=2; i<6; i++)
-+                              HASH_PUSH_BYTE(cp, entry->key.sa[i]);
-+              }
-+      }
-+
-+      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
-+      {
-+              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
-+              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
-+      }
-+      if (entry->key_present.ipv4_hdrlen || entry->key_present.ip_tos || entry->key_present.ip_protocol)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.ip_protocol);             // Byte 0
-+              HASH_PUSH_BYTE(cp, entry->key.ip_tos);                  // Byte 1
-+              HASH_PUSH_BYTE(cp, entry->key.ipv4_hdrlen);             // Byte 2
-+              HASH_PUSH_BYTE(cp, 0);                                                  // Byte 3
-+      }
-+
-+      if (entry->key_present.ipv6_flow_label)
-+      {
-+              HASH_PUSH_DWORD(cp, entry->key.ipv6_flow_label);        // low word
-+      }
-+      if (entry->key_present.sip)
-+      {
-+              // input (entry->key.sip[i]) is network-oriented
-+              // output (hash key) is host-oriented
-+              for (i=3; i>=0; i--)
-+                      HASH_PUSH_BYTE(cp, entry->key.sip[i]);
-+              if (entry->key.ipv6)
-+              {
-+                      for (i=4; i<16; i+=4)
-+                      {
-+                              for (j=i+3; j>=i; j--)
-+                                      HASH_PUSH_BYTE(cp, entry->key.sip[j]);
-+                      }
-+              }
-+      }
-+      if (entry->key_present.dip)
-+      {
-+              // input (entry->key.sip[i]) is network-oriented
-+              // output (hash key) is host-oriented
-+              for (i=3; i>=0; i--)
-+                      HASH_PUSH_BYTE(cp, entry->key.dip[i]);
-+              if (entry->key.ipv6)
-+              {
-+                      for (i=4; i<16; i+=4)
-+                      {
-+                              for (j=i+3; j>=i; j--)
-+                                      HASH_PUSH_BYTE(cp, entry->key.dip[j]);
-+                      }
-+              }
-+      }
-+
-+      if (entry->key_present.l4_bytes_0_3)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
-+      }
-+      if (entry->key_present.l4_bytes_4_7)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[4]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[5]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[6]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[7]);
-+      }
-+      if (entry->key_present.l4_bytes_8_11)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[8]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[9]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[10]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[11]);
-+      }
-+      if (entry->key_present.l4_bytes_12_15)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[12]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[13]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[14]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[15]);
-+      }
-+      if (entry->key_present.l4_bytes_16_19)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[16]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[17]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[18]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[19]);
-+      }
-+      if (entry->key_present.l4_bytes_20_23)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[20]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[21]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[22]);
-+              HASH_PUSH_BYTE(cp, entry->key.l4_bytes[23]);
-+      }
-+      if (entry->key_present.l7_bytes_0_3)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[0]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[1]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[2]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[3]);
-+      }
-+      if (entry->key_present.l7_bytes_4_7)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[4]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[5]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[6]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[7]);
-+      }
-+      if (entry->key_present.l7_bytes_8_11)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[8]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[9]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[10]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[11]);
-+      }
-+      if (entry->key_present.l7_bytes_12_15)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[12]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[13]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[14]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[15]);
-+      }
-+      if (entry->key_present.l7_bytes_16_19)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[16]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[17]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[18]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[19]);
-+      }
-+      if (entry->key_present.l7_bytes_20_23)
-+      {
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[20]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[21]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[22]);
-+              HASH_PUSH_BYTE(cp, entry->key.l7_bytes[23]);
-+      }
-+
-+      // get hash index
-+      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
-+
-+      if (total > HASH_MAX_KEY_DWORD)
-+      {
-+              //hash_printf("Total key words (%d) is too large (> %d)!\n",
-+              //                              total, HASH_MAX_KEY_DWORD);
-+              return -1;
-+      }
-+
-+      if (entry->key_present.port || entry->key_present.Ethertype)
-+              index = hash_gen_crc16((unsigned char *)destp, total * 4);
-+      else
-+      {
-+              if (total == 1)
-+              {
-+                      hash_printf("No key is assigned!\n");
-+                      return -1;
-+              }
-+
-+              index = hash_gen_crc16((unsigned char *)(destp+1), (total-1) * 4);
-+      }
-+
-+      entry->index = index & HASH_BITS_MASK;
-+
-+      //hash_printf("Total key words = %d, Hash Index= %d\n",
-+      //                              total, entry->index);
-+
-+      cp = (unsigned char *)destp;
-+      cp+=3;
-+      HASH_PUSH_BYTE(cp, entry->rule);        // rule
-+
-+      entry->total_dwords = total;
-+
-+      return total;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_build_nat_keys
-+*----------------------------------------------------------------------*/
-+void hash_build_nat_keys(u32 *destp, HASH_ENTRY_T *entry)
-+{
-+      unsigned char   *cp;
-+      int                             i;
-+      unsigned short  index;
-+      int                     total;
-+
-+      memset((void *)destp, 0, HASH_MAX_BYTES);
-+
-+      cp = (unsigned char *)destp + 2;
-+      HASH_PUSH_BYTE(cp, entry->key.port);
-+      cp++;
-+
-+      if (entry->key_present.pppoe_sid || entry->key_present.vlan_id)
-+      {
-+              HASH_PUSH_WORD(cp, entry->key.vlan_id);         // low word
-+              HASH_PUSH_WORD(cp, entry->key.pppoe_sid);       // high word
-+      }
-+
-+      HASH_PUSH_BYTE(cp, entry->key.ip_protocol);
-+      cp+=3;
-+
-+      // input (entry->key.sip[i]) is network-oriented
-+      // output (hash key) is host-oriented
-+      for (i=3; i>=0; i--)
-+              HASH_PUSH_BYTE(cp, entry->key.sip[i]);
-+
-+      // input (entry->key.sip[i]) is network-oriented
-+      // output (hash key) is host-oriented
-+      for (i=3; i>=0; i--)
-+              HASH_PUSH_BYTE(cp, entry->key.dip[i]);
-+
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[0]);
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[1]);
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[2]);
-+      HASH_PUSH_BYTE(cp, entry->key.l4_bytes[3]);
-+
-+      // get hash index
-+      total = (u32)((u32)cp - (u32)destp) / (sizeof(u32));
-+
-+      index = hash_gen_crc16((unsigned char *)destp, total * 4);
-+      entry->index = index & ((1 << HASH_BITS) - 1);
-+
-+      cp = (unsigned char *)destp;
-+      cp+=3;
-+      HASH_PUSH_BYTE(cp, entry->rule);        // rule
-+
-+      entry->total_dwords = total;
-+}
-+
-+
-+/*----------------------------------------------------------------------
-+* hash_write_entry
-+*----------------------------------------------------------------------*/
-+int hash_write_entry(HASH_ENTRY_T *entry, unsigned char *key)
-+{
-+      int             i;
-+      u32             *srcep, *destp, *destp2;
-+
-+      srcep = (u32 *)key;
-+      destp2 = destp = (u32 *)&hash_tables[entry->index][0];
-+
-+      for (i=0; i<(entry->total_dwords); i++, srcep++, destp++)
-+              *destp = *srcep;
-+
-+      srcep = (u32 *)&entry->action;
-+      *destp++ = *srcep;
-+
-+      srcep = (u32 *)&entry->param;
-+      for (i=0; i<(sizeof(ENTRY_PARAM_T)/sizeof(*destp)); i++, srcep++, destp++)
-+              *destp = *srcep;
-+
-+      memset(destp, 0, (HASH_MAX_DWORDS-entry->total_dwords-HASH_ACTION_DWORDS) * sizeof(u32));
-+
-+      consistent_sync(destp2, (entry->total_dwords+HASH_ACTION_DWORDS) * 4, PCI_DMA_TODEVICE);
-+      return 0;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_timer_func
-+*----------------------------------------------------------------------*/
-+static void hash_timer_func(u32 data)
-+{
-+      int                             i, j;
-+      volatile u32    *active_p, *own_p, *valid_p;
-+      u32                             a_bits, own_bits;
-+
-+      valid_p = (volatile u32 *)TOE_V_BIT_BASE;
-+      active_p = (volatile u32 *)hash_activate_bits;
-+      own_p = (volatile u32 *)hash_nat_owner_bits;
-+      for (i=0; i<(HASH_TOTAL_ENTRIES/32); i++, own_p++, active_p++, valid_p++)
-+      {
-+              *active_p |= readl(TOE_A_BIT_BASE + (i*4));
-+              a_bits = *active_p;
-+              own_bits = *own_p;
-+              if (own_bits)
-+              {
-+#ifndef DEBUG_NAT_MIXED_HW_SW_TX
-+                      a_bits = own_bits & ~a_bits;
-+#else
-+                      a_bits = own_bits & a_bits;
-+#endif
-+                      for (j=0; a_bits && j<32; j++)
-+                      {
-+                              if (a_bits & 1)
-+                              {
-+                                      *valid_p &= ~(1 << j);          // invalidate it
-+#if !(defined(NAT_DEBUG_LAN_HASH_TIMEOUT) || defined(NAT_DEBUG_WAN_HASH_TIMEOUT))
-+                                      *own_p &= ~(1 << j);            // release ownership for NAT
-+#endif
-+// #ifdef DEBUG_NAT_MIXED_HW_SW_TX
-+#if 0
-+                                      hash_printf("%lu %s: Clear hash index: %d\n", jiffies/HZ, __func__, i*32+j);
-+#endif
-+                              }
-+                              a_bits >>= 1;
-+                      }
-+                      *active_p &= ~own_bits;         // deactivate it for next polling
-+              }
-+      }
-+
-+      hash_timer_obj.expires = jiffies + HASH_TIMER_PERIOD;
-+      add_timer((struct timer_list *)data);
-+}
-+
-+/*----------------------------------------------------------------------
-+* dm_long
-+*----------------------------------------------------------------------*/
-+void dm_long(u32 location, int length)
-+{
-+      u32             *start_p, *curr_p, *end_p;
-+      u32             *datap, data;
-+      int             i;
-+
-+      //if (length > 1024)
-+      //      length = 1024;
-+
-+      start_p = (u32 *)location;
-+      end_p = (u32 *)location + length;
-+      curr_p = (u32 *)((u32)location & 0xfffffff0);
-+      datap = (u32 *)location;
-+      while (curr_p < end_p)
-+      {
-+              hash_printf("0x%08x: ",(u32)curr_p & 0xfffffff0);
-+              for (i=0; i<4; i++)
-+              {
-+                      if (curr_p < start_p || curr_p >= end_p)
-+               hash_printf("         ");
-+                      else
-+                      {
-+                              data = *datap;
-+                              hash_printf("%08X ", data);
-+                      }
-+                      if (i==1)
-+              hash_printf("- ");
-+
-+                      curr_p++;
-+                      datap++;
-+              }
-+        hash_printf("\n");
-+      }
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_dump_entry
-+*----------------------------------------------------------------------*/
-+void hash_dump_entry(int index)
-+{
-+      hash_printf("Hash Index %d:\n", index);
-+      dm_long((u32)&hash_tables[index][0], HASH_MAX_DWORDS);
-+}
-+
-+
---- /dev/null
-+++ b/drivers/net/sl_switch.c
-@@ -0,0 +1,650 @@
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+#include <linux/delay.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+
-+#define GMAC_GLOBAL_BASE_ADDR       (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+#define GPIO_BASE_ADDR1  (IO_ADDRESS(SL2312_GPIO_BASE1))
-+enum GPIO_REG
-+{
-+    GPIO_DATA_OUT   = 0x00,
-+    GPIO_DATA_IN    = 0x04,
-+    GPIO_PIN_DIR    = 0x08,
-+    GPIO_BY_PASS    = 0x0c,
-+    GPIO_DATA_SET   = 0x10,
-+    GPIO_DATA_CLEAR = 0x14,
-+};
-+
-+#define GMAC_SPEED_10                 0
-+#define GMAC_SPEED_100                        1
-+#define GMAC_SPEED_1000                       2
-+
-+enum phy_state
-+{
-+    LINK_DOWN   = 0,
-+    LINK_UP     = 1
-+};
-+
-+#ifndef BIT
-+#define BIT(x)                                                (1 << (x))
-+#endif
-+
-+//int Get_Set_port_status();
-+unsigned int SPI_read_bit(void);
-+void SPI_write_bit(char bit_EEDO);
-+void SPI_write(unsigned char block,unsigned char subblock,unsigned char addr,unsigned int value);
-+unsigned int SPI_read(unsigned char block,unsigned char subblock,unsigned char addr);
-+int SPI_default(void);
-+void SPI_CS_enable(unsigned char enable);
-+unsigned int SPI_get_identifier(void);
-+void phy_write(unsigned char port_no,unsigned char reg,unsigned int val);
-+unsigned int phy_read(unsigned char port_no,unsigned char reg);
-+void phy_write_masked(unsigned char port_no,unsigned char reg,unsigned int val,unsigned int mask);
-+void init_seq_7385(unsigned char port_no) ;
-+void phy_receiver_init (unsigned char port_no);
-+
-+#define PORT_NO               4
-+int switch_pre_speed[PORT_NO]={0,0,0,0};
-+int switch_pre_link[PORT_NO]={0,0,0,0};
-+
-+
-+
-+
-+
-+/*                            NOTES
-+ *   The Protocol of the SPI are as follows:
-+ *
-+ *                       Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
-+ *    byte0     |   Block id  | r/w | sub-block        |
-+ *    byte1     |             Address                  |
-+ *    byte2     |             Data                     |
-+ *    byte3     |             Data                     |
-+ *    byte4     |             Data                     |
-+ *    byte5     |             Data                     |
-+ */
-+
-+
-+
-+
-+/***************************************/
-+/* define GPIO module base address     */
-+/***************************************/
-+#define GPIO_EECS          0x80000000         /*   EECS: GPIO[22]   */
-+#define GPIO_MOSI          0x20000000         /*   EEDO: GPIO[29]   send to 6996*/
-+#define GPIO_MISO          0x40000000         /*   EEDI: GPIO[30]   receive from 6996*/
-+#define GPIO_EECK          0x10000000         /*   EECK: GPIO[31]   */
-+
-+/*************************************************************
-+* SPI protocol for ADM6996 control
-+**************************************************************/
-+#define SPI_OP_LEN         0x08               // the length of start bit and opcode
-+#define SPI_OPWRITE        0X05               // write
-+#define SPI_OPREAD         0X06               // read
-+#define SPI_OPERASE        0X07               // erase
-+#define SPI_OPWTEN         0X04               // write enable
-+#define SPI_OPWTDIS        0X04               // write disable
-+#define SPI_OPERSALL       0X04               // erase all
-+#define SPI_OPWTALL        0X04               // write all
-+
-+#define SPI_ADD_LEN        8                  // bits of Address
-+#define SPI_DAT_LEN        32                 // bits of Data
-+
-+
-+/****************************************/
-+/*    Function Declare                */
-+/****************************************/
-+
-+//unsigned int SPI_read_bit(void);
-+//void SPI_write_bit(char bit_EEDO);
-+//unsigned int SPI_read_bit(void);
-+/******************************************
-+* SPI_write
-+* addr -> Write Address
-+* value -> value to be write
-+***************************************** */
-+void phy_receiver_init (unsigned char port_no)
-+{
-+    phy_write(port_no,31,0x2a30);
-+    phy_write_masked(port_no, 12, 0x0200, 0x0300);
-+    phy_write(port_no,31,0);
-+}
-+
-+void phy_write(unsigned char port_no,unsigned char reg,unsigned int val)
-+{
-+      unsigned int cmd;
-+
-+      cmd = (port_no<<21)|(reg<<16)|val;
-+      SPI_write(3,0,1,cmd);
-+}
-+
-+unsigned int phy_read(unsigned char port_no,unsigned char reg)
-+{
-+      unsigned int cmd,reg_val;
-+
-+      cmd = BIT(26)|(port_no<<21)|(reg<<16);
-+      SPI_write(3,0,1,cmd);
-+      msleep(2);
-+      reg_val = SPI_read(3,0,2);
-+      return reg_val;
-+}
-+
-+void phy_write_masked(unsigned char port_no,unsigned char reg,unsigned int val,unsigned int mask)
-+{
-+      unsigned int cmd,reg_val;
-+
-+      cmd = BIT(26)|(port_no<<21)|(reg<<16);  // Read reg_val
-+      SPI_write(3,0,1,cmd);
-+      mdelay(2);
-+      reg_val = SPI_read(3,0,2);
-+      reg_val &= ~mask;                       // Clear masked bit
-+      reg_val |= (val&mask) ;                 // set masked bit ,if true
-+      cmd = (port_no<<21)|(reg<<16)|reg_val;
-+      SPI_write(3,0,1,cmd);
-+}
-+
-+void init_seq_7385(unsigned char port_no)
-+{
-+      unsigned char rev;
-+
-+      phy_write(port_no, 31, 0x2a30);
-+      phy_write_masked(port_no, 8, 0x0200, 0x0200);
-+      phy_write(port_no, 31, 0x52b5);
-+      phy_write(port_no, 16, 0xb68a);
-+      phy_write_masked(port_no, 18, 0x0003, 0xff07);
-+      phy_write_masked(port_no, 17, 0x00a2, 0x00ff);
-+      phy_write(port_no, 16, 0x968a);
-+      phy_write(port_no, 31, 0x2a30);
-+      phy_write_masked(port_no, 8, 0x0000, 0x0200);
-+      phy_write(port_no, 31, 0x0000); /* Read revision */
-+      rev = phy_read(port_no, 3) & 0x000f;
-+      if (rev == 0)
-+      {
-+              phy_write(port_no, 31, 0x2a30);
-+              phy_write_masked(port_no, 8, 0x0200, 0x0200);
-+              phy_write(port_no, 31, 0x52b5);
-+              phy_write(port_no, 18, 0x0000);
-+              phy_write(port_no, 17, 0x0689);
-+              phy_write(port_no, 16, 0x8f92);
-+              phy_write(port_no, 31, 0x52B5);
-+              phy_write(port_no, 18, 0x0000);
-+              phy_write(port_no, 17, 0x0E35);
-+              phy_write(port_no, 16, 0x9786);
-+              phy_write(port_no, 31, 0x2a30);
-+              phy_write_masked(port_no, 8, 0x0000, 0x0200);
-+              phy_write(port_no, 23, 0xFF80);
-+              phy_write(port_no, 23, 0x0000);
-+      }
-+      phy_write(port_no, 31, 0x0000);
-+      phy_write(port_no, 18, 0x0048);
-+      if (rev == 0)
-+      {
-+              phy_write(port_no, 31, 0x2a30);
-+              phy_write(port_no, 20, 0x6600);
-+              phy_write(port_no, 31, 0x0000);
-+              phy_write(port_no, 24, 0xa24e);
-+      }
-+      else
-+      {
-+              phy_write(port_no, 31, 0x2a30);
-+              phy_write_masked(port_no, 22, 0x0240, 0x0fc0);
-+              phy_write_masked(port_no, 20, 0x4000, 0x6000);
-+              phy_write(port_no, 31, 1);
-+              phy_write_masked(port_no, 20, 0x6000, 0xe000);
-+              phy_write(port_no, 31, 0x0000);
-+      }
-+}
-+
-+int Get_Set_port_status()
-+{
-+      unsigned int    reg_val,ability,rcv_mask,mac_config;
-+      int is_link=0;
-+      int i;
-+
-+      rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
-+
-+      for(i=0;i<4;i++){
-+              reg_val = phy_read(i,1);
-+              if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */
-+              {
-+                      is_link=1;
-+                      if(switch_pre_link[i]==LINK_DOWN){              // Link Down ==> Link up
-+
-+                              rcv_mask |= BIT(i);                     // Enable receive
-+
-+                              reg_val = phy_read(i,10);
-+                              if(reg_val & 0x0c00){
-+                                      printk("Port%d:Giga mode\n",i);
-+//                                    SPI_write(1,i,0x00,0x300701B1);
-+                                      mac_config = 0x00060004|(6<<6);
-+
-+                                      SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030);       // reset port
-+                                      mac_config |= (( BIT(i) << 19) | 0x08000000);
-+                                      SPI_write(1,i,0x00,mac_config);
-+                                      SPI_write(1,i,0x04,0x000300ff);         // flow control
-+
-+                                      reg_val = SPI_read(5,0,0x12);
-+                                      reg_val &= ~BIT(i);
-+                                      SPI_write(5,0,0x12,reg_val);
-+
-+                                      reg_val = SPI_read(1,i,0x00);
-+                                      reg_val |= 0x10010000;
-+                                      SPI_write(1,i,0x00,reg_val);
-+//                                    SPI_write(1,i,0x00,0x10070181);
-+                                      switch_pre_link[i]=LINK_UP;
-+                                      switch_pre_speed[i]=GMAC_SPEED_1000;
-+                              }
-+                              else{
-+                                      reg_val = phy_read(i,5);
-+                                      ability = (reg_val&0x5e0) >>5;
-+                                      if ((ability & 0x0C)) /* 100M */
-+                                      {
-+//                                            SPI_write(1,i,0x00,0x30050472);
-+                                              if((ability&0x08)==0)           // Half
-+                                                      mac_config = 0x00040004 |(17<<6);
-+                                              else                            // Full
-+                                                      mac_config = 0x00040004 |(17<<6);
-+
-+                                              SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030);       // reset port
-+                                              mac_config |= (( BIT(i) << 19) | 0x08000000);
-+                                              SPI_write(1,i,0x00,mac_config);
-+                                              SPI_write(1,i,0x04,0x000300ff);         // flow control
-+
-+                                              reg_val = SPI_read(5,0,0x12);
-+                                              reg_val &= ~BIT(i);
-+                                              SPI_write(5,0,0x12,reg_val);
-+
-+                                              reg_val = SPI_read(1,i,0x00);
-+                                              reg_val &= ~0x08000000;
-+                                              reg_val |= 0x10010000;
-+                                              SPI_write(1,i,0x00,reg_val);
-+//                                            SPI_write(1,i,0x00,0x10050442);
-+                                              printk("Port%d:100M\n",i);
-+                                              switch_pre_link[i]=LINK_UP;
-+                                              switch_pre_speed[i]=GMAC_SPEED_100;
-+                                      }
-+                                      else if((ability & 0x03)) /* 10M */
-+                                      {
-+//                                            SPI_write(1,i,0x00,0x30050473);
-+                                              if((ability&0x2)==0)            // Half
-+                                                      mac_config = 0x00040004 |(17<<6);
-+                                              else                            // Full
-+                                                      mac_config = 0x00040004 |(17<<6);
-+
-+                                              SPI_write(1,i,0x00,((mac_config & 0xfffffff8) | 1) | 0x20000030);       // reset port
-+                                              mac_config |= (( BIT(i) << 19) | 0x08000000);
-+                                              SPI_write(1,i,0x00,mac_config);
-+                                              SPI_write(1,i,0x04,0x000300ff);         // flow control
-+
-+                                              reg_val = SPI_read(5,0,0x12);
-+                                              reg_val &= ~BIT(i);
-+                                              SPI_write(5,0,0x12,reg_val);
-+
-+                                              reg_val = SPI_read(1,i,0x00);
-+                                              reg_val &= ~0x08000000;
-+                                              reg_val |= 0x10010000;
-+                                              SPI_write(1,i,0x00,reg_val);
-+//                                            SPI_write(1,i,0x00,0x10050443);
-+                                              printk("Port%d:10M\n",i);
-+                                              switch_pre_link[i]=LINK_UP;
-+                                              switch_pre_speed[i]=GMAC_SPEED_10;
-+                                      }
-+                                      else{
-+                                              SPI_write(1,i,0x00,0x20000030);
-+                                              printk("Port%d:Unknown mode\n",i);
-+                                              switch_pre_link[i]=LINK_DOWN;
-+                                              switch_pre_speed[i]=GMAC_SPEED_10;
-+                                      }
-+                              }
-+                      }
-+                      else{                                           // Link up ==> Link UP
-+
-+                      }
-+              }
-+              else{                                                   // Link Down
-+                      if(switch_pre_link[i]==LINK_UP){
-+                              printk("Port%d:Link Down\n",i);
-+                              //phy_receiver_init(i);
-+                              reg_val = SPI_read(1,i,0);
-+                              reg_val &= ~BIT(16);
-+                              SPI_write(1,i,0x00,reg_val);                    // disable RX
-+                              SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
-+                              while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
-+                                      msleep(1);
-+                              SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
-+                              SPI_write(5,0,0x0E,SPI_read(5,0,0x0E) & ~BIT(i));// accept packet
-+
-+                              reg_val = SPI_read(5,0,0x12);
-+                              reg_val |= BIT(i);
-+                              SPI_write(5,0,0x12,reg_val);
-+                      }
-+                      switch_pre_link[i]=LINK_DOWN;
-+                      rcv_mask &= ~BIT(i);                    // disable receive
-+              }
-+      }
-+
-+      SPI_write(2,0,0x10,rcv_mask);                   // Receive mask
-+      return is_link;
-+
-+}
-+EXPORT_SYMBOL(Get_Set_port_status);
-+
-+void SPI_write(unsigned char block,unsigned char subblock,unsigned char addr,unsigned int value)
-+{
-+      int     i;
-+      char    bit;
-+      unsigned int data;
-+
-+      SPI_CS_enable(1);
-+
-+      data = (block<<5) | 0x10 | subblock;
-+
-+      //send write command
-+      for(i=SPI_OP_LEN-1;i>=0;i--)
-+      {
-+              bit = (data>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+
-+      // send 8 bits address (MSB first, LSB last)
-+      for(i=SPI_ADD_LEN-1;i>=0;i--)
-+      {
-+              bit = (addr>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+      // send 32 bits data (MSB first, LSB last)
-+      for(i=SPI_DAT_LEN-1;i>=0;i--)
-+      {
-+              bit = (value>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+
-+      SPI_CS_enable(0);       // CS low
-+
-+}
-+
-+
-+/************************************
-+* SPI_write_bit
-+* bit_EEDO -> 1 or 0 to be written
-+************************************/
-+void SPI_write_bit(char bit_EEDO)
-+{
-+      unsigned int addr;
-+      unsigned int value;
-+
-+      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
-+      value = readl(addr) |GPIO_EECK |GPIO_MOSI ;   /* set EECK/MISO Pin to output */
-+      writel(value,addr);
-+      if(bit_EEDO)
-+      {
-+              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_SET);
-+              writel(GPIO_MOSI,addr); /* set MISO to 1 */
-+
-+      }
-+      else
-+      {
-+              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
-+              writel(GPIO_MOSI,addr); /* set MISO to 0 */
-+      }
-+      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_SET);
-+      writel(GPIO_EECK,addr); /* set EECK to 1 */
-+      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
-+      writel(GPIO_EECK,addr); /* set EECK to 0 */
-+
-+      //return ;
-+}
-+
-+/**********************************************************************
-+* read a bit from ADM6996 register
-+***********************************************************************/
-+unsigned int SPI_read_bit(void) // read data from
-+{
-+      unsigned int addr;
-+      unsigned int value;
-+
-+      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
-+      value = readl(addr) & (~GPIO_MISO);   // set EECK to output and MISO to input
-+      writel(value,addr);
-+
-+      addr =(GPIO_BASE_ADDR1 + GPIO_DATA_SET);
-+      writel(GPIO_EECK,addr); // set EECK to 1
-+
-+
-+      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_IN);
-+      value = readl(addr) ;
-+
-+      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
-+      writel(GPIO_EECK,addr); // set EECK to 0
-+
-+
-+      value = value >> 30;
-+      return value ;
-+}
-+
-+/******************************************
-+* SPI_default
-+* EEPROM content default value
-+*******************************************/
-+int SPI_default(void)
-+{
-+      int i;
-+      unsigned reg_val,cmd;
-+
-+#if 0
-+      SPI_write(7,0,0x1C,0x01);                               // map code space to 0
-+
-+      reg_val = SPI_read(7,0,0x10);
-+      reg_val |= 0x0146;
-+      reg_val &= ~0x0001;
-+      SPI_write(7,0,0x10,reg_val);                            // reset iCPU and enable ext_access
-+      SPI_write(7,0,0x11,0x0000);                             // start address
-+      for(i=0;i<sizeof(vts_img);i++){
-+              SPI_write(7,0,0x12,vts_img[i]);                 // fill in ROM data
-+      }
-+      reg_val |= BIT(0)|BIT(3);
-+      SPI_write(7,0,0x10,reg_val);                            // release iCPU
-+      SPI_write(7,0,0x10,SPI_read(7,0,0x10)&~BIT(7));                         // release iCPU
-+      return ;
-+#endif
-+
-+
-+      for(i=0;i<15;i++){
-+              if(i!=6 && i!=7)
-+                      SPI_write(3,2,0,0x1010400+i);           // Initial memory
-+              mdelay(1);
-+      }
-+
-+      mdelay(30);
-+
-+      SPI_write(2,0,0xB0,0x05);                       // Clear MAC table
-+      SPI_write(2,0,0xD0,0x03);                       // Clear VLAN
-+
-+      //for(i=0;i<5;i++)
-+      SPI_write(1,6,0x19,0x2C);                       // Double Data rate
-+
-+      for(i=0;i<4;i++){
-+              SPI_write(1,i,0x00,0x30050472);         // MAC configure
-+              SPI_write(1,i,0x00,0x10050442);         // MAC configure
-+              SPI_write(1,i,0x10,0x5F4);              // Max length
-+              SPI_write(1,i,0x04,0x00030000);         // Flow control
-+              SPI_write(1,i,0xDF,0x00000001);         // Flow control
-+              SPI_write(1,i,0x08,0x000050c2);         // Flow control mac high
-+              SPI_write(1,i,0x0C,0x002b00f1);         // Flow control mac low
-+              SPI_write(1,i,0x6E,BIT(3));             // forward pause frame
-+      }
-+      SPI_write(1,i,0x00,0x20000030);                 // set port 4 as reset
-+
-+      SPI_write(1,6,0x00,0x300701B1);                 // MAC configure
-+      SPI_write(1,6,0x00,0x10070181);                 // MAC configure
-+      SPI_write(1,6,0x10,0x5F4);                      // Max length
-+      SPI_write(1,6,0x04,0x00030000);         // Flow control
-+      SPI_write(1,6,0xDF,0x00000002);         // Flow control
-+      SPI_write(1,6,0x08,0x000050c2);         // Flow control mac high
-+      SPI_write(1,6,0x0C,0x002b00f1);         // Flow control mac low
-+      SPI_write(1,6,0x6E,BIT(3));             // forward pause frame
-+
-+
-+      //SPI_write(7,0,0x05,0x31);                     // MII delay for loader
-+      //SPI_write(7,0,0x05,0x01);                     // MII delay for kernel
-+      SPI_write(7,0,0x05,0x33);
-+
-+      SPI_write(2,0,0x10,0x4F);                       // Receive mask
-+
-+      mdelay(50);
-+
-+      SPI_write(7,0,0x14,0x02);                       // Release Reset
-+
-+      mdelay(3);
-+
-+      for(i=0;i<4;i++){
-+              init_seq_7385(i);
-+              phy_receiver_init(i);
-+              cmd = BIT(26)|(i<<21)|(0x1B<<16);       // Config LED
-+              SPI_write(3,0,1,cmd);
-+              mdelay(10);
-+              reg_val = SPI_read(3,0,2);
-+              reg_val &= 0xFF00;
-+              reg_val |= 0x61;
-+              cmd = (i<<21)|(0x1B<<16)|reg_val;
-+              SPI_write(3,0,1,cmd);
-+
-+              cmd = BIT(26)|(i<<21)|(0x04<<16);       // Pause enable
-+              SPI_write(3,0,1,cmd);
-+              mdelay(10);
-+              reg_val = SPI_read(3,0,2);
-+              reg_val |= BIT(10)|BIT(11);
-+              cmd = (i<<21)|(0x04<<16)|reg_val;
-+              SPI_write(3,0,1,cmd);
-+
-+              cmd = BIT(26)|(i<<21)|(0x0<<16);        // collision test and re-negotiation
-+              SPI_write(3,0,1,cmd);
-+              mdelay(10);
-+              reg_val = SPI_read(3,0,2);
-+              reg_val |= BIT(7)|BIT(8)|BIT(9);
-+              cmd = (i<<21)|(0x0<<16)|reg_val;
-+              SPI_write(3,0,1,cmd);
-+      }
-+      init_seq_7385(i);
-+      writel(0x5787a7f0,GMAC_GLOBAL_BASE_ADDR+0x1c);//For switch timing
-+      return 4;               // return port_no
-+}
-+EXPORT_SYMBOL(SPI_default);
-+
-+/***********************************************************
-+* SPI_CS_enable
-+* before access ,you have to enable Chip Select. (pull high)
-+* When fisish, you should pull low !!
-+*************************************************************/
-+void SPI_CS_enable(unsigned char enable)
-+{
-+
-+      unsigned int addr,value;
-+
-+      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
-+      value = readl(addr) |GPIO_EECS |GPIO_EECK;   /* set EECS/EECK Pin to output */
-+      writel(value,addr);
-+
-+      if(enable)
-+      {
-+              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
-+              writel(GPIO_EECK,addr); /* set EECK to 0 */     // pull low clk first
-+              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
-+              writel(GPIO_EECS,addr); /* set EECS to 0 */
-+
-+      }
-+      else
-+      {
-+              addr = (GPIO_BASE_ADDR1 + GPIO_DATA_SET);
-+              writel(GPIO_EECK,addr); /* set EECK to 1 */     // pull high clk before disable
-+              writel(GPIO_EECS,addr); /* set EECS to 1 */
-+      }
-+}
-+
-+
-+/************************************************
-+* SPI_read
-+* table -> which table to be read: 1/count  0/EEPROM
-+* addr  -> Address to be read
-+* return : Value of the register
-+*************************************************/
-+unsigned int SPI_read(unsigned char block,unsigned char subblock,unsigned char addr)
-+{
-+      int     i;
-+      char    bit;
-+      unsigned int data,value=0;
-+
-+      SPI_CS_enable(1);
-+
-+      data = (block<<5) | subblock;
-+
-+      //send write command
-+      for(i=SPI_OP_LEN-1;i>=0;i--)
-+      {
-+              bit = (data>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+
-+      // send 8 bits address (MSB first, LSB last)
-+      for(i=SPI_ADD_LEN-1;i>=0;i--)
-+      {
-+              bit = (addr>>i)& 0x01;
-+              SPI_write_bit(bit);
-+      }
-+
-+      // dummy read for chip ready
-+      for(i=0;i<8;i++)
-+              SPI_read_bit();
-+
-+
-+      // read 32 bits data (MSB first, LSB last)
-+      for(i=SPI_DAT_LEN-1;i>=0;i--)
-+      {
-+              bit = SPI_read_bit();
-+              value |= bit<<i;
-+      }
-+
-+      SPI_CS_enable(0);       // CS low
-+      return(value);
-+
-+}
-+
-+void pull_low_gpio(unsigned int val)
-+{
-+
-+      unsigned int addr,value;
-+
-+      addr = (GPIO_BASE_ADDR1 + GPIO_DATA_CLEAR);
-+      writel(val,addr); /* set pin low to save power*/
-+
-+      addr = (GPIO_BASE_ADDR1 + GPIO_PIN_DIR);
-+      value = readl(addr) & ~ val;   /* set Pin to input */
-+      writel(value,addr);
-+
-+//    value = readl(GMAC_GLOBAL_BASE_ADDR+0x0C);      // reset GPIO1 module(self clear)
-+//    value |= BIT(21);
-+//    writel(value,GMAC_GLOBAL_BASE_ADDR+0x0C);
-+}
-+
-+unsigned int SPI_get_identifier(void)
-+{
-+      unsigned int flag=0;
-+
-+      SPI_write(7,0,0x01,0x01);
-+      flag = SPI_read(7,0,0x18);  // chip id
-+      if((flag & 0x0ffff000)==0x07385000){
-+              printk("Get VSC-switch ID 0x%08x\n",flag);
-+              //Giga_switch = 1;;
-+              return 1;
-+      }
-+      else{
-+              printk("VSC-switch not found\n");
-+              //Giga_switch = 0;
-+              pull_low_gpio(GPIO_EECK|GPIO_MOSI|GPIO_MISO|GPIO_EECS); // reduce power consume
-+              return 0;
-+      }
-+}
-+EXPORT_SYMBOL(SPI_get_identifier);
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/sl351x_gmac.h
-@@ -0,0 +1,2223 @@
-+/****************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
-+*--------------------------------------------------------------------------
-+* Name                        : sl351x_gmac.h
-+* Description :
-+*             Define for device driver of Storlink SL351x network Engine
-+*
-+* Historych
-+*
-+*     Date            Writer          Description
-+*     -----------     -----------     -------------------------------------------------
-+*     08/22/2005      Gary Chen       Create and implement
-+*
-+****************************************************************************/
-+#ifndef _GMAC_SL351x_H
-+#define _GMAC_SL351x_H
-+#include <linux/skbuff.h>
-+
-+#define SL351x_GMAC_WORKAROUND                1
-+
-+#undef BIG_ENDIAN
-+#define BIG_ENDIAN                            0
-+#define GMAC_DEBUG                            1
-+#define GMAC_NUM                                      2
-+//#define     L2_jumbo_frame                          1
-+
-+#define _PACKED_                                      __attribute__ ((aligned(1), packed))
-+
-+#ifndef BIT
-+#define BIT(x)                                                (1 << (x))
-+#endif
-+
-+#define REG32(addr)                           (*(volatile unsigned long  * const)(addr))
-+
-+#define DMA_MALLOC(size,handle)               pci_alloc_consistent(NULL,size,handle)
-+#define DMA_MFREE(mem,size,handle)    pci_free_consistent(NULL,size,mem,handle)
-+
-+// Define frame size
-+#define ETHER_ADDR_LEN                                6
-+#define GMAC_MAX_ETH_FRAME_SIZE               1514
-+#define GMAC_TX_BUF_SIZE                      ((GMAC_MAX_ETH_FRAME_SIZE + 31) & (~31))
-+#define MAX_ISR_WORK                  20
-+
-+#ifdef        L2_jumbo_frame
-+#define SW_RX_BUF_SIZE                                9234    // 2048 ,9234
-+#else
-+#define SW_RX_BUF_SIZE                                1536    // 2048
-+#endif
-+
-+#define HW_RX_BUF_SIZE                                1536    // 2048
-+
-+#define GMAC_DEV_TX_TIMEOUT           (10*HZ)                 //add by CH
-+#define       SKB_RESERVE_BYTES                       16
-+
-+/**********************************************************************
-+ * Base Register
-+ **********************************************************************/
-+#define TOE_BASE                                      (IO_ADDRESS(SL2312_TOE_BASE))
-+#define GMAC_GLOBAL_BASE_ADDR       (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+
-+#define TOE_GLOBAL_BASE                               (TOE_BASE + 0x0000)
-+#define TOE_NONTOE_QUE_HDR_BASE               (TOE_BASE + 0x2000)
-+#define TOE_TOE_QUE_HDR_BASE          (TOE_BASE + 0x3000)
-+#define TOE_V_BIT_BASE                                (TOE_BASE + 0x4000)
-+#define TOE_A_BIT_BASE                                (TOE_BASE + 0x6000)
-+#define TOE_GMAC0_DMA_BASE                    (TOE_BASE + 0x8000)
-+#define TOE_GMAC0_BASE                                (TOE_BASE + 0xA000)
-+#define TOE_GMAC1_DMA_BASE                    (TOE_BASE + 0xC000)
-+#define TOE_GMAC1_BASE                                (TOE_BASE + 0xE000)
-+
-+/**********************************************************************
-+ * Queue ID
-+ **********************************************************************/
-+#define TOE_SW_FREE_QID                               0x00
-+#define TOE_HW_FREE_QID                               0x01
-+#define TOE_GMAC0_SW_TXQ0_QID         0x02
-+#define TOE_GMAC0_SW_TXQ1_QID         0x03
-+#define TOE_GMAC0_SW_TXQ2_QID         0x04
-+#define TOE_GMAC0_SW_TXQ3_QID         0x05
-+#define TOE_GMAC0_SW_TXQ4_QID         0x06
-+#define TOE_GMAC0_SW_TXQ5_QID         0x07
-+#define TOE_GMAC0_HW_TXQ0_QID         0x08
-+#define TOE_GMAC0_HW_TXQ1_QID         0x09
-+#define TOE_GMAC0_HW_TXQ2_QID         0x0A
-+#define TOE_GMAC0_HW_TXQ3_QID         0x0B
-+#define TOE_GMAC1_SW_TXQ0_QID         0x12
-+#define TOE_GMAC1_SW_TXQ1_QID         0x13
-+#define TOE_GMAC1_SW_TXQ2_QID         0x14
-+#define TOE_GMAC1_SW_TXQ3_QID         0x15
-+#define TOE_GMAC1_SW_TXQ4_QID         0x16
-+#define TOE_GMAC1_SW_TXQ5_QID         0x17
-+#define TOE_GMAC1_HW_TXQ0_QID         0x18
-+#define TOE_GMAC1_HW_TXQ1_QID         0x19
-+#define TOE_GMAC1_HW_TXQ2_QID         0x1A
-+#define TOE_GMAC1_HW_TXQ3_QID         0x1B
-+#define TOE_GMAC0_DEFAULT_QID         0x20
-+#define TOE_GMAC1_DEFAULT_QID         0x21
-+#define TOE_CLASSIFICATION_QID(x)     (0x22 + x)      // 0x22 ~ 0x2F
-+#define TOE_TOE_QID(x)                                (0x40 + x)      // 0x40 ~ 0x7F
-+
-+/**********************************************************************
-+ * TOE DMA Queue Number should be 2^n, n = 6...12
-+ * TOE DMA Queues are the following queue types:
-+ *            SW Free Queue, HW Free Queue,
-+ *            GMAC 0/1 SW TX Q0-5, and GMAC 0/1 HW TX Q0-5
-+ * They have same descriptor numbers.
-+ * The base address and descriptor number are configured at
-+ * DMA Queues Descriptor Ring Base Address/Size Register (offset 0x0004)
-+ **********************************************************************/
-+#define TOE_SW_FREEQ_DESC_POWER               10
-+#define TOE_SW_FREEQ_DESC_NUM         (1<<TOE_SW_FREEQ_DESC_POWER)
-+#define TOE_HW_FREEQ_DESC_POWER               8
-+#define TOE_HW_FREEQ_DESC_NUM         (1<<TOE_HW_FREEQ_DESC_POWER)
-+#define TOE_GMAC0_SWTXQ_DESC_POWER    8
-+#define TOE_GMAC0_SWTXQ_DESC_NUM      (1<<TOE_GMAC0_SWTXQ_DESC_POWER)
-+#define TOE_GMAC0_HWTXQ_DESC_POWER    8
-+#define TOE_GMAC0_HWTXQ_DESC_NUM      (1<<TOE_GMAC0_HWTXQ_DESC_POWER)
-+#define TOE_GMAC1_SWTXQ_DESC_POWER    8
-+#define TOE_GMAC1_SWTXQ_DESC_NUM      (1<<TOE_GMAC1_SWTXQ_DESC_POWER)
-+#define TOE_GMAC1_HWTXQ_DESC_POWER    8
-+#define TOE_GMAC1_HWTXQ_DESC_NUM      (1<<TOE_GMAC1_HWTXQ_DESC_POWER)
-+#define TOE_DEFAULT_Q0_DESC_POWER     8
-+#define TOE_DEFAULT_Q0_DESC_NUM               (1<<TOE_DEFAULT_Q0_DESC_POWER)
-+#define TOE_DEFAULT_Q1_DESC_POWER     8
-+#define TOE_DEFAULT_Q1_DESC_NUM               (1<<TOE_DEFAULT_Q1_DESC_POWER)
-+#define TOE_TOE_DESC_POWER                    8
-+#define TOE_TOE_DESC_NUM                      (1<<TOE_TOE_DESC_POWER)
-+#define TOE_CLASS_DESC_POWER          8
-+#define TOE_CLASS_DESC_NUM                    (1<<TOE_CLASS_DESC_POWER)
-+#define TOE_INTR_DESC_POWER                   8
-+#define TOE_INTR_DESC_NUM                     (1<<TOE_INTR_DESC_POWER)
-+
-+#define TOE_TOE_QUEUE_MAX                     64
-+#define TOE_TOE_QUEUE_NUM                     64
-+#define TOE_CLASS_QUEUE_MAX                   14
-+#define TOE_CLASS_QUEUE_NUM                   14
-+#define TOE_INTR_QUEUE_MAX                    4
-+#define TOE_INTR_QUEUE_NUM                    4
-+#define TOE_SW_TXQ_MAX                                6
-+#define TOE_SW_TXQ_NUM                                1
-+#define TOE_HW_TXQ_MAX                                4
-+#define TOE_HW_TXQ_NUM                                4
-+#define _max(x,y)                                     ((x>y) ? x :y)
-+#define TX_DESC_NUM                                   _max(TOE_GMAC0_SWTXQ_DESC_NUM, TOE_GMAC1_SWTXQ_DESC_NUM)
-+
-+#define RWPTR_ADVANCE_ONE(x, max)     ((x == (max -1)) ? 0 : x+1)
-+#define RWPTR_RECEDE_ONE(x, max)      ((x == 0) ? (max -1) : x-1)
-+#define SET_WPTR(addr, data)          (*(volatile u16 * const)((u32)(addr)+2) = (u16)data)
-+#define SET_RPTR(addr, data)          (*(volatile u16 * const)((u32)(addr)) = (u16)data)
-+
-+/**********************************************************************
-+ * Global registers
-+ * #define TOE_GLOBAL_BASE                    (TOE_BASE + 0x0000)
-+ * Base 0x60000000
-+ **********************************************************************/
-+#define GLOBAL_TOE_VERSION_REG                        0x0000
-+#define GLOBAL_SW_FREEQ_BASE_SIZE_REG 0x0004
-+#define GLOBAL_HW_FREEQ_BASE_SIZE_REG 0x0008
-+#define GLOBAL_DMA_SKB_SIZE_REG                       0x0010
-+#define GLOBAL_SWFQ_RWPTR_REG                 0x0014
-+#define GLOBAL_HWFQ_RWPTR_REG                 0x0018
-+#define GLOBAL_INTERRUPT_STATUS_0_REG 0x0020
-+#define GLOBAL_INTERRUPT_ENABLE_0_REG 0x0024
-+#define GLOBAL_INTERRUPT_SELECT_0_REG 0x0028
-+#define GLOBAL_INTERRUPT_STATUS_1_REG 0x0030
-+#define GLOBAL_INTERRUPT_ENABLE_1_REG 0x0034
-+#define GLOBAL_INTERRUPT_SELECT_1_REG 0x0038
-+#define GLOBAL_INTERRUPT_STATUS_2_REG 0x0040
-+#define GLOBAL_INTERRUPT_ENABLE_2_REG 0x0044
-+#define GLOBAL_INTERRUPT_SELECT_2_REG 0x0048
-+#define GLOBAL_INTERRUPT_STATUS_3_REG 0x0050
-+#define GLOBAL_INTERRUPT_ENABLE_3_REG 0x0054
-+#define GLOBAL_INTERRUPT_SELECT_3_REG 0x0058
-+#define GLOBAL_INTERRUPT_STATUS_4_REG 0x0060
-+#define GLOBAL_INTERRUPT_ENABLE_4_REG 0x0064
-+#define GLOBAL_INTERRUPT_SELECT_4_REG 0x0068
-+#define GLOBAL_HASH_TABLE_BASE_REG            0x006C
-+#define GLOBAL_QUEUE_THRESHOLD_REG            0x0070
-+
-+/**********************************************************************
-+ * GMAC 0/1 DMA/TOE register
-+ * #define TOE_GMAC0_DMA_BASE         (TOE_BASE + 0x8000)
-+ * #define TOE_GMAC1_DMA_BASE         (TOE_BASE + 0xC000)
-+ * Base 0x60008000 or 0x6000C000
-+ **********************************************************************/
-+#define GMAC_DMA_CTRL_REG                             0x0000
-+#define GMAC_TX_WEIGHTING_CTRL_0_REG  0x0004
-+#define GMAC_TX_WEIGHTING_CTRL_1_REG  0x0008
-+#define GMAC_SW_TX_QUEUE0_PTR_REG             0x000C
-+#define GMAC_SW_TX_QUEUE1_PTR_REG             0x0010
-+#define GMAC_SW_TX_QUEUE2_PTR_REG             0x0014
-+#define GMAC_SW_TX_QUEUE3_PTR_REG             0x0018
-+#define GMAC_SW_TX_QUEUE4_PTR_REG             0x001C
-+#define GMAC_SW_TX_QUEUE5_PTR_REG             0x0020
-+#define GMAC_HW_TX_QUEUE0_PTR_REG             0x0024
-+#define GMAC_HW_TX_QUEUE1_PTR_REG             0x0028
-+#define GMAC_HW_TX_QUEUE2_PTR_REG             0x002C
-+#define GMAC_HW_TX_QUEUE3_PTR_REG             0x0030
-+#define GMAC_DMA_TX_FIRST_DESC_REG            0x0038
-+#define GMAC_DMA_TX_CURR_DESC_REG             0x003C
-+#define GMAC_DMA_TX_DESC_WORD0_REG            0x0040
-+#define GMAC_DMA_TX_DESC_WORD1_REG            0x0044
-+#define GMAC_DMA_TX_DESC_WORD2_REG            0x0048
-+#define GMAC_DMA_TX_DESC_WORD3_REG            0x004C
-+#define GMAC_SW_TX_QUEUE_BASE_REG             0x0050
-+#define GMAC_HW_TX_QUEUE_BASE_REG             0x0054
-+#define GMAC_DMA_RX_FIRST_DESC_REG            0x0058
-+#define GMAC_DMA_RX_CURR_DESC_REG             0x005C
-+#define GMAC_DMA_RX_DESC_WORD0_REG            0x0060
-+#define GMAC_DMA_RX_DESC_WORD1_REG            0x0064
-+#define GMAC_DMA_RX_DESC_WORD2_REG            0x0068
-+#define GMAC_DMA_RX_DESC_WORD3_REG            0x006C
-+#define GMAC_HASH_ENGINE_REG0                 0x0070
-+#define GMAC_HASH_ENGINE_REG1                 0x0074
-+#define GMAC_MR0CR0                                           0x0078  // matching rule 0 Control register 0
-+#define GMAC_MR0CR1                                           0x007C  // matching rule 0 Control register 1
-+#define GMAC_MR0CR2                                           0x0080  // matching rule 0 Control register 2
-+#define GMAC_MR1CR0                                           0x0084  // matching rule 1 Control register 0
-+#define GMAC_MR1CR1                                           0x0088  // matching rule 1 Control register 1
-+#define GMAC_MR1CR2                                           0x008C  // matching rule 1 Control register 2
-+#define GMAC_MR2CR0                                           0x0090  // matching rule 2 Control register 0
-+#define GMAC_MR2CR1                                           0x0094  // matching rule 2 Control register 1
-+#define GMAC_MR2CR2                                           0x0098  // matching rule 2 Control register 2
-+#define GMAC_MR3CR0                                           0x009C  // matching rule 3 Control register 0
-+#define GMAC_MR3CR1                                           0x00A0  // matching rule 3 Control register 1
-+#define GMAC_MR3CR2                                           0x00A4  // matching rule 3 Control register 2
-+#define GMAC_SPR0                                             0x00A8  // Support Protocol Regsister 0
-+#define GMAC_SPR1                                             0x00AC  // Support Protocol Regsister 1
-+#define GMAC_SPR2                                             0x00B0  // Support Protocol Regsister 2
-+#define GMAC_SPR3                                             0x00B4  // Support Protocol Regsister 3
-+#define GMAC_SPR4                                             0x00B8  // Support Protocol Regsister 4
-+#define GMAC_SPR5                                             0x00BC  // Support Protocol Regsister 5
-+#define GMAC_SPR6                                             0x00C0  // Support Protocol Regsister 6
-+#define GMAC_SPR7                                             0x00C4  // Support Protocol Regsister 7
-+#define GMAC_AHB_WEIGHT_REG                           0x00C8  // GMAC Hash/Rx/Tx AHB Weighting register
-+
-+/**********************************************************************
-+ * TOE GMAC 0/1 register
-+ * #define TOE_GMAC0_BASE                             (TOE_BASE + 0xA000)
-+ * #define TOE_GMAC1_BASE                             (TOE_BASE + 0xE000)
-+ * Base 0x6000A000 or 0x6000E000
-+ **********************************************************************/
-+enum GMAC_REGISTER {
-+      GMAC_STA_ADD0   = 0x0000,
-+      GMAC_STA_ADD1   = 0x0004,
-+      GMAC_STA_ADD2   = 0x0008,
-+      GMAC_RX_FLTR    = 0x000c,
-+      GMAC_MCAST_FIL0 = 0x0010,
-+      GMAC_MCAST_FIL1 = 0x0014,
-+      GMAC_CONFIG0    = 0x0018,
-+      GMAC_CONFIG1    = 0x001c,
-+      GMAC_CONFIG2    = 0x0020,
-+      GMAC_CONFIG3    = 0x0024,
-+      GMAC_RESERVED   = 0x0028,
-+      GMAC_STATUS             = 0x002c,
-+      GMAC_IN_DISCARDS= 0x0030,
-+      GMAC_IN_ERRORS  = 0x0034,
-+      GMAC_IN_MCAST   = 0x0038,
-+      GMAC_IN_BCAST   = 0x003c,
-+      GMAC_IN_MAC1    = 0x0040,       // for STA 1 MAC Address
-+      GMAC_IN_MAC2    = 0x0044        // for STA 2 MAC Address
-+};
-+/**********************************************************************
-+ * TOE version Register (offset 0x0000)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int reserved           : 15;   // bit 31:17
-+              unsigned int v_bit_mode         : 1;    // bit 16               1: 128-entry
-+              unsigned int device_id          : 12;   // bit 15:4     Device ID
-+              unsigned int revision_id        : 4;    // bit  3:0     Revision ID
-+#else
-+              unsigned int revision_id        : 4;    // bit  3:0     Revision ID
-+              unsigned int device_id          : 12;   // bit 15:4     Device ID
-+              unsigned int v_bit_mode         : 1;    // bit 16               1: 128-entry
-+              unsigned int reserved           : 15;   // bit 31:17
-+#endif
-+      } bits;
-+} TOE_VERSION_T;
-+
-+
-+/**********************************************************************
-+ * DMA Queues description Ring Base Address/Size Register (offset 0x0004)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      unsigned int base_size;
-+} DMA_Q_BASE_SIZE_T;
-+#define DMA_Q_BASE_MASK       (~0x0f)
-+
-+/**********************************************************************
-+ * DMA SKB Buffer register (offset 0x0008)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_0008
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int hw_skb_size        : 16;   // bit 31:16    HW Free poll SKB Size
-+              unsigned int sw_skb_size        : 16;   // bit 15:0     SW Free poll SKB Size
-+#else
-+              unsigned int sw_skb_size        : 16;   // bit 15:0     SW Free poll SKB Size
-+              unsigned int hw_skb_size        : 16;   // bit 31:16    HW Free poll SKB Size
-+#endif
-+      } bits;
-+} DMA_SKB_SIZE_T;
-+
-+/**********************************************************************
-+ * DMA SW Free Queue Read/Write Pointer Register (offset 0x000C)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_000c
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int wptr                       : 16;   // bit 31:16    Write Ptr, RW
-+              unsigned int rptr                       : 16;   // bit 15:0             Read Ptr, RO
-+#else
-+              unsigned int rptr                       : 16;   // bit 15:0             Read Ptr, RO
-+              unsigned int wptr                       : 16;   // bit 31:16    Write Ptr, RW
-+#endif
-+      } bits;
-+} DMA_RWPTR_T;
-+
-+/**********************************************************************
-+ * DMA HW Free Queue Read/Write Pointer Register (offset 0x0010)
-+ **********************************************************************/
-+// see DMA_RWPTR_T structure
-+
-+/**********************************************************************
-+ * Interrupt Status Register 0        (offset 0x0020)
-+ * Interrupt Mask Register 0  (offset 0x0024)
-+ * Interrupt Select Register 0        (offset 0x0028)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_0020
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int txDerr1            : 1;    // bit 31       GMAC1 AHB Bus Error while Tx
-+              unsigned int txPerr1            : 1;    // bit 30       GMAC1 Tx Descriptor Protocol Error
-+              unsigned int txDerr0            : 1;    // bit 29       GMAC0 AHB Bus Error while Tx
-+              unsigned int txPerr0            : 1;    // bit 28       GMAC0 Tx Descriptor Protocol Error
-+              unsigned int rxDerr1            : 1;    // bit 27       GMAC1 AHB Bus Error while Rx
-+              unsigned int rxPerr1            : 1;    // bit 26       GMAC1 Rx Descriptor Protocol Error
-+              unsigned int rxDerr0            : 1;    // bit 25       GMAC0 AHB Bus Error while Rx
-+              unsigned int rxPerr0            : 1;    // bit 24       GMAC0 Rx Descriptor Protocol Error
-+              unsigned int swtq15_fin         : 1;    // bit 23       GMAC1 SW Tx Queue 5 Finish Interrupt
-+              unsigned int swtq14_fin         : 1;    // bit 22       GMAC1 SW Tx Queue 4 Finish Interrupt
-+              unsigned int swtq13_fin         : 1;    // bit 21       GMAC1 SW Tx Queue 3 Finish Interrupt
-+              unsigned int swtq12_fin         : 1;    // bit 20       GMAC1 SW Tx Queue 2 Finish Interrupt
-+              unsigned int swtq11_fin         : 1;    // bit 19       GMAC1 SW Tx Queue 1 Finish Interrupt
-+              unsigned int swtq10_fin         : 1;    // bit 18       GMAC1 SW Tx Queue 0 Finish Interrupt
-+              unsigned int swtq05_fin         : 1;    // bit 17       GMAC0 SW Tx Queue 5 Finish Interrupt
-+              unsigned int swtq04_fin         : 1;    // bit 16       GMAC0 SW Tx Queue 4 Finish Interrupt
-+              unsigned int swtq03_fin         : 1;    // bit 15       GMAC0 SW Tx Queue 3 Finish Interrupt
-+              unsigned int swtq02_fin         : 1;    // bit 14       GMAC0 SW Tx Queue 2 Finish Interrupt
-+              unsigned int swtq01_fin         : 1;    // bit 13       GMAC0 SW Tx Queue 1 Finish Interrupt
-+              unsigned int swtq00_fin         : 1;    // bit 12       GMAC0 SW Tx Queue 0 Finish Interrupt
-+              unsigned int swtq15_eof         : 1;    // bit 11       GMAC1 SW Tx Queue 5 EOF Interrupt
-+              unsigned int swtq14_eof         : 1;    // bit 10       GMAC1 SW Tx Queue 4 EOF Interrupt
-+              unsigned int swtq13_eof         : 1;    // bit 9        GMAC1 SW Tx Queue 3 EOF Interrupt
-+              unsigned int swtq12_eof         : 1;    // bit 8        GMAC1 SW Tx Queue 2 EOF Interrupt
-+              unsigned int swtq11_eof         : 1;    // bit 7        GMAC1 SW Tx Queue 1 EOF Interrupt
-+              unsigned int swtq10_eof         : 1;    // bit 6        GMAC1 SW Tx Queue 0 EOF Interrupt
-+              unsigned int swtq05_eof         : 1;    // bit 5        GMAC0 SW Tx Queue 5 EOF Interrupt
-+              unsigned int swtq04_eof         : 1;    // bit 4        GMAC0 SW Tx Queue 4 EOF Interrupt
-+              unsigned int swtq03_eof         : 1;    // bit 3        GMAC0 SW Tx Queue 3 EOF Interrupt
-+              unsigned int swtq02_eof         : 1;    // bit 2        GMAC0 SW Tx Queue 2 EOF Interrupt
-+              unsigned int swtq01_eof         : 1;    // bit 1        GMAC0 SW Tx Queue 1 EOF Interrupt
-+              unsigned int swtq00_eof         : 1;    // bit 0        GMAC0 SW Tx Queue 0 EOF Interrupt
-+#else
-+              unsigned int swtq00_eof         : 1;    // bit 0        GMAC0 SW Tx Queue 0 EOF Interrupt
-+              unsigned int swtq01_eof         : 1;    // bit 1        GMAC0 SW Tx Queue 1 EOF Interrupt
-+              unsigned int swtq02_eof         : 1;    // bit 2        GMAC0 SW Tx Queue 2 EOF Interrupt
-+              unsigned int swtq03_eof         : 1;    // bit 3        GMAC0 SW Tx Queue 3 EOF Interrupt
-+              unsigned int swtq04_eof         : 1;    // bit 4        GMAC0 SW Tx Queue 4 EOF Interrupt
-+              unsigned int swtq05_eof         : 1;    // bit 5        GMAC0 SW Tx Queue 5 EOF Interrupt
-+              unsigned int swtq10_eof         : 1;    // bit 6        GMAC1 SW Tx Queue 0 EOF Interrupt
-+              unsigned int swtq11_eof         : 1;    // bit 7        GMAC1 SW Tx Queue 1 EOF Interrupt
-+              unsigned int swtq12_eof         : 1;    // bit 8        GMAC1 SW Tx Queue 2 EOF Interrupt
-+              unsigned int swtq13_eof         : 1;    // bit 9        GMAC1 SW Tx Queue 3 EOF Interrupt
-+              unsigned int swtq14_eof         : 1;    // bit 10       GMAC1 SW Tx Queue 4 EOF Interrupt
-+              unsigned int swtq15_eof         : 1;    // bit 11       GMAC1 SW Tx Queue 5 EOF Interrupt
-+              unsigned int swtq00_fin         : 1;    // bit 12       GMAC0 SW Tx Queue 0 Finish Interrupt
-+              unsigned int swtq01_fin         : 1;    // bit 13       GMAC0 SW Tx Queue 1 Finish Interrupt
-+              unsigned int swtq02_fin         : 1;    // bit 14       GMAC0 SW Tx Queue 2 Finish Interrupt
-+              unsigned int swtq03_fin         : 1;    // bit 15       GMAC0 SW Tx Queue 3 Finish Interrupt
-+              unsigned int swtq04_fin         : 1;    // bit 16       GMAC0 SW Tx Queue 4 Finish Interrupt
-+              unsigned int swtq05_fin         : 1;    // bit 17       GMAC0 SW Tx Queue 5 Finish Interrupt
-+              unsigned int swtq10_fin         : 1;    // bit 18       GMAC1 SW Tx Queue 0 Finish Interrupt
-+              unsigned int swtq11_fin         : 1;    // bit 19       GMAC1 SW Tx Queue 1 Finish Interrupt
-+              unsigned int swtq12_fin         : 1;    // bit 20       GMAC1 SW Tx Queue 2 Finish Interrupt
-+              unsigned int swtq13_fin         : 1;    // bit 21       GMAC1 SW Tx Queue 3 Finish Interrupt
-+              unsigned int swtq14_fin         : 1;    // bit 22       GMAC1 SW Tx Queue 4 Finish Interrupt
-+              unsigned int swtq15_fin         : 1;    // bit 23       GMAC1 SW Tx Queue 5 Finish Interrupt
-+              unsigned int rxPerr0            : 1;    // bit 24       GMAC0 Rx Descriptor Protocol Error
-+              unsigned int rxDerr0            : 1;    // bit 25       GMAC0 AHB Bus Error while Rx
-+              unsigned int rxPerr1            : 1;    // bit 26       GMAC1 Rx Descriptor Protocol Error
-+              unsigned int rxDerr1            : 1;    // bit 27       GMAC1 AHB Bus Error while Rx
-+              unsigned int txPerr0            : 1;    // bit 28       GMAC0 Tx Descriptor Protocol Error
-+              unsigned int txDerr0            : 1;    // bit 29       GMAC0 AHB Bus Error while Tx
-+              unsigned int txPerr1            : 1;    // bit 30       GMAC1 Tx Descriptor Protocol Error
-+              unsigned int txDerr1            : 1;    // bit 31       GMAC1 AHB Bus Error while Tx
-+#endif
-+      } bits;
-+} INTR_REG0_T;
-+
-+#define GMAC1_TXDERR_INT_BIT          BIT(31)
-+#define GMAC1_TXPERR_INT_BIT          BIT(30)
-+#define GMAC0_TXDERR_INT_BIT          BIT(29)
-+#define GMAC0_TXPERR_INT_BIT          BIT(28)
-+#define GMAC1_RXDERR_INT_BIT          BIT(27)
-+#define GMAC1_RXPERR_INT_BIT          BIT(26)
-+#define GMAC0_RXDERR_INT_BIT          BIT(25)
-+#define GMAC0_RXPERR_INT_BIT          BIT(24)
-+#define GMAC1_SWTQ15_FIN_INT_BIT      BIT(23)
-+#define GMAC1_SWTQ14_FIN_INT_BIT      BIT(22)
-+#define GMAC1_SWTQ13_FIN_INT_BIT      BIT(21)
-+#define GMAC1_SWTQ12_FIN_INT_BIT      BIT(20)
-+#define GMAC1_SWTQ11_FIN_INT_BIT      BIT(19)
-+#define GMAC1_SWTQ10_FIN_INT_BIT      BIT(18)
-+#define GMAC0_SWTQ05_FIN_INT_BIT      BIT(17)
-+#define GMAC0_SWTQ04_FIN_INT_BIT      BIT(16)
-+#define GMAC0_SWTQ03_FIN_INT_BIT      BIT(15)
-+#define GMAC0_SWTQ02_FIN_INT_BIT      BIT(14)
-+#define GMAC0_SWTQ01_FIN_INT_BIT      BIT(13)
-+#define GMAC0_SWTQ00_FIN_INT_BIT      BIT(12)
-+#define GMAC1_SWTQ15_EOF_INT_BIT      BIT(11)
-+#define GMAC1_SWTQ14_EOF_INT_BIT      BIT(10)
-+#define GMAC1_SWTQ13_EOF_INT_BIT      BIT(9)
-+#define GMAC1_SWTQ12_EOF_INT_BIT      BIT(8)
-+#define GMAC1_SWTQ11_EOF_INT_BIT      BIT(7)
-+#define GMAC1_SWTQ10_EOF_INT_BIT      BIT(6)
-+#define GMAC0_SWTQ05_EOF_INT_BIT      BIT(5)
-+#define GMAC0_SWTQ04_EOF_INT_BIT      BIT(4)
-+#define GMAC0_SWTQ03_EOF_INT_BIT      BIT(3)
-+#define GMAC0_SWTQ02_EOF_INT_BIT      BIT(2)
-+#define GMAC0_SWTQ01_EOF_INT_BIT      BIT(1)
-+#define GMAC0_SWTQ00_EOF_INT_BIT      BIT(0)
-+
-+
-+/**********************************************************************
-+ * Interrupt Status Register 1        (offset 0x0030)
-+ * Interrupt Mask Register 1  (offset 0x0034)
-+ * Interrupt Select Register 1        (offset 0x0038)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_0030
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int toe_iq3_full       : 1;    // bit 31       TOE Interrupt Queue 3 Full Interrupt
-+              unsigned int toe_iq2_full       : 1;    // bit 30       TOE Interrupt Queue 2 Full Interrupt
-+              unsigned int toe_iq1_full       : 1;    // bit 29       TOE Interrupt Queue 1 Full Interrupt
-+              unsigned int toe_iq0_full       : 1;    // bit 28       TOE Interrupt Queue 0 Full Interrupt
-+              unsigned int toe_iq3_intr       : 1;    // bit 27       TOE Interrupt Queue 3 with Interrupts
-+              unsigned int toe_iq2_intr       : 1;    // bit 26       TOE Interrupt Queue 2 with Interrupts
-+              unsigned int toe_iq1_intr       : 1;    // bit 25       TOE Interrupt Queue 1 with Interrupts
-+              unsigned int toe_iq0_intr       : 1;    // bit 24       TOE Interrupt Queue 0 with Interrupts
-+              unsigned int hwtq13_eof         : 1;    // bit 23       GMAC1 HW Tx Queue3 EOF Interrupt
-+              unsigned int hwtq12_eof         : 1;    // bit 22       GMAC1 HW Tx Queue2 EOF Interrupt
-+              unsigned int hwtq11_eof         : 1;    // bit 21       GMAC1 HW Tx Queue1 EOF Interrupt
-+              unsigned int hwtq10_eof         : 1;    // bit 20       GMAC1 HW Tx Queue0 EOF Interrupt
-+              unsigned int hwtq03_eof         : 1;    // bit 19       GMAC0 HW Tx Queue3 EOF Interrupt
-+              unsigned int hwtq02_eof         : 1;    // bit 18       GMAC0 HW Tx Queue2 EOF Interrupt
-+              unsigned int hwtq01_eof         : 1;    // bit 17       GMAC0 HW Tx Queue1 EOF Interrupt
-+              unsigned int hwtq00_eof         : 1;    // bit 16       GMAC0 HW Tx Queue0 EOF Interrupt
-+              unsigned int class_rx           : 14;   // bit 15:2     Classification Queue Rx Interrupt
-+              unsigned int default_q1_eof     : 1;    // bit 1        Default Queue 1 EOF Interrupt
-+              unsigned int default_q0_eof     : 1;    // bit 0        Default Queue 0 EOF Interrupt
-+#else
-+              unsigned int default_q0_eof     : 1;    // bit 0        Default Queue 0 EOF Interrupt
-+              unsigned int default_q1_eof     : 1;    // bit 1        Default Queue 1 EOF Interrupt
-+              unsigned int class_rx           : 14;   // bit 15:2     Classification Queue Rx Interrupt
-+              unsigned int hwtq00_eof         : 1;    // bit 16       GMAC0 HW Tx Queue0 EOF Interrupt
-+              unsigned int hwtq01_eof         : 1;    // bit 17       GMAC0 HW Tx Queue1 EOF Interrupt
-+              unsigned int hwtq02_eof         : 1;    // bit 18       GMAC0 HW Tx Queue2 EOF Interrupt
-+              unsigned int hwtq03_eof         : 1;    // bit 19       GMAC0 HW Tx Queue3 EOF Interrupt
-+              unsigned int hwtq10_eof         : 1;    // bit 20       GMAC1 HW Tx Queue0 EOF Interrupt
-+              unsigned int hwtq11_eof         : 1;    // bit 21       GMAC1 HW Tx Queue1 EOF Interrupt
-+              unsigned int hwtq12_eof         : 1;    // bit 22       GMAC1 HW Tx Queue2 EOF Interrupt
-+              unsigned int hwtq13_eof         : 1;    // bit 23       GMAC1 HW Tx Queue3 EOF Interrupt
-+              unsigned int toe_iq0_intr       : 1;    // bit 24       TOE Interrupt Queue 0 with Interrupts
-+              unsigned int toe_iq1_intr       : 1;    // bit 25       TOE Interrupt Queue 1 with Interrupts
-+              unsigned int toe_iq2_intr       : 1;    // bit 26       TOE Interrupt Queue 2 with Interrupts
-+              unsigned int toe_iq3_intr       : 1;    // bit 27       TOE Interrupt Queue 3 with Interrupts
-+              unsigned int toe_iq0_full       : 1;    // bit 28       TOE Interrupt Queue 0 Full Interrupt
-+              unsigned int toe_iq1_full       : 1;    // bit 29       TOE Interrupt Queue 1 Full Interrupt
-+              unsigned int toe_iq2_full       : 1;    // bit 30       TOE Interrupt Queue 2 Full Interrupt
-+              unsigned int toe_iq3_full       : 1;    // bit 31       TOE Interrupt Queue 3 Full Interrupt
-+#endif
-+      } bits;
-+} INTR_REG1_T;
-+
-+#define TOE_IQ3_FULL_INT_BIT          BIT(31)
-+#define TOE_IQ2_FULL_INT_BIT          BIT(30)
-+#define TOE_IQ1_FULL_INT_BIT          BIT(29)
-+#define TOE_IQ0_FULL_INT_BIT          BIT(28)
-+#define TOE_IQ3_INT_BIT                               BIT(27)
-+#define TOE_IQ2_INT_BIT                               BIT(26)
-+#define TOE_IQ1_INT_BIT                               BIT(25)
-+#define TOE_IQ0_INT_BIT                               BIT(24)
-+#define GMAC1_HWTQ13_EOF_INT_BIT      BIT(23)
-+#define GMAC1_HWTQ12_EOF_INT_BIT      BIT(22)
-+#define GMAC1_HWTQ11_EOF_INT_BIT      BIT(21)
-+#define GMAC1_HWTQ10_EOF_INT_BIT      BIT(20)
-+#define GMAC0_HWTQ03_EOF_INT_BIT      BIT(19)
-+#define GMAC0_HWTQ02_EOF_INT_BIT      BIT(18)
-+#define GMAC0_HWTQ01_EOF_INT_BIT      BIT(17)
-+#define GMAC0_HWTQ00_EOF_INT_BIT      BIT(16)
-+#define CLASS_RX_INT_BIT(x)                   BIT((x+2))
-+#define DEFAULT_Q1_INT_BIT                    BIT(1)
-+#define DEFAULT_Q0_INT_BIT                    BIT(0)
-+
-+#define TOE_IQ_INT_BITS                               (TOE_IQ0_INT_BIT | TOE_IQ1_INT_BIT | \
-+                                                      TOE_IQ2_INT_BIT | TOE_IQ3_INT_BIT)
-+#define       TOE_IQ_FULL_BITS                        (TOE_IQ0_FULL_INT_BIT | TOE_IQ1_FULL_INT_BIT | \
-+                                                      TOE_IQ2_FULL_INT_BIT | TOE_IQ3_FULL_INT_BIT)
-+#define       TOE_IQ_ALL_BITS                         (TOE_IQ_INT_BITS | TOE_IQ_FULL_BITS)
-+#define TOE_CLASS_RX_INT_BITS         0xfffc
-+
-+/**********************************************************************
-+ * Interrupt Status Register 2        (offset 0x0040)
-+ * Interrupt Mask Register 2  (offset 0x0044)
-+ * Interrupt Select Register 2        (offset 0x0048)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_0040
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int toe_q31_full       : 1;    // bit 31       TOE Queue 31 Full Interrupt
-+              unsigned int toe_q30_full       : 1;    // bit 30       TOE Queue 30 Full Interrupt
-+              unsigned int toe_q29_full       : 1;    // bit 29       TOE Queue 29 Full Interrupt
-+              unsigned int toe_q28_full       : 1;    // bit 28       TOE Queue 28 Full Interrupt
-+              unsigned int toe_q27_full       : 1;    // bit 27       TOE Queue 27 Full Interrupt
-+              unsigned int toe_q26_full       : 1;    // bit 26       TOE Queue 26 Full Interrupt
-+              unsigned int toe_q25_full       : 1;    // bit 25       TOE Queue 25 Full Interrupt
-+              unsigned int toe_q24_full       : 1;    // bit 24       TOE Queue 24 Full Interrupt
-+              unsigned int toe_q23_full       : 1;    // bit 23       TOE Queue 23 Full Interrupt
-+              unsigned int toe_q22_full       : 1;    // bit 22       TOE Queue 22 Full Interrupt
-+              unsigned int toe_q21_full       : 1;    // bit 21       TOE Queue 21 Full Interrupt
-+              unsigned int toe_q20_full       : 1;    // bit 20       TOE Queue 20 Full Interrupt
-+              unsigned int toe_q19_full       : 1;    // bit 19       TOE Queue 19 Full Interrupt
-+              unsigned int toe_q18_full       : 1;    // bit 18       TOE Queue 18 Full Interrupt
-+              unsigned int toe_q17_full       : 1;    // bit 17       TOE Queue 17 Full Interrupt
-+              unsigned int toe_q16_full       : 1;    // bit 16       TOE Queue 16 Full Interrupt
-+              unsigned int toe_q15_full       : 1;    // bit 15       TOE Queue 15 Full Interrupt
-+              unsigned int toe_q14_full       : 1;    // bit 14       TOE Queue 14 Full Interrupt
-+              unsigned int toe_q13_full       : 1;    // bit 13       TOE Queue 13 Full Interrupt
-+              unsigned int toe_q12_full       : 1;    // bit 12       TOE Queue 12 Full Interrupt
-+              unsigned int toe_q11_full       : 1;    // bit 11       TOE Queue 11 Full Interrupt
-+              unsigned int toe_q10_full       : 1;    // bit 10       TOE Queue 10 Full Interrupt
-+              unsigned int toe_q9_full        : 1;    // bit 9        TOE Queue 9 Full Interrupt
-+              unsigned int toe_q8_full        : 1;    // bit 8        TOE Queue 8 Full Interrupt
-+              unsigned int toe_q7_full        : 1;    // bit 7        TOE Queue 7 Full Interrupt
-+              unsigned int toe_q6_full        : 1;    // bit 6        TOE Queue 6 Full Interrupt
-+              unsigned int toe_q5_full        : 1;    // bit 5        TOE Queue 5 Full Interrupt
-+              unsigned int toe_q4_full        : 1;    // bit 4        TOE Queue 4 Full Interrupt
-+              unsigned int toe_q3_full        : 1;    // bit 3        TOE Queue 3 Full Interrupt
-+              unsigned int toe_q2_full        : 1;    // bit 2        TOE Queue 2 Full Interrupt
-+              unsigned int toe_q1_full        : 1;    // bit 1        TOE Queue 1 Full Interrupt
-+              unsigned int toe_q0_full        : 1;    // bit 0        TOE Queue 0 Full Interrupt
-+#else
-+              unsigned int toe_q0_full        : 1;    // bit 0        TOE Queue 0 Full Interrupt
-+              unsigned int toe_q1_full        : 1;    // bit 1        TOE Queue 1 Full Interrupt
-+              unsigned int toe_q2_full        : 1;    // bit 2        TOE Queue 2 Full Interrupt
-+              unsigned int toe_q3_full        : 1;    // bit 3        TOE Queue 3 Full Interrupt
-+              unsigned int toe_q4_full        : 1;    // bit 4        TOE Queue 4 Full Interrupt
-+              unsigned int toe_q5_full        : 1;    // bit 5        TOE Queue 5 Full Interrupt
-+              unsigned int toe_q6_full        : 1;    // bit 6        TOE Queue 6 Full Interrupt
-+              unsigned int toe_q7_full        : 1;    // bit 7        TOE Queue 7 Full Interrupt
-+              unsigned int toe_q8_full        : 1;    // bit 8        TOE Queue 8 Full Interrupt
-+              unsigned int toe_q9_full        : 1;    // bit 9        TOE Queue 9 Full Interrupt
-+              unsigned int toe_q10_full       : 1;    // bit 10       TOE Queue 10 Full Interrupt
-+              unsigned int toe_q11_full       : 1;    // bit 11       TOE Queue 11 Full Interrupt
-+              unsigned int toe_q12_full       : 1;    // bit 12       TOE Queue 12 Full Interrupt
-+              unsigned int toe_q13_full       : 1;    // bit 13       TOE Queue 13 Full Interrupt
-+              unsigned int toe_q14_full       : 1;    // bit 14       TOE Queue 14 Full Interrupt
-+              unsigned int toe_q15_full       : 1;    // bit 15       TOE Queue 15 Full Interrupt
-+              unsigned int toe_q16_full       : 1;    // bit 16       TOE Queue 16 Full Interrupt
-+              unsigned int toe_q17_full       : 1;    // bit 17       TOE Queue 17 Full Interrupt
-+              unsigned int toe_q18_full       : 1;    // bit 18       TOE Queue 18 Full Interrupt
-+              unsigned int toe_q19_full       : 1;    // bit 19       TOE Queue 19 Full Interrupt
-+              unsigned int toe_q20_full       : 1;    // bit 20       TOE Queue 20 Full Interrupt
-+              unsigned int toe_q21_full       : 1;    // bit 21       TOE Queue 21 Full Interrupt
-+              unsigned int toe_q22_full       : 1;    // bit 22       TOE Queue 22 Full Interrupt
-+              unsigned int toe_q23_full       : 1;    // bit 23       TOE Queue 23 Full Interrupt
-+              unsigned int toe_q24_full       : 1;    // bit 24       TOE Queue 24 Full Interrupt
-+              unsigned int toe_q25_full       : 1;    // bit 25       TOE Queue 25 Full Interrupt
-+              unsigned int toe_q26_full       : 1;    // bit 26       TOE Queue 26 Full Interrupt
-+              unsigned int toe_q27_full       : 1;    // bit 27       TOE Queue 27 Full Interrupt
-+              unsigned int toe_q28_full       : 1;    // bit 28       TOE Queue 28 Full Interrupt
-+              unsigned int toe_q29_full       : 1;    // bit 29       TOE Queue 29 Full Interrupt
-+              unsigned int toe_q30_full       : 1;    // bit 30       TOE Queue 30 Full Interrupt
-+              unsigned int toe_q31_full       : 1;    // bit 31       TOE Queue 31 Full Interrupt
-+#endif
-+      } bits;
-+} INTR_REG2_T;
-+
-+#define TOE_QL_FULL_INT_BIT(x)                BIT(x)
-+
-+/**********************************************************************
-+ * Interrupt Status Register 3        (offset 0x0050)
-+ * Interrupt Mask Register 3  (offset 0x0054)
-+ * Interrupt Select Register 3        (offset 0x0058)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_0050
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int toe_q63_full       : 1;    // bit 63       TOE Queue 63 Full Interrupt
-+              unsigned int toe_q62_full       : 1;    // bit 62       TOE Queue 62 Full Interrupt
-+              unsigned int toe_q61_full       : 1;    // bit 61       TOE Queue 61 Full Interrupt
-+              unsigned int toe_q60_full       : 1;    // bit 60       TOE Queue 60 Full Interrupt
-+              unsigned int toe_q59_full       : 1;    // bit 59       TOE Queue 59 Full Interrupt
-+              unsigned int toe_q58_full       : 1;    // bit 58       TOE Queue 58 Full Interrupt
-+              unsigned int toe_q57_full       : 1;    // bit 57       TOE Queue 57 Full Interrupt
-+              unsigned int toe_q56_full       : 1;    // bit 56       TOE Queue 56 Full Interrupt
-+              unsigned int toe_q55_full       : 1;    // bit 55       TOE Queue 55 Full Interrupt
-+              unsigned int toe_q54_full       : 1;    // bit 54       TOE Queue 54 Full Interrupt
-+              unsigned int toe_q53_full       : 1;    // bit 53       TOE Queue 53 Full Interrupt
-+              unsigned int toe_q52_full       : 1;    // bit 52       TOE Queue 52 Full Interrupt
-+              unsigned int toe_q51_full       : 1;    // bit 51       TOE Queue 51 Full Interrupt
-+              unsigned int toe_q50_full       : 1;    // bit 50       TOE Queue 50 Full Interrupt
-+              unsigned int toe_q49_full       : 1;    // bit 49       TOE Queue 49 Full Interrupt
-+              unsigned int toe_q48_full       : 1;    // bit 48       TOE Queue 48 Full Interrupt
-+              unsigned int toe_q47_full       : 1;    // bit 47       TOE Queue 47 Full Interrupt
-+              unsigned int toe_q46_full       : 1;    // bit 46       TOE Queue 46 Full Interrupt
-+              unsigned int toe_q45_full       : 1;    // bit 45       TOE Queue 45 Full Interrupt
-+              unsigned int toe_q44_full       : 1;    // bit 44       TOE Queue 44 Full Interrupt
-+              unsigned int toe_q43_full       : 1;    // bit 43       TOE Queue 43 Full Interrupt
-+              unsigned int toe_q42_full       : 1;    // bit 42       TOE Queue 42 Full Interrupt
-+              unsigned int toe_q41_full       : 1;    // bit 41       TOE Queue 41 Full Interrupt
-+              unsigned int toe_q40_full       : 1;    // bit 40       TOE Queue 40 Full Interrupt
-+              unsigned int toe_q39_full       : 1;    // bit 39       TOE Queue 39 Full Interrupt
-+              unsigned int toe_q38_full       : 1;    // bit 38       TOE Queue 38 Full Interrupt
-+              unsigned int toe_q37_full       : 1;    // bit 37       TOE Queue 37 Full Interrupt
-+              unsigned int toe_q36_full       : 1;    // bit 36       TOE Queue 36 Full Interrupt
-+              unsigned int toe_q35_full       : 1;    // bit 35       TOE Queue 35 Full Interrupt
-+              unsigned int toe_q34_full       : 1;    // bit 34       TOE Queue 34 Full Interrupt
-+              unsigned int toe_q33_full       : 1;    // bit 33       TOE Queue 33 Full Interrupt
-+              unsigned int toe_q32_full       : 1;    // bit 32       TOE Queue 32 Full Interrupt
-+#else
-+              unsigned int toe_q32_full       : 1;    // bit 32       TOE Queue 32 Full Interrupt
-+              unsigned int toe_q33_full       : 1;    // bit 33       TOE Queue 33 Full Interrupt
-+              unsigned int toe_q34_full       : 1;    // bit 34       TOE Queue 34 Full Interrupt
-+              unsigned int toe_q35_full       : 1;    // bit 35       TOE Queue 35 Full Interrupt
-+              unsigned int toe_q36_full       : 1;    // bit 36       TOE Queue 36 Full Interrupt
-+              unsigned int toe_q37_full       : 1;    // bit 37       TOE Queue 37 Full Interrupt
-+              unsigned int toe_q38_full       : 1;    // bit 38       TOE Queue 38 Full Interrupt
-+              unsigned int toe_q39_full       : 1;    // bit 39       TOE Queue 39 Full Interrupt
-+              unsigned int toe_q40_full       : 1;    // bit 40       TOE Queue 40 Full Interrupt
-+              unsigned int toe_q41_full       : 1;    // bit 41       TOE Queue 41 Full Interrupt
-+              unsigned int toe_q42_full       : 1;    // bit 42       TOE Queue 42 Full Interrupt
-+              unsigned int toe_q43_full       : 1;    // bit 43       TOE Queue 43 Full Interrupt
-+              unsigned int toe_q44_full       : 1;    // bit 44       TOE Queue 44 Full Interrupt
-+              unsigned int toe_q45_full       : 1;    // bit 45       TOE Queue 45 Full Interrupt
-+              unsigned int toe_q46_full       : 1;    // bit 46       TOE Queue 46 Full Interrupt
-+              unsigned int toe_q47_full       : 1;    // bit 47       TOE Queue 47 Full Interrupt
-+              unsigned int toe_q48_full       : 1;    // bit 48       TOE Queue 48 Full Interrupt
-+              unsigned int toe_q49_full       : 1;    // bit 49       TOE Queue 49 Full Interrupt
-+              unsigned int toe_q50_full       : 1;    // bit 50       TOE Queue 50 Full Interrupt
-+              unsigned int toe_q51_full       : 1;    // bit 51       TOE Queue 51 Full Interrupt
-+              unsigned int toe_q52_full       : 1;    // bit 52       TOE Queue 52 Full Interrupt
-+              unsigned int toe_q53_full       : 1;    // bit 53       TOE Queue 53 Full Interrupt
-+              unsigned int toe_q54_full       : 1;    // bit 54       TOE Queue 54 Full Interrupt
-+              unsigned int toe_q55_full       : 1;    // bit 55       TOE Queue 55 Full Interrupt
-+              unsigned int toe_q56_full       : 1;    // bit 56       TOE Queue 56 Full Interrupt
-+              unsigned int toe_q57_full       : 1;    // bit 57       TOE Queue 57 Full Interrupt
-+              unsigned int toe_q58_full       : 1;    // bit 58       TOE Queue 58 Full Interrupt
-+              unsigned int toe_q59_full       : 1;    // bit 59       TOE Queue 59 Full Interrupt
-+              unsigned int toe_q60_full       : 1;    // bit 60       TOE Queue 60 Full Interrupt
-+              unsigned int toe_q61_full       : 1;    // bit 61       TOE Queue 61 Full Interrupt
-+              unsigned int toe_q62_full       : 1;    // bit 62       TOE Queue 62 Full Interrupt
-+              unsigned int toe_q63_full       : 1;    // bit 63       TOE Queue 63 Full Interrupt
-+#endif
-+      } bits;
-+} INTR_REG3_T;
-+
-+#define TOE_QH_FULL_INT_BIT(x)                BIT(x-32)
-+
-+/**********************************************************************
-+ * Interrupt Status Register 4        (offset 0x0060)
-+ * Interrupt Mask Register 4  (offset 0x0064)
-+ * Interrupt Select Register 4        (offset 0x0068)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned char byte;
-+      struct bit_0060
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned char reserved          : 1;    //
-+              unsigned char cnt_full          : 1;    // MIB counters half full interrupt
-+              unsigned char rx_pause_on       : 1;    // received pause on frame interrupt
-+              unsigned char tx_pause_on       : 1;    // transmit pause on frame interrupt
-+              unsigned char rx_pause_off  : 1;        // received pause off frame interrupt
-+              unsigned char tx_pause_off      : 1;    // received pause off frame interrupt
-+              unsigned char rx_overrun        : 1;    // GMAC Rx FIFO overrun interrupt
-+              unsigned char status_changed: 1;        // Status Changed Intr for RGMII Mode
-+#else
-+              unsigned char status_changed: 1;        // Status Changed Intr for RGMII Mode
-+              unsigned char rx_overrun        : 1;   // GMAC Rx FIFO overrun interrupt
-+              unsigned char tx_pause_off      : 1;    // received pause off frame interrupt
-+              unsigned char rx_pause_off  : 1;        // received pause off frame interrupt
-+              unsigned char tx_pause_on       : 1;    // transmit pause on frame interrupt
-+              unsigned char rx_pause_on       : 1;    // received pause on frame interrupt
-+              unsigned char cnt_full          : 1;    // MIB counters half full interrupt
-+              unsigned char reserved          : 1;    //
-+#endif
-+      } _PACKED_ bits;
-+} _PACKED_ GMAC_INTR_T;
-+
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_0060_2
-+      {
-+#if (BIG_ENDIAN==1)
-+              GMAC_INTR_T             gmac1;
-+              GMAC_INTR_T             gmac0;
-+              unsigned int    class_qf_int: 14;       // bit 15:2 Classification Rx Queue13-0 Full Intr.
-+              unsigned int    hwfq_empty      : 1;    // bit 1        Hardware Free Queue Empty Intr.
-+              unsigned int    swfq_empty      : 1;    // bit 0        Software Free Queue Empty Intr.
-+#else
-+#endif
-+              unsigned int    swfq_empty      : 1;    // bit 0        Software Free Queue Empty Intr.
-+              unsigned int    hwfq_empty      : 1;    // bit 1        Hardware Free Queue Empty Intr.
-+              unsigned int    class_qf_int: 14;       // bit 15:2 Classification Rx Queue13-0 Full Intr.
-+              GMAC_INTR_T             gmac0;
-+              GMAC_INTR_T             gmac1;
-+      } bits;
-+} INTR_REG4_T;
-+
-+#define GMAC1_RESERVED_INT_BIT                BIT(31)
-+#define GMAC1_MIB_INT_BIT                     BIT(30)
-+#define GMAC1_RX_PAUSE_ON_INT_BIT     BIT(29)
-+#define GMAC1_TX_PAUSE_ON_INT_BIT     BIT(28)
-+#define GMAC1_RX_PAUSE_OFF_INT_BIT    BIT(27)
-+#define GMAC1_TX_PAUSE_OFF_INT_BIT    BIT(26)
-+#define GMAC1_RX_OVERRUN_INT_BIT      BIT(25)
-+#define GMAC1_STATUS_CHANGE_INT_BIT   BIT(24)
-+#define GMAC0_RESERVED_INT_BIT                BIT(23)
-+#define GMAC0_MIB_INT_BIT                     BIT(22)
-+#define GMAC0_RX_PAUSE_ON_INT_BIT     BIT(21)
-+#define GMAC0_TX_PAUSE_ON_INT_BIT     BIT(20)
-+#define GMAC0_RX_PAUSE_OFF_INT_BIT    BIT(19)
-+#define GMAC0_TX_PAUSE_OFF_INT_BIT    BIT(18)
-+#define GMAC0_RX_OVERRUN_INT_BIT      BIT(17)
-+#define GMAC0_STATUS_CHANGE_INT_BIT   BIT(16)
-+#define CLASS_RX_FULL_INT_BIT(x)      BIT((x+2))
-+#define HWFQ_EMPTY_INT_BIT                    BIT(1)
-+#define SWFQ_EMPTY_INT_BIT                    BIT(0)
-+
-+#if 1
-+#define GMAC0_INT_BITS                                (GMAC0_MIB_INT_BIT)
-+#define GMAC1_INT_BITS                                (GMAC1_MIB_INT_BIT)
-+#else
-+#define GMAC0_INT_BITS                                (GMAC0_RESERVED_INT_BIT | GMAC0_MIB_INT_BIT | \
-+                                                                       GMAC0_RX_PAUSE_ON_INT_BIT | GMAC0_TX_PAUSE_ON_INT_BIT |        \
-+                                                                       GMAC0_RX_PAUSE_OFF_INT_BIT | GMAC0_TX_PAUSE_OFF_INT_BIT |      \
-+                                                                       GMAC0_RX_OVERRUN_INT_BIT | GMAC0_STATUS_CHANGE_INT_BIT)
-+#define GMAC1_INT_BITS                                (GMAC1_RESERVED_INT_BIT | GMAC1_MIB_INT_BIT | \
-+                                                                       GMAC1_RX_PAUSE_ON_INT_BIT | GMAC1_TX_PAUSE_ON_INT_BIT |        \
-+                                                                       GMAC1_RX_PAUSE_OFF_INT_BIT | GMAC1_TX_PAUSE_OFF_INT_BIT |      \
-+                                                                       GMAC1_RX_OVERRUN_INT_BIT | GMAC1_STATUS_CHANGE_INT_BIT)
-+#endif
-+
-+#define CLASS_RX_FULL_INT_BITS                0xfffc
-+
-+/**********************************************************************
-+ * GLOBAL_QUEUE_THRESHOLD_REG         (offset 0x0070)
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_0070_2
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    toe_class       : 8;    // 31:24
-+              unsigned int    intrq           : 8;    // 23:16
-+              unsigned int    hwfq_empty      : 8;    // 15:8         Hardware Free Queue Empty Threshold
-+              unsigned int    swfq_empty      : 8;    //  7:0         Software Free Queue Empty Threshold
-+#else
-+#endif
-+              unsigned int    swfq_empty      : 8;    //  7:0         Software Free Queue Empty Threshold
-+              unsigned int    hwfq_empty      : 8;    // 15:8         Hardware Free Queue Empty Threshold
-+              unsigned int    intrq           : 8;    // 23:16
-+              unsigned int    toe_class       : 8;    // 31:24
-+      } bits;
-+} QUEUE_THRESHOLD_T;
-+
-+
-+/**********************************************************************
-+ * GMAC DMA Control Register
-+ * GMAC0 offset 0x8000
-+ * GMAC1 offset 0xC000
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8000
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    rd_enable               : 1;    // bit 31       Rx DMA Enable
-+              unsigned int    td_enable               : 1;    // bit 30       Tx DMA Enable
-+              unsigned int    loopback                : 1;    // bit 29       Loopback TxDMA to RxDMA
-+              unsigned int    drop_small_ack  : 1;    // bit 28       1: Drop, 0: Accept
-+              unsigned int    reserved                : 10;   // bit 27:18
-+              unsigned int    rd_insert_bytes : 2;    // bit 17:16
-+              unsigned int    rd_prot                 : 4;    // bit 15:12 DMA Protection Control
-+              unsigned int    rd_burst_size   : 2;    // bit 11:10 DMA max burst size for every AHB request
-+              unsigned int    rd_bus              : 2;        // bit 9:8      Peripheral Bus Width
-+              unsigned int    td_prot                 : 4;    // bit 7:4  TxDMA protection control
-+              unsigned int    td_burst_size   : 2;    // bit 3:2      TxDMA max burst size for every AHB request
-+              unsigned int    td_bus              : 2;        // bit 1:0  Peripheral Bus Width
-+#else
-+              unsigned int    td_bus              : 2;        // bit 1:0  Peripheral Bus Width
-+              unsigned int    td_burst_size   : 2;    // bit 3:2      TxDMA max burst size for every AHB request
-+              unsigned int    td_prot                 : 4;    // bit 7:4  TxDMA protection control
-+              unsigned int    rd_bus              : 2;        // bit 9:8      Peripheral Bus Width
-+              unsigned int    rd_burst_size   : 2;    // bit 11:10 DMA max burst size for every AHB request
-+              unsigned int    rd_prot                 : 4;    // bit 15:12 DMA Protection Control
-+              unsigned int    rd_insert_bytes : 2;    // bit 17:16
-+              unsigned int    reserved                : 10;   // bit 27:18
-+              unsigned int    drop_small_ack  : 1;    // bit 28       1: Drop, 0: Accept
-+              unsigned int    loopback                : 1;    // bit 29       Loopback TxDMA to RxDMA
-+              unsigned int    td_enable               : 1;    // bit 30       Tx DMA Enable
-+              unsigned int    rd_enable               : 1;    // bit 31       Rx DMA Enable
-+#endif
-+      } bits;
-+} GMAC_DMA_CTRL_T;
-+
-+/**********************************************************************
-+ * GMAC Tx Weighting Control Register 0
-+ * GMAC0 offset 0x8004
-+ * GMAC1 offset 0xC004
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8004
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    reserved                : 8;    // bit 31:24
-+              unsigned int    hw_tq3                  : 6;    // bit 23:18    HW TX Queue 0
-+              unsigned int    hw_tq2                  : 6;    // bit 17:12    HW TX Queue 1
-+              unsigned int    hw_tq1                  : 6;    // bit 11:6             HW TX Queue 2
-+              unsigned int    hw_tq0                  : 6;    // bit 5:0              HW TX Queue 3
-+#else
-+              unsigned int    hw_tq0                  : 6;    // bit 5:0              HW TX Queue 3
-+              unsigned int    hw_tq1                  : 6;    // bit 11:6             HW TX Queue 2
-+              unsigned int    hw_tq2                  : 6;    // bit 17:12    HW TX Queue 1
-+              unsigned int    hw_tq3                  : 6;    // bit 23:18    HW TX Queue 0
-+              unsigned int    reserved                : 8;    // bit 31:24
-+#endif
-+      } bits;
-+} GMAC_TX_WCR0_T;     // Weighting Control Register 0
-+
-+/**********************************************************************
-+ * GMAC Tx Weighting Control Register 1
-+ * GMAC0 offset 0x8008
-+ * GMAC1 offset 0xC008
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8008
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    reserved                : 2;    // bit 31:30
-+              unsigned int    sw_tq5                  : 5;    // bit 29:25    SW TX Queue 5
-+              unsigned int    sw_tq4                  : 5;    // bit 24:20    SW TX Queue 4
-+              unsigned int    sw_tq3                  : 5;    // bit 19:15    SW TX Queue 3
-+              unsigned int    sw_tq2                  : 5;    // bit 14:10    SW TX Queue 2
-+              unsigned int    sw_tq1                  : 5;    // bit 9:5              SW TX Queue 1
-+              unsigned int    sw_tq0                  : 5;    // bit 4:0              SW TX Queue 0
-+#else
-+              unsigned int    sw_tq0                  : 5;    // bit 4:0              SW TX Queue 0
-+              unsigned int    sw_tq1                  : 5;    // bit 9:5              SW TX Queue 1
-+              unsigned int    sw_tq2                  : 5;    // bit 14:10    SW TX Queue 2
-+              unsigned int    sw_tq3                  : 5;    // bit 19:15    SW TX Queue 3
-+              unsigned int    sw_tq4                  : 5;    // bit 24:20    SW TX Queue 4
-+              unsigned int    sw_tq5                  : 5;    // bit 29:25    SW TX Queue 5
-+              unsigned int    reserved                : 2;    // bit 31:30
-+#endif
-+      } bits;
-+} GMAC_TX_WCR1_T;     // Weighting Control Register 1
-+
-+/**********************************************************************
-+ * Queue Read/Write Pointer
-+ * GMAC SW TX Queue 0~5 Read/Write Pointer register
-+ * GMAC0 offset 0x800C ~ 0x8020
-+ * GMAC1 offset 0xC00C ~ 0xC020
-+ * GMAC HW TX Queue 0~3 Read/Write Pointer register
-+ * GMAC0 offset 0x8024 ~ 0x8030
-+ * GMAC1 offset 0xC024 ~ 0xC030
-+ **********************************************************************/
-+// see DMA_RWPTR_T structure
-+
-+/**********************************************************************
-+ * GMAC DMA Tx First Description Address Register
-+ * GMAC0 offset 0x8038
-+ * GMAC1 offset 0xC038
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8038
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int td_first_des_ptr   : 28;   // bit 31:4     first descriptor address
-+              unsigned int td_busy                    :  1;   // bit 3        1: TxDMA busy; 0: TxDMA idle
-+              unsigned int reserved                   :  3;
-+#else
-+              unsigned int reserved                   :  3;
-+              unsigned int td_busy                    :  1;   // bit 3        1: TxDMA busy; 0: TxDMA idle
-+              unsigned int td_first_des_ptr   : 28;   // bit 31:4     first descriptor address
-+#endif
-+      } bits;
-+} GMAC_TXDMA_FIRST_DESC_T;
-+
-+/**********************************************************************
-+ * GMAC DMA Tx Current Description Address Register
-+ * GMAC0 offset 0x803C
-+ * GMAC1 offset 0xC03C
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_803C
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int td_curr_desc_ptr   : 28;   // bit 31:4     current descriptor address
-+              unsigned int reserved                   :  4;
-+#else
-+              unsigned int reserved                   :  4;
-+              unsigned int td_curr_desc_ptr   : 28;   // bit 31:4     current descriptor address
-+#endif
-+      } bits;
-+} GMAC_TXDMA_CURR_DESC_T;
-+
-+/**********************************************************************
-+ * GMAC DMA Tx Description Word 0 Register
-+ * GMAC0 offset 0x8040
-+ * GMAC1 offset 0xC040
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8040
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int reserved           : 1;    // bit 31
-+              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
-+              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
-+              unsigned int status_rvd         : 6;    // bit 28:23 Tx Status, Reserved bits
-+              unsigned int status_tx_ok       : 1;    // bit 22    Tx Status, 1: Successful 0: Failed
-+              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
-+              unsigned int buffer_size        : 16;   // bit 15:0  Transfer size
-+#else
-+              unsigned int buffer_size        : 16;   // bit 15:0  Transfer size
-+              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
-+              unsigned int status_tx_ok       : 1;    // bit 22    Tx Status, 1: Successful 0: Failed
-+              unsigned int status_rvd         : 6;    // bit 28:23 Tx Status, Reserved bits
-+              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
-+              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
-+              unsigned int reserved           : 1;    // bit 31
-+#endif
-+      } bits;
-+} GMAC_TXDESC_0_T;
-+
-+/**********************************************************************
-+ * GMAC DMA Tx Description Word 1 Register
-+ * GMAC0 offset 0x8044
-+ * GMAC1 offset 0xC044
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct txdesc_word1
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    reserved        : 9;    // bit 31:23    Tx Flag, Reserved
-+              unsigned int    ip_fixed_len: 1;        // bit 22
-+              unsigned int    bypass_tss      : 1;    // bit 21
-+              unsigned int    udp_chksum      : 1;    // bit 20               UDP Checksum Enable
-+              unsigned int    tcp_chksum      : 1;    // bit 19               TCP Checksum Enable
-+              unsigned int    ipv6_enable     : 1;    // bit 18               IPV6 Tx Enable
-+              unsigned int    ip_chksum       : 1;    // bit 17               IPV4 Header Checksum Enable
-+              unsigned int    mtu_enable      : 1;    // bit 16               TSS segmentation use MTU setting
-+              unsigned int    byte_count      : 16;   // bit 15: 0    Tx Frame Byte Count
-+#else
-+              unsigned int    byte_count      : 16;   // bit 15: 0    Tx Frame Byte Count
-+              unsigned int    mtu_enable      : 1;    // bit 16               TSS segmentation use MTU setting
-+              unsigned int    ip_chksum       : 1;    // bit 17               IPV4 Header Checksum Enable
-+              unsigned int    ipv6_enable     : 1;    // bit 18               IPV6 Tx Enable
-+              unsigned int    tcp_chksum      : 1;    // bit 19               TCP Checksum Enable
-+              unsigned int    udp_chksum      : 1;    // bit 20               UDP Checksum Enable
-+              unsigned int    bypass_tss      : 1;    // bit 21
-+              unsigned int    ip_fixed_len: 1;        // bit 22
-+              unsigned int    reserved        : 9;    // bit 31:23    Tx Flag, Reserved
-+#endif
-+      } bits;
-+} GMAC_TXDESC_1_T;
-+
-+#define TSS_IP_FIXED_LEN_BIT  BIT(22)
-+#define TSS_UDP_CHKSUM_BIT            BIT(20)
-+#define TSS_TCP_CHKSUM_BIT            BIT(19)
-+#define TSS_IPV6_ENABLE_BIT           BIT(18)
-+#define TSS_IP_CHKSUM_BIT             BIT(17)
-+#define TSS_MTU_ENABLE_BIT            BIT(16)
-+
-+/**********************************************************************
-+ * GMAC DMA Tx Description Word 2 Register
-+ * GMAC0 offset 0x8048
-+ * GMAC1 offset 0xC048
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int    bits32;
-+      unsigned int    buf_adr;
-+} GMAC_TXDESC_2_T;
-+
-+/**********************************************************************
-+ * GMAC DMA Tx Description Word 3 Register
-+ * GMAC0 offset 0x804C
-+ * GMAC1 offset 0xC04C
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct txdesc_word3
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
-+              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
-+              unsigned int    reserved        : 18;   // bit 28:11
-+              unsigned int    mtu_size        : 11;   // bit 10: 0    Tx Frame Byte Count
-+#else
-+              unsigned int    mtu_size        : 11;   // bit 10: 0    Tx Frame Byte Count
-+              unsigned int    reserved        : 18;   // bit 28:11
-+              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
-+              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
-+#endif
-+      } bits;
-+} GMAC_TXDESC_3_T;
-+#define SOF_EOF_BIT_MASK      0x3fffffff
-+#define SOF_BIT                               0x80000000
-+#define EOF_BIT                               0x40000000
-+#define EOFIE_BIT                     BIT(29)
-+#define MTU_SIZE_BIT_MASK     0x7ff
-+
-+/**********************************************************************
-+ * GMAC Tx Descriptor
-+ **********************************************************************/
-+typedef struct
-+{
-+      GMAC_TXDESC_0_T word0;
-+      GMAC_TXDESC_1_T word1;
-+      GMAC_TXDESC_2_T word2;
-+      GMAC_TXDESC_3_T word3;
-+} GMAC_TXDESC_T;
-+
-+
-+/**********************************************************************
-+ * GMAC DMA Rx First Description Address Register
-+ * GMAC0 offset 0x8058
-+ * GMAC1 offset 0xC058
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8058
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rd_first_des_ptr   : 28;   // bit 31:4 first descriptor address
-+              unsigned int rd_busy                    :  1;   // bit 3        1-RxDMA busy; 0-RxDMA idle
-+              unsigned int reserved                   :  3;   // bit 2:0
-+#else
-+              unsigned int reserved                   :  3;   // bit 2:0
-+              unsigned int rd_busy                    :  1;   // bit 3        1-RxDMA busy; 0-RxDMA idle
-+              unsigned int rd_first_des_ptr   : 28;   // bit 31:4 first descriptor address
-+#endif
-+      } bits;
-+} GMAC_RXDMA_FIRST_DESC_T;
-+
-+/**********************************************************************
-+ * GMAC DMA Rx Current Description Address Register
-+ * GMAC0 offset 0x805C
-+ * GMAC1 offset 0xC05C
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_805C
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rd_curr_des_ptr    : 28;   // bit 31:4 current descriptor address
-+              unsigned int reserved                   :  4;   // bit 3:0
-+#else
-+              unsigned int reserved                   :  4;   // bit 3:0
-+              unsigned int rd_curr_des_ptr    : 28;   // bit 31:4 current descriptor address
-+#endif
-+      } bits;
-+} GMAC_RXDMA_CURR_DESC_T;
-+
-+/**********************************************************************
-+ * GMAC DMA Rx Description Word 0 Register
-+ * GMAC0 offset 0x8060
-+ * GMAC1 offset 0xC060
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8060
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int drop                       : 1;    // bit 31        TOE/CIS Queue Full dropped packet to default queue
-+              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
-+              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
-+              unsigned int chksum_status      : 3;    // bit 28:26 Check Sum Status
-+              unsigned int status                     : 4;    // bit 24:22 Status of rx frame
-+              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
-+              unsigned int buffer_size        : 16;   // bit 15:0  number of descriptors used for the current frame
-+#else
-+              unsigned int buffer_size        : 16;   // bit 15:0  number of descriptors used for the current frame
-+              unsigned int desc_count         : 6;    // bit 21:16 number of descriptors used for the current frame
-+              unsigned int status                     : 4;    // bit 24:22 Status of rx frame
-+              unsigned int chksum_status      : 3;    // bit 28:26 Check Sum Status
-+              unsigned int perr                       : 1;    // bit 29        protocol error during processing this descriptor
-+              unsigned int derr                       : 1;    // bit 30        data error during processing this descriptor
-+              unsigned int drop                       : 1;    // bit 31        TOE/CIS Queue Full dropped packet to default queue
-+#endif
-+      } bits;
-+} GMAC_RXDESC_0_T;
-+
-+#define               GMAC_RXDESC_0_T_derr                            BIT(30)
-+#define               GMAC_RXDESC_0_T_perr                            BIT(29)
-+#define               GMAC_RXDESC_0_T_chksum_status(x)        BIT((x+26))
-+#define               GMAC_RXDESC_0_T_status(x)                       BIT((x+22))
-+#define               GMAC_RXDESC_0_T_desc_count(x)           BIT((x+16))
-+
-+#define       RX_CHKSUM_IP_UDP_TCP_OK                 0
-+#define       RX_CHKSUM_IP_OK_ONLY                    1
-+#define       RX_CHKSUM_NONE                                  2
-+#define       RX_CHKSUM_IP_ERR_UNKNOWN                4
-+#define       RX_CHKSUM_IP_ERR                                5
-+#define       RX_CHKSUM_TCP_UDP_ERR                   6
-+#define RX_CHKSUM_NUM                                 8
-+
-+#define RX_STATUS_GOOD_FRAME                  0
-+#define RX_STATUS_TOO_LONG_GOOD_CRC           1
-+#define RX_STATUS_RUNT_FRAME                  2
-+#define RX_STATUS_SFD_NOT_FOUND                       3
-+#define RX_STATUS_CRC_ERROR                           4
-+#define RX_STATUS_TOO_LONG_BAD_CRC            5
-+#define RX_STATUS_ALIGNMENT_ERROR             6
-+#define RX_STATUS_TOO_LONG_BAD_ALIGN  7
-+#define RX_STATUS_RX_ERR                              8
-+#define RX_STATUS_DA_FILTERED                 9
-+#define RX_STATUS_BUFFER_FULL                 10
-+#define RX_STATUS_NUM                                 16
-+
-+
-+/**********************************************************************
-+ * GMAC DMA Rx Description Word 1 Register
-+ * GMAC0 offset 0x8064
-+ * GMAC1 offset 0xC064
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct rxdesc_word1
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    sw_id           : 16;   // bit 31:16    Software ID
-+              unsigned int    byte_count      : 16;   // bit 15: 0    Rx Frame Byte Count
-+#else
-+              unsigned int    byte_count      : 16;   // bit 15: 0    Rx Frame Byte Count
-+              unsigned int    sw_id           : 16;   // bit 31:16    Software ID
-+#endif
-+      } bits;
-+} GMAC_RXDESC_1_T;
-+
-+/**********************************************************************
-+ * GMAC DMA Rx Description Word 2 Register
-+ * GMAC0 offset 0x8068
-+ * GMAC1 offset 0xC068
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int    bits32;
-+      unsigned int    buf_adr;
-+} GMAC_RXDESC_2_T;
-+
-+#define RX_INSERT_NONE                0
-+#define RX_INSERT_1_BYTE      1
-+#define RX_INSERT_2_BYTE      2
-+#define RX_INSERT_3_BYTE      3
-+
-+#define RX_INSERT_BYTES               RX_INSERT_2_BYTE
-+/**********************************************************************
-+ * GMAC DMA Rx Description Word 3 Register
-+ * GMAC0 offset 0x806C
-+ * GMAC1 offset 0xC06C
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct rxdesc_word3
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
-+              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
-+              unsigned int    ctrl_flag       : 1;    // bit 28               Control Flag is present
-+              unsigned int    out_of_seq      : 1;    // bit 27               Out of Sequence packet
-+              unsigned int    option          : 1;    // bit 26               IPV4 option or IPV6 extension header
-+              unsigned int    abnormal        : 1;    // bit 25               abnormal case found
-+              unsigned int    dup_ack         : 1;    // bit 24               Duplicated ACK detected
-+              unsigned int    l7_offset       : 8;    // bit 23: 16   L7 data offset
-+              unsigned int    l4_offset       : 8;    // bit 15: 8    L4 data offset
-+              unsigned int    l3_offset       : 8;    // bit 7: 0             L3 data offset
-+#else
-+              unsigned int    l3_offset       : 8;    // bit 7: 0             L3 data offset
-+              unsigned int    l4_offset       : 8;    // bit 15: 8    L4 data offset
-+              unsigned int    l7_offset       : 8;    // bit 23: 16   L7 data offset
-+              unsigned int    dup_ack         : 1;    // bit 24               Duplicated ACK detected
-+              unsigned int    abnormal        : 1;    // bit 25               abnormal case found
-+              unsigned int    option          : 1;    // bit 26               IPV4 option or IPV6 extension header
-+              unsigned int    out_of_seq      : 1;    // bit 27               Out of Sequence packet
-+              unsigned int    ctrl_flag       : 1;    // bit 28               Control Flag is present
-+              unsigned int    eofie           : 1;    // bit 29               End of frame interrupt enable
-+              unsigned int    sof_eof         : 2;    // bit 31:30    11: only one, 10: first, 01: last, 00: linking
-+#endif
-+      } bits;
-+} GMAC_RXDESC_3_T;
-+
-+/**********************************************************************
-+ * GMAC Rx Descriptor
-+ **********************************************************************/
-+typedef struct
-+{
-+      GMAC_RXDESC_0_T word0;
-+      GMAC_RXDESC_1_T word1;
-+      GMAC_RXDESC_2_T word2;
-+      GMAC_RXDESC_3_T word3;
-+} GMAC_RXDESC_T;
-+
-+/**********************************************************************
-+ * GMAC Hash Engine Enable/Action Register 0 Offset Register
-+ * GMAC0 offset 0x8070
-+ * GMAC1 offset 0xC070
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8070
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    mr1en           : 1;    // bit 31               Enable Matching Rule 1
-+              unsigned int    reserved1       : 1;    // bit 30
-+              unsigned int    timing          : 3;    // bit 29:27
-+              unsigned int    mr1_action      : 5;    // bit 26:22    Matching Rule 1 action offset
-+              unsigned int    mr1hel          : 6;    // bit 21:16    match rule 1 hash entry size
-+              unsigned int    mr0en           : 1;    // bit 15               Enable Matching Rule 0
-+              unsigned int    reserved0       : 4;    // bit 14:11
-+              unsigned int    mr0_action      : 5;    // bit 10:6             Matching Rule 0 action offset
-+              unsigned int    mr0hel          : 6;    // bit 5:0              match rule 0 hash entry size
-+#else
-+              unsigned int    mr0hel          : 6;    // bit 5:0              match rule 0 hash entry size
-+              unsigned int    mr0_action      : 5;    // bit 10:6             Matching Rule 0 action offset
-+              unsigned int    reserved0       : 4;    // bit 14:11
-+              unsigned int    mr0en           : 1;    // bit 15               Enable Matching Rule 0
-+              unsigned int    mr1hel          : 6;    // bit 21:16    match rule 1 hash entry size
-+              unsigned int    mr1_action      : 5;    // bit 26:22    Matching Rule 1 action offset
-+              unsigned int    timing          : 3;    // bit 29:27
-+              unsigned int    reserved1       : 1;    // bit 30
-+              unsigned int    mr1en           : 1;    // bit 31               Enable Matching Rule 1
-+#endif
-+      } bits;
-+} GMAC_HASH_ENABLE_REG0_T;
-+
-+/**********************************************************************
-+ * GMAC Hash Engine Enable/Action Register 1 Offset Register
-+ * GMAC0 offset 0x8074
-+ * GMAC1 offset 0xC074
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8074
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    mr3en           : 1;    // bit 31               Enable Matching Rule 3
-+              unsigned int    reserved3       : 4;    // bit 30:27
-+              unsigned int    mr3_action      : 5;    // bit 26:22    Matching Rule 3 action offset
-+              unsigned int    mr3hel          : 6;    // bit 21:16    match rule 3 hash entry size
-+              unsigned int    mr2en           : 1;    // bit 15               Enable Matching Rule 2
-+              unsigned int    reserved2       : 4;    // bit 14:11
-+              unsigned int    mr2_action      : 5;    // bit 10:6             Matching Rule 2 action offset
-+              unsigned int    mr2hel          : 6;    // bit 5:0              match rule 2 hash entry size
-+#else
-+              unsigned int    mr2hel          : 6;    // bit 5:0              match rule 2 hash entry size
-+              unsigned int    mr2_action      : 5;    // bit 10:6             Matching Rule 2 action offset
-+              unsigned int    reserved2       : 4;    // bit 14:11
-+              unsigned int    mr2en           : 1;    // bit 15               Enable Matching Rule 2
-+              unsigned int    mr3hel          : 6;    // bit 21:16    match rule 3 hash entry size
-+              unsigned int    mr3_action      : 5;    // bit 26:22    Matching Rule 3 action offset
-+              unsigned int    reserved1       : 4;    // bit 30:27
-+              unsigned int    mr3en           : 1;    // bit 31               Enable Matching Rule 3
-+#endif
-+      } bits;
-+} GMAC_HASH_ENABLE_REG1_T;
-+
-+
-+/**********************************************************************
-+ * GMAC Matching Rule Control Register 0
-+ * GMAC0 offset 0x8078
-+ * GMAC1 offset 0xC078
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8078
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    l2                      : 1;    // bit 31               L2 matching enable
-+              unsigned int    l3                      : 1;    // bit 30               L3 matching enable
-+              unsigned int    l4                      : 1;    // bit 29               L4 matching enable
-+              unsigned int    l7                      : 1;    // bit 28               L7 matching enable
-+              unsigned int    port            : 1;    // bit 27               PORT ID matching enable
-+              unsigned int    priority        : 3;    // bit 26:24    priority if multi-rules matched
-+              unsigned int    da                      : 1;    // bit 23               MAC DA enable
-+              unsigned int    sa                      : 1;    // bit 22               MAC SA enable
-+              unsigned int    ether_type      : 1;    // bit 21               Ethernet type enable
-+              unsigned int    vlan            : 1;    // bit 20               VLAN ID enable
-+              unsigned int    pppoe           : 1;    // bit 19               PPPoE Session ID enable
-+              unsigned int    reserved1       : 3;    // bit 18:16
-+              unsigned int    ip_version      : 1;    // bit 15               0: IPV4, 1: IPV6
-+              unsigned int    ip_hdr_len      : 1;    // bit 14               IPV4 Header length
-+              unsigned int    flow_lable      : 1;    // bit 13               IPV6 Flow label
-+              unsigned int    tos_traffic     : 1;    // bit 12               IPV4 TOS or IPV6 Traffice Class
-+              unsigned int    reserved2       : 4;    // bit 11:8
-+              unsigned int    sprx            : 8;    // bit 7:0              Support Protocol Register 7:0
-+#else
-+              unsigned int    sprx            : 8;    // bit 7:0              Support Protocol Register 7:0
-+              unsigned int    reserved2       : 4;    // bit 11:8
-+              unsigned int    tos_traffic     : 1;    // bit 12               IPV4 TOS or IPV6 Traffice Class
-+              unsigned int    flow_lable      : 1;    // bit 13               IPV6 Flow label
-+              unsigned int    ip_hdr_len      : 1;    // bit 14               IPV4 Header length
-+              unsigned int    ip_version      : 1;    // bit 15               0: IPV4, 1: IPV6
-+              unsigned int    reserved1       : 3;    // bit 18:16
-+              unsigned int    pppoe           : 1;    // bit 19               PPPoE Session ID enable
-+              unsigned int    vlan            : 1;    // bit 20               VLAN ID enable
-+              unsigned int    ether_type      : 1;    // bit 21               Ethernet type enable
-+              unsigned int    sa                      : 1;    // bit 22               MAC SA enable
-+              unsigned int    da                      : 1;    // bit 23               MAC DA enable
-+              unsigned int    priority        : 3;    // bit 26:24    priority if multi-rules matched
-+              unsigned int    port            : 1;    // bit 27               PORT ID matching enable
-+              unsigned int    l7                      : 1;    // bit 28               L7 matching enable
-+              unsigned int    l4                      : 1;    // bit 29               L4 matching enable
-+              unsigned int    l3                      : 1;    // bit 30               L3 matching enable
-+              unsigned int    l2                      : 1;    // bit 31               L2 matching enable
-+#endif
-+      } bits;
-+} GMAC_MRxCR0_T;
-+
-+#define MR_L2_BIT                     BIT(31)
-+#define MR_L3_BIT                     BIT(30)
-+#define MR_L4_BIT                     BIT(29)
-+#define MR_L7_BIT                     BIT(28)
-+#define MR_PORT_BIT                   BIT(27)
-+#define MR_PRIORITY_BIT               BIT(26)
-+#define MR_DA_BIT                     BIT(23)
-+#define MR_SA_BIT                     BIT(22)
-+#define MR_ETHER_TYPE_BIT     BIT(21)
-+#define MR_VLAN_BIT                   BIT(20)
-+#define MR_PPPOE_BIT          BIT(19)
-+#define MR_IP_VER_BIT         BIT(15)
-+#define MR_IP_HDR_LEN_BIT     BIT(14)
-+#define MR_FLOW_LABLE_BIT     BIT(13)
-+#define MR_TOS_TRAFFIC_BIT    BIT(12)
-+#define MR_SPR_BIT(x)         BIT(x)
-+#define MR_SPR_BITS           0xff
-+
-+/**********************************************************************
-+ * GMAC Matching Rule Control Register 1
-+ * GMAC0 offset 0x807C
-+ * GMAC1 offset 0xC07C
-+ **********************************************************************/
-+ typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_807C
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    sip                     : 1;    // bit 31               Srce IP
-+              unsigned int    sip_netmask     : 7;    // bit 30:24    Srce IP net mask, number of mask bits
-+              unsigned int    dip                     : 1;    // bit 23               Dest IP
-+              unsigned int    dip_netmask     : 7;    // bit 22:16    Dest IP net mask, number of mask bits
-+              unsigned int    l4_byte0_15     : 16;   // bit 15: 0
-+#else
-+              unsigned int    l4_byte0_15     : 16;   // bit 15: 0
-+              unsigned int    dip_netmask     : 7;    // bit 22:16    Dest IP net mask, number of mask bits
-+              unsigned int    dip                     : 1;    // bit 23               Dest IP
-+              unsigned int    sip_netmask     : 7;    // bit 30:24    Srce IP net mask, number of mask bits
-+              unsigned int    sip                     : 1;    // bit 31               Srce IP
-+#endif
-+      } bits;
-+} GMAC_MRxCR1_T;
-+
-+/**********************************************************************
-+ * GMAC Matching Rule Control Register 2
-+ * GMAC0 offset 0x8080
-+ * GMAC1 offset 0xC080
-+ **********************************************************************/
-+ typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_8080
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    l4_byte16_24: 8;        // bit 31: 24
-+              unsigned int    l7_byte0_23     : 24;   // bit 23:0
-+#else
-+              unsigned int    l7_byte0_23     : 24;   // bit 23:0
-+              unsigned int    l4_byte16_24: 8;        // bit 31: 24
-+#endif
-+      } bits;
-+} GMAC_MRxCR2_T;
-+
-+
-+/**********************************************************************
-+ * GMAC Support registers
-+ * GMAC0 offset 0x80A8
-+ * GMAC1 offset 0xC0A8
-+ **********************************************************************/
-+ typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_80A8
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    reserved: 21;   // bit 31:11
-+              unsigned int    swap    : 3;    // bit 10:8             Swap
-+              unsigned int    protocol: 8;    // bit 7:0              Supported protocol
-+#else
-+              unsigned int    protocol: 8;    // bit 7:0              Supported protocol
-+              unsigned int    swap    : 3;    // bit 10:8             Swap
-+              unsigned int    reserved: 21;   // bit 31:11
-+#endif
-+      } bits;
-+} GMAC_SPR_T;
-+
-+/**********************************************************************
-+ * GMAC_AHB_WEIGHT registers
-+ * GMAC0 offset 0x80C8
-+ * GMAC1 offset 0xC0C8
-+ **********************************************************************/
-+ typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_80C8
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int    reserved                : 7;    // 31:25
-+              unsigned int    tqDV_threshold  : 5;    // 24:20 DMA TqCtrl to Start tqDV FIFO Threshold
-+              unsigned int    pre_req                 : 5;    // 19:15 Rx Data Pre Request FIFO Threshold
-+              unsigned int    tx_weight               : 5;    // 14:10
-+              unsigned int    rx_weight               : 5;    // 9:5
-+              unsigned int    hash_weight             : 5;    // 4:0
-+#else
-+              unsigned int    hash_weight             : 5;    // 4:0
-+              unsigned int    rx_weight               : 5;    // 9:5
-+              unsigned int    tx_weight               : 5;    // 14:10
-+              unsigned int    pre_req                 : 5;    // 19:15 Rx Data Pre Request FIFO Threshold
-+              unsigned int    tqDV_threshold  : 5;    // 24:20 DMA TqCtrl to Start tqDV FIFO Threshold
-+              unsigned int    reserved                : 7;    // 31:25
-+#endif
-+      } bits;
-+} GMAC_AHB_WEIGHT_T;
-+/**********************************************************************
-+ * the register structure of GMAC
-+ **********************************************************************/
-+
-+/**********************************************************************
-+ * GMAC RX FLTR
-+ * GMAC0 Offset 0xA00C
-+ * GMAC1 Offset 0xE00C
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_000c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 27;
-+              unsigned int error                      :  1;   /* enable receive of all error frames */
-+              unsigned int promiscuous        :  1;   /* enable receive of all frames */
-+              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
-+              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
-+              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
-+#else
-+              unsigned int unicast            :  1;   /* enable receive of unicast frames that are sent to STA address */
-+              unsigned int multicast          :  1;   /* enable receive of multicast frames that pass multicast filter */
-+              unsigned int broadcast          :  1;   /* enable receive of broadcast frames */
-+              unsigned int promiscuous        :  1;   /* enable receive of all frames */
-+              unsigned int error                      :  1;   /* enable receive of all error frames */
-+              unsigned int                            : 27;
-+#endif
-+      } bits;
-+} GMAC_RX_FLTR_T;
-+
-+/**********************************************************************
-+ * GMAC Configuration 0
-+ * GMAC0 Offset 0xA018
-+ * GMAC1 Offset 0xE018
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0018
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int reserved           :  2;   // 31
-+              unsigned int port1_chk_classq :  1;     // 29
-+              unsigned int port0_chk_classq :  1;     // 28
-+              unsigned int port1_chk_toeq     :  1;   // 27
-+              unsigned int port0_chk_toeq     :  1;   // 26
-+              unsigned int port1_chk_hwq      :  1;   // 25
-+              unsigned int port0_chk_hwq      :  1;   // 24
-+              unsigned int rx_err_detect  :  1;       // 23
-+              unsigned int ipv6_exthdr_order: 1;      // 22
-+              unsigned int rxc_inv            :  1;   // 21
-+              unsigned int rgmm_edge          :  1;   // 20
-+        unsigned int rx_tag_remove  :  1;   /* 19: Remove Rx VLAN tag */
-+        unsigned int ipv6_rx_chksum :  1;   /* 18: IPv6 RX Checksum enable */
-+        unsigned int ipv4_rx_chksum :  1;   /* 17: IPv4 RX Checksum enable */
-+        unsigned int rgmii_en       :  1;   /* 16: RGMII in-band status enable */
-+              unsigned int tx_fc_en           :  1;   /* 15: TX flow control enable */
-+              unsigned int rx_fc_en           :  1;   /* 14: RX flow control enable */
-+              unsigned int sim_test           :  1;   /* 13: speed up timers in simulation */
-+              unsigned int dis_col            :  1;   /* 12: disable 16 collisions abort function */
-+              unsigned int dis_bkoff          :  1;   /* 11: disable back-off function */
-+              unsigned int max_len            :  3;   /* 8-10 maximum receive frame length allowed */
-+              unsigned int adj_ifg            :  4;   /* 4-7: adjust IFG from 96+/-56 */
-+        unsigned int flow_ctrl      :  1;   /* 3: flow control also trigged by Rx queues */
-+              unsigned int loop_back          :  1;   /* 2: transmit data loopback enable */
-+              unsigned int dis_rx                     :  1;   /* 1: disable receive */
-+              unsigned int dis_tx                     :  1;   /* 0: disable transmit */
-+#else
-+              unsigned int dis_tx                     :  1;   /* 0: disable transmit */
-+              unsigned int dis_rx                     :  1;   /* 1: disable receive */
-+              unsigned int loop_back          :  1;   /* 2: transmit data loopback enable */
-+        unsigned int flow_ctrl      :  1;   /* 3: flow control also trigged by Rx queues */
-+              unsigned int adj_ifg            :  4;   /* 4-7: adjust IFG from 96+/-56 */
-+              unsigned int max_len            :  3;   /* 8-10 maximum receive frame length allowed */
-+              unsigned int dis_bkoff          :  1;   /* 11: disable back-off function */
-+              unsigned int dis_col            :  1;   /* 12: disable 16 collisions abort function */
-+              unsigned int sim_test           :  1;   /* 13: speed up timers in simulation */
-+              unsigned int rx_fc_en           :  1;   /* 14: RX flow control enable */
-+              unsigned int tx_fc_en           :  1;   /* 15: TX flow control enable */
-+        unsigned int rgmii_en       :  1;   /* 16: RGMII in-band status enable */
-+        unsigned int ipv4_rx_chksum :  1;   /* 17: IPv4 RX Checksum enable */
-+        unsigned int ipv6_rx_chksum :  1;   /* 18: IPv6 RX Checksum enable */
-+        unsigned int rx_tag_remove  :  1;   /* 19: Remove Rx VLAN tag */
-+              unsigned int rgmm_edge          :  1;   // 20
-+              unsigned int rxc_inv            :  1;   // 21
-+              unsigned int ipv6_exthdr_order: 1;      // 22
-+              unsigned int rx_err_detect  :  1;       // 23
-+              unsigned int port0_chk_hwq      :  1;   // 24
-+              unsigned int port1_chk_hwq      :  1;   // 25
-+              unsigned int port0_chk_toeq     :  1;   // 26
-+              unsigned int port1_chk_toeq     :  1;   // 27
-+              unsigned int port0_chk_classq :  1;     // 28
-+              unsigned int port1_chk_classq :  1;     // 29
-+              unsigned int reserved           :  2;   // 31
-+#endif
-+      } bits;
-+} GMAC_CONFIG0_T;
-+
-+/**********************************************************************
-+ * GMAC Configuration 1
-+ * GMAC0 Offset 0xA01C
-+ * GMAC1 Offset 0xE01C
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_001c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int reserved           : 16;
-+              unsigned int rel_threshold      : 8;    /* flow control release threshold */
-+              unsigned int set_threshold      : 8;    /* flow control set threshold */
-+#else
-+              unsigned int set_threshold      : 8;    /* flow control set threshold */
-+              unsigned int rel_threshold      : 8;    /* flow control release threshold */
-+              unsigned int reserved           : 16;
-+#endif
-+      } bits;
-+} GMAC_CONFIG1_T;
-+
-+#define GMAC_FLOWCTRL_SET_MAX         32
-+#define GMAC_FLOWCTRL_SET_MIN         0
-+#define GMAC_FLOWCTRL_RELEASE_MAX     32
-+#define GMAC_FLOWCTRL_RELEASE_MIN     0
-+
-+/**********************************************************************
-+ * GMAC Configuration 2
-+ * GMAC0 Offset 0xA020
-+ * GMAC1 Offset 0xE020
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0020
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rel_threshold      : 16;   /* flow control release threshold */
-+              unsigned int set_threshold      : 16;   /* flow control set threshold */
-+#else
-+              unsigned int set_threshold      : 16;   /* flow control set threshold */
-+              unsigned int rel_threshold      : 16;   /* flow control release threshold */
-+#endif
-+      } bits;
-+} GMAC_CONFIG2_T;
-+
-+/**********************************************************************
-+ * GMAC Configuration 3
-+ * GMAC0 Offset 0xA024
-+ * GMAC1 Offset 0xE024
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_0024
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int rel_threshold      : 16;   /* flow control release threshold */
-+              unsigned int set_threshold      : 16;   /* flow control set threshold */
-+#else
-+              unsigned int set_threshold      : 16;   /* flow control set threshold */
-+              unsigned int rel_threshold      : 16;   /* flow control release threshold */
-+#endif
-+      } bits;
-+} GMAC_CONFIG3_T;
-+
-+
-+/**********************************************************************
-+ * GMAC STATUS
-+ * GMAC0 Offset 0xA02C
-+ * GMAC1 Offset 0xE02C
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit1_002c
-+      {
-+#if (BIG_ENDIAN==1)
-+              unsigned int                            : 25;
-+              unsigned int mii_rmii           :  2;   /* PHY interface type */
-+              unsigned int reserved           :  1;
-+              unsigned int duplex                     :  1;   /* duplex mode */
-+              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
-+              unsigned int link                       :  1;   /* link status */
-+#else
-+              unsigned int link                       :  1;   /* link status */
-+              unsigned int speed                      :  2;   /* link speed(00->2.5M 01->25M 10->125M) */
-+              unsigned int duplex                     :  1;   /* duplex mode */
-+              unsigned int reserved           :  1;
-+              unsigned int mii_rmii           :  2;   /* PHY interface type */
-+              unsigned int                            : 25;
-+#endif
-+      } bits;
-+} GMAC_STATUS_T;
-+
-+#define GMAC_SPEED_10                 0
-+#define GMAC_SPEED_100                        1
-+#define GMAC_SPEED_1000                       2
-+
-+#define GMAC_PHY_MII                  0
-+#define GMAC_PHY_GMII                 1
-+#define GMAC_PHY_RGMII_100            2
-+#define GMAC_PHY_RGMII_1000           3
-+
-+/**********************************************************************
-+ * Queue Header
-+ *    (1) TOE Queue Header
-+ *    (2) Non-TOE Queue Header
-+ *    (3) Interrupt Queue Header
-+ *
-+ * memory Layout
-+ *    TOE Queue Header
-+ *     0x60003000 +---------------------------+ 0x0000
-+ *                            |     TOE Queue 0 Header        |
-+ *                            |         8 * 4 Bytes       |
-+ *                            +---------------------------+ 0x0020
-+ *                            |     TOE Queue 1 Header        |
-+ *                            |         8 * 4 Bytes           |
-+ *                            +---------------------------+ 0x0040
-+ *                            |       ......                          |
-+ *                            |                                               |
-+ *                            +---------------------------+
-+ *
-+ *    Non TOE Queue Header
-+ *     0x60002000 +---------------------------+ 0x0000
-+ *                            |   Default Queue 0 Header  |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+ 0x0008
-+ *                            |   Default Queue 1 Header      |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+ 0x0010
-+ *                            |   Classification Queue 0      |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+
-+ *                            |   Classification Queue 1      |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+ (n * 8 + 0x10)
-+ *                            |               ...                             |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+ (13 * 8 + 0x10)
-+ *                            |   Classification Queue 13     |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+ 0x80
-+ *                            |      Interrupt Queue 0        |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+
-+ *                            |      Interrupt Queue 1        |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+
-+ *                            |      Interrupt Queue 2        |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+
-+ *                            |      Interrupt Queue 3        |
-+ *                            |         2 * 4 Bytes           |
-+ *                            +---------------------------+
-+ *
-+ **********************************************************************/
-+#define TOE_QUEUE_HDR_ADDR(n)         (TOE_TOE_QUE_HDR_BASE + n * 32)
-+#define TOE_Q_HDR_AREA_END                    (TOE_QUEUE_HDR_ADDR(TOE_TOE_QUEUE_MAX+1))
-+#define TOE_DEFAULT_Q0_HDR_BASE               (TOE_NONTOE_QUE_HDR_BASE + 0x00)
-+#define TOE_DEFAULT_Q1_HDR_BASE               (TOE_NONTOE_QUE_HDR_BASE + 0x08)
-+#define TOE_CLASS_Q_HDR_BASE          (TOE_NONTOE_QUE_HDR_BASE + 0x10)
-+#define TOE_INTR_Q_HDR_BASE                   (TOE_NONTOE_QUE_HDR_BASE + 0x80)
-+#define INTERRUPT_QUEUE_HDR_ADDR(n)   (TOE_INTR_Q_HDR_BASE + n * 8)
-+#define NONTOE_Q_HDR_AREA_END         (INTERRUPT_QUEUE_HDR_ADDR(TOE_INTR_QUEUE_MAX+1))
-+/**********************************************************************
-+ * TOE Queue Header Word 0
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      unsigned int base_size;
-+} TOE_QHDR0_T;
-+
-+#define TOE_QHDR0_BASE_MASK   (~0x0f)
-+
-+/**********************************************************************
-+ * TOE Queue Header Word 1
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_qhdr1
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int wptr                       : 16;   // bit 31:16
-+              unsigned int rptr                       : 16;   // bit 15:0
-+#else
-+              unsigned int rptr                       : 16;   // bit 15:0
-+              unsigned int wptr                       : 16;   // bit 31:16
-+#endif
-+      } bits;
-+} TOE_QHDR1_T;
-+
-+/**********************************************************************
-+ * TOE Queue Header Word 2
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_qhdr2
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int usd                        : 1;    // bit 31               0: if no data assembled yet
-+              unsigned int ctl                        : 1;    // bit 30               1: have control flag bits (except ack)
-+              unsigned int osq                        : 1;    // bit 29               1: out of sequence
-+              unsigned int sat                        : 1;    // bit 28               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
-+              unsigned int ip_opt                     : 1;    // bit 27               1: have IPV4 option or IPV6 Extension header
-+              unsigned int tcp_opt            : 1;    // bit 26               1: Have TCP option
-+              unsigned int abn                        : 1;    // bit 25               1: Abnormal case Found
-+              unsigned int dack                       : 1;    // bit 24               1: Duplicated ACK
-+              unsigned int reserved           : 7;    // bit 23:17
-+              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
-+#else
-+              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
-+              unsigned int reserved           : 7;    // bit 23:17
-+              unsigned int dack                       : 1;    // bit 24               1: Duplicated ACK
-+              unsigned int abn                        : 1;    // bit 25               1: Abnormal case Found
-+              unsigned int tcp_opt            : 1;    // bit 26               1: Have TCP option
-+              unsigned int ip_opt                     : 1;    // bit 27               1: have IPV4 option or IPV6 Extension header
-+              unsigned int sat                        : 1;    // bit 28               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
-+              unsigned int osq                        : 1;    // bit 29               1: out of sequence
-+              unsigned int ctl                        : 1;    // bit 30               1: have control flag bits (except ack)
-+              unsigned int usd                        : 1;    // bit 31               0: if no data assembled yet
-+#endif
-+      } bits;
-+} TOE_QHDR2_T;
-+
-+/**********************************************************************
-+ * TOE Queue Header Word 3
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      unsigned int seq_num;
-+} TOE_QHDR3_T;
-+
-+/**********************************************************************
-+ * TOE Queue Header Word 4
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      unsigned int ack_num;
-+} TOE_QHDR4_T;
-+
-+/**********************************************************************
-+ * TOE Queue Header Word 5
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_qhdr5
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int SeqCnt             : 16;   // bit 31:16
-+              unsigned int AckCnt             : 16;   // bit 15:0
-+#else
-+              unsigned int AckCnt             : 16;   // bit 15:0
-+              unsigned int SeqCnt             : 16;   // bit 31:16
-+#endif
-+      } bits;
-+} TOE_QHDR5_T;
-+
-+/**********************************************************************
-+ * TOE Queue Header Word 6
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_qhdr6
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int MaxPktSize : 14;   // bit 31:18
-+              unsigned int iq_num             : 2;    // bit 17:16
-+              unsigned int WinSize    : 16;   // bit 15:0
-+#else
-+              unsigned int WinSize    : 16;   // bit 15:0
-+              unsigned int iq_num             : 2;    // bit 17:16
-+              unsigned int MaxPktSize : 14;   // bit 31:18
-+#endif
-+      } bits;
-+} TOE_QHDR6_T;
-+
-+/**********************************************************************
-+ * TOE Queue Header Word 7
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_qhdr7
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int SeqThreshold       : 16;   // bit 31:16
-+              unsigned int AckThreshold       : 16;   // bit 15:0
-+#else
-+              unsigned int AckThreshold       : 16;   // bit 15:0
-+              unsigned int SeqThreshold       : 16;   // bit 31:16
-+#endif
-+      } bits;
-+} TOE_QHDR7_T;
-+
-+/**********************************************************************
-+ * TOE Queue Header
-+ **********************************************************************/
-+typedef struct
-+{
-+      TOE_QHDR0_T             word0;
-+      TOE_QHDR1_T             word1;
-+      TOE_QHDR2_T             word2;
-+      TOE_QHDR3_T             word3;
-+      TOE_QHDR4_T             word4;
-+      TOE_QHDR5_T             word5;
-+      TOE_QHDR6_T             word6;
-+      TOE_QHDR7_T             word7;
-+} TOE_QHDR_T;
-+
-+/**********************************************************************
-+ * NONTOE Queue Header Word 0
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      unsigned int base_size;
-+} NONTOE_QHDR0_T;
-+
-+#define NONTOE_QHDR0_BASE_MASK        (~0x0f)
-+
-+/**********************************************************************
-+ * NONTOE Queue Header Word 1
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_nonqhdr1
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int wptr                       : 16;   // bit 31:16
-+              unsigned int rptr                       : 16;   // bit 15:0
-+#else
-+              unsigned int rptr                       : 16;   // bit 15:0
-+              unsigned int wptr                       : 16;   // bit 31:16
-+#endif
-+      } bits;
-+} NONTOE_QHDR1_T;
-+
-+/**********************************************************************
-+ * Non-TOE Queue Header
-+ **********************************************************************/
-+typedef struct
-+{
-+      NONTOE_QHDR0_T          word0;
-+      NONTOE_QHDR1_T          word1;
-+} NONTOE_QHDR_T;
-+
-+/**********************************************************************
-+ * Interrupt Queue Header Word 0
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_intrqhdr0
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int wptr               : 16;   // bit 31:16    Write Pointer where hw stopped
-+              unsigned int win_size   : 16;   // bit 15:0     Descriptor Ring Size
-+#else
-+              unsigned int win_size   : 16;   // bit 15:0     Descriptor Ring Size
-+              unsigned int wptr               : 16;   // bit 31:16    Write Pointer where hw stopped
-+#endif
-+      } bits;
-+} INTR_QHDR0_T;
-+
-+/**********************************************************************
-+ * Interrupt Queue Header Word 1
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_intrqhdr1
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int ctl                        : 1;    // bit 31               1: have control flag bits (except ack)
-+              unsigned int osq                        : 1;    // bit 30               1: out of sequence
-+              unsigned int sat                        : 1;    // bit 29               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
-+              unsigned int ip_opt                     : 1;    // bit 28               1: have IPV4 option or IPV6 Extension header
-+              unsigned int tcp_opt            : 1;    // bit 27               1: Have TCP option
-+              unsigned int abn                        : 1;    // bit 26               1: Abnormal case Found
-+              unsigned int dack                       : 1;    // bit 25               1: Duplicated ACK
-+              unsigned int tcp_qid            : 8;    // bit 24:17    TCP Queue ID
-+              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
-+#else
-+              unsigned int TotalPktSize       : 17;   // bit 16: 0    Total packet size
-+              unsigned int tcp_qid            : 8;    // bit 24:17    TCP Queue ID
-+              unsigned int dack                       : 1;    // bit 25               1: Duplicated ACK
-+              unsigned int abn                        : 1;    // bit 26               1: Abnormal case Found
-+              unsigned int tcp_opt            : 1;    // bit 27               1: Have TCP option
-+              unsigned int ip_opt                     : 1;    // bit 28               1: have IPV4 option or IPV6 Extension header
-+              unsigned int sat                        : 1;    // bit 29               1: SeqCnt > SeqThreshold, or AckCnt > AckThreshold
-+              unsigned int osq                        : 1;    // bit 30               1: out of sequence
-+              unsigned int ctl                        : 1;    // bit 31               1: have control flag bits (except ack)
-+#endif
-+      } bits;
-+} INTR_QHDR1_T;
-+
-+/**********************************************************************
-+ * Interrupt Queue Header Word 2
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      unsigned int seq_num;
-+} INTR_QHDR2_T;
-+
-+/**********************************************************************
-+ * Interrupt Queue Header Word 3
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      unsigned int ack_num;
-+} INTR_QHDR3_T;
-+
-+/**********************************************************************
-+ * Interrupt Queue Header Word 4
-+ **********************************************************************/
-+typedef union
-+{
-+      unsigned int bits32;
-+      struct bit_intrqhdr4
-+      {
-+#if (BIG_ENDIAN==1)
-+
-+              unsigned int SeqCnt             : 16;   // bit 31:16    Seq# change since last seq# intr.
-+              unsigned int AckCnt             : 16;   // bit 15:0     Ack# change since last ack# intr.
-+#else
-+              unsigned int AckCnt             : 16;   // bit 15:0             Ack# change since last ack# intr.
-+              unsigned int SeqCnt             : 16;   // bit 31:16    Seq# change since last seq# intr.
-+#endif
-+      } bits;
-+} INTR_QHDR4_T;
-+
-+/**********************************************************************
-+ * Interrupt Queue Header
-+ **********************************************************************/
-+typedef struct
-+{
-+      INTR_QHDR0_T            word0;
-+      INTR_QHDR1_T            word1;
-+      INTR_QHDR2_T            word2;
-+      INTR_QHDR3_T            word3;
-+      INTR_QHDR4_T            word4;
-+      unsigned int            word5;
-+      unsigned int            word6;
-+      unsigned int            word7;
-+} INTR_QHDR_T;
-+
-+/**********************************************************************
-+ * GMAC Conf
-+ **********************************************************************/
-+typedef struct gmac_conf {
-+      struct net_device *dev;
-+      int portmap;
-+      int vid;
-+      int flag;     /* 1: active  0: non-active */
-+} sys_gmac_conf;
-+
-+/**********************************************************************
-+ * GMAC private data
-+ **********************************************************************/
-+typedef struct {
-+      unsigned int            rwptr_reg;
-+      unsigned int            desc_base;
-+      unsigned int            total_desc_num;
-+      unsigned short          finished_idx;
-+      GMAC_TXDESC_T           *curr_tx_desc;
-+      GMAC_TXDESC_T           *curr_finished_desc;
-+      struct sk_buff          *tx_skb[TX_DESC_NUM];
-+      unsigned long           total_sent;
-+      unsigned long           total_finished;
-+      unsigned long           intr_cnt;
-+} GMAC_SWTXQ_T;
-+
-+typedef struct {
-+      unsigned int            desc_base;
-+      unsigned long           eof_cnt;
-+} GMAC_HWTXQ_T;
-+
-+typedef struct gmac_private{
-+      struct net_device       *dev;
-+      unsigned int            existed;
-+      unsigned int            port_id;        // 0 or 1
-+      unsigned int            base_addr;
-+      unsigned int            dma_base_addr;
-+      unsigned char           *mac_addr1;
-+      unsigned char           *mac_addr2;
-+      unsigned int            swtxq_desc_base;
-+      unsigned int            hwtxq_desc_base;
-+      GMAC_SWTXQ_T            swtxq[TOE_SW_TXQ_NUM];
-+      GMAC_HWTXQ_T            hwtxq[TOE_HW_TXQ_NUM];
-+      NONTOE_QHDR_T           *default_qhdr;
-+      unsigned int            default_desc_base;
-+      unsigned int            default_desc_num;
-+      unsigned int            rx_curr_desc;
-+      DMA_RWPTR_T                     rx_rwptr;
-+      struct sk_buff          *curr_rx_skb;
-+      dma_addr_t                      default_desc_base_dma;
-+      dma_addr_t                      swtxq_desc_base_dma;
-+      dma_addr_t                      hwtxq_desc_base_dma;
-+      unsigned int            irq;
-+      unsigned int            flow_control_enable     ;
-+      unsigned int            pre_phy_status;
-+      unsigned int            full_duplex_cfg;
-+      unsigned int            speed_cfg;
-+      unsigned int            auto_nego_cfg;
-+      unsigned int            full_duplex_status;
-+      unsigned int            speed_status;
-+      unsigned int            phy_mode;       /* 0->MII 1->GMII 2->RGMII(10/100) 3->RGMII(1000) */
-+      unsigned int            phy_addr;
-+      unsigned int            intr0_enabled;  // 1: enabled
-+      unsigned int            intr1_enabled;  // 1: enabled
-+      unsigned int            intr2_enabled;  // 1: enabled
-+      unsigned int            intr3_enabled;  // 1: enabled
-+      unsigned int            intr4_enabled;  // 1: enabled
-+//    unsigned int            intr4_enabled_1;        // 1: enabled
-+      unsigned int            intr0_selected; // 1: selected
-+      unsigned int            intr1_selected; // 1: selected
-+      unsigned int            intr2_selected; // 1: selected
-+      unsigned int            intr3_selected; // 1: selected
-+      unsigned int            intr4_selected; // 1: selected
-+      // void                                 (*gmac_rcv_handler)(struct sk_buff *, int);
-+      struct net_device_stats ifStatics;
-+      unsigned long           txDerr_cnt[GMAC_NUM];
-+      unsigned long           txPerr_cnt[GMAC_NUM];
-+      unsigned long           RxDerr_cnt[GMAC_NUM];
-+      unsigned long           RxPerr_cnt[GMAC_NUM];
-+      unsigned int            isr_rx_cnt;
-+      unsigned int            isr_tx_cnt;
-+      unsigned long           rx_discard;
-+      unsigned long           rx_error;
-+      unsigned long           rx_mcast;
-+      unsigned long           rx_bcast;
-+      unsigned long           rx_status_cnt[8];
-+      unsigned long           rx_chksum_cnt[8];
-+      unsigned long           rx_sta1_ucast;  // for STA 1 MAC Address
-+      unsigned long           rx_sta2_ucast;  // for STA 2 MAC Address
-+      unsigned long           mib_full_cnt;
-+      unsigned long           rx_pause_on_cnt;
-+      unsigned long           tx_pause_on_cnt;
-+      unsigned long           rx_pause_off_cnt;
-+      unsigned long           tx_pause_off_cnt;
-+      unsigned long           rx_overrun_cnt;
-+      unsigned long           status_changed_cnt;
-+      unsigned long           default_q_cnt;
-+      unsigned long           hw_fq_empty_cnt;
-+      unsigned long           sw_fq_empty_cnt;
-+      unsigned long           default_q_intr_cnt;
-+      pid_t               thr_pid;
-+      wait_queue_head_t   thr_wait;
-+      struct completion   thr_exited;
-+    spinlock_t          lock;
-+    int                 time_to_die;
-+    int                                       operation;
-+#ifdef SL351x_GMAC_WORKAROUND
-+    unsigned long             short_frames_cnt;
-+#endif
-+}GMAC_INFO_T ;
-+
-+typedef struct toe_private {
-+      unsigned int    swfq_desc_base;
-+      unsigned int    hwfq_desc_base;
-+      unsigned int    hwfq_buf_base;
-+//    unsigned int    toe_desc_base[TOE_TOE_QUEUE_NUM];
-+//    unsigned int    toe_desc_num;
-+//    unsigned int    class_desc_base;
-+//    unsigned int    class_desc_num;
-+//    unsigned int    intr_desc_base;
-+//    unsigned int    intr_desc_num;
-+//    unsigned int    intr_buf_base;
-+      DMA_RWPTR_T             fq_rx_rwptr;
-+      GMAC_INFO_T             gmac[GMAC_NUM];
-+      dma_addr_t              sw_freeq_desc_base_dma;
-+      dma_addr_t              hw_freeq_desc_base_dma;
-+      dma_addr_t              hwfq_buf_base_dma;
-+      dma_addr_t              hwfq_buf_end_dma;
-+//    dma_addr_t              toe_desc_base_dma[TOE_TOE_QUEUE_NUM];
-+//    dma_addr_t              class_desc_base_dma;
-+//    dma_addr_t              intr_desc_base_dma;
-+//    dma_addr_t              intr_buf_base_dma;
-+//    unsigned long   toe_iq_intr_full_cnt[TOE_INTR_QUEUE_NUM];
-+//    unsigned long   toe_iq_intr_cnt[TOE_INTR_QUEUE_NUM];
-+//    unsigned long   toe_q_intr_full_cnt[TOE_TOE_QUEUE_NUM];
-+//    unsigned long   class_q_intr_full_cnt[TOE_CLASS_QUEUE_NUM];
-+//    unsigned long   class_q_intr_cnt[TOE_CLASS_QUEUE_NUM];
-+} TOE_INFO_T;
-+
-+extern TOE_INFO_T toe_private_data;
-+
-+#define GMAC_PORT0    0
-+#define GMAC_PORT1    1
-+/**********************************************************************
-+ * PHY Definition
-+ **********************************************************************/
-+#define HPHY_ADDR                     0x01
-+#define GPHY_ADDR                     0x02
-+
-+enum phy_state
-+{
-+    LINK_DOWN   = 0,
-+    LINK_UP     = 1
-+};
-+
-+/* transmit timeout value */
-+
-+#endif //_GMAC_SL351x_H
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/sl351x_hash_cfg.h
-@@ -0,0 +1,365 @@
-+/*-----------------------------------------------------------------------------------
-+*     sl351x_hash_cfg.h
-+*
-+*     Description:
-+*     
-+*     History:
-+*
-+*     9/14/2005       Gary Chen       Create
-+*
-+*-------------------------------------------------------------------------------------*/
-+#ifndef _SL351x_HASH_CFG_H_
-+#define _SL351x_HASH_CFG_H_   1
-+
-+// #define NAT_DEBUG_MSG      1
-+// #define DEBUG_NAT_MIXED_HW_SW_TX   1
-+#ifdef DEBUG_NAT_MIXED_HW_SW_TX
-+      // #define NAT_DEBUG_LAN_HASH_TIMEOUT   1
-+      // #define NAT_DEBUG_WAN_HASH_TIMEOUT   1
-+#endif
-+
-+#define IPIV(a,b,c,d)         ((a<<24)+(b<<16)+(c<<8)+d)
-+#define       IPIV1(a)                        ((a>>24)&0xff)
-+#define       IPIV2(a)                        ((a>>16)&0xff)
-+#define IPIV3(a)                      ((a>>8)&0xff)
-+#define IPIV4(a)                      ((a)&0xff)
-+
-+#define HASH_MAX_BYTES                        64      // 128
-+#define HASH_ACTION_DWORDS            9
-+#define HASH_MAX_DWORDS                       (HASH_MAX_BYTES / sizeof(u32))
-+#define HASH_MAX_KEY_DWORD            (HASH_MAX_DWORDS - HASH_ACTION_DWORDS)
-+#define HASH_INIT_KEY                 0x534C4F52
-+#define HASH_BITS                             12      // 12 : Normal, 7: Simulation
-+#define HASH_TOTAL_ENTRIES            (1 << HASH_BITS)
-+#define HASH_MAX_ENTRIES              (1 << 12)
-+#define HASH_TOE_ENTRIES              (HASH_TOTAL_ENTRIES >> 5)
-+#define HASH_BITS_MASK                        ((1 << HASH_BITS) - 1)
-+
-+#define hash_lock(lock)                       // spin_lock_bh(lock)
-+#define hash_unlock(lock)             // spin_unlock_bh(lock)
-+
-+/*----------------------------------------------------------------------
-+ *  special macro
-+ ----------------------------------------------------------------------*/
-+#define HASH_PUSH_WORD(cp, data)      {*cp++ = (((u16)(data))     ) & 0xff;   \
-+                                                                      *cp++ = (((u16)(data)) >> 8) & 0xff;} 
-+#define HASH_PUSH_DWORD(cp, data)     {*cp++ = (u8)(((u32)(data))      ) & 0xff;      \
-+                                                                      *cp++ = (u8)(((u32)(data)) >>  8) & 0xff;       \
-+                                                                      *cp++ = (u8)(((u32)(data)) >> 16) & 0xff;       \
-+                                                                      *cp++ = (u8)(((u32)(data)) >> 24) & 0xff;}
-+#define HASH_PUSH_BYTE(cp, data)      {*cp++ = ((u8)(data)) & 0xff;}
-+
-+/*----------------------------------------------------------------------
-+ *  key
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      u8              port;
-+      u16             Ethertype;
-+      u8              da[6];
-+      u8              sa[6];
-+      u16             pppoe_sid;      
-+      u16             vlan_id;        
-+      u8              ipv4_hdrlen;    
-+      u8              ip_tos; 
-+      u8              ip_protocol;    
-+      u32             ipv6_flow_label;
-+      u8              sip[16];
-+      u8              dip[16];
-+      //__u32                 sip[4];
-+      //__u32                 dip[4];
-+      u8              l4_bytes[24];
-+      u8              l7_bytes[24];
-+      u8              ipv6;   // 1: IPv6, 0: IPV4
-+} ENTRY_KEY_T;
-+
-+/*----------------------------------------------------------------------
-+ *  key for NAT
-+ *    Note: packed
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      u16             Ethertype;              // not used
-+      u8              port_id;
-+      u8              rule_id;
-+      u8              ip_protocol;
-+      u8              reserved1;              // ip_tos, not used
-+      u16             reserved2;              // not used
-+      u32             sip;
-+      u32             dip;
-+      u16             sport;
-+      u16             dport;
-+} NAT_KEY_T;
-+
-+#define NAT_KEY_DWORD_SIZE    (sizeof(NAT_KEY_T)/sizeof(u32))
-+#define NAT_KEY_SIZE          (sizeof(NAT_KEY_T))
-+
-+/*----------------------------------------------------------------------
-+ *  key for NAT
-+ *    Note: packed
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      u16             Ethertype;              // not used
-+      u8              port_id;
-+      u8              rule_id;
-+      u8              ip_protocol;
-+      u8              reserved1;              // ip_tos, not used
-+      u16             reserved2;              // not used
-+      u32             sip;
-+      u32             dip;
-+      u16             reserved3;
-+      u16             protocol;
-+      u16             reserved4;
-+      u16             call_id;
-+} GRE_KEY_T;
-+
-+#define GRE_KEY_DWORD_SIZE    (sizeof(GRE_KEY_T)/sizeof(u32))
-+#define GRE_KEY_SIZE          (sizeof(GRE_KEY_T))
-+/*----------------------------------------------------------------------
-+ *  key present or not
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      u32             port                    : 1;
-+      u32             Ethertype               : 1;
-+      u32             da                              : 1;
-+      u32             sa                              : 1;
-+      u32             pppoe_sid               : 1;    
-+      u32             vlan_id                 : 1;    
-+      u32             ipv4_hdrlen             : 1;    
-+      u32             ip_tos                  : 1;
-+      u32             ip_protocol             : 1;    
-+      u32             ipv6_flow_label : 1;
-+      u32             sip                             : 1;
-+      u32             dip                             : 1;
-+      u32             l4_bytes_0_3    : 1;
-+      u32             l4_bytes_4_7    : 1;
-+      u32             l4_bytes_8_11   : 1;
-+      u32             l4_bytes_12_15  : 1;
-+      u32             l4_bytes_16_19  : 1;
-+      u32             l4_bytes_20_23  : 1;
-+      u32             l7_bytes_0_3    : 1;
-+      u32             l7_bytes_4_7    : 1;
-+      u32             l7_bytes_8_11   : 1;
-+      u32             l7_bytes_12_15  : 1;
-+      u32             l7_bytes_16_19  : 1;
-+      u32             l7_bytes_20_23  : 1;
-+      u32             reserved                : 8;
-+} KEY_FIELD_T;
-+
-+/*----------------------------------------------------------------------
-+ *  action
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      u32             reserved0       : 5;    // bit 0:4
-+      u32             pppoe           : 2;    // bit 5:6
-+      u32             vlan            : 2;    // bit 7:8
-+      u32             sa                      : 1;    // bit 9
-+      u32             da                      : 1;    // bit 10
-+      u32             Dport           : 1;    // bit 11
-+      u32             Sport           : 1;    // bit 12
-+      u32             Dip                     : 1;    // bit 13
-+      u32             Sip                     : 1;    // bit 14
-+      u32             sw_id           : 1;    // bit 15
-+      u32             frag            : 1;    // bit 16
-+      u32             option          : 1;    // bit 17
-+      u32             ttl_0           : 1;    // bit 18
-+      u32             ttl_1           : 1;    // bit 19
-+      u32             mtu                     : 1;    // bit 20
-+      u32             exception       : 1;    // bit 21
-+      u32             srce_qid        : 1;    // bit 22
-+      u32             discard         : 1;    // bit 23
-+      u32             dest_qid        : 8;    // bit 24:31
-+} ENTRY_ACTION_T;
-+
-+#define ACTION_DISCARD_BIT            BIT(23)
-+#define ACTION_SRCE_QID_BIT           BIT(22)
-+#define ACTION_EXCEPTION_BIT  BIT(21)
-+#define ACTION_MTU_BIT                        BIT(20)
-+#define ACTION_TTL_1_BIT              BIT(19)
-+#define ACTION_TTL_0_BIT              BIT(18)
-+#define ACTION_IP_OPTION              BIT(17)
-+#define ACTION_FRAG_BIT                       BIT(16)
-+#define ACTION_SWID_BIT                       BIT(15)
-+#define ACTION_SIP_BIT                        BIT(14)
-+#define ACTION_DIP_BIT                        BIT(13)
-+#define ACTION_SPORT_BIT              BIT(12)
-+#define ACTION_DPORT_BIT              BIT(11)
-+#define ACTION_DA_BIT                 BIT(10)
-+#define ACTION_SA_BIT                 BIT(9)
-+#define ACTION_VLAN_DEL_BIT           BIT(8)
-+#define ACTION_VLAN_INS_BIT           BIT(7)
-+#define ACTION_PPPOE_DEL_BIT  BIT(6)
-+#define ACTION_PPPOE_INS_BIT  BIT(5)
-+#define ACTION_L4_THIRD_BIT           BIT(4)
-+#define ACTION_L4_FOURTH_BIT  BIT(3)
-+
-+#define NAT_ACTION_BITS                       (ACTION_SRCE_QID_BIT  | ACTION_EXCEPTION_BIT |  \
-+                                                              ACTION_TTL_1_BIT | ACTION_TTL_0_BIT |                   \
-+                                                              ACTION_IP_OPTION | ACTION_FRAG_BIT |                    \
-+                                                              ACTION_DA_BIT | ACTION_SA_BIT)
-+#define NAT_LAN2WAN_ACTIONS           (NAT_ACTION_BITS | ACTION_SIP_BIT | ACTION_SPORT_BIT)
-+#define NAT_WAN2LAN_ACTIONS           (NAT_ACTION_BITS | ACTION_DIP_BIT | ACTION_DPORT_BIT)
-+#define NAT_PPPOE_LAN2WAN_ACTIONS     (NAT_LAN2WAN_ACTIONS | ACTION_PPPOE_INS_BIT)
-+#define NAT_PPPOE_WAN2LAN_ACTIONS     (NAT_WAN2LAN_ACTIONS | ACTION_PPPOE_DEL_BIT)
-+#define NAT_PPTP_LAN2WAN_ACTIONS      (NAT_ACTION_BITS | ACTION_SIP_BIT | ACTION_L4_FOURTH_BIT)
-+#define NAT_PPTP_WAN2LAN_ACTIONS      (NAT_ACTION_BITS | ACTION_DIP_BIT | ACTION_L4_FOURTH_BIT)
-+#define NAT_PPPOE_PPTP_LAN2WAN_ACTIONS        (NAT_PPTP_LAN2WAN_ACTIONS | ACTION_PPPOE_INS_BIT)
-+#define NAT_PPPOE_PPTP_WAN2LAN_ACTIONS        (NAT_PPTP_WAN2LAN_ACTIONS | ACTION_PPPOE_DEL_BIT)
-+                                                              
-+/*----------------------------------------------------------------------
-+ *  parameter
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      u8              da[6];
-+      u8              sa[6];
-+      u16             vlan;   
-+      u16     pppoe;  
-+      u32             Sip;
-+      u32             Dip;
-+      u16     Sport;  
-+      u16     Dport;  
-+      u16     sw_id;  
-+      u16     mtu;    
-+} ENTRY_PARAM_T;
-+
-+/*----------------------------------------------------------------------
-+ *  Hash Entry
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      char                    rule;
-+      ENTRY_KEY_T             key;
-+      KEY_FIELD_T             key_present;
-+      ENTRY_ACTION_T  action;
-+      ENTRY_PARAM_T   param;
-+      int                             index;
-+      int                             total_dwords;
-+} HASH_ENTRY_T;
-+
-+/*----------------------------------------------------------------------
-+ *  NAT Hash Entry
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      short   counter;
-+      short   interval;
-+} HASH_TIMEOUT_T;
-+
-+/*----------------------------------------------------------------------
-+ *  NAT Hash Entry for TCP/UDP protocol
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      NAT_KEY_T                       key;
-+      union {
-+              u32                             dword;
-+              ENTRY_ACTION_T  bits;
-+      } action;
-+      ENTRY_PARAM_T           param;
-+      HASH_TIMEOUT_T          tmo;    // used by software only, to use memory space efficiently
-+} NAT_HASH_ENTRY_T;
-+
-+#define NAT_HASH_ENTRY_SIZE           (sizeof(NAT_HASH_ENTRY_T))
-+
-+/*----------------------------------------------------------------------
-+ *  GRE Hash Entry for PPTP/GRE protocol
-+ ----------------------------------------------------------------------*/
-+typedef struct {
-+      GRE_KEY_T                       key;
-+      union {
-+              u32                             dword;
-+              ENTRY_ACTION_T  bits;
-+      } action;
-+      ENTRY_PARAM_T           param;
-+      HASH_TIMEOUT_T          tmo;    // used by software only, to use memory space efficiently
-+} GRE_HASH_ENTRY_T;
-+
-+#define GRE_HASH_ENTRY_SIZE           (sizeof(GRE_HASH_ENTRY_T))
-+
-+/*----------------------------------------------------------------------
-+ *  External Variables
-+ ----------------------------------------------------------------------*/
-+extern char                           hash_tables[HASH_TOTAL_ENTRIES][HASH_MAX_BYTES] __attribute__ ((aligned(16)));
-+extern u32                            hash_nat_owner_bits[HASH_TOTAL_ENTRIES/32];
-+/*----------------------------------------------------------------------
-+* hash_get_valid_flag
-+*----------------------------------------------------------------------*/
-+static inline int hash_get_valid_flag(int index)
-+{
-+      volatile u32 *hash_valid_bits_ptr = (volatile u32 *)TOE_V_BIT_BASE;
-+
-+#ifdef SL351x_GMAC_WORKAROUND
-+      if (index >= (0x80 * 8) && index < (0x8c * 8))
-+              return 1;
-+#endif        
-+      return (hash_valid_bits_ptr[index/32] & (1 << (index %32)));
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_get_nat_owner_flag
-+*----------------------------------------------------------------------*/
-+static inline int hash_get_nat_owner_flag(int index)
-+{
-+      return (hash_nat_owner_bits[index/32] & (1 << (index %32)));
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_validate_entry
-+*----------------------------------------------------------------------*/
-+static inline void hash_validate_entry(int index)
-+{
-+      volatile u32    *hash_valid_bits_ptr = (volatile u32 *)TOE_V_BIT_BASE;
-+      register int    ptr = index/32, bits = 1 << (index %32);
-+      
-+      hash_valid_bits_ptr[ptr] |= bits;
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_invalidate_entry
-+*----------------------------------------------------------------------*/
-+static inline void hash_invalidate_entry(int index)
-+{
-+      volatile u32 *hash_valid_bits_ptr = (volatile u32 *)TOE_V_BIT_BASE;
-+      register int    ptr = index/32, bits = 1 << (index %32);
-+      
-+      hash_valid_bits_ptr[ptr] &= ~(bits);
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_nat_enable_owner
-+*----------------------------------------------------------------------*/
-+static inline void hash_nat_enable_owner(int index)
-+{
-+      hash_nat_owner_bits[index/32] |= (1 << (index % 32));
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_nat_disable_owner
-+*----------------------------------------------------------------------*/
-+static inline void hash_nat_disable_owner(int index)
-+{
-+      hash_nat_owner_bits[index/32] &= ~(1 << (index % 32));
-+}
-+
-+/*----------------------------------------------------------------------
-+* hash_get_entry
-+*----------------------------------------------------------------------*/
-+static inline void *hash_get_entry(int index)
-+{
-+      return (void*) &hash_tables[index][0];
-+}
-+
-+/*----------------------------------------------------------------------
-+* Functions
-+*----------------------------------------------------------------------*/
-+extern int hash_add_entry(HASH_ENTRY_T *entry);
-+extern void sl351x_hash_init(void);
-+extern void hash_set_valid_flag(int index, int valid);
-+extern void hash_set_nat_owner_flag(int index, int valid);
-+extern void *hash_get_entry(int index);
-+extern int hash_build_keys(u32 *destp, HASH_ENTRY_T *entry);
-+extern void hash_build_nat_keys(u32 *destp, HASH_ENTRY_T *entry);
-+extern int hash_write_entry(HASH_ENTRY_T *entry, u8 *key);
-+extern int hash_add_entry(HASH_ENTRY_T *entry);
-+extern        u16 hash_crc16(u16 crc, u8 *datap, u32 len);
-+extern        u16 hash_gen_crc16(u8 *datap, u32 len);
-+
-+#endif // _SL351x_HASH_CFG_H_
-+
-+
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/sl351x_nat_cfg.h
-@@ -0,0 +1,211 @@
-+/**************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.                
-+*--------------------------------------------------------------------------
-+*     sl_nat_cfg.h
-+*
-+*     Description:
-+*             - Define the Device Control Commands for NAT Configuration
-+*     
-+*     History:
-+*
-+*     4/28/2006       Gary Chen       Create
-+*
-+*-----------------------------------------------------------------------------*/
-+#ifndef _SL351x_NAT_CFG_H_
-+#define _SL351x_NAT_CFG_H_    1
-+
-+/*----------------------------------------------------------------------
-+* Confiuration
-+*----------------------------------------------------------------------*/
-+#ifdef CONFIG_NETFILTER
-+#define CONFIG_SL351x_NAT                     1
-+#undef CONFIG_SL351x_NAT
-+#undef CONFIG_SL351x_SYSCTL
-+#endif
-+#define CONFIG_NAT_MAX_IP_NUM         4       // per device (eth0 or eth1)
-+#define CONFIG_NAT_MAX_XPORT          64
-+#define CONFIG_NAT_MAX_WRULE          16      // per Queue
-+#define CONFIG_NAT_TXQ_NUM                    4
-+/*----------------------------------------------------------------------
-+* Command set
-+*----------------------------------------------------------------------*/
-+#define SIOCDEVSL351x SIOCDEVPRIVATE  // 0x89F0
-+#define NATSSTATUS            0
-+#define NATGSTATUS            1
-+#define NATSETPORT            2
-+#define NATGETPORT            3
-+#define NATADDIP              4
-+#define NATDELIP              5
-+#define NATGETIP              6
-+#define NATAXPORT             7
-+#define NATDXPORT             8
-+#define NATGXPORT             9
-+#define NATSWEIGHT            10
-+#define NATGWEIGHT            11
-+#define NATAWRULE             12
-+#define NATDWRULE             13
-+#define NATGWRULE             14
-+#define NATSDEFQ              15
-+#define NATGDEFQ              16
-+#define NATRMIPCFG            17              // remove IP config
-+#define NATTESTENTRY  18
-+#define NATSETMEM             19
-+#define NATSHOWMEM            20
-+/*----------------------------------------------------------------------
-+* Command Structure
-+*----------------------------------------------------------------------*/
-+// Common Header
-+typedef struct {
-+      unsigned short          cmd;    // command ID
-+      unsigned short          len;    // data length, excluding this header
-+} NATCMD_HDR_T;
-+
-+// NATSSTATUS & NATGSTATUS commands
-+typedef struct {
-+      unsigned char           enable;
-+} NAT_STATUS_T;       
-+
-+// NATSETPORT & NATGETPORT commands
-+typedef struct {
-+      unsigned char           portmap;
-+} NAT_PORTCFG_T;
-+
-+typedef struct {
-+      unsigned int            ipaddr;
-+      unsigned int            netmask;
-+} NAT_IP_ENTRY_T;
-+
-+// NATADDIP & NATDELIP commands
-+typedef struct {
-+      NAT_IP_ENTRY_T  entry;
-+} NAT_IPCFG_T;
-+
-+// NATGETIP command
-+typedef struct {
-+      unsigned int    total;
-+      NAT_IP_ENTRY_T  entry[CONFIG_NAT_MAX_IP_NUM];
-+} NAT_IPCFG_ALL_T;
-+
-+typedef struct {
-+      unsigned int            protocol;
-+      unsigned short          sport_start;
-+      unsigned short          sport_end;
-+      unsigned short          dport_start;
-+      unsigned short          dport_end;
-+} NAT_XPORT_ENTRY_T;
-+
-+// NATAXPORT & NATDXPORT Commands
-+typedef struct {
-+      NAT_XPORT_ENTRY_T       entry;
-+} NAT_XPORT_T;
-+
-+// NATGXPORT Command
-+typedef struct {
-+      unsigned int            total;
-+      NAT_XPORT_ENTRY_T       entry[CONFIG_NAT_MAX_XPORT];
-+} NAT_XPORT_ALL_T;
-+
-+// NATSWEIGHT & NATGWEIGHT Commands
-+typedef struct {
-+      unsigned char           weight[CONFIG_NAT_TXQ_NUM];
-+} NAT_WEIGHT_T;
-+
-+typedef struct {
-+      unsigned int            protocol;
-+      unsigned int            sip_start;
-+      unsigned int            sip_end;
-+      unsigned int            dip_start;
-+      unsigned int            dip_end;
-+      unsigned short          sport_start;
-+      unsigned short          sport_end;
-+      unsigned short          dport_start;
-+      unsigned short          dport_end;
-+} NAT_WRULE_ENTRY_T;  
-+
-+// NATAWRULE & NATDWRULE Commands
-+typedef struct {
-+      unsigned int            qid;
-+      NAT_WRULE_ENTRY_T       entry;
-+} NAT_WRULE_T;
-+
-+// NATGWRULE Command
-+typedef struct {
-+      unsigned int            total;
-+      NAT_WRULE_ENTRY_T       entry[CONFIG_NAT_MAX_WRULE];
-+} NAT_WRULE_ALL_T;
-+
-+// NATSDEFQ & NATGDEFQ commands
-+typedef struct {
-+      unsigned int            qid;
-+} NAT_QUEUE_T;        
-+
-+// NATTESTENTRY 
-+typedef struct {
-+      u_int16_t               cmd;    // command ID
-+      u_int16_t               len;    // data length, excluding this header
-+      u_int8_t                init_enable;
-+} NAT_TESTENTRY_T;    
-+      
-+typedef union
-+{
-+      NAT_STATUS_T            status;
-+      NAT_PORTCFG_T           portcfg;
-+      NAT_IPCFG_T                     ipcfg;
-+      NAT_XPORT_T                     xport;
-+      NAT_WEIGHT_T            weight;
-+      NAT_WRULE_T                     wrule;
-+      NAT_QUEUE_T                     queue;
-+      NAT_TESTENTRY_T init_entry;
-+} NAT_REQ_E;
-+      
-+/*----------------------------------------------------------------------
-+* NAT Configuration
-+*     - Used by driver only
-+*----------------------------------------------------------------------*/
-+typedef struct {
-+      unsigned int            enabled;
-+      unsigned int            init_enabled;
-+      unsigned int            tcp_udp_rule_id;
-+      unsigned int            gre_rule_id;
-+      unsigned int            lan_port;
-+      unsigned int            wan_port;
-+      unsigned int            default_hw_txq;
-+      short                           tcp_tmo_interval;
-+      short                           udp_tmo_interval;
-+      short                           gre_tmo_interval;
-+      NAT_IPCFG_ALL_T         ipcfg[2];       // LAN/WAN port
-+      NAT_XPORT_ALL_T         xport;
-+      NAT_WEIGHT_T            weight;
-+      NAT_WRULE_ALL_T         wrule[CONFIG_NAT_TXQ_NUM];
-+} NAT_CFG_T;
-+
-+/*----------------------------------------------------------------------
-+* NAT Control Block
-+*     - Used by driver only
-+*     - Stores LAN-IN or WAN-IN information
-+*     - WAN-OUT and LAN-OUT driver use them to build up a hash entry
-+*     - NOTES: To update this data structure, MUST take care of alignment issue
-+*   -          MUST make sure that the size of skbuff structure must 
-+*            be larger than (40 + sizof(NAT_CB_T))
-+*----------------------------------------------------------------------*/
-+typedef struct {
-+      unsigned short          tag;
-+      unsigned char           sa[6];
-+      unsigned int            sip;
-+      unsigned int            dip;
-+      unsigned short          sport;
-+      unsigned short          dport;
-+      unsigned char           pppoe_frame;
-+      unsigned char           state;                  // same to enum tcp_conntrack
-+      unsigned char           reserved[2];
-+} NAT_CB_T;
-+
-+#define NAT_CB_TAG            0x4C53  // "SL"
-+#define NAT_CB_SIZE           sizeof(NAT_CB_T)
-+// #define NAT_SKB_CB(skb)    (NAT_CB_T *)(((unsigned int)&((skb)->cb[40]) + 3) & ~3)  // for align 4
-+#define NAT_SKB_CB(skb)       (NAT_CB_T *)&((skb)->cb[40])  // for align 4
-+
-+#endif // _SL351x_NAT_CFG_H_
-+
-+
-+
---- /dev/null
-+++ b/include/asm-arm/arch-sl2312/sl351x_toe.h
-@@ -0,0 +1,88 @@
-+/**************************************************************************
-+* Copyright 2006 StorLink Semiconductors, Inc.  All rights reserved.
-+*--------------------------------------------------------------------------
-+* Name                        : sl351x_toe.h
-+* Description :
-+*             Define for TOE driver of Storlink SL351x
-+*
-+* History
-+*
-+*     Date            Writer          Description
-+*----------------------------------------------------------------------------
-+*                             Xiaochong       Create
-+*
-+****************************************************************************/
-+#ifndef __SL351x_TOE_H
-+#define __SL351x_TOE_H        1
-+#include <net/sock.h>
-+#include <asm/arch/sl351x_gmac.h>
-+#include <linux/timer.h>
-+#include <linux/netdevice.h>
-+#include <linux/ip.h>
-+#include <linux/if_ether.h>
-+/*
-+ * TOE_CONN_T is data structure of tcp connection info, used at both
-+ * device layer and kernel tcp layer
-+ * skb is the jumbo frame
-+ */
-+
-+struct toe_conn{
-+      __u8    qid;            // connection qid 0~63.
-+      __u8    ip_ver;         // 0: not used; 4: ipv4; 6: ipv6.
-+      /* hash key of the connection */
-+      __u16   source;
-+      __u16   dest;
-+      __u32   saddr[4];
-+      __u32   daddr[4];
-+
-+      __u32   seq;
-+      __u32   ack_seq;
-+
-+      /* these fields are used to set TOE QHDR */
-+      __u32   ack_threshold;
-+      __u32   seq_threshold;
-+      __u16   max_pktsize;
-+
-+      /* used by sw toe, accumulated ack_seq of ack frames */
-+      __u16   ack_cnt;
-+      /* used by sw toe, accumulated data frames held at driver */
-+      __u16   cur_pktsize;
-+
-+      __u8    status;
-+#define       TCP_CONN_UNDEFINE               0X00
-+#define       TCP_CONN_CREATION               0X01
-+#define       TCP_CONN_CONNECTING             0X02
-+#define       TCP_CONN_ESTABLISHED    0X04
-+#define       TCP_CONN_RESET                  0X08    // this is used for out-of-order
-+                                                      // or congestion window is small
-+#define       TCP_CONN_CLOSING                0X10
-+#define       TCP_CONN_CLOSED                 0x11
-+
-+      __u16   hash_entry_index;       /* associated hash entry */
-+
-+      // one timer per connection. Otherwise all connections should be scanned
-+      // in a timeout interrupt, and timeout interrupt is triggered no matter
-+      // a connection is actually timeout or not.
-+      struct timer_list       rx_timer;
-+      unsigned long           last_rx_jiffies;
-+      GMAC_INFO_T                     *gmac;
-+      struct net_device       *dev;
-+
-+      //      for generating pure ack frame.
-+      struct ethhdr           l2_hdr;
-+      struct iphdr            l3_hdr;
-+
-+      spinlock_t                      conn_lock;
-+      DMA_RWPTR_T                     toeq_rwptr;
-+      GMAC_RXDESC_T           *curr_desc;
-+      struct sk_buff          *curr_rx_skb;
-+};
-+
-+struct jumbo_frame {
-+      struct sk_buff  *skb0;          // the head of jumbo frame
-+      struct sk_buff  *tail;          // the tail of jumbo frame
-+      struct iphdr    *iphdr0;        // the ip hdr of skb0.
-+      struct tcphdr   *tcphdr0;       // the tcp hdr of skb0.
-+};
-+
-+#endif // __SL351x_TOE_H
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -2131,6 +2131,42 @@
-         The safe and default value for this is N.
-+config NET_GMAC
-+      tristate "Storlink Gigabit Ethernet support"
-+      depends on ARCH_SL2312
-+      help
-+        This driver supports Storlink dual Gigabit Ethernet.
-+
-+config NET_SL2312
-+      tristate "Storlink Gigabit Ethernet support"
-+      depends on NET_GMAC
-+      help
-+        This driver supports Storlink dual Gigabit Ethernet.
-+
-+config NET_SL351X
-+      tristate "Storlink Lepus Gigabit Ethernet support"
-+      depends on NET_GMAC
-+      help
-+        This driver supports Storlink TOE and NAT dual Gigabit Ethernet.
-+
-+config SL2312_TSO
-+      bool "Tx Segmentation Enable"
-+      depends on NET_GMAC
-+      help
-+        TBD
-+
-+config SL2312_MPAGE
-+      bool "Tx Multipage Enable"
-+      depends on NET_GMAC
-+      help
-+        TBD
-+
-+config SL2312_RECVFILE
-+      bool "Rx Multipage Enable"
-+      depends on NET_GMAC
-+      help
-+        TBD
-+
- config DL2K
-       tristate "D-Link DL2000-based Gigabit Ethernet support"
-       depends on PCI
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -236,4 +236,8 @@
- obj-$(CONFIG_FS_ENET) += fs_enet/
--obj-$(CONFIG_NETXEN_NIC) += netxen/
-+
-+obj-$(CONFIG_NET_SL351X)+= sl351x_gmac.o sl351x_nat.o sl351x_hash.o sl351x_crc16.o sl351x_proc.o sl_switch.o
-+obj-$(CONFIG_NET_SL2312)+= sl2312_emac.o
-+
-+
diff --git a/target/linux/storm/patches/1003-gmac_one_phy.patch b/target/linux/storm/patches/1003-gmac_one_phy.patch
deleted file mode 100644 (file)
index 15a69c9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/include/asm-arm/arch-sl2312/sl351x_gmac.h
-+++ b/include/asm-arm/arch-sl2312/sl351x_gmac.h
-@@ -21,7 +21,7 @@
- #undef BIG_ENDIAN
- #define BIG_ENDIAN                            0
- #define GMAC_DEBUG                            1
--#define GMAC_NUM                                      2
-+#define GMAC_NUM                                      1
- //#define     L2_jumbo_frame                          1
- #define _PACKED_                                      __attribute__ ((aligned(1), packed))
diff --git a/target/linux/storm/patches/1004-gmac-enable-napi.patch b/target/linux/storm/patches/1004-gmac-enable-napi.patch
deleted file mode 100644 (file)
index ea374c4..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
---- a/drivers/net/sl351x_gmac.c
-+++ b/drivers/net/sl351x_gmac.c
-@@ -68,9 +68,11 @@
- #include <linux/ip.h>
- #endif
-+/* Enables NAPI unconditionally */
-+#define CONFIG_SL_NAPI                                        1
-+
- // #define SL351x_TEST_WORKAROUND
- #ifdef CONFIG_SL351x_NAT
--#define CONFIG_SL_NAPI                                        1
- #endif
- #define GMAX_TX_INTR_DISABLED                 1
- #define DO_HW_CHKSUM                                  1
-@@ -124,12 +126,17 @@
-  *************************************************************/
- static int    gmac_initialized = 0;
- TOE_INFO_T toe_private_data;
--//static int          do_again = 0;
-+static int            do_again = 0;
- spinlock_t gmac_fq_lock;
- unsigned int FLAG_SWITCH;
- static unsigned int           next_tick = 3 * HZ;
--static unsigned char          eth_mac[CONFIG_MAC_NUM][6]= {{0x00,0x11,0x11,0x87,0x87,0x87}, {0x00,0x22,0x22,0xab,0xab,0xab}};
-+static unsigned char          eth_mac[CONFIG_MAC_NUM][6]= {
-+              {0x00,0x11,0x11,0x87,0x87,0x87},
-+#if GMAC_NUM != 1
-+              {0x00,0x22,0x22,0xab,0xab,0xab}
-+#endif
-+};
- #undef CONFIG_SL351x_RXTOE
- extern NAT_CFG_T nat_cfg;
-@@ -2443,7 +2450,8 @@
-       toe = (TOE_INFO_T *)&toe_private_data;
- //    handle NAPI
- #ifdef CONFIG_SL_NAPI
--if (storlink_ctl.pauseoff == 1)
-+      /* XXX: check this, changed from 'storlink_ctl.pauseoff == 1' to if (1) */
-+if (1)
- {
- /* disable GMAC interrupt */
-     //toe_gmac_disable_interrupt(tp->irq);
-@@ -2530,7 +2538,7 @@
-                               {
-                                       if (likely(netif_rx_schedule_prep(dev)))
-                               {
--                                      unsigned int data32;
-+                                      // unsigned int data32;
-                                       // disable GMAC-0 rx interrupt
-                                       // class-Q & TOE-Q are implemented in future
-                                       //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-@@ -2563,7 +2571,7 @@
-                       {
-                               if (likely(netif_rx_schedule_prep(dev)))
-                       {
--                              unsigned int data32;
-+                              // unsigned int data32;
-                               // disable GMAC-0 rx interrupt
-                               // class-Q & TOE-Q are implemented in future
-                               //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-@@ -4217,7 +4225,7 @@
-       GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
-       unsigned int            status4;
-       volatile DMA_RWPTR_T    fq_rwptr;
--      int                                     max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
-+      // int                                  max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
-       //unsigned long         rx_old_bytes;
-       struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
-       //unsigned long long    rx_time;
-@@ -4479,7 +4487,7 @@
-       if (rwptr.bits.rptr == rwptr.bits.wptr)
-       {
--              unsigned int data32;
-+              // unsigned int data32;
-                       //printk("%s:---[rwptr.bits.rptr == rwptr.bits.wptr]   rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
-           /* Receive descriptor is empty now */
diff --git a/target/linux/storm/patches/1005-gmac-napi-mask-intrs.patch b/target/linux/storm/patches/1005-gmac-napi-mask-intrs.patch
deleted file mode 100644 (file)
index f0b6375..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
---- a/drivers/net/sl351x_gmac.c
-+++ b/drivers/net/sl351x_gmac.c
-@@ -127,6 +127,7 @@
- static int    gmac_initialized = 0;
- TOE_INFO_T toe_private_data;
- static int            do_again = 0;
-+static int rx_poll_enabled;
- spinlock_t gmac_fq_lock;
- unsigned int FLAG_SWITCH;
-@@ -1065,7 +1066,8 @@
-           tp->intr3_enabled =         0xffffffff;
-           tp->intr4_selected =        GMAC0_INT_BITS | CLASS_RX_FULL_INT_BITS |
-                                                       HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
--          tp->intr4_enabled =         GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT;
-+          tp->intr4_enabled =         GMAC0_INT_BITS | SWFQ_EMPTY_INT_BIT| GMAC0_RX_OVERRUN_INT_BIT;
-+          // GMAC0_TX_PAUSE_OFF_INT_BIT| GMAC0_MIB_INT_BIT;
-           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) & ~tp->intr0_selected;
-           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
-@@ -1115,7 +1117,7 @@
-               tp->intr3_enabled       |=      0xffffffff;
-               tp->intr4_selected      |=      CLASS_RX_FULL_INT_BITS |
-                                                               HWFQ_EMPTY_INT_BIT | SWFQ_EMPTY_INT_BIT;
--              tp->intr4_enabled       |=      SWFQ_EMPTY_INT_BIT;
-+              tp->intr4_enabled       |=      SWFQ_EMPTY_INT_BIT | GMAC1_RX_OVERRUN_INT_BIT;
-               }
-           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) | tp->intr0_selected;
-           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
-@@ -2408,7 +2410,7 @@
-       // unsigned short max_cnt=TOE_SW_FREEQ_DESC_NUM>>1;
-       fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--      spin_lock_irqsave(&gmac_fq_lock, flags);
-+      // spin_lock_irqsave(&gmac_fq_lock, flags);
-       //while ((max_cnt--) && (unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
-       //                              TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
-       while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
-@@ -2428,10 +2430,47 @@
-               SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
-               toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
-       }
--      spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+      // spin_unlock_irqrestore(&gmac_fq_lock, flags);
- }
- // EXPORT_SYMBOL(toe_gmac_fill_free_q);
-+static void gmac_registers(const char *message)
-+{
-+      unsigned int            status0;
-+      unsigned int            status1;
-+      unsigned int            status2;
-+      unsigned int            status3;
-+      unsigned int            status4;
-+
-+      printk("%s\n", message);
-+
-+      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
-+      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
-+      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
-+      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+
-+      printk("status: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
-+                 status0, status1, status2, status3, status4);
-+
-+      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_0_REG);
-+      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_2_REG);
-+      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_3_REG);
-+      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+
-+      printk("mask  : s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
-+                 status0, status1, status2, status3, status4);
-+
-+      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
-+      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
-+      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
-+      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
-+      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+
-+      printk("select: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
-+                 status0, status1, status2, status3, status4);
-+}
- /*----------------------------------------------------------------------
- * toe_gmac_interrupt
- *----------------------------------------------------------------------*/
-@@ -2492,6 +2531,7 @@
-               writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
-       if (status4)
-               writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-+
- #if 0
-       /* handle freeq interrupt first */
-       if (status4 & tp->intr4_enabled) {
-@@ -2536,10 +2576,31 @@
-                       }
-                               if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
-                               {
--                                      if (likely(netif_rx_schedule_prep(dev)))
-+                                      if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
-                               {
--                                      // unsigned int data32;
--                                      // disable GMAC-0 rx interrupt
-+                                      unsigned int data32;
-+
-+                                              if (rx_poll_enabled)
-+                                                              gmac_registers("check #1");
-+
-+                                              BUG_ON(rx_poll_enabled == 1);
-+
-+#if 0
-+                                      /* Masks GMAC-0 rx interrupt */
-+                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                              data32 &= ~(DEFAULT_Q0_INT_BIT);
-+                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+
-+                                      /* Masks GMAC-0 queue empty interrupt */
-+                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+                                              data32 &= ~DEFAULT_Q0_INT_BIT;
-+                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+
-+                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+                                              data32 &= ~DEFAULT_Q0_INT_BIT;
-+                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+#endif
-+
-                                       // class-Q & TOE-Q are implemented in future
-                                       //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-                                       //data32 &= ~DEFAULT_Q0_INT_BIT;
-@@ -2549,7 +2610,8 @@
-                                               //tp->total_q_cnt_napi=0;
-                                               //rx_time = jiffies;
-                                               //rx_old_bytes = isPtr->rx_bytes;
--                              __netif_rx_schedule(dev);
-+                                              __netif_rx_schedule(dev);
-+                                              rx_poll_enabled = 1;
-                               }
-                       }
-               }
-@@ -2569,9 +2631,31 @@
-                       if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
-                       {
--                              if (likely(netif_rx_schedule_prep(dev)))
-+                              if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
-                       {
--                              // unsigned int data32;
-+                              unsigned int data32;
-+
-+                                      if (rx_poll_enabled)
-+                                                      gmac_registers("check #2");
-+
-+                                      BUG_ON(rx_poll_enabled == 1);
-+
-+#if 0
-+                                      /* Masks GMAC-1 rx interrupt */
-+                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                      data32 &= ~(DEFAULT_Q1_INT_BIT);
-+                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+
-+                              /* Masks GMAC-1 queue empty interrupt */
-+                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+                                      data32 &= ~DEFAULT_Q1_INT_BIT;
-+                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+
-+                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+                                      data32 &= ~DEFAULT_Q1_INT_BIT;
-+                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+#endif
-+
-                               // disable GMAC-0 rx interrupt
-                               // class-Q & TOE-Q are implemented in future
-                               //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-@@ -2583,9 +2667,13 @@
-                                       //rx_time = jiffies;
-                                       //rx_old_bytes = isPtr->rx_bytes;
-                               __netif_rx_schedule(dev);
-+                              rx_poll_enabled = 1;
-                       }
-                       }
-               }
-+      } else {
-+
-+              gmac_registers("check #3");
-       }
-       // Interrupt Status 0
-@@ -3306,8 +3394,10 @@
-               SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
-       tp->rx_rwptr.bits32 = rwptr.bits32;
--              toe_gmac_fill_free_q();
-       }
-+
-+      /* Handles first available packets only then refill the queue. */
-+      toe_gmac_fill_free_q();
- }
- /*----------------------------------------------------------------------
-@@ -4217,6 +4307,7 @@
-     GMAC_RXDESC_T     *curr_desc;
-       struct sk_buff          *skb;
-     DMA_RWPTR_T                       rwptr;
-+    unsigned int data32;
-       unsigned int            pkt_size;
-       unsigned int        desc_count;
-       unsigned int        good_frame, chksum_status, rx_status;
-@@ -4231,7 +4322,7 @@
-       //unsigned long long    rx_time;
--
-+      BUG_ON(rx_poll_enabled == 0);
- #if 1
-       if (do_again)
-       {
-@@ -4516,6 +4607,30 @@
- #endif
-         //toe_gmac_fill_free_q();
-         netif_rx_complete(dev);
-+
-+              rx_poll_enabled = 0;
-+
-+              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+              if (tp->port_id == 0)
-+                              data32 |= DEFAULT_Q0_INT_BIT;
-+              else
-+                              data32 |= DEFAULT_Q1_INT_BIT;
-+              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+
-+              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+              if (tp->port_id == 0)
-+                              data32 |= DEFAULT_Q0_INT_BIT;
-+              else
-+                              data32 |= DEFAULT_Q1_INT_BIT;
-+              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+
-+              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+              if (tp->port_id == 0)
-+                              data32 |= DEFAULT_Q0_INT_BIT;
-+              else
-+                              data32 |= DEFAULT_Q1_INT_BIT;
-+              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+
-         // enable GMAC-0 rx interrupt
-         // class-Q & TOE-Q are implemented in future
-         //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
diff --git a/target/linux/storm/patches/1006-gmac-napi-tx.patch b/target/linux/storm/patches/1006-gmac-napi-tx.patch
deleted file mode 100644 (file)
index 5861a65..0000000
+++ /dev/null
@@ -1,2094 +0,0 @@
---- a/drivers/net/sl351x_gmac.c
-+++ b/drivers/net/sl351x_gmac.c
-@@ -43,9 +43,13 @@
- #include <linux/mtd/kvctl.h>
-+#define GET_RPTR(x) ((x) & 0xFFFF)
-+#define GET_WPTR(x) ((x) >> 16)
-+
- #define        MIDWAY
- #define        SL_LEPUS
--#define VITESSE_G5SWITCH      1
-+// #define VITESSE_G5SWITCH   1
-+#undef VITESSE_G5SWITCH
- #ifndef CONFIG_SL351x_RXTOE
- //#define CONFIG_SL351x_RXTOE 1
-@@ -126,7 +130,6 @@
-  *************************************************************/
- static int    gmac_initialized = 0;
- TOE_INFO_T toe_private_data;
--static int            do_again = 0;
- static int rx_poll_enabled;
- spinlock_t gmac_fq_lock;
- unsigned int FLAG_SWITCH;
-@@ -190,7 +193,7 @@
- void mac_set_sw_tx_weight(struct net_device *dev, char *weight);
- void mac_get_hw_tx_weight(struct net_device *dev, char *weight);
- void mac_set_hw_tx_weight(struct net_device *dev, char *weight);
--static inline void toe_gmac_fill_free_q(void);
-+static inline void toe_gmac_fill_free_q(int count);
- #ifdef VITESSE_G5SWITCH
- extern int Get_Set_port_status(void);
-@@ -295,12 +298,14 @@
-       for(j = 0; i<CONFIG_MAC_NUM; j++)
-       {
-               i=j;
-+#ifdef VITESSE_G5SWITCH
-               if(Giga_switch){                // if gswitch present, swap eth0/1
-                       if(j==0)
-                               i=1;
-                       else if(j==1)
-                               i=0;
-               }
-+#endif
-               tp = (GMAC_INFO_T *)&toe_private_data.gmac[i];
-               tp->dev = NULL;
-@@ -459,7 +464,7 @@
-               toe->gmac[1].dma_base_addr = TOE_GMAC1_DMA_BASE;
-         toe->gmac[0].auto_nego_cfg = 1;
-         toe->gmac[1].auto_nego_cfg = 1;
--#ifdef CONFIG_SL3516_ASIC
-+#ifndef CONFIG_SL3516_ASIC
-         toe->gmac[0].speed_cfg = GMAC_SPEED_1000;
-         toe->gmac[1].speed_cfg = GMAC_SPEED_1000;
- #else
-@@ -508,7 +513,7 @@
-               // Write GLOBAL_QUEUE_THRESHOLD_REG
-               threshold.bits32 = 0;
-               threshold.bits.swfq_empty = (TOE_SW_FREEQ_DESC_NUM > 256) ? 255 :
--                                                      TOE_SW_FREEQ_DESC_NUM/2;
-+                                                      TOE_SW_FREEQ_DESC_NUM/16;
-               threshold.bits.hwfq_empty = (TOE_HW_FREEQ_DESC_NUM > 256) ? 256/4 :
-                                                       TOE_HW_FREEQ_DESC_NUM/4;
-               threshold.bits.toe_class = (TOE_TOE_DESC_NUM > 256) ? 256/4 :
-@@ -613,18 +618,25 @@
-       rwptr_reg.bits.rptr = 0;
-       toe->fq_rx_rwptr.bits32 = rwptr_reg.bits32;
-       writel(rwptr_reg.bits32, TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+      printk("SWFQ: %08X\n", readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG));
-       // SW Free Queue Descriptors
-       for (i=0; i<TOE_SW_FREEQ_DESC_NUM; i++)
-       {
-+              void *data = NULL;
-               sw_desc_ptr->word0.bits.buffer_size = SW_RX_BUF_SIZE;
--              sw_desc_ptr->word1.bits.sw_id = i;      // used to locate skb
-+              sw_desc_ptr->word1.bits.sw_id = 0;      // used to locate skb
-               if ( (skb = dev_alloc_skb(SW_RX_BUF_SIZE))==NULL)  /* allocate socket buffer */
-               {
-                       printk("%s::skb buffer allocation fail !\n",__func__); while(1);
-               }
--              REG32(skb->data) = (unsigned int)skb;
-+
-+              data = skb->data;
-               skb_reserve(skb, SKB_RESERVE_BYTES);
-+
-+              REG32(data + 0) = (unsigned int)skb;
-+              REG32(data + 4) = (unsigned short)i;
-+
-               // toe->rx_skb[i] = skb;
-               sw_desc_ptr->word2.buf_adr = (unsigned int)__pa(skb->data);
- //            consistent_sync((unsigned int)desc_ptr, sizeof(GMAC_RXDESC_T), PCI_DMA_TODEVICE);
-@@ -851,14 +863,14 @@
- *----------------------------------------------------------------------*/
- static void toe_init_default_queue(void)
- {
--      TOE_INFO_T                              *toe;
-+      TOE_INFO_T              *toe;
-       volatile NONTOE_QHDR_T  *qhdr;
--      GMAC_RXDESC_T                   *desc_ptr;
--      DMA_SKB_SIZE_T                  skb_size;
-+      GMAC_RXDESC_T           *desc_ptr;
-+      DMA_SKB_SIZE_T          skb_size;
-       toe = (TOE_INFO_T *)&toe_private_data;
-       desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T)),
--                                                                                      (dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
-+                                             (dma_addr_t *)&toe->gmac[0].default_desc_base_dma);
-       if (!desc_ptr)
-       {
-               printk("%s::DMA_MALLOC fail !\n",__func__);
-@@ -866,14 +878,17 @@
-       }
-       memset((void *)desc_ptr, 0, TOE_DEFAULT_Q0_DESC_NUM * sizeof(GMAC_RXDESC_T));
-       toe->gmac[0].default_desc_base = (unsigned int)desc_ptr;
-+      printk("toe->gmac[0].default_desc_base_dma: %08X\n", toe->gmac[0].default_desc_base_dma);
-+
-       toe->gmac[0].default_desc_num = TOE_DEFAULT_Q0_DESC_NUM;
-       qhdr = (volatile NONTOE_QHDR_T *)TOE_DEFAULT_Q0_HDR_BASE;
-       qhdr->word0.base_size = ((unsigned int)toe->gmac[0].default_desc_base_dma & NONTOE_QHDR0_BASE_MASK) | TOE_DEFAULT_Q0_DESC_POWER;
-       qhdr->word1.bits32 = 0;
-       toe->gmac[0].rx_rwptr.bits32 = 0;
-       toe->gmac[0].default_qhdr = (NONTOE_QHDR_T *)qhdr;
-+
-       desc_ptr = (GMAC_RXDESC_T *)DMA_MALLOC((TOE_DEFAULT_Q1_DESC_NUM * sizeof(GMAC_RXDESC_T)),
--                                                                                      (dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
-+                                             (dma_addr_t *)&toe->gmac[1].default_desc_base_dma);
-       if (!desc_ptr)
-       {
-               printk("%s::DMA_MALLOC fail !\n",__func__);
-@@ -1071,12 +1086,16 @@
-           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG) & ~tp->intr0_selected;
-           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG);
-+
-           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG) & ~tp->intr1_selected;
-           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG);
-+
-           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG) & ~tp->intr2_selected;
-           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG);
-+
-           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG) & ~tp->intr3_selected;
-           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
-+
-           data = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG) & ~tp->intr4_selected;
-           writel(data, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-       }
-@@ -1176,11 +1195,11 @@
-       GMAC_CONFIG2_T  config2_val;
-       GMAC_CONFIG0_T  config0,config0_mask;
-       GMAC_CONFIG1_T  config1;
--      #ifdef CONFIG_SL351x_NAT
-       GMAC_CONFIG3_T  config3_val;
--      #endif
-       GMAC_TX_WCR0_T  hw_weigh;
-       GMAC_TX_WCR1_T  sw_weigh;
-+
-+      uint32_t weight = 0;
- //    GMAC_HASH_ENABLE_REG0_T hash_ctrl;
- //
- #if 0 /* mac address will be set in late_initcall */
-@@ -1202,24 +1221,23 @@
-       //      config1.bits32 = 0x002004;      //next version
-       /* set flow control threshold */
-       config1.bits32 = 0;
--      config1.bits.set_threshold = 32 / 2;
--      config1.bits.rel_threshold = 32 / 4 * 3;
-+      config1.bits.set_threshold = (32 / 2);
-+      config1.bits.rel_threshold = (32 / 4) * 3;
-       gmac_write_reg(tp->base_addr, GMAC_CONFIG1, config1.bits32, 0xffffffff);
--      /* set flow control threshold */
-+      /* TODO: set flow control threshold */
-       config2_val.bits32 = 0;
--      config2_val.bits.set_threshold = TOE_SW_FREEQ_DESC_NUM/2;
--      config2_val.bits.rel_threshold = TOE_SW_FREEQ_DESC_NUM*3/4;
-+      config2_val.bits.set_threshold = TOE_SW_FREEQ_DESC_NUM/4;
-+      config2_val.bits.rel_threshold = TOE_SW_FREEQ_DESC_NUM/2;
-       gmac_write_reg(tp->base_addr, GMAC_CONFIG2, config2_val.bits32,0xffffffff);
--      #ifdef CONFIG_SL351x_NAT
--      /* set HW free queue flow control threshold */
-+      /* TODO: set HW free queue flow control threshold */
-       config3_val.bits32 = 0;
-       config3_val.bits.set_threshold = PAUSE_SET_HW_FREEQ;
-       config3_val.bits.rel_threshold = PAUSE_REL_HW_FREEQ;
-       gmac_write_reg(tp->base_addr, GMAC_CONFIG3, config3_val.bits32,0xffffffff);
--      #endif
--      /* set_mcast_filter mask*/
-+
-+      /* TODO: set_mcast_filter mask*/
-       //      gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL0,0x0,0xffffffff);
-       //  gmac_write_reg(tp->base_addr,GMAC_MCAST_FIL1,0x0,0xffffffff);
-@@ -1249,7 +1267,7 @@
-       config0.bits.dis_rx = 1;  /* disable rx */
-       config0.bits.dis_tx = 1;  /* disable tx */
-       config0.bits.loop_back = 0; /* enable/disable GMAC loopback */
--      config0.bits.rx_err_detect = 1;
-+      config0.bits.rx_err_detect = 1; /* TODO: was 1, means disabled, 0 enabled ! */
-       config0.bits.rgmii_en = 0;
-       config0.bits.rgmm_edge = 1;
-       config0.bits.rxc_inv = 0;
-@@ -1342,6 +1360,9 @@
-       gmac_write_reg(tp->dma_base_addr, GMAC_AHB_WEIGHT_REG, ahb_weight.bits32, ahb_weight_mask.bits32);
-       #endif
-+      weight = gmac_read_reg(tp->dma_base_addr, GMAC_AHB_WEIGHT_REG);
-+      printk("====> %08X\n", weight);
-+
-       #if defined(CONFIG_SL351x_NAT) || defined(CONFIG_SL351x_RXTOE)
-       gmac_write_reg(tp->dma_base_addr, GMAC_SPR0, IPPROTO_TCP, 0xffffffff);
-       #endif
-@@ -1552,7 +1573,7 @@
-               rwptr.bits32 = readl(swtxq->rwptr_reg);
-               if (rwptr.bits.rptr == swtxq->finished_idx)
-                       break;
--      curr_desc = (volatile GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
-+              curr_desc = (volatile GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
- //            consistent_sync((void *)curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_FROMDEVICE);
-               word0.bits32 = curr_desc->word0.bits32;
-               word1.bits32 = curr_desc->word1.bits32;
-@@ -1573,6 +1594,7 @@
-                               swtxq->finished_idx = RWPTR_ADVANCE_ONE(swtxq->finished_idx, swtxq->total_desc_num);
-                               curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + swtxq->finished_idx;
-                               word0.bits32 = curr_desc->word0.bits32;
-+
- #ifdef _DUMP_TX_TCP_CONTENT
-                               if (curr_desc->word0.bits.buffer_size < 16)
-                               {
-@@ -1592,12 +1614,12 @@
-                       word0.bits.status_tx_ok = 0;
-                       if (swtxq->tx_skb[swtxq->finished_idx])
-                       {
--                              if (interrupt)
--                                      dev_kfree_skb_irq(swtxq->tx_skb[swtxq->finished_idx]);
--                              else
--                                      dev_kfree_skb(swtxq->tx_skb[swtxq->finished_idx]);
-+                              dev_kfree_skb(swtxq->tx_skb[swtxq->finished_idx]);
-                               swtxq->tx_skb[swtxq->finished_idx] = NULL;
-+                      } else {
-+                              BUG();
-                       }
-+
-                       curr_desc->word0.bits32 = word0.bits32;
-                       swtxq->curr_finished_desc = (GMAC_TXDESC_T *)curr_desc;
-                       swtxq->total_finished++;
-@@ -1624,31 +1646,29 @@
- *----------------------------------------------------------------------*/
- static int gmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
- {
--      GMAC_INFO_T                     *tp= dev->priv;
--//    static unsigned int     pcount = 0;
--//    unsigned int                    tx_qid;
--    DMA_RWPTR_T                               rwptr;
--      volatile GMAC_TXDESC_T  *curr_desc;
--      int                                     snd_pages = skb_shinfo(skb)->nr_frags + 1;  /* get number of descriptor */
--      int                                     frag_id = 0;
--      int                                     len, total_len = skb->len;
-+      GMAC_INFO_T *tp= dev->priv;
-+      DMA_RWPTR_T rwptr;
-+      GMAC_TXDESC_T *curr_desc;
-+      int snd_pages = skb_shinfo(skb)->nr_frags + 1;  /* get number of descriptor */
-+      int frag_id = 0;
-+      int len, total_len = skb->len;
-       struct net_device_stats *isPtr;
--      unsigned int                    free_desc;
--      GMAC_SWTXQ_T                    *swtxq;
-+      unsigned int free_desc;
-+      GMAC_SWTXQ_T *swtxq;
-       register unsigned long  word0, word1, word2, word3;
-       unsigned short                  wptr, rptr;
- #ifdef        L2_jumbo_frame
-       int header_len = skb->len;
-       struct iphdr    *ip_hdr;
--    struct tcphdr     *tcp_hdr;
--    int             tcp_hdr_len;
--    unsigned char     *ptr;
--    int             data_len,a;
--    unsigned int    val;
-+      struct tcphdr   *tcp_hdr;
-+      int             tcp_hdr_len;
-+      unsigned char   *ptr;
-+      int             data_len,a;
-+      unsigned int    val;
- #endif
- #ifdef GMAC_LEN_1_2_ISSUE
--      int                                             total_pages;
-+      int total_pages;
-       total_pages = snd_pages;
- #endif
-@@ -1664,13 +1684,6 @@
-     }
- #endif
--#if 0
--      if (storlink_ctl.recvfile==2)
--      {
--          printk("snd_pages=%d skb->len=%d\n",snd_pages,skb->len);
--      }
--#endif
--
- #ifdef GMAC_USE_TXQ0
-       #define tx_qid  0
- #endif
-@@ -1703,9 +1716,9 @@
-       toe_gmac_tx_complete(tp, tx_qid, dev, 0);
-       if (wptr >= swtxq->finished_idx)
--              free_desc = swtxq->total_desc_num - wptr - 1 + swtxq->finished_idx;
-+              free_desc = swtxq->total_desc_num - wptr + swtxq->finished_idx;
-       else
--              free_desc = swtxq->finished_idx - wptr - 1;
-+              free_desc = swtxq->finished_idx - wptr;
-       if (free_desc < snd_pages)
-       {
- //            spin_unlock(&tp->tx_mutex);
-@@ -2063,9 +2076,10 @@
- struct net_device_stats * gmac_get_stats(struct net_device *dev)
- {
-     GMAC_INFO_T *tp = (GMAC_INFO_T *)dev->priv;
-+#if 0 /* don't read stats from hardware, scary numbers. */
-     // unsigned int        flags;
--    unsigned int        pkt_drop;
--    unsigned int        pkt_error;
-+    unsigned int        pkt_drop = 0;
-+    unsigned int        pkt_error = 0;
-     if (netif_running(dev))
-     {
-@@ -2073,10 +2087,14 @@
-         // spin_lock_irqsave(&tp->lock,flags);
-         pkt_drop = gmac_read_reg(tp->base_addr,GMAC_IN_DISCARDS);
-         pkt_error = gmac_read_reg(tp->base_addr,GMAC_IN_ERRORS);
-+      printk("**** stack: %lu, hw: %lu\n", tp->ifStatics.rx_dropped, pkt_drop);
-+
-         tp->ifStatics.rx_dropped = tp->ifStatics.rx_dropped + pkt_drop;
-         tp->ifStatics.rx_errors = tp->ifStatics.rx_errors + pkt_error;
-         // spin_unlock_irqrestore(&tp->lock,flags);
-     }
-+#endif
-+
-     return &tp->ifStatics;
- }
-@@ -2401,36 +2419,63 @@
- * toe_gmac_fill_free_q
- * allocate buffers for free queue.
- *----------------------------------------------------------------------*/
--static inline void toe_gmac_fill_free_q(void)
-+static inline void toe_gmac_fill_free_q(int count)
- {
-       struct sk_buff  *skb;
-       volatile DMA_RWPTR_T    fq_rwptr;
-       volatile GMAC_RXDESC_T  *fq_desc;
--      unsigned long   flags;
-+      unsigned long flags;
-+      unsigned short index;
-+      int filled = 0;
-+      static int entered;
-       // unsigned short max_cnt=TOE_SW_FREEQ_DESC_NUM>>1;
-+      BUG_ON(entered == 1);
-+
-+      entered = 1;
-+
-+
-       fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-       // spin_lock_irqsave(&gmac_fq_lock, flags);
-       //while ((max_cnt--) && (unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
-       //                              TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
--      while ((unsigned short)RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
--                                      TOE_SW_FREEQ_DESC_NUM) != fq_rwptr.bits.rptr) {
-+      index = fq_rwptr.bits.wptr;
-+#if 0
-+      printk("wptr: %hu, rptr: %hu, refill idx: %hu\n",
-+             GET_RPTR(fq_rwptr.bits32),
-+             GET_WPTR(fq_rwptr.bits32),
-+             index);
-+#endif
-+
-+      index = RWPTR_ADVANCE_ONE(index, TOE_SW_FREEQ_DESC_NUM);
-+      fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base + index;
-+      while (fq_desc->word2.buf_adr == 0) {
-+              void *data = NULL;
-+
-               if ((skb = dev_alloc_skb(SW_RX_BUF_SIZE)) == NULL) {
-                       printk("%s::skb allocation fail!\n", __func__);
--                      //while(1);
--                      break;
-+                      goto out;
-               }
--              REG32(skb->data) = (unsigned int)skb;
-+              ++ filled;
-+              data = skb->data;
-               skb_reserve(skb, SKB_RESERVE_BYTES);
--              // fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--              fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr,
--                      TOE_SW_FREEQ_DESC_NUM);
--              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base+fq_rwptr.bits.wptr;
-+
-+              REG32(data + 0) = (unsigned int)skb;
-+              REG32(data + 4) = (unsigned short)index;
-+
-+              // printk("refill skb: %p, idx: %hu\n", skb, index);
-               fq_desc->word2.buf_adr = (unsigned int)__pa(skb->data);
--              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr);
--              toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32;
-+      writel(0x07960202, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+              SET_WPTR(TOE_GLOBAL_BASE+GLOBAL_SWFQ_RWPTR_REG, index);
-+      writel(0x07960200, TOE_GMAC0_BASE+GMAC_CONFIG0);
-+
-+              index = RWPTR_ADVANCE_ONE(index, TOE_SW_FREEQ_DESC_NUM);
-+              fq_desc = (GMAC_RXDESC_T*)toe_private_data.swfq_desc_base+index;
-       }
-+out:
-       // spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+
-+      entered = 0;
- }
- // EXPORT_SYMBOL(toe_gmac_fill_free_q);
-@@ -2442,14 +2487,14 @@
-       unsigned int            status3;
-       unsigned int            status4;
--      printk("%s\n", message);
--
-       status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
-       status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-       status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
-       status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
-       status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+      printk("%s\n", message);
-+
-       printk("status: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
-                  status0, status1, status2, status3, status4);
-@@ -2468,8 +2513,9 @@
-       status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG);
-       status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
--      printk("select: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
--                 status0, status1, status2, status3, status4);
-+      if (status0 || status1 || status2 || status3 || status4)
-+                      printk("select: s0:%08X, s1:%08X, s2:%08X, s3:%08X, s4:%08X\n",
-+                                 status0, status1, status2, status3, status4);
- }
- /*----------------------------------------------------------------------
- * toe_gmac_interrupt
-@@ -2485,75 +2531,44 @@
-       unsigned int            status3;
-       unsigned int            status4;
--//    struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
-       toe = (TOE_INFO_T *)&toe_private_data;
--//    handle NAPI
--#ifdef CONFIG_SL_NAPI
--      /* XXX: check this, changed from 'storlink_ctl.pauseoff == 1' to if (1) */
--if (1)
--{
--/* disable GMAC interrupt */
--    //toe_gmac_disable_interrupt(tp->irq);
--//    isPtr->interrupts++;
-+      if (0 && rx_poll_enabled) {
-+              gmac_registers("interrupt handler");
-+      }
-+
-       /* read Interrupt status */
-       status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
-       status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-       status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
-       status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
-       status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
--      // prompt warning if status bit ON but not enabled
-+
- #if 0
--      if (status0 & ~tp->intr0_enabled)
--              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
--                              status0, tp->intr0_enabled);
--      if (status1 & ~tp->intr1_enabled)
--              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
--                              status1, tp->intr1_enabled);
--      if (status2 & ~tp->intr2_enabled)
--              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
--                              status2, tp->intr2_enabled);
--      if (status3 & ~tp->intr3_enabled)
--              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
--                              status3, tp->intr3_enabled);
--      if (status4 & ~tp->intr4_enabled)
--              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
--                              status4, tp->intr4_enabled);
-+      /* handle freeq interrupt first */
-+      if (status4 & SWFQ_EMPTY_INT_BIT)
-+      {
-+              toe_gmac_fill_free_q();
-+              writel(status4 & SWFQ_EMPTY_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-+              tp->sw_fq_empty_cnt++;
-+      }
- #endif
-+      if (status4 & GMAC0_MIB_INT_BIT)
-+              writel(GMAC0_MIB_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-+
-+      if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
-+              writel(GMAC0_RX_OVERRUN_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-+
-       if (status0)
-               writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
--      if (status1)
--              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
-       if (status2)
-               writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
-       if (status3)
-               writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
--      if (status4)
--              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
--
--#if 0
--      /* handle freeq interrupt first */
--      if (status4 & tp->intr4_enabled) {
--              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
--              {
--                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
--                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
--
--                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
--                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
--                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
--                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
--                      printk("\nfreeq int\n");
--                      toe_gmac_fill_free_q();
--                      tp->sw_fq_empty_cnt++;
--              }
--      }
--#endif
-       // Interrupt Status 1
--      if (status1 & tp->intr1_enabled)
-+      if ((status1 & 3) || (status4 & 1))
-       {
-               #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
-               #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
-@@ -2563,7 +2578,7 @@
-               // because they should pass packets to upper layer
-               if (tp->port_id == 0)
-               {
--                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
-+                      if (((status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS)) || (status4 & 1))
-                       {
-                               if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
-                                       tp->hwtxq[3].eof_cnt++;
-@@ -2574,50 +2589,51 @@
-                               if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
-                                       tp->hwtxq[0].eof_cnt++;
-                       }
--                              if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
-+                      if (status1 & DEFAULT_Q0_INT_BIT || status4 & 1)
-+                      {
-+                              if (likely(netif_rx_schedule_prep(dev)))
-                               {
--                                      if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
--                              {
--                                      unsigned int data32;
-+                                      unsigned int data32;
-+
-+                                      BUG_ON(rx_poll_enabled == 1);
--                                              if (rx_poll_enabled)
--                                                              gmac_registers("check #1");
-+                                      /* Masks GMAC-0 rx interrupt */
-+                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                      data32 &= ~(DEFAULT_Q0_INT_BIT);
-+                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--                                              BUG_ON(rx_poll_enabled == 1);
-+                                      /* Masks GMAC-0 queue empty interrupt */
-+                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+                                      data32 &= ~DEFAULT_Q0_INT_BIT;
-+                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+                                      __netif_rx_schedule(dev);
-+                                      rx_poll_enabled = 1;
-+                              } else {
- #if 0
--                                      /* Masks GMAC-0 rx interrupt */
--                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--                                              data32 &= ~(DEFAULT_Q0_INT_BIT);
--                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--
--                                      /* Masks GMAC-0 queue empty interrupt */
--                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
--                                              data32 &= ~DEFAULT_Q0_INT_BIT;
--                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
--
--                                              data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
--                                              data32 &= ~DEFAULT_Q0_INT_BIT;
--                                              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
--#endif
--
--                                      // class-Q & TOE-Q are implemented in future
--                                      //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--                                      //data32 &= ~DEFAULT_Q0_INT_BIT;
--                                              //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--                                              //printk("\%s: DEFAULT_Q0_INT_BIT===================>>>>>>>>>>>>\n",__func__);
--                                              writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
--                                              //tp->total_q_cnt_napi=0;
--                                              //rx_time = jiffies;
--                                              //rx_old_bytes = isPtr->rx_bytes;
--                                              __netif_rx_schedule(dev);
--                                              rx_poll_enabled = 1;
--                              }
-+                                      unsigned int data32;
-+
-+                                      if (rx_poll_enabled)
-+                                              gmac_registers("->poll() running.");
-+                                      /* Masks GMAC-0 rx interrupt */
-+                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                      data32 &= ~(DEFAULT_Q0_INT_BIT);
-+                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+
-+                                      /* Masks GMAC-0 queue empty interrupt */
-+                                      data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+                                      data32 &= ~DEFAULT_Q0_INT_BIT;
-+                                      writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-+#endif
-+                              }
-+                      } else {
-+                              if (0)
-+                                      gmac_registers("status1 & DEFAULT_Q0_INT_BIT || status4 & 1");
-                       }
-               }
--              else if (tp->port_id == 1)
-+              else if (tp->port_id == 1 && netif_running(dev))
-               {
--                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
-+                      if ((status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
-                       {
-                               if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
-                                       tp->hwtxq[3].eof_cnt++;
-@@ -2629,14 +2645,14 @@
-                                       tp->hwtxq[0].eof_cnt++;
-                       }
--                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
-+                      if ((status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
-                       {
-                               if (!rx_poll_enabled && likely(netif_rx_schedule_prep(dev)))
--                      {
--                              unsigned int data32;
-+                              {
-+                                      unsigned int data32;
-                                       if (rx_poll_enabled)
--                                                      gmac_registers("check #2");
-+                                              gmac_registers("check #2");
-                                       BUG_ON(rx_poll_enabled == 1);
-@@ -2646,7 +2662,7 @@
-                                       data32 &= ~(DEFAULT_Q1_INT_BIT);
-                                       writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--                              /* Masks GMAC-1 queue empty interrupt */
-+                                      /* Masks GMAC-1 queue empty interrupt */
-                                       data32  = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-                                       data32 &= ~DEFAULT_Q1_INT_BIT;
-                                       writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-@@ -2656,24 +2672,21 @@
-                                       writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
- #endif
--                              // disable GMAC-0 rx interrupt
--                              // class-Q & TOE-Q are implemented in future
--                              //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--                              //data32 &= ~DEFAULT_Q1_INT_BIT;
-+                                      // disable GMAC-0 rx interrupt
-+                                      // class-Q & TOE-Q are implemented in future
-+                                      //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+                                      //data32 &= ~DEFAULT_Q1_INT_BIT;
-                                       //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-                                       //printk("\%s: 1111111111--->DEFAULT_Q1_INT_BIT===================>>>>>>>>>>>>\n",__func__);
-                                       writel(0x0, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
-                                       //tp->total_q_cnt_napi=0;
-                                       //rx_time = jiffies;
-                                       //rx_old_bytes = isPtr->rx_bytes;
--                              __netif_rx_schedule(dev);
--                              rx_poll_enabled = 1;
--                      }
-+                                      __netif_rx_schedule(dev);
-+                                      rx_poll_enabled = 1;
-+                              }
-                       }
-               }
--      } else {
--
--              gmac_registers("check #3");
-       }
-       // Interrupt Status 0
-@@ -2814,676 +2827,93 @@
-               }
-       }
--      //toe_gmac_enable_interrupt(tp->irq);
--#ifdef IxscriptMate_1518
--      if (storlink_ctl.pauseoff == 1)
--      {
--              GMAC_CONFIG0_T config0;
--              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
--              config0.bits.dis_rx = 0;
--              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
--              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
--              config0.bits.dis_rx = 0;
--              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
--      }
--#endif
--//     enable_irq(gmac_irq[dev_index]);
--      //printk("gmac_interrupt complete!\n\n");
--//    return IRQ_RETVAL(handled);
-       return  IRQ_RETVAL(1);
- }
--else
--{
--#endif        //endif NAPI
-+/*----------------------------------------------------------------------
-+* gmac_get_phy_vendor
-+*----------------------------------------------------------------------*/
-+static unsigned int gmac_get_phy_vendor(int phy_addr)
-+{
-+    unsigned int      reg_val;
-+    reg_val=(mii_read(phy_addr,0x02) << 16) + mii_read(phy_addr,0x03);
-+    return reg_val;
-+}
--      /* disable GMAC interrupt */
--    toe_gmac_disable_interrupt(tp->irq);
-+/*----------------------------------------------------------------------
-+* gmac_set_phy_status
-+*----------------------------------------------------------------------*/
-+void gmac_set_phy_status(struct net_device *dev)
-+{
-+      GMAC_INFO_T *tp = dev->priv;
-+      GMAC_STATUS_T   status;
-+      unsigned int    reg_val, ability,wan_port_id;
-+      unsigned int    i = 0;
--//    isPtr->interrupts++;
--      /* read Interrupt status */
--      status0 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG);
--      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
--      status2 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG);
--      status3 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG);
--      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
--      // prompt warning if status bit ON but not enabled
-+#ifdef VITESSE_G5SWITCH
-+      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1)){
- #if 0
--      if (status0 & ~tp->intr0_enabled)
--              printk("Intr 0 Status error. status = 0x%X, enable = 0x%X\n",
--                              status0, tp->intr0_enabled);
--      if (status1 & ~tp->intr1_enabled)
--              printk("Intr 1 Status error. status = 0x%X, enable = 0x%X\n",
--                              status1, tp->intr1_enabled);
--      if (status2 & ~tp->intr2_enabled)
--              printk("Intr 2 Status error. status = 0x%X, enable = 0x%X\n",
--                              status2, tp->intr2_enabled);
--      if (status3 & ~tp->intr3_enabled)
--              printk("Intr 3 Status error. status = 0x%X, enable = 0x%X\n",
--                              status3, tp->intr3_enabled);
--      if (status4 & ~tp->intr4_enabled)
--              printk("Intr 4 Status error. status = 0x%X, enable = 0x%X\n",
--                              status4, tp->intr4_enabled);
--#endif
--#define       INTERRUPT_SELECT                        1
--      if (status0)
--              writel(status0 & tp->intr0_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_0_REG);
--      if (status1)
--              writel(status1 & tp->intr1_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_1_REG);
--      if (status2)
--              writel(status2 & tp->intr2_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_2_REG);
--      if (status3)
--              writel(status3 & tp->intr3_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_3_REG);
--      if (status4)
--              writel(status4 & tp->intr4_enabled, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
--
--      /* handle freeq interrupt first */
--      if (status4 & tp->intr4_enabled) {
--              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
--              {
--                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
--                      //      tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
--
--                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
--                      //      SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
--                      if (toe->gmac[0].dev && netif_running(toe->gmac[0].dev))
--                              toe_gmac_handle_default_rxq(toe->gmac[0].dev,&toe->gmac[0]);
--                      if (toe->gmac[1].dev && netif_running(toe->gmac[1].dev))
--                              toe_gmac_handle_default_rxq(toe->gmac[1].dev,&toe->gmac[1]);
--                      printk("\nfreeq int\n");
--                      toe_gmac_fill_free_q();
--                      tp->sw_fq_empty_cnt++;
--
--                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
--                              SWFQ_EMPTY_INT_BIT);
--              }
--      }
--
--      // Interrupt Status 1
--      if (status1 & tp->intr1_enabled)
--      {
--              #define G1_INTR0_BITS   (GMAC1_HWTQ13_EOF_INT_BIT | GMAC1_HWTQ12_EOF_INT_BIT | GMAC1_HWTQ11_EOF_INT_BIT | GMAC1_HWTQ10_EOF_INT_BIT)
--              #define G0_INTR0_BITS   (GMAC0_HWTQ03_EOF_INT_BIT | GMAC0_HWTQ02_EOF_INT_BIT | GMAC0_HWTQ01_EOF_INT_BIT | GMAC0_HWTQ00_EOF_INT_BIT)
--              // Handle GMAC 0/1 HW Tx queue 0-3 EOF events
--              // Only count
--              // TOE, Classification, and default queues interrupts are handled by ISR
--              // because they should pass packets to upper layer
--              if (tp->port_id == 0)
--              {
--#ifndef       INTERRUPT_SELECT
--                      if (netif_running(dev) && (status1 & G0_INTR0_BITS) && (tp->intr1_enabled & G0_INTR0_BITS))
--                      {
--                              if (status1 & GMAC0_HWTQ03_EOF_INT_BIT)
--                                      tp->hwtxq[3].eof_cnt++;
--                              if (status1 & GMAC0_HWTQ02_EOF_INT_BIT)
--                                      tp->hwtxq[2].eof_cnt++;
--                              if (status1 & GMAC0_HWTQ01_EOF_INT_BIT)
--                                      tp->hwtxq[1].eof_cnt++;
--                              if (status1 & GMAC0_HWTQ00_EOF_INT_BIT)
--                                      tp->hwtxq[0].eof_cnt++;
--#endif        //INTERRUPT_SELECT
--#ifndef       INTERRUPT_SELECT
--                      }
--#endif        //INTERRUPT_SELECT
--                      if (netif_running(dev) && (status1 & DEFAULT_Q0_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q0_INT_BIT))
--                      {
--                              tp->default_q_intr_cnt++;
--                              toe_gmac_handle_default_rxq(dev, tp);
-+              rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
-+              rcv_mask |= 0x4F;
-+              for(i=0;i<4;i++){
-+                      reg_val = BIT(26)|(i<<21)|(10<<16);
-+                      SPI_write(3,0,1,reg_val);
-+                      msleep(10);
-+                      reg_val = SPI_read(3,0,2);
-+                      if(reg_val & 0x0c00){
-+                              printk("Port%d:Giga mode\n",i);
-+                              SPI_write(1,i,0x00,0x300701B1);
-+                              SPI_write(1,i,0x00,0x10070181);
-+                              switch_pre_link[i]=LINK_UP;
-+                              switch_pre_speed[i]=GMAC_SPEED_1000;
-                       }
--#ifdef CONFIG_SL351x_RXTOE
--                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
--                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
--                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
--                              toe_gmac_handle_toeq(dev, tp, status1);
--                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
-+                      else{
-+                              reg_val = BIT(26)|(i<<21)|(5<<16);
-+                              SPI_write(3,0,1,reg_val);
-+                              msleep(10);
-+                              ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5;
-+                              if ((ability & 0x0C)) /* 100M full duplex */
-+                              {
-+                                      SPI_write(1,i,0x00,0x30050472);
-+                                      SPI_write(1,i,0x00,0x10050442);
-+                                      printk("Port%d:100M\n",i);
-+                                      switch_pre_link[i]=LINK_UP;
-+                              switch_pre_speed[i]=GMAC_SPEED_100;
-+                              }
-+                              else if((ability & 0x03)) /* 10M full duplex */
-+                              {
-+                                      SPI_write(1,i,0x00,0x30050473);
-+                                      SPI_write(1,i,0x00,0x10050443);
-+                                      printk("Port%d:10M\n",i);
-+                                      switch_pre_link[i]=LINK_UP;
-+                                      switch_pre_speed[i]=GMAC_SPEED_10;
-+                              }
-+                              else{
-+                                      SPI_write(1,i,0x00,BIT(16));                    // disable RX
-+                                      SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
-+                                      while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
-+                                              msleep(1);
-+
-+                                      SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
-+                                      switch_pre_link[i]=LINK_DOWN;
-+                                      switch_pre_speed[i]=GMAC_SPEED_10;
-+                                      rcv_mask &= ~BIT(i);
-+                                      SPI_write(2,0,0x10,rcv_mask);                   // Disable Receive
-+                              }
-                       }
--#endif
-               }
--              else if (tp->port_id == 1)
--              {
--#ifndef       INTERRUPT_SELECT
--                      if (netif_running(dev) && (status1 & G1_INTR0_BITS) && (tp->intr1_enabled & G1_INTR0_BITS))
--                      {
--                              if (status1 & GMAC1_HWTQ13_EOF_INT_BIT)
--                                      tp->hwtxq[3].eof_cnt++;
--                              if (status1 & GMAC1_HWTQ12_EOF_INT_BIT)
--                                      tp->hwtxq[2].eof_cnt++;
--                              if (status1 & GMAC1_HWTQ11_EOF_INT_BIT)
--                                      tp->hwtxq[1].eof_cnt++;
--                              if (status1 & GMAC1_HWTQ10_EOF_INT_BIT)
--                                      tp->hwtxq[0].eof_cnt++;
--#endif        //INTERRUPT_SELECT
--#ifndef       INTERRUPT_SELECT
--                      }
--#endif        //INTERRUPT_SELECT
--                      if (netif_running(dev) && (status1 & DEFAULT_Q1_INT_BIT) && (tp->intr1_enabled & DEFAULT_Q1_INT_BIT))
--                      {
--                              tp->default_q_intr_cnt++;
--                              toe_gmac_handle_default_rxq(dev, tp);
--                      }
--#ifdef CONFIG_SL351x_RXTOE
--                      if (netif_running(dev) && (status1 & TOE_IQ_ALL_BITS) &&
--                          (tp->intr1_enabled & TOE_IQ_ALL_BITS)) {
--                              //printk("status %x, bits %x, slct %x\n", status1, TOE_IQ_ALL_BITS, tp->intr1_selected);
--                              toe_gmac_handle_toeq(dev, tp, status1);
--                              //toe_gmac_handle_toeq(dev, toe, tp, status1);
--                      }
- #endif
--              }
-+              gmac_get_switch_status(dev);
-+              gmac_write_reg(tp->base_addr, GMAC_STATUS, 0x7d, 0x0000007f);
-+//            SPI_write(2,0,0x10,rcv_mask);                   // Enable Receive
-+              return ;
-       }
-+#endif
-+      reg_val = gmac_get_phy_vendor(tp->phy_addr);
-+      printk("GMAC-%d Addr %d Vendor ID: 0x%08x\n", tp->port_id, tp->phy_addr, reg_val);
--      // Interrupt Status 0
--      if (status0 & tp->intr0_enabled)
--      {
--
--              #define ERR_INTR_BITS   (GMAC0_TXDERR_INT_BIT | GMAC0_TXPERR_INT_BIT |  \
--                                                               GMAC1_TXDERR_INT_BIT | GMAC1_TXPERR_INT_BIT |  \
--                                                               GMAC0_RXDERR_INT_BIT | GMAC0_RXPERR_INT_BIT |  \
--                                                               GMAC1_RXDERR_INT_BIT | GMAC1_RXPERR_INT_BIT)
--#ifndef       INTERRUPT_SELECT
--              if (status0 &  ERR_INTR_BITS)
--              {
--                      if ((status0 & GMAC0_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXDERR_INT_BIT))
--                      {
--                              tp->txDerr_cnt[0]++;
--                              printk("GMAC0 TX AHB Bus Error!\n");
--                      }
--                      if ((status0 & GMAC0_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_TXPERR_INT_BIT))
--                      {
--                              tp->txPerr_cnt[0]++;
--                              printk("GMAC0 Tx Descriptor Protocol Error!\n");
--                      }
--                      if ((status0 & GMAC1_TXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXDERR_INT_BIT))
--                      {
--                              tp->txDerr_cnt[1]++;
--                              printk("GMAC1 Tx AHB Bus Error!\n");
--                      }
--                      if ((status0 & GMAC1_TXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_TXPERR_INT_BIT))
--                      {
--                              tp->txPerr_cnt[1]++;
--                              printk("GMAC1 Tx Descriptor Protocol Error!\n");
--                      }
--
--                      if ((status0 & GMAC0_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXDERR_INT_BIT))
--                      {
--                              tp->RxDerr_cnt[0]++;
--                              printk("GMAC0 Rx AHB Bus Error!\n");
--                      }
--                      if ((status0 & GMAC0_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC0_RXPERR_INT_BIT))
--                      {
--                              tp->RxPerr_cnt[0]++;
--                              printk("GMAC0 Rx Descriptor Protocol Error!\n");
--                      }
--                      if ((status0 & GMAC1_RXDERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXDERR_INT_BIT))
--                      {
--                              tp->RxDerr_cnt[1]++;
--                              printk("GMAC1 Rx AHB Bus Error!\n");
--                      }
--                      if ((status0 & GMAC1_RXPERR_INT_BIT) && (tp->intr0_enabled & GMAC1_RXPERR_INT_BIT))
--                      {
--                              tp->RxPerr_cnt[1]++;
--                              printk("GMAC1 Rx Descriptor Protocol Error!\n");
--                      }
--              }
--#endif        //INTERRUPT_SELECT
--#ifndef       GMAX_TX_INTR_DISABLED
--              if (tp->port_id == 1 && netif_running(dev) &&
--                      (((status0 & GMAC1_SWTQ10_FIN_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_FIN_INT_BIT))
--                      ||
--                      ((status0 & GMAC1_SWTQ10_EOF_INT_BIT) && (tp->intr0_enabled & GMAC1_SWTQ10_EOF_INT_BIT))))
--              {
--                      toe_gmac_tx_complete(&toe_private_data.gmac[1], 0, dev, 1);
--              }
--
--              if (tp->port_id == 0 && netif_running(dev) &&
--                      (((status0 & GMAC0_SWTQ00_FIN_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_FIN_INT_BIT))
--                      ||
--                      ((status0 & GMAC0_SWTQ00_EOF_INT_BIT) && (tp->intr0_enabled & GMAC0_SWTQ00_EOF_INT_BIT))))
--              {
--                      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
--              }
--#endif
--              // clear enabled status bits
--      }
--      // Interrupt Status 4
--#ifndef       INTERRUPT_SELECT
--      if (status4 & tp->intr4_enabled)
--      {
--              #define G1_INTR4_BITS           (0xff000000)
--              #define G0_INTR4_BITS           (0x00ff0000)
--
--              if (tp->port_id == 0)
--              {
--                      if ((status4 & G0_INTR4_BITS) && (tp->intr4_enabled & G0_INTR4_BITS))
--                      {
--                              if (status4 & GMAC0_RESERVED_INT_BIT)
--                                      printk("GMAC0_RESERVED_INT_BIT is ON\n");
--                              if (status4 & GMAC0_MIB_INT_BIT)
--                                      tp->mib_full_cnt++;
--                              if (status4 & GMAC0_RX_PAUSE_ON_INT_BIT)
--                                      tp->rx_pause_on_cnt++;
--                              if (status4 & GMAC0_TX_PAUSE_ON_INT_BIT)
--                                      tp->tx_pause_on_cnt++;
--                              if (status4 & GMAC0_RX_PAUSE_OFF_INT_BIT)
--                                      tp->rx_pause_off_cnt++;
--                              if (status4 & GMAC0_TX_PAUSE_OFF_INT_BIT)
--                                      tp->rx_pause_off_cnt++;
--                              if (status4 & GMAC0_RX_OVERRUN_INT_BIT)
--                                      tp->rx_overrun_cnt++;
--                              if (status4 & GMAC0_STATUS_CHANGE_INT_BIT)
--                                      tp->status_changed_cnt++;
--                      }
--              }
--              else if (tp->port_id == 1)
--              {
--                      if ((status4 & G1_INTR4_BITS) && (tp->intr4_enabled & G1_INTR4_BITS))
--                      {
--                              if (status4 & GMAC1_RESERVED_INT_BIT)
--                                      printk("GMAC1_RESERVED_INT_BIT is ON\n");
--                              if (status4 & GMAC1_MIB_INT_BIT)
--                                      tp->mib_full_cnt++;
--                              if (status4 & GMAC1_RX_PAUSE_ON_INT_BIT)
--                              {
--                                      //printk("Gmac pause on\n");
--                                      tp->rx_pause_on_cnt++;
--                              }
--                              if (status4 & GMAC1_TX_PAUSE_ON_INT_BIT)
--                              {
--                                      //printk("Gmac pause on\n");
--                                      tp->tx_pause_on_cnt++;
--                              }
--                              if (status4 & GMAC1_RX_PAUSE_OFF_INT_BIT)
--                              {
--                                      //printk("Gmac pause off\n");
--                                      tp->rx_pause_off_cnt++;
--                              }
--                              if (status4 & GMAC1_TX_PAUSE_OFF_INT_BIT)
--                              {
--                                      //printk("Gmac pause off\n");
--                                      tp->rx_pause_off_cnt++;
--                              }
--                              if (status4 & GMAC1_RX_OVERRUN_INT_BIT)
--                              {
--                                      //printk("Gmac Rx Overrun \n");
--                                      tp->rx_overrun_cnt++;
--                              }
--                              if (status4 & GMAC1_STATUS_CHANGE_INT_BIT)
--                                      tp->status_changed_cnt++;
--                      }
--              }
--#if 0
--              if ((status4 & SWFQ_EMPTY_INT_BIT) && (tp->intr4_enabled & SWFQ_EMPTY_INT_BIT))
--              {
--                      // unsigned long data = REG32(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--//                    mac_stop_rxdma(tp->sc);
--                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG,
--                              tp->intr4_enabled & ~SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
--
--                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG,
--                              SWFQ_EMPTY_INT_BIT, SWFQ_EMPTY_INT_BIT);
--                      toe_gmac_fill_free_q();
--                      tp->sw_fq_empty_cnt++;
--
--                      gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
--                              SWFQ_EMPTY_INT_BIT);
--//#if 0
--/*                    if (netif_running(dev))
--                              toe_gmac_handle_default_rxq(dev, tp);
--                      printk("SWFQ_EMPTY_INT_BIT is ON!\n");  // should not be happened */
--//#endif
--              }
--#endif
--      }
--#endif        //INTERRUPT_SELECT
--      toe_gmac_enable_interrupt(tp->irq);
--//enable gmac rx function when do RFC 2544
--#ifdef IxscriptMate_1518
--      if (storlink_ctl.pauseoff == 1)
--      {
--              GMAC_CONFIG0_T config0;
--              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
--              config0.bits.dis_rx = 0;
--              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
--              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
--              config0.bits.dis_rx = 0;
--              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
--      }
--#endif
--      //printk("gmac_interrupt complete!\n\n");
--//    return IRQ_RETVAL(handled);
--      return  IRQ_RETVAL(1);
--#ifdef CONFIG_SL_NAPI
--}
--#endif
--}
--
--/*----------------------------------------------------------------------
--*     toe_gmac_handle_default_rxq
--*     (1) Get rx Buffer for default Rx queue
--*     (2) notify or call upper-routine to handle it
--*     (3) get a new buffer and insert it into SW free queue
--*     (4) Note: The SW free queue Read-Write Pointer should be locked when accessing
--*----------------------------------------------------------------------*/
--//static inline void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
--static void toe_gmac_handle_default_rxq(struct net_device *dev, GMAC_INFO_T *tp)
--{
--      TOE_INFO_T                      *toe;
--    GMAC_RXDESC_T     *curr_desc;
--      struct sk_buff          *skb;
--    DMA_RWPTR_T                       rwptr;
--      unsigned int            pkt_size;
--      int                                     max_cnt;
--      unsigned int        desc_count;
--      unsigned int        good_frame, chksum_status, rx_status;
--      struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
--
--//when do ixia RFC 2544 test and packet size is select 1518 bytes,disable gmace rx function immediately after one interrupt come in.
--#ifdef IxscriptMate_1518
--      if (storlink_ctl.pauseoff == 1)
--      {
--              GMAC_CONFIG0_T config0;
--              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
--              config0.bits.dis_rx = 1;
--              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
--              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
--              config0.bits.dis_rx = 1;
--              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
--      }
--#endif
--      rwptr.bits32 = readl(&tp->default_qhdr->word1);
--#if 0
--      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
--      {
--              mac_stop_txdma((struct net_device *)tp->dev);
--              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
--                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
--              while(1);
--      }
--#endif
--      toe = (TOE_INFO_T *)&toe_private_data;
--      max_cnt = DEFAULT_RXQ_MAX_CNT;
--      while ((--max_cnt) && rwptr.bits.rptr != rwptr.bits.wptr)
--//    while (rwptr.bits.rptr != rwptr.bits.wptr)
--      {
--//if packet size is not 1518 for RFC 2544,enable gmac rx function.The other packet size have RX workaround.
--#ifdef IxscriptMate_1518
--      if (storlink_ctl.pauseoff == 1)
--              {
--                      if (pkt_size != 1514)
--                      {
--                                              GMAC_CONFIG0_T config0;
--                                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
--                                              config0.bits.dis_rx = 0;
--                                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
--                                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
--                                              config0.bits.dis_rx = 0;
--                                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
--                      }
--              }
--#endif
--      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
--//            consistent_sync(curr_desc, sizeof(GMAC_RXDESC_T), PCI_DMA_FROMDEVICE);
--              tp->default_q_cnt++;
--      tp->rx_curr_desc = (unsigned int)curr_desc;
--      rx_status = curr_desc->word0.bits.status;
--      chksum_status = curr_desc->word0.bits.chksum_status;
--      tp->rx_status_cnt[rx_status]++;
--      tp->rx_chksum_cnt[chksum_status]++;
--        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
--              desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
--              good_frame=1;
--              if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
--                      || (pkt_size < 60)
--                  || (chksum_status & 0x4)
--                      || rx_status)
--              {
--                      good_frame = 0;
--                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
--                              printk("%s::derr (GMAC-%d)!!!\n", __func__, tp->port_id);
--                      if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_perr)
--                              printk("%s::perr (GMAC-%d)!!!\n", __func__, tp->port_id);
--                      if (rx_status)
--                      {
--                              if (rx_status == 4 || rx_status == 7)
--                                      isPtr->rx_crc_errors++;
--//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
--                      }
--#ifdef SL351x_GMAC_WORKAROUND
--                      else if (pkt_size < 60)
--                      {
--                              if (tp->short_frames_cnt < GMAC_SHORT_FRAME_THRESHOLD)
--                                      tp->short_frames_cnt++;
--                              if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
--                              {
--                                      GMAC_CONFIG0_T config0;
--                                      config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
--                                      config0.bits.dis_rx = 1;
--                                      writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
--                                      config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
--                                      config0.bits.dis_rx = 1;
--                                      writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
--                              }
--                      }
--#endif
--//                    if (chksum_status)
--//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
--                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
--                      dev_kfree_skb_irq(skb);
--              }
--              if (good_frame)
--              {
--                      if (curr_desc->word0.bits.drop)
--                              printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
--//                    if (chksum_status)
--//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
--
--              /* get frame information from the first descriptor of the frame */
--#ifdef SL351x_GMAC_WORKAROUND
--                      if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
--                      {
--                              GMAC_CONFIG0_T config0;
--                              config0.bits32 = readl(TOE_GMAC0_BASE+GMAC_CONFIG0);
--                              config0.bits.dis_rx = 0;
--                              writel(config0.bits32, TOE_GMAC0_BASE+GMAC_CONFIG0);
--                              config0.bits32 = readl(TOE_GMAC1_BASE+GMAC_CONFIG0);
--                              config0.bits.dis_rx = 0;
--                              writel(config0.bits32, TOE_GMAC1_BASE+GMAC_CONFIG0);
--                      }
--                      tp->short_frames_cnt = 0;
--#endif
--                      isPtr->rx_packets++;
--                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr - SKB_RESERVE_BYTES)));
--                      if (!skb)
--                      {
--                              printk("Fatal Error!!skb==NULL\n");
--                              goto next_rx;
--                      }
--                      tp->curr_rx_skb = skb;
--                      // consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
--
--      //              curr_desc->word2.buf_adr = 0;
--
--                      skb_reserve (skb, RX_INSERT_BYTES);     /* 16 byte align the IP fields. */
--                      skb_put(skb, pkt_size);
--                      skb->dev = dev;
--                      if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
--                      {
--                              skb->ip_summed = CHECKSUM_UNNECESSARY;
--#ifdef CONFIG_SL351x_NAT
--                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
--                              {
--                                      struct iphdr    *ip_hdr;
--                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
--                                      sl351x_nat_input(skb,
--                                                                      tp->port_id,
--                                                                      (void *)curr_desc->word3.bits.l3_offset,
--                                                                      (void *)curr_desc->word3.bits.l4_offset);
--                              }
--#endif
--                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
--#if 0
--#ifdef CONFIG_SL351x_RXTOE
--                              if (storlink_ctl.rx_max_pktsize) {
--                                      struct iphdr    *ip_hdr;
--                                      struct tcphdr   *tcp_hdr;
--                                      int ip_hdrlen;
--
--                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
--                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
--                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
--                                              ip_hdrlen = ip_hdr->ihl << 2;
--                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
--                                              if (tcp_hdr->syn) {
--                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
--                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
--                                                      TCP_SKB_CB(skb)->connection = connection;
--                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
--                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
--                                                      //                      __func__, skb->data, connection, connection->mode);
--                                              }
--                                      }
--                              }
--#endif
--#endif
--                      }
--                      else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
--                      {
--                              skb->ip_summed = CHECKSUM_UNNECESSARY;
--#ifdef CONFIG_SL351x_NAT
--                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
--                              {
--                                      struct iphdr            *ip_hdr;
--                                      //struct tcphdr         *tcp_hdr;
--                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
--                                      //tcp_hdr = (struct tcphdr *)&(skb->data[curr_desc->word3.bits.l4_offset]);
--                                      if (ip_hdr->protocol == IPPROTO_UDP)
--                                      {
--                                              sl351x_nat_input(skb,
--                                                                              tp->port_id,
--                                                                              (void *)curr_desc->word3.bits.l3_offset,
--                                                                              (void *)curr_desc->word3.bits.l4_offset);
--                                      }
--                                      else if (ip_hdr->protocol == IPPROTO_GRE)
--                                      {
--                                              sl351x_nat_input(skb,
--                                                                      tp->port_id,
--                                                                      (void *)curr_desc->word3.bits.l3_offset,
--                                                                      (void *)curr_desc->word3.bits.l4_offset);
--                                      }
--                              }
--#endif
--                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
--                      }
--                      else
--                      {
--                              skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
--                      }
--
--                      netif_rx(skb);  /* socket rx */
--                      dev->last_rx = jiffies;
--
--                      isPtr->rx_bytes += pkt_size;
--
--        }
--
--next_rx:
--              // advance one for Rx default Q 0/1
--              rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
--              SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
--      tp->rx_rwptr.bits32 = rwptr.bits32;
--
--      }
--
--      /* Handles first available packets only then refill the queue. */
--      toe_gmac_fill_free_q();
--}
--
--/*----------------------------------------------------------------------
--* gmac_get_phy_vendor
--*----------------------------------------------------------------------*/
--static unsigned int gmac_get_phy_vendor(int phy_addr)
--{
--    unsigned int      reg_val;
--    reg_val=(mii_read(phy_addr,0x02) << 16) + mii_read(phy_addr,0x03);
--    return reg_val;
--}
--
--/*----------------------------------------------------------------------
--* gmac_set_phy_status
--*----------------------------------------------------------------------*/
--void gmac_set_phy_status(struct net_device *dev)
--{
--      GMAC_INFO_T *tp = dev->priv;
--      GMAC_STATUS_T   status;
--      unsigned int    reg_val, ability,wan_port_id;
--      unsigned int    i = 0;
--
--#ifdef VITESSE_G5SWITCH
--      if((tp->port_id == GMAC_PORT1)&&(Giga_switch==1)){
--#if 0
--              rcv_mask = SPI_read(2,0,0x10);                  // Receive mask
--              rcv_mask |= 0x4F;
--              for(i=0;i<4;i++){
--                      reg_val = BIT(26)|(i<<21)|(10<<16);
--                      SPI_write(3,0,1,reg_val);
--                      msleep(10);
--                      reg_val = SPI_read(3,0,2);
--                      if(reg_val & 0x0c00){
--                              printk("Port%d:Giga mode\n",i);
--                              SPI_write(1,i,0x00,0x300701B1);
--                              SPI_write(1,i,0x00,0x10070181);
--                              switch_pre_link[i]=LINK_UP;
--                              switch_pre_speed[i]=GMAC_SPEED_1000;
--                      }
--                      else{
--                              reg_val = BIT(26)|(i<<21)|(5<<16);
--                              SPI_write(3,0,1,reg_val);
--                              msleep(10);
--                              ability = (reg_val = SPI_read(3,0,2)&0x5e0) >>5;
--                              if ((ability & 0x0C)) /* 100M full duplex */
--                              {
--                                      SPI_write(1,i,0x00,0x30050472);
--                                      SPI_write(1,i,0x00,0x10050442);
--                                      printk("Port%d:100M\n",i);
--                                      switch_pre_link[i]=LINK_UP;
--                              switch_pre_speed[i]=GMAC_SPEED_100;
--                              }
--                              else if((ability & 0x03)) /* 10M full duplex */
--                              {
--                                      SPI_write(1,i,0x00,0x30050473);
--                                      SPI_write(1,i,0x00,0x10050443);
--                                      printk("Port%d:10M\n",i);
--                                      switch_pre_link[i]=LINK_UP;
--                                      switch_pre_speed[i]=GMAC_SPEED_10;
--                              }
--                              else{
--                                      SPI_write(1,i,0x00,BIT(16));                    // disable RX
--                                      SPI_write(5,0,0x0E,BIT(i));                     // dicard packet
--                                      while((SPI_read(5,0,0x0C)&BIT(i))==0)           // wait to be empty
--                                              msleep(1);
--
--                                      SPI_write(1,i,0x00,0x20000030);                 // PORT_RST
--                                      switch_pre_link[i]=LINK_DOWN;
--                                      switch_pre_speed[i]=GMAC_SPEED_10;
--                                      rcv_mask &= ~BIT(i);
--                                      SPI_write(2,0,0x10,rcv_mask);                   // Disable Receive
--                              }
--                      }
--              }
--#endif
--              gmac_get_switch_status(dev);
--              gmac_write_reg(tp->base_addr, GMAC_STATUS, 0x7d, 0x0000007f);
--//            SPI_write(2,0,0x10,rcv_mask);                   // Enable Receive
--              return ;
--      }
--#endif
--
--      reg_val = gmac_get_phy_vendor(tp->phy_addr);
--      printk("GMAC-%d Addr %d Vendor ID: 0x%08x\n", tp->port_id, tp->phy_addr, reg_val);
--
--      switch (tp->phy_mode)
-+      switch (tp->phy_mode)
-       {
-               case GMAC_PHY_GMII:
-               mii_write(tp->phy_addr,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */
-@@ -3552,6 +2982,7 @@
-               status.bits.link = LINK_DOWN;
-               //              clear_bit(__LINK_STATE_START, &dev->state);
-               printk("Link Down (0x%04x) ", reg_val);
-+#ifdef VITESSE_G5SWITCH
-               if(Giga_switch == 1)
-               {
-                               wan_port_id = 1;
-@@ -3565,6 +2996,7 @@
-                               storlink_ctl.link[ tp->port_id] = 0;
- #endif
-               }
-+#endif
-       }
-       else
-       {
-@@ -3572,6 +3004,7 @@
-               status.bits.link = LINK_UP;
-               //              set_bit(__LINK_STATE_START, &dev->state);
-               printk("Link Up (0x%04x) ",reg_val);
-+#ifdef VITESSE_G5SWITCH
-               if(Giga_switch == 1)
-               {
-                               wan_port_id = 1;
-@@ -3585,6 +3018,7 @@
-                               storlink_ctl.link[ tp->port_id] = 1;
- #endif
-               }
-+#endif
-       }
-       //    value = mii_read(PHY_ADDR,0x05);
-@@ -3863,6 +3297,7 @@
-                       }
-               }
-               status.bits.link = LINK_UP; /* link up */
-+#ifdef VITESSE_G5SWITCH
-               if(Giga_switch==1)
-               {
-                               wan_port_id = 1;
-@@ -3874,6 +3309,7 @@
-                               storlink_ctl.link[ tp->port_id] = 1;
- #endif
-               }
-+#endif
-               if ((ability & 0x20)==0x20)
-               {
-                       if (tp->flow_control_enable == 0)
-@@ -3914,6 +3350,7 @@
-       else
-       {
-               status.bits.link = LINK_DOWN; /* link down */
-+#ifdef VITESSE_G5SWITCH
-               if(Giga_switch == 1)
-               {
-                               wan_port_id = 1;
-@@ -3925,6 +3362,7 @@
-                               storlink_ctl.link[ tp->port_id] = 0;
- #endif
-               }
-+#endif
-               if (tp->pre_phy_status == LINK_UP)
-               {
-                       printk("GMAC-%d LINK_Down......\n",tp->port_id);
-@@ -4298,86 +3736,102 @@
- }
- #ifdef CONFIG_SL_NAPI
-+
-+static int gmax_rx(struct net_device *dev, int *budget)
-+{
-+      return 0;
-+}
-+
-+static int gmac_tx(struct net_device *dev, int *budget)
-+{
-+      return 0;
-+}
-+
- /*----------------------------------------------------------------------
- * gmac_rx_poll
- *----------------------------------------------------------------------*/
- static int gmac_rx_poll(struct net_device *dev, int *budget)
- {
--      TOE_INFO_T                      *toe;
--    GMAC_RXDESC_T     *curr_desc;
--      struct sk_buff          *skb;
--    DMA_RWPTR_T                       rwptr;
--    unsigned int data32;
--      unsigned int            pkt_size;
--      unsigned int        desc_count;
--      unsigned int        good_frame, chksum_status, rx_status;
--      int                 rx_pkts_num = 0;
--      int                 quota = min(dev->quota, *budget);
--      GMAC_INFO_T                     *tp = (GMAC_INFO_T *)dev->priv;
--      unsigned int            status4;
--      volatile DMA_RWPTR_T    fq_rwptr;
--      // int                                  max_cnt = TOE_SW_FREEQ_DESC_NUM;//TOE_SW_FREEQ_DESC_NUM = 64
--      //unsigned long         rx_old_bytes;
-+      TOE_INFO_T      *toe;
-+      GMAC_RXDESC_T   *curr_desc;
-+      struct sk_buff  *skb;
-+      DMA_RWPTR_T     rwptr;
-+      unsigned int    data32;
-+      unsigned int    pkt_size;
-+      unsigned int    desc_count;
-+      unsigned int    good_frame, chksum_status, rx_status;
-+      int             rx_pkts_num = 0;
-+      int             quota = min(dev->quota, *budget);
-+      GMAC_INFO_T     *tp = (GMAC_INFO_T *)dev->priv;
-+      unsigned int    status1;
-+      unsigned int    status4;
-       struct net_device_stats *isPtr = (struct net_device_stats *)&tp->ifStatics;
--      //unsigned long long    rx_time;
--
-       BUG_ON(rx_poll_enabled == 0);
--#if 1
--      if (do_again)
--      {
--                      toe_gmac_fill_free_q();
--                      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
--                      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--                      //printk("\n%s:: do_again toe_gmac_fill_free_q =======>status4=0x%x =====fq_rwptr =0x%8x======>JKJKJKJKJKJKJKJKJ \n", __func__,status4,fq_rwptr.bits32);
--                      if (fq_rwptr.bits.wptr != fq_rwptr.bits.rptr)
--                      {
--                                              //status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
--                                              do_again =0;
--                                              //netif_rx_complete(dev);
--                                              gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4, 0x1);
--                                              fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--                                              rwptr.bits32 = readl(&tp->default_qhdr->word1);
--                      }
--                      else
--                              return 1;
--      }
--#endif
--      rwptr.bits32 = readl(&tp->default_qhdr->word1);
--#if 0
--      if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr)
--      {
--              mac_stop_txdma((struct net_device *)tp->dev);
--              printk("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n",
--                              rwptr.bits32, tp->rx_rwptr.bits.rptr);
--              while(1);
--      }
--#endif
-+
-       toe = (TOE_INFO_T *)&toe_private_data;
--      fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--      //printk("%s:---Before-------------->Default Queue HW RW ptr (0x%8x),   fq_rwptr =0x%8x \n",__func__,rwptr.bits32,fq_rwptr.bits32 );
--      //printk("%s:---Before while   rx_pkts_num=%d------rx_finished_idx=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rx_finished_idx,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
--//    while ((--max_cnt) && (rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
-+rx_poll_retry:
-+      status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+      if (status1 & 1) {
-+              writel(1, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+      }
-+      rwptr.bits32 = readl(&tp->default_qhdr->word1);
-       while ((rwptr.bits.rptr != rwptr.bits.wptr) && (rx_pkts_num < quota))
-       {
--
--      curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
-+              curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr;
-               tp->default_q_cnt++;
--      tp->rx_curr_desc = (unsigned int)curr_desc;
--      rx_status = curr_desc->word0.bits.status;
--      chksum_status = curr_desc->word0.bits.chksum_status;
--      tp->rx_status_cnt[rx_status]++;
--      tp->rx_chksum_cnt[chksum_status]++;
--        pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
-+              tp->rx_curr_desc = (unsigned int)curr_desc;
-+              rx_status = curr_desc->word0.bits.status;
-+              chksum_status = curr_desc->word0.bits.chksum_status;
-+              tp->rx_status_cnt[rx_status]++;
-+              tp->rx_chksum_cnt[chksum_status]++;
-+              pkt_size = curr_desc->word1.bits.byte_count;  /*total byte count in a frame*/
-               desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */
-               good_frame=1;
-+
-+              if (0) {
-+
-+                              int free, busy;
-+                              uint32_t rwptr1;
-+                              uint32_t rwptr2;
-+
-+                              rwptr1 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                              free = (GET_WPTR(rwptr1) - GET_RPTR(rwptr1)) & 0xFF;
-+
-+                              rwptr2 = readl(&tp->default_qhdr->word1);
-+                              busy = (GET_RPTR(rwptr2) - GET_WPTR(rwptr2)) & 0xFF;
-+
-+                              if (GET_WPTR(rwptr1) == GET_RPTR(rwptr1)) {
-+                                      printk("frame  status: %d\n"
-+                                             "SWFQ: wptr: %hu, rptr: %hu, free: %d\n"
-+                                             "GMAC: wptr: %hu, rptr: %hu, free: %d\n",
-+                                             rx_status,
-+                                             GET_WPTR(rwptr1), GET_RPTR(rwptr1), free,
-+                                             GET_WPTR(rwptr2), GET_RPTR(rwptr2), busy);
-+                              }
-+              }
-+
-+              {
-+                      GMAC_RXDESC_T   *fq_desc;
-+                      void *data;
-+                      struct sk_buff *skb;
-+                      unsigned short idx;
-+
-+                      skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-+                      idx = (unsigned short)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES + 4));
-+
-+                      BUG_ON(idx > TOE_SW_FREEQ_DESC_NUM);
-+                      BUG_ON(skb == NULL);
-+                      fq_desc = (GMAC_RXDESC_T*)toe->swfq_desc_base + idx;
-+                      fq_desc->word2.buf_adr = 0;
-+              }
-+
-               if ((curr_desc->word0.bits32 & (GMAC_RXDESC_0_T_derr | GMAC_RXDESC_0_T_perr))
--                      || (pkt_size < 60)
-+                  || (pkt_size < 60)
-                   || (chksum_status & 0x4)
-                   || rx_status )
--//                    || rx_status || (rwptr.bits.rptr > rwptr.bits.wptr ))
-               {
-                       good_frame = 0;
-                       if (curr_desc->word0.bits32 & GMAC_RXDESC_0_T_derr)
-@@ -4388,7 +3842,6 @@
-                       {
-                               if (rx_status == 4 || rx_status == 7)
-                                       isPtr->rx_crc_errors++;
--//                            printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id);
-                       }
- #ifdef SL351x_GMAC_WORKAROUND
-                       else if (pkt_size < 60)
-@@ -4407,17 +3860,32 @@
-                               }
-                       }
- #endif
--//                    if (chksum_status)
--//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
-                       skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
--                      dev_kfree_skb_irq(skb);
-+                      dev_kfree_skb(skb);
-+
-+                      if (0) {
-+                              int free, busy;
-+                              uint32_t rwptr1;
-+                              uint32_t rwptr2;
-+
-+                              rwptr1 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
-+                              free = (GET_WPTR(rwptr1) - GET_RPTR(rwptr1)) & 0xFF;
-+
-+                              rwptr2 = readl(&tp->default_qhdr->word1);
-+                              busy = (GET_RPTR(rwptr2) - GET_WPTR(rwptr2)) & 0xFF;
-+
-+                              printk("frame  status: %d\n"
-+                                     "SWFQ: wptr: %hu, rptr: %hu, free: %d\n"
-+                                     "GMAC: wptr: %hu, rptr: %hu, free: %d\n",
-+                                     rx_status,
-+                                     GET_WPTR(rwptr1), GET_RPTR(rwptr1), free,
-+                                     GET_WPTR(rwptr2), GET_RPTR(rwptr2), busy);
-+                      }
-               }
-               if (good_frame)
-               {
-                       if (curr_desc->word0.bits.drop)
-                               printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id);
--//                    if (chksum_status)
--//                            printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id);
- #ifdef SL351x_GMAC_WORKAROUND
-                       if (tp->short_frames_cnt >= GMAC_SHORT_FRAME_THRESHOLD)
-@@ -4432,225 +3900,118 @@
-                       }
-                       tp->short_frames_cnt = 0;
- #endif
--              /* get frame information from the first descriptor of the frame */
-+                      /* get frame information from the first descriptor of the frame */
-                       isPtr->rx_packets++;
--                      //consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
-+                      consistent_sync((void *)__va(curr_desc->word2.buf_adr), pkt_size, PCI_DMA_FROMDEVICE);
-                       skb = (struct sk_buff *)(REG32(__va(curr_desc->word2.buf_adr) - SKB_RESERVE_BYTES));
-                       tp->curr_rx_skb = skb;
--      //              curr_desc->word2.buf_adr = 0;
--                  //skb_reserve (skb, SKB_RESERVE_BYTES);
-                       skb_reserve (skb, RX_INSERT_BYTES);     /* 2 byte align the IP fields. */
--                      //if ((skb->tail+pkt_size) > skb->end )
--                      //printk("%s::------------->Here skb->len=%d,pkt_size= %d,skb->head=0x%x,skb->tail= 0x%x, skb->end= 0x%x\n", __func__, skb->len, pkt_size,skb->head,skb->tail,skb->end);
-                       skb_put(skb, pkt_size);
--
-                       skb->dev = dev;
-                       if (chksum_status == RX_CHKSUM_IP_UDP_TCP_OK)
-                       {
-                               skb->ip_summed = CHECKSUM_UNNECESSARY;
--#ifdef CONFIG_SL351x_NAT
--                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
--                              {
--                                      struct iphdr    *ip_hdr;
--                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
--                                      sl351x_nat_input(skb,
--                                                                      tp->port_id,
--                                                                      (void *)curr_desc->word3.bits.l3_offset,
--                                                                      (void *)curr_desc->word3.bits.l4_offset);
--                              }
--#endif
-                               skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
--#if 0
--#ifdef CONFIG_SL351x_RXTOE
--                              if (storlink_ctl.rx_max_pktsize) {
--                                      struct iphdr    *ip_hdr;
--                                      struct tcphdr   *tcp_hdr;
--                                      int ip_hdrlen;
--
--                                      ip_hdr = (struct iphdr*)&(skb->data[0]);
--                                      if ((skb->protocol == __constant_htons(ETH_P_IP)) &&
--                                         ((ip_hdr->protocol & 0x00ff) == IPPROTO_TCP)) {
--                                              ip_hdrlen = ip_hdr->ihl << 2;
--                                              tcp_hdr = (struct tcphdr*)&(skb->data[ip_hdrlen]);
--                                              if (tcp_hdr->syn) {
--                                                      struct toe_conn* connection = init_toeq(ip_hdr->version,
--                                                                      ip_hdr, tcp_hdr, toe, &(skb->data[0]) - 14);
--                                                      TCP_SKB_CB(skb)->connection = connection;
--                                                      //      hash_dump_entry(TCP_SKB_CB(skb)->connection->hash_entry_index);
--                                                      //              printk("%s::skb data %x, conn %x, mode %x\n",
--                                                      //                      __func__, skb->data, connection, connection->mode);
--                                              }
--                                      }
--                              }
--#endif
--#endif
-                       }
-                       else if (chksum_status == RX_CHKSUM_IP_OK_ONLY)
-                       {
-                               skb->ip_summed = CHECKSUM_UNNECESSARY;
--#ifdef CONFIG_SL351x_NAT
--                              if (nat_cfg.enabled && curr_desc->word3.bits.l3_offset && curr_desc->word3.bits.l4_offset)
--                              {
--                                      struct iphdr    *ip_hdr;
--                                      ip_hdr = (struct iphdr *)&(skb->data[curr_desc->word3.bits.l3_offset]);
--                                      if (ip_hdr->protocol == IPPROTO_UDP)
--                                      {
--                                              sl351x_nat_input(skb,
--                                                                              tp->port_id,
--                                                                              (void *)curr_desc->word3.bits.l3_offset,
--                                                                              (void *)curr_desc->word3.bits.l4_offset);
--                                      }
--                                      else if (ip_hdr->protocol == IPPROTO_GRE)
--                                      {
--                                              sl351x_nat_input(skb,
--                                                                      tp->port_id,
--                                                                      (void *)curr_desc->word3.bits.l3_offset,
--                                                                      (void *)curr_desc->word3.bits.l4_offset);
--                                      }
--                              }
--#endif
-                               skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-                       }
-                       else
-                       {
-                               skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */
-                       }
--                      //netif_rx(skb);  /* socket rx */
-+
-                       netif_receive_skb(skb); //For NAPI
-                       dev->last_rx = jiffies;
-                       isPtr->rx_bytes += pkt_size;
--                      //printk("------------------->isPtr->rx_bytes = %d\n",isPtr->rx_bytes);
--
-+              }
--        }
-               // advance one for Rx default Q 0/1
-               rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
-               SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
--      tp->rx_rwptr.bits32 = rwptr.bits32;
-+              tp->rx_rwptr.bits32 = rwptr.bits32;
-               rx_pkts_num++;
--              //rwptr.bits32 = readl(&tp->default_qhdr->word1);//try read default_qhdr again
--              //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--              //printk("%s:---Loop  -------->rx_pkts_num=%d------------>Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits32,fq_rwptr.bits32 );
--#if 0
--              if ((status4 & 0x1) == 0)
--              {
--                      //if (!((dev->last_rx <= (rx_time + 2)) &&  (isPtr->rx_bytes > (rx_old_bytes + 1000000 ))))
--                      if (tp->total_q_cnt_napi < 1024)
--                      {
--                              tp->total_q_cnt_napi++;
--                              toe_gmac_fill_free_q();  //for iperf test disable
--                      }
--                      //else
--                              //printk("%s:---isPtr->rx_bytes =%u , rx_old_bytes =%u\n",__func__,isPtr->rx_bytes,rx_old_bytes );
-+              // rwptr.bits32 = readl(&tp->default_qhdr->word1);
-+              status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+              if (status4 & 1) {
-+                      writel(status4 & SWFQ_EMPTY_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-               }
-+
-+              toe_gmac_fill_free_q(5);
-+      }
-+
-+#if 0
-+      /* avoid races with hard_start_xmit() */
-+
-+      spin_lock(&gmac_fq_lock);
-+      toe_gmac_tx_complete(&toe_private_data.gmac[0], 0, dev, 1);
-+      spin_unlock(&gmac_fq_lock);
- #endif
--              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
--              //printk("%s:---Loop  -------->rx_pkts_num=%d----rwptr.bits.rptr=0x%x-------->Default Queue HW RW ptr = (0x%8x),   fq_rwptr =0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits32,fq_rwptr.bits32 );
--              //printk("%s:---Loop  rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
-+
-+      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+      if (status4 & 1)
-+      {
-+              writel(status4 & SWFQ_EMPTY_INT_BIT, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_STATUS_4_REG);
-+              status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);
-+              toe_gmac_fill_free_q(rx_pkts_num);
-       }
--      // advance one for Rx default Q 0/1
--              //rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num);
--              //SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr);
--      //tp->rx_rwptr.bits32 = rwptr.bits32;
--      //rwptr.bits.rptr = rwptr.bits.rptr;
-+      rwptr.bits32 = readl(&tp->default_qhdr->word1);
-+      if (rwptr.bits.rptr != rwptr.bits.wptr &&
-+          quota > rx_pkts_num)
-+              goto rx_poll_retry;
-       dev->quota -= rx_pkts_num;
-       *budget -= rx_pkts_num;
--      status4 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG);//try read SWFQ empty again
--      //fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG);
--      rwptr.bits32 = readl(&tp->default_qhdr->word1); //try read default_qhdr again
--      //printk("%s:---After    rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
--//    if (rwptr.bits.rptr > rwptr.bits.wptr )
--//                    {
--                              //toe_gmac_disable_rx(dev);
--                              //wait_event_interruptible_timeout(freeq_wait,
--                                      //(rx_pkts_num == 100), CMTP_INTEROP_TIMEOUT);
--                              //printk("\n%s:: return 22222=======> rx_pkts_num =%d,   rwptr.bits.rptr=%d,   rwptr.bits.wptr = %d ====---------=======>JKJKJKJKJK\n",
--                                      //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
--//                            return 1;
--//                    }
--
--      if (rwptr.bits.rptr == rwptr.bits.wptr)
-+      /* Receive queue is empty now */
-+      if (quota >= rx_pkts_num)
-       {
--              // unsigned int data32;
--                      //printk("%s:---[rwptr.bits.rptr == rwptr.bits.wptr]   rx_pkts_num=%d------rwptr.bits.rptr=0x%x------->Default_Q [rwptr.bits.rptr(SW)=0x%x,   rwptr.bits.wptr(HW) = 0x%x ]---->Free_Q(SW_HW) = 0x%8x \n",__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.rptr,rwptr.bits.wptr,fq_rwptr.bits32 );
--
--          /* Receive descriptor is empty now */
--#if 1
--     if (status4 & 0x1)
--                      {
--                              do_again =1;
--                              //writel(0x40400000, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_4_REG); //disable SWFQ empty interrupt
--                              //toe_gmac_disable_interrupt(tp->irq);
--                              tp->sw_fq_empty_cnt++;
--                              //toe_gmac_disable_rx(dev);
--                              writel(0x07960202, TOE_GMAC0_BASE+GMAC_CONFIG0);
--                              writel(0x07960202, TOE_GMAC1_BASE+GMAC_CONFIG0);
--                              //printk("\n%s ::  freeq int-----tp->sw_fq_empty_cnt  =%d---------====================----------------->\n",__func__,tp->sw_fq_empty_cnt);
--                              //while ((fq_rwptr.bits.wptr >= (fq_rwptr.bits.rptr+256)) || (fq_rwptr.bits.wptr <= (fq_rwptr.bits.rptr+256)))
--                              //{
--                                      //gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_STATUS_4_REG, status4,
--                                      //0x1);
--                              //printk("\n%s::fq_rwptr.wrptr = %x =======> ===========>here \n", __func__,fq_rwptr.bits32);
--                              //if ((status4 & 0x1) == 0)
--                                      //break;
--                               return 1;
--                              //}
-+              unsigned long flags;
-+              netif_rx_complete(dev);
-+              rx_poll_enabled = 0;
-+#if 0
-+              status1 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG);
-+              if (status1 & 1) {
-+                      if (netif_rx_reschedule(dev, rx_pkts_num)) {
-+                              rx_poll_enabled = 1;
-+                              return 1;
-                       }
-+              }
- #endif
--        //toe_gmac_fill_free_q();
--        netif_rx_complete(dev);
--
--              rx_poll_enabled = 0;
--              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--              if (tp->port_id == 0)
--                              data32 |= DEFAULT_Q0_INT_BIT;
--              else
--                              data32 |= DEFAULT_Q1_INT_BIT;
--              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-+              spin_lock_irqsave(&gmac_fq_lock, flags);
-               data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
-               if (tp->port_id == 0)
--                              data32 |= DEFAULT_Q0_INT_BIT;
-+                      data32 |= DEFAULT_Q0_INT_BIT;
-               else
--                              data32 |= DEFAULT_Q1_INT_BIT;
-+                      data32 |= DEFAULT_Q1_INT_BIT;
-               writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);
--              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+              data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
-               if (tp->port_id == 0)
--                              data32 |= DEFAULT_Q0_INT_BIT;
-+                      data32 |= DEFAULT_Q0_INT_BIT;
-               else
--                              data32 |= DEFAULT_Q1_INT_BIT;
--              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG);
-+                      data32 |= DEFAULT_Q1_INT_BIT;
-+              writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--        // enable GMAC-0 rx interrupt
--        // class-Q & TOE-Q are implemented in future
--        //data32 = readl(TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--        //if (tp->port_id == 0)
--              //data32 |= DEFAULT_Q0_INT_BIT;
--        //else
--              //data32 |= DEFAULT_Q1_INT_BIT;
--        //writel(data32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG);
--              writel(0x3, TOE_GLOBAL_BASE+GLOBAL_INTERRUPT_ENABLE_1_REG);
--              //printk("\n%s::netif_rx_complete-->  rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x ====---------=======>JKJKJKJKJK\n",
--              //__func__,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
--        writel(0x07960200, TOE_GMAC0_BASE+GMAC_CONFIG0);
--              writel(0x07960200, TOE_GMAC1_BASE+GMAC_CONFIG0);
--        return 0;
--    }
--    else
--    {
--        //printk("\n%s:: return 1 -->status4= 0x%x,rx_pkts_num =%d,   rwptr.bits.rptr=0x%x,   rwptr.bits.wptr = 0x%x  ======> \n", __func__,status4,rx_pkts_num,rwptr.bits.rptr,rwptr.bits.wptr);
--        return 1;
--    }
-+              spin_unlock_irqrestore(&gmac_fq_lock, flags);
-+
-+              return 0;
-+      }
-+      else
-+      {
-+              /* not done, will call ->poll() later. */
-+              return 1;
-+      }
- }
- #endif
-@@ -5114,6 +4475,7 @@
-                       {
-                               sl351x_nat_workaround_cnt++;
-                               sl351x_nat_workaround_handler();
-+                              printk("%():%d - workaround\n", __func__, __LINE__);
-                       }
- #endif
- #endif
-@@ -5124,6 +4486,7 @@
-       }
- do_workaround:
-+      printk("doing workaround ?!\n");
-       gmac_initialized = 0;
-       if (hanged_state)
-@@ -5290,6 +4653,7 @@
-       GMAC_SWTXQ_T    *swtxq;
-       DMA_RWPTR_T             rwptr;
-+      printk("**** %s():%d\n", __func__, __LINE__);
-       toe = (TOE_INFO_T *)&toe_private_data;
-       tp = (GMAC_INFO_T *)&toe->gmac[0];
-       for (i=0; i<GMAC_NUM; i++, tp++)
-@@ -5341,6 +4705,7 @@
-       volatile GMAC_RXDESC_T  *curr_desc;
-       struct sk_buff                  *skb;
-+      printk("**** %s():%d\n", __func__, __LINE__);
-       toe = (TOE_INFO_T *)&toe_private_data;
-       tp = (GMAC_INFO_T *)&toe->gmac[0];
-       for (i=0; i<GMAC_NUM; i++, tp++)
-@@ -5374,6 +4739,7 @@
-       volatile GMAC_RXDESC_T  *curr_desc;
-       struct sk_buff                  *skb;
-+      printk("**** %s():%d\n", __func__, __LINE__);
-       toe = (TOE_INFO_T *)&toe_private_data;
-       classq = (CLASSQ_INFO_T *)&toe->classq[0];
-       for (i=0; i<TOE_CLASS_QUEUE_NUM; i++, classq++)
-@@ -5410,6 +4776,7 @@
-       GMAC_RXDESC_T   *toe_curr_desc;
-       struct sk_buff                  *skb;
-+      printk("**** %s():%d\n", __func__, __LINE__);
-       toe = (TOE_INFO_T *)&toe_private_data;
-       toe_qhdr = (TOE_QHDR_T *)TOE_TOE_QUE_HDR_BASE;
-       for (i=0; i<TOE_TOE_QUEUE_NUM; i++, toe_qhdr++)
---- a/include/asm-arm/arch-sl2312/sl351x_gmac.h
-+++ b/include/asm-arm/arch-sl2312/sl351x_gmac.h
-@@ -107,7 +107,7 @@
-  * The base address and descriptor number are configured at
-  * DMA Queues Descriptor Ring Base Address/Size Register (offset 0x0004)
-  **********************************************************************/
--#define TOE_SW_FREEQ_DESC_POWER               10
-+#define TOE_SW_FREEQ_DESC_POWER               8
- #define TOE_SW_FREEQ_DESC_NUM         (1<<TOE_SW_FREEQ_DESC_POWER)
- #define TOE_HW_FREEQ_DESC_POWER               8
- #define TOE_HW_FREEQ_DESC_NUM         (1<<TOE_HW_FREEQ_DESC_POWER)
-@@ -123,12 +123,12 @@
- #define TOE_DEFAULT_Q0_DESC_NUM               (1<<TOE_DEFAULT_Q0_DESC_POWER)
- #define TOE_DEFAULT_Q1_DESC_POWER     8
- #define TOE_DEFAULT_Q1_DESC_NUM               (1<<TOE_DEFAULT_Q1_DESC_POWER)
--#define TOE_TOE_DESC_POWER                    8
--#define TOE_TOE_DESC_NUM                      (1<<TOE_TOE_DESC_POWER)
-+#define TOE_TOE_DESC_POWER            8
-+#define TOE_TOE_DESC_NUM              (1<<TOE_TOE_DESC_POWER)
- #define TOE_CLASS_DESC_POWER          8
--#define TOE_CLASS_DESC_NUM                    (1<<TOE_CLASS_DESC_POWER)
--#define TOE_INTR_DESC_POWER                   8
--#define TOE_INTR_DESC_NUM                     (1<<TOE_INTR_DESC_POWER)
-+#define TOE_CLASS_DESC_NUM            (1<<TOE_CLASS_DESC_POWER)
-+#define TOE_INTR_DESC_POWER           8
-+#define TOE_INTR_DESC_NUM             (1<<TOE_INTR_DESC_POWER)
- #define TOE_TOE_QUEUE_MAX                     64
- #define TOE_TOE_QUEUE_NUM                     64
diff --git a/target/linux/storm/patches/1020-mtd.patch b/target/linux/storm/patches/1020-mtd.patch
deleted file mode 100644 (file)
index 8e397bc..0000000
+++ /dev/null
@@ -1,4949 +0,0 @@
---- a/drivers/mtd/chips/Kconfig
-+++ b/drivers/mtd/chips/Kconfig
-@@ -220,6 +220,13 @@
-         This option enables basic support for ROM chips accessed through
-         a bus mapping driver.
-+config MTD_SERIAL
-+      tristate "Support for Serial chips in bus mapping"
-+      depends on MTD
-+      help
-+        This option enables basic support for Serial chips accessed through
-+        a bus mapping driver.
-+
- config MTD_ABSENT
-       tristate "Support for absent chips in bus mapping"
-       help
---- a/drivers/mtd/chips/cfi_cmdset_0002.c
-+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -39,10 +39,15 @@
- #include <linux/mtd/cfi.h>
- #include <linux/mtd/xip.h>
-+//****** Storlink SoC ******
- #define AMD_BOOTLOC_BUG
--#define FORCE_WORD_WRITE 0
--
--#define MAX_WORD_RETRIES 3
-+//#define FORCE_WORD_WRITE 0
-+#define FORCE_WORD_WRITE 1
-+#define FORCE_FAST_PROG 0
-+
-+//#define MAX_WORD_RETRIES 3
-+#define MAX_WORD_RETRIES 3 // CONFIG_MTD_CFI_AMDSTD_RETRY
-+//**************************
- #define MANUFACTURER_AMD      0x0001
- #define MANUFACTURER_ATMEL    0x001F
-@@ -322,6 +327,13 @@
- #endif
-               bootloc = extp->TopBottom;
-+//****** Storlink SoC ******
-+              if(bootloc == 5)
-+              {
-+                      bootloc = 3;
-+                      extp->TopBottom = 3;
-+              }
-+//**************************
-               if ((bootloc != 2) && (bootloc != 3)) {
-                       printk(KERN_WARNING "%s: CFI does not contain boot "
-                              "bank location. Assuming top.\n", map->name);
-@@ -340,6 +352,9 @@
-                               cfi->cfiq->EraseRegionInfo[j] = swap;
-                       }
-               }
-+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
-+              cfi->device_type = CFI_DEVICETYPE_X8;
-+#endif
-               /* Set the default CFI lock/unlock addresses */
-               cfi->addr_unlock1 = 0x555;
-               cfi->addr_unlock2 = 0x2aa;
-@@ -461,6 +476,7 @@
-       map_word d, t;
-       d = map_read(map, addr);
-+      udelay(20);     //Storlink SoC
-       t = map_read(map, addr);
-       return map_word_equal(map, d, t);
-@@ -626,7 +642,9 @@
-       default:
-               printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate);
-       }
-+//****** Storlink SoC ******
-       wake_up(&chip->wq);
-+//**************************
- }
- #ifdef CONFIG_MTD_XIP
-@@ -940,7 +958,9 @@
-       cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+//****** Storlink SoC ******
-       wake_up(&chip->wq);
-+//**************************
-       spin_unlock(chip->mutex);
-       return 0;
-@@ -1005,7 +1025,10 @@
-        */
-       unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
-       int ret = 0;
--      map_word oldd;
-+//****** Storlink SoC ******
-+//    map_word oldd;
-+      map_word oldd, tmp;
-+//**************************
-       int retry_cnt = 0;
-       adr += chip->start;
-@@ -1037,9 +1060,15 @@
-       ENABLE_VPP(map);
-       xip_disable(map, chip, adr);
-  retry:
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG  /* Unlock bypass */
-+      cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+#else
-       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+#endif
-+//**************************
-       map_write(map, datum, adr);
-       chip->state = FL_WRITING;
-@@ -1072,7 +1101,13 @@
-               }
-               if (chip_ready(map, adr))
--                      break;
-+              {
-+                      tmp = map_read(map, adr);
-+                      if(map_word_equal(map, tmp, datum))
-+//                            goto op_done;
-+                break;
-+
-+              }
-               /* Latency issues. Drop the lock, wait a while and retry */
-               UDELAY(map, chip, adr, 1);
-@@ -1084,8 +1119,17 @@
-               /* FIXME - should have reset delay before continuing */
-               if (++retry_cnt <= MAX_WORD_RETRIES)
-+              {
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG
-+                      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+              //udelay(1);
-+#endif
-+                      udelay(1);
-                       goto retry;
--
-+              }
-               ret = -EIO;
-       }
-       xip_enable(map, chip, adr);
-@@ -1171,7 +1215,14 @@
-                               return 0;
-               }
-       }
--
-+//****** Storlink SoC ******
-+      map_write( map, CMD(0xF0), chipstart );
-+#if FORCE_FAST_PROG
-+              cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-+//**************************
-       /* We are now aligned, write as much as possible */
-       while(len >= map_bankwidth(map)) {
-               map_word datum;
-@@ -1181,7 +1232,15 @@
-               ret = do_write_oneword(map, &cfi->chips[chipnum],
-                                      ofs, datum);
-               if (ret)
-+              {
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG
-+                      /* Get out of unlock bypass mode */
-+                      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-                       return ret;
-+              }
-               ofs += map_bankwidth(map);
-               buf += map_bankwidth(map);
-@@ -1189,19 +1248,38 @@
-               len -= map_bankwidth(map);
-               if (ofs >> cfi->chipshift) {
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG
-+                      /* Get out of unlock bypass mode */
-+                      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-                       chipnum ++;
-                       ofs = 0;
-                       if (chipnum == cfi->numchips)
-                               return 0;
-                       chipstart = cfi->chips[chipnum].start;
-+#if FORCE_FAST_PROG
-+                      /* Go into unlock bypass mode for next set of chips */
-+                      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-               }
-       }
-+#if FORCE_FAST_PROG
-+      /* Get out of unlock bypass mode */
-+      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-+
-       /* Write the trailing bytes if any */
-       if (len & (map_bankwidth(map)-1)) {
-               map_word tmp_buf;
-  retry1:
-+
-               spin_lock(cfi->chips[chipnum].mutex);
-               if (cfi->chips[chipnum].state != FL_READY) {
-@@ -1221,7 +1299,11 @@
- #endif
-                       goto retry1;
-               }
--
-+#if FORCE_FAST_PROG
-+              cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-               tmp_buf = map_read(map, ofs + chipstart);
-               spin_unlock(cfi->chips[chipnum].mutex);
-@@ -1231,11 +1313,23 @@
-               ret = do_write_oneword(map, &cfi->chips[chipnum],
-                               ofs, tmp_buf);
-               if (ret)
-+              {
-+#if FORCE_FAST_PROG
-+      /* Get out of unlock bypass mode */
-+      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-                       return ret;
--
-+              }
-+#if FORCE_FAST_PROG
-+      /* Get out of unlock bypass mode */
-+      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-               (*retlen) += len;
-       }
-+      map_write( map, CMD(0xF0), chipstart );
-       return 0;
- }
-@@ -1275,6 +1369,7 @@
-       ENABLE_VPP(map);
-       xip_disable(map, chip, cmd_adr);
-+      map_write( map, CMD(0xF0), chip->start );       //Storlink
-       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-       //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-@@ -1535,6 +1630,9 @@
-       DECLARE_WAITQUEUE(wait, current);
-       int ret = 0;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-       adr += chip->start;
-       spin_lock(chip->mutex);
-@@ -1613,6 +1711,9 @@
-       chip->state = FL_READY;
-       put_chip(map, chip, adr);
-       spin_unlock(chip->mutex);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-       return ret;
- }
---- /dev/null
-+++ b/drivers/mtd/chips/map_serial.c
-@@ -0,0 +1,188 @@
-+/*
-+ * Common code to handle map devices which are simple ROM
-+ * (C) 2000 Red Hat. GPL'd.
-+ * $Id: map_serial.c,v 1.3 2006/06/05 02:34:54 middle Exp $
-+ */
-+
-+#include <linux/version.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+
-+#include <asm/byteorder.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+
-+#include <asm/hardware.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/init.h> //add
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/flash.h>
-+
-+static int mapserial_erase(struct mtd_info *mtd, struct erase_info *instr);
-+static int mapserial_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
-+static int mapserial_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
-+static void mapserial_nop (struct mtd_info *);
-+struct mtd_info *map_serial_probe(struct map_info *map);
-+
-+extern int m25p80_sector_erase(__u32 address, __u32 schip_en);
-+
-+static struct mtd_chip_driver mapserial_chipdrv = {
-+      probe: map_serial_probe,
-+      name: "map_serial",
-+      module: THIS_MODULE
-+};
-+
-+struct mtd_info *map_serial_probe(struct map_info *map)
-+{
-+      struct mtd_info *mtd;
-+
-+      mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
-+      if (!mtd)
-+              return NULL;
-+
-+      memset(mtd, 0, sizeof(*mtd));
-+
-+      map->fldrv = &mapserial_chipdrv;
-+      mtd->priv = map;
-+      mtd->name = map->name;
-+      mtd->type = MTD_OTHER;
-+      mtd->erase = mapserial_erase;
-+      mtd->size = map->size;
-+      mtd->read = mapserial_read;
-+      mtd->write = mapserial_write;
-+      mtd->sync = mapserial_nop;
-+      mtd->flags = (MTD_WRITEABLE|MTD_ERASEABLE);
-+//    mtd->erasesize = 512; // page size;
-+#ifdef CONFIG_MTD_SL2312_SERIAL_ST
-+      mtd->erasesize = M25P80_SECTOR_SIZE; // block size;
-+#else
-+      mtd->erasesize = 0x1000; // block size;
-+#endif
-+
-+      __module_get(THIS_MODULE);
-+      //MOD_INC_USE_COUNT;
-+      return mtd;
-+}
-+
-+#define       FLASH_ACCESS_OFFSET                             0x00000010
-+#define       FLASH_ADDRESS_OFFSET                            0x00000014
-+#define       FLASH_WRITE_DATA_OFFSET                         0x00000018
-+#define       FLASH_READ_DATA_OFFSET                          0x00000018
-+
-+static __u32 readflash_ctrl_reg(__u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    return __raw_readl(base);
-+}
-+
-+static void writeflash_ctrl_reg(__u32 data, __u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    __raw_writel(data, base);
-+}
-+
-+static int mapserial_erase_block(struct map_info *map,unsigned int block)
-+{
-+
-+      __u32 address;
-+#ifdef CONFIG_MTD_SL2312_SERIAL_ST
-+
-+      if(!m25p80_sector_erase(block, 0))
-+              return (MTD_ERASE_DONE);
-+#else
-+      __u32 opcode;
-+      __u32 count=0;
-+//      __u8  status;
-+
-+ //     printk("mapserial_erase_block : erase block %d \n",block);
-+//      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd;
-+      opcode = 0x80000000 | 0x0200 | 0x50;
-+      address = (block << 13);
-+      writeflash_ctrl_reg(address,FLASH_ADDRESS_OFFSET);
-+      writeflash_ctrl_reg(opcode,FLASH_ACCESS_OFFSET);
-+      opcode=readflash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode = readflash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          count++;
-+          if (count > 10000)
-+          {
-+            return (MTD_ERASE_FAILED);
-+          }
-+      }
-+      return (MTD_ERASE_DONE);
-+#endif
-+}
-+
-+static int mapserial_erase(struct mtd_info *mtd, struct erase_info *instr)
-+{
-+      struct map_info *map = (struct map_info *)mtd->priv;
-+    unsigned int    addr;
-+    int             len;
-+    unsigned int    block;
-+    unsigned int    ret=0;
-+
-+      addr = instr->addr;
-+      len = instr->len;
-+    while (len > 0)
-+    {
-+        block = addr / mtd->erasesize;
-+#ifdef CONFIG_MTD_SL2312_SERIAL_ST
-+        ret = mapserial_erase_block(map,addr);
-+#else
-+              ret = mapserial_erase_block(map,block);
-+#endif
-+        addr = addr + mtd->erasesize;
-+        len = len - mtd->erasesize;
-+    }
-+    return (ret);
-+}
-+
-+static int mapserial_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
-+{
-+      struct map_info *map = (struct map_info *)mtd->priv;
-+//        printk("mapserial_read : \n");
-+      map->copy_from(map, buf, from, len);
-+      *retlen = len;
-+      return 0;
-+}
-+
-+static void mapserial_nop(struct mtd_info *mtd)
-+{
-+      /* Nothing to see here */
-+}
-+
-+static int mapserial_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
-+{
-+      struct map_info *map = (struct map_info *)mtd->priv;
-+//    printk("mapserial_write : buf %x to %x len %x \n",(int)buf, (int)to, (int)len);
-+      //map->copy_to(map, buf, to, len);
-+      map->copy_to(map, to, buf, len);
-+      *retlen = len;
-+      return 0;
-+}
-+
-+int __init map_serial_init(void)
-+{
-+      register_mtd_chip_driver(&mapserial_chipdrv);
-+      return 0;
-+}
-+
-+static void __exit map_serial_exit(void)
-+{
-+      unregister_mtd_chip_driver(&mapserial_chipdrv);
-+}
-+
-+module_init(map_serial_init);
-+module_exit(map_serial_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-+MODULE_DESCRIPTION("MTD chip driver for ROM chips");
---- a/drivers/mtd/maps/Kconfig
-+++ b/drivers/mtd/maps/Kconfig
-@@ -614,5 +614,30 @@
-         This selection automatically selects the map_ram driver.
-+#***************************************************************************************
-+# Storlink parallel/Serial Flash configuration
-+#***************************************************************************************
-+config MTD_SL2312_CFI
-+        tristate "CFI Flash device mapped on SL2312"
-+        depends on MTD_CFI
-+        help
-+          Map driver for SL2312 demo board.
-+
-+config MTD_SL2312_SERIAL_ATMEL
-+        tristate "ATMEL Serial Flash device mapped on SL2312"
-+        depends on MTD_PARTITIONS && ARCH_SL2312
-+        help
-+          Map driver for SL2312 demo board.
-+
-+config MTD_SL2312_SERIAL_ST
-+        tristate "ST Serial Flash device mapped on SL2312"
-+        depends on MTD_PARTITIONS && ARCH_SL2312
-+        help
-+          Map driver for SL2312 demo board.
-+
-+config SL2312_SHARE_PIN
-+        tristate "Parallel Flash share pin on SL2312 ASIC"
-+        depends on SL3516_ASIC
-+
- endmenu
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312-flash-atmel.c
-@@ -0,0 +1,554 @@
-+/*
-+ * $Id: sl2312-flash-atmel.c,v 1.2 2006/06/05 02:35:57 middle Exp $
-+ *
-+ * Flash and EPROM on Hitachi Solution Engine and similar boards.
-+ *
-+ * (C) 2001 Red Hat, Inc.
-+ *
-+ * GPL'd
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+#include <asm/hardware.h>
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/flash.h>
-+#include <linux/init.h> //add
-+
-+
-+#define  g_page_addr  AT45DB321_PAGE_SHIFT    //321 : shift 10  ; 642 : shift 11
-+#define  g_chipen     SERIAL_FLASH_CHIP0_EN   //atmel
-+
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+void address_to_page(__u32 address, __u16 *page, __u16 *offset)
-+{
-+    *page = address / SPAGE_SIZE;
-+    *offset = address % SPAGE_SIZE;
-+}
-+
-+static __u32 read_flash_ctrl_reg(__u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    return __raw_readl(base);
-+}
-+
-+static void write_flash_ctrl_reg(__u32 ofs,__u32 data)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    __raw_writel(data, base);
-+}
-+
-+void atmel_read_status(__u8 cmd, __u8 *data)
-+{
-+      __u32 opcode;
-+      __u32 value;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | cmd | g_chipen;
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      *data = value & 0xff;
-+}
-+
-+void main_memory_page_read(__u8 cmd, __u16 page, __u16 offset, __u8 *data)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u32 value;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA | cmd | g_chipen;
-+      address = (page << g_page_addr) + offset;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      *data = value & 0xff;
-+}
-+
-+void buffer_to_main_memory(__u8 cmd, __u16 page)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (page << g_page_addr);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+
-+void atmel_flash_read_page(__u32 address, __u8 *buffer, __u32 len)
-+{
-+    __u8  byte;
-+    __u16 page, offset;
-+    __u16 i;
-+
-+    address_to_page(address, &page, &offset);
-+
-+     for(i=0; i<len; i++,offset++)
-+    {
-+        main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
-+        buffer [i]= byte;
-+    }
-+}
-+
-+void atmel_flash_program_page(__u32 address, __u8 *buffer, __u32 len)
-+{
-+    __u8  pattern;
-+    __u16 page, offset;
-+    __u32 i;
-+
-+    address_to_page(address, &page, &offset);
-+ //   printk("atmel_flash_program_page: offset %x len %x page %x \n", offset, len, page);
-+
-+    if(offset)
-+          main_memory_to_buffer(MAIN_MEMORY_TO_BUFFER1,page);
-+
-+    for(i=0; i<len; i++,offset++)
-+    {
-+        pattern = buffer[i];
-+        atmel_buffer_write(BUFFER1_WRITE,offset,pattern);
-+    }
-+
-+  //  printk("atmel_flash_program_page: offset %x \n", offset);
-+    buffer_to_main_memory(BUFFER1_TO_MAIN_MEMORY, page);
-+  //  printk("atmel_flash_program_page: buffer_to_main_memory %x page\n", page);
-+
-+}
-+
-+
-+void main_memory_to_buffer(__u8 cmd, __u16 page)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (page << g_page_addr);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void main_memory_page_program(__u8 cmd, __u16 page, __u16 offset, __u8 data)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | cmd | g_chipen;
-+      address = (page << g_page_addr) + offset;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, data);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+}
-+
-+void atmel_buffer_write(__u8 cmd, __u16 offset, __u8 data)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | cmd  | g_chipen;
-+      address = offset;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, data);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void atmel_erase_page(__u8 cmd, __u16 page)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (page << g_page_addr);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void atmel_erase_block(__u8 cmd, __u16 block)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (block << 13);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void flash_delay(void)
-+{
-+      int i;
-+
-+      for(i=0; i<50; i++)
-+           i=i;
-+}
-+
-+
-+
-+
-+__u32 sl2312_read32(struct map_info *map, unsigned long ofs)
-+{
-+
-+#if 0
-+    __u16 page, offset;
-+    __u32 pattern;
-+    __u8  byte, i;
-+
-+     pattern = 0;
-+     address_to_page(ofs, &page, &offset);
-+     for(i=0; i<4; i++, offset++)
-+    {
-+        pattern = pattern << 8;
-+        main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
-+//printk("sl2312_read32:: address = %08x  data = %c \n",ofs,byte);
-+        pattern += byte;
-+    }
-+    return pattern;
-+#else
-+      return read_flash_ctrl_reg(ofs);
-+#endif
-+
-+}
-+
-+__u8 sl2312_read8(struct map_info *map, unsigned long ofs)
-+{
-+    __u16 page, offset;
-+    __u8  byte;
-+
-+     address_to_page(ofs, &page, &offset);
-+     main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
-+       //printk("sl2312_read8:: address = %08x  data = %c \n",ofs,byte);
-+     return byte;
-+
-+}
-+
-+void sl2312_write32(struct map_info *map, __u32 d, unsigned long ofs)
-+{
-+#if 0
-+    __u16 page, offset;
-+    __u8  byte, i;
-+
-+     address_to_page(ofs, &page, &offset);
-+     for(i=0; i<4; i++, offset++)
-+    {
-+      byte = d & 0xff;
-+        main_memory_page_program(MAIN_MEMORY_PROGRAM_BUFFER1, page, offset, byte);
-+        d = d >> 8;
-+//printk("sl2312_write32:: address = %08x  data = %c \n",ofs,byte);
-+    }
-+#else
-+      write_flash_ctrl_reg(ofs, d);
-+#endif
-+}
-+
-+void sl2312_write8(struct map_info *map, __u8 d, unsigned long ofs)
-+{
-+     __u16 page, offset;
-+
-+     address_to_page(ofs, &page, &offset);
-+     main_memory_page_program(MAIN_MEMORY_PROGRAM_BUFFER1, page, offset, d);
-+//printk("sl2312_write8:: address = %08x  data = %c \n",ofs,d);
-+
-+}
-+
-+void sl2312_copy_from(struct map_info *map, void *buf, unsigned long ofs, ssize_t len)
-+{
-+     __u32 size;
-+     __u8  *buffer;
-+     __u32 length;//i, j,
-+
-+     //printk("sl2312_copy_from:: address = %08x  datalen = %d \n",ofs,len);
-+
-+     length = len;
-+     buffer = (__u8 *)buf;
-+     while(len)
-+     {
-+        size = SPAGE_SIZE - (ofs%SPAGE_SIZE);
-+        if(size > len)
-+            size = len;
-+        atmel_flash_read_page(ofs, buffer, size);
-+        buffer+=size;
-+        ofs+=size;
-+        len -= size;
-+     }
-+
-+#if 0
-+        buffer = (__u8 *)buf;
-+        for(i=0; i<length; i+=16)
-+       {
-+          for(j=0; j<16; j++,buffer++)
-+         {
-+            if((i*16+j)<length)
-+              printk("%x  ",(int)*buffer);
-+       }
-+          printk("\n");
-+       }
-+
-+       printk("\n");
-+#endif
-+
-+}
-+
-+
-+void sl2312_copy_to(struct map_info *map, unsigned long ofs, void *buf, ssize_t len)
-+{
-+     __u32 size;
-+     __u8  *buffer;
-+
-+     buffer = (__u8 *)buf;
-+     //printk("sl2312_copy_to:offset %x len %x \n", ofs, len);
-+//     printk("sl2312_copy_to:buf is %x \n", (int)buf);
-+
-+     while(len)
-+     {
-+        size = SPAGE_SIZE - (ofs%SPAGE_SIZE);
-+        if(size > len)
-+            size = len;
-+        atmel_flash_program_page(ofs, buffer, size);
-+        buffer+=size;
-+        ofs+=size;
-+      len-=size;
-+    }
-+
-+
-+}
-+
-+
-+static struct mtd_info *serial_mtd;
-+
-+static struct mtd_partition *parsed_parts;
-+
-+static struct map_info sl2312_serial_map = {
-+//    name: "SL2312 serial flash",
-+//    size: 4194304, //0x400000,
-+//            //buswidth: 4,
-+//    bankwidth: 4,
-+//    phys:            SL2312_FLASH_BASE,
-+//#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
-+//    //read32: sl2312_read32,
-+//    //read8: sl2312_read8,
-+//    copy_from: sl2312_copy_from,
-+//    //write8: sl2312_write8,
-+//    //write32: sl2312_write32,
-+//    read: sl2312_read32,
-+//    write: sl2312_write32,
-+//    copy_to: sl2312_copy_to
-+//#endif
-+      .name = "SL2312 serial flash",
-+      .size = 4194304, //0x400000,
-+              //buswidth: 4,
-+      .bankwidth = 4,
-+      .phys =          SL2312_FLASH_BASE,
-+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
-+      //read32: sl2312_read32,
-+      //read8: sl2312_read8,
-+      .copy_from = sl2312_copy_from,
-+      //write8: sl2312_write8,
-+      //write32: sl2312_write32,
-+      .read = sl2312_read32,
-+      .write = sl2312_write32,
-+      .copy_to = sl2312_copy_to
-+#endif
-+};
-+
-+
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+
-+
-+      ///* boot code */
-+      //{ name: "bootloader", offset: 0x00000000, size: 0x20000, },
-+      ///* kernel image */
-+      //{ name: "kerel image", offset: 0x000020000, size: 0x2E0000 },
-+      ///* All else is writable (e.g. JFFS) */
-+      //{ name: "user data", offset: 0x00300000, size: 0x00100000, },
-+      /* boot code */
-+      { .name = "bootloader", .offset = 0x00000000, .size = 0x20000, },
-+      /* kernel image */
-+      { .name = "kerel image", .offset = 0x000020000, .size = 0xE0000 },
-+      /* All else is writable (e.g. JFFS) */
-+      { .name = "user data", .offset = 0x00100000, .size = 0x00300000, },
-+
-+
-+};
-+
-+
-+
-+static int __init init_sl2312_maps(void)
-+{
-+      int nr_parts = 0;
-+      struct mtd_partition *parts;
-+
-+      serial_mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-+      if (!serial_mtd)
-+              return NULL;
-+
-+      memset(serial_mtd, 0, sizeof(struct mtd_info));
-+      //sl2312flash_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
-+    //sl2312_serial_map.map_priv_1 = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)FLASH_VBASE;
-+    sl2312_serial_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)ioremap(FLASH_START, SFLASH_SIZE);
-+    if (!sl2312_serial_map.virt) {
-+              printk(" failed to ioremap \n");
-+              return -EIO;
-+      }
-+      serial_mtd = do_map_probe("map_serial", &sl2312_serial_map);
-+      if (serial_mtd) {
-+              //serial_mtd->module = THIS_MODULE;
-+              serial_mtd->owner = THIS_MODULE;
-+
-+      }
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+      nr_parts = parse_redboot_partitions(serial_mtd, &parsed_parts);
-+      if (nr_parts > 0)
-+              printk(KERN_NOTICE "Found RedBoot partition table.\n");
-+      else if (nr_parts < 0)
-+              printk(KERN_NOTICE "Error looking for RedBoot partitions.\n");
-+#else
-+      parsed_parts = sl2312_partitions;
-+      parts = sl2312_partitions;
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parsed_parts);
-+#endif /* CONFIG_MTD_REDBOOT_PARTS */
-+
-+      if (nr_parts > 0)
-+          add_mtd_partitions(serial_mtd, parsed_parts, nr_parts);
-+      else
-+          add_mtd_device(serial_mtd);
-+
-+      return 0;
-+}
-+
-+static void __exit cleanup_sl2312_maps(void)
-+{
-+      if (parsed_parts)
-+          del_mtd_partitions(serial_mtd);
-+      else
-+          del_mtd_device(serial_mtd);
-+
-+      map_destroy(serial_mtd);
-+
-+
-+}
-+
-+module_init(init_sl2312_maps);
-+module_exit(cleanup_sl2312_maps);
-+
-+
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Plus Chen <plus@storlink.com.tw>");
-+MODULE_DESCRIPTION("MTD map driver for Storlink Sword boards");
-+
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312-flash-cfi.c
-@@ -0,0 +1,370 @@
-+/*======================================================================
-+
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 2 of the License, or
-+   (at your option) any later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software
-+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+======================================================================*/
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/string.h>
-+
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/system.h>
-+#include <asm/arch/sl2312.h>
-+#include <linux/mtd/kvctl.h>
-+#include "sl2312_flashmap.h"
-+
-+
-+//extern int parse_afs_partitions(struct mtd_info *, struct mtd_partition **);
-+
-+/* the base address of FLASH control register */
-+#define FLASH_CONTROL_BASE_ADDR           (IO_ADDRESS(SL2312_FLASH_CTRL_BASE))
-+#define SL2312_GLOBAL_BASE_ADDR     (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+
-+/* define read/write register utility */
-+#define FLASH_READ_REG(offset)                        (__raw_readl(offset+FLASH_CONTROL_BASE_ADDR))
-+#define FLASH_WRITE_REG(offset,val)   (__raw_writel(val,offset+FLASH_CONTROL_BASE_ADDR))
-+
-+/* the offset of FLASH control register */
-+enum EMAC_REGISTER {
-+      FLASH_ID        = 0x0000,
-+      FLASH_STATUS    = 0x0008,
-+      FLASH_TYPE      = 0x000c,
-+      FLASH_ACCESS    = 0x0020,
-+      FLASH_ADDRESS   = 0x0024,
-+      FLASH_DATA              = 0x0028,
-+      FLASH_TIMING    = 0x002c,
-+};
-+
-+//#define FLASH_BASE  FLASH_CONTROL_BASE_ADDR
-+//#define FLASH_SIZE  0x00800000 //INTEGRATOR_FLASH_SIZE
-+
-+//#define FLASH_PART_SIZE 8388608
-+
-+static unsigned int flash_indirect_access = 0;
-+
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+static unsigned int chip_en = 0x00000000;
-+
-+void sl2312flash_enable_parallel_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val & 0xfffffffd;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+
-+void sl2312flash_disable_parallel_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val | 0x00000002;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+#endif
-+
-+
-+static struct map_info sl2312flash_map =
-+{
-+      name:           "SL2312 CFI Flash",
-+      size:       FLASH_SIZE,
-+      bankwidth:   2,
-+      //bankwidth:   1, //for 8 bits width
-+    phys:       SL2312_FLASH_BASE,
-+};
-+
-+static struct mtd_info *mtd;
-+#if 0
-+static struct mtd_partition sl2312_partitions[] = {
-+      /* boot code */
-+      {
-+              name: "bootloader",
-+              offset: 0x00000000,
-+              size: 0x20000,
-+//            mask_flags: MTD_WRITEABLE,
-+      },
-+      /* kernel image */
-+      {
-+              name: "kerel image",
-+              offset: 0x00020000,
-+              size: 0x2E0000
-+      },
-+      /* All else is writable (e.g. JFFS) */
-+      {
-+              name: "user data",
-+              offset: 0x00300000,
-+              size: 0x00100000,
-+      }
-+};
-+#endif
-+
-+
-+
-+static int __init sl2312flash_init(void)
-+{
-+      struct mtd_partition *parts;
-+      int nr_parts = 0;
-+      int ret;
-+#ifndef CONFIG_SL2312_SHARE_PIN
-+    unsigned int    reg_val;
-+#endif
-+
-+    printk("SL2312 MTD Driver Init.......\n");
-+
-+#ifndef CONFIG_SL2312_SHARE_PIN
-+      /* enable flash */
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val & 0xfffffffd;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+#else
-+    sl2312flash_enable_parallel_flash();      /* enable Parallel FLASH */
-+#endif
-+    FLASH_WRITE_REG(FLASH_ACCESS,0x00004000); /* parallel flash direct access mode */
-+    ret = FLASH_READ_REG(FLASH_ACCESS);
-+    if (ret == 0x00004000)
-+    {
-+        flash_indirect_access = 0;  /* parallel flash direct access */
-+    }
-+    else
-+    {
-+        flash_indirect_access = 1;  /* parallel flash indirect access */
-+    }
-+
-+      /*
-+       * Also, the CFI layer automatically works out what size
-+       * of chips we have, and does the necessary identification
-+       * for us automatically.
-+       */
-+#ifdef CONFIG_GEMINI_IPI
-+      sl2312flash_map.virt = FLASH_VBASE;//(unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
-+#else
-+      sl2312flash_map.virt = (unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
-+#endif
-+      //printk("sl2312flash_map.virt  = %08x\n",(unsigned int)sl2312flash_map.virt);
-+
-+//    simple_map_init(&sl2312flash_map);
-+
-+      mtd = do_map_probe("cfi_probe", &sl2312flash_map);
-+      if (!mtd)
-+      {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+        sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
-+#endif
-+              return -ENXIO;
-+      }
-+      mtd->owner = THIS_MODULE;
-+//    mtd->erase = flash_erase;
-+//    mtd->read = flash_read;
-+//    mtd->write = flash_write;
-+
-+    parts = sl2312_partitions;
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
-+      ret = add_mtd_partitions(mtd, parts, nr_parts);
-+      /*If we got an error, free all resources.*/
-+      if (ret < 0) {
-+              del_mtd_partitions(mtd);
-+              map_destroy(mtd);
-+      }
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+    sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
-+#endif
-+    printk("SL2312 MTD Driver Init Success ......\n");
-+      return ret;
-+}
-+
-+static void __exit sl2312flash_exit(void)
-+{
-+      if (mtd) {
-+              del_mtd_partitions(mtd);
-+              map_destroy(mtd);
-+      }
-+
-+      if (sl2312flash_map.virt) {
-+          iounmap((void *)sl2312flash_map.virt);
-+          sl2312flash_map.virt = 0;
-+      }
-+}
-+
-+char chrtohex(char c)
-+{
-+  char val;
-+  if ((c >= '0') && (c <= '9'))
-+  {
-+    val = c - '0';
-+    return val;
-+  }
-+  else if ((c >= 'a') && (c <= 'f'))
-+  {
-+    val = 10 + (c - 'a');
-+    return val;
-+  }
-+  else if ((c >= 'A') && (c <= 'F'))
-+  {
-+    val = 10 + (c - 'A');
-+    return val;
-+  }
-+  printk("<1>Error number\n");
-+  return 0;
-+}
-+
-+
-+int get_vlaninfo(vlaninfo* vlan)
-+{
-+      vctl_mheader head;
-+      vctl_entry entry;
-+      struct mtd_info *mymtd=NULL;
-+      int i, j, loc = 0;
-+      char *payload=0, *tmp1, *tmp2, tmp3[9];
-+      size_t retlen;
-+
-+      #ifdef CONFIG_SL2312_SHARE_PIN
-+      sl2312flash_enable_parallel_flash();
-+      #endif
-+      for(i=0;i<MAX_MTD_DEVICES;i++)
-+      {
-+              mymtd=get_mtd_device(NULL,i);
-+              //    printk("mymtd->name: %s\n", mymtd->name);
-+              if(mymtd && !strcmp(mymtd->name,"VCTL"))
-+              {
-+                      //      printk("%s\n", mymtd->name);
-+                      break;
-+              }
-+      }
-+      if( i >= MAX_MTD_DEVICES)
-+      {
-+              printk("Can't find version control\n");
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              return 0;
-+      }
-+
-+      if (!mymtd | !mymtd->read)
-+      {
-+              printk("<1>Can't read Version Configuration\n");
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              return 0;
-+      }
-+
-+      mymtd->read(mymtd, 0, VCTL_HEAD_SIZE, &retlen, (u_char*)&head);
-+      //  printk("entry header: %c%c%c%c\n", head.header[0], head.header[1], head.header[2], head.header[3]);
-+      //  printk("entry number: %x\n", head.entry_num);
-+      if ( strncmp(head.header, "FLFM", 4) )
-+      {
-+              printk("VCTL is a erase block\n");
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              return 0;
-+      }
-+      loc += retlen;
-+      for (i = 0; i < head.entry_num; i++)
-+      {
-+              mymtd->read(mymtd, loc, VCTL_ENTRY_LEN, &retlen, (u_char*)&entry);
-+              //    printk("type: %x\n", entry.type);
-+              //    printk("size: %x\n", entry.size);
-+              strncpy(tmp3, entry.header, 4);
-+              if (entry.type == VCT_VLAN)
-+              {
-+                      for (j = 0; j < 6 ; j++)
-+                      {
-+                              vlan[0].mac[j] = 0;
-+                              vlan[1].mac[j] = 0;
-+                      }
-+                      vlan[0].vlanid = 1;
-+                      vlan[1].vlanid = 2;
-+                      vlan[0].vlanmap = 0x7F;
-+                      vlan[1].vlanmap = 0x80;
-+
-+                      payload = (char *)kmalloc(entry.size - VCTL_ENTRY_LEN, GFP_KERNEL);
-+                      loc += VCTL_ENTRY_LEN;
-+                      mymtd->read(mymtd, loc, entry.size - VCTL_ENTRY_LEN, &retlen, payload);
-+                      //      printk("%s\n", payload);
-+                      tmp1 = strstr(payload, "MAC1:");
-+                      tmp2 = strstr(payload, "MAC2:");
-+                      if(!tmp1||!tmp2){
-+                              kfree(payload);
-+                              #ifdef CONFIG_SL2312_SHARE_PIN
-+                              sl2312flash_disable_parallel_flash();
-+                              #endif
-+                              printk("Error VCTL format!!\n");
-+                              return 0;
-+                      }
-+                      tmp1 += 7;
-+                      tmp2 += 7;
-+
-+
-+                      for (j = 0; j < 6; j++)
-+                      {
-+                              vlan[0].mac[j] = chrtohex(tmp1[2*j])*16 + chrtohex(tmp1[(2*j)+1]);
-+                              vlan[1].mac[j] = chrtohex(tmp2[2*j])*16 + chrtohex(tmp2[(2*j)+1]);
-+                      }
-+                      tmp1 = strstr(payload, "ID1:");
-+                      tmp2 = strstr(payload, "ID2:");
-+                      tmp1 += 4;
-+                      tmp2 += 4;
-+                      vlan[0].vlanid = tmp1[0] - '0';
-+                      vlan[1].vlanid = tmp2[0] - '0';
-+                      tmp1 = strstr(payload, "MAP1:");
-+                      tmp2 = strstr(payload, "MAP2:");
-+                      tmp1 += 7;
-+                      tmp2 += 7;
-+                      vlan[0].vlanmap = chrtohex(tmp1[0]) * 16 + chrtohex(tmp1[1]);
-+                      vlan[1].vlanmap = chrtohex(tmp2[0]) * 16 + chrtohex(tmp2[1]);
-+                      //  printk("Vlan1 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[0].vlanid, vlan[0].vlanmap, vlan[0].mac[0], vlan[0].mac[1], vlan[0].mac[2], vlan[0].mac[3], vlan[0].mac[4], vlan[0].mac[5]);
-+                      //  printk("Vlan2 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[1].vlanid, vlan[1].vlanmap, vlan[1].mac[0], vlan[1].mac[1], vlan[1].mac[2], vlan[1].mac[3], vlan[1].mac[4], vlan[1].mac[5]);
-+                      break;
-+              }
-+              loc += entry.size;
-+      }
-+      if ( entry.type == VCT_VLAN )
-+      {
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              kfree(payload);
-+              return 1;
-+      }
-+      if (i >= head.entry_num)
-+      printk("Can't find vlan information\n");
-+      #ifdef CONFIG_SL2312_SHARE_PIN
-+      sl2312flash_disable_parallel_flash();
-+      #endif
-+      return 0;
-+}
-+
-+EXPORT_SYMBOL(get_vlaninfo);
-+
-+
-+module_init(sl2312flash_init);
-+module_exit(sl2312flash_exit);
-+
-+MODULE_AUTHOR("Storlink Ltd");
-+MODULE_DESCRIPTION("CFI map driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312-flash-m25p80.c
-@@ -0,0 +1,498 @@
-+/*
-+ * $Id: sl2312-flash-m25p80.c,v 1.2 2006/06/02 08:46:02 middle Exp $
-+ *
-+ * Flash and EPROM on Hitachi Solution Engine and similar boards.
-+ *
-+ * (C) 2001 Red Hat, Inc.
-+ *
-+ * GPL'd
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+#include <asm/hardware.h>
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/flash.h>
-+#include <linux/init.h> //add
-+#define  g_chipen     SERIAL_FLASH_CHIP0_EN   //ST
-+
-+//static int m25p80_page_program(__u32 address, __u8 data, __u32 schip_en);
-+static void m25p80_write_cmd(__u8 cmd, __u32 schip_en);
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+
-+static __u32 read_flash_ctrl_reg(__u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    return __raw_readl(base);
-+}
-+
-+static void write_flash_ctrl_reg(__u32 ofs,__u32 data)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    __raw_writel(data, base);
-+}
-+
-+static void m25p80_read(__u32 address, __u8 *data, __u32 schip_en)
-+{
-+      __u32 opcode,status;
-+      __u32 value;
-+
-+      //opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ;
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | M25P80_READ;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      status=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(status&0x80000000)
-+      {
-+          status=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      *data = value & 0xff;
-+}
-+
-+static int m25p80_page_program(__u32 address, __u8 *data, __u32 schip_en)
-+{
-+      __u32 opcode;
-+      __u32  status;
-+        __u32 tmp;
-+        int res = FLASH_ERR_OK;
-+        //volatile FLASH_DATA_T* data_ptr = (volatile FLASH_DATA_T*) data;
-+        opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+
-+                    opcode|=g_chipen;
-+
-+          write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+          //middle delay_ms(130);
-+          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+          if((status&0x02)==0x02)
-+                {
-+                     //middle delay_ms(100);
-+               m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
-+          }
-+
-+
-+      m25p80_write_cmd(M25P80_WRITE_ENABLE, schip_en);
-+      ////middle delay_ms(10);
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | M25P80_PAGE_PROGRAM;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, *data);
-+
-+      //status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //while(status!=data)
-+      //{
-+      //    status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //    //middle delay_ms(10);
-+      //}
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+      //opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+
-+              opcode|=g_chipen;
-+
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //while(status&0xfd)
-+      while(status&0x01)
-+      {
-+                //if((status&0x9c)!=0)
-+                //    printf("  m25p80_page_program   Protect Status = %x\n",status);
-+                write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+          flash_delay();
-+          schedule();
-+          //middle delay_ms(50);
-+      }
-+      //printf("status = %x, data = %x\n",status,data);
-+      if((status&0x02)==0x02)
-+      {
-+        //middle delay_ms(100);
-+          m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
-+      }
-+    //};//while (len > 0)
-+    return res;
-+}
-+
-+void m25p80_copy_from(struct map_info *map, void *buf, unsigned long ofs, ssize_t len)
-+{
-+//     __u32 size;
-+     __u8  *buffer;
-+     __u32 length;//i, j,
-+
-+      length = len;
-+     buffer = (__u8 *)buf;
-+     while(len)
-+     {
-+        m25p80_read(ofs, buffer, g_chipen);
-+        buffer++;
-+        ofs++;
-+        len --;
-+     }        ;
-+
-+}
-+
-+__u32 m25p80_read32(struct map_info *map, unsigned long ofs)
-+{
-+
-+      return read_flash_ctrl_reg(ofs);
-+
-+
-+}
-+
-+void m25p80_write32(struct map_info *map, __u32 d, unsigned long ofs)
-+{
-+
-+      write_flash_ctrl_reg(ofs, d);
-+
-+}
-+
-+void m25p80_copy_to(struct map_info *map, unsigned long ofs, void *buf, ssize_t len)
-+{
-+     __u32 size, i, ret;
-+
-+     while(len > 0)
-+     {
-+        if(len >= M25P80_PAGE_SIZE)
-+                      size = M25P80_PAGE_SIZE;
-+              else
-+                      size = len;
-+
-+        for(i=0;i<size;i++)
-+          {
-+              ret = m25p80_page_program( (ofs+i),  (buf+i),  g_chipen);
-+          }
-+        buf+=M25P80_PAGE_SIZE;
-+        ofs+=M25P80_PAGE_SIZE;
-+              len-=M25P80_PAGE_SIZE;
-+
-+    };
-+
-+
-+}
-+
-+static struct mtd_info *serial_mtd;
-+
-+static struct mtd_partition *parsed_parts;
-+
-+static struct map_info m25p80_map = {
-+
-+      .name = "SL2312 serial flash m25p80",
-+      .size = 1048576, //0x100000,
-+              //buswidth: 4,
-+      .bankwidth = 4,
-+      .phys =          SL2312_FLASH_BASE,
-+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
-+      .copy_from = m25p80_copy_from,
-+      .read = m25p80_read32,
-+      .write = m25p80_write32,
-+      .copy_to = m25p80_copy_to
-+#endif
-+};
-+
-+
-+
-+static struct mtd_partition m25p80_partitions[] = {
-+
-+      /* boot code */
-+      { .name = "bootloader", .offset = 0x00000000, .size = 0x20000, },
-+      /* kernel image */
-+      { .name = "kerel image", .offset = 0x000020000, .size = 0xC0000 },
-+      /* All else is writable (e.g. JFFS) */
-+      { .name = "user data", .offset = 0x000E0000, .size = 0x00010000, },
-+
-+
-+};
-+
-+void flash_delay()
-+{
-+      int i,j;
-+      for(i=0;i<0x100;i++)
-+              j=i*3+5;
-+}
-+
-+int m25p80_sector_erase(__u32 address, __u32 schip_en)
-+{
-+      __u32 opcode;
-+      __u32  status;
-+      __u32 tmp;
-+      int res = FLASH_ERR_OK;
-+      //printf("\n-->m25p80_sector_erase");
-+      if(address >= FLASH_START)
-+              address-=FLASH_START;
-+
-+      m25p80_write_cmd(M25P80_WRITE_ENABLE, schip_en);
-+      //printf("\n     m25p80_sector_erase : after we-en");
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | M25P80_SECTOR_ERASE;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      #ifdef MIDWAY_DIAG
-+              opcode|=schip_en;
-+      #endif
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+      #ifdef MIDWAY_DIAG
-+              opcode|=schip_en;
-+      #endif
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //while(status&0xfd)
-+      while(status&0x01)
-+      {
-+                //if((status&0x9c)!=0)
-+                //    printf("  m25p80_sector_erase   Protect Status = %x\n",status);
-+                write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+          flash_delay();
-+          schedule();
-+          //middle delay_ms(50);
-+      }
-+      if((status&0x02)==0x02)
-+      {
-+                //middle delay_ms(100);
-+          m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
-+      }
-+      //printf("\n<--m25p80_sector_erase");
-+      return res;
-+}
-+
-+static void m25p80_write_cmd(__u8 cmd, __u32 schip_en)
-+{
-+      __u32 opcode,tmp;
-+      __u32  status;
-+
-+
-+
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE | cmd;
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(tmp&0x80000000)
-+      {
-+          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      //////
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(tmp&0x80000000)
-+      {
-+          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      //middle delay_ms(130);
-+      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //printf("\ncmd =%x  status = %x",cmd,status);
-+      if(cmd==M25P80_WRITE_ENABLE)
-+      {
-+              //printf("\n**-->enable**  status = %x",status);
-+              //middle delay_ms(100);
-+                 while((status&0x03) != 2)
-+                 {
-+                      //if((status&0x9c)!=0)
-+                      //    printf("  M25P80_WRITE_ENABLE   Protect Status = %x\n",status);
-+
-+                        write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                        tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  //flash_delay();
-+                              }
-+                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+                     //printf("\n**enable**  status = %x",status);
-+                     flash_delay();
-+                     schedule();
-+                     //middle delay_ms(100);
-+                 }
-+      }
-+      else if(cmd==M25P80_WRITE_DISABLE)
-+      {
-+                 //while((status&0x03) == 2)
-+                 //   printf("\n**disable**  status = %x",status);
-+                 //middle delay_ms(100);
-+                 while((status&0x03) != 0)
-+                 {
-+             //m25p80_write_status((status&0xfd),schip_en);
-+                     write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                     tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                      while(tmp&0x80000000)
-+                      {
-+                          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                          flash_delay();
-+                          schedule();
-+                      }
-+                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+                     //printf("\n**disable**  status = %x",status);
-+                     flash_delay();
-+                     schedule();
-+                     //middle delay_ms(50);
-+                 }
-+      }
-+      else
-+      {
-+                 //while((status&0x01) !=0)
-+                 while((status&0x01) !=0)
-+                 {
-+                        write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                        tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+                     flash_delay();
-+                     schedule();
-+                     //middle delay_ms(50);
-+                 }
-+      }
-+      //////
-+
-+      //printf("\n<--  status = %x",status);
-+}
-+
-+static int __init init_sl2312_m25p80(void)
-+{
-+      int nr_parts = 0;
-+      struct mtd_partition *parts;
-+
-+      serial_mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-+      if (!serial_mtd)
-+              return NULL;
-+
-+      memset(serial_mtd, 0, sizeof(struct mtd_info));
-+      m25p80_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)ioremap(FLASH_START, SFLASH_SIZE);
-+    if (!m25p80_map.virt) {
-+              printk(" failed to ioremap \n");
-+              return -EIO;
-+      }
-+      serial_mtd = do_map_probe("map_serial", &m25p80_map);
-+      if (serial_mtd) {
-+              serial_mtd->owner = THIS_MODULE;
-+
-+      }
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+      nr_parts = parse_redboot_partitions(serial_mtd, &parsed_parts);
-+      if (nr_parts > 0)
-+              printk(KERN_NOTICE "Found RedBoot partition table.\n");
-+      else if (nr_parts < 0)
-+              printk(KERN_NOTICE "Error looking for RedBoot partitions.\n");
-+#else
-+      parsed_parts = m25p80_partitions;
-+      parts = m25p80_partitions;
-+      nr_parts = sizeof(m25p80_partitions)/sizeof(*parts);
-+      nr_parts = sizeof(m25p80_partitions)/sizeof(*parsed_parts);
-+#endif /* CONFIG_MTD_REDBOOT_PARTS */
-+
-+      if (nr_parts > 0)
-+          add_mtd_partitions(serial_mtd, parsed_parts, nr_parts);
-+      else
-+          add_mtd_device(serial_mtd);
-+
-+      return 0;
-+}
-+
-+static void __exit cleanup_sl2312_m25p80(void)
-+{
-+      if (parsed_parts)
-+          del_mtd_partitions(serial_mtd);
-+      else
-+          del_mtd_device(serial_mtd);
-+
-+      map_destroy(serial_mtd);
-+
-+
-+}
-+
-+module_init(init_sl2312_m25p80);
-+module_exit(cleanup_sl2312_m25p80);
-+
-+
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Plus Chen <plus@storlink.com.tw>");
-+MODULE_DESCRIPTION("MTD map driver for Storlink Sword boards");
-+
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312_flashmap.h
-@@ -0,0 +1,21 @@
-+/*
-+ * Please note that the name are used in mkflash script. Therefore
-+ * don't change them.  If you want to add different partitions, you
-+ * will need to modify mkflash script as well so that the end image
-+ * is what you include here!
-+ *
-+ * Also, the 7th item is always the size, so please don't add extra
-+ * spaces in the name or other items.
-+ *
-+ *  - Alan
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
-+      { name: "kernel",        offset: 0x00020000, size: 0x00100000, },
-+      { name: "rootfs",        offset: 0x00120000, size: 0x00500000, },
-+      { name: "rootfs_data",   offset: 0x00620000, size: 0x001A0000, },
-+      { name: "VCTL",          offset: 0x007C0000, size: 0x00010000, },
-+      { name: "cfg",           offset: 0x007D0000, size: 0x00020000, },
-+      { name: "FIS directory", offset: 0x007F0000, size: 0x00010000, }
-+};
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312_flashmap.h.16MB
-@@ -0,0 +1,21 @@
-+/*
-+ * Please note that the name are used in mkflash script. Therefore
-+ * don't change them.  If you want to add different partitions, you
-+ * will need to modify mkflash script as well so that the end image
-+ * is what you include here!
-+ *
-+ * Also, the 7th item is always the size, so please don't add extra
-+ * spaces in the name or other items.
-+ *
-+ *  - Alan
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
-+      { name: "Kernel",        offset: 0x00020000, size: 0x00300000, },
-+      { name: "Ramdisk",       offset: 0x00320000, size: 0x00600000, },
-+      { name: "Application",   offset: 0x00920000, size: 0x00600000, },
-+      { name: "VCTL",          offset: 0x00F20000, size: 0x00020000, },
-+      { name: "CurConf",       offset: 0x00F40000, size: 0x000A0000, },
-+      { name: "FIS directory", offset: 0x00FE0000, size: 0x00020000, }
-+};
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312_flashmap.h.8MB
-@@ -0,0 +1,21 @@
-+/*
-+ * Please note that the name are used in mkflash script. Therefore
-+ * don't change them.  If you want to add different partitions, you
-+ * will need to modify mkflash script as well so that the end image
-+ * is what you include here!
-+ *
-+ * Also, the 7th item is always the size, so please don't add extra
-+ * spaces in the name or other items.
-+ *
-+ *  - Alan
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
-+      { name: "Kernel",        offset: 0x00020000, size: 0x00200000, },
-+      { name: "Ramdisk",       offset: 0x00220000, size: 0x00280000, },
-+      { name: "Application",   offset: 0x004A0000, size: 0x00300000, },
-+      { name: "VCTL",          offset: 0x007A0000, size: 0x00020000, },
-+      { name: "CurConf",       offset: 0x007C0000, size: 0x00020000, },
-+      { name: "FIS directory", offset: 0x007E0000, size: 0x00020000, }
-+};
---- a/drivers/mtd/mtdchar.c
-+++ b/drivers/mtd/mtdchar.c
-@@ -59,6 +59,77 @@
-       enum mtd_file_modes mode;
- };
-+/***********************************************************************
-+/*             Storlink SoC -- flash
-+/***********************************************************************/
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+unsigned int share_pin_flag=0;                // bit0:FLASH, bit1:UART, bit2:EMAC, bit3-4:IDE
-+unsigned int check_sleep_flag=0;      // bit0:FLASH, bit1:IDE
-+static spinlock_t sl2312_flash_lock = SPIN_LOCK_UNLOCKED;
-+EXPORT_SYMBOL(share_pin_flag);
-+int dbg=0;
-+DECLARE_WAIT_QUEUE_HEAD(wq);
-+extern struct wait_queue_head_t *flash_wait;
-+unsigned int flash_req=0;
-+void mtd_lock()
-+{
-+      struct task_struct *tsk = current;
-+      unsigned int value ;
-+      unsigned long flags;
-+      flash_req = 1;
-+      DECLARE_WAITQUEUE(wait, tsk);
-+      add_wait_queue(&wq, &wait);
-+      for(;;)
-+      {
-+              set_task_state(tsk, TASK_INTERRUPTIBLE);
-+              spin_lock_irqsave(&sl2312_flash_lock,flags);
-+              if((share_pin_flag&0x1E)){//||(check_sleep_flag&0x00000002)) {
-+                      spin_unlock_irqrestore(&sl2312_flash_lock, flags);
-+                      check_sleep_flag |= 0x00000001;
-+                      if(dbg)
-+                              printk("mtd yield %x %x\n",share_pin_flag,check_sleep_flag);
-+                      wake_up_interruptible(&flash_wait);
-+                      schedule();
-+              }
-+              else {
-+                      check_sleep_flag &= ~0x01;
-+                      share_pin_flag |= 0x00000001 ;                  // set share pin flag
-+                      spin_unlock_irqrestore(&sl2312_flash_lock, flags);
-+                      value = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+                      value = value & (~PFLASH_SHARE_BIT) ;
-+                      writel(value,IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+                      if(dbg)
-+                              printk("mtd Go %x %x\n",share_pin_flag,check_sleep_flag);
-+                      tsk->state = TASK_RUNNING;
-+                      remove_wait_queue(&wq, &wait);
-+                      return ;
-+              }
-+      }
-+}
-+
-+void mtd_unlock()
-+{
-+      unsigned int value ;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&sl2312_flash_lock,flags);            // Disable IRQ
-+      value = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+      value = value | PFLASH_SHARE_BIT ;                              // Disable Flash PADs
-+      writel(value,IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+      share_pin_flag &= ~(0x00000001);                        // clear share pin flag
-+      check_sleep_flag &= ~0x00000001;
-+      spin_unlock_irqrestore(&sl2312_flash_lock, flags);      // Restore IRQ
-+      if (check_sleep_flag & 0x00000002)
-+      {
-+              check_sleep_flag &= ~(0x00000002);
-+              wake_up_interruptible(&flash_wait);
-+      }
-+      DEBUG(MTD_DEBUG_LEVEL0, "Flash Unlock...\n");
-+      flash_req = 0;
-+}
-+#endif
-+/***********************************************************************/
-+
- static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
- {
-       struct mtd_file_info *mfi = file->private_data;
-@@ -162,13 +233,21 @@
-       int len;
-       char *kbuf;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-+
-       DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
-       if (*ppos + count > mtd->size)
-               count = mtd->size - *ppos;
--      if (!count)
-+      if (!count){
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return 0;
-+      }
-       /* FIXME: Use kiovec in 2.5 to lock down the user's buffers
-          and pass them directly to the MTD functions */
-@@ -178,8 +257,12 @@
-       else
-               kbuf=kmalloc(count, GFP_KERNEL);
--      if (!kbuf)
-+      if (!kbuf) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return -ENOMEM;
-+      }
-       while (count) {
-@@ -224,6 +307,9 @@
-                       *ppos += retlen;
-                       if (copy_to_user(buf, kbuf, retlen)) {
-                               kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                               return -EFAULT;
-                       }
-                       else
-@@ -235,13 +321,19 @@
-                               count = 0;
-               }
-               else {
--                      kfree(kbuf);
-+                      kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-               }
-       }
-       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-       return total_retlen;
- } /* mtd_read */
-@@ -255,24 +347,40 @@
-       int ret=0;
-       int len;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-+
-       DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
--      if (*ppos == mtd->size)
-+      if (*ppos == mtd->size){
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return -ENOSPC;
-+      }
-       if (*ppos + count > mtd->size)
-               count = mtd->size - *ppos;
--      if (!count)
-+      if (!count){
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return 0;
-+      }
-       if (count > MAX_KMALLOC_SIZE)
-               kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
-       else
-               kbuf=kmalloc(count, GFP_KERNEL);
--      if (!kbuf)
-+      if (!kbuf) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return -ENOMEM;
-+      }
-       while (count) {
-@@ -283,6 +391,9 @@
-               if (copy_from_user(kbuf, buf, len)) {
-                       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-               }
-@@ -323,11 +434,17 @@
-               }
-               else {
-                       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-               }
-       }
-       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-       return total_retlen;
- } /* mtd_write */
-@@ -381,36 +498,67 @@
-       u_long size;
-       struct mtd_info_user info;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-+
-       DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
-       size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
-       if (cmd & IOC_IN) {
-               if (!access_ok(VERIFY_READ, argp, size))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-       }
-       if (cmd & IOC_OUT) {
-               if (!access_ok(VERIFY_WRITE, argp, size))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-       }
-       switch (cmd) {
-       case MEMGETREGIONCOUNT:
-               if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               break;
-       case MEMGETREGIONINFO:
-       {
-               struct region_info_user ur;
--              if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
-+              if (copy_from_user(&ur, argp, sizeof(struct region_info_user))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
--              if (ur.regionindex >= mtd->numeraseregions)
-+              if (ur.regionindex >= mtd->numeraseregions) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
-+              }
-               if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
--                              sizeof(struct mtd_erase_region_info)))
-+                              sizeof(struct mtd_erase_region_info))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               break;
-       }
-@@ -433,7 +581,12 @@
-               struct erase_info *erase;
-               if(!(file->f_mode & 2))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EPERM;
-+              }
-               erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
-               if (!erase)
-@@ -447,6 +600,9 @@
-                       if (copy_from_user(&erase->addr, argp,
-                                   sizeof(struct erase_info_user))) {
-                               kfree(erase);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                               return -EFAULT;
-                       }
-                       erase->mtd = mtd;
-@@ -484,14 +640,26 @@
-               struct mtd_oob_buf buf;
-               struct mtd_oob_ops ops;
--              if(!(file->f_mode & 2))
-+              if(!(file->f_mode & 2)) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EPERM;
-+              }
--              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
-+              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
--              if (buf.length > 4096)
-+              if (buf.length > 4096) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
-+              }
-               if (!mtd->write_oob)
-                       ret = -EOPNOTSUPP;
-@@ -499,8 +667,12 @@
-                       ret = access_ok(VERIFY_READ, buf.ptr,
-                                       buf.length) ? 0 : EFAULT;
--              if (ret)
-+              if (ret) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-+              }
-               ops.ooblen = buf.length;
-               ops.ooboffs = buf.start & (mtd->oobsize - 1);
-@@ -536,19 +708,35 @@
-               struct mtd_oob_buf buf;
-               struct mtd_oob_ops ops;
--              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
-+              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
--              if (buf.length > 4096)
-+              if (buf.length > 4096) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
-+              }
--              if (!mtd->read_oob)
-+              if (!mtd->read_oob) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       ret = -EOPNOTSUPP;
-+              }
-               else
-                       ret = access_ok(VERIFY_WRITE, buf.ptr,
-                                       buf.length) ? 0 : -EFAULT;
--              if (ret)
-+              if (ret) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-+              }
-               ops.ooblen = buf.length;
-               ops.ooboffs = buf.start & (mtd->oobsize - 1);
-@@ -580,7 +768,12 @@
-               struct erase_info_user info;
-               if (copy_from_user(&info, argp, sizeof(info)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->lock)
-                       ret = -EOPNOTSUPP;
-@@ -594,7 +787,12 @@
-               struct erase_info_user info;
-               if (copy_from_user(&info, argp, sizeof(info)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->unlock)
-                       ret = -EOPNOTSUPP;
-@@ -629,11 +827,21 @@
-               loff_t offs;
-               if (copy_from_user(&offs, argp, sizeof(loff_t)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->block_isbad)
-                       ret = -EOPNOTSUPP;
-               else
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return mtd->block_isbad(mtd, offs);
-+              }
-               break;
-       }
-@@ -642,11 +850,21 @@
-               loff_t offs;
-               if (copy_from_user(&offs, argp, sizeof(loff_t)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->block_markbad)
-                       ret = -EOPNOTSUPP;
-               else
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return mtd->block_markbad(mtd, offs);
-+              }
-               break;
-       }
-@@ -654,8 +872,12 @@
-       case OTPSELECT:
-       {
-               int mode;
--              if (copy_from_user(&mode, argp, sizeof(int)))
-+              if (copy_from_user(&mode, argp, sizeof(int))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               mfi->mode = MTD_MODE_NORMAL;
-@@ -670,7 +892,12 @@
-       {
-               struct otp_info *buf = kmalloc(4096, GFP_KERNEL);
-               if (!buf)
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -ENOMEM;
-+              }
-               ret = -EOPNOTSUPP;
-               switch (mfi->mode) {
-               case MTD_MODE_OTP_FACTORY:
-@@ -701,12 +928,24 @@
-       {
-               struct otp_info info;
--              if (mfi->mode != MTD_MODE_OTP_USER)
-+              if (mfi->mode != MTD_MODE_OTP_USER) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
--              if (copy_from_user(&info, argp, sizeof(info)))
-+              }
-+              if (copy_from_user(&info, argp, sizeof(info))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
--              if (!mtd->lock_user_prot_reg)
-+              }
-+              if (!mtd->lock_user_prot_reg) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EOPNOTSUPP;
-+              }
-               ret = mtd->lock_user_prot_reg(mtd, info.start, info.length);
-               break;
-       }
-@@ -742,8 +981,12 @@
-                       break;
-               case MTD_MODE_RAW:
--                      if (!mtd->read_oob || !mtd->write_oob)
-+                      if (!mtd->read_oob || !mtd->write_oob) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                               return -EOPNOTSUPP;
-+                      }
-                       mfi->mode = arg;
-               case MTD_MODE_NORMAL:
-@@ -766,6 +1009,10 @@
-               ret = -ENOTTY;
-       }
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-+
-       return ret;
- } /* memory_ioctl */
---- a/drivers/mtd/nand/Kconfig
-+++ b/drivers/mtd/nand/Kconfig
-@@ -44,6 +44,13 @@
-         This enables the driver for the autronix autcpu12 board to
-         access the SmartMediaCard.
-+config MTD_NAND_SL2312
-+      tristate "NAND Flash device on Storlink board"
-+      depends on ARM && MTD_NAND && ARCH_SL2312
-+      help
-+        This enables the driver for the Storlink board to
-+        access the nand device.
-+
- config MTD_NAND_EDB7312
-       tristate "Support for Cirrus Logic EBD7312 evaluation board"
-       depends on ARCH_EDB7312
---- /dev/null
-+++ b/drivers/mtd/nand/sl2312-flash-nand.c
-@@ -0,0 +1,2287 @@
-+/*
-+ *  drivers/mtd/sl2312.c
-+ *
-+ * $Id: sl2312-flash-nand.c,v 1.5 2006/06/15 07:02:29 middle Exp $
-+ *
-+ * Copyright (C) 2001 Toshiba Corporation
-+ *
-+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
-+ * the terms of the GNU General Public License version 2. This program
-+ * is licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ *
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/nand.h>
-+#include <linux/mtd/nand_ecc.h>
-+#include <linux/mtd/partitions.h>
-+#include <linux/delay.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/arch/sl2312.h>
-+#include "sl2312-flash-nand.h"
-+
-+
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/types.h>
-+#include <linux/mtd/compatmac.h>
-+#include <linux/interrupt.h>
-+#include <linux/bitops.h>
-+
-+
-+/*
-+ * NAND low-level MTD interface functions
-+ */
-+static void sl2312_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
-+static void sl2312_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
-+static int sl2312_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
-+
-+static int sl2312_nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-+static int sl2312_nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-+static int sl2312_nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-+static int sl2312_nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
-+static int sl2312_nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-+                         size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-+static int sl2312_nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);
-+static int sl2312_nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
-+                      unsigned long count, loff_t to, size_t * retlen);
-+static int sl2312_nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
-+                      unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
-+static int sl2312_nand_erase (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
-+static void sl2312_nand_sync (struct mtd_info *mtd);
-+static int sl2312_nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  struct nand_oobinfo *oobsel);
-+static int sl2312_nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt);
-+static int sl2312_nand_erase_block(struct mtd_info *mtd, int page);
-+
-+/*
-+ * MTD structure for sl2312 NDFMC
-+ */
-+static struct mtd_info *sl2312_mtd = NULL;
-+static int nand_page=0,nand_col=0;
-+
-+/* Define default oob placement schemes for large and small page devices */
-+static struct nand_oobinfo nand_oob_8 = {
-+      .useecc = MTD_NANDECC_AUTOPLACE,
-+      .eccbytes = 3,
-+      .eccpos = {0, 1, 2},
-+      .oobfree = { {3, 2}, {6, 2} }
-+};
-+
-+static struct nand_oobinfo nand_oob_16 = {
-+      .useecc = MTD_NANDECC_AUTOPLACE,
-+      .eccbytes = 6,
-+      .eccpos = {0, 1, 2, 3, 6, 7},
-+      .oobfree = { {8, 8} }
-+};
-+
-+static struct nand_oobinfo nand_oob_64 = {
-+      .useecc = MTD_NANDECC_AUTOPLACE,
-+      .eccbytes = 24,
-+      .eccpos = {
-+              40, 41, 42, 43, 44, 45, 46, 47,
-+              48, 49, 50, 51, 52, 53, 54, 55,
-+              56, 57, 58, 59, 60, 61, 62, 63},
-+      .oobfree = { {2, 38} }
-+};
-+
-+
-+/*
-+ * Define partitions for flash device
-+ */
-+/* the base address of FLASH control register */
-+#define FLASH_CONTROL_BASE_ADDR           (IO_ADDRESS(SL2312_FLASH_CTRL_BASE))
-+#define SL2312_GLOBAL_BASE_ADDR     (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+//#define SL2312_FLASH_BASE_ADDR      (IO_ADDRESS(SL2312_FLASH_BASE))
-+#define SL2312_FLASH_BASE_ADDR       FLASH_VADDR(SL2312_FLASH_BASE)
-+static unsigned int CHIP_EN;
-+/* define read/write register utility */
-+//#define FLASH_READ_REG(offset)                      (__raw_readl(offset+FLASH_CONTROL_BASE_ADDR))
-+//#define FLASH_WRITE_REG(offset,val)         (__raw_writel(val,offset+FLASH_CONTROL_BASE_ADDR))
-+//#define FLASH_READ_DATA(offset)                     (__raw_readb(offset+SL2312_FLASH_BASE_ADDR))
-+//#define FLASH_WRITE_DATA(offset,val)        (__raw_writeb(val,offset+SL2312_FLASH_BASE_ADDR))
-+
-+unsigned int FLASH_READ_REG(unsigned int addr)
-+{
-+    unsigned int *base;
-+    unsigned int data;
-+
-+    base = (unsigned int *)(FLASH_CONTROL_BASE_ADDR + addr);
-+    data = *base;
-+    return (data);
-+}
-+
-+void FLASH_WRITE_REG(unsigned int addr,unsigned int data)
-+{
-+    unsigned int *base;
-+
-+    base = (unsigned int *)(FLASH_CONTROL_BASE_ADDR + addr);
-+    *base = data;
-+    return;
-+}
-+
-+unsigned int FLASH_READ_DATA(unsigned int addr)
-+{
-+    unsigned char *base;
-+    unsigned int data;
-+
-+    base = (unsigned char *)(SL2312_FLASH_BASE_ADDR + addr);
-+    data = *base;
-+    return (data);
-+}
-+
-+void FLASH_WRITE_DATA(unsigned int addr,unsigned int data)
-+{
-+    unsigned char *base;
-+
-+    base = (unsigned char *)(SL2312_FLASH_BASE_ADDR + addr);
-+    *base = data;
-+    return;
-+}
-+
-+/* the offset of FLASH control register */
-+enum NFLASH_REGISTER {
-+      NFLASH_ID                       = 0x0000,
-+      NFLASH_STATUS                   = 0x0008,
-+      NFLASH_TYPE                     = 0x000c,
-+      NFLASH_ACCESS                   = 0x0030,
-+      NFLASH_COUNT                    = 0x0034,
-+      NFLASH_CMD_ADDR                 = 0x0038,
-+      NFLASH_ADDRESS                  = 0x003C,
-+      NFLASH_DATA                             = 0x0040,
-+      NFLASH_TIMING                   = 0x004C,
-+      NFLASH_ECC_STATUS               = 0x0050,
-+      NFLASH_ECC_CONTROL              = 0x0054,
-+      NFLASH_ECC_OOB                  = 0x005c,
-+      NFLASH_ECC_CODE_GEN0    = 0x0060,
-+      NFLASH_ECC_CODE_GEN1    = 0x0064,
-+      NFLASH_ECC_CODE_GEN2    = 0x0068,
-+      NFLASH_ECC_CODE_GEN3    = 0x006C,
-+      NFLASH_FIFO_CONTROL             = 0x0070,
-+      NFLASH_FIFO_STATUS              = 0x0074,
-+      NFLASH_FIFO_ADDRESS             = 0x0078,
-+      NFLASH_FIFO_DATA                = 0x007c,
-+};
-+
-+
-+
-+//#define FLASH_BASE  FLASH_CONTROL_BASE_ADDR
-+//#define FLASH_SIZE  0x00800000 //INTEGRATOR_FLASH_SIZE
-+
-+//#define FLASH_PART_SIZE 8388608
-+
-+//static unsigned int flash_indirect_access = 0;
-+
-+
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+void sl2312flash_enable_nand_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val & 0xfffffffb;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+
-+void sl2312flash_disable_nand_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val | 0x00000004;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+#endif
-+
-+extern struct nand_oobinfo jffs2_oobinfo;
-+/*
-+ * Define partitions for flash devices
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot", offset: 0x00000000, size: 0x0020000, },
-+      { name: "Kernel", offset: 0x00020000, size: 0x00200000, },
-+      { name: "Ramdisk", offset: 0x00220000, size: 0x00280000, },
-+      { name: "Application", offset: 0x004A0000, size: 0x00320000, },
-+      { name: "VCTL", offset: 0x007C0000, size: 0x20000, },
-+      { name: "CurConf", offset: 0x007E0000, size: 0x20000, },
-+      { name: "FIS directory", offset: 0x007e0000, size: 0x00020000, }
-+
-+};
-+
-+
-+/*
-+ *    hardware specific access to control-lines
-+*/
-+static void sl2312_hwcontrol(struct mtd_info *mtd, int cmd)
-+{
-+
-+      return ;
-+}
-+
-+static int sl2312_nand_scan_bbt(struct mtd_info *mtd)
-+{
-+      return 0;
-+}
-+
-+/**
-+ * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset relative to mtd start
-+ */
-+static int sl2312_nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
-+{
-+      /* Check for invalid offset */
-+      if (ofs > mtd->size)
-+              return -EINVAL;
-+
-+      return sl2312_nand_block_checkbad (mtd, ofs, 1, 0);
-+}
-+
-+/**
-+ * nand_block_checkbad - [GENERIC] Check if a block is marked bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset from device start
-+ * @getchip:  0, if the chip is already selected
-+ * @allowbbt: 1, if its allowed to access the bbt area
-+ *
-+ * Check, if the block is bad. Either by reading the bad block table or
-+ * calling of the scan function.
-+ */
-+
-+static int sl2312_nand_erase_block(struct mtd_info *mtd, int page)
-+{
-+      int opcode;
-+      /* Send commands to erase a page */
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+
-+              if(mtd->oobblock > 528)
-+                  FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff21);  // 3 address & 2 command
-+              else
-+                  FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff11);  // 2 address & 2 command
-+
-+              FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x0000d060); // write read id command
-+              FLASH_WRITE_REG(NFLASH_ADDRESS, page); //write address 0x00
-+
-+
-+
-+              /* read maker code */
-+              opcode = 0x80003000|DWIDTH|CHIP_EN; //set start bit & 8bits write command
-+              FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+
-+              while(opcode&0x80000000) //polling flash access 31b
-+              {
-+           opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+           //sl2312_flash_delay();
-+           schedule();
-+           //cond_resched();
-+              }
-+}
-+
-+void sl2312_flash_delay(void)
-+{
-+      int i;
-+
-+      for(i=0; i<50; i++)
-+           i=i;
-+}
-+
-+static int sl2312_nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
-+{
-+      struct nand_chip *this = mtd->priv;
-+
-+      if (!this->bbt)
-+              return this->block_bad(mtd, ofs, getchip);
-+
-+      /* Return info from the table */
-+      return nand_isbad_bbt (mtd, ofs, allowbbt);
-+}
-+
-+/**
-+ * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset relative to mtd start
-+ */
-+static int sl2312_nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
-+{
-+      struct nand_chip *this = mtd->priv;
-+      int ret;
-+
-+        if ((ret = sl2312_nand_block_isbad(mtd, ofs))) {
-+              /* If it was bad already, return success and do nothing. */
-+              if (ret > 0)
-+                      return 0;
-+              return ret;
-+        }
-+
-+      return this->block_markbad(mtd, ofs);
-+}
-+
-+/*
-+ *    Get chip for selected access
-+ */
-+static inline void sl2312_nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state, int *erase_state)
-+{
-+
-+      DECLARE_WAITQUEUE (wait, current);
-+
-+      /*
-+       * Grab the lock and see if the device is available
-+       * For erasing, we keep the spinlock until the
-+       * erase command is written.
-+      */
-+retry:
-+      spin_lock_bh (&this->chip_lock);
-+
-+      if (this->state == FL_READY) {
-+              this->state = new_state;
-+              if (new_state != FL_ERASING)
-+                      spin_unlock_bh (&this->chip_lock);
-+              return;
-+      }
-+
-+      if (this->state == FL_ERASING) {
-+              if (new_state != FL_ERASING) {
-+                      this->state = new_state;
-+                      spin_unlock_bh (&this->chip_lock);
-+                      this->select_chip(mtd, 0);      /* select in any case */
-+                      this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-+                      return;
-+              }
-+      }
-+
-+      set_current_state (TASK_UNINTERRUPTIBLE);
-+      add_wait_queue (&this->wq, &wait);
-+      spin_unlock_bh (&this->chip_lock);
-+      schedule ();
-+      remove_wait_queue (&this->wq, &wait);
-+      goto retry;
-+}
-+
-+/*
-+*     read device ready pin
-+*/
-+static int sl2312_device_ready(struct mtd_info *mtd)
-+{
-+      int ready;
-+
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+      FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000070); //set only command no address and two data
-+
-+      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000070); //write read status command
-+
-+
-+      ready = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
-+      FLASH_WRITE_REG(NFLASH_ACCESS, ready);
-+
-+      while(ready&0x80000000) //polling flash access 31b
-+    {
-+        ready=FLASH_READ_REG(NFLASH_ACCESS);
-+        //sl2312_flash_delay();
-+              schedule();
-+    }
-+    FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+              ready=FLASH_READ_REG(NFLASH_DATA)&0xff;
-+      return ready;
-+}
-+void sl2312_enable_hwecc(struct mtd_info *mtd, int mode)
-+{
-+      /* reset first */
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
-+
-+}
-+
-+
-+void sl2312_device_setup(void)
-+{
-+
-+}
-+static u_char sl2312_nand_read_byte(struct mtd_info *mtd)
-+{
-+
-+        unsigned int    data=0, page=0, col=0, tmp, i;
-+
-+        printk ("**************************sl2312_nand_read_byte !! \n");
-+        //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
-+        //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
-+        page = nand_page;
-+        col  = nand_col;
-+        for(i=0;i<(mtd->oobblock+mtd->oobsize);i++)
-+        {
-+              if(i==col)
-+                              data = FLASH_READ_DATA(page*mtd->oobblock +i);
-+                      else
-+                              tmp = FLASH_READ_DATA(page*mtd->oobblock +i);
-+        }
-+        return data&0xff;
-+}
-+
-+static void sl2312_nand_write_byte(struct mtd_info *mtd, u_char byte)
-+{
-+        //struct nand_chip *this = mtd->priv;
-+        unsigned int    page=0, col=0, i;
-+        u_char *databuf,oobbuf[mtd->oobsize];
-+        size_t  retlen;
-+        retlen=0;
-+              printk ("********************sl2312_nand_write_byte !! \n");
-+              page = nand_page;
-+        col  = nand_col;
-+              databuf = kmalloc (mtd->oobsize+mtd->oobblock,GFP_KERNEL);
-+
-+              if (!databuf) {
-+                      printk ("sl2312_nand_write_byte : Unable to allocate SL2312 NAND MTD device structure.\n");
-+
-+              }
-+
-+               for(i=0;i<(mtd->oobblock+mtd->oobsize);i++)
-+              databuf[i] = FLASH_READ_DATA(page*mtd->oobblock +i);
-+
-+        databuf[col] = byte;
-+        sl2312_nand_write_ecc (mtd, page, mtd->oobblock, &retlen, databuf, oobbuf, NULL);
-+
-+}
-+
-+static void sl2312_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
-+{
-+      int i, page=0,col=0;
-+      struct nand_chip *this = mtd->priv;
-+      u_char *databuf, *oobbuf;
-+        size_t  retlen;
-+        retlen=0;
-+
-+
-+              printk ("***********************sl2312_nand_write_buf !! \n");
-+              databuf = &(this->data_buf[0]);
-+              oobbuf = &(this->data_buf[mtd->oobblock]);
-+              for (i = 0; i < mtd->oobsize; i++)
-+                      oobbuf[i] = 0xff;
-+
-+      if(len < mtd->oobblock)
-+      {
-+              //addr = FLASH_READ_REG(NFLASH_ADDRESS);
-+              //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
-+              //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
-+              page = nand_page;
-+        col  = nand_col;
-+
-+              sl2312_nand_read_ecc (mtd, page, mtd->oobblock , &retlen, databuf, oobbuf, NULL);
-+
-+        for(i=col;i<len;i++)
-+              databuf[col+i] = buf[i];
-+
-+        sl2312_nand_write_ecc (mtd, page, mtd->oobblock, &retlen, databuf, oobbuf, NULL);
-+
-+      }
-+
-+}
-+
-+static void sl2312_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-+{
-+      int i, page=0,col=0,addr=0,tmp=0;
-+      //struct nand_chip *this = mtd->priv;
-+      printk ("********************sl2312_nand_read_buf !! \n");
-+      if(len < mtd->oobblock)
-+      {
-+              //addr = FLASH_READ_REG(NFLASH_ADDRESS);
-+              //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
-+              //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
-+              page = nand_page;
-+        col  = nand_col;
-+              for (i=col; i<((mtd->oobblock+mtd->oobsize)-col); i++)
-+              {
-+                      if(i<len)
-+                              buf[i] = FLASH_READ_DATA(addr+i);
-+                      else
-+                              tmp = FLASH_READ_DATA(addr+i);
-+              }
-+      }
-+}
-+
-+static int sl2312_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-+{
-+      int i;
-+      //struct nand_chip *this = mtd->priv;
-+      u_char *datatmp, *oobtmp;
-+      size_t  retlen;
-+      retlen=0;
-+
-+      datatmp = kmalloc (mtd->oobblock,GFP_KERNEL);
-+      oobtmp = kmalloc (mtd->oobsize,GFP_KERNEL);
-+
-+      if ((!datatmp)||(!oobtmp)) {
-+              printk ("sl2312_nand_verify_buf : Unable to allocate SL2312 NAND MTD device structure.\n");
-+
-+      }
-+      //page = nand_page;
-+      for(i=0;i<mtd->oobblock;i++)
-+              datatmp[i] = FLASH_READ_DATA(nand_page*mtd->oobblock +i);
-+      /* read oobdata */
-+      for (i = 0; i <  mtd->oobsize; i++)
-+              oobtmp[i] = FLASH_READ_DATA(nand_page*mtd->oobblock + mtd->oobblock + i);
-+
-+      if(len==mtd->oobblock)
-+      {
-+              for (i=0; i<len; i++)
-+              {
-+                      if (buf[i] != datatmp[i])
-+                      {
-+                              kfree(datatmp);
-+                              kfree(oobtmp);
-+                              printk("Data verify error -> page: %x, byte: %x \n",nand_page,i);
-+                              return i;
-+                      }
-+              }
-+      }
-+      else if(len == mtd->oobsize)
-+      {
-+              for (i=0; i<len; i++)
-+              {
-+                      if (buf[i] != oobtmp[i])
-+                      {
-+                              kfree(datatmp);
-+                              kfree(oobtmp);
-+                              printk("OOB verify error -> page: %x, byte: %x \n",nand_page,i);
-+                              return i;
-+                      }
-+              }
-+      }
-+      else
-+      {
-+              printk (KERN_WARNING "sl2312_nand_verify_buf : verify length not match 0x%08x\n", len);
-+              kfree(datatmp);
-+              kfree(oobtmp);
-+              return -1;
-+      }
-+
-+      kfree(datatmp);
-+      kfree(oobtmp);
-+      return 0;
-+}
-+
-+/*
-+ * Send command to NAND device
-+ */
-+static void sl2312_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
-+{
-+      register struct nand_chip *this = mtd->priv;
-+      int opcode;
-+
-+
-+      /*
-+       * program and erase have their own busy handlers
-+       * status and sequential in needs no delay
-+      */
-+      switch (command) {
-+
-+      case NAND_CMD_PAGEPROG:
-+      case NAND_CMD_ERASE1:
-+      case NAND_CMD_ERASE2:
-+      case NAND_CMD_SEQIN:
-+      case NAND_CMD_STATUS:
-+      case NAND_CMD_READ0:
-+
-+              /*
-+               * Write out the command to the device.
-+               */
-+              if (column != -1 || page_addr != -1) {
-+
-+                      /* Serially input address */
-+                      if (column != -1)
-+                              //FLASH_WRITE_REG(NFLASH_ADDRESS,column);
-+                              nand_col=column;
-+
-+                      opcode = FLASH_READ_REG(NFLASH_ADDRESS);
-+
-+                      if (page_addr != -1)
-+                              //FLASH_WRITE_REG(NFLASH_ADDRESS,opcode|(page_addr<<8));
-+                              nand_page = page_addr;
-+
-+              }
-+              return;
-+
-+      case NAND_CMD_RESET:
-+              if (this->dev_ready)
-+                      break;
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+              FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff70); //set only command and no other data
-+              FLASH_WRITE_REG(NFLASH_CMD_ADDR, NAND_CMD_RESET); //write reset command
-+
-+              opcode = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
-+              FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+
-+              while(opcode&0x80000000) //polling flash access 31b
-+              {
-+           opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+           //sl2312_flash_delay();
-+           schedule();
-+              }
-+              while ( !(sl2312_device_ready(mtd) & 0x40));
-+              {
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+                      //sl2312_flash_delay();
-+                      schedule();
-+                      return;
-+              }
-+      /* This applies to read commands */
-+      default:
-+              /*
-+               * If we don't have access to the busy pin, we apply the given
-+               * command delay
-+              */
-+              if (!this->dev_ready) {
-+                      udelay (this->chip_delay);
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+                      return;
-+              }
-+      }
-+
-+      /* wait until command is processed */
-+      while (!this->dev_ready(mtd));
-+
-+}
-+/*Add function*/
-+static void nand_read_id(int chip_no, unsigned char *id)
-+{
-+      unsigned int opcode, i;
-+
-+      if(chip_no==0)
-+              CHIP_EN = NFLASH_CHIP0_EN;
-+      else
-+              CHIP_EN = NFLASH_CHIP1_EN;
-+
-+      opcode = FLASH_READ_REG(NFLASH_TYPE);
-+
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+      if((opcode&0x00000300)<=0x00000100)
-+          FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000100); //set only command & address and two data
-+      else
-+          FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000300); //set only command & address and 4 data
-+
-+      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000090); //write read id command
-+      FLASH_WRITE_REG(NFLASH_ADDRESS, 0x00000000); //write address 0x00
-+
-+      /* read maker code */
-+      opcode = 0x80002000|DWIDTH|CHIP_EN;//|chip0_en; //set start bit & 8bits read command
-+      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+      opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+              while(opcode&0x80000000) //polling flash access 31b
-+              {
-+           opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+           //sl2312_flash_delay();
-+           schedule();
-+              }
-+
-+    opcode = FLASH_READ_REG(NFLASH_DATA);
-+    if(DWIDTH==NFLASH_WiDTH16)
-+    {
-+                      id[0] = opcode&0xff;
-+                      id[1] = (opcode&0xff00)>>8;
-+    }
-+    else
-+    {
-+          id[0] = opcode&0xff;
-+          opcode = 0x80002000|DWIDTH|CHIP_EN;//|chip0_en; //set start bit & 8bits read command
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+                      opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+                      while(opcode&0x80000000) //polling flash access 31b
-+              {
-+             opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+             //sl2312_flash_delay();
-+             schedule();
-+              }
-+              opcode = FLASH_READ_REG(NFLASH_DATA);
-+                      id[1] = (opcode&0xff00)>>8;
-+
-+                      opcode=FLASH_READ_REG(NFLASH_TYPE);
-+                      if((opcode&0x300)>0x100)
-+                      {
-+                          for(i=0;i<2;i++)
-+                          {
-+                                      //data cycle 3 & 4 ->not use
-+                                      opcode = 0x80002000|DWIDTH|CHIP_EN;//set start bit & 8bits read command
-+                                      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+                                      opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+                                      while(opcode&0x80000000) //polling flash access 31b
-+                                      {
-+                                 opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+                                 //sl2312_flash_delay();
-+                                 schedule();
-+                                      }
-+
-+                                      opcode=FLASH_READ_REG(NFLASH_DATA);
-+                                      id[2+i] = (opcode&(0xff0000<<i*8))>>(8*(2+i));
-+                          }
-+                      }
-+    }
-+    FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+}
-+
-+/*
-+ * NAND erase a block
-+ */
-+static int sl2312_nand_erase (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
-+{
-+      int page, len, status, pages_per_block, ret, chipnr;
-+      struct nand_chip *this = mtd->priv;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3,
-+             "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
-+
-+      /* Start address must align on block boundary */
-+      if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Length must align on block boundary */
-+      if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Do not allow erase past end of device */
-+      if ((instr->len + instr->addr) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
-+              return -EINVAL;
-+      }
-+
-+      instr->fail_addr = 0xffffffff;
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_ERASING, NULL);
-+
-+      /* Shift to get first page */
-+      page = (int) (instr->addr >> this->page_shift);
-+      chipnr = (int) (instr->addr >> this->chip_shift);
-+
-+      /* Calculate pages in each block */
-+      pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
-+
-+      /* Select the NAND device */
-+      //this->select_chip(mtd, chipnr);
-+      this->select_chip(mtd, 0);
-+
-+      /* Check the WP bit */
-+      /* Check, if it is write protected */
-+      status = sl2312_device_ready(mtd);
-+      if (!(status & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
-+              instr->state = MTD_ERASE_FAILED;
-+              goto erase_exit;
-+      }
-+
-+      /* Loop through the pages */
-+      len = instr->len;
-+
-+      instr->state = MTD_ERASING;
-+
-+      while (len) {
-+              /* Check if we have a bad block, we do not erase bad blocks ! */
-+              if (this->block_bad(mtd, ((loff_t) page) << this->page_shift, 0)) {
-+                      printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
-+                      //instr->state = MTD_ERASE_FAILED;
-+                      //goto erase_exit;
-+              }
-+
-+              /* Invalidate the page cache, if we erase the block which contains
-+                 the current cached page */
-+              if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
-+                      this->pagebuf = -1;
-+              /////////
-+
-+              ///* Send commands to erase a page */
-+              //FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+          //
-+              //if(mtd->oobblock > 528)
-+              //    FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff21);  // 3 address & 2 command
-+              //else
-+              //    FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff11);  // 2 address & 2 command
-+              //
-+              //FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x0000d060); // write read id command
-+              //FLASH_WRITE_REG(NFLASH_ADDRESS, page); //write address 0x00
-+              //
-+              //
-+              //
-+              ///* read maker code */
-+              //opcode = 0x80003000|DWIDTH|CHIP_EN; //set start bit & 8bits write command
-+              //FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+              //
-+              //while(opcode&0x80000000) //polling flash access 31b
-+              //{
-+        //   opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+        //   //sl2312_flash_delay();
-+        //   schedule();
-+        //   //cond_resched();
-+              //}
-+              sl2312_nand_erase_block(mtd, page);
-+              //////////////
-+              status = this->waitfunc (mtd, this, FL_ERASING);
-+              /* See if block erase succeeded */
-+              if (status & 0x01) {
-+                      DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
-+                      instr->state = MTD_ERASE_FAILED;
-+                      instr->fail_addr = (page << this->page_shift);
-+                      goto erase_exit;
-+              }
-+
-+              /* Increment page address and decrement length */
-+              len -= (1 << this->phys_erase_shift);
-+              page += pages_per_block;
-+
-+              /* Check, if we cross a chip boundary */
-+              if (len && !(page & this->pagemask)) {
-+                      chipnr++;
-+                      this->select_chip(mtd, 0);
-+                      this->select_chip(mtd, 0);
-+              }
-+              //sl2312_flash_delay();
-+           schedule();
-+           //cond_resched();
-+      }
-+      instr->state = MTD_ERASE_DONE;
-+
-+erase_exit:
-+      /* De-select the NAND device */
-+      this->select_chip(mtd, 0);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;;
-+      /* Do call back function */
-+      if (!ret && instr->callback)
-+              instr->callback (instr);
-+
-+      /* The device is ready */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      spin_unlock_bh (&this->chip_lock);
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+      /* Return more or less happy */
-+      return ret;
-+}
-+
-+static void sl2312_nand_select_chip(struct mtd_info *mtd, int chip)
-+{
-+      //struct nand_chip *this = mtd->priv;
-+
-+      switch(chip) {
-+      case -1:
-+              CHIP_EN = NFLASH_CHIP0_EN;
-+              break;
-+      case 0:
-+              CHIP_EN = NFLASH_CHIP0_EN;
-+              break;
-+      case 1:
-+              CHIP_EN = NFLASH_CHIP1_EN;
-+              break;
-+      default:
-+                      CHIP_EN = NFLASH_CHIP0_EN;
-+                      break;
-+      }
-+}
-+
-+/**
-+ * nand_default_block_markbad - [DEFAULT] mark a block bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset from device start
-+ *
-+ * This is the default implementation, which can be overridden by
-+ * a hardware specific driver.
-+*/
-+static int sl2312_nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
-+{
-+      struct nand_chip *this = mtd->priv;
-+      u_char buf[2] = {0, 0};
-+      size_t  retlen;
-+      int block;
-+
-+      /* Get block number */
-+      block = ((int) ofs) >> this->bbt_erase_shift;
-+      this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
-+
-+      /* Do we have a flash based bad block table ? */
-+      if (this->options & NAND_USE_FLASH_BBT)
-+              return nand_update_bbt (mtd, ofs);
-+
-+      /* We write two bytes, so we dont have to mess with 16 bit access */
-+      ofs += mtd->oobsize + (this->badblockpos & ~0x01);
-+      return sl2312_nand_write_oob (mtd, ofs , 2, &retlen, buf);
-+}
-+
-+/* Appropriate chip should already be selected */
-+static int sl2312_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)//(struct mtd_info *mtd, unsigned long page, )
-+{
-+      u_char *buf, *oobbuf;
-+      size_t  retlen;
-+      unsigned long page, chipnr;
-+      struct nand_chip *this = mtd->priv;
-+
-+      if (getchip) {
-+              page = (int)(ofs >> this->page_shift);
-+              chipnr = (int)(ofs >> this->chip_shift);
-+
-+              /* Grab the lock and see if the device is available */
-+              sl2312_nand_get_chip (this, mtd, FL_READING, NULL);
-+              /* Select the NAND device */
-+              this->select_chip(mtd, chipnr);
-+      } else
-+              page = (int) ofs;
-+
-+      buf = kmalloc (mtd->oobblock,GFP_KERNEL);
-+      oobbuf = kmalloc (mtd->oobsize,GFP_KERNEL);
-+
-+      if ((!buf)||(!oobbuf)) {
-+              printk ("sl2312_nand_block_bad : Unable to allocate SL2312 NAND MTD device structure.\n");
-+
-+      }
-+
-+      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , &retlen, buf, oobbuf, NULL);
-+
-+
-+      if(((mtd->oobblock < 528)&&(oobbuf[5] != 0xff))||((mtd->oobblock > 528)&&(oobbuf[0] != 0xff)))
-+      {
-+              kfree(buf);
-+              kfree(oobbuf);
-+              return 1;
-+      }
-+
-+      kfree(buf);
-+      kfree(oobbuf);
-+      return 0;
-+}
-+
-+/*
-+*     Use NAND read ECC
-+*/
-+static int sl2312_nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
-+{
-+      return sl2312_nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
-+}
-+
-+/*
-+ * NAND read with ECC
-+ */
-+static int sl2312_nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-+                        size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
-+{
-+      int j, col, page, opcode, i;
-+      int end=0;//, ecc=0;//, end_page=0;
-+      int erase_state = 0;
-+      int read = 0, oob = 0, ecc_failed = 0;//, ecc_status = 0
-+      struct nand_chip *this = mtd->priv;
-+      u_char *data_poi, *oob_data = oob_buf;
-+      //u_char ecc_calc[6];
-+      //u_char ecc_code[6];
-+      int     eccmode;
-+      int     *oob_config;
-+
-+
-+
-+      // use chip default if zero
-+      if (oobsel == NULL)
-+              oobsel = &mtd->oobinfo;
-+
-+      eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-+      oob_config = oobsel->eccpos;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-+
-+      /* Do not allow reads past end of device */
-+      if ((from + len) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
-+              *retlen = 0;
-+              return -EINVAL;
-+      }
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd ,FL_READING, &erase_state);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* First we calculate the starting page */
-+      page = from >> this->page_shift;
-+
-+      //end_page = mtd->oobblock + mtd->oobsize;
-+      end = mtd->oobblock;
-+      //ecc = mtd->eccsize;
-+      /* Get raw starting column */
-+      col = (from & (mtd->oobblock - 1));
-+
-+
-+      /* Send the read command */
-+      //this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
-+
-+      /* Loop until all data read */
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+      while (read < len) {
-+
-+              //udelay(1200);
-+              /* If we have consequent page reads, apply delay or wait for ready/busy pin */
-+              if (read) {
-+                      if (!this->dev_ready)
-+                              udelay (this->chip_delay);
-+                      else
-+                              while (!this->dev_ready(mtd));
-+              }
-+
-+              /*
-+               * If the read is not page aligned, we have to read into data buffer
-+               * due to ecc, else we read into return buffer direct
-+               */
-+              if (!col && (len - read) >= end)
-+                      data_poi = &buf[read];
-+              else
-+                      data_poi = this->data_buf;
-+
-+              /* get oob area, if we have no oob buffer from fs-driver */
-+              if (!oob_buf) {
-+                      oob_data = &this->data_buf[end];
-+                      oob = 0;
-+              }
-+
-+              j = 0;
-+              switch (eccmode) {
-+                      case NAND_ECC_NONE: {   /* No ECC, Read in a page */
-+                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+                              break;
-+                      }
-+
-+                      case NAND_ECC_SOFT:     /* Software ECC 3/256: Read in a page + oob data */
-+                              break;
-+
-+                      case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data: Read in first 256 byte, get ecc, */
-+                              break;
-+
-+                      case NAND_ECC_HW3_512:
-+                      case NAND_ECC_HW6_512: /* Hardware ECC 3/6 byte / 512 byte data : Read in a page  */
-+                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
-+                              break;
-+
-+                      default:
-+                              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
-+                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0);
-+                              //BUG();
-+              }//end switch
-+
-+                      for(i=0;i<end;i++)
-+                      {
-+                              //udelay(7);
-+                              data_poi[i] = FLASH_READ_DATA(page*mtd->oobblock +i);
-+                      }
-+                      /* read oobdata */
-+                      for (i = 0; i <  mtd->oobsize; i++)
-+                      {
-+                              //udelay(7);
-+                              oob_data[oob + i] = FLASH_READ_DATA(page*mtd->oobblock +end+i);
-+                      }
-+
-+              /* Skip ECC, if not active */
-+                      if (eccmode == NAND_ECC_NONE)
-+                              goto readdata;
-+
-+                      // compare ecc and correct data
-+
-+                              opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                              while(!(opcode&0x80000000)) //polling flash access 31b
-+                              {
-+                                 opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                                 //sl2312_flash_delay();
-+                                 schedule();
-+                              }
-+                              for(j=0;j<(end/512);j++)
-+                              {//for 2k page
-+
-+                                      opcode = 0x00000000|oob_data[mtd->oobsize-3-4*j]<<16|oob_data[mtd->oobsize-2-4*j]<<8|oob_data[mtd->oobsize-1-4*j];
-+
-+                                      //opcode=FLASH_READ_REG(NFLASH_ECC_CODE_GEN0+(j*4));
-+
-+                                      FLASH_WRITE_REG(NFLASH_ECC_OOB, opcode);
-+                                      opcode = 0x00000000|(j<<8); //select ECC code generation 0
-+                                      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, opcode); //???
-+
-+                                      opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                                      if((opcode&0x00000003)==0x03)
-+                                      {
-+                                              printk (KERN_WARNING "\nPageRead Uncorrectable error !!\n");
-+                                              ecc_failed++;
-+                                      }
-+                                      else if((opcode&0x00000003)==0x01)
-+                                      {
-+                                              printk (KERN_WARNING "\nPageRead One bit data error !!");
-+                                              // correct data
-+                                              if((data_poi[(opcode&0xff80)>>7]>>((opcode&0x38)>>3))%1)
-+                                                      data_poi[(opcode&0xff80)>>7] &= ~(1<<((opcode&0x38)>>3));
-+                                              else
-+                                                      data_poi[(opcode&0xff80)>>7] |= (1<<((opcode&0x38)>>3));
-+
-+                                      }
-+                                      else if((opcode&0x00000003)==0x02)
-+                                      {
-+                                              printk (KERN_WARNING "\nPageRead One bit ECC error !!\n");
-+                                      }
-+                                      else if((opcode&0x00000003)==0x00)
-+                                      {
-+
-+                                      }
-+
-+                              }//for 2k page
-+readdata:
-+              if (col || (len - read) < end) {
-+                      for (j = col; j < end && read < len; j++)
-+                              buf[read++] = data_poi[j];
-+              } else
-+                      read += mtd->oobblock;
-+              /* For subsequent reads align to page boundary. */
-+              col = 0;
-+              /* Increment page address */
-+              page++;
-+              schedule();
-+      }
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_INDIRECT);
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      /*
-+       * Return success, if no ECC failures, else -EIO
-+       * fs driver will take care of that, because
-+       * retlen == desired len and result == -EIO
-+       */
-+      *retlen = read;
-+      return ecc_failed ? -EIO : 0;
-+}
-+
-+/*
-+ * Wait for command done. This applies to erase and program only
-+ * Erase can take up to 400ms and program up to 20ms according to
-+ * general NAND and SmartMedia specs
-+ *
-+*/
-+static int sl2312_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
-+{
-+      unsigned long   timeo = jiffies;
-+      int     status, opcode;
-+
-+      if (state == FL_ERASING)
-+               timeo += (HZ * 400) / 1000;
-+      else
-+               timeo += (HZ * 20) / 1000;
-+
-+      spin_lock_bh (&this->chip_lock);
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+      FLASH_WRITE_REG(NFLASH_COUNT, 0x007f000070); //set only command no address and two data
-+
-+      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000070); //write read status command
-+
-+
-+      opcode = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
-+      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+
-+      while(opcode&0x80000000) //polling flash access 31b
-+    {
-+        opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+        //sl2312_flash_delay();
-+        schedule();
-+    }
-+
-+      while (time_before(jiffies, timeo)) {
-+              /* Check, if we were interrupted */
-+              if (this->state != state) {
-+                      spin_unlock_bh (&this->chip_lock);
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+                      return 0;
-+              }
-+              if (this->dev_ready) {
-+                      if (this->dev_ready(mtd))
-+                              break;
-+              }
-+              if (FLASH_READ_REG(NFLASH_DATA) & 0x40)
-+                      break;
-+
-+              spin_unlock_bh (&this->chip_lock);
-+              yield ();
-+              spin_lock_bh (&this->chip_lock);
-+      }
-+      status = FLASH_READ_REG(NFLASH_DATA)&0xff;
-+      spin_unlock_bh (&this->chip_lock);
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+      return status;
-+}
-+
-+static int sl2312_nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
-+{
-+      int i, col, page, j=0;
-+      //int erase_state = 0;
-+      struct nand_chip *this = mtd->priv;
-+      u_char *databuf, *oobbuf;
-+
-+      databuf = &this->data_buf[0];
-+      oobbuf = &this->data_buf[mtd->oobblock];
-+              for (i = 0; i < mtd->oobsize; i++)
-+                      oobbuf[i] = 0xff;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-+
-+      /* Shift to get page */
-+      page = ((int) from) >> this->page_shift;
-+
-+      /* Mask to get column */
-+      col = from & (mtd->oobsize-1);  //0x0f;
-+
-+      /* Initialize return length value */
-+      *retlen = 0;
-+      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , retlen, databuf, oobbuf, NULL);
-+      for(i=col,j=0;i<mtd->oobsize||i<(col+len);i++,j++)
-+              buf[j] = oobbuf[i];
-+
-+      *retlen = j ;
-+      return 0;
-+}
-+
-+#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
-+/*
-+*     Use NAND write ECC
-+*/
-+static int sl2312_nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
-+{
-+      return (sl2312_nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
-+}
-+
-+/*
-+ * NAND write with ECC
-+ */
-+static int sl2312_nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-+                         size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
-+{
-+      int page, ret = 0, oob = 0, written = 0;
-+      struct nand_chip *this = mtd->priv;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
-+
-+
-+      /* Do not allow write past end of device */
-+      if ((to + len) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
-+              return -EINVAL;
-+      }
-+
-+      /* reject writes, which are not page aligned */
-+      if (NOTALIGNED (to) || NOTALIGNED(len)) {
-+              printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
-+              return -EINVAL;
-+      }
-+
-+      // if oobsel is NULL, use chip defaults
-+      if (oobsel == NULL)
-+              oobsel = &mtd->oobinfo;
-+
-+      /* Shift to get page */
-+      page = ((int) to) >> this->page_shift;
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Check the WP bit */
-+      if (!(sl2312_device_ready(mtd) & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Device is write protected!!!\n");
-+              ret = -EIO;
-+              goto out;
-+      }
-+
-+      /* Loop until all data is written */
-+      while (written < len) {
-+              //udelay(100);
-+              int cnt = mtd->oobblock;
-+              this->data_poi = (u_char*) &buf[written];
-+              /* We use the same function for write and writev */
-+              if (eccbuf) {
-+                      ret = sl2312_nand_write_page (mtd, this, page, &eccbuf[oob], oobsel);
-+                      oob += mtd->oobsize;
-+              } else
-+                      ret = sl2312_nand_write_page (mtd, this, page, NULL, oobsel);
-+
-+              if (ret)
-+                      goto out;
-+
-+              /* Update written bytes count */
-+              written += cnt;
-+              /* Increment page address */
-+              page++;
-+      }
-+
-+out:
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      *retlen = written;
-+      return ret;
-+}
-+
-+/*
-+ *    Nand_page_program function is used for write and writev !
-+ *    This function will always program a full page of data
-+ *    If you call it with a non page aligned buffer, you're lost :)
-+ */
-+static int sl2312_nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  struct nand_oobinfo *oobsel)
-+{
-+      int     i, j, status, opcode;
-+      u_char  ecc_code[16], *oob_data;
-+      int     eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-+      //int   *oob_config = oobsel->eccpos;
-+
-+      /* pad oob area, if we have no oob buffer from fs-driver */
-+      if (!oob_buf) {
-+              oob_data = &this->data_buf[mtd->oobblock];
-+              for (i = 0; i < mtd->oobsize; i++)
-+                      oob_data[i] = 0xff;
-+      } else
-+              oob_data = oob_buf;
-+
-+      /* Send command to begin auto page programming */
-+
-+      memset(oob_data,0xff,mtd->oobsize);
-+      /* Write out complete page of data, take care of eccmode */
-+      switch (eccmode) {
-+      /* No ecc and software ecc 3/256, write all */
-+      case NAND_ECC_NONE:
-+              printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+              break;
-+      case NAND_ECC_SOFT:
-+              break;
-+
-+      /* Hardware ecc 3 byte / 256 data, write first half, get ecc, then second, if 512 byte pagesize */
-+      case NAND_ECC_HW3_256:
-+              break;
-+
-+      /* Hardware ecc 3 byte / 512 byte data, write full page */
-+      case NAND_ECC_HW3_512:
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
-+
-+      /* Hardware ecc 6 byte / 512 byte data, write full page */
-+      case NAND_ECC_HW6_512:
-+              break;
-+
-+      default:
-+              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+              //BUG();
-+      }
-+
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+
-+      for(i=0;i<mtd->oobblock;i++)
-+      {
-+              //udelay(5);
-+              FLASH_WRITE_DATA((page*mtd->oobblock)+i,this->data_poi[i]);
-+      }
-+      ///////////////
-+      if(eccmode!=NAND_ECC_NONE)
-+      {
-+              opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+              while(!(opcode&0x80000000)) //polling flash access 31b
-+      {
-+                 opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                 //sl2312_flash_delay();
-+                 schedule();
-+      }
-+
-+
-+      for(i=0;i<(mtd->oobblock/512);i++)
-+      {
-+              opcode=FLASH_READ_REG(NFLASH_ECC_CODE_GEN0+(i*4));
-+
-+              for(j=3;j>0;j--)
-+                    oob_data[(mtd->oobsize-j-(i*4))] = (opcode<<((4-j)*8)) >>24;
-+
-+              for(j=0;j<4;j++)
-+              {
-+                      ecc_code[15-i*4] = opcode;
-+                      ecc_code[15-i*4-1] = opcode>>8;
-+                      ecc_code[15-i*4-2] = opcode>>16;
-+              }
-+      }
-+
-+      //disable ecc
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000);
-+
-+      /* Write out OOB data */
-+      for(i=0;i<mtd->oobsize;i++)
-+      {
-+              //udelay(5);
-+                      FLASH_WRITE_DATA((page*mtd->oobblock)+mtd->oobblock+i,oob_data[i]);
-+              }
-+    }
-+    else
-+    {
-+      for(i=0;i<mtd->oobsize;i++)
-+      {
-+              //udelay(5);
-+                      FLASH_WRITE_DATA((page*mtd->oobblock)+mtd->oobblock+i,0xff);
-+              }
-+    }
-+
-+
-+      /* call wait ready function */
-+      status = this->waitfunc (mtd, this, FL_WRITING);
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+      /* See if device thinks it succeeded */
-+      if (status & 0x01) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+              return -EIO;
-+      }
-+
-+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-+      /*
-+       * The NAND device assumes that it is always writing to
-+       * a cleanly erased page. Hence, it performs its internal
-+       * write verification only on bits that transitioned from
-+       * 1 to 0. The device does NOT verify the whole page on a
-+       * byte by byte basis. It is possible that the page was
-+       * not completely erased or the page is becoming unusable
-+       * due to wear. The read with ECC would catch the error
-+       * later when the ECC page check fails, but we would rather
-+       * catch it early in the page write stage. Better to write
-+       * no data than invalid data.
-+       */
-+
-+      /* Send command to read back the page */
-+      this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
-+      /* Loop through and verify the data */
-+      if (this->verify_buf(mtd, this->data_poi, mtd->oobblock)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-+              return -EIO;
-+      }
-+
-+      /* check, if we have a fs-supplied oob-buffer */
-+      if (oob_buf) {
-+              if (this->verify_buf(mtd, oob_data, mtd->oobsize)) {
-+                      DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-+                      return -EIO;
-+              }
-+      } else {
-+              if (eccmode != NAND_ECC_NONE) {
-+                      int ecc_bytes = 0;
-+
-+                      switch (this->eccmode) {
-+                      case NAND_ECC_SOFT:
-+                      case NAND_ECC_HW3_256: ecc_bytes = (mtd->oobblock == 512) ? 6 : 3; break;
-+                      case NAND_ECC_HW3_512: ecc_bytes = 3; break;
-+                      case NAND_ECC_HW6_512: ecc_bytes = 6; break;
-+                      }
-+
-+
-+
-+                      for(i=0;i < (mtd->oobblock+mtd->oobsize);i++)
-+                      {
-+                              if(i>=mtd->oobblock)
-+                                      oob_data[i-mtd->oobblock] = FLASH_READ_DATA((page*mtd->oobblock) +i);
-+                              else
-+                                      oob_data[0] = FLASH_READ_DATA((page*mtd->oobblock) +i);
-+                      }
-+
-+                      if(this->eccmode == NAND_ECC_HW3_512)
-+                      {
-+                              for(i=0;i<(mtd->oobblock/512);i++)
-+                      {
-+                              for(j=0;j<3;j++)
-+                              {
-+                                  if (oob_data[mtd->oobsize-1-j-4*i] != ecc_code[15-j-4*i]) {
-+                                                      DEBUG (MTD_DEBUG_LEVEL0,
-+                                                             "%s: Failed ECC write "
-+                                                     "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
-+                                                      return -EIO;
-+                                              }
-+                              }
-+                      }
-+                      }
-+              }//eccmode != NAND_ECC_NONE
-+      }
-+      /*
-+       * Terminate the read command. This is faster than sending a reset command or
-+       * applying a 20us delay before issuing the next programm sequence.
-+       * This is not a problem for all chips, but I have found a bunch of them.
-+       */
-+      //this->select_chip(mtd, -1);
-+      //this->select_chip(mtd, 0);
-+#endif
-+
-+      return 0;
-+}
-+
-+/*
-+ * NAND write with iovec
-+ */
-+static int sl2312_nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-+              loff_t to, size_t * retlen)
-+{
-+      return (sl2312_nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, 0));
-+}
-+
-+static int sl2312_nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-+              loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel)
-+{
-+      int i, page, len, total_len, ret = 0, written = 0;
-+      struct nand_chip *this = mtd->priv;
-+
-+      /* Calculate total length of data */
-+      total_len = 0;
-+      for (i = 0; i < count; i++)
-+              total_len += (int) vecs[i].iov_len;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3,
-+             "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
-+
-+      /* Do not allow write past end of page */
-+      if ((to + total_len) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n");
-+              return -EINVAL;
-+      }
-+
-+      /* reject writes, which are not page aligned */
-+      if (NOTALIGNED (to) || NOTALIGNED(total_len)) {
-+              printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
-+              return -EINVAL;
-+      }
-+
-+      // if oobsel is NULL, use chip defaults
-+      if (oobsel == NULL)
-+              oobsel = &mtd->oobinfo;
-+
-+      /* Shift to get page */
-+      page = ((int) to) >> this->page_shift;
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Check the WP bit */
-+      if (!(sl2312_device_ready(mtd) & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "sl2312_nand_writev_ecc: Device is write protected!!!\n");
-+              ret = -EIO;
-+              goto out;
-+      }
-+
-+      /* Loop until all iovecs' data has been written */
-+      len = 0;
-+      while (count) {
-+              /*
-+               *  Check, if the tuple gives us not enough data for a
-+               *  full page write. Then we can use the iov direct,
-+               *  else we have to copy into data_buf.
-+               */
-+              if ((vecs->iov_len - len) >= mtd->oobblock) {
-+                      this->data_poi = (u_char *) vecs->iov_base;
-+                      this->data_poi += len;
-+                      len += mtd->oobblock;
-+                      /* Check, if we have to switch to the next tuple */
-+                      if (len >= (int) vecs->iov_len) {
-+                              vecs++;
-+                              len = 0;
-+                              count--;
-+                      }
-+              } else {
-+                      /*
-+                       * Read data out of each tuple until we have a full page
-+                       * to write or we've read all the tuples.
-+                      */
-+                      int cnt = 0;
-+                      while ((cnt < mtd->oobblock) && count) {
-+                              if (vecs->iov_base != NULL && vecs->iov_len) {
-+                                      this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
-+                              }
-+                              /* Check, if we have to switch to the next tuple */
-+                              if (len >= (int) vecs->iov_len) {
-+                                      vecs++;
-+                                      len = 0;
-+                                      count--;
-+                              }
-+                      }
-+                      this->data_poi = this->data_buf;
-+              }
-+
-+              /* We use the same function for write and writev !) */
-+              ret = sl2312_nand_write_page (mtd, this, page, NULL, oobsel);
-+              if (ret)
-+                      goto out;
-+
-+              /* Update written bytes count */
-+              written += mtd->oobblock;;
-+
-+              /* Increment page address */
-+              page++;
-+      }
-+
-+out:
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      *retlen = written;
-+      return ret;
-+}
-+
-+/*
-+static u_char ffchars[] = {
-+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-+};
-+*/
-+/*
-+ * NAND write out-of-band
-+ */
-+static int sl2312_nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
-+{
-+      int column, page, status, ret = 0, j=0;
-+      struct nand_chip *this = mtd->priv;
-+      u_char *databuf, *oobbuf;
-+
-+
-+              databuf = &this->data_buf[0];
-+              oobbuf = &this->data_buf[mtd->oobblock];
-+              for (j = 0; j < mtd->oobsize; j++)
-+                      oobbuf[j] = 0xff;
-+//#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-+//    int     i;
-+//#endif
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
-+
-+      /* Shift to get page */
-+      page = ((int) to) >> this->page_shift;
-+
-+      /* Mask to get column */
-+      column = to & 0x1f;
-+
-+      /* Initialize return length value */
-+      *retlen = 0;
-+
-+      /* Do not allow write past end of page */
-+      if ((column + len) > mtd->oobsize) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Reset the chip. Some chips (like the Toshiba TC5832DC found
-+         in one of my DiskOnChip 2000 test units) will clear the whole
-+         data page too if we don't do this. I have no clue why, but
-+         I seem to have 'fixed' it in the doc2000 driver in
-+         August 1999.  dwmw2. */
-+      this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-+
-+      /* Check the WP bit */
-+      if (!(sl2312_device_ready(mtd) & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Device is write protected!!!\n");
-+              ret = -EIO;
-+              goto out;
-+      }
-+      /* Write out desired data */
-+      this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page);
-+
-+      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , retlen, databuf, oobbuf, NULL);
-+
-+    for(j=column;j<(column+len);j++)
-+      oobbuf[j] = buf[j-column];
-+    sl2312_nand_write_ecc (mtd, page, mtd->oobblock, retlen, databuf, oobbuf, NULL);
-+
-+      status = this->waitfunc (mtd, this, FL_WRITING);
-+
-+      /* See if device thinks it succeeded */
-+      if (status & 0x01) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
-+              ret = -EIO;
-+              goto out;
-+      }
-+      /* Return happy */
-+      *retlen = len;
-+
-+
-+out:
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      return ret;
-+}
-+
-+/*
-+ * NAND sync
-+ */
-+static void sl2312_nand_sync (struct mtd_info *mtd)
-+{
-+      struct nand_chip *this = mtd->priv;
-+      DECLARE_WAITQUEUE (wait, current);
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
-+
-+retry:
-+      /* Grab the spinlock */
-+      spin_lock_bh (&this->chip_lock);
-+
-+      /* See what's going on */
-+      switch (this->state) {
-+      case FL_READY:
-+      case FL_SYNCING:
-+              this->state = FL_SYNCING;
-+              spin_unlock_bh (&this->chip_lock);
-+              break;
-+
-+      default:
-+              /* Not an idle state */
-+              add_wait_queue (&this->wq, &wait);
-+              spin_unlock_bh (&this->chip_lock);
-+              schedule ();
-+
-+              remove_wait_queue (&this->wq, &wait);
-+              goto retry;
-+      }
-+
-+      /* Lock the device */
-+      spin_lock_bh (&this->chip_lock);
-+
-+      /* Set the device to be ready again */
-+      if (this->state == FL_SYNCING) {
-+              this->state = FL_READY;
-+              wake_up (&this->wq);
-+      }
-+
-+      /* Unlock the device */
-+      spin_unlock_bh (&this->chip_lock);
-+}
-+
-+
-+/*
-+ * Scan for the NAND device
-+ */
-+int sl2312_nand_scan (struct mtd_info *mtd, int maxchips)
-+{
-+      int i, j, nand_maf_id, nand_dev_id, busw;
-+      struct nand_chip *this = mtd->priv;
-+      unsigned char id[4];
-+
-+      /* Get buswidth to select the correct functions*/
-+      busw = this->options & NAND_BUSWIDTH_16;
-+
-+      /* check for proper chip_delay setup, set 20us if not */
-+      if (!this->chip_delay)
-+              this->chip_delay = 20;
-+
-+      /* check, if a user supplied command function given */
-+      if (this->cmdfunc == NULL)
-+              this->cmdfunc = sl2312_nand_command;
-+
-+      /* check, if a user supplied wait function given */
-+      if (this->waitfunc == NULL)
-+              this->waitfunc = sl2312_nand_waitfunc;
-+
-+      if (!this->select_chip)
-+              this->select_chip = sl2312_nand_select_chip;
-+      if (!this->write_byte)
-+              this->write_byte = sl2312_nand_write_byte; //busw ? nand_write_byte16 : nand_write_byte;
-+      if (!this->read_byte)
-+              this->read_byte = sl2312_nand_read_byte; //busw ? nand_read_byte16 : nand_read_byte;
-+//    if (!this->write_word)
-+//            this->write_word = nand_write_word;
-+//    if (!this->read_word)
-+//            this->read_word = nand_read_word;
-+//    if (!this->block_bad)
-+              this->block_bad = sl2312_nand_block_bad; //nand_block_bad;
-+      if (!this->block_markbad)
-+              this->block_markbad = sl2312_nand_default_block_markbad;
-+      if (!this->write_buf)
-+              this->write_buf = sl2312_nand_write_buf; //busw ? nand_write_buf16 : nand_write_buf;
-+      if (!this->read_buf)
-+              this->read_buf = sl2312_nand_read_buf; //busw ? nand_read_buf16 : nand_read_buf;
-+      if (!this->verify_buf)
-+              this->verify_buf = sl2312_nand_verify_buf; //busw ? nand_verify_buf16 : nand_verify_buf;
-+      if (!this->scan_bbt)
-+              this->scan_bbt = sl2312_nand_scan_bbt;
-+
-+      /* Select the device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Read manufacturer and device IDs */
-+      nand_read_id(0,id);
-+
-+      nand_maf_id = id[0];
-+      nand_dev_id = id[1];
-+
-+      /* Print and store flash device information */
-+      for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-+
-+              if (nand_dev_id != nand_flash_ids[i].id)
-+                      continue;
-+
-+              if (!mtd->name) mtd->name = nand_flash_ids[i].name;
-+              this->chipsize = nand_flash_ids[i].chipsize << 20;
-+
-+              /* New devices have all the information in additional id bytes */
-+              if (!nand_flash_ids[i].pagesize) {
-+                      int extid;
-+
-+                      /* The 4th id byte is the important one */
-+                      extid = id[3];
-+                      /* Calc pagesize */
-+                      mtd->oobblock = 1024 << (extid & 0x3);
-+                      extid >>= 2;
-+                      /* Calc oobsize */
-+                      mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512);
-+                      extid >>= 2;
-+                      /* Calc blocksize. Blocksize is multiples of 64KiB */
-+                      mtd->erasesize = (64 * 1024)  << (extid & 0x03);
-+                      extid >>= 2;
-+                      /* Get buswidth information */
-+                      busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
-+
-+              } else {
-+                      /* Old devices have this data hardcoded in the
-+                       * device id table */
-+                      mtd->erasesize = nand_flash_ids[i].erasesize;
-+                      mtd->oobblock = nand_flash_ids[i].pagesize;
-+                      mtd->oobsize = mtd->oobblock / 32;
-+                      busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
-+              }
-+
-+              /* Check, if buswidth is correct. Hardware drivers should set
-+               * this correct ! */
-+              if (busw != (this->options & NAND_BUSWIDTH_16)) {
-+                      printk (KERN_INFO "NAND device: Manufacturer ID:"
-+                              " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-+                              nand_manuf_ids[i].name , mtd->name);
-+                      printk (KERN_WARNING
-+                              "NAND bus width %d instead %d bit\n",
-+                                      (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
-+                                      busw ? 16 : 8);
-+                      this->select_chip(mtd, -1);
-+                      return 1;
-+              }
-+
-+              /* Calculate the address shift from the page size */
-+              this->page_shift = ffs(mtd->oobblock) - 1;
-+              this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
-+              this->chip_shift = ffs(this->chipsize) - 1;
-+
-+              /* Set the bad block position */
-+              this->badblockpos = mtd->oobblock > 512 ?
-+                      NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-+
-+              /* Get chip options, preserve non chip based options */
-+              this->options &= ~NAND_CHIPOPTIONS_MSK;
-+              this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
-+              /* Set this as a default. Board drivers can override it, if neccecary */
-+              this->options |= NAND_NO_AUTOINCR;
-+              /* Check if this is a not a samsung device. Do not clear the options
-+               * for chips which are not having an extended id.
-+               */
-+              if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
-+                      this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
-+
-+              /* Check for AND chips with 4 page planes */
-+      //      if (this->options & NAND_4PAGE_ARRAY)
-+      //              this->erase_cmd = multi_erase_cmd;
-+      //      else
-+      //              this->erase_cmd = single_erase_cmd;
-+
-+              /* Do not replace user supplied command function ! */
-+      //      if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
-+      //              this->cmdfunc = nand_command_lp;
-+
-+              /* Try to identify manufacturer */
-+              for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
-+                      if (nand_manuf_ids[j].id == nand_maf_id)
-+                              break;
-+              }
-+              printk (KERN_INFO "NAND device: Manufacturer ID:"
-+                      " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-+                      nand_manuf_ids[j].name , nand_flash_ids[i].name);
-+              break;
-+      }
-+      /////////////////////////////
-+
-+      for (i=1; i < maxchips; i++) {
-+              this->select_chip(mtd, i);
-+
-+              /* Send the command for reading device ID */
-+              nand_read_id(1,id);
-+
-+              /* Read manufacturer and device IDs */
-+              if (nand_maf_id != id[0] ||
-+                  nand_dev_id != id[1])
-+                      break;
-+      }
-+      if (i > 1)
-+              printk(KERN_INFO "%d NAND chips detected\n", i);
-+
-+      /* Allocate buffers, if neccecary */
-+      if (!this->oob_buf) {
-+              size_t len;
-+              len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);
-+              this->oob_buf = kmalloc (len, GFP_KERNEL);
-+              if (!this->oob_buf) {
-+                      printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");
-+                      return -ENOMEM;
-+              }
-+              this->options |= NAND_OOBBUF_ALLOC;
-+      }
-+
-+      if (!this->data_buf) {
-+              size_t len;
-+              len = mtd->oobblock + mtd->oobsize;
-+              this->data_buf = kmalloc (len, GFP_KERNEL);
-+              if (!this->data_buf) {
-+                      if (this->options & NAND_OOBBUF_ALLOC)
-+                              kfree (this->oob_buf);
-+                      printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
-+                      return -ENOMEM;
-+              }
-+              this->options |= NAND_DATABUF_ALLOC;
-+      }
-+
-+      /* Store the number of chips and calc total size for mtd */
-+      this->numchips = i;
-+      mtd->size = i * this->chipsize;
-+      /* Convert chipsize to number of pages per chip -1. */
-+      this->pagemask = (this->chipsize >> this->page_shift) - 1;
-+      /* Preset the internal oob buffer */
-+      memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
-+
-+      /* If no default placement scheme is given, select an
-+       * appropriate one */
-+      if (!this->autooob) {
-+              /* Select the appropriate default oob placement scheme for
-+               * placement agnostic filesystems */
-+              switch (mtd->oobsize) {
-+              case 8:
-+                      this->autooob = &nand_oob_8;
-+                      break;
-+              case 16:
-+                      this->autooob = &nand_oob_16;
-+                      break;
-+              case 64:
-+                      this->autooob = &nand_oob_64;
-+                      break;
-+              default:
-+                      printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
-+                              mtd->oobsize);
-+                      BUG();
-+              }
-+      }
-+
-+      /* The number of bytes available for the filesystem to place fs dependend
-+       * oob data */
-+      if (this->options & NAND_BUSWIDTH_16) {
-+              mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2);
-+              if (this->autooob->eccbytes & 0x01)
-+                      mtd->oobavail--;
-+      } else
-+              mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1);
-+
-+
-+      /*
-+       * check ECC mode, default to software
-+       * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize
-+       * fallback to software ECC
-+      */
-+      this->eccsize = 256;    /* set default eccsize */
-+      this->eccbytes = 3;
-+
-+      switch (this->eccmode) {
-+      case NAND_ECC_HW12_2048:
-+              if (mtd->oobblock < 2048) {
-+                      printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
-+                             mtd->oobblock);
-+                      this->eccmode = NAND_ECC_SOFT;
-+                      this->calculate_ecc = nand_calculate_ecc;
-+                      this->correct_data = nand_correct_data;
-+              } else
-+                      this->eccsize = 2048;
-+              break;
-+
-+      case NAND_ECC_HW3_512:
-+      case NAND_ECC_HW6_512:
-+      case NAND_ECC_HW8_512:
-+              if (mtd->oobblock == 256) {
-+                      printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
-+                      this->eccmode = NAND_ECC_SOFT;
-+                      this->calculate_ecc = nand_calculate_ecc;
-+                      this->correct_data = nand_correct_data;
-+              } else
-+                      this->eccsize = 512; /* set eccsize to 512 */
-+              break;
-+
-+      case NAND_ECC_HW3_256:
-+              break;
-+
-+      case NAND_ECC_NONE:
-+              printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");
-+              this->eccmode = NAND_ECC_NONE;
-+              break;
-+
-+      case NAND_ECC_SOFT:
-+              this->calculate_ecc = nand_calculate_ecc;
-+              this->correct_data = nand_correct_data;
-+              break;
-+
-+      default:
-+              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
-+              BUG();
-+      }
-+
-+      /* Check hardware ecc function availability and adjust number of ecc bytes per
-+       * calculation step
-+      */
-+      switch (this->eccmode) {
-+      case NAND_ECC_HW12_2048:
-+              this->eccbytes += 4;
-+      case NAND_ECC_HW8_512:
-+              this->eccbytes += 2;
-+      case NAND_ECC_HW6_512:
-+              this->eccbytes += 3;
-+//    case NAND_ECC_HW3_512:
-+      case NAND_ECC_HW3_256:
-+              if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
-+                      break;
-+              printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
-+              BUG();
-+      }
-+
-+      mtd->eccsize = this->eccsize;
-+
-+      /* Set the number of read / write steps for one page to ensure ECC generation */
-+      switch (this->eccmode) {
-+      case NAND_ECC_HW12_2048:
-+              this->eccsteps = mtd->oobblock / 2048;
-+              break;
-+      case NAND_ECC_HW3_512:
-+      case NAND_ECC_HW6_512:
-+      case NAND_ECC_HW8_512:
-+              this->eccsteps = mtd->oobblock / 512;
-+              break;
-+      case NAND_ECC_HW3_256:
-+      case NAND_ECC_SOFT:
-+              this->eccsteps = mtd->oobblock / 256;
-+              break;
-+
-+      case NAND_ECC_NONE:
-+              this->eccsteps = 1;
-+              break;
-+      }
-+
-+      /* Initialize state, waitqueue and spinlock */
-+      this->state = FL_READY;
-+      init_waitqueue_head (&this->wq);
-+      spin_lock_init (&this->chip_lock);
-+
-+      /* De-select the device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Print warning message for no device */
-+      if (!mtd->size) {
-+              printk (KERN_WARNING "No NAND device found!!!\n");
-+              return 1;
-+      }
-+
-+      /* Fill in remaining MTD driver data */
-+      mtd->type = MTD_NANDFLASH;
-+      mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
-+      mtd->ecctype = MTD_ECC_SW;
-+      mtd->erase = sl2312_nand_erase;
-+      mtd->point = NULL;
-+      mtd->unpoint = NULL;
-+      mtd->read = sl2312_nand_read;
-+      mtd->write = sl2312_nand_write;
-+      mtd->read_ecc = sl2312_nand_read_ecc;
-+      mtd->write_ecc = sl2312_nand_write_ecc;
-+      mtd->read_oob = sl2312_nand_read_oob;
-+      mtd->write_oob = sl2312_nand_write_oob;
-+      mtd->readv = NULL;
-+      mtd->writev = sl2312_nand_writev;
-+      mtd->writev_ecc = sl2312_nand_writev_ecc;
-+      mtd->sync = sl2312_nand_sync;
-+      mtd->lock = NULL;
-+      mtd->unlock = NULL;
-+      mtd->suspend = NULL;
-+      mtd->resume = NULL;
-+      mtd->block_isbad = sl2312_nand_block_isbad;
-+      mtd->block_markbad = sl2312_nand_block_markbad;
-+
-+      /* and make the autooob the default one */
-+      memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
-+
-+      mtd->owner = THIS_MODULE;
-+
-+      /* Build bad block table */
-+      return this->scan_bbt (mtd);
-+}
-+
-+/*End Add function*/
-+
-+/*
-+ * Main initialization routine
-+ */
-+extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
-+
-+int __init sl2312_mtd_init (void)
-+{
-+      struct nand_chip *this;
-+      int err = 0;
-+      struct mtd_partition *parts;
-+      int nr_parts = 0;
-+      int ret, data, *base;
-+
-+      printk("NAND MTD Driver Start Init ......\n");
-+
-+      base = (unsigned int *)(IO_ADDRESS(SL2312_GLOBAL_BASE) + 0x30);
-+      data = *base;
-+      data&=0xffffffeb;
-+      data|=0x3; //disable p & s flash
-+        *base = data;
-+
-+      /* Allocate memory for MTD device structure and private data */
-+      sl2312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-+      if (!sl2312_mtd) {
-+              printk ("Unable to allocate SL2312 NAND MTD device structure.\n");
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      //  sl2312_device_setup();
-+
-+      /* io is indirect via a register so don't need to ioremap address */
-+
-+      /* Get pointer to private data */
-+      this = (struct nand_chip *) (&sl2312_mtd[1]);
-+
-+      /* Initialize structures */
-+      memset((char *) sl2312_mtd, 0, sizeof(struct mtd_info));
-+      memset((char *) this, 0, sizeof(struct nand_chip));
-+
-+      /* Link the private data with the MTD structure */
-+      sl2312_mtd->priv = this;
-+      sl2312_mtd->name = "sl2312-nand";
-+
-+      /* Set address of NAND IO lines */
-+      this->IO_ADDR_R = (void __iomem *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE+NFLASH_DATA)); //(unsigned long)&(sl2312_ndfmcptr->dtr);
-+      this->IO_ADDR_W = (void __iomem *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE+NFLASH_DATA)); //(unsigned long)&(sl2312_ndfmcptr->dtr);
-+      this->read_byte = sl2312_nand_read_byte;
-+    this->write_byte = sl2312_nand_write_byte;
-+    this->write_buf = sl2312_nand_write_buf;
-+      this->read_buf = sl2312_nand_read_buf;
-+      this->verify_buf = sl2312_nand_verify_buf;
-+      this->select_chip = sl2312_nand_select_chip;
-+      this->block_bad = sl2312_nand_block_bad;
-+      this->hwcontrol = sl2312_hwcontrol;
-+      this->dev_ready = sl2312_device_ready;
-+      this->cmdfunc = sl2312_nand_command;
-+      this->waitfunc = sl2312_nand_waitfunc;
-+      //this->calculate_ecc = sl2312_readecc;
-+      this->enable_hwecc = sl2312_enable_hwecc;
-+      this->eccmode = NAND_ECC_HW3_512;
-+      /*this->eccsize = 512;  */
-+      /* 20 us command delay time */
-+      this->chip_delay = 20;
-+
-+      this->correct_data = nand_correct_data;
-+//    this->scan_bbt = sl2312_nand_scan_bbt;
-+
-+      /* Allocate memory for internal data buffer */
-+      this->data_buf = kmalloc (sizeof(u_char) * (sl2312_mtd->oobblock + sl2312_mtd->oobsize), GFP_KERNEL);
-+      if (!this->data_buf) {
-+              printk ("Unable to allocate NAND data buffer.\n");
-+              err = -ENOMEM;
-+              goto out_ior;
-+      }
-+
-+      /* Scan to find existance of the device */
-+      if (sl2312_nand_scan(sl2312_mtd, 1)) {
-+              err = -ENXIO;
-+              goto out_ior;
-+      }
-+
-+      /* Register the partitions */
-+      parts = sl2312_partitions;
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
-+
-+      ret = add_mtd_partitions(sl2312_mtd, sl2312_partitions, nr_parts);
-+      /*If we got an error, free all resources.*/
-+      if (ret < 0) {
-+              del_mtd_partitions(sl2312_mtd);
-+              map_destroy(sl2312_mtd);
-+      }
-+      goto out;
-+
-+//out_buf:
-+//    kfree (this->data_buf);
-+out_ior:
-+out:
-+      printk("NAND MTD Driver Init Success ......\n");
-+      return err;
-+}
-+
-+module_init(sl2312_mtd_init);
-+
-+/*
-+ * Clean up routine
-+ */
-+#ifdef MODULE
-+static void __exit sl2312_cleanup (void)
-+{
-+      struct nand_chip *this = (struct nand_chip *) &sl2312_mtd[1];
-+
-+      /* Unregister partitions */
-+      del_mtd_partitions(sl2312_mtd);
-+
-+      /* Unregister the device */
-+      del_mtd_device (sl2312_mtd);
-+
-+      /* Free internal data buffers */
-+      kfree (this->data_buf);
-+
-+      /* Free the MTD device structure */
-+      kfree (sl2312_mtd);
-+}
-+module_exit(sl2312_cleanup);
-+#endif
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
-+MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBsl2312");
---- /dev/null
-+++ b/drivers/mtd/nand/sl2312-flash-nand.h
-@@ -0,0 +1,24 @@
-+#ifndef SL2312_FLASH_NAND_H
-+#define SL2312_FLASH_NAND_H
-+
-+#include <linux/wait.h>
-+#include <linux/spinlock.h>
-+
-+/*Add function*/
-+static void nand_read_id(int chip_no,unsigned char *id);
-+
-+
-+
-+#define       NFLASH_WiDTH8              0x00000000
-+#define       NFLASH_WiDTH16             0x00000400
-+#define       NFLASH_WiDTH32             0x00000800
-+#define NFLASH_CHIP0_EN            0x00000000  // 16th bit = 0
-+#define NFLASH_CHIP1_EN            0x00010000  // 16th bit = 1
-+#define       NFLASH_DIRECT              0x00004000
-+#define       NFLASH_INDIRECT            0x00000000
-+
-+
-+#define       DWIDTH             NFLASH_WiDTH8
-+
-+
-+#endif /* SL2312_FLASH_NAND_H */
---- /dev/null
-+++ b/include/linux/mtd/kvctl.h
-@@ -0,0 +1,40 @@
-+#ifndef KVCTL_H
-+#define KVCTL_H
-+
-+#define VCTL_HEAD_SIZE        8
-+#define VCTL_ENTRY_LEN        20
-+
-+typedef struct
-+{
-+  char header[4];
-+  unsigned int entry_num;
-+} vctl_mheader;
-+
-+typedef struct
-+{
-+  char header[4];
-+  unsigned int size;
-+  unsigned int type;
-+  char majorver[4];
-+  char minorver[4];
-+  unsigned char *payload;
-+} vctl_entry;
-+
-+typedef struct
-+{
-+  unsigned char mac[6];
-+  unsigned char vlanid;
-+  unsigned char vlanmap;
-+} vlaninfo;
-+
-+#define VCT_VENDORSPEC                0
-+#define VCT_BOOTLOADER                1
-+#define VCT_KERNEL            2
-+#define VCT_VERCTL            3
-+#define VCT_CURRCONF          4
-+#define VCT_DEFAULTCONF               5
-+#define VCT_ROOTFS            6
-+#define VCT_APP                       7
-+#define VCT_VLAN              8
-+
-+#endif
---- a/drivers/mtd/maps/Makefile
-+++ b/drivers/mtd/maps/Makefile
-@@ -71,3 +71,7 @@
- obj-$(CONFIG_MTD_OMAP_NOR)    += omap_nor.o
- obj-$(CONFIG_MTD_MTX1)                += mtx-1_flash.o
- obj-$(CONFIG_MTD_TQM834x)     += tqm834x.o
-+###### for Storlink Soc #######
-+obj-$(CONFIG_MTD_SL2312_CFI) += sl2312-flash-cfi.o
-+obj-$(CONFIG_MTD_SL2312_SERIAL_ATMEL) += sl2312-flash-atmel.o
-+obj-$(CONFIG_MTD_SL2312_SERIAL_ST) += sl2312-flash-m25p80.o
diff --git a/target/linux/storm/patches/1021-serial.patch b/target/linux/storm/patches/1021-serial.patch
deleted file mode 100644 (file)
index b7009af..0000000
+++ /dev/null
@@ -1,2809 +0,0 @@
---- /dev/null
-+++ b/drivers/serial/it8712.c
-@@ -0,0 +1,858 @@
-+/*
-+ *  linux/drivers/char/serial_uart00.c
-+ *
-+ *  Driver for UART00 serial ports
-+ *
-+ *  Based on drivers/char/serial_amba.c, by ARM Limited &
-+ *                                          Deep Blue Solutions Ltd.
-+ *  Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *  $Id: it8712.c,v 1.2 2006/06/06 06:36:04 middle Exp $
-+ *
-+ */
-+#include <linux/module.h>
-+#include <linux/tty.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <asm/hardware.h>
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+#include <asm/sizes.h>
-+
-+#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/int_ctrl.h>
-+#include <asm/arch/it8712.h>
-+#include "it8712.h"
-+
-+//#define DEBUG           1
-+#define UART_NR               1
-+
-+#define SERIAL_IT8712_NAME    "ttySI"
-+#define SERIAL_IT8712_MAJOR   204
-+#define SERIAL_IT8712_MINOR   41      /* Temporary - will change in future */
-+#define SERIAL_IT8712_NR      UART_NR
-+#define UART_PORT_SIZE 0x50
-+#define LPC_HOST_CONTINUE_MODE        0x00000040
-+
-+#define IT8712_NO_PORTS         UART_NR
-+#define IT8712_ISR_PASS_LIMIT 256
-+
-+#define LPC_BUS_CTRL  *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
-+#define LPC_BUS_STATUS        *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
-+#define LPC_SERIAL_IRQ_CTRL   *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 8))
-+#define LPC_SERIAL_IRQ_STATUS *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x0c))
-+#define LPC_SERIAL_IRQ_TRITYPE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x10))
-+#define LPC_SERIAL_IRQ_POLARITY       *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x14))
-+#define LPC_SERIAL_IRQ_ENABLE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x18))
-+
-+
-+
-+
-+/*
-+ * Access macros for the SL2312 UARTs
-+ */
-+#define UART_GET_INT_STATUS(p)        (inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
-+#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
-+#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
-+#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
-+#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
-+#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
-+#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
-+#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
-+#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
-+#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
-+#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
-+#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
-+#define UART_GET_DIV_HI(p)    inb(((p)->membase+UART_DLM))
-+#define UART_PUT_DIV_HI(p, c) outb(c,((p)->membase+UART_DLM))
-+#define UART_GET_DIV_LO(p)    inb(((p)->membase+UART_DLL))
-+#define UART_PUT_DIV_LO(p, c) outb(c,((p)->membase+UART_DLL))
-+#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
-+#define UART_RX_DATA(s)               ((s) & UART_LSR_DR)
-+#define UART_TX_READY(s)      ((s) & UART_LSR_THRE)
-+
-+static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+        unsigned int reg;
-+
-+        //printk("it8712 stop tx : \n");
-+        reg = UART_GET_IER(port);
-+        reg &= ~(UART_IER_THRI);
-+      UART_PUT_IER(port, reg);
-+}
-+
-+static void it8712_stop_rx(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+        //printk("it8712 stop rx : \n");
-+        reg = UART_GET_IER(port);
-+        reg &= ~(UART_IER_RDI);
-+      UART_PUT_IER(port, reg);
-+
-+}
-+
-+static void it8712_enable_ms(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+        //printk("it8712 enable ms : \n");
-+
-+        reg = UART_GET_IER(port);
-+        reg |= (UART_IER_MSI);
-+      UART_PUT_IER(port, reg);
-+
-+}
-+
-+static void it8712_rx_chars(struct uart_port *port, struct pt_regs *regs)
-+{
-+      struct tty_struct *tty = port->info->tty;
-+      unsigned int status, mask, ch, flg, ignored = 0;
-+
-+ //       printk("it8712_rx_chars : \n");
-+      status = UART_GET_LSR(port);
-+      while (UART_RX_DATA(status)) {
-+
-+              /*
-+               * We need to read rds before reading the
-+               * character from the fifo
-+               */
-+              ch = UART_GET_CHAR(port);
-+              port->icount.rx++;
-+
-+              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+                      goto ignore_char;
-+
-+              flg = TTY_NORMAL;
-+
-+              /*
-+               * Note that the error handling code is
-+               * out of the main execution path
-+               */
-+
-+              if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
-+                      goto handle_error;
-+              if (uart_handle_sysrq_char(port, ch, regs))
-+                      goto ignore_char;
-+
-+      error_return:
-+              *tty->flip.flag_buf_ptr++ = flg;
-+              *tty->flip.char_buf_ptr++ = ch;
-+              tty->flip.count++;
-+      ignore_char:
-+              status = UART_GET_LSR(port);
-+      } // end of while
-+out:
-+      tty_flip_buffer_push(tty);
-+      return;
-+
-+handle_error:
-+      if (status & UART_LSR_BI) {
-+              status &= ~(UART_LSR_FE);
-+              port->icount.brk++;
-+
-+#ifdef SUPPORT_SYSRQ
-+              if (uart_handle_break(port))
-+                      goto ignore_char;
-+#endif
-+      } else if (status & UART_LSR_PE)
-+              port->icount.parity++;
-+      else if (status & UART_LSR_FE)
-+              port->icount.frame++;
-+
-+      if (status & UART_LSR_OE)
-+              port->icount.overrun++;
-+
-+      if (status & port->ignore_status_mask) {
-+              if (++ignored > 100)
-+                      goto out;
-+              goto ignore_char;
-+      }
-+
-+      mask = status & port->read_status_mask;
-+
-+      if (mask & UART_LSR_BI)
-+              flg = TTY_BREAK;
-+      else if (mask & UART_LSR_PE)
-+              flg = TTY_PARITY;
-+      else if (mask & UART_LSR_FE)
-+              flg = TTY_FRAME;
-+
-+      if (status & UART_LSR_OE) {
-+              /*
-+               * CHECK: does overrun affect the current character?
-+               * ASSUMPTION: it does not.
-+               */
-+              *tty->flip.flag_buf_ptr++ = flg;
-+              *tty->flip.char_buf_ptr++ = ch;
-+              tty->flip.count++;
-+              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+                      goto ignore_char;
-+              ch = 0;
-+              flg = TTY_OVERRUN;
-+      }
-+#ifdef SUPPORT_SYSRQ
-+      port->sysrq = 0;
-+#endif
-+      goto error_return;
-+}
-+
-+static void it8712_tx_chars(struct uart_port *port)
-+{
-+        struct circ_buf *xmit = &port->info->xmit;
-+      int count;
-+
-+      if (port->x_char) {
-+              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
-+              UART_PUT_CHAR(port, port->x_char);
-+              port->icount.tx++;
-+              port->x_char = 0;
-+
-+              return;
-+      }
-+      if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+              it8712_stop_tx(port, 0);
-+              return;
-+      }
-+
-+      count = port->fifosize >> 1;
-+      do {
-+              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
-+              UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-+              xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+              port->icount.tx++;
-+              if (uart_circ_empty(xmit))
-+                      break;
-+      } while (--count > 0);
-+
-+      if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+              uart_write_wakeup(port);
-+
-+      if (uart_circ_empty(xmit))
-+              it8712_stop_tx(port, 0);
-+}
-+
-+static void it8712_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+        unsigned int reg;
-+
-+        //printk("it8712 start tx : \n");
-+        reg = UART_GET_IER(port);
-+        reg |= (UART_IER_THRI);
-+      UART_PUT_IER(port, reg);
-+      it8712_tx_chars(port);
-+}
-+
-+static void it8712_modem_status(struct uart_port *port)
-+{
-+      unsigned int status;
-+
-+//        printk("it8712 modem status : \n");
-+
-+      status = UART_GET_MSR(port);
-+
-+      if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
-+                     UART_MSR_TERI | UART_MSR_DDCD)))
-+              return;
-+
-+        if (status & UART_MSR_DDCD)
-+                uart_handle_dcd_change(port, status & UART_MSR_DCD);
-+
-+        if (status & UART_MSR_DDSR)
-+                port->icount.dsr++;
-+
-+        if (status & UART_MSR_DCTS)
-+                uart_handle_cts_change(port, status & UART_MSR_CTS);
-+
-+      wake_up_interruptible(&port->info->delta_msr_wait);
-+
-+}
-+
-+static irqreturn_t  it8712_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+      struct uart_port *port = dev_id;
-+      unsigned int status, pass_counter = 0, data;
-+
-+
-+              data = LPC_SERIAL_IRQ_STATUS;
-+      if((data&0x10)==0x10)
-+      {
-+              status = UART_GET_INT_STATUS(port);
-+              do {
-+//                         printk("it8712_int: status %x \n", status);
-+                      switch(status)
-+                      {
-+                         case UART_IIR_RDI:
-+                         case UART_IIR_RLSI:
-+                         case UART_IIR_RCTO:
-+                              it8712_rx_chars(port, regs);
-+                         break;
-+                         case UART_IIR_THRI:
-+                              it8712_tx_chars(port);
-+                         break;
-+                         case UART_IIR_MSI:
-+                              it8712_modem_status(port);
-+                         break;
-+                         default:
-+                         break;
-+                      }
-+                      if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
-+                              break;
-+
-+                      status = UART_GET_INT_STATUS(port);
-+              } while (status);
-+      }
-+
-+              status = 0;
-+        status |= (IRQ_LPC_MASK);
-+        *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = status;
-+
-+      //cnt=0;
-+      //do{
-+      //      data = LPC_SERIAL_IRQ_STATUS;
-+              LPC_SERIAL_IRQ_STATUS = data;
-+      //      cnt++;
-+      //}while(data);
-+      //if(cnt>2)
-+      //      printf("it8712_uart_Isr clear LPC_SERIAL_IRQ_STATUS %x \n", cnt);
-+        return IRQ_HANDLED;
-+}
-+
-+static u_int it8712_tx_empty(struct uart_port *port)
-+{
-+//        printk("it8712 tx empty : \n");
-+
-+      return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
-+}
-+
-+static u_int it8712_get_mctrl(struct uart_port *port)
-+{
-+      unsigned int result = 0;
-+      unsigned int status;
-+
-+//        printk("it8712 get mctrl : \n");
-+
-+      status = UART_GET_MSR(port);
-+      if (status & UART_MSR_DCD)
-+              result |= TIOCM_CAR;
-+      if (status & UART_MSR_DSR)
-+              result |= TIOCM_DSR;
-+      if (status & UART_MSR_CTS)
-+              result |= TIOCM_CTS;
-+      if (status & UART_MSR_RI)
-+              result |= TIOCM_RI;
-+
-+      return result;
-+}
-+
-+static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
-+{
-+}
-+
-+static void it8712_break_ctl(struct uart_port *port, int break_state)
-+{
-+      unsigned int lcr;
-+
-+//        printk("it8712 break ctl : \n");
-+
-+      lcr = UART_GET_LCR(port);
-+      if (break_state == -1)
-+              lcr |= UART_LCR_SBC;
-+      else
-+              lcr &= ~UART_LCR_SBC;
-+      UART_PUT_LCR(port, lcr);
-+}
-+
-+static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
-+{
-+      u_int quot;
-+
-+      /* Special case: B0 rate */
-+      if (!baud)
-+              baud = 9600;
-+
-+      quot = (port->uartclk/(16 * baud)) ;
-+
-+      return quot;
-+}
-+static void it8712_set_termios(struct uart_port *port, struct termios *termios,
-+                               struct termios *old)
-+{
-+      unsigned int  uart_mc, old_ier, baud, quot;
-+      unsigned long flags;
-+
-+        termios->c_cflag |= CREAD;
-+        termios->c_cflag |= CLOCAL;
-+#ifdef DEBUG
-+      printk("it8712_set_cflag(0x%x) called\n", cflag);
-+#endif
-+        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-+        quot = uart_get_divisor(port, baud);
-+
-+      /* byte size and parity */
-+      switch (termios->c_cflag & CSIZE) {
-+      case CS5:
-+              uart_mc = UART_LCR_WLEN5;
-+              break;
-+      case CS6:
-+              uart_mc = UART_LCR_WLEN6;
-+              break;
-+      case CS7:
-+              uart_mc = UART_LCR_WLEN7;
-+              break;
-+      default: // CS8
-+              uart_mc = UART_LCR_WLEN8;
-+              break;
-+      }
-+
-+      if (termios->c_cflag & CSTOPB)
-+              uart_mc|= UART_LCR_STOP;
-+      if (termios->c_cflag & PARENB) {
-+              uart_mc |= UART_LCR_EVEN;
-+              if (!(termios->c_cflag & PARODD))
-+                      uart_mc |= UART_LCR_ODD;
-+      }
-+
-+        spin_lock_irqsave(&port->lock, flags);
-+        /*
-+         * Update the per-port timeout
-+         */
-+        uart_update_timeout(port, termios->c_cflag, baud);
-+      port->read_status_mask = UART_LSR_OE;
-+      if (termios->c_iflag & INPCK)
-+              port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+      if (termios->c_iflag & (BRKINT | PARMRK))
-+              port->read_status_mask |= UART_LSR_BI;
-+
-+      /*
-+       * Characters to ignore
-+       */
-+      port->ignore_status_mask = 0;
-+      if (termios->c_iflag & IGNPAR)
-+              port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+      if (termios->c_iflag & IGNBRK) {
-+              port->ignore_status_mask |= UART_LSR_BI;
-+              /*
-+               * If we're ignoring parity and break indicators,
-+               * ignore overruns to (for real raw support).
-+               */
-+              if (termios->c_iflag & IGNPAR)
-+                      port->ignore_status_mask |= UART_LSR_OE;
-+      }
-+
-+      old_ier = UART_GET_IER(port);
-+
-+        if(UART_ENABLE_MS(port, termios->c_cflag))
-+             old_ier |= UART_IER_MSI;
-+
-+      /* Set baud rate */
-+      quot = quot / 13;
-+      UART_PUT_LCR(port, UART_LCR_DLAB);
-+      UART_PUT_DIV_LO(port, (quot & 0xff));
-+      UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
-+
-+      UART_PUT_LCR(port, uart_mc);
-+//    UART_PUT_LCR(port, 0x07); // ???? it is wired
-+        UART_PUT_MCR(port, 0x08);
-+        UART_PUT_FCR(port, 0x01);
-+      UART_PUT_IER(port, 0x07);
-+
-+      spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static int it8712_startup(struct uart_port *port)
-+{
-+      int retval, i;
-+      unsigned int regs;
-+
-+        //printk("it8712 startup : \n");
-+
-+      /*
-+       * Use iobase to store a pointer to info. We need this to start a
-+       * transmission as the tranmittr interrupt is only generated on
-+       * the transition to the idle state
-+       */
-+
-+      //      regs = 0;
-+    //    regs |= (IRQ_LPC_MASK);
-+    //    *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
-+
-+      /*
-+       * Allocate the IRQ
-+       */
-+      retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", port);
-+      if (retval)
-+              return retval;
-+
-+      //printk("Init LPC int...........\n");
-+        /* setup interrupt controller  */
-+        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        regs &= ~(IRQ_LPC_MASK);
-+        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
-+        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        regs &= ~(IRQ_LPC_MASK);
-+        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
-+        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_LPC_MASK);
-+
-+      LPC_SERIAL_IRQ_POLARITY = 0x10; //0x10; //0x02;
-+      LPC_SERIAL_IRQ_TRITYPE = 0x10; //0x10;//
-+      LPC_SERIAL_IRQ_ENABLE = 0x10;
-+
-+      LPC_BUS_CTRL = 0xc0;
-+      LPC_SERIAL_IRQ_CTRL = 0xc0;
-+      for(i=0;i<1000;i++) ;
-+      LPC_SERIAL_IRQ_CTRL = 0x80;
-+      /*
-+       * Finally, enable interrupts. Use the TII interrupt to minimise
-+       * the number of interrupts generated. If higher performance is
-+       * needed, consider using the TI interrupt with a suitable FIFO
-+       * threshold
-+       */
-+      //UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
-+      UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI|UART_IER_RLSI));//middle
-+
-+      return 0;
-+}
-+
-+static void it8712_shutdown(struct uart_port *port)
-+{
-+        //printk("it8712 shutdown : \n");
-+
-+      /*
-+       * disable all interrupts, disable the port
-+       */
-+      UART_PUT_IER(port, 0x0);
-+
-+      /* disable break condition and fifos */
-+//    UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
-+
-+      /*
-+       * Free the interrupt
-+       */
-+      free_irq(port->irq, port);
-+}
-+
-+static const char *it8712_type(struct uart_port *port)
-+{
-+      return port->type == PORT_IT8712 ? "IT8712" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void it8712_release_port(struct uart_port *port)
-+{
-+//        printk("it8712 release port : \n");
-+
-+      release_mem_region(port->mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int it8712_request_port(struct uart_port *port)
-+{
-+      return request_mem_region(port->mapbase, UART_PORT_SIZE,
-+                                  "serial_it8712") != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void it8712_config_port(struct uart_port *port, int flags)
-+{
-+
-+      if (flags & UART_CONFIG_TYPE) {
-+              if (it8712_request_port(port) == 0)
-+                      port->type = PORT_IT8712;
-+      }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+      int ret = 0;
-+
-+      if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
-+              ret = -EINVAL;
-+      if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+              ret = -EINVAL;
-+      if (ser->baud_base < 9600)
-+              ret = -EINVAL;
-+      return ret;
-+}
-+
-+static struct uart_ops it8712_pops = {
-+      .tx_empty       = it8712_tx_empty,
-+      .set_mctrl      = it8712_set_mctrl_null,
-+      .get_mctrl      = it8712_get_mctrl,
-+      .stop_tx        = it8712_stop_tx,
-+      .start_tx       = it8712_start_tx,
-+      .stop_rx        = it8712_stop_rx,
-+      .enable_ms      = it8712_enable_ms,
-+      .break_ctl      = it8712_break_ctl,
-+      .startup        = it8712_startup,
-+      .shutdown       = it8712_shutdown,
-+      .set_termios    = it8712_set_termios,
-+      .type           = it8712_type,
-+      .release_port   = it8712_release_port,
-+      .request_port   = it8712_request_port,
-+      .config_port    = it8712_config_port,
-+      .verify_port    = it8712_verify_port,
-+};
-+
-+#ifdef CONFIG_ARCH_SL2312
-+
-+static struct uart_port it8712_ports[UART_NR] = {
-+      {
-+              membase:        (void *)0,
-+              mapbase:        0,
-+              iotype:         SERIAL_IO_MEM,
-+              irq:            0,
-+              uartclk:        UART_CLK/2,
-+              fifosize:       16,
-+              ops:            &it8712_pops,
-+              flags:          ASYNC_BOOT_AUTOCONF,
-+      }
-+};
-+
-+#endif
-+
-+#ifdef CONFIG_SERIAL_IT8712_CONSOLE
-+#ifdef used_and_not_const_char_pointer
-+static int it8712_console_read(struct uart_port *port, char *s, u_int count)
-+{
-+      unsigned int status;
-+      int c;
-+#ifdef DEBUG
-+      printk("it8712_console_read() called\n");
-+#endif
-+
-+      c = 0;
-+      while (c < count) {
-+              status = UART_GET_LSR(port);
-+              if (UART_RX_DATA(status)) {
-+                      *s++ = UART_GET_CHAR(port);
-+                      c++;
-+              } else {
-+                      // nothing more to get, return
-+                      return c;
-+              }
-+      }
-+      // return the count
-+      return c;
-+}
-+#endif
-+static void it8712_console_write(struct console *co, const char *s, unsigned count)
-+{
-+#ifdef CONFIG_ARCH_SL2312
-+      struct uart_port *port = it8712_ports + co->index;
-+      unsigned int status, old_ies;
-+      int i;
-+
-+      /*
-+       *      First save the CR then disable the interrupts
-+       */
-+      old_ies = UART_GET_IER(port);
-+      //if(old_ies!=7)
-+      //{
-+      //
-+      //      printk("old_ies = %x\n",old_ies);
-+      //      old_ies = 7;
-+      //}
-+      UART_PUT_IER(port,0x0);
-+
-+      /*
-+       *      Now, do each character
-+       */
-+      for (i = 0; i < count; i++) {
-+              do {
-+                      status = UART_GET_LSR(port);
-+              } while (!UART_TX_READY(status));
-+              UART_PUT_CHAR(port, s[i]);
-+              if (s[i] == '\n') {
-+                      do {
-+                              status = UART_GET_LSR(port);
-+                      } while (!UART_TX_READY(status));
-+                      UART_PUT_CHAR(port, '\r');
-+              }
-+      }
-+
-+      /*
-+       *      Finally, wait for transmitter to become empty
-+       *      and restore the IES
-+       */
-+      do {
-+              status = UART_GET_LSR(port);
-+      } while (!(status&UART_LSR_THRE));
-+      UART_PUT_IER(port, old_ies);
-+#endif
-+}
-+
-+static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+      //printk("it8712 console get options : \n");
-+
-+      u_int uart_mc, quot;
-+      uart_mc= UART_GET_MCR(port);
-+
-+      *parity = 'n';
-+      if (uart_mc & UART_LCR_PARITY) {
-+              if (uart_mc & UART_LCR_EVEN)
-+                      *parity = 'e';
-+              else
-+                      *parity = 'o';
-+      }
-+
-+      switch (uart_mc & UART_LCR_MSK){
-+
-+      case UART_LCR_WLEN5:
-+              *bits = 5;
-+              break;
-+      case UART_LCR_WLEN6:
-+              *bits = 6;
-+              break;
-+      case UART_LCR_WLEN7:
-+              *bits = 7;
-+              break;
-+      case UART_LCR_WLEN8:
-+              *bits = 8;
-+              break;
-+      }
-+      UART_PUT_MCR(port,UART_LCR_DLAB);
-+      quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
-+      UART_PUT_MCR(port,uart_mc);
-+      *baud = (port->uartclk / (16 *quot));
-+}
-+
-+static int __init it8712_console_setup(struct console *co, char *options)
-+{
-+      struct uart_port *port;
-+      int baud = 38400;
-+      int bits = 8;
-+      int parity = 'n';
-+      int flow= 'n';
-+      int base;//, irq;
-+      int i ;
-+
-+      printk("it8712 console setup : \n");
-+
-+      LPCSetConfig(0, 0x02, 0x01);
-+        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
-+        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
-+      base = IT8712_IO_BASE;
-+      base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
-+      it8712_ports[0].mapbase = base;
-+      it8712_ports[0].membase = (void *)IO_ADDRESS(base);
-+      it8712_ports[0].irq = IRQ_LPC_OFFSET;
-+    //        irq = LPCGetConfig(LDN_SERIAL1, 0x70);
-+      //it8712_ports[0].irq += irq;
-+
-+      //printk("it8712 irq is %x \n", it8712_ports[0].irq);
-+
-+      // setup LPC Host 'quiet mode'
-+      //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
-+      //for(i=0;i<1000;i++) ;                                         // delay
-+      //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
-+      LPC_BUS_CTRL = 0xc0;
-+      LPC_SERIAL_IRQ_CTRL = 0xc0;
-+      for(i=0;i<1000;i++) ;
-+      LPC_SERIAL_IRQ_CTRL = 0x80;
-+
-+#ifdef CONFIG_ARCH_SL2312
-+      /*
-+       * Check whether an invalid uart number has been specified, and
-+       * if so, search for the first available port that does have
-+       * console support.
-+       */
-+      port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
-+#else
-+      return -ENODEV;
-+#endif
-+
-+      if (options)
-+              uart_parse_options(options, &baud, &parity, &bits, &flow);
-+      else
-+              it8712_console_get_options(port, &baud, &parity, &bits);
-+
-+      return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+extern struct uart_driver it8712_reg;
-+static struct console it8712_console = {
-+      .name           = SERIAL_IT8712_NAME,
-+      .write          = it8712_console_write,
-+      .device         = uart_console_device,
-+        .setup          = it8712_console_setup,
-+      .flags          = CON_PRINTBUFFER,
-+      .index          = 0,
-+        .data           = &it8712_reg,
-+};
-+
-+static int __init it8712_console_init(void)
-+{
-+      register_console(&it8712_console);
-+        return 0;
-+}
-+
-+console_initcall(it8712_console_init);
-+
-+#define IT8712_CONSOLE        &it8712_console
-+#else
-+#define IT8712_CONSOLE        NULL
-+#endif
-+
-+static struct uart_driver it8712_reg = {
-+      .owner                  = NULL,
-+      .driver_name            = SERIAL_IT8712_NAME,
-+      .dev_name               = SERIAL_IT8712_NAME,
-+        .major                  = SERIAL_IT8712_MAJOR,
-+      .minor                  = SERIAL_IT8712_MINOR,
-+      .nr                     = UART_NR,
-+      .cons                   = IT8712_CONSOLE,
-+};
-+
-+static int __init it8712_init(void)
-+{
-+        int result;
-+      //printk("serial_it8712: it871212_init \n");
-+
-+
-+        result = uart_register_driver(&it8712_reg);
-+        if(result)
-+             return result;
-+      result = uart_add_one_port(&it8712_reg, &it8712_ports[0]);
-+
-+        return result;
-+
-+}
-+
-+
-+__initcall(it8712_init);
---- /dev/null
-+++ b/drivers/serial/it8712.h
-@@ -0,0 +1,135 @@
-+#define UART_RX               0       /* In:  Receive buffer (DLAB=0) */
-+#define UART_TX               0       /* Out: Transmit buffer (DLAB=0) */
-+#define UART_DLL      0       /* Out: Divisor Latch Low (DLAB=1) */
-+#define UART_TRG      0       /* (LCR=BF) FCTR bit 7 selects Rx or Tx
-+                               * In: Fifo count
-+                               * Out: Fifo custom trigger levels
-+                               * XR16C85x only */
-+
-+#define UART_DLM      1       /* Out: Divisor Latch High (DLAB=1) */
-+#define UART_IER      1       /* Out: Interrupt Enable Register */
-+#define UART_FCTR     1       /* (LCR=BF) Feature Control Register
-+                               * XR16C85x only */
-+
-+#define UART_IIR      2       /* In:  Interrupt ID Register */
-+#define UART_FCR      2       /* Out: FIFO Control Register */
-+#define UART_EFR      2       /* I/O: Extended Features Register */
-+                              /* (DLAB=1, 16C660 only) */
-+
-+#define UART_LCR      3       /* Out: Line Control Register */
-+#define UART_MCR      4       /* Out: Modem Control Register */
-+#define UART_LSR      5       /* In:  Line Status Register */
-+#define UART_MSR      6       /* In:  Modem Status Register */
-+#define UART_SCR      7       /* I/O: Scratch Register */
-+#define UART_EMSR     7       /* (LCR=BF) Extended Mode Select Register
-+                               * FCTR bit 6 selects SCR or EMSR
-+                               * XR16c85x only */
-+
-+/*
-+ * These are the definitions for the FIFO Control Register
-+ * (16650 only)
-+ */
-+#define UART_FCR_ENABLE_FIFO  0x01 /* Enable the FIFO */
-+#define UART_FCR_CLEAR_RCVR   0x02 /* Clear the RCVR FIFO */
-+#define UART_FCR_CLEAR_XMIT   0x04 /* Clear the XMIT FIFO */
-+#define UART_FCR_DMA_SELECT   0x08 /* For DMA applications */
-+#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
-+#define UART_FCR_TRIGGER_1    0x00 /* Mask for trigger set at 1 */
-+#define UART_FCR_TRIGGER_4    0x40 /* Mask for trigger set at 4 */
-+#define UART_FCR_TRIGGER_8    0x80 /* Mask for trigger set at 8 */
-+#define UART_FCR_TRIGGER_14   0xC0 /* Mask for trigger set at 14 */
-+/* 16650 redefinitions */
-+#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
-+#define UART_FCR6_R_TRIGGER_16        0x40 /* Mask for receive trigger set at 4 */
-+#define UART_FCR6_R_TRIGGER_24  0x80 /* Mask for receive trigger set at 8 */
-+#define UART_FCR6_R_TRIGGER_28        0xC0 /* Mask for receive trigger set at 14 */
-+#define UART_FCR6_T_TRIGGER_16        0x00 /* Mask for transmit trigger set at 16 */
-+#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
-+#define UART_FCR6_T_TRIGGER_24  0x20 /* Mask for transmit trigger set at 24 */
-+#define UART_FCR6_T_TRIGGER_30        0x30 /* Mask for transmit trigger set at 30 */
-+/* TI 16750 definitions */
-+#define UART_FCR7_64BYTE      0x20 /* Go into 64 byte mode */
-+
-+/*
-+ * These are the definitions for the Line Control Register
-+ *
-+ * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
-+ * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
-+ */
-+#define UART_LCR_DLAB 0x80    /* Divisor latch access bit */
-+#define UART_LCR_SBC  0x40    /* Set break control */
-+#define UART_LCR_SPAR 0x20    /* Stick parity (?) */
-+#define UART_LCR_EPAR 0x10    /* Even parity select */
-+#define UART_LCR_PARITY       0x08    /* Parity Enable */
-+#define UART_LCR_STOP 0x04    /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
-+#define UART_LCR_WLEN5  0x00  /* Wordlength: 5 bits */
-+#define UART_LCR_WLEN6  0x01  /* Wordlength: 6 bits */
-+#define UART_LCR_WLEN7  0x02  /* Wordlength: 7 bits */
-+#define UART_LCR_WLEN8  0x03  /* Wordlength: 8 bits */
-+#define UART_LCR_EVEN   0x18    /* Even parity */
-+#define UART_LCR_ODD    0x08    /* Odd parity */
-+#define UART_LCR_MSK    0x03
-+/*
-+ * These are the definitions for the Line Status Register
-+ */
-+#define UART_LSR_DE     0x80    /* FIFO Data Error */
-+#define UART_LSR_TEMT 0x40    /* Transmitter empty */
-+#define UART_LSR_THRE 0x20    /* Transmit-hold-register empty */
-+#define UART_LSR_BI   0x10    /* Break interrupt indicator */
-+#define UART_LSR_FE   0x08    /* Frame error indicator */
-+#define UART_LSR_PE   0x04    /* Parity error indicator */
-+#define UART_LSR_OE   0x02    /* Overrun error indicator */
-+#define UART_LSR_DR   0x01    /* Receiver data ready */
-+
-+/*
-+ * These are the definitions for the Interrupt Identification Register
-+ */
-+#define UART_IIR_NO_INT       0x01    /* No interrupts pending */
-+#define UART_IIR_ID   0x06    /* Mask for the interrupt ID */
-+
-+#define UART_IIR_MSI  0x00    /* Modem status interrupt */
-+#define UART_IIR_THRI 0x02    /* Transmitter holding register empty */
-+#define UART_IIR_RDI  0x04    /* Receiver data interrupt */
-+#define UART_IIR_RLSI 0x06    /* Receiver line status interrupt */
-+#define UART_IIR_RCTO 0x0c    /* Receiver character timeout interrupt */
-+/*
-+ * These are the definitions for the Interrupt Enable Register
-+ */
-+#define UART_IER_MSI  0x08    /* Enable Modem status interrupt */
-+#define UART_IER_RLSI 0x04    /* Enable receiver line status interrupt */
-+#define UART_IER_THRI 0x02    /* Enable Transmitter holding register int. */
-+#define UART_IER_RDI  0x01    /* Enable receiver data interrupt */
-+/*
-+ * Sleep mode for ST16650 and TI16750.
-+ * Note that for 16650, EFR-bit 4 must be selected as well.
-+ */
-+#define UART_IERX_SLEEP  0x10 /* Enable sleep mode */
-+
-+/*
-+ * These are the definitions for the Modem Control Register
-+ */
-+#define UART_MCR_LOOP 0x10    /* Enable loopback test mode */
-+#define UART_MCR_OUT2 0x08    /* Out2 complement */
-+#define UART_MCR_OUT1 0x04    /* Out1 complement */
-+#define UART_MCR_RTS  0x02    /* RTS complement */
-+#define UART_MCR_DTR  0x01    /* DTR complement */
-+
-+/*
-+ * These are the definitions for the Modem Status Register
-+ */
-+#define UART_MSR_DCD  0x80    /* Data Carrier Detect */
-+#define UART_MSR_RI   0x40    /* Ring Indicator */
-+#define UART_MSR_DSR  0x20    /* Data Set Ready */
-+#define UART_MSR_CTS  0x10    /* Clear to Send */
-+#define UART_MSR_DDCD 0x08    /* Delta DCD */
-+#define UART_MSR_TERI 0x04    /* Trailing edge ring indicator */
-+#define UART_MSR_DDSR 0x02    /* Delta DSR */
-+#define UART_MSR_DCTS 0x01    /* Delta CTS */
-+#define UART_MSR_ANY_DELTA 0x0F       /* Any of the delta bits! */
-+
-+#define UART_PARITY_NONE      0x00
-+#define UART_PARITY_ODD               0x01
-+#define UART_PARITY_EVEN      0x02
-+
-+
-+
---- /dev/null
-+++ b/drivers/serial/serial_it8712.c
-@@ -0,0 +1,876 @@
-+/*
-+ *  linux/drivers/char/serial_uart00.c
-+ *
-+ *  Driver for UART00 serial ports
-+ *
-+ *  Based on drivers/char/serial_amba.c, by ARM Limited &
-+ *                                          Deep Blue Solutions Ltd.
-+ *  Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *  $Id: serial_it8712.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
-+ *
-+ */
-+#include <linux/module.h>
-+
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+#include <asm/sizes.h>
-+
-+#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/int_ctrl.h>
-+#include <asm/arch/it8712.h>
-+#include "serial_it8712.h"
-+
-+//#define DEBUG           1
-+#define UART_NR               1
-+
-+#define SERIAL_IT8712_NAME    "ttySI"
-+#define SERIAL_IT8712_MAJOR   204
-+#define SERIAL_IT8712_MINOR   41      /* Temporary - will change in future */
-+#define SERIAL_IT8712_NR      UART_NR
-+#define UART_PORT_SIZE 0x50
-+
-+#define CALLOUT_IT8712_NAME   "cuaslI"
-+#define CALLOUT_IT8712_MAJOR  205
-+#define CALLOUT_IT8712_MINOR  41      /* Temporary - will change in future */
-+#define CALLOUT_IT8712_NR     UART_NR
-+#define LPC_HOST_CONTINUE_MODE        0x00000040
-+
-+#define IT8712_NO_PORTS         UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *it8712_table[UART_NR];
-+static struct termios *it8712_termios[UART_NR], *it8712_termios_locked[UART_NR];
-+static struct console it8712_console;
-+
-+#define IT8712_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the SL2312 UARTs
-+ */
-+#define UART_GET_INT_STATUS(p)        (inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
-+#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
-+#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
-+#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
-+#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
-+#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
-+#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
-+#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
-+#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
-+#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
-+#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
-+#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
-+#define UART_GET_DIV_HI(p)    inb(((p)->membase+UART_DLM))
-+#define UART_PUT_DIV_HI(p, c) outb(c,((p)->membase+UART_DLM))
-+#define UART_GET_DIV_LO(p)    inb(((p)->membase+UART_DLL))
-+#define UART_PUT_DIV_LO(p, c) outb(c,((p)->membase+UART_DLL))
-+#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
-+#define UART_RX_DATA(s)               ((s) & UART_LSR_DR)
-+#define UART_TX_READY(s)      ((s) & UART_LSR_THRE)
-+
-+static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+        unsigned int reg;
-+
-+//        printk("it8712 stop tx : \n");
-+        reg = UART_GET_IER(port);
-+        reg &= ~(UART_IER_THRI);
-+      UART_PUT_IER(port, reg);
-+}
-+
-+static void it8712_stop_rx(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+//        printk("it8712 stop rx : \n");
-+        reg = UART_GET_IER(port);
-+        reg &= ~(UART_IER_RDI);
-+      UART_PUT_IER(port, reg);
-+
-+}
-+
-+static void it8712_enable_ms(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+//        printk("it8712 enable ms : \n");
-+
-+        reg = UART_GET_IER(port);
-+        reg |= (UART_IER_MSI);
-+      UART_PUT_IER(port, reg);
-+
-+}
-+
-+static void
-+it8712_rx_chars(struct uart_info *info, struct pt_regs *regs)
-+{
-+      struct tty_struct *tty = info->tty;
-+      unsigned int status, mask, ch, flg, ignored = 0;
-+      struct uart_port *port = info->port;
-+
-+ //       printk("it8712_rx_chars : \n");
-+      status = UART_GET_LSR(port);
-+      while (UART_RX_DATA(status)) {
-+
-+              /*
-+               * We need to read rds before reading the
-+               * character from the fifo
-+               */
-+              ch = UART_GET_CHAR(port);
-+              port->icount.rx++;
-+
-+              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+                      goto ignore_char;
-+
-+              flg = TTY_NORMAL;
-+
-+              /*
-+               * Note that the error handling code is
-+               * out of the main execution path
-+               */
-+
-+              if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
-+                      goto handle_error;
-+              if (uart_handle_sysrq_char(info, ch, regs))
-+                      goto ignore_char;
-+
-+      error_return:
-+              *tty->flip.flag_buf_ptr++ = flg;
-+              *tty->flip.char_buf_ptr++ = ch;
-+              tty->flip.count++;
-+      ignore_char:
-+              status = UART_GET_LSR(port);
-+      } // end of while
-+out:
-+      tty_flip_buffer_push(tty);
-+      return;
-+
-+handle_error:
-+      if (status & UART_LSR_BI) {
-+              status &= ~(UART_LSR_FE);
-+              port->icount.brk++;
-+
-+#ifdef SUPPORT_SYSRQ
-+              if (uart_handle_break(info, &it8712_console))
-+                      goto ignore_char;
-+#endif
-+      } else if (status & UART_LSR_PE)
-+              port->icount.parity++;
-+      else if (status & UART_LSR_FE)
-+              port->icount.frame++;
-+
-+      if (status & UART_LSR_OE)
-+              port->icount.overrun++;
-+
-+      if (status & port->ignore_status_mask) {
-+              if (++ignored > 100)
-+                      goto out;
-+              goto ignore_char;
-+      }
-+
-+      mask = status & port->read_status_mask;
-+
-+      if (mask & UART_LSR_BI)
-+              flg = TTY_BREAK;
-+      else if (mask & UART_LSR_PE)
-+              flg = TTY_PARITY;
-+      else if (mask & UART_LSR_FE)
-+              flg = TTY_FRAME;
-+
-+      if (status & UART_LSR_OE) {
-+              /*
-+               * CHECK: does overrun affect the current character?
-+               * ASSUMPTION: it does not.
-+               */
-+              *tty->flip.flag_buf_ptr++ = flg;
-+              *tty->flip.char_buf_ptr++ = ch;
-+              tty->flip.count++;
-+              if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+                      goto ignore_char;
-+              ch = 0;
-+              flg = TTY_OVERRUN;
-+      }
-+#ifdef SUPPORT_SYSRQ
-+      info->sysrq = 0;
-+#endif
-+      goto error_return;
-+}
-+
-+static void it8712_tx_chars(struct uart_info *info)
-+{
-+      int count;
-+      struct uart_port *port=info->port;
-+
-+      if (port->x_char) {
-+              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
-+              UART_PUT_CHAR(port, port->x_char);
-+              port->icount.tx++;
-+              port->x_char = 0;
-+
-+              return;
-+      }
-+      if (info->xmit.head == info->xmit.tail
-+          || info->tty->stopped
-+          || info->tty->hw_stopped) {
-+              it8712_stop_tx(info->port, 0);
-+              return;
-+      }
-+
-+      count = port->fifosize >> 1;
-+      do {
-+              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
-+              UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
-+              info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
-+              port->icount.tx++;
-+              if (info->xmit.head == info->xmit.tail)
-+                      break;
-+      } while (--count > 0);
-+
-+      if (CIRC_CNT(info->xmit.head,
-+                   info->xmit.tail,
-+                   UART_XMIT_SIZE) < WAKEUP_CHARS)
-+              uart_event(info, EVT_WRITE_WAKEUP);
-+
-+      if (info->xmit.head == info->xmit.tail)
-+              it8712_stop_tx(info->port, 0);
-+}
-+
-+static void it8712_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
-+{
-+        unsigned int reg;
-+      struct uart_info *info=(struct uart_info*)(port->iobase);
-+
-+//        printk("it8712 start tx : \n");
-+        reg = UART_GET_IER(port);
-+        reg |= (UART_IER_THRI);
-+      UART_PUT_IER(port, reg);
-+      it8712_tx_chars(info);
-+}
-+
-+static void it8712_modem_status(struct uart_info *info)
-+{
-+      unsigned int status;
-+      struct uart_icount *icount = &info->port->icount;
-+
-+//        printk("it8712 modem status : \n");
-+
-+      status = UART_GET_MSR(info->port);
-+
-+      if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
-+                     UART_MSR_TERI | UART_MSR_DDCD)))
-+              return;
-+
-+      if (status & UART_MSR_DCD) {
-+              icount->dcd++;
-+#ifdef CONFIG_HARD_PPS
-+              if ((info->flags & ASYNC_HARDPPS_CD) &&
-+                  (status & UART_MSR_DCD_MSK))
-+                      hardpps();
-+#endif
-+              if (info->flags & ASYNC_CHECK_CD) {
-+                      if (status & UART_MSR_DCD)
-+                              wake_up_interruptible(&info->open_wait);
-+                      else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-+                                 (info->flags & ASYNC_CALLOUT_NOHUP))) {
-+                              if (info->tty)
-+                                      tty_hangup(info->tty);
-+                      }
-+              }
-+      }
-+
-+      if (status & UART_MSR_DDSR)
-+              icount->dsr++;
-+
-+      if (status & UART_MSR_DCTS) {
-+              icount->cts++;
-+
-+              if (info->flags & ASYNC_CTS_FLOW) {
-+                      status &= UART_MSR_CTS;
-+
-+                      if (info->tty->hw_stopped) {
-+                              if (status) {
-+                                      info->tty->hw_stopped = 0;
-+                                      info->ops->start_tx(info->port, 1, 0);
-+                                      uart_event(info, EVT_WRITE_WAKEUP);
-+                              }
-+                      } else {
-+                              if (!status) {
-+                                      info->tty->hw_stopped = 1;
-+                                      info->ops->stop_tx(info->port, 0);
-+                              }
-+                      }
-+              }
-+      }
-+      wake_up_interruptible(&info->delta_msr_wait);
-+
-+}
-+
-+static void it8712_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+      struct uart_info *info = dev_id;
-+      unsigned int status, pass_counter = 0;
-+
-+      status = UART_GET_INT_STATUS(info->port);
-+      do {
-+//                 printk("it8712_int: status %x \n", status);
-+              switch(status)
-+              {
-+                 case UART_IIR_RDI:
-+                 case UART_IIR_RLSI:
-+                 case UART_IIR_RCTO:
-+                      it8712_rx_chars(info, regs);
-+                 break;
-+                 case UART_IIR_THRI:
-+                      it8712_tx_chars(info);
-+                 break;
-+                 case UART_IIR_MSI:
-+                      it8712_modem_status(info);
-+                 break;
-+                 default:
-+                 break;
-+              }
-+              if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
-+                      break;
-+
-+              status = UART_GET_INT_STATUS(info->port);
-+      } while (status);
-+}
-+
-+static u_int it8712_tx_empty(struct uart_port *port)
-+{
-+//        printk("it8712 tx empty : \n");
-+
-+      return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
-+}
-+
-+static u_int it8712_get_mctrl(struct uart_port *port)
-+{
-+      unsigned int result = 0;
-+      unsigned int status;
-+
-+//        printk("it8712 get mctrl : \n");
-+
-+      status = UART_GET_MSR(port);
-+      if (status & UART_MSR_DCD)
-+              result |= TIOCM_CAR;
-+      if (status & UART_MSR_DSR)
-+              result |= TIOCM_DSR;
-+      if (status & UART_MSR_CTS)
-+              result |= TIOCM_CTS;
-+      if (status & UART_MSR_RI)
-+              result |= TIOCM_RI;
-+
-+      return result;
-+}
-+
-+static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
-+{
-+}
-+
-+static void it8712_break_ctl(struct uart_port *port, int break_state)
-+{
-+      unsigned int lcr;
-+
-+//        printk("it8712 break ctl : \n");
-+
-+      lcr = UART_GET_LCR(port);
-+      if (break_state == -1)
-+              lcr |= UART_LCR_SBC;
-+      else
-+              lcr &= ~UART_LCR_SBC;
-+      UART_PUT_LCR(port, lcr);
-+}
-+
-+static inline u_int uart_calculate_quot(struct uart_info *info, u_int baud)
-+{
-+      u_int quot;
-+
-+      /* Special case: B0 rate */
-+      if (!baud)
-+              baud = 9600;
-+
-+      quot = (info->port->uartclk/(16 * baud)) ;
-+
-+      return quot;
-+}
-+static void it8712_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+      u_int uart_mc=0, old_ier;
-+      unsigned long flags;
-+
-+#ifdef DEBUG
-+      printk("it8712_set_cflag(0x%x) called\n", cflag);
-+#endif
-+
-+
-+      /* byte size and parity */
-+      switch (cflag & CSIZE) {
-+      case CS5: uart_mc = UART_LCR_WLEN5; break;
-+      case CS6: uart_mc = UART_LCR_WLEN6; break;
-+      case CS7: uart_mc = UART_LCR_WLEN7; break;
-+      default:  uart_mc = UART_LCR_WLEN8; break; // CS8
-+      }
-+      if (cflag & CSTOPB)
-+              uart_mc|= UART_LCR_STOP;
-+      if (cflag & PARENB) {
-+              uart_mc |= UART_LCR_EVEN;
-+              if (!(cflag & PARODD))
-+                      uart_mc |= UART_LCR_ODD;
-+      }
-+
-+      port->read_status_mask = UART_LSR_OE;
-+      if (iflag & INPCK)
-+              port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+      if (iflag & (BRKINT | PARMRK))
-+              port->read_status_mask |= UART_LSR_BI;
-+
-+      /*
-+       * Characters to ignore
-+       */
-+      port->ignore_status_mask = 0;
-+      if (iflag & IGNPAR)
-+              port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+      if (iflag & IGNBRK) {
-+              port->ignore_status_mask |= UART_LSR_BI;
-+              /*
-+               * If we're ignoring parity and break indicators,
-+               * ignore overruns to (for real raw support).
-+               */
-+              if (iflag & IGNPAR)
-+                      port->ignore_status_mask |= UART_LSR_OE;
-+      }
-+
-+      /* first, disable everything */
-+      save_flags(flags); cli();
-+      old_ier = UART_GET_IER(port);
-+
-+      if ((port->flags & ASYNC_HARDPPS_CD) ||
-+          (cflag & CRTSCTS) || !(cflag & CLOCAL))
-+              old_ier |= UART_IER_MSI;
-+
-+      /* Set baud rate */
-+      quot = quot / 13;
-+      UART_PUT_LCR(port, UART_LCR_DLAB);
-+      UART_PUT_DIV_LO(port, (quot & 0xff));
-+      UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
-+
-+      UART_PUT_LCR(port, uart_mc);
-+//    UART_PUT_LCR(port, 0x07); // ???? it is wired
-+        UART_PUT_MCR(port, 0x08);
-+        UART_PUT_FCR(port, 0x01);
-+      UART_PUT_IER(port, 0x05);
-+
-+      restore_flags(flags);
-+}
-+
-+static int it8712_startup(struct uart_port *port, struct uart_info *info)
-+{
-+      int retval;
-+      unsigned int regs;
-+
-+//        printk("it8712 startup : \n");
-+
-+      /*
-+       * Use iobase to store a pointer to info. We need this to start a
-+       * transmission as the tranmittr interrupt is only generated on
-+       * the transition to the idle state
-+       */
-+
-+      port->iobase=(u_int)info;
-+
-+      /*
-+       * Allocate the IRQ
-+       */
-+      retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", info);
-+      if (retval)
-+              return retval;
-+
-+        /* setup interrupt controller  */
-+        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        regs |= (IRQ_SERIRQ0_MASK);
-+        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
-+        regs = *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        regs &= ~(IRQ_SERIRQ0_MASK);
-+        *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
-+        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_SERIRQ0_MASK);
-+
-+      /*
-+       * Finally, enable interrupts. Use the TII interrupt to minimise
-+       * the number of interrupts generated. If higher performance is
-+       * needed, consider using the TI interrupt with a suitable FIFO
-+       * threshold
-+       */
-+      UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
-+
-+      return 0;
-+}
-+
-+static void it8712_shutdown(struct uart_port *port, struct uart_info *info)
-+{
-+//        printk("it8712 shutdown : \n");
-+
-+      /*
-+       * disable all interrupts, disable the port
-+       */
-+      UART_PUT_IER(port, 0x0);
-+
-+      /* disable break condition and fifos */
-+//    UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
-+
-+      /*
-+       * Free the interrupt
-+       */
-+      free_irq(port->irq, info);
-+}
-+
-+static const char *it8712_type(struct uart_port *port)
-+{
-+      return port->type == PORT_IT8712 ? "IT8712" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void it8712_release_port(struct uart_port *port)
-+{
-+//        printk("it8712 release port : \n");
-+
-+      release_mem_region(port->mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int it8712_request_port(struct uart_port *port)
-+{
-+      return request_mem_region(port->mapbase, UART_PORT_SIZE,
-+                                  "serial_it8712") != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void it8712_config_port(struct uart_port *port, int flags)
-+{
-+
-+      if (flags & UART_CONFIG_TYPE) {
-+              if (it8712_request_port(port) == 0)
-+                      port->type = PORT_IT8712;
-+      }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+      int ret = 0;
-+
-+      if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
-+              ret = -EINVAL;
-+      if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+              ret = -EINVAL;
-+      if (ser->baud_base < 9600)
-+              ret = -EINVAL;
-+      return ret;
-+}
-+
-+static struct uart_ops it8712_pops = {
-+      tx_empty:       it8712_tx_empty,
-+      set_mctrl:      it8712_set_mctrl_null,
-+      get_mctrl:      it8712_get_mctrl,
-+      stop_tx:        it8712_stop_tx,
-+      start_tx:       it8712_start_tx,
-+      stop_rx:        it8712_stop_rx,
-+      enable_ms:      it8712_enable_ms,
-+      break_ctl:      it8712_break_ctl,
-+      startup:        it8712_startup,
-+      shutdown:       it8712_shutdown,
-+      change_speed:   it8712_change_speed,
-+      type:           it8712_type,
-+      release_port:   it8712_release_port,
-+      request_port:   it8712_request_port,
-+      config_port:    it8712_config_port,
-+      verify_port:    it8712_verify_port,
-+};
-+
-+#ifdef CONFIG_ARCH_SL2312
-+
-+static struct uart_port it8712_ports[UART_NR] = {
-+      {
-+              membase:        (void *)0,
-+              mapbase:        0,
-+              iotype:         SERIAL_IO_MEM,
-+              irq:            0,
-+              uartclk:        UART_CLK/2,
-+              fifosize:       16,
-+              ops:            &it8712_pops,
-+              flags:          ASYNC_BOOT_AUTOCONF,
-+      }
-+};
-+
-+#endif
-+
-+#ifdef CONFIG_SERIAL_IT8712_CONSOLE
-+#ifdef used_and_not_const_char_pointer
-+static int it8712_console_read(struct uart_port *port, char *s, u_int count)
-+{
-+      unsigned int status;
-+      int c;
-+#ifdef DEBUG
-+      printk("it8712_console_read() called\n");
-+#endif
-+
-+      c = 0;
-+      while (c < count) {
-+              status = UART_GET_LSR(port);
-+              if (UART_RX_DATA(status)) {
-+                      *s++ = UART_GET_CHAR(port);
-+                      c++;
-+              } else {
-+                      // nothing more to get, return
-+                      return c;
-+              }
-+      }
-+      // return the count
-+      return c;
-+}
-+#endif
-+static void it8712_console_write(struct console *co, const char *s, unsigned count)
-+{
-+#ifdef CONFIG_ARCH_SL2312
-+      struct uart_port *port = it8712_ports + co->index;
-+      unsigned int status, old_ies;
-+      int i;
-+
-+      /*
-+       *      First save the CR then disable the interrupts
-+       */
-+      old_ies = UART_GET_IER(port);
-+      UART_PUT_IER(port,0x0);
-+
-+      /*
-+       *      Now, do each character
-+       */
-+      for (i = 0; i < count; i++) {
-+              do {
-+                      status = UART_GET_LSR(port);
-+              } while (!UART_TX_READY(status));
-+              UART_PUT_CHAR(port, s[i]);
-+              if (s[i] == '\n') {
-+                      do {
-+                              status = UART_GET_LSR(port);
-+                      } while (!UART_TX_READY(status));
-+                      UART_PUT_CHAR(port, '\r');
-+              }
-+      }
-+
-+      /*
-+       *      Finally, wait for transmitter to become empty
-+       *      and restore the IES
-+       */
-+      do {
-+              status = UART_GET_LSR(port);
-+      } while (!(status&UART_LSR_THRE));
-+      UART_PUT_IER(port, old_ies);
-+#endif
-+}
-+
-+static kdev_t it8712_console_device(struct console *co)
-+{
-+      return MKDEV(SERIAL_IT8712_MAJOR, SERIAL_IT8712_MINOR + co->index);
-+}
-+
-+static int it8712_console_wait_key(struct console *co)
-+{
-+#ifdef CONFIG_ARCH_SL2312
-+      struct uart_port *port = (it8712_ports + co->index);
-+      unsigned int status;
-+
-+      do {
-+              status = UART_GET_LSR(port);
-+      } while (!UART_RX_DATA(status));
-+      return UART_GET_CHAR(port);
-+#else
-+      return 0;
-+#endif
-+}
-+
-+static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+      printk("it8712 console get options : \n");
-+
-+      u_int uart_mc, quot;
-+      uart_mc= UART_GET_MCR(port);
-+
-+      *parity = 'n';
-+      if (uart_mc & UART_LCR_PARITY) {
-+              if (uart_mc & UART_LCR_EVEN)
-+                      *parity = 'e';
-+              else
-+                      *parity = 'o';
-+      }
-+
-+      switch (uart_mc & UART_LCR_MSK){
-+
-+      case UART_LCR_WLEN5:
-+              *bits = 5;
-+              break;
-+      case UART_LCR_WLEN6:
-+              *bits = 6;
-+              break;
-+      case UART_LCR_WLEN7:
-+              *bits = 7;
-+              break;
-+      case UART_LCR_WLEN8:
-+              *bits = 8;
-+              break;
-+      }
-+      UART_PUT_MCR(port,UART_LCR_DLAB);
-+      quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
-+      UART_PUT_MCR(port,uart_mc);
-+      *baud = (port->uartclk / (16 *quot));
-+}
-+
-+static int __init it8712_console_setup(struct console *co, char *options)
-+{
-+      struct uart_port *port;
-+      int baud = 38400;
-+      int bits = 8;
-+      int parity = 'n';
-+      int flow= 'n';
-+      int base, irq;
-+      int i ;
-+
-+//    printk("it8712 console setup : \n");
-+
-+      LPCSetConfig(0, 0x02, 0x01);
-+        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
-+        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
-+      base = IT8712_IO_BASE;
-+      base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
-+      it8712_ports[0].mapbase = base;
-+      it8712_ports[0].membase = IO_ADDRESS(base);
-+      it8712_ports[0].irq = IRQ_SERIRQ0_OFFSET;
-+              irq = LPCGetConfig(LDN_SERIAL1, 0x70);
-+      it8712_ports[0].irq += irq;
-+
-+      printk("it8712 irq is %x %x \n", it8712_ports[0].irq, irq);
-+
-+      // setup LPC Host 'quiet mode'
-+      *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
-+      for(i=0;i<1000;i++) ;                                           // delay
-+      *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
-+
-+#ifdef CONFIG_ARCH_SL2312
-+      /*
-+       * Check whether an invalid uart number has been specified, and
-+       * if so, search for the first available port that does have
-+       * console support.
-+       */
-+      port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
-+#else
-+      return -ENODEV;
-+#endif
-+
-+      if (options)
-+              uart_parse_options(options, &baud, &parity, &bits, &flow);
-+      else
-+              it8712_console_get_options(port, &baud, &parity, &bits);
-+
-+      return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console it8712_console = {
-+      name:           SERIAL_IT8712_NAME,
-+      write:          it8712_console_write,
-+#ifdef used_and_not_const_char_pointer
-+      read:           it8712_console_read,
-+#endif
-+      device:         it8712_console_device,
-+//    wait_key:       it8712_console_wait_key,
-+      setup:          it8712_console_setup,
-+      flags:          (CON_PRINTBUFFER|CON_ENABLED),
-+      index:          -1,
-+};
-+
-+void __init it8712_console_init(void)
-+{
-+      register_console(&it8712_console);
-+}
-+
-+#define IT8712_CONSOLE        &it8712_console
-+#else
-+#define IT8712_CONSOLE        NULL
-+#endif
-+
-+static struct uart_driver it8712_reg = {
-+      owner:                  NULL,
-+      normal_major:           SERIAL_IT8712_MAJOR,
-+      normal_name:            SERIAL_IT8712_NAME,
-+      normal_driver:          &normal,
-+      callout_major:          CALLOUT_IT8712_MAJOR,
-+      callout_name:           CALLOUT_IT8712_NAME,
-+      callout_driver:         &callout,
-+      table:                  it8712_table,
-+      termios:                it8712_termios,
-+      termios_locked:         it8712_termios_locked,
-+      minor:                  SERIAL_IT8712_MINOR,
-+      nr:                     UART_NR,
-+#ifdef CONFIG_ARCH_SL2312
-+      port:                   it8712_ports,
-+#endif
-+      state:                  NULL,
-+      cons:                   IT8712_CONSOLE,
-+};
-+
-+static int __init it8712_init(void)
-+{
-+//    printk("serial_it8712: it871212_init \n");
-+
-+      return uart_register_driver(&it8712_reg);
-+}
-+
-+
-+__initcall(it8712_init);
---- /dev/null
-+++ b/drivers/serial/serial_sl2312.c
-@@ -0,0 +1,827 @@
-+/*
-+ *  linux/drivers/char/serial_uart00.c
-+ *
-+ *  Driver for UART00 serial ports
-+ *
-+ *  Based on drivers/char/serial_amba.c, by ARM Limited &
-+ *                                          Deep Blue Solutions Ltd.
-+ *  Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *  $Id: serial_sl2312.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
-+ *
-+ */
-+#include <linux/module.h>
-+
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <linux/serial_core.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+#include <asm/sizes.h>
-+#include <linux/spinlock.h>
-+#include <linux/irq.h>
-+
-+
-+#if defined(CONFIG_SERIAL_SL2312_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <asm/arch/sl2312.h>
-+#define UART_TYPE (volatile unsigned int*)
-+#include <asm/arch/uart.h>
-+#include <asm/arch/int_ctrl.h>
-+
-+// #define DEBUG           1
-+#define UART_NR               1
-+
-+
-+#define SERIAL_SL2312_NAME    "ttyS"
-+#define SERIAL_SL2312_MAJOR   204
-+#define SERIAL_SL2312_MINOR   40      /* Temporary - will change in future */
-+#define SERIAL_SL2312_NR      UART_NR
-+#define UART_PORT_SIZE 0x50
-+
-+#define SL2312_NO_PORTS         UART_NR
-+#define SL2312_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the SL2312 UARTs
-+ */
-+#define UART_GET_INT_STATUS(p)        (inl(UART_IIR((p)->membase)) & 0x0F)      // interrupt identification
-+#define UART_PUT_IER(p, c)      outl(c,UART_IER((p)->membase))    // interrupt enable
-+#define UART_GET_IER(p)         inl(UART_IER((p)->membase))
-+#define UART_PUT_CHAR(p, c)     outl(c,UART_THR((p)->membase))    // transmitter holding
-+#define UART_GET_CHAR(p)        inl(UART_RBR((p)->membase))       // receive buffer
-+#define UART_GET_LSR(p)         inl(UART_LSR((p)->membase))       // line status
-+#define UART_GET_MSR(p)         inl(UART_MSR((p)->membase))       // modem status
-+#define UART_GET_MCR(p)         inl(UART_MCR((p)->membase))       // modem control
-+#define UART_PUT_MCR(p, c)      outl(c,UART_MCR((p)->membase))
-+#define UART_GET_LCR(p)         inl(UART_LCR((p)->membase))       // mode control
-+#define UART_PUT_LCR(p, c)      outl(c,UART_LCR((p)->membase))
-+#define UART_GET_DIV_HI(p)    inl(UART_DIV_HI((p)->membase))
-+#define UART_PUT_DIV_HI(p, c) outl(c,UART_DIV_HI((p)->membase))
-+#define UART_GET_DIV_LO(p)    inl(UART_DIV_LO((p)->membase))
-+#define UART_PUT_DIV_LO(p, c) outl(c,UART_DIV_LO((p)->membase))
-+#define UART_PUT_MDR(p, c)      outl(c,UART_MDR((p)->membase))
-+#define UART_RX_DATA(s)               ((s) & UART_LSR_DR)
-+#define UART_TX_READY(s)      ((s) & UART_LSR_THRE)
-+
-+
-+static void sl2312_stop_tx(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+//        printk("sl2312 stop tx : \n");
-+        reg = UART_GET_IER(port);
-+        reg &= ~(UART_IER_TE);
-+      UART_PUT_IER(port, reg);
-+}
-+
-+static void sl2312_stop_rx(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+//        printk("sl2312 stop rx : \n");
-+        reg = UART_GET_IER(port);
-+        reg &= ~(UART_IER_DR);
-+      UART_PUT_IER(port, reg);
-+
-+}
-+
-+static void sl2312_enable_ms(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+//        printk("sl2312 enable ms : \n");
-+
-+        reg = UART_GET_IER(port);
-+        reg |= (UART_IER_MS);
-+      UART_PUT_IER(port, reg);
-+
-+}
-+
-+static void
-+sl2312_rx_chars(struct uart_port *port)
-+{
-+      struct tty_struct *tty = port->info->tty;
-+      unsigned int status, mask, ch, flg, ignored = 0;
-+
-+
-+ //       printk("sl2312_rx_chars : \n");
-+      status = UART_GET_LSR(port);
-+      while (UART_RX_DATA(status)) {
-+
-+              /*
-+               * We need to read rds before reading the
-+               * character from the fifo
-+               */
-+              ch = UART_GET_CHAR(port);
-+              port->icount.rx++;
-+
-+              //if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+              if (tty && !tty_buffer_request_room(tty, 1))
-+                      goto ignore_char;
-+
-+              flg = TTY_NORMAL;
-+
-+              /*
-+               * Note that the error handling code is
-+               * out of the main execution path
-+               */
-+
-+              if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
-+                      goto handle_error;
-+              if (uart_handle_sysrq_char(port, ch))
-+                      goto ignore_char;
-+
-+      error_return:
-+              //*tty->flip.flag_buf_ptr++ = flg;
-+              //*tty->flip.char_buf_ptr++ = ch;
-+              //tty->flip.count++;
-+              tty_insert_flip_char(tty, ch, flg);
-+      ignore_char:
-+              status = UART_GET_LSR(port);
-+      } // end of while
-+out:
-+      tty_flip_buffer_push(tty);
-+      return;
-+
-+handle_error:
-+      if (status & UART_LSR_BI) {
-+              status &= ~(UART_LSR_FE);
-+              port->icount.brk++;
-+
-+#ifdef SUPPORT_SYSRQ
-+              if (uart_handle_break(port))
-+                      goto ignore_char;
-+#endif
-+      } else if (status & UART_LSR_PE)
-+              port->icount.parity++;
-+      else if (status & UART_LSR_FE)
-+              port->icount.frame++;
-+
-+      if (status & UART_LSR_OE)
-+              port->icount.overrun++;
-+
-+      if (status & port->ignore_status_mask) {
-+              if (++ignored > 100)
-+                      goto out;
-+              goto ignore_char;
-+      }
-+
-+      mask = status & port->read_status_mask;
-+
-+      if (mask & UART_LSR_BI)
-+              flg = TTY_BREAK;
-+      else if (mask & UART_LSR_PE)
-+              flg = TTY_PARITY;
-+      else if (mask & UART_LSR_FE)
-+              flg = TTY_FRAME;
-+
-+      if (status & UART_LSR_OE) {
-+              /*
-+               * CHECK: does overrun affect the current character?
-+               * ASSUMPTION: it does not.
-+               */
-+              //*tty->flip.flag_buf_ptr++ = flg;
-+              //*tty->flip.char_buf_ptr++ = ch;
-+              //tty->flip.count++;
-+
-+              tty_insert_flip_char(tty, 0, TTY_BREAK);
-+
-+              // if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+              if (tty_buffer_request_room(tty, 1))
-+                      goto ignore_char;
-+              ch = 0;
-+              flg = TTY_OVERRUN;
-+      }
-+#ifdef SUPPORT_SYSRQ
-+      port->sysrq = 0;
-+#endif
-+      goto error_return;
-+}
-+
-+static void sl2312_tx_chars(struct uart_port *port)
-+{
-+      struct circ_buf *xmit = &port->info->xmit;
-+      int count;
-+
-+
-+      if (port->x_char) {
-+              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
-+              UART_PUT_CHAR(port, port->x_char);
-+              port->icount.tx++;
-+              port->x_char = 0;
-+
-+              return;
-+      }
-+      if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+              sl2312_stop_tx(port);
-+
-+              return;
-+      }
-+
-+      count = port->fifosize >> 1;
-+      do {
-+              while(!(UART_GET_LSR(port)&UART_LSR_THRE));
-+              UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-+              xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+              port->icount.tx++;
-+              if (uart_circ_empty(xmit))
-+                      break;
-+      } while (--count > 0);
-+
-+      if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+              uart_write_wakeup(port);
-+
-+      if (uart_circ_empty(xmit))
-+              sl2312_stop_tx(port);
-+
-+}
-+
-+static void sl2312_start_tx(struct uart_port *port)
-+{
-+        unsigned int reg;
-+
-+//        printk("sl2312 start tx : \n");
-+        reg = UART_GET_IER(port);
-+        reg |= (UART_IER_TE);
-+      UART_PUT_IER(port, reg);
-+
-+      sl2312_tx_chars(port);
-+}
-+
-+static void sl2312_modem_status(struct uart_port *port)
-+{
-+      unsigned int status;
-+
-+//        printk("it8712 modem status : \n");
-+
-+      status = UART_GET_MSR(port);
-+
-+      if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
-+                     UART_MSR_TERI | UART_MSR_DDCD)))
-+              return;
-+
-+        if (status & UART_MSR_DDCD)
-+                uart_handle_dcd_change(port, status & UART_MSR_DCD);
-+
-+        if (status & UART_MSR_DDSR)
-+                port->icount.dsr++;
-+
-+        if (status & UART_MSR_DCTS)
-+                uart_handle_cts_change(port, status & UART_MSR_CTS);
-+
-+      wake_up_interruptible(&port->info->delta_msr_wait);
-+
-+}
-+
-+static irqreturn_t sl2312_int(int irq, void *dev_id)
-+{
-+      struct uart_port *port = dev_id;
-+      unsigned int status, pass_counter = 0;
-+
-+      status = UART_GET_INT_STATUS(port);
-+      do {
-+              switch(status)
-+              {
-+                 case UART_IIR_DR:
-+                 case UART_IIR_RLS:
-+                      sl2312_rx_chars(port);
-+                 break;
-+                 case UART_IIR_TE:
-+                      sl2312_tx_chars(port);
-+                 break;
-+                 case UART_IIR_MODEM:
-+                      sl2312_modem_status(port);
-+                 break;
-+                 default:
-+                 break;
-+              }
-+              if (pass_counter++ > SL2312_ISR_PASS_LIMIT)
-+                      break;
-+
-+              status = UART_GET_INT_STATUS(port);
-+      } while (status);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static u_int sl2312_tx_empty(struct uart_port *port)
-+{
-+//        printk("sl2312 tx empty : \n");
-+
-+      return ((UART_GET_LSR(port) & UART_LSR_TE)? TIOCSER_TEMT : 0);
-+}
-+
-+static u_int sl2312_get_mctrl(struct uart_port *port)
-+{
-+      unsigned int result = 0;
-+      unsigned int status;
-+
-+//        printk("sl2312 get mctrl : \n");
-+
-+      status = UART_GET_MSR(port);
-+      if (status & UART_MSR_DCD)
-+              result |= TIOCM_CAR;
-+      if (status & UART_MSR_DSR)
-+              result |= TIOCM_DSR;
-+      if (status & UART_MSR_CTS)
-+              result |= TIOCM_CTS;
-+      if (status & UART_MSR_RI)
-+              result |= TIOCM_RI;
-+
-+      return result;
-+}
-+
-+static void sl2312_set_mctrl_null(struct uart_port *port, u_int mctrl)
-+{
-+}
-+
-+static void sl2312_break_ctl(struct uart_port *port, int break_state)
-+{
-+      unsigned int lcr;
-+
-+//        printk("sl2312 break ctl : \n");
-+
-+      lcr = UART_GET_LCR(port);
-+      if (break_state == -1)
-+              lcr |= UART_LCR_SETBREAK;
-+      else
-+              lcr &= ~UART_LCR_SETBREAK;
-+      UART_PUT_LCR(port, lcr);
-+}
-+
-+static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
-+{
-+      u_int quot;
-+
-+      /* Special case: B0 rate */
-+      if (!baud)
-+              baud = 9600;
-+
-+      quot = (port->uartclk / (16 * baud)-1)  ;
-+
-+      return quot;
-+}
-+
-+static void sl2312_set_termios(struct uart_port *port, struct ktermios *termios,
-+                               struct ktermios *old)
-+{
-+      unsigned int  uart_mc, old_ier, baud, quot;
-+      unsigned long flags;
-+
-+        termios->c_cflag |= CREAD;
-+#ifdef DEBUG
-+      printk("it8712_set_cflag(0x%x) called\n", cflag);
-+#endif
-+        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-+        quot = (port->uartclk / (16 * baud))  ;
-+        //uart_get_divisor(port, baud);
-+
-+      /* byte size and parity */
-+      switch (termios->c_cflag & CSIZE) {
-+      case CS5:
-+              uart_mc = UART_LCR_LEN5;
-+              break;
-+      case CS6:
-+              uart_mc = UART_LCR_LEN6;
-+              break;
-+      case CS7:
-+              uart_mc = UART_LCR_LEN7;
-+              break;
-+      default: // CS8
-+              uart_mc = UART_LCR_LEN8;
-+              break;
-+      }
-+
-+      if (termios->c_cflag & CSTOPB)
-+              uart_mc|= UART_LCR_STOP;
-+      if (termios->c_cflag & PARENB) {
-+              uart_mc |= UART_LCR_EVEN;
-+              if (!(termios->c_cflag & PARODD))
-+                      uart_mc |= UART_LCR_ODD;
-+      }
-+
-+    spin_lock_irqsave(&port->lock, flags);
-+        /*
-+         * Update the per-port timeout
-+         */
-+        uart_update_timeout(port, termios->c_cflag, baud);
-+      port->read_status_mask = UART_LSR_OE;
-+      if (termios->c_iflag & INPCK)
-+              port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+      if (termios->c_iflag & (BRKINT | PARMRK))
-+              port->read_status_mask |= UART_LSR_BI;
-+
-+      /*
-+       * Characters to ignore
-+       */
-+      port->ignore_status_mask = 0;
-+      if (termios->c_iflag & IGNPAR)
-+              port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+      if (termios->c_iflag & IGNBRK) {
-+              port->ignore_status_mask |= UART_LSR_BI;
-+              /*
-+               * If we're ignoring parity and break indicators,
-+               * ignore overruns to (for real raw support).
-+               */
-+              if (termios->c_iflag & IGNPAR)
-+                      port->ignore_status_mask |= UART_LSR_OE;
-+      }
-+
-+      //save_flags(flags); cli();
-+      old_ier = UART_GET_IER(port);
-+
-+        if(UART_ENABLE_MS(port, termios->c_cflag))
-+             old_ier |= UART_IER_MS;
-+
-+      /* Set baud rate */
-+      UART_PUT_LCR(port, UART_LCR_DLAB);
-+      UART_PUT_DIV_LO(port, (quot & 0xff));
-+      UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
-+
-+      UART_PUT_LCR(port, uart_mc);
-+      UART_PUT_IER(port, old_ier);
-+
-+      //restore_flags(flags);
-+      spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+
-+
-+static int sl2312_startup(struct uart_port *port)
-+{
-+      int retval;
-+      unsigned int regs;
-+
-+//        printk("sl2312 startup : \n");
-+
-+      /*
-+       * Use iobase to store a pointer to info. We need this to start a
-+       * transmission as the tranmittr interrupt is only generated on
-+       * the transition to the idle state
-+       */
-+
-+      /*
-+       * Allocate the IRQ
-+       */
-+      retval = request_irq(port->irq, sl2312_int, IRQF_DISABLED, "sl2312", port);
-+      if (retval)
-+              return retval;
-+
-+        /* setup interrupt controller  */
-+        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        regs &= ~(IRQ_UART_MASK);
-+        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
-+        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
-+        regs &= ~(IRQ_UART_MASK);
-+        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
-+        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_UART_MASK);
-+
-+      /*
-+       * Finally, enable interrupts. Use the TII interrupt to minimise
-+       * the number of interrupts generated. If higher performance is
-+       * needed, consider using the TI interrupt with a suitable FIFO
-+       * threshold
-+       */
-+      UART_PUT_IER(port, (UART_IER_DR|UART_IER_TE));
-+
-+      return 0;
-+}
-+
-+static void sl2312_shutdown(struct uart_port *port)
-+{
-+//        printk("sl2312 shutdown : \n");
-+
-+      /*
-+       * disable all interrupts, disable the port
-+       */
-+      UART_PUT_IER(port, 0x0);
-+
-+      /* disable break condition and fifos */
-+//    UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
-+
-+      /*
-+       * Free the interrupt
-+       */
-+      free_irq(port->irq, port);
-+}
-+
-+static const char *sl2312_type(struct uart_port *port)
-+{
-+      return port->type == PORT_SL2312 ? "SL2312" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void sl2312_release_port(struct uart_port *port)
-+{
-+//        printk("sl2312 release port : \n");
-+
-+      release_mem_region(port->mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int sl2312_request_port(struct uart_port *port)
-+{
-+      return request_mem_region(port->mapbase, UART_PORT_SIZE,
-+                                  "serial_sl2312") != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void sl2312_config_port(struct uart_port *port, int flags)
-+{
-+
-+      if (flags & UART_CONFIG_TYPE) {
-+              if (sl2312_request_port(port) == 0)
-+                      port->type = PORT_SL2312;
-+      }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int sl2312_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+      int ret = 0;
-+
-+      if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
-+              ret = -EINVAL;
-+      if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+              ret = -EINVAL;
-+      if (ser->baud_base < 9600)
-+              ret = -EINVAL;
-+      return ret;
-+}
-+
-+static struct uart_ops sl2312_pops = {
-+      .tx_empty               =sl2312_tx_empty,
-+      .set_mctrl              =sl2312_set_mctrl_null,
-+      .get_mctrl              =sl2312_get_mctrl,
-+      .stop_tx                =sl2312_stop_tx,
-+      .start_tx               =sl2312_start_tx,
-+      .stop_rx                =sl2312_stop_rx,
-+      .enable_ms              =sl2312_enable_ms,
-+      .break_ctl              =sl2312_break_ctl,
-+      .startup                =sl2312_startup,
-+      .shutdown               =sl2312_shutdown,
-+      .set_termios    =sl2312_set_termios,
-+      .type                   =sl2312_type,
-+      .release_port   =sl2312_release_port,
-+      .request_port   =sl2312_request_port,
-+      .config_port    =sl2312_config_port,
-+      .verify_port    =sl2312_verify_port,
-+};
-+
-+#ifdef CONFIG_ARCH_SL2312
-+
-+static struct uart_port sl2312_ports[UART_NR] = {
-+      {
-+              membase:        (void *)IO_ADDRESS(SL2312_UART_BASE),
-+              mapbase:        SL2312_UART_BASE,
-+              iotype:         SERIAL_IO_MEM,
-+              irq:            IRQ_UART,
-+              uartclk:        UART_CLK,
-+              fifosize:       16,
-+              ops:            &sl2312_pops,
-+              flags:          ASYNC_BOOT_AUTOCONF,
-+      }
-+};
-+
-+#endif
-+
-+#ifdef CONFIG_SERIAL_SL2312_CONSOLE
-+#ifdef used_and_not_const_char_pointer
-+static int sl2312_console_read(struct uart_port *port, char *s, u_int count)
-+{
-+      unsigned int status;
-+      int c;
-+#ifdef DEBUG
-+      printk("sl2312_console_read() called\n");
-+#endif
-+
-+      c = 0;
-+      while (c < count) {
-+              status = UART_GET_LSR(port);
-+              if (UART_RX_DATA(status)) {
-+                      *s++ = UART_GET_CHAR(port);
-+                      c++;
-+              } else {
-+                      // nothing more to get, return
-+                      return c;
-+              }
-+      }
-+      // return the count
-+      return c;
-+}
-+#endif
-+static void sl2312_console_write(struct console *co, const char *s, unsigned count)
-+{
-+#ifdef CONFIG_ARCH_SL2312
-+      struct uart_port *port = sl2312_ports + co->index;
-+      unsigned int status, old_ies;
-+      int i;
-+
-+      /*
-+       *      First save the CR then disable the interrupts
-+       */
-+      old_ies = UART_GET_IER(port);
-+      UART_PUT_IER(port,0x0);
-+
-+      /*
-+       *      Now, do each character
-+       */
-+      for (i = 0; i < count; i++) {
-+              do {
-+                      status = UART_GET_LSR(port);
-+              } while (!UART_TX_READY(status));
-+              UART_PUT_CHAR(port, s[i]);
-+              if (s[i] == '\n') {
-+                      do {
-+                              status = UART_GET_LSR(port);
-+                      } while (!UART_TX_READY(status));
-+                      UART_PUT_CHAR(port, '\r');
-+              }
-+      }
-+
-+      /*
-+       *      Finally, wait for transmitter to become empty
-+       *      and restore the IES
-+       */
-+      do {
-+              status = UART_GET_LSR(port);
-+      } while (!(status&UART_LSR_TE));
-+      UART_PUT_IER(port, old_ies);
-+#endif
-+}
-+
-+#if 0
-+static void sl2312_console_device(struct console *co,int *index)
-+{
-+
-+      struct uart_driver *p = co->data;
-+    *index = co->index;
-+    return p->tty_driver;
-+
-+}
-+#endif
-+
-+static void /*__init*/ sl2312_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+//    printk("sl2312 console get options : \n");
-+
-+      u_int uart_mc, quot;
-+      uart_mc= UART_GET_MCR(port);
-+
-+      *parity = 'n';
-+      if (uart_mc & UART_LCR_PE) {
-+              if (uart_mc & UART_LCR_EVEN)
-+                      *parity = 'e';
-+              else
-+                      *parity = 'o';
-+      }
-+
-+      switch (uart_mc & UART_LCR_MSK){
-+
-+      case UART_LCR_LEN5:
-+              *bits = 5;
-+              break;
-+      case UART_LCR_LEN6:
-+              *bits = 6;
-+              break;
-+      case UART_LCR_LEN7:
-+              *bits = 7;
-+              break;
-+      case UART_LCR_LEN8:
-+              *bits = 8;
-+              break;
-+      }
-+      UART_PUT_MCR(port,UART_LCR_DLAB);
-+      quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
-+      UART_PUT_MCR(port,uart_mc);
-+      *baud = port->uartclk / (16 *quot );
-+}
-+
-+static int __init sl2312_console_setup(struct console *co, char *options)
-+{
-+      struct uart_port *port;
-+      int baud = 19200;
-+      int bits = 8;
-+      int parity = 'n';
-+      int flow= 'n';
-+
-+      printk("sl2312 console setup : \n");
-+
-+#ifdef CONFIG_ARCH_SL2312
-+      /*
-+       * Check whether an invalid uart number has been specified, and
-+       * if so, search for the first available port that does have
-+       * console support.
-+       */
-+      port = uart_get_console(sl2312_ports,SL2312_NO_PORTS,co);
-+#else
-+      return -ENODEV;
-+#endif
-+
-+      if (options)
-+              uart_parse_options(options, &baud, &parity, &bits, &flow);
-+      else
-+              sl2312_console_get_options(port, &baud, &parity, &bits);
-+
-+      return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+extern struct uart_driver sl2312_reg;
-+static struct console sl2312_console = {
-+      .name      = SERIAL_SL2312_NAME,
-+      .write          = sl2312_console_write,
-+      .device         = uart_console_device,
-+//    .device         = sl2312_console_device,
-+      .setup          = sl2312_console_setup,
-+//    .flags          = (CON_PRINTBUFFER|CON_ENABLED),
-+      .flags          = CON_PRINTBUFFER,
-+      .index          = -1,
-+      .data       = &sl2312_reg,
-+};
-+
-+static int __init sl2312_console_init(void)
-+{
-+      register_console(&sl2312_console);
-+      return 0;
-+
-+}
-+
-+console_initcall(sl2312_console_init);
-+
-+#define SL2312_CONSOLE        &sl2312_console
-+#else
-+#define SL2312_CONSOLE        NULL
-+#endif
-+
-+// static
-+struct uart_driver sl2312_reg = {
-+      .owner         = NULL,
-+      .driver_name    = SERIAL_SL2312_NAME,
-+      .dev_name               = SERIAL_SL2312_NAME,
-+      .major          = SERIAL_SL2312_MAJOR,
-+      .minor                  = SERIAL_SL2312_MINOR,
-+      .nr                             = UART_NR,
-+      .cons                   = SL2312_CONSOLE,
-+};
-+
-+static int __init sl2312_init(void)
-+{
-+       int result;
-+      //printk("serial_it8712: it871212_init \n");
-+
-+        result = uart_register_driver(&sl2312_reg);
-+        if(result)
-+             return result;
-+      result = uart_add_one_port(&sl2312_reg, &sl2312_ports[0]);
-+
-+        return result;
-+}
-+
-+
-+__initcall(sl2312_init);
---- a/include/linux/serial_core.h
-+++ b/include/linux/serial_core.h
-@@ -147,6 +147,10 @@
- #define PORT_SB1250_DUART     77
-+/* Storlink Soc */
-+#define PORT_SL2312     72
-+#define PORT_IT8712     73
-+
- #ifdef __KERNEL__
- #include <linux/compiler.h>
---- a/drivers/char/Makefile
-+++ b/drivers/char/Makefile
-@@ -70,6 +70,16 @@
- obj-$(CONFIG_APPLICOM)                += applicom.o
- obj-$(CONFIG_SONYPI)          += sonypi.o
- obj-$(CONFIG_RTC)             += rtc.o
-+
-+###  for Storlink SoC ###
-+obj-$(CONFIG_SL2312_RTC) += sl2312_rtc.o
-+obj-$(CONFIG_IT8712_GPIO)   += it8712_gpio.o
-+obj-$(CONFIG_GEMINI_GPIO)   += gemini_gpio.o
-+obj-$(CONFIG_GEMINI_PWC) += gemini_pwr.o
-+obj-$(CONFIG_GEMINI_CIR)    += gemini_cir.o
-+obj-$(CONFIG_GEMINI_I2S)    += gemini_i2s.o
-+obj-$(CONFIG_SL2312_WATCHDOG) += sl2312_wd.o
-+
- obj-$(CONFIG_HPET)            += hpet.o
- obj-$(CONFIG_GEN_RTC)         += genrtc.o
- obj-$(CONFIG_EFI_RTC)         += efirtc.o
---- a/drivers/serial/Kconfig
-+++ b/drivers/serial/Kconfig
-@@ -280,6 +280,56 @@
- comment "Non-8250 serial port support"
-+config SERIAL_SL2312
-+      bool "SL2312  serial port (sl2312) support"
-+      depends on ARCH_SL2312
-+      select SERIAL_CORE
-+      select SERIAL_SL2312_CONSOLE
-+      help
-+         Say Y here if you want to use the hard logic uart on SWORD. This
-+         driver also supports soft logic implentations of this uart core.
-+
-+config SERIAL_SL2312_CONSOLE
-+      bool "Support for console on SL2312 serial port"
-+      depends on SERIAL_SL2312
-+      select SERIAL_CORE_CONSOLE
-+      help
-+        Say Y here if you want to support a serial console on an SWORD
-+        hard logic uart or uart00 IP core.
-+
-+        Even if you say Y here, the currently visible virtual console
-+        (/dev/tty0) will still be used as the system console by default, but
-+        you can alter that using a kernel command line option such as
-+        "console=ttyS0". (Try "man bootparam" or see the documentation of
-+        your boot loader (lilo or loadlin) about how to pass options to the
-+        kernel at boot time.)
-+
-+
-+config SERIAL_IT8712
-+      bool "Sl2312 serial port(IT8712) support"
-+      depends on ARM && ARCH_SL2312 && SL2312_LPC
-+      select SERIAL_CORE
-+      select SERIAL_IT8712_CONSOLE
-+      help
-+        Say Y here if you want to use the hard logic uart on Excalibur. This
-+        driver also supports soft logic implentations of this uart core.
-+
-+config SERIAL_IT8712_CONSOLE
-+      bool "Support for console on Sword serial port(IT8712)"
-+      depends on SERIAL_IT8712
-+      select SERIAL_CORE_CONSOLE
-+      help
-+        Say Y here if you want to support a serial console on an Excalibur
-+        hard logic uart or uart00 IP core.
-+
-+        Even if you say Y here, the currently visible virtual console
-+        (/dev/tty0) will still be used as the system console by default, but
-+        you can alter that using a kernel command line option such as
-+        "console=ttySI0". (Try "man bootparam" or see the documentation of
-+        your boot loader (lilo or loadlin) about how to pass options to the
-+        kernel at boot time.)
-+
-+
- config SERIAL_AMBA_PL010
-       tristate "ARM AMBA PL010 serial port support"
-       depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
---- a/drivers/serial/Makefile
-+++ b/drivers/serial/Makefile
-@@ -62,5 +62,7 @@
- obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
- obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
- obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
-+obj-$(CONFIG_SERIAL_IT8712) += it8712.o
-+obj-$(CONFIG_SERIAL_SL2312) += serial_sl2312.o
- obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
- obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
diff --git a/target/linux/storm/patches/1022-watchdog.patch b/target/linux/storm/patches/1022-watchdog.patch
deleted file mode 100644 (file)
index 3055a94..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
---- a/arch/arm/mach-sl2312/sl3516_device.c
-+++ b/arch/arm/mach-sl2312/sl3516_device.c
-@@ -76,9 +76,30 @@
-       .resource       = sl3516_sata0_resources,
- };
-+static struct resource sl351x_wdt_resources[] = {
-+      [0] = {
-+              .start  = SL2312_WAQTCHDOG_BASE + 0x00,
-+              .end    = SL2312_WAQTCHDOG_BASE + 0x1C,
-+              .flags  = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start  = IRQ_WATCHDOG,
-+              .end    = IRQ_WATCHDOG,
-+              .flags  = IORESOURCE_IRQ,
-+      },
-+};
-+
-+static struct platform_device sl351x_wdt = {
-+      .name           = "sl351x-wdt",
-+      .id             = -1,
-+      .resource       = sl351x_wdt_resources,
-+      .num_resources  = ARRAY_SIZE(sl351x_wdt_resources),
-+};
-+
- static struct platform_device *sata_devices[] __initdata = {
-       &sata_device,
-       &sata0_device,
-+      &sl351x_wdt,
- };
- static int __init sl3516_init(void)
---- a/drivers/char/watchdog/Kconfig
-+++ b/drivers/char/watchdog/Kconfig
-@@ -171,6 +171,17 @@
-         To compile this driver as a module, choose M here: the
-         module will be called ep93xx_wdt.
-+config WATCHDOG_SL351X
-+      tristate "SL351x Watchdog"
-+      depends on WATCHDOG && ARCH_SL2312
-+      help
-+        This driver adds watchdog support for the integrated watchdog in the
-+        SL351x processors (Farraday core). If you have one of these processors
-+        and wish to have watchdog support enabled, say Y, otherwise say N.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called sl351x_wdt.
-+
- config OMAP_WATCHDOG
-       tristate "OMAP Watchdog"
-       depends on ARCH_OMAP16XX || ARCH_OMAP24XX
---- a/drivers/char/watchdog/Makefile
-+++ b/drivers/char/watchdog/Makefile
-@@ -36,6 +36,7 @@
- obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
- obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
- obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
-+obj-$(CONFIG_WATCHDOG_SL351X) += sl351x_wdt.o
- obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
- obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
- obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
---- /dev/null
-+++ b/drivers/char/watchdog/sl351x_wdt.c
-@@ -0,0 +1,332 @@
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/platform_device.h>
-+#include <asm/uaccess.h>
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/arch/watchdog.h>
-+#include <asm/io.h>
-+#include <linux/interrupt.h>
-+
-+#define WATCHDOG_TEST 1
-+#define PFX "sl351x-wdt: "
-+
-+#define _WATCHDOG_COUNTER  0x00
-+#define _WATCHDOG_LOAD     0x04
-+#define _WATCHDOG_RESTART  0x08
-+#define _WATCHDOG_CR       0x0C
-+#define _WATCHDOG_STATUS   0x10
-+#define _WATCHDOG_CLEAR    0x14
-+#define _WATCHDOG_INTRLEN  0x18
-+
-+static struct resource  *wdt_mem;
-+static struct resource  *wdt_irq;
-+static void __iomem     *wdt_base;
-+static int            wdt_margin = WATCHDOG_TIMEOUT_MARGIN;   /* in range of 0 .. 60s */
-+
-+static int open_state = WATCHDOG_DRIVER_CLOSE;
-+static int wd_expire = 0;
-+
-+static void watchdog_enable(void)
-+{
-+      unsigned long wdcr;
-+
-+      wdcr = readl(wdt_base + _WATCHDOG_CR);
-+      wdcr |= (WATCHDOG_WDENABLE_MSK|WATCHDOG_WDRST_MSK);
-+#ifdef WATCHDOG_TEST
-+      wdcr |= WATCHDOG_WDINTR_MSK;
-+//    wdcr &= ~WATCHDOG_WDRST_MSK;
-+#endif
-+      wdcr &= ~WATCHDOG_WDCLOCK_MSK;
-+      writel(wdcr, wdt_base + _WATCHDOG_CR);
-+}
-+
-+static void watchdog_set_timeout(unsigned long timeout)
-+{
-+      timeout = WATCHDOG_TIMEOUT_SCALE * timeout;
-+      writel(timeout, wdt_base + _WATCHDOG_LOAD);
-+      writel(WATCHDOG_RESTART_VALUE, wdt_base + _WATCHDOG_RESTART);
-+}
-+
-+static void watchdog_keepalive(void)
-+{
-+      writel(WATCHDOG_RESTART_VALUE, wdt_base + _WATCHDOG_RESTART);
-+}
-+
-+static void watchdog_disable(void)
-+{
-+      unsigned long wdcr;
-+
-+      wdcr = readl(wdt_base + _WATCHDOG_CR);
-+      wdcr &= ~WATCHDOG_WDENABLE_MSK;
-+      writel(wdcr, wdt_base + _WATCHDOG_CR);
-+}
-+
-+
-+#ifdef WATCHDOG_TEST
-+static irqreturn_t watchdog_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+      unsigned int clear;
-+
-+      writel(WATCHDOG_CLEAR_STATUS, wdt_base + _WATCHDOG_CLEAR);
-+      printk(KERN_INFO PFX "Watchdog timeout, resetting system...\n");
-+
-+      clear = __raw_readl(IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x0C);
-+      clear &= 0x01;
-+      __raw_writel(clear,IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x08);
-+      wd_expire = 1;
-+      return IRQ_HANDLED;
-+}
-+
-+#endif
-+
-+#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE
-+static struct watchdog_info sl351x_wdt_ident = {
-+      .options          =     OPTIONS,
-+      .firmware_version =     0,
-+      .identity         =     "sl351x Watchdog",
-+};
-+
-+struct file_operations watchdog_fops = {
-+      .write          = watchdog_write,
-+      .read           = watchdog_read,
-+      .open           = watchdog_open,
-+      .release        = watchdog_release,
-+      .ioctl          = watchdog_ioctl,
-+};
-+
-+static int watchdog_open(struct inode *inode, struct file *filp)
-+{
-+      if (open_state == WATCHDOG_DRIVER_OPEN)
-+              return -EBUSY;
-+
-+      wd_expire = 0;
-+
-+      watchdog_disable();
-+      watchdog_set_timeout(wdt_margin);
-+      watchdog_enable();
-+
-+      printk(KERN_INFO PFX "watchog timer enabled, margin: %ds.\n", wdt_margin);
-+      open_state = WATCHDOG_DRIVER_OPEN;
-+
-+      return nonseekable_open(inode, filp);
-+}
-+
-+static int watchdog_release(struct inode *inode, struct file *filp)
-+{
-+      watchdog_disable();
-+
-+      open_state = WATCHDOG_DRIVER_CLOSE;
-+      wd_expire = 0;
-+      printk(KERN_INFO PFX "watchog timer disabled, margin: %ds.\n", wdt_margin);
-+
-+      return 0;
-+}
-+
-+static ssize_t watchdog_read(struct file *filp, char *buf, size_t count, loff_t *off)
-+{
-+      int i;
-+      unsigned long val;
-+
-+
-+      for(i=0;i< count;i++)
-+      {
-+              if ((i%4)==0)
-+                      val = *((unsigned long *)WATCHDOG_COUNTER);
-+              buf[i] = (val & 0xFF);
-+              val >>= 8;
-+      }
-+      return count;
-+}
-+
-+static ssize_t watchdog_write(struct file *filp, const char *buf, size_t len, loff_t *off)
-+{
-+      /*  Refresh the timer. */
-+      if (len) {
-+              watchdog_keepalive();
-+      }
-+      return len;
-+
-+}
-+
-+static int watchdog_ioctl(struct inode *inode, struct file *filp,
-+                        unsigned int cmd, unsigned long arg)
-+{
-+      void __user *argp = (void __user *)arg;
-+      int margin;
-+
-+      switch(cmd)
-+      {
-+      case WDIOC_GETSUPPORT:
-+              return copy_to_user(argp, &sl351x_wdt_ident,
-+                                  sizeof(sl351x_wdt_ident)) ? -EFAULT : 0;
-+
-+      case WDIOC_GETSTATUS:
-+      case WDIOC_GETBOOTSTATUS:
-+              return put_user(0, (int __user*)argp);
-+
-+      case WDIOC_KEEPALIVE:
-+              watchdog_keepalive();
-+              return 0;
-+
-+      case WDIOC_SETTIMEOUT:
-+              if (get_user(margin, (int __user*)argp))
-+                      return -EFAULT;
-+
-+              /* Arbitrary, can't find the card's limits */
-+              if ((margin < 0) || (margin > 60))
-+                      return -EINVAL;
-+
-+              // watchdog_disable();
-+              wdt_margin = margin;
-+              watchdog_set_timeout(margin);
-+              watchdog_keepalive();
-+              // watchdog_enable();
-+
-+              /* Fall through */
-+
-+      case WDIOC_GETTIMEOUT:
-+              return put_user(wdt_margin, (int *)arg);
-+
-+      default:
-+              return -ENOIOCTLCMD;
-+      }
-+}
-+
-+static struct miscdevice wd_dev= {
-+      WATCHDOG_MINOR,
-+      "watchdog",
-+      &watchdog_fops
-+};
-+
-+static char banner[] __initdata = KERN_INFO "SL351x Watchdog Timer, (c) 2007 WILIBOX\n";
-+
-+static int sl351x_wdt_probe(struct platform_device *pdev)
-+{
-+      struct resource *res;
-+      int ret, size;
-+      unsigned long wdcr;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (res == NULL) {
-+              printk(KERN_INFO PFX "failed to get memory region resouce\n");
-+              return -ENOMEM;
-+      }
-+
-+      size = (res->end-res->start)+1;
-+
-+      wdt_mem = request_mem_region(res->start, size, pdev->name);
-+      if (wdt_mem == NULL) {
-+              printk(KERN_INFO PFX "failed to get memory region\n");
-+              return -ENOENT;
-+      }
-+
-+      wdt_base = ioremap(res->start, size);
-+      if (wdt_base == NULL) {
-+              printk(KERN_INFO PFX "failed to ioremap() region\n");
-+              return -EINVAL;
-+      }
-+
-+      res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+      if (res == NULL) {
-+               printk(KERN_INFO PFX "failed to get irq resource\n");
-+               return -ENOENT;
-+      }
-+
-+      wdt_irq = res;
-+
-+      ret = request_irq(res->start, watchdog_irq, 0, pdev->name, pdev);
-+      if (ret != 0) {
-+              printk(KERN_INFO PFX "failed to install irq (%d)\n", ret);
-+              return ret;
-+      }
-+
-+      wdcr = readl(wdt_base + _WATCHDOG_CR);
-+      if (wdcr & WATCHDOG_WDENABLE_MSK) {
-+              printk(KERN_INFO PFX "Found watchdog in enabled state, reseting ...\n");
-+              wdcr &= ~WATCHDOG_WDENABLE_MSK;
-+              writel(wdcr, wdt_base + _WATCHDOG_CR);
-+      }
-+
-+      ret = misc_register(&wd_dev);
-+
-+      return ret;
-+}
-+
-+static int sl351x_wdt_remove(struct platform_device *pdev)
-+{
-+      if (wdt_base != NULL) {
-+              iounmap(wdt_base);
-+              wdt_base = NULL;
-+      }
-+
-+      if (wdt_irq != NULL) {
-+              free_irq(wdt_irq->start, pdev);
-+              release_resource(wdt_irq);
-+              wdt_irq = NULL;
-+      }
-+
-+      if (wdt_mem != NULL) {
-+              release_resource(wdt_mem);
-+              wdt_mem = NULL;
-+      }
-+
-+      misc_deregister(&wd_dev);
-+
-+      return 0;
-+}
-+
-+static void sl351x_wdt_shutdown(struct platform_device *dev)
-+{
-+      watchdog_disable();
-+}
-+
-+#ifdef CONFIG_PM
-+static int sl351x_wdt_suspend(struct platform_device *dev, pm_message_t state)
-+{
-+      watchdog_disable();
-+}
-+
-+static int sl351x_wdt_resume(struct platform_device *dev)
-+{
-+      watchdog_set_timeout(wdt_margin);
-+      watchdog_enable();
-+}
-+
-+#else
-+#define sl351x_wdt_suspend    NULL
-+#define sl351x_wdt_resume     NULL
-+#endif
-+
-+static struct platform_driver sl351x_wdt_driver = {
-+      .probe          = sl351x_wdt_probe,
-+      .remove         = sl351x_wdt_remove,
-+      .shutdown       = sl351x_wdt_shutdown,
-+      .suspend        = sl351x_wdt_suspend,
-+      .resume         = sl351x_wdt_resume,
-+      .driver         = {
-+              .owner  = THIS_MODULE,
-+              .name   = "sl351x-wdt",
-+      },
-+};
-+
-+static int __init watchdog_init(void)
-+{
-+      printk(banner);
-+      return platform_driver_register(&sl351x_wdt_driver);
-+}
-+
-+static void __exit watchdog_exit(void)
-+{
-+      platform_driver_unregister(&sl351x_wdt_driver);
-+}
-+
-+module_init(watchdog_init);
-+module_exit(watchdog_exit);