static void netx_eth_receive(struct net_device *ndev) { struct netx_eth_priv *priv = netdev_priv(ndev); unsigned int val, frameno, seg, len; unsigned char *data; struct sk_buff *skb; val = pfifo_pop(IND_FIFO_PORT_LO(priv->id)); frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT; seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; skb = netdev_alloc_skb(ndev, len); if (unlikely(skb == NULL)) { printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", ndev->name); ndev->stats.rx_dropped++; return; } data = skb_put(skb, len); memcpy_fromio(data, priv->sram_base + frameno * 1560, len); pfifo_push(EMPTY_PTR_FIFO(priv->id), FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno)); skb->protocol = eth_type_trans(skb, ndev); netif_rx(skb); ndev->stats.rx_packets++; ndev->stats.rx_bytes += len; }
static int netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct netx_eth_priv *priv = netdev_priv(ndev); unsigned char *buf = skb->data; unsigned int len = skb->len; spin_lock_irq(&priv->lock); memcpy_toio(priv->sram_base + 1560, (void *)buf, len); if (len < 60) { memset_io(priv->sram_base + 1560 + len, 0, 60 - len); len = 60; } pfifo_push(REQ_FIFO_PORT_LO(priv->id), FIFO_PTR_SEGMENT(priv->id) | FIFO_PTR_FRAMENO(1) | FIFO_PTR_FRAMELEN(len)); ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; netif_stop_queue(ndev); spin_unlock_irq(&priv->lock); dev_kfree_skb(skb); return NETDEV_TX_OK; }
static int netx_eth_rx (struct eth_device *edev) { struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv; int xcno = priv->xcno; unsigned int val, frameno, seg, len; if(!PFIFO_REG( PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(xcno)))) { return 0; } val = PFIFO_REG( PFIFO_BASE(IND_FIFO_PORT_LO(xcno)) ); frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT; seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; /* get data */ memcpy((void*)NetRxPackets[0], (void *)(SRAM_BASE(seg) + frameno * 1560), len); /* pass to barebox */ net_receive(NetRxPackets[0], len); PFIFO_REG(PFIFO_BASE(EMPTY_PTR_FIFO(xcno))) = FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno); return 0; }
static int netx_eth_init_dev(struct eth_device *edev) { struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv; int xcno = priv->xcno; int i; loadxc(xcno); /* Fill empty pointer fifo */ for (i = 2; i <= 18; i++) PFIFO_REG( PFIFO_BASE(EMPTY_PTR_FIFO(xcno)) ) = FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(xcno); return 0; }
static void netx_eth_timeout(struct net_device *ndev) { struct netx_eth_priv *priv = netdev_priv(ndev); int i; printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name); spin_lock_irq(&priv->lock); xc_reset(priv->xc); xc_start(priv->xc); for (i=2; i<=18; i++) pfifo_push(EMPTY_PTR_FIFO(priv->id), FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); spin_unlock_irq(&priv->lock); netif_wake_queue(ndev); }
static int netx_eth_send (struct eth_device *edev, void *packet, int length) { struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv; int xcno = priv->xcno; unsigned int val; int timeout = 500; unsigned char *dst = (unsigned char *)(SRAM_BASE(xcno) + 1560); memcpy(dst, (void *)packet, length); if( length < 60 ) { memset(dst + length, 0, 60 - length); length = 60; } PFIFO_REG(PFIFO_BASE(REQ_FIFO_PORT_LO(xcno))) = FIFO_PTR_SEGMENT(xcno) | FIFO_PTR_FRAMENO(1) | FIFO_PTR_FRAMELEN(length); while (!PFIFO_REG( PFIFO_FILL_LEVEL(CON_FIFO_PORT_LO(xcno))) && timeout) { timeout--; udelay(100); } #if 0 if (!timeout) { loadxc(0); loadxc(1); eth_init(gd->bd); return -1; } #endif val = PFIFO_REG( PFIFO_BASE(CON_FIFO_PORT_LO(xcno)) ); if((val & FIFO_PTR_ERROR_MASK) & 0x8) printf("error sending frame: %d\n",val); return 0; }