📄 dl2k.c
字号:
/* 16 byte align the IP header */ skb_reserve (skb, 2); np->rx_ring[entry].fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); } np->rx_ring[entry].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48; np->rx_ring[entry].status = 0; entry = (entry + 1) % RX_RING_SIZE; } np->old_rx = entry; spin_unlock(&np->rx_lock); return 0;}static voidrio_error (struct net_device *dev, int int_status){ long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; u16 macctrl; /* Link change event */ if (int_status & LinkEvent) { if (mii_wait_link (dev, 10) == 0) { printk (KERN_INFO "%s: Link up\n", dev->name); if (np->phy_media) mii_get_media_pcs (dev); else mii_get_media (dev); if (np->speed == 1000) np->tx_coalesce = tx_coalesce; else np->tx_coalesce = 1; macctrl = 0; macctrl |= (np->vlan) ? AutoVLANuntagging : 0; macctrl |= (np->full_duplex) ? DuplexSelect : 0; macctrl |= (np->tx_flow) ? TxFlowControlEnable : 0; macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0; writew(macctrl, ioaddr + MACCtrl); np->link_status = 1; netif_carrier_on(dev); } else { printk (KERN_INFO "%s: Link off\n", dev->name); np->link_status = 0; netif_carrier_off(dev); } } /* UpdateStats statistics registers */ if (int_status & UpdateStats) { get_stats (dev); } /* PCI Error, a catastronphic error related to the bus interface occurs, set GlobalReset and HostReset to reset. */ if (int_status & HostError) { printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n", dev->name, int_status); writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2); mdelay (500); }}static struct net_device_stats *get_stats (struct net_device *dev){ long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv;#ifdef MEM_MAPPING int i;#endif unsigned int stat_reg; /* All statistics registers need to be acknowledged, else statistic overflow could cause problems */ np->stats.rx_packets += readl (ioaddr + FramesRcvOk); np->stats.tx_packets += readl (ioaddr + FramesXmtOk); np->stats.rx_bytes += readl (ioaddr + OctetRcvOk); np->stats.tx_bytes += readl (ioaddr + OctetXmtOk); np->stats.multicast = readl (ioaddr + McstFramesRcvdOk); np->stats.collisions += readl (ioaddr + SingleColFrames) + readl (ioaddr + MultiColFrames); /* detailed tx errors */ stat_reg = readw (ioaddr + FramesAbortXSColls); np->stats.tx_aborted_errors += stat_reg; np->stats.tx_errors += stat_reg; stat_reg = readw (ioaddr + CarrierSenseErrors); np->stats.tx_carrier_errors += stat_reg; np->stats.tx_errors += stat_reg; /* Clear all other statistic register. */ readl (ioaddr + McstOctetXmtOk); readw (ioaddr + BcstFramesXmtdOk); readl (ioaddr + McstFramesXmtdOk); readw (ioaddr + BcstFramesRcvdOk); readw (ioaddr + MacControlFramesRcvd); readw (ioaddr + FrameTooLongErrors); readw (ioaddr + InRangeLengthErrors); readw (ioaddr + FramesCheckSeqErrors); readw (ioaddr + FramesLostRxErrors); readl (ioaddr + McstOctetXmtOk); readl (ioaddr + BcstOctetXmtOk); readl (ioaddr + McstFramesXmtdOk); readl (ioaddr + FramesWDeferredXmt); readl (ioaddr + LateCollisions); readw (ioaddr + BcstFramesXmtdOk); readw (ioaddr + MacControlFramesXmtd); readw (ioaddr + FramesWEXDeferal);#ifdef MEM_MAPPING for (i = 0x100; i <= 0x150; i += 4) readl (ioaddr + i);#endif readw (ioaddr + TxJumboFrames); readw (ioaddr + RxJumboFrames); readw (ioaddr + TCPCheckSumErrors); readw (ioaddr + UDPCheckSumErrors); readw (ioaddr + IPCheckSumErrors); return &np->stats;}static intclear_stats (struct net_device *dev){ long ioaddr = dev->base_addr;#ifdef MEM_MAPPING int i;#endif /* All statistics registers need to be acknowledged, else statistic overflow could cause problems */ readl (ioaddr + FramesRcvOk); readl (ioaddr + FramesXmtOk); readl (ioaddr + OctetRcvOk); readl (ioaddr + OctetXmtOk); readl (ioaddr + McstFramesRcvdOk); readl (ioaddr + SingleColFrames); readl (ioaddr + MultiColFrames); readl (ioaddr + LateCollisions); /* detailed rx errors */ readw (ioaddr + FrameTooLongErrors); readw (ioaddr + InRangeLengthErrors); readw (ioaddr + FramesCheckSeqErrors); readw (ioaddr + FramesLostRxErrors); /* detailed tx errors */ readw (ioaddr + FramesAbortXSColls); readw (ioaddr + CarrierSenseErrors); /* Clear all other statistic register. */ readl (ioaddr + McstOctetXmtOk); readw (ioaddr + BcstFramesXmtdOk); readl (ioaddr + McstFramesXmtdOk); readw (ioaddr + BcstFramesRcvdOk); readw (ioaddr + MacControlFramesRcvd); readl (ioaddr + McstOctetXmtOk); readl (ioaddr + BcstOctetXmtOk); readl (ioaddr + McstFramesXmtdOk); readl (ioaddr + FramesWDeferredXmt); readw (ioaddr + BcstFramesXmtdOk); readw (ioaddr + MacControlFramesXmtd); readw (ioaddr + FramesWEXDeferal);#ifdef MEM_MAPPING for (i = 0x100; i <= 0x150; i += 4) readl (ioaddr + i);#endif readw (ioaddr + TxJumboFrames); readw (ioaddr + RxJumboFrames); readw (ioaddr + TCPCheckSumErrors); readw (ioaddr + UDPCheckSumErrors); readw (ioaddr + IPCheckSumErrors); return 0;}intchange_mtu (struct net_device *dev, int new_mtu){ struct netdev_private *np = dev->priv; int max = (np->jumbo) ? MAX_JUMBO : 1536; if ((new_mtu < 68) || (new_mtu > max)) { return -EINVAL; } dev->mtu = new_mtu; return 0;}static voidset_multicast (struct net_device *dev){ long ioaddr = dev->base_addr; u32 hash_table[2]; u16 rx_mode = 0; struct netdev_private *np = dev->priv; hash_table[0] = hash_table[1] = 0; /* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */ hash_table[1] |= cpu_to_le32(0x02000000); if (dev->flags & IFF_PROMISC) { /* Receive all frames promiscuously. */ rx_mode = ReceiveAllFrames; } else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > multicast_filter_limit)) { /* Receive broadcast and multicast frames */ rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast; } else if (dev->mc_count > 0) { int i; struct dev_mc_list *mclist; /* Receive broadcast frames and multicast frames filtering by Hashtable */ rx_mode = ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast; for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist=mclist->next) { int bit, index = 0; int crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr); /* The inverted high significant 6 bits of CRC are used as an index to hashtable */ for (bit = 0; bit < 6; bit++) if (crc & (1 << (31 - bit))) index |= (1 << bit); hash_table[index / 32] |= (1 << (index % 32)); } } else { rx_mode = ReceiveBroadcast | ReceiveUnicast; } if (np->vlan) { /* ReceiveVLANMatch field in ReceiveMode */ rx_mode |= ReceiveVLANMatch; } writel (hash_table[0], ioaddr + HashTable0); writel (hash_table[1], ioaddr + HashTable1); writew (rx_mode, ioaddr + ReceiveMode);}static intrio_ethtool_ioctl (struct net_device *dev, void __user *useraddr){ struct netdev_private *np = dev->priv; u32 ethcmd; if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) return -EFAULT; switch (ethcmd) { case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; strcpy(info.driver, "DL2K"); strcpy(info.version, DRV_VERSION); strcpy(info.bus_info, pci_name(np->pdev)); memset(&info.fw_version, 0, sizeof(info.fw_version)); if (copy_to_user(useraddr, &info, sizeof(info))) return -EFAULT; return 0; } case ETHTOOL_GSET: { struct ethtool_cmd cmd = { ETHTOOL_GSET }; if (np->phy_media) { /* fiber device */ cmd.supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE; cmd.advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE; cmd.port = PORT_FIBRE; cmd.transceiver = XCVR_INTERNAL; } else { /* copper device */ cmd.supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII; cmd.advertising = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full| ADVERTISED_Autoneg | ADVERTISED_MII; cmd.port = PORT_MII; cmd.transceiver = XCVR_INTERNAL; } if ( np->link_status ) { cmd.speed = np->speed; cmd.duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; } else { cmd.speed = -1; cmd.duplex = -1; } if ( np->an_enable) cmd.autoneg = AUTONEG_ENABLE; else cmd.autoneg = AUTONEG_DISABLE; cmd.phy_address = np->phy_addr; if (copy_to_user(useraddr, &cmd, sizeof(cmd))) return -EFAULT; return 0; } case ETHTOOL_SSET: { struct ethtool_cmd cmd; if (copy_from_user(&cmd, useraddr, sizeof(cmd))) return -EFAULT; netif_carrier_off(dev); if (cmd.autoneg == AUTONEG_ENABLE) { if (np->an_enable) return 0; else { np->an_enable = 1; mii_set_media(dev); return 0; } } else { np->an_enable = 0; if (np->speed == 1000){ cmd.speed = SPEED_100; cmd.duplex = DUPLEX_FULL; printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manul 100Mbps, Full duplex.\n"); } switch(cmd.speed + cmd.duplex){ case SPEED_10 + DUPLEX_HALF: np->speed = 10; np->full_duplex = 0; break; case SPEED_10 + DUPLEX_FULL: np->speed = 10; np->full_duplex = 1; break; case SPEED_100 + DUPLEX_HALF: np->speed = 100; np->full_duplex = 0; break; case SPEED_100 + DUPLEX_FULL: np->speed = 100; np->full_duplex = 1; break; case SPEED_1000 + DUPLEX_HALF:/* not supported */ case SPEED_1000 + DUPLEX_FULL:/* not supported */ default: return -EINVAL; } mii_set_media(dev); } return 0; }#ifdef ETHTOOL_GLINK case ETHTOOL_GLINK:{ struct ethtool_value link = { ETHTOOL_GLINK }; link.data = np->link_status; if (copy_to_user(useraddr, &link, sizeof(link))) return -EFAULT; return 0; } #endif default: return -EOPNOTSUPP; } }static intrio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd){ int phy_addr; struct netdev_private *np = dev->priv; struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; struct netdev_desc *desc; int i; phy_addr = np->phy_addr; switch (cmd) { case SIOCETHTOOL: return rio_ethtool_ioctl(dev, rq->ifr_data); case SIOCDEVPRIVATE: break; case SIOCDEVPRIVATE + 1: miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num); break; case SIOCDEVPRIVATE + 2: mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value); break; case SIOCDEVPRIVATE + 3: break; case SIOCDEVPRIVATE + 4: break; case SIOCDEVPRIVATE + 5: netif_stop_queue (dev); break; case SIOCDEVPRIVATE + 6: netif_wake_queue (dev); break; case SIOCDEVPRIVATE + 7: printk ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n", netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx, np->old_rx); break; case SIOCDEVPRIVATE + 8: printk("TX ring:\n"); for (i = 0; i < TX_RING_SIZE; i++) { desc = &np->tx_ring[i]; printk ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", i, (u32) (np->tx_ring_dma + i * sizeof (*desc)), (u32) desc->next_desc, (u32) desc->status, (u32) (desc->fraginfo >> 32), (u32) desc->fraginfo); printk ("\n"); } printk ("\n"); break; default: return -EOPNOTSUPP; } return 0;}#define EEP_READ 0x0200#define EEP_BUSY 0x8000/* Read the EEPROM word *//* We use I/O instruction to read/write eeprom to avoid fail on some machines */intread_eeprom (long ioaddr, int eep_addr){ int i = 1000; outw (EEP_READ | (eep_addr & 0xff), ioaddr + EepromCtrl); while (i-- > 0) { if (!(inw (ioaddr + EepromCtrl) & EEP_BUSY)) { return inw (ioaddr + EepromData); } } return 0;}enum phy_ctrl_bits { MII_READ = 0x00, MII_CLK = 0x01, MII_DATA1 = 0x02, MII_WRITE = 0x04, MII_DUPLEX = 0x08,};#define mii_delay() readb(ioaddr)static voidmii_sendbit (struct net_device *dev, u32 data){ long ioaddr = dev->base_addr + PhyCtrl; data = (data) ? MII_DATA1 : 0; data |= MII_WRITE; data |= (readb (ioaddr) & 0xf8) | MII_WRITE; writeb (data, ioaddr); mii_delay (); writeb (data | MII_CLK, ioaddr); mii_delay ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -