fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / dl2k.c
index 4673bd8..9d446a0 100644 (file)
@@ -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 <linux/dma-mapping.h>
 
 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, &ethtool_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 (&ethcmd, 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.