示例#1
0
文件: eth.c 项目: bbbLinux/u_boot
static int fm_eth_send(struct eth_device *dev, void *buf, int len)
{
	struct fm_eth *fm_eth;
	struct fm_port_global_pram *pram;
	struct fm_port_bd *txbd, *txbd_base;
	u16 offset_in;
	int i;

	fm_eth = (struct fm_eth *)dev->priv;
	pram = fm_eth->tx_pram;
	txbd = fm_eth->cur_txbd;

	/* find one empty TxBD */
	for (i = 0; txbd->status & TxBD_READY; i++) {
		udelay(100);
		if (i > 0x1000) {
			printf("%s: Tx buffer not ready\n", dev->name);
			return 0;
		}
	}
	/* setup TxBD */
	txbd->buf_ptr_hi = 0;
	txbd->buf_ptr_lo = (u32)buf;
	txbd->len = len;
	sync();
	txbd->status = TxBD_READY | TxBD_LAST;
	sync();

	/* update TxQD, let RISC to send the packet */
	offset_in = muram_readw(&pram->txqd.offset_in);
	offset_in += sizeof(struct fm_port_bd);
	if (offset_in >= muram_readw(&pram->txqd.bd_ring_size))
		offset_in = 0;
	muram_writew(&pram->txqd.offset_in, offset_in);
	sync();

	/* wait for buffer to be transmitted */
	for (i = 0; txbd->status & TxBD_READY; i++) {
		udelay(100);
		if (i > 0x10000) {
			printf("%s: Tx error\n", dev->name);
			return 0;
		}
	}

	/* advance the TxBD */
	txbd++;
	txbd_base = (struct fm_port_bd *)fm_eth->tx_bd_ring;
	if (txbd >= (txbd_base + TX_BD_RING_SIZE))
		txbd = txbd_base;
	/* update current txbd */
	fm_eth->cur_txbd = (void *)txbd;

	return 1;
}
示例#2
0
文件: eth.c 项目: bbbLinux/u_boot
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;
	u8 *data;
	u16 offset_out;

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

	while (!(status & RxBD_EMPTY)) {
		if (!(status & RxBD_ERROR)) {
			data = (u8 *)rxbd->buf_ptr_lo;
			len = rxbd->len;
			NetReceive(data, len);
		} else {
			printf("%s: Rx error\n", dev->name);
			return 0;
		}

		/* clear the RxBDs */
		rxbd->status = RxBD_EMPTY;
		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 = 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 1;
}
示例#3
0
文件: eth.c 项目: OpenNoah/u-boot
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;
}