[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/boot/common/src/uboot/drivers/gmac/Makefile b/boot/common/src/uboot/drivers/gmac/Makefile
new file mode 100644
index 0000000..7983907
--- /dev/null
+++ b/boot/common/src/uboot/drivers/gmac/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB 	:= $(obj)libgmac.o
+
+COBJS-y	+= gmac.o
+COBJS-y	+= net.o
+
+
+
+
+COBJS	:= $(COBJS-y)
+SRCS 	:= $(COBJS:.o=.c)
+OBJS 	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+########################################################################
diff --git a/boot/common/src/uboot/drivers/gmac/gmac.c b/boot/common/src/uboot/drivers/gmac/gmac.c
new file mode 100644
index 0000000..af7488e
--- /dev/null
+++ b/boot/common/src/uboot/drivers/gmac/gmac.c
@@ -0,0 +1,766 @@
+/** -----------------------------------------------------------------------------------------------------------------@n
+ * °æÈ¨ËùÓÐ(C)2000-2011, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾ 
+ * 
+ * ÎÄ ¼þ Ãû: drv_gmac.c  @defgroup DRV_GMAC
+ * 
+ * ×÷    Õß: ÕÔÀû±ó10113809
+ * 
+ * Ä£¿é¸ÅÊö:
+ *     - <´Ë´¦ÌîÄ£¿é¸ÅÊö, ÌîÍêºó¿ÕÒ»ÐÐ>
+ * 
+ * Ä£¿éÏêÊö:
+ *     - <´Ë´¦ÌîÄ£¿éÏêÊö, ÌîÍêºó¿ÕÒ»ÐÐ>
+ * 
+ * ÓÃÀý1:
+ * @code
+ * 
+ * 
+ * @endcode
+ * 
+ * °æ    ±¾: v0.0
+ * 
+ * ------------------------------------------------------------------------------------------------------------------ 
+ * 
+ *     ÐÞ¸ÄÈÕÆÚ ÐÞ¸ÄÈË            ÐÞ¸ÄÄÚÈÝ
+ * @li 20120114 ÕÔÀû±ó10113809       ´´½¨
+ * @li 20120907 ÕÔÀû±ó10113809    Ð޸ĴúÂëÖеÄbug
+ * @li 20120908 ÕÔÀû±ó10113809    Ð޸ĴúÂë¹æ·¶£¬µ÷Õû´úÂë½á¹¹
+ * @li 20120910 ÕÔÀû±ó10113809    µ÷Õû´úÂë½á¹¹£¬Ôö¼Ó×¢ÊÍ£¬Ìí¼Ó¹¦ÄÜ
+ * @li 20120925 ÕÔÀû±ó10113809    µ÷Õû´úÂë½á¹¹£¬Ôö¼Ó×¢ÊÍ£¬Ìí¼Ó¹¦ÄÜ£¬ÓÃalignedÊôÐÔ½øÐÐ×Ö½Ú¶ÔÆë
+ *      20150302 ÐìÏÄÃô10180991         Ϊ7520sÐÞ¸Ä
+ *
+ *     
+ * @n@{ --------------------------------------------------------------------------------------------------------------- */
+   
+#include <linux/string.h>                         /* ʹÓÃÀïÃæµÄmemcpyº¯Êý */
+#include <asm/arch/gmac.h>						 /* ʹÓÃÀïÃæµÄÊý¾ÝÀàÐͶ¨Òå BYTE WORD32Ö®ÀàµÄ */
+#include <common.h>
+
+//#define PHY_CLOCK			  		5	
+#define GMAC_RX_DES_ADDR    CONFIG_GMAC_DMA_BUF_ADDR
+#define GMAC_TX_DES_ADDR    (CONFIG_GMAC_DMA_BUF_ADDR+GMAC_RX_BUF_NUM*128)
+
+#define GMAC_RX_BUF_ADDR    (CONFIG_GMAC_DMA_BUF_ADDR+0x800)
+#define GMAC_TX_BUF_ADDR    (CONFIG_GMAC_DMA_BUF_ADDR+0x1800)
+//#define GMAC_TX_BUF_ADDR    (CONFIG_GMAC_DMA_BUF_ADDR+0x8000)
+
+volatile  unsigned int g_dwRxBdOffset = 0;
+volatile  unsigned int g_dwTxBdOffset = 0;
+
+/*---------------------------------------------------------------------------------------------------------------------
+ * ÒÔÏÂͨ¹ý±àÒëÆ÷alignedÊôÐÔÉùÃ÷×Ö½Ú¶ÔÆë£¬´¦Àí·½Ê½±È½Ï·½±ã£¬´¦Àí´úÂë²»Ò׳ö´í£¬Ê¡È¥Á˲»ÉÙÈßÓàµÄ¼ÆË㣬µ«ÐèÒª±àÒëÆ÷Ö§
+ * ³ÖcÀ©Õ¹ÊôÐÔ¡£ÃèÊö·û´óСΪ×Ö½Ú¶ÔÆëµÄÕûÊý±¶£¬±£Ö¤ÁËÊ×µØÖ·×Ö½Ú¶ÔÆëµÄÇé¿öÏÂÿ¸öÃèÊö·ûµØÖ·¶¼ÊÇ×Ö½Ú¶ÔÆëµÄ¡£Îª±£Ö¤Ã¿¸ö
+ * »º³åÇøµØÖ·¶¼ÊÇ×Ö½Ú¶ÔÆëµÄÐèÒª»º³åÇø´óСΪ×Ö½Ú¶ÔÆëµÄÕûÊý±¶¡£
+ *
+ * ÔÚʵ¼ÊʹÓÃÖпª±ÙÊÕ·¢»º³åÇøÒ²¿ÉÒÔÔÚϵͳ¹æ»®ÄÚ´æÊ¹ÓõÄʱºò½øÐпª±Ù£¬Ö»ÒªÄܱ£Ö¤Ê×µØÖ··ûºÏmacÇý¶¯µÄµØÖ·¶ÔÆëÒªÇó¼´¿É£¬
+ * È»ºóͨ¹ý²ÎÊý´«µÝµ½ÃèÊö·û³õʼ»¯º¯ÊýÖС£Êµ¼ÊÉÏ»º³åÇøÒ²¿ÉÒÔ²»¶ÔÆëÖ±½ÓʹÓ㬲»¹ýÐèÒª×öÒ»Ð©ÌØÊâ´¦Àí£¬ÌØ±ðÊǽÓÊÕ¶Ë¡£
+ *
+ *--------------------------------------------------------------------------------------------------------------------*/
+//T_GMAC_RxDescr  g_tRxDes[GMAC_RX_BUF_NUM]__attribute__((aligned(8)));
+//T_GMAC_TxDescr  g_tTxDes[GMAC_TX_BUF_NUM]__attribute__((aligned(8)));
+
+
+T_GMAC_RxDescr  *g_tRxDes = (T_GMAC_RxDescr *) GMAC_RX_DES_ADDR;
+T_GMAC_TxDescr  *g_tTxDes = (T_GMAC_TxDescr *) GMAC_TX_DES_ADDR;
+
+T_GMAC_DmaRegs  *g_ptGmacDmaRegs  = (T_GMAC_DmaRegs *) GMAC_DMA_ADDR_BASE;
+T_GMAC_GmacRegs *g_ptGmacGmacRegs = (T_GMAC_GmacRegs *) GMAC_MAC_ADDR_BASE;
+
+
+/*data in DDR*/
+//volatile BYTE  g_RxBuf[GMAC_RX_BUF_SIZE * GMAC_RX_BUF_NUM]__attribute__((aligned(8)));
+//volatile BYTE  g_TxBuf[GMAC_TX_BUF_SIZE * GMAC_TX_BUF_NUM]__attribute__((aligned(8)));
+
+/*data in IRAM*/
+volatile BYTE *g_RxBuf = (volatile BYTE *) GMAC_RX_BUF_ADDR;
+volatile BYTE *g_TxBuf = (volatile BYTE *) GMAC_TX_BUF_ADDR;
+
+WORD16	phyid = 0;
+WORD32	autotimeout = 100000;
+
+static WORD16 mii_read(WORD32 tPhyAddr, WORD32 tPhyReg);
+
+static void zx_gmac_initBd(void)
+{
+    unsigned int dwIdx;
+    T_GMAC_TxDescr *ptTxTmp;
+    T_GMAC_RxDescr *ptRxTmp;
+
+    ptTxTmp = g_tTxDes;
+    g_dwTxBdOffset = 0;
+    for (dwIdx = 0; dwIdx < GMAC_TX_DESC_NUM; dwIdx++) 
+    { 
+       /* Initialize Tx descriptor ring */
+		//ptTxTmp->dwDescr0  =0;
+      	ptTxTmp->dwDescr0   = GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXINT | GMAC_DESC_TXSTS_TXCHAIN);
+		//ptTxTmp->dwDescr0   = GMAC_ENDIAN32_SWAP( GMAC_DESC_TXSTS_TXCHAIN);
+		//ptTxTmp->dwDescr0  |= ~ GMAC_ENDIAN32_SWAP( GMAC_DESC_TXSTS_OWNBYDMA);
+       ptTxTmp->dwDescr1   = GMAC_ENDIAN32_SWAP(GMAC_TX_BUF_SIZE & GMAC_DESC_TXCTRL_SIZE1MASK); 
+       ptTxTmp->dwBuf1Addr = GMAC_ENDIAN32_SWAP((WORD32)&g_TxBuf[dwIdx * GMAC_TX_BUF_SIZE]);
+       ptTxTmp->ptNext     = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTxTmp+1))); 
+	   ptTxTmp++;
+    }
+    ptTxTmp--;
+    ptTxTmp->ptNext    = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(g_tTxDes)));
+    ptTxTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXRINGEND); 
+
+    ptRxTmp = g_tRxDes;
+    g_dwRxBdOffset = 0;
+    for(dwIdx = 0; dwIdx < GMAC_RX_DESC_NUM; dwIdx++)
+    {
+		//±êÃ÷½ÓÊÕÃèÊö·û±»dmaÕ¼ÓÃ
+	 	ptRxTmp->dwDescr0   = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+        ptRxTmp->dwDescr1   = GMAC_ENDIAN32_SWAP((GMAC_RX_BUF_SIZE & GMAC_DESC_RXCTRL_SIZE1MASK) | GMAC_DESC_RXCTRL_RXCHAIN);
+        ptRxTmp->dwBuf1Addr = GMAC_ENDIAN32_SWAP((WORD32)&g_RxBuf[dwIdx * GMAC_RX_BUF_SIZE]);
+        ptRxTmp->ptNext     = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptRxTmp+1)));      
+        ptRxTmp++;
+    }
+	
+    ptRxTmp--;
+    ptRxTmp->ptNext    = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(g_tRxDes)));
+    ptRxTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_RXCTRL_RXRINGEND);
+}
+
+
+int zx_gmac_init(void)
+{
+
+	g_ptGmacDmaRegs->dwBusMode = GMAC_BUSMODE_SRST; // software reset all gmac subsystem inter registers and logic
+
+	zx_gmac_initBd();
+	
+	/* ËÙÂÊģʽҪÓëPHYµÄËÙÂÊÆ¥Åä */
+	/*PS: Port Select Selects between GMII and MII:*/
+	g_ptGmacGmacRegs->dwMacConfig = (GMAC_POART_MODE);
+
+	/* µÈ´ý¸´Î»Íê³É*/
+	/*SWR: Software Reset*/
+	while((g_ptGmacDmaRegs->dwBusMode & GMAC_BUSMODE_SRST_MASK) == GMAC_BUSMODE_SRST)
+	{
+	/* cpuËٶȺܿ죬ÉÏÃæ½øÐÐËÙÂÊÆ¥Åäʱ¼Ä´æÆ÷Ä£¿é»¹Ã»Óи´Î»³É¹¦£¬ÕâÀïÖØÐÂÆ¥Åä */
+		g_ptGmacGmacRegs->dwMacConfig = (GMAC_POART_MODE);
+	}
+	
+	//É趨PBL: Programmable Burst Length
+	g_ptGmacDmaRegs->dwBusMode &= (~GMAC_BUSMODE_PBL_MASK);
+	g_ptGmacDmaRegs->dwBusMode |= ( GMAC_BUSMODE_PBL_8& GMAC_BUSMODE_PBL_MASK);
+
+	//g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)&g_RxBd[0] + 0x7) & 0xFFFFFFF8;
+	//g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)&g_TxBd[0] + 0x7) & 0xFFFFFFF8;
+	//g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)g_ptRxDes);
+	//g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)g_ptTxDes);
+	g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)g_tRxDes);
+	g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)g_tTxDes);
+
+	g_ptGmacDmaRegs->dwStatus    = 0x0001ffff; //write 1 to clear init
+	g_ptGmacDmaRegs->dwIntEnable = (GMAC_INT_TIE|GMAC_INT_RIE|GMAC_INT_NIE);  //interrupt is disable
+	 //g_ptGmacDmaRegs->dwIntEnable = (GMAC_INT_ERE|GMAC_INT_ETE|GMAC_INT_TIE|GMAC_INT_RIE|GMAC_INT_NIE);
+	//g_ptGmacDmaRegs->dwIntEnable = 0x1e7ff;
+	//g_ptGmacDmaRegs->dwIntEnable = 0x180f5; // linux gmac
+
+
+	while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+
+	/* ¸´Î»ÉèÖÃport selectºóÆäËû±ÈÌØÎ»¶¼Îª0 Òò´ËûÓнøÐÐÇå0²Ù×÷ */
+	g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_100M | GMAC_MAC_NORMAL | GMAC_MAC_DUPLEX_MODE );
+	//g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_10M | GMAC_MAC_NORMAL | GMAC_MAC_DUPLEX_MODE );
+	
+	//g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_100M | GMAC_MAC_LOOP | GMAC_MAC_DUPLEX_MODE );
+	g_ptGmacGmacRegs->dwMacFrameFilter &= ~(GMAC_MAC_RCVALL_EN);
+	g_ptGmacGmacRegs->dwMacFrameFilter |= (GMAC_MAC_RCVALL_EN);
+	//g_ptGmacGmacRegs->dwMacFrameFilter |= (1 << 0);
+
+	//TSF: Transmit Store and Forward
+	//g_ptGmacDmaRegs->dwOpMode |= (dwMode & (GMAC_DMA_TSF | GMAC_DMA_RSF));
+
+	g_ptGmacDmaRegs->dwOpMode |= (1 << 1);  //enable dma 
+	g_ptGmacDmaRegs->dwOpMode |= (1 << 13);
+	
+	g_ptGmacDmaRegs->dwOpMode |= (1 << 3); //useful when rsf
+	g_ptGmacDmaRegs->dwOpMode |= (1 << 4);
+	g_ptGmacDmaRegs->dwOpMode |= (1 << 14);//useful when tsf
+//	g_ptGmacDmaRegs->dwOpMode = 0x601a;
+
+	g_ptGmacGmacRegs->dwMacConfig |= (1 << 3);   //enable mac rt tx
+	g_ptGmacGmacRegs->dwMacConfig |= (1 << 2);
+	printf("Mac Config = %x\n",g_ptGmacGmacRegs->dwMacConfig);
+	//g_ptGmacGmacRegs->dwMacConfig = 0x0040c80c;
+	return 0;
+}
+
+void zx_gmac_stop(void)
+{
+	g_ptGmacDmaRegs->dwOpMode  &= ~ ((1 << 1)|(1 << 13));  //disable dma 
+	g_ptGmacGmacRegs->dwMacConfig &= ~ ((1 << 2)|(1 << 3)); //disable mac rxtx
+	g_ptGmacDmaRegs->dwIntEnable = 0x00;  //disable dma interrupt
+
+	g_ptGmacDmaRegs->dwOpMode |= 1 << 20;  //clear tx fifo
+	while(g_ptGmacDmaRegs->dwOpMode & (1 << 20));  //wait for clear tx fifo  
+}
+
+int zx_gmac_send(BYTE  *const txdata,const WORD32 txlen)
+{
+	T_GMAC_TxDescr *ptTmp;
+	T_GMAC_TxDescr *ptFirstBd;
+	BYTE *pBuf;
+	WORD32 dwBdNum    = 0;
+	WORD32 dwTmplen   = txlen;
+	WORD32 dwBdOffset = g_dwTxBdOffset;
+	WORD32 dwIdx;
+
+	WORD16	tval=0;
+	
+   /* Ö»Óûñȡһ´Î¾Í¿ÉÒÔ Öмä¹ý³Ì»áͬ²½È«¾Ö±äÁ¿rd_bd_offsetÓëÃèÊö·ûÁ´±í */
+   //ptTmp = (T_GMAC_TxDescr *)(((WORD32)&g_TxBd[g_dwTxBdOffset*sizeof(T_GMAC_TxDescr)] + 0x7) & 0xFFFFFFF8);
+	ptTmp = &g_tTxDes[g_dwTxBdOffset];
+
+	if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_TXSTS_OWNBYDMAMASK) == GMAC_DESC_TXSTS_OWNBYDMA)
+	{
+		printf("ERROR: GMAC DESC TXSTS OWN BY DMA\n");
+		return 1;
+	}
+
+	ptFirstBd = ptTmp;
+	pBuf = txdata;
+	
+	while(1)
+	{
+	/* »¹ÐèÒªÅÐ¶Ï ÒòΪ²»Ö»ÊÇÉÏÃæÐèÒªÅжÏownλ */
+		if ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_TXSTS_OWNBYDMAMASK) != GMAC_DESC_TXSTS_OWNBYDMA)
+		{
+			ptTmp->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_TXLAST | GMAC_DESC_TXSTS_TXFIRST));
+			if(dwTmplen == txlen)
+			{
+				ptTmp->dwDescr0     |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXFIRST);
+				ptFirstBd->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_OWNBYDMAMASK));  //show this bd has data wait for tx
+			}
+
+			if(dwTmplen > GMAC_TX_BUF_SIZE)
+			{
+				memcpy((void *)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (void *)pBuf, GMAC_TX_BUF_SIZE);//long frame
+				// ptTmp->dwBuf1Addr = (WORD32)pBuf;
+				ptTmp->dwDescr1 &= GMAC_ENDIAN32_SWAP(~GMAC_DESC_TXCTRL_SIZE1MASK);
+				ptTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(GMAC_TX_BUF_SIZE & GMAC_DESC_TXCTRL_SIZE1MASK);
+				pBuf += GMAC_TX_BUF_SIZE;
+				if(ptFirstBd != ptTmp)
+				{
+					ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA);
+				}
+
+				ptTmp = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
+				dwTmplen -= GMAC_TX_BUF_SIZE;
+				dwBdNum++;
+				g_dwTxBdOffset = (g_dwTxBdOffset+1)%GMAC_TX_DESC_NUM;
+			}
+			else
+			{
+				memcpy((void *)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (void *)pBuf, dwTmplen);
+				//ptTmp->dwBuf1Addr = (WORD32)pBuf;
+				pBuf += dwTmplen;
+				/* Ôö¼ÓÏÂÃæÒ»ÐдúÂë, ½â¾öbug, ½«Êý¾Ý³¤¶È×Ö¶ÎÏÈÇå0ÔÙ¸³Öµ, ·ñÔò²»Äܵõ½Ô¤ÆÚµÄÊý¾Ý³¤¶È */
+				/* »·»Ø²âÊÔÖе¼ÖÂÃèÊö·ûËùÔÚÄÚ´æµØÖ·±»¸²¸Ç£¬µ±È»Ò²¿ÉÄܲúÉúÆäËûÏÖÏ󣬱¾ÖʾÍÊÇÉÏÊöÔ­Òò 2010.09.07 */
+				ptTmp->dwDescr1 &= GMAC_ENDIAN32_SWAP(~GMAC_DESC_TXCTRL_SIZE1MASK);
+				ptTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(dwTmplen & GMAC_DESC_TXCTRL_SIZE1MASK);
+				ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXLAST);
+				ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA);
+				
+				for ( dwIdx = 0; dwIdx < 100; dwIdx++ );	/* delay */  
+				//ptFirstBd->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA);  //due to bd only two ,not necessary
+				
+				if(((g_ptGmacDmaRegs->dwStatus >> 20) & 0x7) == 0x6)		/*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/	
+				{
+					//Print("Reg = %x\n",g_ptGmacDmaRegs->dwStatus);
+					g_ptGmacDmaRegs->dwTxPollDemand = 1;
+				
+				}
+				else
+				{
+					printf("Reg = %x\n",g_ptGmacDmaRegs->dwStatus);
+					//g_ptGmacDmaRegs->dwTxPollDemand = 1;
+				}
+				//mac_tx_enable();
+				//memset((void *)ptTmp->Buf1Addr, 0, dwTmplen);
+				g_dwTxBdOffset = (g_dwTxBdOffset+1)%GMAC_TX_DESC_NUM;
+				
+				return 0;               
+			}      
+		}
+		else
+		{
+			ptTmp = ptFirstBd;
+			while(dwBdNum--)
+			{
+				ptTmp->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_OWNBYDMAMASK));
+				ptTmp = (T_GMAC_TxDescr *)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
+			}
+			g_ptGmacDmaRegs->dwTxPollDemand = 1;   
+			g_dwTxBdOffset = dwBdOffset;
+			return 1;
+		}
+	}
+}
+
+int zx_gmac_getbd(WORD32 bdnum)
+{
+	T_GMAC_RxDescr *ptTmp;
+	if(bdnum > GMAC_RX_DESC_NUM)
+		{
+			printf("buffer description num error\n");
+			return 1;
+		}
+	ptTmp = &g_tRxDes[bdnum];
+	if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) != GMAC_DESC_RXSTS_OWNBYDMA)  //check rx bd descr0 bit31 is 0 ,show that data come
+		return 1;
+	
+	return 0;	
+}
+
+int zx_gmac_rx(BYTE *const prxbuf, WORD32 *const prxlen,WORD32 bdnum)
+{
+	T_GMAC_RxDescr  *ptTmp; 
+	WORD32  dwRet;
+	WORD32  dwTmpLen;
+	BYTE  *pBuf = NULL;
+	int sdFirstBd=0;
+    
+	/* Ö»Óûñȡһ´Î¾Í¿ÉÒÔ Öмä¹ý³Ì»áͬ²½È«¾Ö±äÁ¿rd_bd_offsetÓëÃèÊö·ûÁ´±í */
+	//ptTmp = (T_GMAC_RxDescr *)(((WORD32)&g_RxBd[g_dwRxBdOffset*sizeof(T_GMAC_RxDescr)] + 0x7) & 0xFFFFFFF8);
+	//ptTmp = &g_tRxDes[g_dwRxBdOffset];
+	ptTmp = &g_tRxDes[bdnum];
+	if(ptTmp == 0)
+	{
+		printf("ERROR: g_tRxDes == 0\n");
+		return 0;
+	}
+   
+	if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) == GMAC_DESC_RXSTS_OWNBYDMA)
+	{
+		printf("ERROR: GMAC DESC RXSTS OWN BY DMA\n");
+		return 0;
+	}
+	
+	pBuf = prxbuf;
+	dwTmpLen = 0;
+
+   //memset((void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)),0,0x200);
+
+	while((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) != GMAC_DESC_RXSTS_OWNBYDMA)
+	{
+		if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXES) == GMAC_DESC_RXSTS_RXES)
+		{
+			printf("ERROR: GMAC RX DESC ERROR : ");
+			if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXCE) == GMAC_DESC_RXSTS_RXCE)
+			{
+				printf("CRC Error\n");
+				return 0;
+			}
+			else
+			{
+				//printf("\nRX DESC: GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0)=%x\n", GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0));
+			}
+		}
+
+		//Èç¹ûÖ»ÓÐÒ»¸ö½ÓÊÕÃèÊö·ûÓÐÊý¾Ý(¼ÈÊǵÚÒ»¸ö£¬ÓÖÊÇ×îºóÒ»¸ö)
+		if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) == GMAC_DESC_RXSTS_RXFIRST) 
+		&& ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) == GMAC_DESC_RXSTS_RXLAST))
+		{
+			dwRet = (((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_FRAMELENMASK) 
+			>> GMAC_DESC_RXSTS_FRAMELENSHFT)-4);    // remove 4 bytes crc
+
+			memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), dwRet); 
+
+			//memset((void*)ptTmp->dwBuf1Addr, 0, (ptTmp->dwDescr1 & 0x1FFF));   
+			ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+			/*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+			if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+			{
+				g_ptGmacDmaRegs->dwRxPollDemand = 1;
+			}
+
+			//g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+			return dwRet;                
+		}
+
+		//Èç¹ûÊǵÚÒ»¸ö½ÓÊÕÃèÊö·û(ºóÃæ»¹ÓнÓÊÕÃèÊö·û)
+		if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) == GMAC_DESC_RXSTS_RXFIRST) 
+		&& ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) != GMAC_DESC_RXSTS_RXLAST))
+		{
+			memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF)); 
+			pBuf += (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF);
+			dwTmpLen += GMAC_RX_BUF_SIZE;
+			ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(0x1u << 31);            
+			/*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+			if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+			{
+				g_ptGmacDmaRegs->dwRxPollDemand = 1;
+			}
+
+			//g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+			sdFirstBd = 1;
+			ptTmp = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));			 
+
+			continue;
+		}
+
+		//Èç¹ûÊÇ×îºóÒ»¸ö½ÓÊÕÃèÊö·û(µ«²»ÊǵÚÒ»¸ö½ÓÊÕÃèÊö·û)
+		if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) != GMAC_DESC_RXSTS_RXFIRST) 
+		&& ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) == GMAC_DESC_RXSTS_RXLAST) 
+		&& sdFirstBd == 1)
+		{
+			dwRet = (((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) >> 16) & 0x3FFF)-4); 
+			memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (dwRet-dwTmpLen));
+			ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+			/*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+			if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+			{
+				g_ptGmacDmaRegs->dwRxPollDemand = 1;
+			}
+
+			//g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+			return dwRet;                
+		}
+
+		//Èç¹û¼È²»ÊǵÚÒ»¸ö£¬Ò²²»ÊÇ×îºóÒ»¸ö½ÓÊÕÃèÊö·û
+		if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) != GMAC_DESC_RXSTS_RXFIRST) 
+		&& ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) != GMAC_DESC_RXSTS_RXLAST) 
+		&& sdFirstBd == 1)
+		{
+			memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF));
+			pBuf += (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF); 
+			dwTmpLen += GMAC_RX_BUF_SIZE;
+			ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+			/*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+			if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+			{
+				g_ptGmacDmaRegs->dwRxPollDemand = 1;
+			}
+			//g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+			ptTmp = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
+		}
+
+		if(sdFirstBd == 0)
+		{
+			printf("ERROR: RX DESC lost first bd\n");/*lost first bd */
+		break;
+		}
+	}
+	return dwTmpLen;
+}
+
+static void mii_write(WORD32 tPhyAddr, WORD32 tPhyReg, WORD16 tData)
+{
+    while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+
+    g_ptGmacGmacRegs->dwGMIIData  = (WORD32)tData;
+	
+    g_ptGmacGmacRegs->dwGMIIAddr  = (GMAC_GMII_MDC << GMAC_GMII_MDC_SHIFT);
+	
+    g_ptGmacGmacRegs->dwGMIIAddr |= ((tPhyAddr << GMAC_GMII_ADDR_SHIFT)   & GMAC_GMII_ADDR_MSK)
+                                 |  ((tPhyReg  << GMAC_GMII_PHYREG_SHIFT) & GMAC_GMII_PHYREG_MSK)
+                                 |  GMAC_GMII_WRITE 
+                                 |  GMAC_GMII_BUSY;	
+    
+    while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+}
+
+
+static WORD16 mii_read(WORD32 tPhyAddr, WORD32 tPhyReg)
+{
+	while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+	
+    g_ptGmacGmacRegs->dwGMIIAddr  = (GMAC_GMII_MDC << GMAC_GMII_MDC_SHIFT);//clock 3  35~60MHZ  ʱÖÓλ
+	
+    g_ptGmacGmacRegs->dwGMIIAddr |= ((tPhyAddr << GMAC_GMII_ADDR_SHIFT)   & GMAC_GMII_ADDR_MSK)
+                                 |  ((tPhyReg  << GMAC_GMII_PHYREG_SHIFT) & GMAC_GMII_PHYREG_MSK)
+                                 |  GMAC_GMII_BUSY;	
+    
+    while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+
+    return (WORD16)(g_ptGmacGmacRegs->dwGMIIData&0xFFFF);    /*  0xFFFF: 16λÊý¾ÝÑÚÂë */
+	
+}
+
+#if (GMAC_PHY_USE == GMAC_PHY_88E1111)
+int gmac_phy_led(WORD32 tphyid,WORD32 ledctrl,WORD32 lednum)
+{   
+	WORD32 tphy;
+   	WORD16 tval=0;
+	WORD16 tctrl=0;
+	WORD32 tcount=0;
+
+	tphy = tphyid;
+	if(lednum > GMAC_PHY_LED_MAX)
+		return 1;
+
+	if(ledctrl)
+	{
+		tctrl = mii_read(tphy, GMAC_PHY_LED_CTRL_REG);
+		tval  = mii_read(tphy, GMAC_PHY_LED_MANUAL_REG);
+
+		mii_write(tphy, GMAC_PHY_LED_CTRL_REG, tctrl|(1<<15));  /*¿ªÆôled ¹¦ÄÜÜ */
+
+		tval &= ~(0x1 << (lednum-1));
+		mii_write(tphy, GMAC_PHY_LED_MANUAL_REG,tval);
+		tcount++;
+	}
+	else
+	{
+		tctrl = mii_read(tphy, GMAC_PHY_LED_CTRL_REG);
+		tval  = mii_read(tphy, GMAC_PHY_LED_MANUAL_REG);
+
+		tval |= (0x1 << (lednum-1));
+		mii_write(tphy, GMAC_PHY_LED_MANUAL_REG,tval);
+		tcount--;
+
+		if(tcount == 0)
+		mii_write(tphy, GMAC_PHY_LED_CTRL_REG, tctrl&(~(1<<15)));  /* ½ûÖ¹Led ¹¦ÄÜ¿ */
+	}
+	return 0;
+	
+}
+
+void gmac_phy_setclock(WORD32 tphyid)
+{
+	WORD32 tphy;
+	WORD16 tval=0;
+
+	tphy = tphyid;
+
+	mii_write(tphy, 27, 0x800F);     /* GMII PORT to Copper */    
+	/*software reset*/
+	tval = mii_read(tphy, 0x0);
+	mii_write(tphy, 0x0, tval | ( 1 << 15)); 
+	while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+	mii_write(tphy, 22, 0x00);     /*  */    
+	/*software reset*/
+	tval = mii_read(tphy, 0x0);
+	mii_write(tphy, 0x0, tval | ( 1 << 15)); 
+	while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+	mii_write(tphy, 30, 0x00);     /*  */    
+	/*software reset*/
+	tval = mii_read(tphy, 0x0);
+	mii_write(tphy, 0x0, tval | ( 1 << 15)); 
+	while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+	mii_write(tphy, 20, 0x51);     /* 100M  25MHZ*/
+	/*software reset*/
+	tval = mii_read(tphy, 0x0);
+	mii_write(tphy, 0x0, tval | ( 1 << 15)); 
+	while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+	//mii_write(tphy,  0, 0x3100);   /* 100M Full Duplex, Autonegotiation */
+	mii_write(tphy,  0, 0x3100);   /* 100M half Duplex, Autonegotiation */
+	/*software reset*/
+	tval = mii_read(tphy, 0x0);
+	mii_write(tphy, 0x0, tval | ( 1 << 15)); 
+	while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+}
+
+int gmac_phy_init(void)
+{
+	WORD32	i;
+	WORD32 tphy;
+    	WORD16	tval=0;
+	// »ñÈ¡µÚÒ»¸öPHYµÄÐòºÅ¼°ID
+	WORD32 val;
+
+	val = *(volatile WORD32 *)(0x01306114); 
+	//*(volatile WORD32 *)(0x01306114) = val & 0xFFFE; //¸´Î»gmac top
+	//*(volatile WORD32 *)(0x01306114) = val | 0x01;
+
+	//*(volatile WORD32 *)(0x01306114) = val & 0xFFFd; //¸´Î»gmac bus
+	//*(volatile WORD32 *)(0x01306114) = val | 0x02;
+
+	*(volatile WORD32 *)(0x01306114) = val & 0xFFDF; //¸´Î»gmac
+	*(volatile WORD32 *)(0x01306114) = val | 0x20;
+
+
+	for(i = 0; i < PHY_88E1111_MAX_NUM; i++)
+	{
+		tval = mii_read(i, PHY_88E1111_PHYIDR1);
+		if(tval == GMAC_PHY_88E1111_ID)
+		{
+			tphy = i;
+			break;
+		}
+	}
+	if(PHY_88E1111_MAX_NUM == i)
+	{
+		printf("Error: can not find phy 88E1111\n");
+		return 1;
+	}
+	phyid = tphy;
+	gmac_phy_setclock(tphy);
+	
+	mii_write(tphy, 16, 0x38);
+		
+	/* Disable Auto-Selection when loopback */
+	tval = mii_read(tphy, 27);
+	tval = tval | (0x1<<15); 
+	mii_write(tphy, 27, tval);
+
+	/*software reset*/
+	tval = mii_read(tphy, 0);
+	mii_write(tphy, 0, tval | ( 1 << 15)); 
+	while( mii_read(tphy, 0x0) & ( 1 << 15));
+		
+	/* Disable Autonegotiation */
+	tval = mii_read(tphy, 0x0);
+	tval = tval & (~(0x1 << 12)); 
+	mii_write(tphy, 0x0, tval); 
+       	/*software reset*/
+	tval = mii_read(tphy, 0x0);
+	mii_write(tphy, 0x0, tval | ( 1 << 15)); 
+	while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+	/* enable led,set tx led*/
+	tval = mii_read(tphy, 24);
+	mii_write(tphy, 24, tval & 0x7fbe); 
+	tval = mii_read(tphy, 24);
+	mii_write(tphy, 24, tval | ( 1 << 1)); 
+
+	/* set phy tx  and crc error count*/
+	//tval = mii_read(tphy, 29);
+	mii_write(tphy, 29, 0x0010); 
+	//tval = mii_read(tphy, 30);
+	mii_write(tphy, 30, 0x0001); 
+	//tval = mii_read(tphy, 29);
+	mii_write(tphy, 29, 0x000c); 
+	
+     // tval = mii_read(tphy, 29);
+    mii_write(tphy, 18, 0xff); 
+    
+	/* enable phyloopback */
+	//tval = mii_read(tphy, 0x0);
+	//tval = tval  | (0x1 << 14); 
+	//mii_write(tphy, 0x0, tval); 
+      
+	
+	/* Debug */
+	tval = mii_read(tphy, 0x0);
+	printf("Phy Reg0 = %x\n",(u32)tval);	
+	return 0;
+}
+#endif
+
+#if (GMAC_PHY_USE == GMAC_PHY_IP101A)
+void gmac_phy_setclock(WORD32 tphyid)
+{
+    WORD32 tphy;
+    WORD16 tval=0;
+	
+	tphy = tphyid;
+
+	/*software reset*/
+	mii_write(tphy, MII_BMCR, BMCR_RESET); 
+	while( mii_read(tphy, MII_BMCR) & BMCR_RESET);
+#if 0
+	#if 1
+	tval = mii_read(tphy, MII_BMCR);
+	tval |= (BMCR_LOOPBACK);   /* enable loopback */
+	mii_write(tphy, MII_BMCR, tval); 
+	#endif
+	
+  	tval = mii_read(tphy, MII_BMCR);
+	tval |= (BMCR_FULLDPLX | BMCR_SPEED100);   /* 100M Full Duplex, disAutonegotiation */
+	tval &= ~BMCR_ANENABLE;    //disable auto-negotiation
+	mii_write(tphy, MII_BMCR, tval); 
+
+	tval = mii_read(tphy, 16);
+	tval |= (0x1<<11);   /* disAutonegotiation  dis midx*/
+	mii_write(tphy, 16, tval); 
+#endif
+
+}
+
+//char TYPE = 0;
+int gmac_phy_init(void)
+{
+	WORD32	i = 0,j = 0;
+	WORD32 tphy = 0,autospeed = 0,autoduplex = 0;
+    WORD16	tval=0;
+    WORD32	val = 0,utmp = 0; 
+
+	val = *(volatile WORD32 *)(0x013C020);      	  
+	*(volatile WORD32 *)(0x013C020) = val | (0x1<9);    // GPIO cfg rmii_clk_o
+	*(volatile WORD32 *)(0x0013B11C) = 0x00000005; //enable rmii clock RMII_CLOCK_CFG
+
+	val = *(volatile WORD32 *)(0x013C020);      	  
+	*(volatile WORD32 *)(0x013C020) = val | (0x1<18);    // GPIO cfg rmii_clk_o
+	
+    val = *(volatile WORD32 *)(0x00140150); 
+	//*(volatile WORD32 *)(0x00140150) = val & 0xFFFFFFEF ; // GMAC_MOD_CFG gmac phy reset
+
+	*(volatile WORD32 *)(0x00140150) = val | 0x10 ; 
+	udelay(200); 									//IP101A phy delay >10ms  ²Åok
+
+
+	// »ñÈ¡µÚÒ»¸öPHYµÄÐòºÅ¼°ID
+	for(i = 0; i < IP101A_PHY_MAX_NUM; i++)
+	{
+		tval = mii_read(i, MII_PHYSID1);
+		printf("Phy Reg%d = %x\n",(s32)i,(u32)tval);	
+		if(tval == IP101A_PHY_ID)
+		{
+			tphy = i;
+		    phyid = tphy;
+			break;
+		}
+	}
+    if(IP101A_PHY_MAX_NUM == i)
+    {
+        printf("Error: can not find phy IP101A\n");
+        return -1;
+    }
+
+	gmac_phy_setclock(tphy);
+
+	mii_write(tphy, MII_ADVERTISE, 0x1E1); 
+	tval = BMCR_ANENABLE | BMCR_ANRESTART;
+	mii_write(tphy, MII_BMCR, tval); 
+	
+    /* ²éѯ×ÔЭÉÌÊÇ·ñÍê³É */
+	while(autotimeout)
+	//while(1)
+	{
+	  tval = mii_read(tphy, MII_BMSR);
+	  if(tval&BMSR_ANEGCOMPLETE)
+	  {
+	  	break;
+	  }
+	    autotimeout--;
+	}
+	if(autotimeout == 0)
+	{
+		printf("phy IP101A auto negotiation failed\n");
+		return -1;
+	}
+        /* ²éѯÊÇ·ñÁ¬½ÓÉÏ*/
+    tval = mii_read(tphy, MII_LPA);
+	autospeed  = tval & LPA_100 ? GMAC_PHY_SPEED_100 : GMAC_PHY_SPEED_10; 
+    autoduplex = (mii_read(tphy, MII_BMCR) & 0x0100) >> 8;
+    if(autospeed == GMAC_PHY_SPEED_100)
+    {
+		printf("phy IP101A auto negotiation speed is 100M\n");
+	}
+	else
+	{
+		printf("phy IP101A auto negotiation speed is 10M\n");
+	}
+
+	if(autoduplex == GMAC_PHY_DUPLEX_FULL) 
+	{
+		printf("phy IP101A auto negotiation duplex is full\n");
+	}
+	else
+	{
+		printf("phy IP101A auto negotiation duplex is half\n");
+	}
+
+	return 0;
+}
+#endif
+
diff --git a/boot/common/src/uboot/drivers/gmac/net.c b/boot/common/src/uboot/drivers/gmac/net.c
new file mode 100644
index 0000000..ce03adf
--- /dev/null
+++ b/boot/common/src/uboot/drivers/gmac/net.c
@@ -0,0 +1,315 @@
+/*******************************************************************************

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

+*

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

+* Îļþ±êʶ:

+* ÄÚÈÝÕªÒª: ¸ºÔðCPUºÍPPÄ£¿éÖ®¼äµÄÊý¾Ý½»»¥

+* ÆäËü˵Ã÷:

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

+* ×÷¡¡¡¡Õß:	±«Ð¡ÔÆ

+* Íê³ÉÈÕÆÚ: 2012-1-12 16:22:32

+*

+* Ð޸ļǼ1

+* ÐÞ¸ÄÈÕÆÚ:

+* °æ±¾¡¡ºÅ:

+* Ð޸ġ¡ÈË:

+* ÐÞ¸ÄÄÚÈÝ:

+*

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

+#include <common.h>

+#include <asm/errno.h>

+#include <malloc.h>

+#include <net.h>

+#include <asm/arch/gmac.h>

+

+

+#if 0

+#include <tm/io.h>

+#include <tm/tm.h>

+#include <tm/pon.h>

+#include <tm/pp/dma.h>

+#include <tm/pp/bmu.h>

+#include <tm/pp/red.h>

+#include <tm/pp/pp.h>

+#include <tm/pp/net.h>

+#include <tm/switch/smac.h>

+#endif

+

+

+#ifdef CONFIG_CMD_NET

+

+#define CACHE_ALIGNED(x)  ((x)&(~0x1f))

+#if 0

+typedef struct _queue_ctrl{

+	u8  *pFirst;

+	u32  nextToProc;

+} NET_QUEUE_CTRL;

+#endif

+u8 default_mac[6]={0x00,0xd0,0xd0,0x01,0x02,0x03};

+/*NET_QUEUE_CTRL queue_ctrl[PP_MAX_QUEUE];

+int pp_net_debug=0;*/

+

+void (* volatile net_recv) (u8 * buf, int len) = NULL; 

+

+void register_net_recv(void *handle)

+{

+	net_recv = handle;

+}

+

+/*

+ * Get pointer to next RX descriptor to be processed by SW

+ */

+ #if 0

+static inline struct pp_desc * pp_get_next_rxdesc(int rxq)

+{

+	struct pp_desc *desc;

+	NET_QUEUE_CTRL *qc;

+	qc    = &queue_ctrl[rxq];

+	desc  = (struct pp_desc *)(qc->nextToProc * PP_DESC_SIZE + qc->pFirst);

+	if(unlikely(++qc->nextToProc >= PP_QUEUE_SIZE)){

+		qc->nextToProc = 0;

+	}

+	return desc;

+}

+

+static void dump_net_data(u8 *data, u32 len)

+{

+	int i;

+	len = len > 64?64:len;

+	for(i=0;i<len;i++){

+		printf("%.2x ",data[i]);

+		if((i&0xf) == 0xf)

+			printf("\n");

+	}

+	printf("\n");

+}

+

+void dump_desc(struct pp_desc *desc)

+{

+	u32 *data = (u32 *)desc;

+	printf("%.8x:0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",(u32)desc,data[0],data[1],data[2],data[3]);

+	printf("bp %u gem %u len %u\n",desc->BP,desc->Gemport_ID,desc->Pkt_Len);

+}

+

+

+static void free_desc(struct pp_desc *desc,int bp)

+{

+    // free desc  

+#ifdef CONFIG_ZX279112

+    if(soft_release_rx_desc(desc->Direction, desc->CPU_Queue_ID,desc->Buffer_Type) < 0)

+#else

+    if(soft_release_rx_desc(desc->CPU_Queue_ID,desc->Buffer_Type) < 0)

+#endif

+    	printf("failed to rls rx desc1\n");

+    // free bp 

+    if(pp_bmu_free_bp((u16)bp) < 0)

+    	printf("failed to rls bp\n");	    

+}

+

+static inline int pp_net_rx(struct eth_device* dev,int cnt,int rxq)

+{

+	int i,bp,len;

+	struct pp_desc *desc ;

+	u8 *buf;

+	

+	// receive packet 

+#ifdef CONFIG_SYS_ARM_CACHE_WRITETHROUGH	

+	invalidate_dcache_all();

+#endif	

+	for(i=0;i<cnt;i++){

+		//get desc, invalid cache, and prefetch 

+		desc = pp_get_next_rxdesc(rxq);

+#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)    

+		invalidate_dcache_range((u32)desc,(u32)desc+16);

+#endif		

+		bp  = desc->BP;

+		// check bp 

+		if(unlikely(bp >= BP_NUMBERS)){

+			printf("invalid bp %u\n",bp);

+			dump_desc(desc);

+			//error handle  

+#ifdef CONFIG_ZX279112

+		    soft_release_rx_desc(desc->Direction, rxq,1);

+#else

+		    soft_release_rx_desc(rxq,1);

+#endif

+		    continue;

+		}

+		buf = (u8 *)(BP_TO_ADDR(bp)) + desc->Offset;

+		len = desc->Pkt_Len;

+#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)    

+		invalidate_dcache_range((u32)buf,(u32)buf+len);

+#endif		

+        if(pp_net_debug>0){

+        	dump_desc(desc);

+    		printf("receive len %u, BP %d ,gem %d,addr %x\n",len,

+    			bp,desc->Gemport_ID,(u32)buf);

+    		dump_net_data(buf,len);

+    		pp_net_debug--;

+    	}

+

+        if(net_recv == NULL)

+			NetReceive(buf, len);

+		else

+			net_recv(buf, len);

+        free_desc(desc,bp);

+	}

+	return cnt;

+}

