void emacps_recv_handler(void *arg) { struct pbuf *p; XEmacPs_Bd *rxbdset, *curbdptr; struct xemac_s *xemac; xemacpsif_s *xemacpsif; XEmacPs_BdRing *rxring; volatile s32_t bd_processed; s32_t rx_bytes, k; u32_t bdindex; u32_t 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); /* 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; }
int emacps_check_rx( xemacpsif_s *xemacpsif ) { NetworkBufferDescriptor_t *pxBuffer; int rx_bytes; volatile int msgCount = 0; int head = xemacpsif->rxHead; /* There seems to be an issue (SI# 692601), see comments below. */ resetrx_on_no_rxdata(xemacpsif); /* This FreeRTOS+TCP driver shall be compiled with the option "ipconfigUSE_LINKED_RX_MESSAGES" enabled. It allows the driver to send a chain of RX messages within one message to the IP-task. */ for( ; ; ) { if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) || ( pxDMA_rx_buffers[ head ] == NULL ) ) { break; } pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ]; /* Just avoiding to use or refer to the same buffer again */ pxDMA_rx_buffers[ head ] = NULL; /* * Adjust the buffer size to the actual number of bytes received. */ rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK; pxBuffer->xDataLength = rx_bytes; if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) { Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes ); } /* store it in the receive queue, where it'll be processed by a different handler. */ iptraceNETWORK_INTERFACE_RECEIVE(); pxBuffer->pxNextBuffer = NULL; if( ethMsg == NULL ) { // Becomes the first message ethMsg = pxBuffer; } else if( ethLast != NULL ) { // Add to the tail ethLast->pxNextBuffer = pxBuffer; } ethLast = pxBuffer; msgCount++; if( ++head == ipconfigNIC_N_RX_DESC ) { head = 0; } } xemacpsif->rxHead = head; if( ethMsg != NULL ) { passEthMessages( ); } if( msgCount != 0 ) { /* Some packets (network buffer descriptors) have been passed to the IP-stack. Now allocate new descriptors and put them in place. */ emacps_set_rx_buffers( xemacpsif, msgCount ); } return msgCount; }