예제 #1
0
static  void
wd_trs( struct device *dev )
{
	unsigned char errors;

	if( wd_debug )
		printk("\nwd_trs() - TX complete, status = x%x", inb_p(TSR));

	if( ( errors = inb_p( TSR ) & PTXOK  ) || tx_aborted ){
		if( (errors&~0x02) == 0 ){
			stats.tx_packets++;
			tx_aborted = 0;
		}
		dev->tbusy = 0;
		mark_bh (INET_BH);
		
#if 0		
		/* attempt to start a new transmission. */
		len = dev_tint( (unsigned char *)dev->mem_start, dev );
		if( len != 0 ){
      			len=max(len, ETHER_MIN_LEN);
			cmd=inb_p(WD_COMM);
			outb_p(len&0xff,WD_TB0);
			outb_p(len>>8,WD_TB1);
			cmd |= CTRANS;
			outb_p(cmd,WD_COMM);
			interrupt_mask |= TRANS_MASK;
		}
		else
		{
예제 #2
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;
}
예제 #3
0
파일: dev.c 프로젝트: uping/prettyos
/*
 * traversal the net_device and send some data
 */
void dev_transmit(void)
{
		struct net_device *dev;
		for(dev = dev_base;dev != NULL; dev = dev->next)
		{
				if(dev->flags != 0 && dev->tbusy)
						dev_tint(dev);
		}
}
예제 #4
0
void dev_transmit(void)
{
	struct device *dev;

	for (dev = dev_base; dev != NULL; dev = dev->next) 
	{
		if (dev->flags != 0 && !dev->tbusy) {
			/*
			 *	Kick the device
			 */
			dev_tint(dev);
		}
	}
}
예제 #5
0
/*
 * Copy a buffer to the adapter transmit page memory.
 * Start sending.
 */
static int
de600_start_xmit(struct sk_buff *skb, struct device *dev)
{
	int	transmit_from;
	int	len;
	int	tickssofar;
	byte	*buffer = skb->data;

	/*
	 * If some higher layer thinks we've missed a
	 * tx-done interrupt we are passed NULL.
	 * Caution: dev_tint() handles the cli()/sti() itself.
	 */

	if (skb == NULL) {
		dev_tint(dev);
		return 0;
	}

	if (free_tx_pages <= 0) {	/* Do timeouts, to avoid hangs. */
		tickssofar = jiffies - dev->trans_start;

		if (tickssofar < 5)
			return 1;

		/* else */
		printk("%s: transmit timed out (%d), %s?\n",
			dev->name,
			tickssofar,
			"network cable problem"
			);
		/* Restart the adapter. */
		if (adapter_init(dev)) {
			return 1;
		}
	}

	/* Start real output */
	PRINTK(("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages));

	if ((len = skb->len) < RUNT)
		len = RUNT;

	cli();
	select_nic();
	tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len;
	tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */

#ifdef CHECK_LOST_DE600
	/* This costs about 40 instructions per packet... */
	de600_setup_address(NODE_ADDRESS, RW_ADDR);
	de600_read_byte(READ_DATA, dev);
	if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) {
		if (adapter_init(dev)) {
			sti();
			return 1;
		}
	}
#endif

	de600_setup_address(transmit_from, RW_ADDR);
	for ( ; len > 0; --len, ++buffer)
		de600_put_byte(*buffer);

	if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
		dev->trans_start = jiffies;
		dev->tbusy = 0;	/* allow more packets into adapter */
		/* Send page and generate a faked interrupt */
		de600_setup_address(transmit_from, TX_ADDR);
		de600_put_command(TX_ENABLE);
	}
	else {
		dev->tbusy = !free_tx_pages;
		select_prn();
	}
	
	sti(); /* interrupts back on */
	
#ifdef FAKE_SMALL_MAX
	/* This will "patch" the socket TCP proto at an early moment */
	if (skb->sk && (skb->sk->protocol == IPPROTO_TCP) &&
		(skb->sk->prot->rspace != &de600_rspace))
		skb->sk->prot->rspace = de600_rspace; /* Ugh! */
#endif

	dev_kfree_skb (skb, FREE_WRITE);

	return 0;
}
예제 #6
0
파일: 3c501.c 프로젝트: 0xffea/gnumach
static int el_start_xmit(struct sk_buff *skb, struct device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int ioaddr = dev->base_addr;
	unsigned long flags;
	
	if(dev->interrupt)		/* May be unloading, don't stamp on */
		return 1;		/* the packet buffer this time      */

	if (dev->tbusy) 
	{
		if (jiffies - dev->trans_start < 20) 
		{
			if (el_debug > 2)
				printk(" transmitter busy, deferred.\n");
			return 1;
		}
		if (el_debug)
			printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
				dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
		lp->stats.tx_errors++;
		outb(TX_NORM, TX_CMD);
		outb(RX_NORM, RX_CMD);
		outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
		outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
		dev->tbusy = 0;
		dev->trans_start = jiffies;
	}

	if (skb == NULL) 
	{
		dev_tint(dev);
		return 0;
	}

	save_flags(flags);

	/*
	 *	Avoid incoming interrupts between us flipping tbusy and flipping
	 *	mode as the driver assumes tbusy is a faithful indicator of card
	 *	state
	 */
	 
	cli();
	
	/*
	 *	Avoid timer-based retransmission conflicts. 
	 */
	 
	if (set_bit(0, (void*)&dev->tbusy) != 0)
	{
		restore_flags(flags);
		printk("%s: Transmitter access conflict.\n", dev->name);
	}
	else
	{
		int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
		unsigned char *buf = skb->data;

load_it_again_sam:
		lp->tx_pkt_start = gp_start;
    		lp->collisions = 0;

		/*
		 *	Command mode with status cleared should [in theory]
		 *	mean no more interrupts can be pending on the card.
		 */
		 
#ifdef BLOCKOUT_1
		disable_irq(dev->irq);		 
#endif	
		outb_p(AX_SYS, AX_CMD);
		inb_p(RX_STATUS);
		inb_p(TX_STATUS);
	
		lp->loading=1;
	
		/* 
		 *	Turn interrupts back on while we spend a pleasant afternoon
		 *	loading bytes into the board 
		 */

		restore_flags(flags);
		outw(0x00, RX_BUF_CLR);		/* Set rx packet area to 0. */
		outw(gp_start, GP_LOW);		/* aim - packet will be loaded into buffer start */
		outsb(DATAPORT,buf,skb->len);	/* load buffer (usual thing each byte increments the pointer) */
		outw(gp_start, GP_LOW);		/* the board reuses the same register */
#ifndef BLOCKOUT_1		
		if(lp->loading==2)		/* A receive upset our load, despite our best efforts */
		{
			if(el_debug>2)
				printk("%s: burped during tx load.\n", dev->name);
			goto load_it_again_sam;	/* Sigh... */
		}
#endif
		outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */
		lp->loading=0;
#ifdef BLOCKOUT_1		
		enable_irq(dev->irq);
#endif		
		dev->trans_start = jiffies;
	}

	if (el_debug > 2)
		printk(" queued xmit.\n");
	dev_kfree_skb (skb, FREE_WRITE);
	return 0;
}
예제 #7
0
static int
el_start_xmit(struct sk_buff *skb, struct device *dev)
{

    if (dev->tbusy) {
	if (jiffies - dev->trans_start < 20) {
	    if (el_debug > 2)
		printk(" transmitter busy, deferred.\n");
	    return 1;
	}
	if (el_debug)
	    printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
		    dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
	el_status.stats.tx_errors++;
#ifdef oldway
	el_reset(dev);
#else
	outb(TX_NORM, TX_CMD);
	outb(RX_NORM, RX_CMD);
	outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
#endif
	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
	dev->tbusy = 0;
	dev->trans_start = jiffies;
    }

    if (skb == NULL) {
	dev_tint(dev);
	return 0;
    }

    /* Fill in the ethernet header. */
    if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {
	skb->dev = dev;
	arp_queue (skb);
	return 0;
    }
    skb->arp=1;

    if (skb->len <= 0)
	return 0;

    /* Avoid timer-based retransmission conflicts. */
    if (set_bit(0, (void*)&dev->tbusy) != 0)
	printk("%s: Transmitter access conflict.\n", dev->name);
    else {
	int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
	unsigned char *buf = skb->data;

	el_status.tx_pkt_start = gp_start;
    	el_status.collisions = 0;

	outb(AX_SYS, AX_CMD);
	inb(RX_STATUS);
	inb(TX_STATUS);
	outb(0x00, RX_BUF_CLR);	/* Set rx packet area to 0. */
	outw(gp_start, GP_LOW);
	outsb(DATAPORT,buf,skb->len);
	outw(gp_start, GP_LOW);
	outb(AX_XMIT, AX_CMD);		/* Trigger xmit.  */
	dev->trans_start = jiffies;
    }

    if (el_debug > 2)
	printk(" queued xmit.\n");
    if (skb->free)
	kfree_skb (skb, FREE_WRITE);
    return 0;
}
예제 #8
0
파일: ni52.c 프로젝트: openmach/openmach
static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
{
  int len,i;
#ifndef NO_NOPCOMMANDS
  int next_nop;
#endif
  struct priv *p = (struct priv *) dev->priv;

  if(dev->tbusy)
  {
    int tickssofar = jiffies - dev->trans_start;
    if (tickssofar < 5)
      return 1;

    if(p->scb->status & CU_ACTIVE) /* COMMAND-UNIT active? */
    {
      dev->tbusy = 0;
#ifdef DEBUG
      printk("%s: strange ... timeout with CU active?!?\n",dev->name);
      printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);
#endif
      p->scb->cmd = CUC_ABORT;
      ni_attn586();
      WAIT_4_SCB_CMD();
      p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
      p->scb->cmd = CUC_START;
      ni_attn586();
      WAIT_4_SCB_CMD();
      dev->trans_start = jiffies;
      return 0;
    }
    else
    {
#ifdef DEBUG
      printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status);
      printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
#endif
      ni52_close(dev);
      ni52_open(dev);
    }
    dev->trans_start = jiffies;
    return 0;
  }

  if(skb == NULL)
  {
    dev_tint(dev);
    return 0;
  }

  if (skb->len <= 0)
    return 0;
  if(skb->len > XMIT_BUFF_SIZE)
  {
    printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
    return 0;
  }

  if (set_bit(0, (void*)&dev->tbusy) != 0)
     printk("%s: Transmitter access conflict.\n", dev->name);
  else
  {
    memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
    len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;

#if (NUM_XMIT_BUFFS == 1)
#  ifdef NO_NOPCOMMANDS
    p->xmit_buffs[0]->size = TBD_LAST | len;
    for(i=0;i<16;i++)
    {
      p->scb->cbl_offset = make16(p->xmit_cmds[0]);
      p->scb->cmd = CUC_START;
      p->xmit_cmds[0]->cmd_status = 0;

      ni_attn586();
      dev->trans_start = jiffies;
      if(!i)
        dev_kfree_skb(skb,FREE_WRITE);
      WAIT_4_SCB_CMD();
      if( (p->scb->status & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */
        break;
      if(p->xmit_cmds[0]->cmd_status)
        break;
      if(i==15)
        printk("%s: Can't start transmit-command.\n",dev->name);
    }
#  else
    next_nop = (p->nop_point + 1) & 0x1;
    p->xmit_buffs[0]->size = TBD_LAST | len;

    p->xmit_cmds[0]->cmd_link   = p->nop_cmds[next_nop]->cmd_link 
                                = make16((p->nop_cmds[next_nop]));
    p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;

    p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
    dev->trans_start = jiffies;
    p->nop_point = next_nop;
    dev_kfree_skb(skb,FREE_WRITE);
#  endif
#else
    p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
    if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) 
      next_nop = 0;

    p->xmit_cmds[p->xmit_count]->cmd_status  = 0;
    p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link 
                                          = make16((p->nop_cmds[next_nop]));
    p->nop_cmds[next_nop]->cmd_status = 0;

    p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
    dev->trans_start = jiffies;
    p->xmit_count = next_nop;
  
    cli();
    if(p->xmit_count != p->xmit_last)
      dev->tbusy = 0;
    sti();
    dev_kfree_skb(skb,FREE_WRITE);
#endif
  }
  return 0;
}
예제 #9
0
static int elp_start_xmit(struct sk_buff *skb, struct device *dev)

{
    elp_device * adapter = (elp_device *) dev->priv;

    CHECK_NULL(dev);

    /*
     * not sure what this does, but the 3c509 driver does it, so...
     */
    if (skb == NULL) {
        dev_tint(dev);
        return 0;
    }

    /*
     * Fill in the ethernet header
     * (for kernels prior to 1.1.4 only)
     */
#if (ELP_KERNEL_TYPE < 2)
    IS_SKB(skb);
    if (!skb->arp && dev->rebuild_header(SKB_DATA, dev)) {
        skb->dev = dev;
        IS_SKB(skb);
        arp_queue (skb);
        return 0;
    }
#endif

    /*
     * if we ended up with a munged length, don't send it
     */
    if (skb->len <= 0)
        return 0;

    if (elp_debug >= 3)
        printk("%s: request to send packet of length %d\n", dev->name, (int)skb->len);

    /*
     * if the transmitter is still busy, we have a transmit timeout...
     */
    if (dev->tbusy) {
        int tickssofar = jiffies - dev->trans_start;
        if (tickssofar < 200) /* was 500, AJT */
            return 1;
        printk("%s: transmit timed out, resetting adapter\n", dev->name);
        if ((INB(adapter->io_addr+PORT_STATUS)&STATUS_ACRF) != 0)
            printk("%s: hmmm...seemed to have missed an interrupt!\n", dev->name);
        adapter_reset(adapter);
        dev->trans_start = jiffies;
        dev->tbusy = 0;
    }

    /*
     * send the packet at skb->data for skb->len
     */
    if (!send_packet(adapter, (unsigned char *)SKB_DATA, skb->len)) {
        printk("%s: send packet PCB failed\n", dev->name);
        return 1;
    }

    if (elp_debug >= 3)
        printk("%s: packet of length %d sent\n", dev->name, (int)skb->len);


    /*
     * start the transmit timeout
     */
    dev->trans_start = jiffies;

    /*
     * the transmitter is now busy
     */
    dev->tbusy = 1;

    /*
     * if we have been asked to free the buffer, do so
     */
#if (ELP_KERNEL_TYPE < 4)
    if (skb->free)
    {
        IS_SKB(skb);
        kfree_skb(skb, FREE_WRITE);
    }
#else
    dev_kfree_skb(skb, FREE_WRITE);
#endif

    return 0;
}
예제 #10
0
/*
 * Copy a buffer to the adapter transmit page memory.
 * Start sending.
 */
static int
d_link_start_xmit(struct sk_buff *skb, struct device *dev)
{
	int		transmit_from;
	int		len;
	int		tickssofar;
	unsigned char	*buffer = skb->data;

	/*
	 * If some higher layer thinks we've missed a
	 * 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 (hardware addresses) with an arp. */
	if (!skb->arp)
		if(dev->rebuild_header(skb->data, dev)) {
			skb->dev = dev;
			arp_queue (skb);
			return 0;
		}
	skb->arp = 1;

	if (free_tx_pages <= 0) {	/* Do timeouts, to avoid hangs. */
		tickssofar = jiffies - dev->trans_start;

		if (tickssofar < 5)
			return 1;

		/* else */
		printk("%s: transmit timed out (%d), %s?\n",
			dev->name,
			tickssofar,
			"network cable problem"
			);
		/* Restart the adapter. */
		adapter_init(dev);
	}

	/* Start real output */
	PRINTK(("d_link_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages));

	if ((len = skb->len) < RUNT)
		len = RUNT;

	cli();
	select_nic();

	tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len;
	tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */

	d_link_setup_address(transmit_from, RW_ADDR);
	for ( ; len > 0; --len, ++buffer)
		d_link_put_byte(*buffer);

	if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
		dev->trans_start = jiffies;
		dev->tbusy = 0;	/* allow more packets into adapter */
		/* Send page and generate an interrupt */
		d_link_setup_address(transmit_from, TX_ADDR);
		d_link_put_command(TX_ENABLE);
	}
	else {
		dev->tbusy = !free_tx_pages;
		select_prn();
	}
	
	sti(); /* interrupts back on */
	
	if (skb->free)
		kfree_skb (skb, FREE_WRITE);

	return 0;
}
예제 #11
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 < 10)
			return 1;
		printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
			   htons(inw(ioaddr + TX_STATUS)),
			   inb(ioaddr + TX_STATUS) & 0x80
			   ? "IRQ conflict" : "network cable problem");
		printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
			   dev->name, htons(inw(ioaddr + 0)),
			   htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
			   htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
			   htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
			   htons(inw(ioaddr +14)));
		printk("eth card: %04x %04x\n",
			htons(inw(ioaddr+FJ_STATUS0)),
			htons(inw(ioaddr+FJ_CONFIG0)));
		lp->stats.tx_errors++;
		/* ToDo: We should try to restart the adaptor... */
		cli();

		/* Initialize LAN Controller and LAN Card */
		outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
		outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
		outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
		outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
		net_open(dev);

		sti();
	}

	/* 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.  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;

		if (length > ETH_FRAME_LEN) {
			if (net_debug)
				printk("%s: Attempting to send a large packet (%d bytes).\n",
					dev->name, length);
			return 1;
		}

		if (net_debug > 4)
			printk("%s: Transmitting a packet of length %lu.\n", dev->name,
				   (unsigned long)skb->len);

		/* Disable both interrupts. */
		outw(0x0000, ioaddr + TX_INTR);
		
		outw(length, ioaddr + DATAPORT);
		outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);

		lp->tx_queue++;
		lp->tx_queue_len += length + 2;

		if (lp->tx_started == 0) {
			/* If the Tx is idle, always trigger a transmit. */
			outb(0x80 | lp->tx_queue, ioaddr + TX_START);
			lp->tx_queue = 0;
			lp->tx_queue_len = 0;
			dev->trans_start = jiffies;
			lp->tx_started = 1;
			dev->tbusy = 0;
		} else if (lp->tx_queue_len < 4096 - 1502)
			/* Yes, there is room for one more packet. */
			dev->tbusy = 0;

		/* Re-enable interrupts */
		outw(0x8182, ioaddr + TX_INTR);
	}
	dev_kfree_skb (skb, FREE_WRITE);

	return 0;
}
예제 #12
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;
}
예제 #13
0
static int
tulip_start_xmit(struct sk_buff *skb, struct device *dev)
{
	struct tulip_private *tp = (struct tulip_private *)dev->priv;
	int ioaddr = dev->base_addr;
	int entry;

	/* Transmitter timeout, serious problems. */
	if (dev->tbusy) {
		int tickssofar = jiffies - dev->trans_start;
		int i;
		if (tickssofar < 20)
			return 1;
		printk("%s: transmit timed out, status %8.8x, SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
			   dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12),
			   inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15));
		printk("  Rx ring %8.8x: ", (int)tp->rx_ring);
		for (i = 0; i < RX_RING_SIZE; i++)
			printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
		printk("\n  Tx ring %8.8x: ", (int)tp->tx_ring);
		for (i = 0; i < TX_RING_SIZE; i++)
			printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
		printk("\n");

		tp->stats.tx_errors++;
		/* We should reinitialize the hardware here. */
		dev->tbusy=0;
		dev->trans_start = jiffies;
		return 0;
	}

	if (skb == NULL || skb->len <= 0) {
		printk("%s: Obsolete driver layer request made: skbuff==NULL.\n",
			   dev->name);
		dev_tint(dev);
		return 0;
	}

	/* 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 this ever occurs the queue layer is doing something evil! */
	if (set_bit(0, (void*)&dev->tbusy) != 0) {
		printk("%s: Transmitter access conflict.\n", dev->name);
		return 1;
	}

	/* Caution: the write order is important here, set the base address
	   with the "ownership" bits last. */

	/* Calculate the next Tx descriptor entry. */
	entry = tp->cur_tx % TX_RING_SIZE;

	tp->tx_full = 1;
	tp->tx_skbuff[entry] = skb;
	tp->tx_ring[entry].length = skb->len |
		(entry == TX_RING_SIZE-1 ? 0xe2000000 : 0xe0000000);
	tp->tx_ring[entry].buffer1 = skb->data;
	tp->tx_ring[entry].buffer2 = 0;
	tp->tx_ring[entry].status = 0x80000000;	/* Pass ownership to the chip. */

	tp->cur_tx++;

	/* Trigger an immediate transmit demand. */
	outl(0, ioaddr + CSR1);

	dev->trans_start = jiffies;

	return 0;
}
예제 #14
0
static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
{
  int len;
#ifndef NO_NOPCOMMANDS
  int next_nop;
#endif
  struct priv *p = (struct priv *) dev->priv;

  if(dev->tbusy)
  {
    int tickssofar = jiffies - dev->trans_start;

    if (tickssofar < 30)
      return 1;

#ifdef DEBUG
    printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status);
    printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
#endif

    ni52_close(dev);
    ni52_open(dev);
    dev->trans_start = jiffies;
  }

  if(skb == NULL)
  {
    dev_tint(dev);
    return 0;
  }

  if (skb->len <= 0)
    return 0;

  if (set_bit(0, (void*)&dev->tbusy) != 0)
     printk("%s: Transmitter access conflict.\n", dev->name);
  else
  {
    memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
    len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;

#ifdef ONLY_ONE_XMIT_BUF  
#  ifdef NO_NOPCOMMANDS
    p->xmit_buffs[0]->size = TBD_LAST | len;
    p->xmit_cmds[0]->cmd_status = 0;
    p->scb->cbl_offset = make16(p->xmit_cmds[0]);
    p->scb->cmd = CUC_START;

    dev->trans_start = jiffies;
    ni_attn586();
    while(p->scb->cmd)
      for(len=0;len<256;len++);

  /*  DELAY(1); */ /* TEST;TEST;TEST */
#  else
    next_nop = (p->nop_point + 1) & 0x1;
    p->xmit_buffs[0]->size = TBD_LAST | len;

    p->xmit_cmds[0]->cmd_cmd    = CMD_XMIT | CMD_INT;
    p->xmit_cmds[0]->cmd_status = 0;
    p->xmit_cmds[0]->cmd_link   = p->nop_cmds[next_nop]->cmd_link 
                                = make16((p->nop_cmds[next_nop]));
    p->nop_cmds[next_nop]->cmd_status = 0;

    p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
    dev->trans_start = jiffies;
    p->nop_point = next_nop;
#  endif
#else
    p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
    if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) 
      next_nop = 0;

    p->xmit_cmds[p->xmit_count]->cmd_cmd  = CMD_XMIT | CMD_INT;
    p->xmit_cmds[p->xmit_count]->cmd_status  = 0;
    p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link 
                                          = make16((p->nop_cmds[next_nop]));
    p->nop_cmds[next_nop]->cmd_status = 0;

    p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
    dev->trans_start = jiffies;
    p->xmit_count = next_nop;
  
    cli();
    if(p->xmit_count != p->xmit_last)
      dev->tbusy = 0;
    sti();
#endif
  }

  dev_kfree_skb(skb,FREE_WRITE);

  return 0;
}
예제 #15
0
파일: znet.c 프로젝트: openmach/openmach
static int znet_send_packet(struct sk_buff *skb, struct device *dev)
{
	int ioaddr = dev->base_addr;

	if (znet_debug > 4)
		printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy);

	/* Transmitter timeout, likely just recovery after suspending the machine. */
	if (dev->tbusy) {
		ushort event, tx_status, rx_offset, state;
		int tickssofar = jiffies - dev->trans_start;
		if (tickssofar < 10)
			return 1;
		outb(CMD0_STAT0, ioaddr); event = inb(ioaddr);
		outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr);
		outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr);
		outb(CMD0_STAT3, ioaddr); state = inb(ioaddr);
		printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x,"
			   " resetting.\n", dev->name, event, tx_status, rx_offset, state);
		if (tx_status == 0x0400)
		  printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n",
				 dev->name);
		outb(CMD0_RESET, ioaddr);
		hardware_init(dev);
	}

	if (skb == NULL) {
		dev_tint(dev);
		return 0;
	}

	/* Check that the part hasn't reset itself, probably from suspend. */
	outb(CMD0_STAT0, ioaddr);
	if (inw(ioaddr) == 0x0010
		&& inw(ioaddr) == 0x0000
		&& inw(ioaddr) == 0x0010)
	  hardware_init(dev);

	/* 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(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
	else {
		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
		unsigned char *buf = (void *)skb->data;
		ushort *tx_link = zn.tx_cur - 1;
		ushort rnd_len = (length + 1)>>1;

		{
			short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE;
			unsigned addr = inb(dma_port);
			addr |= inb(dma_port) << 8;
			addr <<= 1;
			if (((int)zn.tx_cur & 0x1ffff) != addr)
			  printk(KERN_WARNING "Address mismatch at Tx: %#x vs %#x.\n",
					 (int)zn.tx_cur & 0xffff, addr);
			zn.tx_cur = (ushort *)(((int)zn.tx_cur & 0xfe0000) | addr);
		}

		if (zn.tx_cur >= zn.tx_end)
		  zn.tx_cur = zn.tx_start;
		*zn.tx_cur++ = length;
		if (zn.tx_cur + rnd_len + 1 > zn.tx_end) {
			int semi_cnt = (zn.tx_end - zn.tx_cur)<<1; /* Cvrt to byte cnt. */
			memcpy(zn.tx_cur, buf, semi_cnt);
			rnd_len -= semi_cnt>>1;
			memcpy(zn.tx_start, buf + semi_cnt, length - semi_cnt);
			zn.tx_cur = zn.tx_start + rnd_len;
		} else {
예제 #16
0
static int
i596_start_xmit(struct sk_buff *skb, struct device *dev)
{
    struct i596_private *lp = (struct i596_private *)dev->priv;
    int ioaddr = dev->base_addr;
    struct tx_cmd *tx_cmd;

    if (i596_debug > 2) printk ("%s: Apricot start xmit\n", dev->name);

    /* Transmitter timeout, serious problems. */
    if (dev->tbusy) {
	int tickssofar = jiffies - dev->trans_start;
	if (tickssofar < 5)
	    return 1;
	printk("%s: transmit timed out, status resetting.\n",
	       dev->name);
	lp->stats.tx_errors++;
	/* Try to restart the adaptor */
	if (lp->last_restart == lp->stats.tx_packets) {
	    if (i596_debug > 1) printk ("Resetting board.\n");

	    /* Shutdown and restart */
            i596_reset(dev,lp, ioaddr);
	} else {
	    /* Issue a channel attention signal */
	    if (i596_debug > 1) printk ("Kicking board.\n");

	    lp->scb.command = CUC_START|RX_START;
	    outw(0, ioaddr+4);

	    lp->last_restart = lp->stats.tx_packets;
	}
	dev->tbusy = 0;
	dev->trans_start = jiffies;
    }

    /* If some higher level thinks we've misses a tx-done interrupt
       we are passed NULL. n.b. dev_tint handles the cli()/sti()
       itself. */
    if (skb == NULL) {
	dev_tint(dev);
	return 0;
    }

    /* shouldn't happen */
    if (skb->len <= 0) return 0;

    if (i596_debug > 3) printk("%s: i596_start_xmit() called\n", dev->name);

    /* 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;
	dev->trans_start = jiffies;

	tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
	if (tx_cmd == NULL)
	{
	    printk ("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
	    lp->stats.tx_dropped++;

	    dev_kfree_skb(skb, FREE_WRITE);
	}
	else
	{
	    tx_cmd->tbd = (struct i596_tbd *) (tx_cmd + 1);
	    tx_cmd->tbd->next = (struct i596_tbd *) I596_NULL;

	    tx_cmd->cmd.command = CMD_FLEX|CmdTx;

	    tx_cmd->pad = 0;
	    tx_cmd->size = 0;
	    tx_cmd->tbd->pad = 0;
	    tx_cmd->tbd->size = EOF | length;

	    tx_cmd->tbd->data = skb->data;

	    if (i596_debug > 3) print_eth(skb->data);

	    i596_add_cmd(dev, (struct i596_cmd *)tx_cmd);

	    lp->stats.tx_packets++;
	}
    }

    dev->tbusy = 0;

    return 0;
}
예제 #17
0
static int
net_send_packet(struct sk_buff *skb, struct device *dev)
{
	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 > 0) printk("%s: transmit timed out, %s?\n", dev->name,
			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
		/* Try to restart the adaptor. */
		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.  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 {
		struct net_local *lp = (struct net_local *)dev->priv;
		unsigned long ioaddr = dev->base_addr;
		unsigned long flags;

		if (net_debug > 3)printk("%s: sent %ld byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);

		/* keep the upload from being interrupted, since we
                   ask the chip to start transmitting before the
                   whole packet has been completely uploaded. */
		save_flags(flags);
		cli();

		/* initiate a transmit sequence */
		outw(lp->send_cmd, ioaddr + TX_CMD_PORT);
		outw(skb->len, ioaddr + TX_LEN_PORT);

		/* Test to see if the chip has allocated memory for the packet */
		if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
			/* Gasp!  It hasn't.  But that shouldn't happen since
			   we're waiting for TxOk, so return 1 and requeue this packet. */
			restore_flags(flags);
			printk("cs8900 did not allocate memory for tx!\n");
			return 1;
		}

		/* Write the contents of the packet */
                outsw(ioaddr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);

		restore_flags(flags);
		dev->trans_start = jiffies;
	}
	dev_kfree_skb (skb, FREE_WRITE);

	return 0;
}