]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/lwIP_Demo/lwIP_port/netif/xemacpsif_dma.c
Completely re-generate the Zynq 7000 demo using the 2016.1 SDK tools.
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo / src / lwIP_Demo / lwIP_port / netif / xemacpsif_dma.c
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/lwIP_Demo/lwIP_port/netif/xemacpsif_dma.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/lwIP_Demo/lwIP_port/netif/xemacpsif_dma.c
new file mode 100644 (file)
index 0000000..429b51a
--- /dev/null
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
+ *
+ * Xilinx, Inc.
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include "lwipopts.h"
+#include "lwip/stats.h"
+#include "lwip/sys.h"
+#include "lwip/inet_chksum.h"
+
+#include "netif/xadapter.h"
+#include "netif/xemacpsif.h"
+#include "xstatus.h"
+
+#include "xlwipconfig.h"
+#include "xparameters.h"
+#include "xparameters_ps.h"
+#include "xil_exception.h"
+#include "xil_mmu.h"
+#ifdef CONFIG_XTRACE
+#include "xtrace.h"
+#endif
+#ifdef OS_IS_FREERTOS
+#include "FreeRTOS.h"
+#include "semphr.h"
+#include "timers.h"
+#endif
+
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
+ *** to run it on a PEEP board
+ ***/
+
+#define INTC_BASE_ADDR         XPAR_SCUGIC_CPU_BASEADDR
+#define INTC_DIST_BASE_ADDR    XPAR_SCUGIC_DIST_BASEADDR
+
+/* Byte alignment of BDs */
+#define BD_ALIGNMENT (XEMACPS_DMABD_MINIMUM_ALIGNMENT*2)
+
+static int tx_pbufs_storage[XLWIP_CONFIG_N_TX_DESC];
+static int rx_pbufs_storage[XLWIP_CONFIG_N_RX_DESC];
+
+static int EmacIntrNum;
+extern u8 _end;
+
+#ifdef OS_IS_FREERTOS
+extern BaseType_t xInsideISR;
+#endif
+
+#define XEMACPS_BD_TO_INDEX(ringptr, bdptr)                            \
+       (((u32)bdptr - (u32)(ringptr)->BaseBdAddr) / (ringptr)->Separation)
+
+
+int is_tx_space_available(xemacpsif_s *emac)
+{
+       XEmacPs_BdRing *txring;
+       int freecnt = 0;
+
+       txring = &(XEmacPs_GetTxRing(&emac->emacps));
+
+       /* tx space is available as long as there are valid BD's */
+       freecnt = XEmacPs_BdRingGetFreeCnt(txring);
+       return freecnt;
+}
+
+void process_sent_bds(XEmacPs_BdRing *txring)
+{
+       XEmacPs_Bd *txbdset;
+       XEmacPs_Bd *CurBdPntr;
+       int n_bds;
+       XStatus Status;
+       int n_pbufs_freed = 0;
+       unsigned int BdIndex;
+       struct pbuf *p;
+       unsigned int *Temp;
+
+       while (1) {
+               /* obtain processed BD's */
+               n_bds = XEmacPs_BdRingFromHwTx(txring,
+                                                               XLWIP_CONFIG_N_TX_DESC, &txbdset);
+               if (n_bds == 0)  {
+                       return;
+               }
+               /* free the processed BD's */
+               n_pbufs_freed = n_bds;
+               CurBdPntr = txbdset;
+               while (n_pbufs_freed > 0) {
+                       BdIndex = XEMACPS_BD_TO_INDEX(txring, CurBdPntr);
+                       Temp = (unsigned int *)CurBdPntr;
+                       *Temp = 0;
+                       Temp++;
+                       *Temp = 0x80000000;
+                       if (BdIndex == (XLWIP_CONFIG_N_TX_DESC - 1)) {
+                               *Temp = 0xC0000000;
+                       }
+
+                       p = (struct pbuf *)tx_pbufs_storage[BdIndex];
+                       if(p != NULL) {
+                               pbuf_free(p);
+                       }
+                       tx_pbufs_storage[BdIndex] = 0;
+                       CurBdPntr = XEmacPs_BdRingNext(txring, CurBdPntr);
+                       n_pbufs_freed--;
+                       dsb();
+               }
+
+               Status = XEmacPs_BdRingFree(txring, n_bds, txbdset);
+               if (Status != XST_SUCCESS) {
+                       LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n"));
+               }
+       }
+       return;
+}
+
+void vPendableSendCompleteFunction( void *pvParameter, uint32_t ulParameter )
+{
+       ( void ) ulParameter;
+       process_sent_bds(pvParameter);
+}
+
+void emacps_send_handler(void *arg)
+{
+       struct xemac_s *xemac;
+       xemacpsif_s   *xemacpsif;
+       XEmacPs_BdRing *TxRingPtr;
+       unsigned int regval;
+#ifdef OS_IS_FREERTOS
+       xInsideISR++;
+#endif
+       xemac = (struct xemac_s *)(arg);
+       xemacpsif = (xemacpsif_s *)(xemac->state);
+       TxRingPtr = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+       regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
+       XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval);
+
+#ifdef OS_IS_FREERTOS
+       xInsideISR--;
+#endif
+
+       /* If Transmit done interrupt is asserted, process completed BD's - Replaced
+       a call to process_sent_bds(TxRingPtr); with a pendable function to prevent
+       the memory allocation files being accessed from the ISR with not redress if
+       obtaining the mutex fails. */
+       {
+               BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+               xTimerPendFunctionCallFromISR( vPendableSendCompleteFunction, TxRingPtr, 0, &xHigherPriorityTaskWoken );
+               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+       }
+}
+
+XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p)
+{
+       struct pbuf *q;
+       int n_pbufs;
+       XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL;
+       XEmacPs_Bd *temp_txbd;
+       XStatus Status;
+       XEmacPs_BdRing *txring;
+       unsigned int BdIndex;
+       unsigned int lev;
+
+       lev = mfcpsr();
+       mtcpsr(lev | 0x000000C0);
+
+#ifdef PEEP
+    while((XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
+                                                                       XEMACPS_TXSR_OFFSET)) & 0x08);
+#endif
+       txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+
+       /* first count the number of pbufs */
+       for (q = p, n_pbufs = 0; q != NULL; q = q->next)
+               n_pbufs++;
+
+       /* obtain as many BD's */
+       Status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
+       if (Status != XST_SUCCESS) {
+               mtcpsr(lev);
+               LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
+               return ERR_IF;
+       }
+
+       for(q = p, txbd = txbdset; q != NULL; q = q->next) {
+               BdIndex = XEMACPS_BD_TO_INDEX(txring, txbd);
+               if (tx_pbufs_storage[BdIndex] != 0) {
+                       mtcpsr(lev);
+                       LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
+                       return ERR_IF;
+               }
+
+               /* Send the data from the pbuf to the interface, one pbuf at a
+                  time. The size of the data in each pbuf is kept in the ->len
+                  variable. */
+               Xil_DCacheFlushRange((unsigned int)q->payload, (unsigned)q->len);
+
+               XEmacPs_BdSetAddressTx(txbd, (u32)q->payload);
+               if (q->len > (XEMACPS_MAX_FRAME_SIZE - 18))
+                       XEmacPs_BdSetLength(txbd, (XEMACPS_MAX_FRAME_SIZE - 18) & 0x3FFF);
+               else
+                       XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);
+
+               tx_pbufs_storage[BdIndex] = (int)q;
+
+               pbuf_ref(q);
+               last_txbd = txbd;
+               XEmacPs_BdClearLast(txbd);
+               dsb();
+               txbd = XEmacPs_BdRingNext(txring, txbd);
+       }
+       XEmacPs_BdSetLast(last_txbd);
+       dsb();
+       /* For fragmented packets, remember the 1st BD allocated for the 1st
+          packet fragment. The used bit for this BD should be cleared at the end
+          after clearing out used bits for other fragments. For packets without
+          just remember the allocated BD. */
+       temp_txbd = txbdset;
+       txbd = txbdset;
+       txbd = XEmacPs_BdRingNext(txring, txbd);
+       q = p->next;
+       for(; q != NULL; q = q->next) {
+               XEmacPs_BdClearTxUsed(txbd);
+               txbd = XEmacPs_BdRingNext(txring, txbd);
+       }
+       XEmacPs_BdClearTxUsed(temp_txbd);
+       dsb();
+
+       Status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
+       if (Status != XST_SUCCESS) {
+               mtcpsr(lev);
+               LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
+               return ERR_IF;
+       }
+       dsb();
+       /* Start transmit */
+       XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
+       XEMACPS_NWCTRL_OFFSET,
+       (XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
+       XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));
+       dsb();
+       mtcpsr(lev);
+       return Status;
+}
+
+void setup_rx_bds(XEmacPs_BdRing *rxring)
+{
+       XEmacPs_Bd *rxbd;
+       XStatus Status;
+       struct pbuf *p;
+       unsigned int FreeBds;
+       unsigned int BdIndex;
+       unsigned int *Temp;
+
+       FreeBds = XEmacPs_BdRingGetFreeCnt (rxring);
+       while (FreeBds > 0) {
+               FreeBds--;
+               Status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd);
+               if (Status != XST_SUCCESS) {
+                       LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n"));
+                       return;
+               }
+               BdIndex = XEMACPS_BD_TO_INDEX(rxring, rxbd);
+               Temp = (unsigned int *)rxbd;
+               *Temp = 0;
+               if (BdIndex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
+                       *Temp = 0x00000002;
+               }
+               Temp++;
+               *Temp = 0;
+
+               p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+               if (!p) {
+#if LINK_STATS
+                       lwip_stats.link.memerr++;
+                       lwip_stats.link.drop++;
+#endif
+                       LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n"));
+                       XEmacPs_BdRingUnAlloc(rxring, 1, rxbd);
+                       dsb();
+                       return;
+               }
+               XEmacPs_BdSetAddressRx(rxbd, (u32)p->payload);
+               dsb();
+
+               rx_pbufs_storage[BdIndex] = (int)p;
+               Status = XEmacPs_BdRingToHw(rxring, 1, rxbd);
+               if (Status != XST_SUCCESS) {
+                       LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
+                       if (Status == XST_DMA_SG_LIST_ERROR)
+                               LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n"));
+                       else
+                       {
+                               LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n"));
+                       }
+                       return;
+               }
+       }
+}
+
+void emacps_recv_handler(void *arg)
+{
+       struct pbuf *p;
+       XEmacPs_Bd *rxbdset, *CurBdPtr;
+       struct xemac_s *xemac;
+       xemacpsif_s *xemacpsif;
+       XEmacPs_BdRing *rxring;
+       volatile int bd_processed;
+       int rx_bytes, k;
+       unsigned int BdIndex;
+       unsigned int regval;
+
+       xemac = (struct xemac_s *)(arg);
+       xemacpsif = (xemacpsif_s *)(xemac->state);
+       rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+
+#ifdef OS_IS_FREERTOS
+       xInsideISR++;
+#endif
+       /*
+        * If Reception done interrupt is asserted, call RX call back function
+        * to handle the processed BDs and then raise the according flag.
+        */
+       regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
+       XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval);
+
+       resetrx_on_no_rxdata(xemacpsif);
+
+       while(1) {
+
+               bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
+
+               if (bd_processed <= 0) {
+                       break;
+               }
+
+               for (k = 0, CurBdPtr=rxbdset; k < bd_processed; k++) {
+
+                       BdIndex = XEMACPS_BD_TO_INDEX(rxring, CurBdPtr);
+                       p = (struct pbuf *)rx_pbufs_storage[BdIndex];
+
+                       /*
+                        * Adjust the buffer size to the actual number of bytes received.
+                        */
+                       rx_bytes = XEmacPs_BdGetLength(CurBdPtr);
+                       pbuf_realloc(p, rx_bytes);
+                       Xil_DCacheInvalidateRange((unsigned int)p->payload, (unsigned)XEMACPS_MAX_FRAME_SIZE);
+                       /* store it in the receive queue,
+                        * where it'll be processed by a different handler
+                        */
+                       if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
+#if LINK_STATS
+                               lwip_stats.link.memerr++;
+                               lwip_stats.link.drop++;
+#endif
+                               pbuf_free(p);
+                       } else {
+#if !NO_SYS
+                               sys_sem_signal(&xemac->sem_rx_data_available);
+#endif
+                       }
+                       CurBdPtr = XEmacPs_BdRingNext( rxring, CurBdPtr);
+               }
+               /* free up the BD's */
+               XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
+               setup_rx_bds(rxring);
+       }
+
+#ifdef OS_IS_FREERTOS
+       xInsideISR--;
+#endif
+       return;
+}
+
+void clean_dma_txdescs(struct xemac_s *xemac)
+{
+       XEmacPs_Bd BdTemplate;
+       XEmacPs_BdRing *TxRingPtr;
+       xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+
+       TxRingPtr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+
+       XEmacPs_BdClear(&BdTemplate);
+       XEmacPs_BdSetStatus(&BdTemplate, XEMACPS_TXBUF_USED_MASK);
+
+       /*
+        * Create the TxBD ring
+        */
+       XEmacPs_BdRingCreate(TxRingPtr, (u32) xemacpsif->tx_bdspace,
+                       (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT,
+                                XLWIP_CONFIG_N_TX_DESC);
+       XEmacPs_BdRingClone(TxRingPtr, &BdTemplate, XEMACPS_SEND);
+}
+
+
+XStatus init_dma(struct xemac_s *xemac)
+{
+       XEmacPs_Bd BdTemplate;
+       XEmacPs_BdRing *RxRingPtr, *TxRingPtr;
+       XEmacPs_Bd *rxbd;
+       struct pbuf *p;
+       XStatus Status;
+       int i;
+       unsigned int BdIndex;
+       char *endAdd = (char *) &_end;
+       /*
+        * Align the BD starte address to 1 MB boundary.
+        */
+       char *endAdd_aligned = (char *)(((int)endAdd + 0x100000) & (~0xFFFFF));
+       xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+       struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
+
+       /*
+        * The BDs need to be allocated in uncached memory. Hence the 1 MB
+        * address range that starts at address 0xFF00000 is made uncached
+        * by setting appropriate attributes in the translation table.
+        */
+       Xil_SetTlbAttributes((int)endAdd_aligned, 0xc02); // addr, attr
+
+       RxRingPtr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+       TxRingPtr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+       LWIP_DEBUGF(NETIF_DEBUG, ("RxRingPtr: 0x%08x\r\n", RxRingPtr));
+       LWIP_DEBUGF(NETIF_DEBUG, ("TxRingPtr: 0x%08x\r\n", TxRingPtr));
+
+       xemacpsif->rx_bdspace = (void *)endAdd_aligned;
+       /*
+        * We allocate 65536 bytes for Rx BDs which can accomodate a
+        * maximum of 8192 BDs which is much more than any application
+        * will ever need.
+        */
+       xemacpsif->tx_bdspace = (void *)(endAdd_aligned + 0x10000);
+
+       LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: 0x%08x\r\n", xemacpsif->rx_bdspace));
+       LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: 0x%08x\r\n", xemacpsif->tx_bdspace));
+
+       if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) {
+               xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors",
+                               __FILE__, __LINE__);
+               return XST_FAILURE;
+       }
+
+       /*
+        * Setup RxBD space.
+        *
+        * Setup a BD template for the Rx channel. This template will be copied to
+        * every RxBD. We will not have to explicitly set these again.
+        */
+       XEmacPs_BdClear(&BdTemplate);
+
+       /*
+        * Create the RxBD ring
+        */
+
+       Status = XEmacPs_BdRingCreate(RxRingPtr, (u32) xemacpsif->rx_bdspace,
+                               (u32) xemacpsif->rx_bdspace, BD_ALIGNMENT,
+                                    XLWIP_CONFIG_N_RX_DESC);
+
+       if (Status != XST_SUCCESS) {
+               LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n"));
+               return XST_FAILURE;
+       }
+
+       Status = XEmacPs_BdRingClone(RxRingPtr, &BdTemplate, XEMACPS_RECV);
+       if (Status != XST_SUCCESS) {
+               LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n"));
+               return XST_FAILURE;
+       }
+
+       XEmacPs_BdClear(&BdTemplate);
+       XEmacPs_BdSetStatus(&BdTemplate, XEMACPS_TXBUF_USED_MASK);
+       /*
+        * Create the TxBD ring
+        */
+       Status = XEmacPs_BdRingCreate(TxRingPtr, (u32) xemacpsif->tx_bdspace,
+                               (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT,
+                                    XLWIP_CONFIG_N_TX_DESC);
+
+       if (Status != XST_SUCCESS) {
+               return XST_FAILURE;
+       }
+
+       /* We reuse the bd template, as the same one will work for both rx and tx. */
+       Status = XEmacPs_BdRingClone(TxRingPtr, &BdTemplate, XEMACPS_SEND);
+       if (Status != XST_SUCCESS) {
+               return ERR_IF;
+       }
+
+       /*
+        * Allocate RX descriptors, 1 RxBD at a time.
+        */
+       for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) {
+               Status = XEmacPs_BdRingAlloc(RxRingPtr, 1, &rxbd);
+               if (Status != XST_SUCCESS) {
+                       LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n"));
+                       return ERR_IF;
+               }
+
+               p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+               if (!p) {
+#if LINK_STATS
+                       lwip_stats.link.memerr++;
+                       lwip_stats.link.drop++;
+#endif
+                       LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n"));
+                       return -1;
+               }
+
+               XEmacPs_BdSetAddressRx(rxbd, (u32)p->payload);
+
+               BdIndex = XEMACPS_BD_TO_INDEX(RxRingPtr, rxbd);
+               rx_pbufs_storage[BdIndex] = (int)p;
+
+               /* Enqueue to HW */
+               Status = XEmacPs_BdRingToHw(RxRingPtr, 1, rxbd);
+               if (Status != XST_SUCCESS) {
+                       LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n"));
+                       return XST_FAILURE;
+               }
+       }
+
+       /*
+        * Connect the device driver handler that will be called when an
+        * interrupt for the device occurs, the handler defined above performs
+        * the specific interrupt processing for the device.
+        */
+       XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
+                               (Xil_ExceptionHandler)XEmacPs_IntrHandler,
+                                               (void *)&xemacpsif->emacps);
+       /*
+        * Enable the interrupt for emacps.
+        */
+       XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr);
+       EmacIntrNum = (u32) xtopologyp->scugic_emac_intr;
+       return 0;
+}
+
+/*
+ * resetrx_on_no_rxdata():
+ *
+ * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata
+ * called by the user.
+ * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.
+ * Under heavy Rx traffic because of the HW bug there are times when the Rx path
+ * becomes unresponsive. The workaround for it is to check for the Rx path for
+ * traffic (by reading the stats registers regularly). If the stats register
+ * does not increment for sometime (proving no Rx traffic), the function resets
+ * the Rx data path.
+ *
+ */
+
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
+{
+       unsigned long regctrl;
+       unsigned long tempcntr;
+
+       tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
+       if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
+               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                               XEMACPS_NWCTRL_OFFSET);
+               regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                               XEMACPS_NWCTRL_OFFSET, regctrl);
+               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
+               regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
+       }
+       xemacpsif->last_rx_frms_cntr = tempcntr;
+}
+
+void FreeTxRxPBufs(void)
+{
+       int Index;
+       struct pbuf *p;
+
+       for (Index = 0; Index < XLWIP_CONFIG_N_TX_DESC; Index++) {
+               if (tx_pbufs_storage[Index] != 0) {
+                       p = (struct pbuf *)tx_pbufs_storage[Index];
+                       pbuf_free(p);
+                       tx_pbufs_storage[Index] = 0;
+               }
+       }
+
+       for (Index = 0; Index < XLWIP_CONFIG_N_RX_DESC; Index++) {
+               p = (struct pbuf *)rx_pbufs_storage[Index];
+               pbuf_free(p);
+
+       }
+}
+
+void FreeOnlyTxPBufs(void)
+{
+       int Index;
+       struct pbuf *p;
+
+       for (Index = 0; Index < XLWIP_CONFIG_N_TX_DESC; Index++) {
+               if (tx_pbufs_storage[Index] != 0) {
+                       p = (struct pbuf *)tx_pbufs_storage[Index];
+                       pbuf_free(p);
+                       tx_pbufs_storage[Index] = 0;
+               }
+       }
+}
+
+void EmacDisableIntr(void)
+{
+       XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, EmacIntrNum);
+}
+
+void EmacEnableIntr(void)
+{
+       XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, EmacIntrNum);
+}