static void ether1_recv_done (struct net_device *dev) { int status; int nexttail, rbdaddr; rbd_t rbd; do { status = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_status, NORMALIRQS); if ((status & RFD_COMPLETE) == 0) break; rbdaddr = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS); ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE); if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) { int length = rbd.rbd_status & RBD_ACNT; struct sk_buff *skb; length = (length + 1) & ~1; skb = dev_alloc_skb (length + 2); if (skb) { skb->dev = dev; skb_reserve (skb, 2); ether1_readbuffer (dev, skb_put (skb, length), rbd.rbd_bufl, length); skb->protocol = eth_type_trans (skb, dev); netif_rx (skb); priv(dev)->stats.rx_packets ++; } else priv(dev)->stats.rx_dropped ++; } else { printk(KERN_WARNING "%s: %s\n", dev->name, (rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid"); priv(dev)->stats.rx_dropped ++; } nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS); /* nexttail should be rx_head */ if (nexttail != priv(dev)->rx_head) printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n", dev->name, nexttail, priv(dev)->rx_head); ether1_writew(dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS); ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_command, NORMALIRQS); ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_status, NORMALIRQS); ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS); priv(dev)->rx_tail = nexttail; priv(dev)->rx_head = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_link, NORMALIRQS); } while (1); }
static int ether1_ramtest(struct net_device *dev, unsigned char byte) { unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL); int i, ret = BUFFER_SIZE; int max_errors = 15; int bad = -1; int bad_start = 0; if (!buffer) return 1; memset (buffer, byte, BUFFER_SIZE); ether1_writebuffer (dev, buffer, 0, BUFFER_SIZE); memset (buffer, byte ^ 0xff, BUFFER_SIZE); ether1_readbuffer (dev, buffer, 0, BUFFER_SIZE); for (i = 0; i < BUFFER_SIZE; i++) { if (buffer[i] != byte) { if (max_errors >= 0 && bad != buffer[i]) { if (bad != -1) printk ("\n"); printk (KERN_CRIT "%s: RAM failed with (%02X instead of %02X) at 0x%04X", dev->name, buffer[i], byte, i); ret = -ENODEV; max_errors --; bad = buffer[i]; bad_start = i; } } else { if (bad != -1) { if (bad_start == i - 1) printk ("\n"); else printk (" - 0x%04X\n", i - 1); bad = -1; } } } if (bad != -1) printk (" - 0x%04X\n", BUFFER_SIZE); kfree (buffer); return ret; }
static void ether1_xmit_done (struct net_device *dev) { nop_t nop; int caddr, tst; caddr = priv(dev)->tx_tail; again: ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); switch (nop.nop_command & CMD_MASK) { case CMD_TDR: /* special case */ if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) != (unsigned short)I82586_NULL) { ether1_writew(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS); writeb(CTRL_CA, REG_CONTROL); } priv(dev)->tx_tail = NOP_ADDR; return; case CMD_NOP: if (nop.nop_link == caddr) { if (priv(dev)->initialising == 0) printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name); else priv(dev)->initialising = 0; return; } if (caddr == nop.nop_link) return; caddr = nop.nop_link; goto again; case CMD_TX: if (nop.nop_status & STAT_COMPLETE) break; printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name); priv(dev)->restart = 1; return; default: printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name, nop.nop_command & CMD_MASK, caddr); priv(dev)->restart = 1; return; } while (nop.nop_status & STAT_COMPLETE) { if (nop.nop_status & STAT_OK) { dev->stats.tx_packets++; dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS); } else { dev->stats.tx_errors++; if (nop.nop_status & STAT_COLLAFTERTX) dev->stats.collisions++; if (nop.nop_status & STAT_NOCARRIER) dev->stats.tx_carrier_errors++; if (nop.nop_status & STAT_TXLOSTCTS) printk (KERN_WARNING "%s: cts lost\n", dev->name); if (nop.nop_status & STAT_TXSLOWDMA) dev->stats.tx_fifo_errors++; if (nop.nop_status & STAT_COLLEXCESSIVE) dev->stats.collisions += 16; } if (nop.nop_link == caddr) { printk (KERN_ERR "%s: tx buffer chaining error: tx command points to itself\n", dev->name); break; } caddr = nop.nop_link; ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); if ((nop.nop_command & CMD_MASK) != CMD_NOP) { printk (KERN_ERR "%s: tx buffer chaining error: no nop after tx command\n", dev->name); break; } if (caddr == nop.nop_link) break; caddr = nop.nop_link; ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); if ((nop.nop_command & CMD_MASK) != CMD_TX) { printk (KERN_ERR "%s: tx buffer chaining error: no tx command after nop\n", dev->name); break; } } priv(dev)->tx_tail = caddr; caddr = priv(dev)->tx_head; tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN); priv(dev)->tx_head = caddr; if (tst != -1) netif_wake_queue(dev); }