コード例 #1
0
ファイル: xemacliteif.c プロジェクト: AlexShiLucky/freertos
/*
 * low_level_output():
 *
 * Should do the actual transmission of the packet. The packet is
 * contained in the pbuf that is passed to the function. This pbuf
 * might be chained.
 *
 */
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
	SYS_ARCH_DECL_PROTECT(lev);
	struct xemac_s *xemac = (struct xemac_s *)(netif->state);
	xemacliteif_s *xemacliteif = (xemacliteif_s *)(xemac->state);
	XEmacLite *instance = xemacliteif->instance;
	struct pbuf *q;

	SYS_ARCH_PROTECT(lev);

	/* check if space is available to send */
        if (XEmacLite_TxBufferAvailable(instance) == TRUE) {
		if (pq_qlength(xemacliteif->send_q)) {  	/* send backlog */
			_unbuffered_low_level_output(instance, (struct pbuf *)pq_dequeue(xemacliteif->send_q));
		} else { 				/* send current */
			_unbuffered_low_level_output(instance, p);
			SYS_ARCH_UNPROTECT(lev);
			return ERR_OK;
		}
	}

	/* if we cannot send the packet immediately, then make a copy of the whole packet
	 * into a separate pbuf and store it in send_q. We cannot enqueue the pbuf as is
	 * since parts of the pbuf may be modified inside lwIP.
	 */
	q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL);
	if (!q) {
#if LINK_STATS
		lwip_stats.link.drop++;
#endif
		SYS_ARCH_UNPROTECT(lev);
		return ERR_MEM;
	}

	for (q->len = 0; p; p = p->next) {
		memcpy(q->payload + q->len, p->payload, p->len);
		q->len += p->len;
	}
	if (pq_enqueue(xemacliteif->send_q, (void *)q) < 0) {
#if LINK_STATS
		lwip_stats.link.drop++;
#endif
		SYS_ARCH_UNPROTECT(lev);
		return ERR_MEM;
	}

	SYS_ARCH_UNPROTECT(lev);

	return ERR_OK;
}
コード例 #2
0
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
	SYS_ARCH_DECL_PROTECT(lev);
        err_t err;

	struct xemac_s *xemac = (struct xemac_s *)(netif->state);
	xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);

	SYS_ARCH_PROTECT(lev);

	/* check if space is available to send */
        if (is_tx_space_available(xlltemacif)) {
		_unbuffered_low_level_output(xlltemacif, p);
		err = ERR_OK;
	} else {
#if LINK_STATS
		lwip_stats.link.drop++;
#endif
		print("pack dropped, no space\r\n");
		err = ERR_MEM;
	}

	SYS_ARCH_UNPROTECT(lev);
	return err;
}
コード例 #3
0
static void
xemacif_send_handler(void *arg) {
	struct xemac_s *xemac = (struct xemac_s *)(arg);
	xemacliteif_s *xemacliteif = (xemacliteif_s *)(xemac->state);
	XEmacLite *instance = xemacliteif->instance;
	struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];

	XIntc_AckIntr(xtopologyp->intc_baseaddr, 1 << xtopologyp->intc_emac_intr);

	if (pq_qlength(xemacliteif->send_q) && (XEmacLite_TxBufferAvailable(instance) == XTRUE)) {
		struct pbuf *p = pq_dequeue(xemacliteif->send_q);
		_unbuffered_low_level_output(instance, p);
		pbuf_free(p);
	}
}
コード例 #4
0
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
        SYS_ARCH_DECL_PROTECT(lev);
        err_t err;
        struct xemac_s *xemac = (struct xemac_s *)(netif->state);
        xaxiemacif_s *xaxiemacif = (xaxiemacif_s *)(xemac->state);

	/*
	 * With AXI Ethernet on Zynq, we observed unexplained delays for
	 * BD Status update. As a result, we are hitting a condition where 
	 * there are no BDs free to transmit packets. So, we have added
	 * this logic where we look for the status update in a definite
	 * loop.
	 */
	XAxiDma_BdRing *txring = XAxiDma_GetTxRing(&xaxiemacif->axidma);
        int count = 100;

        SYS_ARCH_PROTECT(lev);

        while (count) {

        	/* check if space is available to send */
        	if (is_tx_space_available(xaxiemacif)) {
                	_unbuffered_low_level_output(xaxiemacif, p);
                	err = ERR_OK;
                	break;
        	} else {
#if LINK_STATS
                	lwip_stats.link.drop++;
#endif
                	process_sent_bds(txring);
                	count--;
        	}
        }

	if (count == 0) {
		print("pack dropped, no space\r\n");
		err = ERR_MEM;
	}

        SYS_ARCH_UNPROTECT(lev);
        return err;
}