📄 de2104x.c
字号:
/* TP selected. If there is only TP and BNC, then it's BNC */ else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_BNC) && de_ok_to_advertise(de, DE_MEDIA_BNC)) de->media_type = DE_MEDIA_BNC; /* TP selected. If there is only TP and AUI, then it's AUI */ else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_AUI) && de_ok_to_advertise(de, DE_MEDIA_AUI)) de->media_type = DE_MEDIA_AUI; /* otherwise, ignore the hint */ else have_media = 0; if (have_media) goto set_media; } /* * Absent or ambiguous activity hint, move to next advertised * media state. If de->media_type is left unchanged, this * simply resets the PHY and reloads the current media settings. */ if (de->media_type == DE_MEDIA_AUI) { u32 next_states[] = { DE_MEDIA_BNC, DE_MEDIA_TP_AUTO }; de_next_media(de, next_states, ARRAY_SIZE(next_states)); } else if (de->media_type == DE_MEDIA_BNC) { u32 next_states[] = { DE_MEDIA_TP_AUTO, DE_MEDIA_AUI }; de_next_media(de, next_states, ARRAY_SIZE(next_states)); } else { u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO }; de_next_media(de, next_states, ARRAY_SIZE(next_states)); } set_media: 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 void de_media_interrupt (struct de_private *de, u32 status){ if (status & LinkPass) { de_link_up(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); return; } if (!(status & LinkFail)) BUG(); if (netif_carrier_ok(de->dev)) { de_link_down(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); }}static int de_reset_mac (struct de_private *de){ u32 status, tmp; /* * Reset MAC. de4x5.c and tulip.c examined for "advice" * in this area. */ if (dr32(BusMode) == 0xffffffff) return -EBUSY; /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ dw32 (BusMode, CmdReset); mdelay (1); dw32 (BusMode, de_bus_mode); mdelay (1); for (tmp = 0; tmp < 5; tmp++) { dr32 (BusMode); mdelay (1); } mdelay (1); status = dr32(MacStatus); if (status & (RxState | TxState)) return -EBUSY; if (status == 0xffffffff) return -ENODEV; return 0;}static void de_adapter_wake (struct de_private *de){ u32 pmctl; if (de->de21040) return; pci_read_config_dword(de->pdev, PCIPM, &pmctl); if (pmctl & PM_Mask) { pmctl &= ~PM_Mask; pci_write_config_dword(de->pdev, PCIPM, pmctl); /* de4x5.c delays, so we do too */ msleep(10); }}static void de_adapter_sleep (struct de_private *de){ u32 pmctl; if (de->de21040) return; pci_read_config_dword(de->pdev, PCIPM, &pmctl); pmctl |= PM_Sleep; pci_write_config_dword(de->pdev, PCIPM, pmctl);}static int de_init_hw (struct de_private *de){ struct net_device *dev = de->dev; u32 macmode; int rc; de_adapter_wake(de); macmode = dr32(MacMode) & ~MacModeClear; rc = de_reset_mac(de); if (rc) return rc; de_set_media(de); /* reset phy */ dw32(RxRingAddr, de->ring_dma); dw32(TxRingAddr, de->ring_dma + (sizeof(struct de_desc) * DE_RX_RING_SIZE)); dw32(MacMode, RxTx | macmode); dr32(RxMissed); /* self-clearing */ dw32(IntrMask, de_intr_mask); de_set_rx_mode(dev); return 0;}static int de_refill_rx (struct de_private *de){ unsigned i; for (i = 0; i < DE_RX_RING_SIZE; i++) { struct sk_buff *skb; skb = dev_alloc_skb(de->rx_buf_sz); if (!skb) goto err_out; skb->dev = de->dev; de->rx_skb[i].mapping = pci_map_single(de->pdev, skb->data, de->rx_buf_sz, PCI_DMA_FROMDEVICE); de->rx_skb[i].skb = skb; de->rx_ring[i].opts1 = cpu_to_le32(DescOwn); if (i == (DE_RX_RING_SIZE - 1)) de->rx_ring[i].opts2 = cpu_to_le32(RingEnd | de->rx_buf_sz); else de->rx_ring[i].opts2 = cpu_to_le32(de->rx_buf_sz); de->rx_ring[i].addr1 = cpu_to_le32(de->rx_skb[i].mapping); de->rx_ring[i].addr2 = 0; } return 0;err_out: de_clean_rings(de); return -ENOMEM;}static int de_init_rings (struct de_private *de){ memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE); de->tx_ring[DE_TX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd); de->rx_tail = 0; de->tx_head = de->tx_tail = 0; return de_refill_rx (de);}static int de_alloc_rings (struct de_private *de){ de->rx_ring = pci_alloc_consistent(de->pdev, DE_RING_BYTES, &de->ring_dma); if (!de->rx_ring) return -ENOMEM; de->tx_ring = &de->rx_ring[DE_RX_RING_SIZE]; return de_init_rings(de);}static void de_clean_rings (struct de_private *de){ unsigned i; memset(de->rx_ring, 0, sizeof(struct de_desc) * DE_RX_RING_SIZE); de->rx_ring[DE_RX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd); wmb(); memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE); de->tx_ring[DE_TX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd); wmb(); for (i = 0; i < DE_RX_RING_SIZE; i++) { if (de->rx_skb[i].skb) { pci_unmap_single(de->pdev, de->rx_skb[i].mapping, de->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(de->rx_skb[i].skb); } } for (i = 0; i < DE_TX_RING_SIZE; i++) { struct sk_buff *skb = de->tx_skb[i].skb; if ((skb) && (skb != DE_DUMMY_SKB)) { if (skb != DE_SETUP_SKB) { dev_kfree_skb(skb); de->net_stats.tx_dropped++; pci_unmap_single(de->pdev, de->tx_skb[i].mapping, skb->len, PCI_DMA_TODEVICE); } else { pci_unmap_single(de->pdev, de->tx_skb[i].mapping, sizeof(de->setup_frame), PCI_DMA_TODEVICE); } } } memset(&de->rx_skb, 0, sizeof(struct ring_info) * DE_RX_RING_SIZE); memset(&de->tx_skb, 0, sizeof(struct ring_info) * DE_TX_RING_SIZE);}static void de_free_rings (struct de_private *de){ de_clean_rings(de); pci_free_consistent(de->pdev, DE_RING_BYTES, de->rx_ring, de->ring_dma); de->rx_ring = NULL; de->tx_ring = NULL;}static int de_open (struct net_device *dev){ struct de_private *de = dev->priv; int rc; unsigned long flags; if (netif_msg_ifup(de)) printk(KERN_DEBUG "%s: enabling interface\n", dev->name); de->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); rc = de_alloc_rings(de); if (rc) { printk(KERN_ERR "%s: ring allocation failure, err=%d\n", dev->name, rc); return rc; } rc = de_init_hw(de); if (rc) { printk(KERN_ERR "%s: h/w init failure, err=%d\n", dev->name, rc); goto err_out_free; } rc = request_irq(dev->irq, de_interrupt, SA_SHIRQ, dev->name, dev); if (rc) { printk(KERN_ERR "%s: IRQ %d request failure, err=%d\n", dev->name, dev->irq, rc); goto err_out_hw; } netif_start_queue(dev); mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); return 0;err_out_hw: spin_lock_irqsave(&de->lock, flags); de_stop_hw(de); spin_unlock_irqrestore(&de->lock, flags);err_out_free: de_free_rings(de); return rc;}static int de_close (struct net_device *dev){ struct de_private *de = dev->priv; unsigned long flags; if (netif_msg_ifdown(de)) printk(KERN_DEBUG "%s: disabling interface\n", dev->name); del_timer_sync(&de->media_timer); spin_lock_irqsave(&de->lock, flags); de_stop_hw(de); netif_stop_queue(dev); netif_carrier_off(dev); spin_unlock_irqrestore(&de->lock, flags); free_irq(dev->irq, dev); de_free_rings(de); de_adapter_sleep(de); pci_disable_device(de->pdev); return 0;}static void de_tx_timeout (struct net_device *dev){ struct de_private *de = dev->priv; printk(KERN_DEBUG "%s: NIC status %08x mode %08x sia %08x desc %u/%u/%u\n", dev->name, dr32(MacStatus), dr32(MacMode), dr32(SIAStatus), de->rx_tail, de->tx_head, de->tx_tail); del_timer_sync(&de->media_timer); disable_irq(dev->irq); spin_lock_irq(&de->lock); de_stop_hw(de); netif_stop_queue(dev); netif_carrier_off(dev); spin_unlock_irq(&de->lock); enable_irq(dev->irq); /* Update the error counts. */ __de_get_stats(de); synchronize_irq(dev->irq); de_clean_rings(de); de_init_hw(de); netif_wake_queue(dev);}static void __de_get_regs(struct de_private *de, u8 *buf){ int i; u32 *rbuf = (u32 *)buf; /* read all CSRs */ for (i = 0; i < DE_NUM_REGS; i++) rbuf[i] = dr32(i * 8); /* handle self-clearing RxMissed counter, CSR8 */ de_rx_missed(de, rbuf[8]);}static int __de_get_settings(struct de_private *de, struct ethtool_cmd *ecmd){ ecmd->supported = de->media_supported; ecmd->transceiver = XCVR_INTERNAL; ecmd->phy_address = 0; ecmd->advertising = de->media_advertise; switch (de->media_type) { case DE_MEDIA_AUI: ecmd->port = PORT_AUI; ecmd->speed = 5; break; case DE_MEDIA_BNC: ecmd->port = PORT_BNC; ecmd->speed = 2; break; default: ecmd->port = PORT_TP; ecmd->speed = SPEED_10; break; } if (dr32(MacMode) & FullDuplex) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; if (de->media_lock) ecmd->autoneg = AUTONEG_DISABLE; else ecmd->autoneg = AUTONEG_ENABLE; /* ignore maxtxpkt, maxrxpkt for now */ return 0;}static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd){ u32 new_media; unsigned int media_lock; if (ecmd->speed != SPEED_10 && ecmd->speed != 5 && ecmd->speed != 2) return -EINVAL; if (de->de21040 && ecmd->speed == 2) return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI && ecmd->port != PORT_BNC) return -EINVAL; if (de->de21040 && ecmd->port == PORT_BNC) return -EINVAL; if (ecmd->transceiver != XCVR_INTERNAL) return -EINVAL; if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) return -EINVAL; if (ecmd->advertising & ~de->media_supported) return -EINVAL; if (ecmd->autoneg == AUTONEG_ENABLE && (!(ecmd->advertising & ADVERTISED_Autoneg))) return -EINVAL; switch (ecmd->port) { case PORT_AUI: new_media = DE_MEDIA_AUI; if (!(ecmd->advertising & ADVERTISED_AUI)) return -EINVAL; break; case PORT_BNC: new_media = DE_MEDIA_BNC; if (!(ecmd->advertising & ADVERTISED_BNC)) return -EINVAL; break; default: if (ecmd->autoneg == AUTONEG_ENABLE) new_media = DE_MEDIA_TP_AUTO; else if (ecmd->duplex == DUPLEX_FULL) new_media = DE_MEDIA_TP_FD; else new_media = DE_MEDIA_TP; if (!(ecmd->advertising & ADVERTISED_TP)) return -EINVAL; if (!(ecmd->advertising & (ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half))) return -EINVAL; break; } media_lock = (ecmd->autoneg == AUTONEG_ENABLE) ? 0 : 1; if ((new_media == de->media_type) && (media_lock == de->media_lock) && (ecmd->advertising == de->media_advertise)) return 0; /* nothing to change */ de_link_down(de); de_stop_rxtx(de); de->media_type = new_media; de->media_lock = media_lock; de->media_advertise = ecmd->advertising; de_set_media(de); return 0;}static void de_get_drvinfo (struct net_device *dev,struct ethtool_drvinfo *info){ struct de_private *de = dev->priv; strcpy (info->driver, DRV_NAME); strcpy (info->version, DRV_VERSION); strcpy (info->bus_info, pci_name(de->pdev)); info->eedump_len = DE_EEPROM_SIZE;}static int de_get_regs_len(struct net_device *dev){ return DE_REGS_SIZE;}static int de_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd){ struct de_private *de = dev->priv; int rc; spin_lock_irq(&de->lock); rc = __de_get_settings(de, ecmd); spin_unlock_irq(&de->lock); return rc;}static int de_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd){ struct de_private *de = dev->priv; int rc; spin_lock_irq(&de->lock); rc = __de_set_settings(de, ecmd); spin_unlock_irq(&de->lock); return rc;}static u32 de_get_msglevel(struct net_device *dev){ struct de_private *de = dev->priv; return de->msg_enable;}static void de_set_msglevel(struct net_device *dev, u32 msglvl){ struct de_private *de = dev->priv; de->msg_enable = msglvl;}static int de_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data){ struct de_private *de = dev->priv; if (!de->ee_data) return -EOPNOTSUPP; if ((eeprom->offset != 0) || (eeprom->magic != 0) || (eeprom->len != DE_EEPROM_SIZE)) return -EINVAL; memcpy(data, de->ee_data, eeprom->len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -