Esempio n. 1
0
int eth_rx(void)
{
	struct udevice *current;
	uchar *packet;
	int flags;
	int ret;
	int i;

	current = eth_get_dev();
	if (!current)
		return -ENODEV;

	if (!device_active(current))
		return -EINVAL;

	/* Process up to 32 packets at one time */
	flags = ETH_RECV_CHECK_DEVICE;
	for (i = 0; i < 32; i++) {
		ret = eth_get_ops(current)->recv(current, flags, &packet);
		flags = 0;
		if (ret > 0)
			net_process_received_packet(packet, ret);
		if (ret >= 0 && eth_get_ops(current)->free_pkt)
			eth_get_ops(current)->free_pkt(current, packet, ret);
		if (ret <= 0)
			break;
	}
	if (ret == -EAGAIN)
		ret = 0;
	if (ret < 0) {
		/* We cannot completely return the error at present */
		debug("%s: recv() returned error %d\n", __func__, ret);
	}
	return ret;
}
Esempio n. 2
0
static int bcm_sf2_eth_receive(struct eth_device *dev)
{
	struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma);
	uint8_t *buf = (uint8_t *)net_rx_packets[0];
	int rcvlen;
	int rc = 0;
	int i = 0;

	while (1) {
		/* Poll Rx queue to get a packet */
		rcvlen = dma->check_rx_done(dma, buf);
		if (rcvlen < 0) {
			/* No packet received */
			rc = -1;
			debug("\nNO More Rx\n");
			break;
		} else if ((rcvlen == 0) || (rcvlen > RX_BUF_SIZE)) {
			error("%s: Wrong Ethernet packet size (%d B), skip!\n",
			      __func__, rcvlen);
			break;
		} else {
			debug("recieved\n");

			/* Forward received packet to uboot network handler */
			net_process_received_packet(buf, rcvlen);

			if (++i >= PKTBUFSRX)
				i = 0;
			buf = net_rx_packets[i];
		}
	}

	return rc;
}
Esempio n. 3
0
/* Get a data block via Ethernet */
static int cs8900_recv(struct eth_device *dev)
{
	int i;
	u16 rxlen;
	u16 *addr;
	u16 status;

	struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);

	status = get_reg(dev, PP_RER);

	if ((status & PP_RER_RxOK) == 0)
		return 0;

	status = REG_READ(&priv->regs->rtdata);
	rxlen = REG_READ(&priv->regs->rtdata);

	if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
		debug("packet too big!\n");
	for (addr = (u16 *)net_rx_packets[0], i = rxlen >> 1; i > 0; i--)
		*addr++ = REG_READ(&priv->regs->rtdata);
	if (rxlen & 1)
		*addr++ = REG_READ(&priv->regs->rtdata);

	/* Pass the packet up to the protocol layers. */
	net_process_received_packet(net_rx_packets[0], rxlen);
	return rxlen;
}
Esempio n. 4
0
File: uec.c Progetto: eesuda/u-boot
static int uec_recv(struct eth_device* dev)
{
	uec_private_t		*uec = dev->priv;
	volatile qe_bd_t	*bd;
	u16			status;
	u16			len;
	u8			*data;

	bd = uec->rxBd;
	status = bd->status;

	while (!(status & RxBD_EMPTY)) {
		if (!(status & RxBD_ERROR)) {
			data = BD_DATA(bd);
			len = BD_LENGTH(bd);
			net_process_received_packet(data, len);
		} else {
			printf("%s: Rx error\n", dev->name);
		}
		status &= BD_CLEAN;
		BD_LENGTH_SET(bd, 0);
		BD_STATUS_SET(bd, status | RxBD_EMPTY);
		BD_ADVANCE(bd, status, uec->p_rx_bd_ring);
		status = bd->status;
	}
	uec->rxBd = bd;

	return 1;
}
static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
			 const struct dpaa_fd *fd)
{
	u64 fd_addr;
	uint16_t fd_offset;
	uint32_t fd_length;
	struct ldpaa_fas *fas;
	uint32_t status, err;
	u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
	u32 time_start;
	struct qbman_release_desc releasedesc;
	struct qbman_swp *swp = dflt_dpio->sw_portal;

	fd_addr = ldpaa_fd_get_addr(fd);
	fd_offset = ldpaa_fd_get_offset(fd);
	fd_length = ldpaa_fd_get_len(fd);

	debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);

	if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
		/* Read the frame annotation status word and check for errors */
		fas = (struct ldpaa_fas *)
				((uint8_t *)(fd_addr) +
				dflt_dpni->buf_layout.private_data_size);
		status = le32_to_cpu(fas->status);
		if (status & LDPAA_ETH_RX_ERR_MASK) {
			printf("Rx frame error(s): 0x%08x\n",
			       status & LDPAA_ETH_RX_ERR_MASK);
			goto error;
		} else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
			printf("Unsupported feature in bitmask: 0x%08x\n",
			       status & LDPAA_ETH_RX_UNSUPP_MASK);
			goto error;
		}
	}

	debug("Rx frame: To Upper layer\n");
	net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
				    fd_length);

error:
	flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
	qbman_release_desc_clear(&releasedesc);
	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
	time_start = get_timer(0);
	do {
		/* Release buffer into the QBMAN */
		err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
	} while (get_timer(time_start) < timeo && err == -EBUSY);

	if (err == -EBUSY)
		printf("Rx frame: QBMAN buffer release fails\n");

	return;
}
Esempio n. 6
0
void uboot_push_packet_len(int len) {
    PRINTK("pushed len = %d\n", len);
    if (len >= 2000) {
        printf("NE2000: packet too big\n");
        return;
    }
    dp83902a_recv(&pbuf[0], len);

    /*Just pass it to the upper layer*/
    net_process_received_packet(&pbuf[0], len);
}
Esempio n. 7
0
static int fm_eth_recv(struct eth_device *dev)
{
	struct fm_eth *fm_eth;
	struct fm_port_global_pram *pram;
	struct fm_port_bd *rxbd, *rxbd_base;
	u16 status, len;
	u32 buf_lo, buf_hi;
	u8 *data;
	u16 offset_out;
	int ret = 1;

	fm_eth = (struct fm_eth *)dev->priv;
	pram = fm_eth->rx_pram;
	rxbd = fm_eth->cur_rxbd;
	status = muram_readw(&rxbd->status);

	while (!(status & RxBD_EMPTY)) {
		if (!(status & RxBD_ERROR)) {
			buf_hi = muram_readw(&rxbd->buf_ptr_hi);
			buf_lo = in_be32(&rxbd->buf_ptr_lo);
			data = (u8 *)((ulong)(buf_hi << 16) << 16 | buf_lo);
			len = muram_readw(&rxbd->len);
			net_process_received_packet(data, len);
		} else {
			printf("%s: Rx error\n", dev->name);
			ret = 0;
		}

		/* clear the RxBDs */
		muram_writew(&rxbd->status, RxBD_EMPTY);
		muram_writew(&rxbd->len, 0);
		sync();

		/* advance RxBD */
		rxbd++;
		rxbd_base = (struct fm_port_bd *)fm_eth->rx_bd_ring;
		if (rxbd >= (rxbd_base + RX_BD_RING_SIZE))
			rxbd = rxbd_base;
		/* read next status */
		status = muram_readw(&rxbd->status);

		/* update RxQD */
		offset_out = muram_readw(&pram->rxqd.offset_out);
		offset_out += sizeof(struct fm_port_bd);
		if (offset_out >= muram_readw(&pram->rxqd.bd_ring_size))
			offset_out = 0;
		muram_writew(&pram->rxqd.offset_out, offset_out);
		sync();
	}
	fm_eth->cur_rxbd = (void *)rxbd;

	return ret;
}
int ll_temac_recv_fifo(struct eth_device *dev)
{
	int i, length = 0;
	u32 *buf = (u32 *)net_rx_packets[0];
	struct ll_temac *ll_temac = dev->priv;
	struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;

	if (in_be32(&fifo_ctrl->isr) & LL_FIFO_ISR_RC) {

		/* reset isr */
		out_be32(&fifo_ctrl->isr, ~0UL);

		/*
		 * MAYBE here:
		 *   while (fifo_ctrl->isr);
		 */

		/*
		 * The length is written (into RLR) by the XPS LL FIFO
		 * when the packet is received across the RX LocalLink
		 * interface and the receive data FIFO had enough
		 * locations that all of the packet data has been saved.
		 * The RLR should only be read when a receive packet is
		 * available for processing (the receive occupancy is
		 * not zero). Once the RLR is read, the receive packet
		 * data should be read from the receive data FIFO before
		 * the RLR is read again.
		 *
		 * [F] page 17, Receive Length Register (RLR)
		 */
		if (in_be32(&fifo_ctrl->rdfo) & LL_FIFO_RDFO_MASK) {
			length = in_be32(&fifo_ctrl->rlf) & LL_FIFO_RLF_MASK;
		} else {
			printf("%s: Got error, no receive occupancy\n",
					__func__);
			return -1;
		}

		if (length > PKTSIZE_ALIGN) {
			printf("%s: Got error, receive package too big (%i)\n",
					__func__, length);
			ll_temac_reset_fifo(dev);
			return -1;
		}

		for (i = 0; i < length; i += 4)
			*buf++ = in_be32(&fifo_ctrl->rdfd);

		net_process_received_packet(net_rx_packets[0], length);
	}

	return 0;
}
Esempio n. 9
0
/**************************************************************************
RECV - Receive a frame
***************************************************************************/
static int rtl_recv(struct eth_device *dev)
{
	/* return true if there's an ethernet packet ready to read */
	/* nic->packet should contain data on return */
	/* nic->packetlen should contain length of data */
	int cur_rx;
	int length = 0;

#ifdef DEBUG_RTL8169_RX
	printf ("%s\n", __FUNCTION__);
#endif
	ioaddr = dev->iobase;

	cur_rx = tpc->cur_rx;

	rtl_inval_rx_desc(&tpc->RxDescArray[cur_rx]);

	if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) {
		if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) {
			unsigned char rxdata[RX_BUF_LEN];
			length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx].
						status) & 0x00001FFF) - 4;

			rtl_inval_buffer(tpc->RxBufferRing[cur_rx], length);
			memcpy(rxdata, tpc->RxBufferRing[cur_rx], length);

			if (cur_rx == NUM_RX_DESC - 1)
				tpc->RxDescArray[cur_rx].status =
					cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE);
			else
				tpc->RxDescArray[cur_rx].status =
					cpu_to_le32(OWNbit + RX_BUF_SIZE);
			tpc->RxDescArray[cur_rx].buf_addr =
				cpu_to_le32(bus_to_phys(tpc->RxBufferRing[cur_rx]));
			rtl_flush_rx_desc(&tpc->RxDescArray[cur_rx]);

			net_process_received_packet(rxdata, length);
		} else {
			puts("Error Rx");
		}
		cur_rx = (cur_rx + 1) % NUM_RX_DESC;
		tpc->cur_rx = cur_rx;
		return 1;

	} else {
		ushort sts = RTL_R8(IntrStatus);
		RTL_W8(IntrStatus, sts & ~(TxErr | RxErr | SYSErr));
		udelay(100);	/* wait */
	}
	tpc->cur_rx = cur_rx;
	return (0);		/* initially as this is called to flush the input */
}
Esempio n. 10
0
/*
 * mcs7830_recv() - network interface's recv callback
 * @eth:	network device to receive frames from
 * Return: zero upon success, negative upon error
 *
 * this routine checks for available ethernet frames that the network
 * interface might have received, and notifies the network stack
 */
static int mcs7830_recv(struct eth_device *eth)
{
	struct ueth_data *dev;
	ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, MCS7830_RX_URB_SIZE);
	int rc, wantlen, gotlen;
	uint8_t sts;

	debug("%s()\n", __func__);
	dev = eth->priv;

	/* fetch input data from the adapter */
	wantlen = MCS7830_RX_URB_SIZE;
	rc = usb_bulk_msg(dev->pusb_dev,
			  usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
			  &buf[0], wantlen, &gotlen,
			  USBCALL_TIMEOUT);
	debug("%s() RX want len %d, got len %d, rc %d\n",
	      __func__, wantlen, gotlen, rc);
	if (rc != 0) {
		error("RX: failed to receive\n");
		return rc;
	}
	if (gotlen > wantlen) {
		error("RX: got too many bytes (%d)\n", gotlen);
		return -EIO;
	}

	/*
	 * the bulk message that we received from USB contains exactly
	 * one ethernet frame and a trailing status byte
	 */
	if (gotlen < sizeof(sts))
		return -EIO;
	gotlen -= sizeof(sts);
	sts = buf[gotlen];

	if (sts == STAT_RX_FRAME_CORRECT) {
		debug("%s() got a frame, len=%d\n", __func__, gotlen);
		net_process_received_packet(buf, gotlen);
		return 0;
	}

	debug("RX: frame error (sts 0x%02X, %s %s %s %s %s)\n",
	      sts,
	      (sts & STAT_RX_LARGE_FRAME) ? "large" : "-",
	      (sts & STAT_RX_LENGTH_ERROR) ?  "length" : "-",
	      (sts & STAT_RX_SHORT_FRAME) ? "short" : "-",
	      (sts & STAT_RX_CRC_ERROR) ? "crc" : "-",
	      (sts & STAT_RX_ALIGNMENT_ERROR) ?  "align" : "-");
	return -EIO;
}
Esempio n. 11
0
/*
 * mcs7830_recv() - network interface's recv callback
 * @eth:	network device to receive frames from
 * Return: zero upon success, negative upon error
 *
 * this routine checks for available ethernet frames that the network
 * interface might have received, and notifies the network stack
 */
static int mcs7830_recv(struct eth_device *eth)
{
	ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, MCS7830_RX_URB_SIZE);
	struct ueth_data *ueth = eth->priv;
	int len;

	len = mcs7830_recv_common(ueth, buf);
	if (len >= 0) {
		net_process_received_packet(buf, len);
		return 0;
	}

	return len;
}
Esempio n. 12
0
/*
 * This function handles receipt of a packet from the network
 */
static int keystone2_eth_rcv_packet(struct eth_device *dev)
{
	void *hd;
	int  pkt_size;
	u32  *pkt;

	hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size);
	if (hd == NULL)
		return 0;

	net_process_received_packet((uchar *)pkt, pkt_size);

	ksnav_release_rxhd(&netcp_pktdma, hd);

	return pkt_size;
}
Esempio n. 13
0
static int macb_recv(struct eth_device *netdev)
{
	struct macb_device *macb = to_macb(netdev);
	uchar *packet;
	int length;

	macb->wrapped = false;
	for (;;) {
		macb->next_rx_tail = macb->rx_tail;
		length = _macb_recv(macb, &packet);
		if (length >= 0) {
			net_process_received_packet(packet, length);
			reclaim_rx_buffers(macb, macb->next_rx_tail);
		} else if (length < 0) {
			return length;
		}
	}
}
Esempio n. 14
0
/* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
static int zynq_gem_recv(struct eth_device *dev)
{
	int frame_len;
	struct zynq_gem_priv *priv = dev->priv;
	struct emac_bd *current_bd = &priv->rx_bd[priv->rxbd_current];
	struct emac_bd *first_bd;

	if (!(current_bd->addr & ZYNQ_GEM_RXBUF_NEW_MASK))
		return 0;

	if (!(current_bd->status &
			(ZYNQ_GEM_RXBUF_SOF_MASK | ZYNQ_GEM_RXBUF_EOF_MASK))) {
		printf("GEM: SOF or EOF not set for last buffer received!\n");
		return 0;
	}

	frame_len = current_bd->status & ZYNQ_GEM_RXBUF_LEN_MASK;
	if (frame_len) {
		unsigned long addr = current_bd->addr & ZYNQ_GEM_RXBUF_ADD_MASK;
		addr &= ~(ARCH_DMA_MINALIGN - 1);

		net_process_received_packet((u8 *)addr, frame_len);

		if (current_bd->status & ZYNQ_GEM_RXBUF_SOF_MASK)
			priv->rx_first_buf = priv->rxbd_current;
		else {
			current_bd->addr &= ~ZYNQ_GEM_RXBUF_NEW_MASK;
			current_bd->status = 0xF0000000; /* FIXME */
		}

		if (current_bd->status & ZYNQ_GEM_RXBUF_EOF_MASK) {
			first_bd = &priv->rx_bd[priv->rx_first_buf];
			first_bd->addr &= ~ZYNQ_GEM_RXBUF_NEW_MASK;
			first_bd->status = 0xF0000000;
		}

		if ((++priv->rxbd_current) >= RX_BUF)
			priv->rxbd_current = 0;
	}

	return frame_len;
}
Esempio n. 15
0
int sh_eth_recv(struct eth_device *dev)
{
	struct sh_eth_dev *eth = dev->priv;
	int port = eth->port, len = 0;
	struct sh_eth_info *port_info = &eth->port_info[port];
	uchar *packet;

	/* Check if the rx descriptor is ready */
	invalidate_cache(port_info->rx_desc_cur, sizeof(struct rx_desc_s));
	if (!(port_info->rx_desc_cur->rd0 & RD_RACT)) {
		/* Check for errors */
		if (!(port_info->rx_desc_cur->rd0 & RD_RFE)) {
			len = port_info->rx_desc_cur->rd1 & 0xffff;
			packet = (uchar *)
				ADDR_TO_P2(port_info->rx_desc_cur->rd2);
			invalidate_cache(packet, len);
			net_process_received_packet(packet, len);
		}

		/* Make current descriptor available again */
		if (port_info->rx_desc_cur->rd0 & RD_RDLE)
			port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE;
		else
			port_info->rx_desc_cur->rd0 = RD_RACT;

		flush_cache_wback(port_info->rx_desc_cur,
				  sizeof(struct rx_desc_s));

		/* Point to the next descriptor */
		port_info->rx_desc_cur++;
		if (port_info->rx_desc_cur >=
		    port_info->rx_desc_base + NUM_RX_DESC)
			port_info->rx_desc_cur = port_info->rx_desc_base;
	}

	/* Restart the receiver if disabled */
	if (!(sh_eth_read(eth, EDRRR) & EDRRR_R))
		sh_eth_write(eth, EDRRR_R, EDRRR);

	return len;
}
static int sec_rx(struct eth_device *dev)
{
    int length;

    for (;;)
    {
	if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
	    length = -1;
	    break;     /* nothing received - leave for() loop */
	}

	length = rtx->rxbd[rxIdx].cbd_datlen;

	if (rtx->rxbd[rxIdx].cbd_sc & 0x003f)
	{
	    printf("err: %x\n", rtx->rxbd[rxIdx].cbd_sc);
	}
	else
	{
	    /* Pass the packet up to the protocol layers. */
	    net_process_received_packet(net_rx_packets[rxIdx], length - 4);
	}


	/* Give the buffer back to the SCC. */
	rtx->rxbd[rxIdx].cbd_datlen = 0;

	/* wrap around buffer index when necessary */
	if ((rxIdx + 1) >= PKTBUFSRX) {
	    rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP |
					       BD_ENET_RX_EMPTY);
	    rxIdx = 0;
	}
	else {
	    rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
	    rxIdx++;
	}
    }
    return length;
}
Esempio n. 17
0
/*
 * Get a data block via Ethernet
 */
static int ftgmac100_recv(struct eth_device *dev)
{
	struct ftgmac100_data *priv = dev->priv;
	struct ftgmac100_rxdes *curr_des;
	unsigned short rxlen;

	curr_des = &priv->rxdes[priv->rx_index];

	if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
		return -1;

	if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
				FTGMAC100_RXDES0_CRC_ERR |
				FTGMAC100_RXDES0_FTL |
				FTGMAC100_RXDES0_RUNT |
				FTGMAC100_RXDES0_RX_ODD_NB)) {
		return -1;
	}

	rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);

	debug("%s(): RX buffer %d, %x received\n",
	       __func__, priv->rx_index, rxlen);

	/* invalidate d-cache */
	dma_map_single((void *)curr_des->rxdes2, rxlen, DMA_FROM_DEVICE);

	/* pass the packet up to the protocol layers. */
	net_process_received_packet((void *)curr_des->rxdes2, rxlen);

	/* release buffer to DMA */
	curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;

	priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;

	return 0;
}
Esempio n. 18
0
static int bfin_EMAC_recv(struct eth_device *dev)
{
	int length = 0;

	for (;;) {
		if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) {
			length = -1;
			break;
		}
		if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) {
			printf("Ethernet: rx dma overrun\n");
			break;
		}
		if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) {
			printf("Ethernet: rx error\n");
			break;
		}
		length = rxbuf[rxIdx]->StatusWord & 0x000007FF;
		if (length <= 4) {
			printf("Ethernet: bad frame\n");
			break;
		}

		debug("%s: len = %d\n", __func__, length - 4);

		net_rx_packets[rxIdx] = rxbuf[rxIdx]->FrmData->Dest;
		net_process_received_packet(net_rx_packets[rxIdx], length - 4);
		bfin_write_DMA1_IRQ_STATUS(DMA_DONE | DMA_ERR);
		rxbuf[rxIdx]->StatusWord = 0x00000000;
		if ((rxIdx + 1) >= PKTBUFSRX)
			rxIdx = 0;
		else
			rxIdx++;
	}

	return length;
}
static int au1x00_recv(struct eth_device* dev){
	volatile mac_fifo_t *fifo_rx =
		(volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS);

	int length;
	u32 status;

	for(;;){
		if(!(fifo_rx[next_rx].addr&RX_T_DONE)){
			/* Nothing has been received */
			return(-1);
		}

		status = fifo_rx[next_rx].status;

		length = status&0x3FFF;

		if(status&RX_ERROR){
			printf("Rx error 0x%x\n", status);
		} else {
			/* Pass the packet up to the protocol layers. */
			net_process_received_packet(net_rx_packets[next_rx],
						    length - 4);
		}

		fifo_rx[next_rx].addr =
			(virt_to_phys(net_rx_packets[next_rx])) | RX_DMA_ENABLE;

		next_rx++;
		if(next_rx>=NO_OF_FIFOS){
			next_rx=0;
		}
	} /* for */

	return(0); /* Does anyone use this? */
}
Esempio n. 20
0
/*
 * This function handles receipt of a packet from the network
 */
static int davinci_eth_rcv_packet (struct eth_device *dev)
{
	volatile emac_desc *rx_curr_desc;
	volatile emac_desc *curr_desc;
	volatile emac_desc *tail_desc;
	int status, ret = -1;

	rx_curr_desc = emac_rx_active_head;
	if (!rx_curr_desc)
		return 0;
	status = rx_curr_desc->pkt_flag_len;
	if ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0) {
		if (status & EMAC_CPPI_RX_ERROR_FRAME) {
			/* Error in packet - discard it and requeue desc */
			printf ("WARN: emac_rcv_pkt: Error in packet\n");
		} else {
			unsigned long tmp = (unsigned long)rx_curr_desc->buffer;
			unsigned short len =
				rx_curr_desc->buff_off_len & 0xffff;

			invalidate_dcache_range(tmp, tmp + ALIGN(len, PKTALIGN));
			net_process_received_packet(rx_curr_desc->buffer, len);
			ret = len;
		}

		/* Ack received packet descriptor */
		writel(BD_TO_HW((ulong)rx_curr_desc), &adap_emac->RX0CP);
		curr_desc = rx_curr_desc;
		emac_rx_active_head =
			(volatile emac_desc *) (HW_TO_BD(rx_curr_desc->next));

		if (status & EMAC_CPPI_EOQ_BIT) {
			if (emac_rx_active_head) {
				writel(BD_TO_HW((ulong)emac_rx_active_head),
				       &adap_emac->RX0HDP);
			} else {
				emac_rx_queue_active = 0;
				printf ("INFO:emac_rcv_packet: RX Queue not active\n");
			}
		}

		/* Recycle RX descriptor */
		rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
		rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
		rx_curr_desc->next = 0;

		if (emac_rx_active_head == 0) {
			printf ("INFO: emac_rcv_pkt: active queue head = 0\n");
			emac_rx_active_head = curr_desc;
			emac_rx_active_tail = curr_desc;
			if (emac_rx_queue_active != 0) {
				writel(BD_TO_HW((ulong)emac_rx_active_head),
				       &adap_emac->RX0HDP);
				printf ("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
				emac_rx_queue_active = 1;
			}
		} else {
			tail_desc = emac_rx_active_tail;
			emac_rx_active_tail = curr_desc;
			tail_desc->next = BD_TO_HW((ulong) curr_desc);
			status = tail_desc->pkt_flag_len;
			if (status & EMAC_CPPI_EOQ_BIT) {
				writel(BD_TO_HW((ulong)curr_desc),
				       &adap_emac->RX0HDP);
				status &= ~EMAC_CPPI_EOQ_BIT;
				tail_desc->pkt_flag_len = status;
			}
		}
		return (ret);
	}
	return (0);
}
Esempio n. 21
0
static int rtl_recv_common(pci_dev_t dev, unsigned long dev_iobase,
			   uchar **packetp)
#endif
{
	/* return true if there's an ethernet packet ready to read */
	/* nic->packet should contain data on return */
	/* nic->packetlen should contain length of data */
	int cur_rx;
	int length = 0;

#ifdef DEBUG_RTL8169_RX
	printf ("%s\n", __FUNCTION__);
#endif
	ioaddr = dev_iobase;

	cur_rx = tpc->cur_rx;

	rtl_inval_rx_desc(&tpc->RxDescArray[cur_rx]);

	if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) {
		if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) {
			length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx].
						status) & 0x00001FFF) - 4;

			rtl_inval_buffer(tpc->RxBufferRing[cur_rx], length);
			memcpy(rxdata, tpc->RxBufferRing[cur_rx], length);

			if (cur_rx == NUM_RX_DESC - 1)
				tpc->RxDescArray[cur_rx].status =
					cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE);
			else
				tpc->RxDescArray[cur_rx].status =
					cpu_to_le32(OWNbit + RX_BUF_SIZE);
#ifdef CONFIG_DM_ETH
			tpc->RxDescArray[cur_rx].buf_addr = cpu_to_le32(
				dm_pci_mem_to_phys(dev,
					(pci_addr_t)(unsigned long)
					tpc->RxBufferRing[cur_rx]));
#else
			tpc->RxDescArray[cur_rx].buf_addr = cpu_to_le32(
				pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)
				tpc->RxBufferRing[cur_rx]));
#endif
			rtl_flush_rx_desc(&tpc->RxDescArray[cur_rx]);
#ifdef CONFIG_DM_ETH
			*packetp = rxdata;
#else
			net_process_received_packet(rxdata, length);
#endif
		} else {
			puts("Error Rx");
			length = -EIO;
		}
		cur_rx = (cur_rx + 1) % NUM_RX_DESC;
		tpc->cur_rx = cur_rx;
		return length;

	} else {
		ushort sts = RTL_R8(IntrStatus);
		RTL_W8(IntrStatus, sts & ~(TxErr | RxErr | SYSErr));
		udelay(100);	/* wait */
	}
	tpc->cur_rx = cur_rx;
	return (0);		/* initially as this is called to flush the input */
}
Esempio n. 22
0
static void ax88180_rx_handler (struct eth_device *dev)
{
	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
	unsigned long data_size;
	unsigned short rxcurt_ptr, rxbound_ptr, next_ptr;
	int i;
#if defined (CONFIG_DRIVER_AX88180_16BIT)
	unsigned short *rxdata = (unsigned short *)net_rx_packets[0];
#else
	unsigned long *rxdata = (unsigned long *)net_rx_packets[0];
#endif
	unsigned short count;

	rxcurt_ptr = INW (dev, RXCURT);
	rxbound_ptr = INW (dev, RXBOUND);
	next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;

	debug ("ax88180: RX original RXBOUND=0x%04x,"
	       " RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);

	while (next_ptr != rxcurt_ptr) {

		OUTW (dev, RX_START_READ, RXINDICATOR);

		data_size = READ_RXBUF (dev) & 0xFFFF;

		if ((data_size == 0) || (data_size > MAX_RX_SIZE)) {

			OUTW (dev, RX_STOP_READ, RXINDICATOR);

			ax88180_mac_reset (dev);
			printf ("ax88180: Invalid Rx packet length!"
				" (len=0x%04lx)\n", data_size);

			debug ("ax88180: RX RXBOUND=0x%04x,"
			       "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
			return;
		}

		rxbound_ptr += (((data_size + 0xF) & 0xFFF0) >> 4) + 1;
		rxbound_ptr &= RX_PAGE_NUM_MASK;

		/* Comput access times */
		count = (data_size + priv->PadSize) >> priv->BusWidth;

		for (i = 0; i < count; i++) {
			*(rxdata + i) = READ_RXBUF (dev);
		}

		OUTW (dev, RX_STOP_READ, RXINDICATOR);

		/* Pass the packet up to the protocol layers. */
		net_process_received_packet(net_rx_packets[0], data_size);

		OUTW (dev, rxbound_ptr, RXBOUND);

		rxcurt_ptr = INW (dev, RXCURT);
		rxbound_ptr = INW (dev, RXBOUND);
		next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;

		debug ("ax88180: RX updated RXBOUND=0x%04x,"
		       "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
	}

	return;
}
Esempio n. 23
0
static int mvgbe_recv(struct eth_device *dev)
{
	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
	struct mvgbe_rxdesc *p_rxdesc_curr = dmvgbe->p_rxdesc_curr;
	u32 cmd_sts;
	u32 timeout = 0;
	u32 rxdesc_curr_addr;

	/* wait untill rx packet available or timeout */
	do {
		if (timeout < MVGBE_PHY_SMI_TIMEOUT)
			timeout++;
		else {
			debug("%s time out...\n", __func__);
			return -1;
		}
	} while (readl(&p_rxdesc_curr->cmd_sts) & MVGBE_BUFFER_OWNED_BY_DMA);

	if (p_rxdesc_curr->byte_cnt != 0) {
		debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n",
			__func__, (u32) p_rxdesc_curr->byte_cnt,
			(u32) p_rxdesc_curr->buf_ptr,
			(u32) p_rxdesc_curr->cmd_sts);
	}

	/*
	 * In case received a packet without first/last bits on
	 * OR the error summary bit is on,
	 * the packets needs to be dropeed.
	 */
	cmd_sts = readl(&p_rxdesc_curr->cmd_sts);

	if ((cmd_sts &
		(MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC))
		!= (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC)) {

		printf("Err..(%s) Dropping packet spread on"
			" multiple descriptors\n", __func__);

	} else if (cmd_sts & MVGBE_ERROR_SUMMARY) {

		printf("Err..(%s) Dropping packet with errors\n",
			__func__);

	} else {
		/* !!! call higher layer processing */
		debug("%s: Sending Received packet to"
		      " upper layer (net_process_received_packet)\n",
		      __func__);

		/* let the upper layer handle the packet */
		net_process_received_packet((p_rxdesc_curr->buf_ptr +
					     RX_BUF_OFFSET),
					    (int)(p_rxdesc_curr->byte_cnt -
						  RX_BUF_OFFSET));
	}
	/*
	 * free these descriptors and point next in the ring
	 */
	p_rxdesc_curr->cmd_sts =
		MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_EN_INTERRUPT;
	p_rxdesc_curr->buf_size = PKTSIZE_ALIGN;
	p_rxdesc_curr->byte_cnt = 0;

	rxdesc_curr_addr = (u32)&dmvgbe->p_rxdesc_curr;
	writel((unsigned)p_rxdesc_curr->nxtdesc_p, rxdesc_curr_addr);

	return 0;
}
/**
 * Pull one frame from the card
 * @param[in] dev Our ethernet device to handle
 * @return Length of packet read
 */
static int fec_recv(struct eth_device *dev)
{
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
	unsigned long ievent;
	int frame_length, len = 0;
	uint16_t bd_status;
	uint32_t addr, size, end;
	int i;
	ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);

	/*
	 * Check if any critical events have happened
	 */
	ievent = readl(&fec->eth->ievent);
	writel(ievent, &fec->eth->ievent);
	debug("fec_recv: ievent 0x%lx\n", ievent);
	if (ievent & FEC_IEVENT_BABR) {
		fec_halt(dev);
		fec_init(dev, fec->bd);
		printf("some error: 0x%08lx\n", ievent);
		return 0;
	}
	if (ievent & FEC_IEVENT_HBERR) {
		/* Heartbeat error */
		writel(0x00000001 | readl(&fec->eth->x_cntrl),
				&fec->eth->x_cntrl);
	}
	if (ievent & FEC_IEVENT_GRA) {
		/* Graceful stop complete */
		if (readl(&fec->eth->x_cntrl) & 0x00000001) {
			fec_halt(dev);
			writel(~0x00000001 & readl(&fec->eth->x_cntrl),
					&fec->eth->x_cntrl);
			fec_init(dev, fec->bd);
		}
	}

	/*
	 * Read the buffer status. Before the status can be read, the data cache
	 * must be invalidated, because the data in RAM might have been changed
	 * by DMA. The descriptors are properly aligned to cachelines so there's
	 * no need to worry they'd overlap.
	 *
	 * WARNING: By invalidating the descriptor here, we also invalidate
	 * the descriptors surrounding this one. Therefore we can NOT change the
	 * contents of this descriptor nor the surrounding ones. The problem is
	 * that in order to mark the descriptor as processed, we need to change
	 * the descriptor. The solution is to mark the whole cache line when all
	 * descriptors in the cache line are processed.
	 */
	addr = (uint32_t)rbd;
	addr &= ~(ARCH_DMA_MINALIGN - 1);
	size = roundup(sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
	invalidate_dcache_range(addr, addr + size);

	bd_status = readw(&rbd->status);
	debug("fec_recv: status 0x%x\n", bd_status);

	if (!(bd_status & FEC_RBD_EMPTY)) {
		if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
			((readw(&rbd->data_length) - 4) > 14)) {
			/*
			 * Get buffer address and size
			 */
			addr = readl(&rbd->data_pointer);
			frame_length = readw(&rbd->data_length) - 4;
			/*
			 * Invalidate data cache over the buffer
			 */
			end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
			addr &= ~(ARCH_DMA_MINALIGN - 1);
			invalidate_dcache_range(addr, end);

			/*
			 *  Fill the buffer and pass it to upper layers
			 */
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
			swap_packet((uint32_t *)addr, frame_length);
#endif
			memcpy(buff, (char *)addr, frame_length);
			net_process_received_packet(buff, frame_length);
			len = frame_length;
		} else {
			if (bd_status & FEC_RBD_ERR)
				printf("error frame: 0x%08x 0x%08x\n",
				       addr, bd_status);
		}

		/*
		 * Free the current buffer, restart the engine and move forward
		 * to the next buffer. Here we check if the whole cacheline of
		 * descriptors was already processed and if so, we mark it free
		 * as whole.
		 */
		size = RXDESC_PER_CACHELINE - 1;
		if ((fec->rbd_index & size) == size) {
			i = fec->rbd_index - size;
			addr = (uint32_t)&fec->rbd_base[i];
			for (; i <= fec->rbd_index ; i++) {
				fec_rbd_clean(i == (FEC_RBD_NUM - 1),
					      &fec->rbd_base[i]);
			}
			flush_dcache_range(addr,
				addr + ARCH_DMA_MINALIGN);
		}

		fec_rx_task_enable(fec);
		fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
	}
	debug("fec_recv: stop\n");

	return len;
}