📄 de2104x.c
字号:
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 + -