+

+/*

+ * get the count of unprocess packet

+ */

+static inline int pp_get_rx_cnt(u32 queue)

+{

+	return ZX_REG_READ(PP_DMA_CPU_QUEUE_CNT(queue));

+}

+#endif

+int max_rx_delay=1000;

+/*

+ * pp net poll interface

+ */

+static int gmac_net_poll(struct eth_device* dev)

+{

+	int i,len=0,trxlen=0;

+//   	unsigned char  *rxbuf;

+	unsigned char  rxbuf[256];

+

+	

+	//for(i=2;i>0;i--)

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

+	{

+		if(zx_gmac_getbd(i)!=0)

+			{

+				trxlen=zx_gmac_rx(rxbuf,&len,i);

+				if(net_recv == NULL)

+				NetReceive(rxbuf, trxlen);

+				else

+				net_recv(rxbuf, trxlen);

+				if(zx_gmac_getbd(i)!=0)

+				/* new packet arrived or hardware has update rx cnt, wait for a while */

+				udelay(1);

+			}

+	}

+    return 0;

+}

+#if 0

+int pp_data_raw_send(u8 *data, u32 len,struct pp_desc *desc)

+{

+	int bp;

+	u8 *buf;

+	/* get the tx descriptor */

+	/* alloc bp to save data */

+	if((bp = pp_bmu_alloc_bp())<0){

+		PON_NET_DBG("alloc bp failed\n");

+		return -1;

+	}

+	/* check bp */

+	if(unlikely(bp >= BP_NUMBERS)){

+		PON_NET_DBG("invalid bp %d\n",bp);

+		return -1;

+	}	

+	/* copy data to bp */

+	buf = (u8 *)BP_TO_ADDR(bp)+16;

+	memcpy(buf,data,len);

+

+	/* make desc */

+	desc->BP              = bp;

+	desc->Pkt_Len         = len;

+	desc->Pkt_Len_Changed = len;

+	desc->Offset          = 16;

+    if(pp_net_debug>0){

+    	printf("send len %u, BP %d ,addr %x\n",len,

+    		bp,(u32)buf);

+    	dump_desc(desc);

+    	dump_net_data(buf,len);

+    	pp_net_debug--;

+    }	

+	

+#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)    

+    flush_dcache_range((u32)buf,(u32)buf+len);

+#endif    

+	/* insert desc */

+	if(soft_insert_tx_desc((u32 *)desc)<0){

+		PON_NET_DBG("insert desc failed\n");

+		return -2;		

+	}

+	return 0;	    

+}

+#endif

+/* 

+ * send packet to sw, 

+ */

+static int gmac_net_sw_tx(struct eth_device* dev, volatile void* packet, int length)

+{

+	if(zx_gmac_send((u8 *)packet,length) != 0)

+	{

+		printf("gmac send error\n");

+		return 1;

+	}

+	return 0;

+}

+#if 0

+void pp_queue_init(void)

+{

+	int i;

+	NET_QUEUE_CTRL *qc;

+	/* init inner rx queue status */

+	for(i=0;i<PP_MAX_QUEUE;i++){

+		qc = &queue_ctrl[i];

+		qc->pFirst      = (u8 *)(PP_VA_DESC_BASE + 0x10000 * (PP_RX_QUEUE_OFF+i));

+		qc->nextToProc  = 0;

+	}

+}

+#endif

+int  gmac_eth_init(struct eth_device* dev, bd_t* bd)

+{	

+	zx_gmac_init();	

+	return 0;

+}

+

+void gmac_eth_halt(struct eth_device* dev)

+{

+	udelay(100); /* wait for send complete */

+	zx_gmac_stop();	

+

+}

+

+/*int pp_net_init(void)

+{

+    tm_set_onu_mac(ONU_MAC1,default_mac);

+	pp_queue_init();

+	return 0;

+}*/

+

+void gmac_net_register(void)

+{

+	struct eth_device *dev;

+

+	dev = malloc(sizeof(*dev));

+	if (!dev)	{

+		free(dev);

+		return ;

+	}

+

+	memset(dev, 0, sizeof(*dev));

+

+	dev->init 	= gmac_eth_init;

+	dev->halt 	= gmac_eth_halt;

+	dev->send 	= gmac_net_sw_tx;

+	dev->recv 	= gmac_net_poll;

+

+	sprintf(dev->name, "eth0");

+

+	/* get mac */

+	if(!eth_getenv_enetaddr("ethaddr", dev->enetaddr)){

+		puts("Please set MAC address\n");

+	}

+	else{

+		memcpy(default_mac,dev->enetaddr,6);

+	}

+

+	eth_register(dev);

+}

+

+#endif