 if (residue) { buf += len; len = residue; continue; } 
static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev){	struct ns83820 *dev = PRIV(ndev);	u32 free_idx, cmdsts, extsts;	int nr_free, nr_frags;	unsigned tx_done_idx, last_idx;	dma_addr_t buf;	unsigned len;	skb_frag_t *frag;	int stopped = 0;	int do_intr = 0;	volatile u32 *first_desc;	dprintk("ns83820_hard_start_xmit\n");	nr_frags =  skb_shinfo(skb)->nr_frags;again:	if (unlikely(dev->CFG_cache & CFG_LNKSTS)) {		netif_stop_queue(ndev);		if (unlikely(dev->CFG_cache & CFG_LNKSTS))			return 1;		netif_start_queue(ndev);	}	last_idx = free_idx = dev->tx_free_idx;	tx_done_idx = dev->tx_done_idx;	nr_free = (tx_done_idx + NR_TX_DESC-2 - free_idx) % NR_TX_DESC;	nr_free -= 1;	if (nr_free <= nr_frags) {		dprintk("stop_queue - not enough(%p)\n", ndev);		netif_stop_queue(ndev);		/* Check again: we may have raced with a tx done irq */		if (dev->tx_done_idx != tx_done_idx) {			dprintk("restart queue(%p)\n", ndev);			netif_start_queue(ndev);			goto again;		}		return 1;	}	if (free_idx == dev->tx_intr_idx) {		do_intr = 1;		dev->tx_intr_idx = (dev->tx_intr_idx + NR_TX_DESC/4) % NR_TX_DESC;	}	nr_free -= nr_frags;	if (nr_free < MIN_TX_DESC_FREE) {		dprintk("stop_queue - last entry(%p)\n", ndev);		netif_stop_queue(ndev);		stopped = 1;	}	frag = skb_shinfo(skb)->frags;	if (!nr_frags)		frag = NULL;	extsts = 0;	if (skb->ip_summed == CHECKSUM_HW) {		extsts |= EXTSTS_IPPKT;		if (IPPROTO_TCP == skb->nh.iph->protocol)			extsts |= EXTSTS_TCPPKT;		else if (IPPROTO_UDP == skb->nh.iph->protocol)			extsts |= EXTSTS_UDPPKT;	}#ifdef NS83820_VLAN_ACCEL_SUPPORT	if(vlan_tx_tag_present(skb)) {		/* fetch the vlan tag info out of the		 * ancilliary data if the vlan code		 * is using hw vlan acceleration		 */		short tag = vlan_tx_tag_get(skb);		extsts |= (EXTSTS_VPKT | htons(tag));	}#endif	len = skb->len;	if (nr_frags)		len -= skb->data_len;	buf = pci_map_single(dev->pci_dev, skb->data, len, PCI_DMA_TODEVICE);	first_desc = dev->tx_descs + (free_idx * DESC_SIZE);	for (;;) {		volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE);		u32 residue = 0;		dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len,			(unsigned long long)buf);		last_idx = free_idx;		free_idx = (free_idx + 1) % NR_TX_DESC;		desc[DESC_LINK] = cpu_to_le32(dev->tx_phy_descs + (free_idx * DESC_SIZE * 4));		desc_addr_set(desc + DESC_BUFPTR, buf);		desc[DESC_EXTSTS] = cpu_to_le32(extsts);		cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0);		cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN;		cmdsts |= len;		desc[DESC_CMDSTS] = cpu_to_le32(cmdsts);		if (residue) {			buf += len;			len = residue;			continue;		}		if (!nr_frags)			break;		buf = pci_map_page(dev->pci_dev, frag->page,				   frag->page_offset,				   frag->size, PCI_DMA_TODEVICE);		dprintk("frag: buf=%08Lx  page=%08lx offset=%08lx\n",			(long long)buf, (long) page_to_pfn(frag->page),			frag->page_offset);		len = frag->size;		frag++;		nr_frags--;	}	dprintk("done pkt\n");	spin_lock_irq(&dev->tx_lock);	dev->tx_skbs[last_idx] = skb;	first_desc[DESC_CMDSTS] |= cpu_to_le32(CMDSTS_OWN);	dev->tx_free_idx = free_idx;	atomic_inc(&dev->nr_tx_skbs);	spin_unlock_irq(&dev->tx_lock);	kick_tx(dev);	/* Check again: we may have raced with a tx done irq */	if (stopped && (dev->tx_done_idx != tx_done_idx) && start_tx_okay(dev))		netif_start_queue(ndev);	/* set the transmit start time to catch transmit timeouts */	ndev->trans_start = jiffies;	return 0;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/c16ef1ceedff27c1b452724ca7f89b729651098f/ns83820.c/buggy/drivers/net/ns83820.c