⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 de2104x.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
			BUG();		if (unlikely(skb == DE_DUMMY_SKB))			goto next;		if (unlikely(skb == DE_SETUP_SKB)) {			pci_unmap_single(de->pdev, de->tx_skb[tx_tail].mapping,					 sizeof(de->setup_frame), PCI_DMA_TODEVICE);			goto next;		}		pci_unmap_single(de->pdev, de->tx_skb[tx_tail].mapping,				 skb->len, PCI_DMA_TODEVICE);		if (status & LastFrag) {			if (status & TxError) {				if (netif_msg_tx_err(de))					printk(KERN_DEBUG "%s: tx err, status 0x%x\n",					       de->dev->name, status);				de->net_stats.tx_errors++;				if (status & TxOWC)					de->net_stats.tx_window_errors++;				if (status & TxMaxCol)					de->net_stats.tx_aborted_errors++;				if (status & TxLinkFail)					de->net_stats.tx_carrier_errors++;				if (status & TxFIFOUnder)					de->net_stats.tx_fifo_errors++;			} else {				de->net_stats.tx_packets++;				de->net_stats.tx_bytes += skb->len;				if (netif_msg_tx_done(de))					printk(KERN_DEBUG "%s: tx done, slot %d\n", de->dev->name, tx_tail);			}			dev_kfree_skb_irq(skb);		}next:		de->tx_skb[tx_tail].skb = NULL;		tx_tail = NEXT_TX(tx_tail);	}	de->tx_tail = tx_tail;	if (netif_queue_stopped(de->dev) && (TX_BUFFS_AVAIL(de) > (DE_TX_RING_SIZE / 4)))		netif_wake_queue(de->dev);}static int de_start_xmit (struct sk_buff *skb, struct net_device *dev){	struct de_private *de = dev->priv;	unsigned int entry, tx_free;	u32 mapping, len, flags = FirstFrag | LastFrag;	struct de_desc *txd;	spin_lock_irq(&de->lock);	tx_free = TX_BUFFS_AVAIL(de);	if (tx_free == 0) {		netif_stop_queue(dev);		spin_unlock_irq(&de->lock);		return 1;	}	tx_free--;	entry = de->tx_head;	txd = &de->tx_ring[entry];	len = skb->len;	mapping = pci_map_single(de->pdev, skb->data, len, PCI_DMA_TODEVICE);	if (entry == (DE_TX_RING_SIZE - 1))		flags |= RingEnd;	if (!tx_free || (tx_free == (DE_TX_RING_SIZE / 2)))		flags |= TxSwInt;	flags |= len;	txd->opts2 = cpu_to_le32(flags);	txd->addr1 = cpu_to_le32(mapping);	de->tx_skb[entry].skb = skb;	de->tx_skb[entry].mapping = mapping;	wmb();	txd->opts1 = cpu_to_le32(DescOwn);	wmb();	de->tx_head = NEXT_TX(entry);	if (netif_msg_tx_queued(de))		printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",		       dev->name, entry, skb->len);	if (tx_free == 0)		netif_stop_queue(dev);	spin_unlock_irq(&de->lock);	/* Trigger an immediate transmit demand. */	dw32(TxPoll, NormalTxPoll);	dev->trans_start = jiffies;	return 0;}/* Set or clear the multicast filter for this adaptor.   Note that we only use exclusion around actually queueing the   new frame, not around filling de->setup_frame.  This is non-deterministic   when re-entered but still correct. */#undef set_bit_le#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev){	struct de_private *de = dev->priv;	u16 hash_table[32];	struct dev_mc_list *mclist;	int i;	u16 *eaddrs;	memset(hash_table, 0, sizeof(hash_table));	set_bit_le(255, hash_table); 			/* Broadcast entry */	/* This should work on big-endian machines as well. */	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;	     i++, mclist = mclist->next) {		int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff;		set_bit_le(index, hash_table);		for (i = 0; i < 32; i++) {			*setup_frm++ = hash_table[i];			*setup_frm++ = hash_table[i];		}		setup_frm = &de->setup_frame[13*6];	}	/* Fill the final entry with our physical address. */	eaddrs = (u16 *)dev->dev_addr;	*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];	*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];	*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];}static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev){	struct de_private *de = dev->priv;	struct dev_mc_list *mclist;	int i;	u16 *eaddrs;	/* We have <= 14 addresses so we can use the wonderful	   16 address perfect filtering of the Tulip. */	for (i = 0, mclist = dev->mc_list; i < dev->mc_count;	     i++, mclist = mclist->next) {		eaddrs = (u16 *)mclist->dmi_addr;		*setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;		*setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;		*setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;	}	/* Fill the unused entries with the broadcast address. */	memset(setup_frm, 0xff, (15-i)*12);	setup_frm = &de->setup_frame[15*6];	/* Fill the final entry with our physical address. */	eaddrs = (u16 *)dev->dev_addr;	*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];	*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];	*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];}static void __de_set_rx_mode (struct net_device *dev){	struct de_private *de = dev->priv;	u32 macmode;	unsigned int entry;	u32 mapping;	struct de_desc *txd;	struct de_desc *dummy_txd = NULL;	macmode = dr32(MacMode) & ~(AcceptAllMulticast | AcceptAllPhys);	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */		macmode |= AcceptAllMulticast | AcceptAllPhys;		goto out;	}	if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {		/* Too many to filter well -- accept all multicasts. */		macmode |= AcceptAllMulticast;		goto out;	}	/* Note that only the low-address shortword of setup_frame is valid!	   The values are doubled for big-endian architectures. */	if (dev->mc_count > 14)	/* Must use a multicast hash table. */		build_setup_frame_hash (de->setup_frame, dev);	else		build_setup_frame_perfect (de->setup_frame, dev);	/*	 * Now add this frame to the Tx list.	 */	entry = de->tx_head;	/* Avoid a chip errata by prefixing a dummy entry. */	if (entry != 0) {		de->tx_skb[entry].skb = DE_DUMMY_SKB;		dummy_txd = &de->tx_ring[entry];		dummy_txd->opts2 = (entry == (DE_TX_RING_SIZE - 1)) ?				   cpu_to_le32(RingEnd) : 0;		dummy_txd->addr1 = 0;		/* Must set DescOwned later to avoid race with chip */		entry = NEXT_TX(entry);	}	de->tx_skb[entry].skb = DE_SETUP_SKB;	de->tx_skb[entry].mapping = mapping =	    pci_map_single (de->pdev, de->setup_frame,			    sizeof (de->setup_frame), PCI_DMA_TODEVICE);	/* Put the setup frame on the Tx list. */	txd = &de->tx_ring[entry];	if (entry == (DE_TX_RING_SIZE - 1))		txd->opts2 = cpu_to_le32(SetupFrame | RingEnd | sizeof (de->setup_frame));	else		txd->opts2 = cpu_to_le32(SetupFrame | sizeof (de->setup_frame));	txd->addr1 = cpu_to_le32(mapping);	wmb();	txd->opts1 = cpu_to_le32(DescOwn);	wmb();	if (dummy_txd) {		dummy_txd->opts1 = cpu_to_le32(DescOwn);		wmb();	}	de->tx_head = NEXT_TX(entry);	if (TX_BUFFS_AVAIL(de) < 0)		BUG();	if (TX_BUFFS_AVAIL(de) == 0)		netif_stop_queue(dev);	/* Trigger an immediate transmit demand. */	dw32(TxPoll, NormalTxPoll);out:	if (macmode != dr32(MacMode))		dw32(MacMode, macmode);}static void de_set_rx_mode (struct net_device *dev){	unsigned long flags;	struct de_private *de = dev->priv;	spin_lock_irqsave (&de->lock, flags);	__de_set_rx_mode(dev);	spin_unlock_irqrestore (&de->lock, flags);}static inline void de_rx_missed(struct de_private *de, u32 rx_missed){	if (unlikely(rx_missed & RxMissedOver))		de->net_stats.rx_missed_errors += RxMissedMask;	else		de->net_stats.rx_missed_errors += (rx_missed & RxMissedMask);}static void __de_get_stats(struct de_private *de){	u32 tmp = dr32(RxMissed); /* self-clearing */	de_rx_missed(de, tmp);}static struct net_device_stats *de_get_stats(struct net_device *dev){	struct de_private *de = dev->priv;	/* The chip only need report frame silently dropped. */	spin_lock_irq(&de->lock); 	if (netif_running(dev) && netif_device_present(dev)) 		__de_get_stats(de);	spin_unlock_irq(&de->lock);	return &de->net_stats;}static inline int de_is_running (struct de_private *de){	return (dr32(MacStatus) & (RxState | TxState)) ? 1 : 0;}static void de_stop_rxtx (struct de_private *de){	u32 macmode;	unsigned int work = 1000;	macmode = dr32(MacMode);	if (macmode & RxTx) {		dw32(MacMode, macmode & ~RxTx);		dr32(MacMode);	}	while (--work > 0) {		if (!de_is_running(de))			return;		cpu_relax();	}		printk(KERN_WARNING "%s: timeout expired stopping DMA\n", de->dev->name);}static inline void de_start_rxtx (struct de_private *de){	u32 macmode;	macmode = dr32(MacMode);	if ((macmode & RxTx) != RxTx) {		dw32(MacMode, macmode | RxTx);		dr32(MacMode);	}}static void de_stop_hw (struct de_private *de){	udelay(5);	dw32(IntrMask, 0);	de_stop_rxtx(de);	dw32(MacStatus, dr32(MacStatus));	udelay(10);	de->rx_tail = 0;	de->tx_head = de->tx_tail = 0;}static void de_link_up(struct de_private *de){	if (!netif_carrier_ok(de->dev)) {		netif_carrier_on(de->dev);		if (netif_msg_link(de))			printk(KERN_INFO "%s: link up, media %s\n",			       de->dev->name, media_name[de->media_type]);	}}static void de_link_down(struct de_private *de){	if (netif_carrier_ok(de->dev)) {		netif_carrier_off(de->dev);		if (netif_msg_link(de))			printk(KERN_INFO "%s: link down\n", de->dev->name);	}}static void de_set_media (struct de_private *de){	unsigned media = de->media_type;	u32 macmode = dr32(MacMode);	if (de_is_running(de))		BUG();	if (de->de21040)		dw32(CSR11, FULL_DUPLEX_MAGIC);	dw32(CSR13, 0); /* Reset phy */	dw32(CSR14, de->media[media].csr14);	dw32(CSR15, de->media[media].csr15);	dw32(CSR13, de->media[media].csr13);	/* must delay 10ms before writing to other registers,	 * especially CSR6	 */	mdelay(10);	if (media == DE_MEDIA_TP_FD)		macmode |= FullDuplex;	else		macmode &= ~FullDuplex;		if (netif_msg_link(de)) {		printk(KERN_INFO "%s: set link %s\n"		       KERN_INFO "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"		       KERN_INFO "%s:    set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",		       de->dev->name, media_name[media],		       de->dev->name, dr32(MacMode), dr32(SIAStatus),		       dr32(CSR13), dr32(CSR14), dr32(CSR15),		       de->dev->name, macmode, de->media[media].csr13,		       de->media[media].csr14, de->media[media].csr15);	}	if (macmode != dr32(MacMode))		dw32(MacMode, macmode);}static void de_next_media (struct de_private *de, u32 *media,			   unsigned int n_media){	unsigned int i;	for (i = 0; i < n_media; i++) {		if (de_ok_to_advertise(de, media[i])) {			de->media_type = media[i];			return;		}	}}static void de21040_media_timer (unsigned long data){	struct de_private *de = (struct de_private *) data;	struct net_device *dev = de->dev;	u32 status = dr32(SIAStatus);	unsigned int carrier;	unsigned long flags;		carrier = (status & NetCxnErr) ? 0 : 1;			if (carrier) {		if (de->media_type != DE_MEDIA_AUI && (status & LinkFailStatus))			goto no_link_yet;		de->media_timer.expires = jiffies + DE_TIMER_LINK;		add_timer(&de->media_timer);		if (!netif_carrier_ok(dev))			de_link_up(de);		else			if (netif_msg_timer(de))				printk(KERN_INFO "%s: %s link ok, status %x\n",				       dev->name, media_name[de->media_type],				       status);		return;	}	de_link_down(de);		if (de->media_lock)		return;	if (de->media_type == DE_MEDIA_AUI) {		u32 next_state = DE_MEDIA_TP;		de_next_media(de, &next_state, 1);	} else {		u32 next_state = DE_MEDIA_AUI;		de_next_media(de, &next_state, 1);	}	spin_lock_irqsave(&de->lock, flags);	de_stop_rxtx(de);	spin_unlock_irqrestore(&de->lock, flags);	de_set_media(de);	de_start_rxtx(de);no_link_yet:	de->media_timer.expires = jiffies + DE_TIMER_NO_LINK;	add_timer(&de->media_timer);	if (netif_msg_timer(de))		printk(KERN_INFO "%s: no link, trying media %s, status %x\n",		       dev->name, media_name[de->media_type], status);}static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media){	switch (new_media) {	case DE_MEDIA_TP_AUTO:		if (!(de->media_advertise & ADVERTISED_Autoneg))			return 0;		if (!(de->media_advertise & (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full)))			return 0;		break;	case DE_MEDIA_BNC:		if (!(de->media_advertise & ADVERTISED_BNC))			return 0;		break;	case DE_MEDIA_AUI:		if (!(de->media_advertise & ADVERTISED_AUI))			return 0;		break;	case DE_MEDIA_TP:		if (!(de->media_advertise & ADVERTISED_10baseT_Half))			return 0;		break;	case DE_MEDIA_TP_FD:		if (!(de->media_advertise & ADVERTISED_10baseT_Full))			return 0;		break;	}		return 1;}static void de21041_media_timer (unsigned long data){	struct de_private *de = (struct de_private *) data;	struct net_device *dev = de->dev;	u32 status = dr32(SIAStatus);	unsigned int carrier;	unsigned long flags;		carrier = (status & NetCxnErr) ? 0 : 1;			if (carrier) {		if ((de->media_type == DE_MEDIA_TP_AUTO ||		     de->media_type == DE_MEDIA_TP ||		     de->media_type == DE_MEDIA_TP_FD) &&		    (status & LinkFailStatus))			goto no_link_yet;		de->media_timer.expires = jiffies + DE_TIMER_LINK;		add_timer(&de->media_timer);		if (!netif_carrier_ok(dev))			de_link_up(de);		else			if (netif_msg_timer(de))				printk(KERN_INFO "%s: %s link ok, mode %x status %x\n",				       dev->name, media_name[de->media_type],				       dr32(MacMode), status);		return;	}	de_link_down(de);		/* if media type locked, don't switch media */	if (de->media_lock)		goto set_media;	/* if activity detected, use that as hint for new media type */	if (status & NonselPortActive) {		unsigned int have_media = 1;		/* if AUI/BNC selected, then activity is on TP port */		if (de->media_type == DE_MEDIA_AUI ||		    de->media_type == DE_MEDIA_BNC) {			if (de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))				de->media_type = DE_MEDIA_TP_AUTO;			else				have_media = 0;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -