Ejemplo n.º 1
0
static void seeq8005_timeout(struct net_device *dev)
{
	int ioaddr = dev->base_addr;
	printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
		   tx_done(dev) ? "IRQ conflict" : "network cable problem");
	/* Try to restart the adaptor. */
	seeq8005_init(dev, 1);
	dev->trans_start = jiffies;
	netif_wake_queue(dev);
}
Ejemplo n.º 2
0
static int seeq8005_open(struct net_device *dev)
{
	struct net_local *lp = netdev_priv(dev);

	{
		 int irqval = request_irq(dev->irq, seeq8005_interrupt, 0, "seeq8005", dev);
		 if (irqval) {
			 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
					 dev->irq, irqval);
			 return -EAGAIN;
		 }
	}

	
	seeq8005_init(dev, 1);

	lp->open_time = jiffies;

	netif_start_queue(dev);
	return 0;
}
Ejemplo n.º 3
0
/* Open/initialize the board.  This is called (in the current kernel)
   sometime after booting when the 'ifconfig' program is run.

   This routine should set everything up anew at each open, even
   registers that "should" only need to be set once at boot, so that
   there is non-reboot way to recover if something goes wrong.
   */
static int seeq8005_open(struct net_device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;

	{
		 int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", dev);
		 if (irqval) {
			 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
					 dev->irq, irqval);
			 return -EAGAIN;
		 }
	}

	/* Reset the hardware here.  Don't forget to set the station address. */
	seeq8005_init(dev, 1);

	lp->open_time = jiffies;

	netif_start_queue(dev);
	return 0;
}
Ejemplo n.º 4
0
static int
seeq8005_send_packet(struct sk_buff *skb, struct device *dev)
{
	int ioaddr = dev->base_addr;
	struct net_local *lp = (struct net_local *)dev->priv;

	if (dev->tbusy) {
		/* If we get here, some higher level has decided we are broken.
		   There should really be a "kick me" function call instead. */
		int tickssofar = jiffies - dev->trans_start;
		if (tickssofar < 5)
			return 1;
		printk("%s: transmit timed out, %s?\n", dev->name,
			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
		/* Try to restart the adaptor. */
		seeq8005_init(dev, 1);
		dev->tbusy=0;
		dev->trans_start = jiffies;
	}

	/* Block a timer-based transmit from overlapping.  This could better be
	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
		printk("%s: Transmitter access conflict.\n", dev->name);
	else {
		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
		unsigned char *buf = skb->data;

		hardware_send_packet(dev, buf, length); 
		dev->trans_start = jiffies;
		lp->stats.tx_bytes += length;
	}
	dev_kfree_skb (skb);

	/* You might need to clean up and record Tx statistics here. */

	return 0;
}
Ejemplo n.º 5
0
/* We have a good packet(s), get it/them out of the buffers. */
static void seeq8005_rx(struct net_device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int boguscount = 10;
	int pkt_hdr;
	int ioaddr = dev->base_addr;

	do {
		int next_packet;
		int pkt_len;
		int i;
		int status;

		status = inw(SEEQ_STATUS);
	  	outw( lp->receive_ptr, SEEQ_DMAAR);
		outw(SEEQCMD_FIFO_READ | SEEQCMD_RX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
	  	wait_for_buffer(dev);
	  	next_packet = ntohs(inw(SEEQ_BUFFER));
	  	pkt_hdr = inw(SEEQ_BUFFER);
	  	
		if (net_debug>2) {
			printk("%s: 0x%04x recv next=0x%04x, hdr=0x%04x\n",dev->name,lp->receive_ptr,next_packet,pkt_hdr);
		}
			
		if ((next_packet == 0) || ((pkt_hdr & SEEQPKTH_CHAIN)==0)) {	/* Read all the frames? */
			return;							/* Done for now */
		}
			
		if ((pkt_hdr & SEEQPKTS_DONE)==0)
			break;
			
		if (next_packet < lp->receive_ptr) {
			pkt_len = (next_packet + 0x10000 - ((DEFAULT_TEA+1)<<8)) - lp->receive_ptr - 4;
		} else {
			pkt_len = next_packet - lp->receive_ptr - 4;
		}
		
		if (next_packet < ((DEFAULT_TEA+1)<<8)) {			/* is the next_packet address sane? */
			printk("%s: recv packet ring corrupt, resetting board\n",dev->name);
			seeq8005_init(dev,1);
			return;
		}
		
		lp->receive_ptr = next_packet;
		
		if (net_debug>2) {
			printk("%s: recv len=0x%04x\n",dev->name,pkt_len);
		}

		if (pkt_hdr & SEEQPKTS_ANY_ERROR) {				/* There was an error. */
			lp->stats.rx_errors++;
			if (pkt_hdr & SEEQPKTS_SHORT) lp->stats.rx_frame_errors++;
			if (pkt_hdr & SEEQPKTS_DRIB) lp->stats.rx_frame_errors++;
			if (pkt_hdr & SEEQPKTS_OVERSIZE) lp->stats.rx_over_errors++;
			if (pkt_hdr & SEEQPKTS_CRC_ERR) lp->stats.rx_crc_errors++;
			/* skip over this packet */
			outw( SEEQCMD_FIFO_WRITE | SEEQCMD_DMA_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
			outw( (lp->receive_ptr & 0xff00)>>8, SEEQ_REA);
		} else {
			/* Malloc up new buffer. */
			struct sk_buff *skb;
			unsigned char *buf;

			skb = dev_alloc_skb(pkt_len);
			if (skb == NULL) {
				printk("%s: Memory squeeze, dropping packet.\n", dev->name);
				lp->stats.rx_dropped++;
				break;
			}
			skb->dev = dev;
			skb_reserve(skb, 2);	/* align data on 16 byte */
			buf = skb_put(skb,pkt_len);
			
			insw(SEEQ_BUFFER, buf, (pkt_len + 1) >> 1);
			
			if (net_debug>2) {
				char * p = buf;
				printk("%s: recv ",dev->name);
				for(i=0;i<14;i++) {
					printk("%02x ",*(p++)&0xff);
				}
				printk("\n");
			}

			skb->protocol=eth_type_trans(skb,dev);
			netif_rx(skb);
			dev->last_rx = jiffies;
			lp->stats.rx_packets++;
			lp->stats.rx_bytes += pkt_len;
		}
	} while ((--boguscount) && (pkt_hdr & SEEQPKTH_CHAIN));