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;
}
Beispiel #2
0
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;
}