X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fdl2k.c;h=9d446a0fe0bfcb4ca4207b2557fbfd756964e9f4;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=4673bd8291e2bfedc453a53b80c3c5a2774f1c8c;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 4673bd829..9d446a0fe 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -9,53 +9,15 @@ the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ -/* - Rev Date Description - ========================================================================== - 0.01 2001/05/03 Created DL2000-based linux driver - 0.02 2001/05/21 Added VLAN and hardware checksum support. - 1.00 2001/06/26 Added jumbo frame support. - 1.01 2001/08/21 Added two parameters, rx_coalesce and rx_timeout. - 1.02 2001/10/08 Supported fiber media. - Added flow control parameters. - 1.03 2001/10/12 Changed the default media to 1000mbps_fd for - the fiber devices. - 1.04 2001/11/08 Fixed Tx stopped when tx very busy. - 1.05 2001/11/22 Fixed Tx stopped when unidirectional tx busy. - 1.06 2001/12/13 Fixed disconnect bug at 10Mbps mode. - Fixed tx_full flag incorrect. - Added tx_coalesce paramter. - 1.07 2002/01/03 Fixed miscount of RX frame error. - 1.08 2002/01/17 Fixed the multicast bug. - 1.09 2002/03/07 Move rx-poll-now to re-fill loop. - Added rio_timer() to watch rx buffers. - 1.10 2002/04/16 Fixed miscount of carrier error. - 1.11 2002/05/23 Added ISR schedule scheme - Fixed miscount of rx frame error for DGE-550SX. - Fixed VLAN bug. - 1.12 2002/06/13 Lock tx_coalesce=1 on 10/100Mbps mode. - 1.13 2002/08/13 1. Fix disconnection (many tx:carrier/rx:frame - errs) with some mainboards. - 2. Use definition "DRV_NAME" "DRV_VERSION" - "DRV_RELDATE" for flexibility. - 1.14 2002/08/14 Support ethtool. - 1.15 2002/08/27 Changed the default media to Auto-Negotiation - for the fiber devices. - 1.16 2002/09/04 More power down time for fiber devices auto- - negotiation. - Fix disconnect bug after ifup and ifdown. - 1.17 2002/10/03 Fix RMON statistics overflow. - Always use I/O mapping to access eeprom, - avoid system freezing with some chipsets. -*/ #define DRV_NAME "D-Link DL2000-based linux driver" -#define DRV_VERSION "v1.17a" -#define DRV_RELDATE "2002/10/04" +#define DRV_VERSION "v1.18" +#define DRV_RELDATE "2006/06/27" #include "dl2k.h" +#include static char version[] __devinitdata = - KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n"; + KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n"; #define MAX_UNITS 8 static int mtu[MAX_UNITS]; static int vlan[MAX_UNITS]; @@ -72,16 +34,16 @@ static int tx_coalesce=16; /* HW xmit count each TxDMAComplete */ MODULE_AUTHOR ("Edward Peng"); MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter"); MODULE_LICENSE("GPL"); -MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i"); -MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s"); -MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i"); -MODULE_PARM (jumbo, "1-" __MODULE_STRING (MAX_UNITS) "i"); -MODULE_PARM (tx_flow, "i"); -MODULE_PARM (rx_flow, "i"); -MODULE_PARM (copy_thresh, "i"); -MODULE_PARM (rx_coalesce, "i"); /* Rx frame count each interrupt */ -MODULE_PARM (rx_timeout, "i"); /* Rx DMA wait time in 64ns increments */ -MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxDMAComplete */ +module_param_array(mtu, int, NULL, 0); +module_param_array(media, charp, NULL, 0); +module_param_array(vlan, int, NULL, 0); +module_param_array(jumbo, int, NULL, 0); +module_param(tx_flow, int, 0); +module_param(rx_flow, int, 0); +module_param(copy_thresh, int, 0); +module_param(rx_coalesce, int, 0); /* Rx frame count each interrupt */ +module_param(rx_timeout, int, 0); /* Rx DMA wait time in 64ns increments */ +module_param(tx_coalesce, int, 0); /* HW xmit count each TxDMAComplete */ /* Enable the default interrupts */ @@ -90,15 +52,15 @@ MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxDMAComplete */ #define EnableInt() \ writew(DEFAULT_INTR, ioaddr + IntEnable) -static int max_intrloop = 50; -static int multicast_filter_limit = 0x40; +static const int max_intrloop = 50; +static const int multicast_filter_limit = 0x40; static int rio_open (struct net_device *dev); static void rio_timer (unsigned long data); static void rio_tx_timeout (struct net_device *dev); static void alloc_list (struct net_device *dev); static int start_xmit (struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rio_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +static irqreturn_t rio_interrupt (int irq, void *dev_instance); static void rio_free_tx (struct net_device *dev, int irq); static void tx_error (struct net_device *dev, int tx_status); static int receive_packet (struct net_device *dev); @@ -107,7 +69,6 @@ static int change_mtu (struct net_device *dev, int new_mtu); static void set_multicast (struct net_device *dev); static struct net_device_stats *get_stats (struct net_device *dev); static int clear_stats (struct net_device *dev); -static int rio_ethtool_ioctl (struct net_device *dev, void *useraddr); static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int rio_close (struct net_device *dev); static int find_miiphy (struct net_device *dev); @@ -122,6 +83,8 @@ static int mii_read (struct net_device *dev, int phy_addr, int reg_num); static int mii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data); +static const struct ethtool_ops ethtool_ops; + static int __devinit rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -168,7 +131,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) #endif dev->base_addr = ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); np->chip_id = chip_idx; np->pdev = pdev; spin_lock_init (&np->tx_lock); @@ -181,9 +144,9 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) if (media[card_idx] != NULL) { np->an_enable = 0; if (strcmp (media[card_idx], "auto") == 0 || - strcmp (media[card_idx], "autosense") == 0 || + strcmp (media[card_idx], "autosense") == 0 || strcmp (media[card_idx], "0") == 0 ) { - np->an_enable = 2; + np->an_enable = 2; } else if (strcmp (media[card_idx], "100mbps_fd") == 0 || strcmp (media[card_idx], "4") == 0) { np->speed = 100; @@ -244,6 +207,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) dev->tx_timeout = &rio_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->change_mtu = &change_mtu; + SET_ETHTOOL_OPS(dev, ðtool_ops); #if 0 dev->features = NETIF_F_IP_CSUM; #endif @@ -268,7 +232,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) err = find_miiphy (dev); if (err) goto err_out_unmap_rx; - + /* Fiber device? */ np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0; np->link_status = 0; @@ -299,11 +263,11 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], irq); if (tx_coalesce > 1) - printk(KERN_INFO "tx_coalesce:\t%d packets\n", + printk(KERN_INFO "tx_coalesce:\t%d packets\n", tx_coalesce); if (np->coalesce) printk(KERN_INFO "rx_coalesce:\t%d packets\n" - KERN_INFO "rx_timeout: \t%d ns\n", + KERN_INFO "rx_timeout: \t%d ns\n", np->rx_coalesce, np->rx_timeout*640); if (np->vlan) printk(KERN_INFO "vlan(id):\t%d\n", np->vlan); @@ -335,7 +299,7 @@ find_miiphy (struct net_device *dev) int i, phy_found = 0; struct netdev_private *np; long ioaddr; - np = dev->priv; + np = netdev_priv(dev); ioaddr = dev->base_addr; np->phy_addr = 1; @@ -362,7 +326,7 @@ parse_eeprom (struct net_device *dev) u8 *psib; u32 crc; PSROM_t psrom = (PSROM_t) sromdata; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int cid, next; @@ -375,7 +339,7 @@ parse_eeprom (struct net_device *dev) } #ifdef MEM_MAPPING ioaddr = dev->base_addr; -#endif +#endif /* Check CRC */ crc = ~ether_crc_le (256 - 4, sromdata); if (psrom->crc != crc) { @@ -387,7 +351,7 @@ parse_eeprom (struct net_device *dev) for (i = 0; i < 6; i++) dev->dev_addr[i] = psrom->mac_addr[i]; - /* Parse Software Infomation Block */ + /* Parse Software Information Block */ i = 0x30; psib = (u8 *) sromdata; do { @@ -432,20 +396,20 @@ parse_eeprom (struct net_device *dev) static int rio_open (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i; u16 macctrl; - - i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev); + + i = request_irq (dev->irq, &rio_interrupt, IRQF_SHARED, dev->name, dev); if (i) return i; - + /* Reset all logic functions */ writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset, ioaddr + ASICCtrl + 2); mdelay(10); - + /* DebugCtrl bit 4, 5, 9 must set */ writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl); @@ -476,7 +440,7 @@ rio_open (struct net_device *dev) /* VLAN supported */ if (np->vlan) { /* priority field in RxDMAIntCtrl */ - writel (readl(ioaddr + RxDMAIntCtrl) | 0x7 << 10, + writel (readl(ioaddr + RxDMAIntCtrl) | 0x7 << 10, ioaddr + RxDMAIntCtrl); /* VLANId */ writew (np->vlan, ioaddr + VLANId); @@ -495,9 +459,9 @@ rio_open (struct net_device *dev) add_timer (&np->timer); /* Start Tx/Rx */ - writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable, + writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl); - + macctrl = 0; macctrl |= (np->vlan) ? AutoVLANuntagging : 0; macctrl |= (np->full_duplex) ? DuplexSelect : 0; @@ -506,17 +470,17 @@ rio_open (struct net_device *dev) writew(macctrl, ioaddr + MACCtrl); netif_start_queue (dev); - + /* Enable default interrupts */ EnableInt (); return 0; } -static void +static void rio_timer (unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned int entry; int next_tick = 1*HZ; unsigned long flags; @@ -545,7 +509,7 @@ rio_timer (unsigned long data) skb_reserve (skb, 2); np->rx_ring[entry].fraginfo = cpu_to_le64 (pci_map_single - (np->pdev, skb->tail, np->rx_buf_sz, + (np->pdev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); } np->rx_ring[entry].fraginfo |= @@ -557,7 +521,7 @@ rio_timer (unsigned long data) np->timer.expires = jiffies + next_tick; add_timer(&np->timer); } - + static void rio_tx_timeout (struct net_device *dev) { @@ -574,7 +538,7 @@ rio_tx_timeout (struct net_device *dev) static void alloc_list (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = 0; @@ -583,7 +547,7 @@ alloc_list (struct net_device *dev) /* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */ for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_skbuff[i] = 0; + np->tx_skbuff[i] = NULL; np->tx_ring[i].status = cpu_to_le64 (TFDDone); np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma + ((i+1)%TX_RING_SIZE) * @@ -597,7 +561,7 @@ alloc_list (struct net_device *dev) sizeof (struct netdev_desc)); np->rx_ring[i].status = 0; np->rx_ring[i].fraginfo = 0; - np->rx_skbuff[i] = 0; + np->rx_skbuff[i] = NULL; } /* Allocate the rx buffers */ @@ -616,7 +580,7 @@ alloc_list (struct net_device *dev) /* Rubicon now supports 40 bits of addressing space. */ np->rx_ring[i].fraginfo = cpu_to_le64 ( pci_map_single ( - np->pdev, skb->tail, np->rx_buf_sz, + np->pdev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48; } @@ -631,7 +595,7 @@ alloc_list (struct net_device *dev) static int start_xmit (struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct netdev_desc *txdesc; unsigned entry; u32 ioaddr; @@ -647,7 +611,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) txdesc = &np->tx_ring[entry]; #if 0 - if (skb->ip_summed == CHECKSUM_HW) { + if (skb->ip_summed == CHECKSUM_PARTIAL) { txdesc->status |= cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable | IPChecksumEnable); @@ -668,12 +632,12 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) * Work around: Always use 1 descriptor in 10Mbps mode */ if (entry % np->tx_coalesce == 0 || np->speed == 10) txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag | - WordAlignDisable | + WordAlignDisable | TxDMAIndicate | (1 << FragCountShift)); else txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag | - WordAlignDisable | + WordAlignDisable | (1 << FragCountShift)); /* TxDMAPollNow */ @@ -694,14 +658,14 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) dev->base_addr + TFDListPtr0); writel (0, dev->base_addr + TFDListPtr1); } - + /* NETDEV WATCHDOG timer */ dev->trans_start = jiffies; return 0; } static irqreturn_t -rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs) +rio_interrupt (int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct netdev_private *np; @@ -711,9 +675,9 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs) int handled = 0; ioaddr = dev->base_addr; - np = dev->priv; + np = netdev_priv(dev); while (1) { - int_status = readw (ioaddr + IntStatus); + int_status = readw (ioaddr + IntStatus); writew (int_status, ioaddr + IntStatus); int_status &= DEFAULT_INTR; if (int_status == 0 || --cnt < 0) @@ -729,7 +693,7 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs) if (tx_status & 0x01) tx_error (dev, tx_status); /* Free used tx skbuffs */ - rio_free_tx (dev, 1); + rio_free_tx (dev, 1); } /* Handle uncommon events */ @@ -742,19 +706,19 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs) return IRQ_RETVAL(handled); } -static void -rio_free_tx (struct net_device *dev, int irq) +static void +rio_free_tx (struct net_device *dev, int irq) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->old_tx % TX_RING_SIZE; int tx_use = 0; unsigned long flag = 0; - + if (irq) spin_lock(&np->tx_lock); else spin_lock_irqsave(&np->tx_lock, flag); - + /* Free used tx skbuffs */ while (entry != np->cur_tx) { struct sk_buff *skb; @@ -763,14 +727,14 @@ rio_free_tx (struct net_device *dev, int irq) break; skb = np->tx_skbuff[entry]; pci_unmap_single (np->pdev, - np->tx_ring[entry].fraginfo, + np->tx_ring[entry].fraginfo & DMA_48BIT_MASK, skb->len, PCI_DMA_TODEVICE); if (irq) dev_kfree_skb_irq (skb); else dev_kfree_skb (skb); - np->tx_skbuff[entry] = 0; + np->tx_skbuff[entry] = NULL; entry = (entry + 1) % TX_RING_SIZE; tx_use++; } @@ -780,11 +744,11 @@ rio_free_tx (struct net_device *dev, int irq) spin_unlock_irqrestore(&np->tx_lock, flag); np->old_tx = entry; - /* If the ring is no longer full, clear tx_full and + /* If the ring is no longer full, clear tx_full and call netif_wake_queue() */ if (netif_queue_stopped(dev) && - ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE + ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE < TX_QUEUE_LEN - 1 || np->speed == 10)) { netif_wake_queue (dev); } @@ -798,7 +762,7 @@ tx_error (struct net_device *dev, int tx_status) int frame_id; int i; - np = dev->priv; + np = netdev_priv(dev); frame_id = (tx_status & 0xffff0000); printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n", @@ -841,11 +805,11 @@ tx_error (struct net_device *dev, int tx_status) /* Let TxStartThresh stay default value */ } /* Maximum Collisions */ -#ifdef ETHER_STATS - if (tx_status & 0x08) +#ifdef ETHER_STATS + if (tx_status & 0x08) np->stats.collisions16++; #else - if (tx_status & 0x08) + if (tx_status & 0x08) np->stats.collisions++; #endif /* Restart the Tx */ @@ -855,7 +819,7 @@ tx_error (struct net_device *dev, int tx_status) static int receive_packet (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; int cnt = 30; @@ -890,35 +854,38 @@ receive_packet (struct net_device *dev) /* Small skbuffs for short packets */ if (pkt_len > copy_thresh) { - pci_unmap_single (np->pdev, desc->fraginfo, + pci_unmap_single (np->pdev, + desc->fraginfo & DMA_48BIT_MASK, np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put (skb = np->rx_skbuff[entry], pkt_len); np->rx_skbuff[entry] = NULL; } else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) { pci_dma_sync_single_for_cpu(np->pdev, - desc->fraginfo, + desc->fraginfo & + DMA_48BIT_MASK, np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb->dev = dev; /* 16 byte align the IP header */ skb_reserve (skb, 2); eth_copy_and_sum (skb, - np->rx_skbuff[entry]->tail, + np->rx_skbuff[entry]->data, pkt_len, 0); skb_put (skb, pkt_len); pci_dma_sync_single_for_device(np->pdev, - desc->fraginfo, + desc->fraginfo & + DMA_48BIT_MASK, np->rx_buf_sz, PCI_DMA_FROMDEVICE); } skb->protocol = eth_type_trans (skb, dev); -#if 0 +#if 0 /* Checksum done by hw, but csum value unavailable. */ - if (np->pci_rev_id >= 0x0c && + if (np->pci_rev_id >= 0x0c && !(frame_status & (TCPError | UDPError | IPError))) { skb->ip_summed = CHECKSUM_UNNECESSARY; - } + } #endif netif_rx (skb); dev->last_rx = jiffies; @@ -948,7 +915,7 @@ receive_packet (struct net_device *dev) skb_reserve (skb, 2); np->rx_ring[entry].fraginfo = cpu_to_le64 (pci_map_single - (np->pdev, skb->tail, np->rx_buf_sz, + (np->pdev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); } np->rx_ring[entry].fraginfo |= @@ -965,7 +932,7 @@ static void rio_error (struct net_device *dev, int int_status) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 macctrl; /* Link change event */ @@ -978,14 +945,14 @@ rio_error (struct net_device *dev, int int_status) mii_get_media (dev); if (np->speed == 1000) np->tx_coalesce = tx_coalesce; - else + else np->tx_coalesce = 1; macctrl = 0; macctrl |= (np->vlan) ? AutoVLANuntagging : 0; macctrl |= (np->full_duplex) ? DuplexSelect : 0; - macctrl |= (np->tx_flow) ? + macctrl |= (np->tx_flow) ? TxFlowControlEnable : 0; - macctrl |= (np->rx_flow) ? + macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0; writew(macctrl, ioaddr + MACCtrl); np->link_status = 1; @@ -1002,7 +969,7 @@ rio_error (struct net_device *dev, int int_status) get_stats (dev); } - /* PCI Error, a catastronphic error related to the bus interface + /* 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", @@ -1016,7 +983,7 @@ static struct net_device_stats * get_stats (struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); #ifdef MEM_MAPPING int i; #endif @@ -1024,16 +991,16 @@ get_stats (struct net_device *dev) /* 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); - + np->stats.collisions += readl (ioaddr + SingleColFrames) + + readl (ioaddr + MultiColFrames); + /* detailed tx errors */ stat_reg = readw (ioaddr + FramesAbortXSColls); np->stats.tx_aborted_errors += stat_reg; @@ -1080,7 +1047,7 @@ clear_stats (struct net_device *dev) long ioaddr = dev->base_addr; #ifdef MEM_MAPPING int i; -#endif +#endif /* All statistics registers need to be acknowledged, else statistic overflow could cause problems */ @@ -1093,7 +1060,7 @@ clear_stats (struct net_device *dev) readl (ioaddr + SingleColFrames); readl (ioaddr + MultiColFrames); readl (ioaddr + LateCollisions); - /* detailed rx errors */ + /* detailed rx errors */ readw (ioaddr + FrameTooLongErrors); readw (ioaddr + InRangeLengthErrors); readw (ioaddr + FramesCheckSeqErrors); @@ -1119,7 +1086,7 @@ clear_stats (struct net_device *dev) #ifdef MEM_MAPPING for (i = 0x100; i <= 0x150; i += 4) readl (ioaddr + i); -#endif +#endif readw (ioaddr + TxJumboFrames); readw (ioaddr + RxJumboFrames); readw (ioaddr + TCPCheckSumErrors); @@ -1132,7 +1099,7 @@ clear_stats (struct net_device *dev) int change_mtu (struct net_device *dev, int new_mtu) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int max = (np->jumbo) ? MAX_JUMBO : 1536; if ((new_mtu < 68) || (new_mtu > max)) { @@ -1150,27 +1117,27 @@ set_multicast (struct net_device *dev) long ioaddr = dev->base_addr; u32 hash_table[2]; u16 rx_mode = 0; - struct netdev_private *np = dev->priv; - + struct netdev_private *np = netdev_priv(dev); + 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) || + } 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 + /* 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) + 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); @@ -1194,149 +1161,128 @@ set_multicast (struct net_device *dev) writew (rx_mode, ioaddr + ReceiveMode); } -static int -rio_ethtool_ioctl (struct net_device *dev, void *useraddr) +static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, "dl2k"); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pdev)); +} + +static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct netdev_private *np = netdev_priv(dev); + 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; + return 0; +} + +static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - 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; + struct netdev_private *np = netdev_priv(dev); + 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; - } - - 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; + } 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 Manual 100Mbps, Full duplex.\n"); } -#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 + 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 -EOPNOTSUPP; - } + return -EINVAL; + } + mii_set_media(dev); + } + return 0; } +static u32 rio_get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->link_status; +} + +static const struct ethtool_ops ethtool_ops = { + .get_drvinfo = rio_get_drvinfo, + .get_settings = rio_get_settings, + .set_settings = rio_set_settings, + .get_link = rio_get_link, +}; static int rio_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_data; - + struct netdev_private *np = netdev_priv(dev); + 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, (void *) rq->ifr_data); case SIOCDEVPRIVATE: break; - + case SIOCDEVPRIVATE + 1: miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num); break; @@ -1490,7 +1436,7 @@ mii_wait_link (struct net_device *dev, int wait) int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; do { @@ -1512,7 +1458,7 @@ mii_get_media (struct net_device *dev) int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, MII_BMSR); @@ -1521,7 +1467,7 @@ mii_get_media (struct net_device *dev) /* Auto-Negotiation not completed */ return -1; } - negotiate.image = mii_read (dev, phy_addr, MII_ANAR) & + negotiate.image = mii_read (dev, phy_addr, MII_ANAR) & mii_read (dev, phy_addr, MII_ANLPAR); mscr.image = mii_read (dev, phy_addr, MII_MSCR); mssr.image = mii_read (dev, phy_addr, MII_MSSR); @@ -1573,9 +1519,9 @@ mii_get_media (struct net_device *dev) printk ("Half duplex\n"); } } - if (np->tx_flow) + if (np->tx_flow) printk(KERN_INFO "Enable Tx Flow Control\n"); - else + else printk(KERN_INFO "Disable Tx Flow Control\n"); if (np->rx_flow) printk(KERN_INFO "Enable Rx Flow Control\n"); @@ -1594,7 +1540,7 @@ mii_set_media (struct net_device *dev) ANAR_t anar; int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; /* Does user set speed? */ @@ -1615,7 +1561,7 @@ mii_set_media (struct net_device *dev) pscr.image = mii_read (dev, phy_addr, MII_PHY_SCR); pscr.bits.mdi_crossover_mode = 3; /* 11'b */ mii_write (dev, phy_addr, MII_PHY_SCR, pscr.image); - + /* Soft reset PHY */ mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET); bmcr.image = 0; @@ -1684,7 +1630,7 @@ mii_get_media_pcs (struct net_device *dev) int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, PCS_BMSR); @@ -1693,7 +1639,7 @@ mii_get_media_pcs (struct net_device *dev) /* Auto-Negotiation not completed */ return -1; } - negotiate.image = mii_read (dev, phy_addr, PCS_ANAR) & + negotiate.image = mii_read (dev, phy_addr, PCS_ANAR) & mii_read (dev, phy_addr, PCS_ANLPAR); np->speed = 1000; if (negotiate.bits.full_duplex) { @@ -1720,9 +1666,9 @@ mii_get_media_pcs (struct net_device *dev) printk ("Half duplex\n"); } } - if (np->tx_flow) + if (np->tx_flow) printk(KERN_INFO "Enable Tx Flow Control\n"); - else + else printk(KERN_INFO "Disable Tx Flow Control\n"); if (np->rx_flow) printk(KERN_INFO "Enable Rx Flow Control\n"); @@ -1740,7 +1686,7 @@ mii_set_media_pcs (struct net_device *dev) ANAR_PCS_t anar; int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; /* Auto-Negotiation? */ @@ -1748,9 +1694,9 @@ mii_set_media_pcs (struct net_device *dev) /* Advertise capabilities */ esr.image = mii_read (dev, phy_addr, PCS_ESR); anar.image = mii_read (dev, phy_addr, MII_ANAR); - anar.bits.half_duplex = + anar.bits.half_duplex = esr.bits.media_1000BT_HD | esr.bits.media_1000BX_HD; - anar.bits.full_duplex = + anar.bits.full_duplex = esr.bits.media_1000BT_FD | esr.bits.media_1000BX_FD; anar.bits.pause = 1; anar.bits.asymmetric = 1; @@ -1794,7 +1740,7 @@ static int rio_close (struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct sk_buff *skb; int i; @@ -1808,26 +1754,28 @@ rio_close (struct net_device *dev) synchronize_irq (dev->irq); free_irq (dev->irq, dev); del_timer_sync (&np->timer); - + /* Free all the skbuffs in the queue. */ for (i = 0; i < RX_RING_SIZE; i++) { np->rx_ring[i].status = 0; np->rx_ring[i].fraginfo = 0; skb = np->rx_skbuff[i]; if (skb) { - pci_unmap_single (np->pdev, np->rx_ring[i].fraginfo, - skb->len, PCI_DMA_FROMDEVICE); + pci_unmap_single(np->pdev, + np->rx_ring[i].fraginfo & DMA_48BIT_MASK, + skb->len, PCI_DMA_FROMDEVICE); dev_kfree_skb (skb); - np->rx_skbuff[i] = 0; + np->rx_skbuff[i] = NULL; } } for (i = 0; i < TX_RING_SIZE; i++) { skb = np->tx_skbuff[i]; if (skb) { - pci_unmap_single (np->pdev, np->tx_ring[i].fraginfo, - skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(np->pdev, + np->tx_ring[i].fraginfo & DMA_48BIT_MASK, + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb (skb); - np->tx_skbuff[i] = 0; + np->tx_skbuff[i] = NULL; } } @@ -1840,7 +1788,7 @@ rio_remove1 (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); if (dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unregister_netdev (dev); pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, @@ -1867,7 +1815,7 @@ static struct pci_driver rio_driver = { static int __init rio_init (void) { - return pci_module_init (&rio_driver); + return pci_register_driver(&rio_driver); } static void __exit @@ -1880,9 +1828,9 @@ module_init (rio_init); module_exit (rio_exit); /* - -Compile command: - + +Compile command: + gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.c Read Documentation/networking/dl2k.txt for details.