]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/lwIP_Demo/lwIP_port/netif/xemacpsif_dma.c
Reorganise Zynq project after spitting lwIP example into a separate configuration.
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo / src / lwIP_Demo / lwIP_port / netif / xemacpsif_dma.c
1 /*
2  * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
3  *
4  * Xilinx, Inc.
5  * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
6  * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
7  * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
8  * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
9  * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
10  * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
11  * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
12  * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
13  * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
14  * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  */
18
19 #include "lwipopts.h"
20 #include "lwip/stats.h"
21 #include "lwip/sys.h"
22 #include "lwip/inet_chksum.h"
23
24 #include "netif/xadapter.h"
25 #include "netif/xemacpsif.h"
26 #include "xstatus.h"
27
28 #include "xlwipconfig.h"
29 #include "xparameters.h"
30 #include "xparameters_ps.h"
31 #include "xil_exception.h"
32 #include "xil_mmu.h"
33 #ifdef CONFIG_XTRACE
34 #include "xtrace.h"
35 #endif
36 #ifdef OS_IS_FREERTOS
37 #include "FreeRTOS.h"
38 #include "semphr.h"
39 #include "timers.h"
40 #endif
41
42 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
43  *** to run it on a PEEP board
44  ***/
45
46 #define INTC_BASE_ADDR          XPAR_SCUGIC_CPU_BASEADDR
47 #define INTC_DIST_BASE_ADDR     XPAR_SCUGIC_DIST_BASEADDR
48
49 /* Byte alignment of BDs */
50 #define BD_ALIGNMENT (XEMACPS_DMABD_MINIMUM_ALIGNMENT*2)
51
52 static int tx_pbufs_storage[XLWIP_CONFIG_N_TX_DESC];
53 static int rx_pbufs_storage[XLWIP_CONFIG_N_RX_DESC];
54
55 static int EmacIntrNum;
56 extern u8 _end;
57
58 #ifdef OS_IS_FREERTOS
59 extern BaseType_t xInsideISR;
60 #endif
61
62 #define XEMACPS_BD_TO_INDEX(ringptr, bdptr)                             \
63         (((u32)bdptr - (u32)(ringptr)->BaseBdAddr) / (ringptr)->Separation)
64
65
66 int is_tx_space_available(xemacpsif_s *emac)
67 {
68         XEmacPs_BdRing *txring;
69         int freecnt = 0;
70
71         txring = &(XEmacPs_GetTxRing(&emac->emacps));
72
73         /* tx space is available as long as there are valid BD's */
74         freecnt = XEmacPs_BdRingGetFreeCnt(txring);
75         return freecnt;
76 }
77
78 void process_sent_bds(XEmacPs_BdRing *txring)
79 {
80         XEmacPs_Bd *txbdset;
81         XEmacPs_Bd *CurBdPntr;
82         int n_bds;
83         XStatus Status;
84         int n_pbufs_freed = 0;
85         unsigned int BdIndex;
86         struct pbuf *p;
87         unsigned int *Temp;
88
89         while (1) {
90                 /* obtain processed BD's */
91                 n_bds = XEmacPs_BdRingFromHwTx(txring,
92                                                                 XLWIP_CONFIG_N_TX_DESC, &txbdset);
93                 if (n_bds == 0)  {
94                         return;
95                 }
96                 /* free the processed BD's */
97                 n_pbufs_freed = n_bds;
98                 CurBdPntr = txbdset;
99                 while (n_pbufs_freed > 0) {
100                         BdIndex = XEMACPS_BD_TO_INDEX(txring, CurBdPntr);
101                         Temp = (unsigned int *)CurBdPntr;
102                         *Temp = 0;
103                         Temp++;
104                         *Temp = 0x80000000;
105                         if (BdIndex == (XLWIP_CONFIG_N_TX_DESC - 1)) {
106                                 *Temp = 0xC0000000;
107                         }
108
109                         p = (struct pbuf *)tx_pbufs_storage[BdIndex];
110                         if(p != NULL) {
111                                 pbuf_free(p);
112                         }
113                         tx_pbufs_storage[BdIndex] = 0;
114                         CurBdPntr = XEmacPs_BdRingNext(txring, CurBdPntr);
115                         n_pbufs_freed--;
116                         dsb();
117                 }
118
119                 Status = XEmacPs_BdRingFree(txring, n_bds, txbdset);
120                 if (Status != XST_SUCCESS) {
121                         LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n"));
122                 }
123         }
124         return;
125 }
126
127 void emacps_send_handler(void *arg)
128 {
129         struct xemac_s *xemac;
130         xemacpsif_s   *xemacpsif;
131         XEmacPs_BdRing *TxRingPtr;
132         unsigned int regval;
133 #ifdef OS_IS_FREERTOS
134         xInsideISR++;
135 #endif
136         xemac = (struct xemac_s *)(arg);
137         xemacpsif = (xemacpsif_s *)(xemac->state);
138         TxRingPtr = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
139         regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
140         XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval);
141
142         /* If Transmit done interrupt is asserted, process completed BD's */
143         process_sent_bds(TxRingPtr);
144 #ifdef OS_IS_FREERTOS
145         xInsideISR--;
146 #endif
147 }
148
149 XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p)
150 {
151         struct pbuf *q;
152         int n_pbufs;
153         XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL;
154         XEmacPs_Bd *temp_txbd;
155         XStatus Status;
156         XEmacPs_BdRing *txring;
157         unsigned int BdIndex;
158         unsigned int lev;
159
160         lev = mfcpsr();
161         mtcpsr(lev | 0x000000C0);
162
163 #ifdef PEEP
164     while((XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
165                                                                         XEMACPS_TXSR_OFFSET)) & 0x08);
166 #endif
167         txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
168
169         /* first count the number of pbufs */
170         for (q = p, n_pbufs = 0; q != NULL; q = q->next)
171                 n_pbufs++;
172
173         /* obtain as many BD's */
174         Status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
175         if (Status != XST_SUCCESS) {
176                 mtcpsr(lev);
177                 LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
178                 return ERR_IF;
179         }
180
181         for(q = p, txbd = txbdset; q != NULL; q = q->next) {
182                 BdIndex = XEMACPS_BD_TO_INDEX(txring, txbd);
183                 if (tx_pbufs_storage[BdIndex] != 0) {
184                         mtcpsr(lev);
185                         LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
186                         return ERR_IF;
187                 }
188
189                 /* Send the data from the pbuf to the interface, one pbuf at a
190                    time. The size of the data in each pbuf is kept in the ->len
191                    variable. */
192                 Xil_DCacheFlushRange((unsigned int)q->payload, (unsigned)q->len);
193
194                 XEmacPs_BdSetAddressTx(txbd, (u32)q->payload);
195                 if (q->len > (XEMACPS_MAX_FRAME_SIZE - 18))
196                         XEmacPs_BdSetLength(txbd, (XEMACPS_MAX_FRAME_SIZE - 18) & 0x3FFF);
197                 else
198                         XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);
199
200                 tx_pbufs_storage[BdIndex] = (int)q;
201
202                 pbuf_ref(q);
203                 last_txbd = txbd;
204                 XEmacPs_BdClearLast(txbd);
205                 dsb();
206                 txbd = XEmacPs_BdRingNext(txring, txbd);
207         }
208         XEmacPs_BdSetLast(last_txbd);
209         dsb();
210         /* For fragmented packets, remember the 1st BD allocated for the 1st
211            packet fragment. The used bit for this BD should be cleared at the end
212            after clearing out used bits for other fragments. For packets without
213            just remember the allocated BD. */
214         temp_txbd = txbdset;
215         txbd = txbdset;
216         txbd = XEmacPs_BdRingNext(txring, txbd);
217         q = p->next;
218         for(; q != NULL; q = q->next) {
219                 XEmacPs_BdClearTxUsed(txbd);
220                 txbd = XEmacPs_BdRingNext(txring, txbd);
221         }
222         XEmacPs_BdClearTxUsed(temp_txbd);
223         dsb();
224
225         Status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
226         if (Status != XST_SUCCESS) {
227                 mtcpsr(lev);
228                 LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
229                 return ERR_IF;
230         }
231         dsb();
232         /* Start transmit */
233         XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
234         XEMACPS_NWCTRL_OFFSET,
235         (XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
236         XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));
237         dsb();
238         mtcpsr(lev);
239         return Status;
240 }
241
242 void setup_rx_bds(XEmacPs_BdRing *rxring)
243 {
244         XEmacPs_Bd *rxbd;
245         XStatus Status;
246         struct pbuf *p;
247         unsigned int FreeBds;
248         unsigned int BdIndex;
249         unsigned int *Temp;
250
251         FreeBds = XEmacPs_BdRingGetFreeCnt (rxring);
252         while (FreeBds > 0) {
253                 FreeBds--;
254                 Status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd);
255                 if (Status != XST_SUCCESS) {
256                         LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n"));
257                         return;
258                 }
259                 BdIndex = XEMACPS_BD_TO_INDEX(rxring, rxbd);
260                 Temp = (unsigned int *)rxbd;
261                 *Temp = 0;
262                 if (BdIndex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
263                         *Temp = 0x00000002;
264                 }
265                 Temp++;
266                 *Temp = 0;
267
268                 p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
269                 if (!p) {
270 #if LINK_STATS
271                         lwip_stats.link.memerr++;
272                         lwip_stats.link.drop++;
273 #endif
274                         LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n"));
275                         XEmacPs_BdRingUnAlloc(rxring, 1, rxbd);
276                         dsb();
277                         return;
278                 }
279                 XEmacPs_BdSetAddressRx(rxbd, (u32)p->payload);
280                 dsb();
281
282                 rx_pbufs_storage[BdIndex] = (int)p;
283                 Status = XEmacPs_BdRingToHw(rxring, 1, rxbd);
284                 if (Status != XST_SUCCESS) {
285                         LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
286                         if (Status == XST_DMA_SG_LIST_ERROR)
287                                 LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n"));
288                         else
289                         {
290                                 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"));
291                         }
292                         return;
293                 }
294         }
295 }
296
297 void emacps_recv_handler(void *arg)
298 {
299         struct pbuf *p;
300         XEmacPs_Bd *rxbdset, *CurBdPtr;
301         struct xemac_s *xemac;
302         xemacpsif_s *xemacpsif;
303         XEmacPs_BdRing *rxring;
304         volatile int bd_processed;
305         int rx_bytes, k;
306         unsigned int BdIndex;
307         unsigned int regval;
308
309         xemac = (struct xemac_s *)(arg);
310         xemacpsif = (xemacpsif_s *)(xemac->state);
311         rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
312
313 #ifdef OS_IS_FREERTOS
314         xInsideISR++;
315 #endif
316         /*
317          * If Reception done interrupt is asserted, call RX call back function
318          * to handle the processed BDs and then raise the according flag.
319          */
320         regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
321         XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval);
322
323         resetrx_on_no_rxdata(xemacpsif);
324
325         while(1) {
326
327                 bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
328
329                 if (bd_processed <= 0) {
330                         break;
331                 }
332
333                 for (k = 0, CurBdPtr=rxbdset; k < bd_processed; k++) {
334
335                         BdIndex = XEMACPS_BD_TO_INDEX(rxring, CurBdPtr);
336                         p = (struct pbuf *)rx_pbufs_storage[BdIndex];
337
338                         /*
339                          * Adjust the buffer size to the actual number of bytes received.
340                          */
341                         rx_bytes = XEmacPs_BdGetLength(CurBdPtr);
342                         pbuf_realloc(p, rx_bytes);
343                         Xil_DCacheInvalidateRange((unsigned int)p->payload, (unsigned)XEMACPS_MAX_FRAME_SIZE);
344                         /* store it in the receive queue,
345                          * where it'll be processed by a different handler
346                          */
347                         if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
348 #if LINK_STATS
349                                 lwip_stats.link.memerr++;
350                                 lwip_stats.link.drop++;
351 #endif
352                                 pbuf_free(p);
353                         } else {
354 #if !NO_SYS
355                                 sys_sem_signal(&xemac->sem_rx_data_available);
356 #endif
357                         }
358                         CurBdPtr = XEmacPs_BdRingNext( rxring, CurBdPtr);
359                 }
360                 /* free up the BD's */
361                 XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
362                 setup_rx_bds(rxring);
363         }
364
365 #ifdef OS_IS_FREERTOS
366         xInsideISR--;
367 #endif
368         return;
369 }
370
371 void clean_dma_txdescs(struct xemac_s *xemac)
372 {
373         XEmacPs_Bd BdTemplate;
374         XEmacPs_BdRing *TxRingPtr;
375         xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
376
377         TxRingPtr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
378
379         XEmacPs_BdClear(&BdTemplate);
380         XEmacPs_BdSetStatus(&BdTemplate, XEMACPS_TXBUF_USED_MASK);
381
382         /*
383          * Create the TxBD ring
384          */
385         XEmacPs_BdRingCreate(TxRingPtr, (u32) xemacpsif->tx_bdspace,
386                         (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT,
387                                  XLWIP_CONFIG_N_TX_DESC);
388         XEmacPs_BdRingClone(TxRingPtr, &BdTemplate, XEMACPS_SEND);
389 }
390
391
392 XStatus init_dma(struct xemac_s *xemac)
393 {
394         XEmacPs_Bd BdTemplate;
395         XEmacPs_BdRing *RxRingPtr, *TxRingPtr;
396         XEmacPs_Bd *rxbd;
397         struct pbuf *p;
398         XStatus Status;
399         int i;
400         unsigned int BdIndex;
401         char *endAdd = (char *) &_end;
402         /*
403          * Align the BD starte address to 1 MB boundary.
404          */
405         char *endAdd_aligned = (char *)(((int)endAdd + 0x100000) & (~0xFFFFF));
406         xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
407         struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
408
409         /*
410          * The BDs need to be allocated in uncached memory. Hence the 1 MB
411          * address range that starts at address 0xFF00000 is made uncached
412          * by setting appropriate attributes in the translation table.
413          */
414         Xil_SetTlbAttributes((int)endAdd_aligned, 0xc02); // addr, attr
415
416         RxRingPtr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
417         TxRingPtr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
418         LWIP_DEBUGF(NETIF_DEBUG, ("RxRingPtr: 0x%08x\r\n", RxRingPtr));
419         LWIP_DEBUGF(NETIF_DEBUG, ("TxRingPtr: 0x%08x\r\n", TxRingPtr));
420
421         xemacpsif->rx_bdspace = (void *)endAdd_aligned;
422         /*
423          * We allocate 65536 bytes for Rx BDs which can accomodate a
424          * maximum of 8192 BDs which is much more than any application
425          * will ever need.
426          */
427         xemacpsif->tx_bdspace = (void *)(endAdd_aligned + 0x10000);
428
429         LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: 0x%08x\r\n", xemacpsif->rx_bdspace));
430         LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: 0x%08x\r\n", xemacpsif->tx_bdspace));
431
432         if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) {
433                 xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors",
434                                 __FILE__, __LINE__);
435                 return XST_FAILURE;
436         }
437
438         /*
439          * Setup RxBD space.
440          *
441          * Setup a BD template for the Rx channel. This template will be copied to
442          * every RxBD. We will not have to explicitly set these again.
443          */
444         XEmacPs_BdClear(&BdTemplate);
445
446         /*
447          * Create the RxBD ring
448          */
449
450         Status = XEmacPs_BdRingCreate(RxRingPtr, (u32) xemacpsif->rx_bdspace,
451                                 (u32) xemacpsif->rx_bdspace, BD_ALIGNMENT,
452                                      XLWIP_CONFIG_N_RX_DESC);
453
454         if (Status != XST_SUCCESS) {
455                 LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n"));
456                 return XST_FAILURE;
457         }
458
459         Status = XEmacPs_BdRingClone(RxRingPtr, &BdTemplate, XEMACPS_RECV);
460         if (Status != XST_SUCCESS) {
461                 LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n"));
462                 return XST_FAILURE;
463         }
464
465         XEmacPs_BdClear(&BdTemplate);
466         XEmacPs_BdSetStatus(&BdTemplate, XEMACPS_TXBUF_USED_MASK);
467         /*
468          * Create the TxBD ring
469          */
470         Status = XEmacPs_BdRingCreate(TxRingPtr, (u32) xemacpsif->tx_bdspace,
471                                 (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT,
472                                      XLWIP_CONFIG_N_TX_DESC);
473
474         if (Status != XST_SUCCESS) {
475                 return XST_FAILURE;
476         }
477
478         /* We reuse the bd template, as the same one will work for both rx and tx. */
479         Status = XEmacPs_BdRingClone(TxRingPtr, &BdTemplate, XEMACPS_SEND);
480         if (Status != XST_SUCCESS) {
481                 return ERR_IF;
482         }
483
484         /*
485          * Allocate RX descriptors, 1 RxBD at a time.
486          */
487         for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) {
488                 Status = XEmacPs_BdRingAlloc(RxRingPtr, 1, &rxbd);
489                 if (Status != XST_SUCCESS) {
490                         LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n"));
491                         return ERR_IF;
492                 }
493
494                 p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
495                 if (!p) {
496 #if LINK_STATS
497                         lwip_stats.link.memerr++;
498                         lwip_stats.link.drop++;
499 #endif
500                         LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n"));
501                         return -1;
502                 }
503
504                 XEmacPs_BdSetAddressRx(rxbd, (u32)p->payload);
505
506                 BdIndex = XEMACPS_BD_TO_INDEX(RxRingPtr, rxbd);
507                 rx_pbufs_storage[BdIndex] = (int)p;
508
509                 /* Enqueue to HW */
510                 Status = XEmacPs_BdRingToHw(RxRingPtr, 1, rxbd);
511                 if (Status != XST_SUCCESS) {
512                         LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n"));
513                         return XST_FAILURE;
514                 }
515         }
516
517         /*
518          * Connect the device driver handler that will be called when an
519          * interrupt for the device occurs, the handler defined above performs
520          * the specific interrupt processing for the device.
521          */
522         XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
523                                 (Xil_ExceptionHandler)XEmacPs_IntrHandler,
524                                                 (void *)&xemacpsif->emacps);
525         /*
526          * Enable the interrupt for emacps.
527          */
528         XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr);
529         EmacIntrNum = (u32) xtopologyp->scugic_emac_intr;
530         return 0;
531 }
532
533 /*
534  * resetrx_on_no_rxdata():
535  *
536  * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata
537  * called by the user.
538  * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.
539  * Under heavy Rx traffic because of the HW bug there are times when the Rx path
540  * becomes unresponsive. The workaround for it is to check for the Rx path for
541  * traffic (by reading the stats registers regularly). If the stats register
542  * does not increment for sometime (proving no Rx traffic), the function resets
543  * the Rx data path.
544  *
545  */
546
547 void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
548 {
549         unsigned long regctrl;
550         unsigned long tempcntr;
551
552         tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
553         if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
554                 regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
555                                 XEMACPS_NWCTRL_OFFSET);
556                 regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
557                 XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
558                                 XEMACPS_NWCTRL_OFFSET, regctrl);
559                 regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
560                 regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
561                 XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
562         }
563         xemacpsif->last_rx_frms_cntr = tempcntr;
564 }
565
566 void FreeTxRxPBufs(void)
567 {
568         int Index;
569         struct pbuf *p;
570
571         for (Index = 0; Index < XLWIP_CONFIG_N_TX_DESC; Index++) {
572                 if (tx_pbufs_storage[Index] != 0) {
573                         p = (struct pbuf *)tx_pbufs_storage[Index];
574                         pbuf_free(p);
575                         tx_pbufs_storage[Index] = 0;
576                 }
577         }
578
579         for (Index = 0; Index < XLWIP_CONFIG_N_RX_DESC; Index++) {
580                 p = (struct pbuf *)rx_pbufs_storage[Index];
581                 pbuf_free(p);
582
583         }
584 }
585
586 void FreeOnlyTxPBufs(void)
587 {
588         int Index;
589         struct pbuf *p;
590
591         for (Index = 0; Index < XLWIP_CONFIG_N_TX_DESC; Index++) {
592                 if (tx_pbufs_storage[Index] != 0) {
593                         p = (struct pbuf *)tx_pbufs_storage[Index];
594                         pbuf_free(p);
595                         tx_pbufs_storage[Index] = 0;
596                 }
597         }
598 }
599
600 void EmacDisableIntr(void)
601 {
602         XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, EmacIntrNum);
603 }
604
605 void EmacEnableIntr(void)
606 {
607         XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, EmacIntrNum);
608 }