예제 #1
0
static int
net_send_packet(struct sk_buff *skb, struct device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int ioaddr = dev->base_addr;

	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. */
		chipset_init(dev, 1);
		dev->tbusy=0;
		dev->trans_start = jiffies;
	}

	/* If some higher layer thinks we've missed an tx-done interrupt
	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
	   itself. */
	if (skb == NULL) {
		dev_tint(dev);
		return 0;
	}

	/* For ethernet, fill in the header.  This should really be done by a
	   higher level, rather than duplicated for each ethernet adaptor. */
	if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {
		skb->dev = dev;
		arp_queue (skb);
		return 0;
	}
	skb->arp=1;

	/* 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 (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(ioaddr, buf, length);
		dev->trans_start = jiffies;
	}
	if (skb->free)
		kfree_skb (skb, FREE_WRITE);

	/* You might need to clean up and record Tx statistics here. */
	if (inw(ioaddr) == /*RU*/81)
		lp->stats.tx_aborted_errors++;

	return 0;
}
예제 #2
0
static netdev_tx_t eepro_send_packet(struct sk_buff *skb,
				     struct net_device *dev)
{
	struct eepro_local *lp = netdev_priv(dev);
	unsigned long flags;
	int ioaddr = dev->base_addr;
	short length = skb->len;

	if (net_debug > 5)
		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);

	if (length < ETH_ZLEN) {
		if (skb_padto(skb, ETH_ZLEN))
			return NETDEV_TX_OK;
		length = ETH_ZLEN;
	}
	netif_stop_queue (dev);

	eepro_dis_int(ioaddr);
	spin_lock_irqsave(&lp->lock, flags);

	{
		unsigned char *buf = skb->data;

		if (hardware_send_packet(dev, buf, length))
			/* we won't wake queue here because we're out of space */
			dev->stats.tx_dropped++;
		else {
			dev->stats.tx_bytes+=skb->len;
			netif_wake_queue(dev);
		}

	}

	dev_kfree_skb (skb);

	/* You might need to clean up and record Tx statistics here. */
	/* dev->stats.tx_aborted_errors++; */

	if (net_debug > 5)
		printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);

	eepro_en_int(ioaddr);
	spin_unlock_irqrestore(&lp->lock, flags);

	return NETDEV_TX_OK;
}
예제 #3
0
static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
	unsigned char *buf = skb->data;

	/* Block a timer-based transmit from overlapping */
	netif_stop_queue(dev);
	
	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;
}
예제 #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;
}
static netdev_tx_t seeq8005_send_packet(struct sk_buff *skb,
					struct net_device *dev)
{
	short length = skb->len;
	unsigned char *buf;

	if (length < ETH_ZLEN) {
		if (skb_padto(skb, ETH_ZLEN))
			return NETDEV_TX_OK;
		length = ETH_ZLEN;
	}
	buf = skb->data;

	
	netif_stop_queue(dev);

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

	return NETDEV_TX_OK;
}
예제 #6
0
static netdev_tx_t seeq8005_send_packet(struct sk_buff *skb,
					struct net_device *dev)
{
	short length = skb->len;
	unsigned char *buf;

	if (length < ETH_ZLEN) {
		if (skb_padto(skb, ETH_ZLEN))
			return NETDEV_TX_OK;
		length = ETH_ZLEN;
	}
	buf = skb->data;

	/* Block a timer-based transmit from overlapping */
	netif_stop_queue(dev);

	hardware_send_packet(dev, buf, length);
	dev->stats.tx_bytes += length;
	dev_kfree_skb (skb);
	/* You might need to clean up and record Tx statistics here. */

	return NETDEV_TX_OK;
}
예제 #7
0
static int
bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
    struct net_local *lp = netdev_priv(dev);
    unsigned long flags;

    /* Block a timer-based transmit from overlapping.  This could better be
     * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
     */
    local_irq_save(flags);

    if (stdma_islocked()) {
        local_irq_restore(flags);
        lp->stats.tx_errors++;
    }
    else {
        int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        unsigned long buf = virt_to_phys(skb->data);
        int stat;

        stdma_lock(bionet_intr, NULL);
        local_irq_restore(flags);
        if( !STRAM_ADDR(buf+length-1) ) {
            memcpy(nic_packet->buffer, skb->data, length);
            buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
        }

        if (bionet_debug >1) {
            u_char *data = nic_packet->buffer, *p;
            int i;

            printk( "%s: TX pkt type 0x%4x from ", dev->name,
                    ((u_short *)data)[6]);

            for( p = &data[6], i = 0; i < 6; i++ )
                printk("%02x%s", *p++,i != 5 ? ":" : "" );
            printk(" to ");

            for( p = data, i = 0; i < 6; i++ )
                printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );

            printk( "%s: ", dev->name );
            printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
                   " %02x%02x%02x%02x len %d\n",
                   data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
                   data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
                   data[28], data[29], data[30], data[31], data[32], data[33],
                   length );
        }
        dma_cache_maintenance(buf, length, 1);

        stat = hardware_send_packet(buf, length);
        ENABLE_IRQ();
        stdma_release();

        dev->trans_start = jiffies;
        dev->tbusy	 = 0;
        lp->stats.tx_packets++;
        lp->stats.tx_bytes+=length;
    }
    dev_kfree_skb(skb);

    return 0;
}
예제 #8
0
static int
eexp_send_packet(struct sk_buff *skb, struct device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int ioaddr = dev->base_addr;

	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;
		if (net_debug > 1)
			printk("%s: transmit timed out, %s?  ", dev->name,
				   inw(ioaddr+SCB_STATUS) & 0x8000 ? "IRQ conflict" :
				   "network cable problem");
		lp->stats.tx_errors++;
		/* Try to restart the adaptor. */
		if (lp->last_restart == lp->stats.tx_packets) {
			if (net_debug > 1) printk("Resetting board.\n");
			/* Completely reset the adaptor. */
			init_82586_mem(dev);
		} else {
			/* Issue the channel attention signal and hope it "gets better". */
			if (net_debug > 1) printk("Kicking board.\n");
			outw(0xf000|CUC_START|RX_START, ioaddr + SCB_CMD);
			outb(0, ioaddr + SIGNAL_CA);
			lp->last_restart = lp->stats.tx_packets;
		}
		dev->tbusy=0;
		dev->trans_start = jiffies;
	}

	/* If some higher layer thinks we've missed an tx-done interrupt
	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
	   itself. */
	if (skb == NULL) {
		dev_tint(dev);
		return 0;
	}

	/* Block a timer-based transmit from overlapping. */
	if (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;

		/* Disable the 82586's input to the interrupt line. */
		outb(irqrmap[dev->irq], ioaddr + SET_IRQ);
		hardware_send_packet(dev, buf, length);
		dev->trans_start = jiffies;
		/* Enable the 82586 interrupt input. */
		outb(0x08 | irqrmap[dev->irq], ioaddr + SET_IRQ);
	}

	dev_kfree_skb (skb, FREE_WRITE);

	/* You might need to clean up and record Tx statistics here. */
	lp->stats.tx_aborted_errors++;

	return 0;
}