示例#1
0
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);
}
示例#2
0
文件: ether1.c 项目: 020gzh/linux
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;
}
示例#3
0
文件: ether1.c 项目: 020gzh/linux
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);
}