Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / net / sk98lin / skge.c
index 53da481..38a26df 100644 (file)
@@ -72,8 +72,8 @@
  *             <linux/slab.h>
  *             <linux/interrupt.h>
  *             <linux/pci.h>
+ *             <linux/bitops.h>
  *             <asm/byteorder.h>
- *             <asm/bitops.h>
  *             <asm/io.h>
  *             <linux/netdevice.h>
  *             <linux/etherdevice.h>
  *             "h/skgeinit.h"
  *             "h/skaddr.h"
  *             "h/skgesirq.h"
- *             "h/skcsum.h"
  *             "h/skrlmt.h"
  *
  ******************************************************************************/
 
 #include       "h/skversion.h"
 
+#include       <linux/in.h>
 #include       <linux/module.h>
+#include       <linux/moduleparam.h>
 #include       <linux/init.h>
-
-#ifdef CONFIG_PROC_FS
-#include       <linux/proc_fs.h>
-#endif
+#include       <linux/dma-mapping.h>
+#include       <linux/ip.h>
 
 #include       "h/skdrv1st.h"
 #include       "h/skdrv2nd.h"
@@ -207,7 +206,6 @@ static void SkGeSetRxMode(struct SK_NET_DEVICE *dev);
 static struct  net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
 static int     SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
 static void    GetConfiguration(SK_AC*);
-static void    ProductStr(SK_AC*);
 static int     XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
 static void    FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
 static void    FillRxRing(SK_AC*, RX_PORT*);
@@ -236,17 +234,11 @@ static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
  * Extern Function Prototypes
  *
  ******************************************************************************/
-
-#ifdef CONFIG_PROC_FS
-static const char      SK_Root_Dir_entry[] = "sk98lin";
-static struct          proc_dir_entry *pSkRootDir = NULL;
-extern struct  file_operations sk_proc_fops;
-#endif
-
 extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); 
 extern void SkDimDisplayModerationSettings(SK_AC *pAC);
 extern void SkDimStartModerationTimer(SK_AC *pAC);
 extern void SkDimModerate(SK_AC *pAC);
+extern void SkGeBlinkTimer(unsigned long data);
 
 #ifdef DEBUG
 static void    DumpMsg(struct sk_buff*, char*);
@@ -255,302 +247,33 @@ static void      DumpLong(char*, int);
 #endif
 
 /* global variables *********************************************************/
-static const char *BootString = BOOT_STRING;
-struct SK_NET_DEVICE *SkGeRootDev = NULL;
-static int probed __initdata = 0;
 static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
+extern  struct ethtool_ops SkGeEthtoolOps;
 
 /* local variables **********************************************************/
 static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
 static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
 
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry   *pSkRootDir;
-#endif
-
-
-
 /*****************************************************************************
  *
- *     skge_probe - find all SK-98xx adapters
+ *     SkPciWriteCfgDWord - write a 32 bit value to pci config space
  *
  * Description:
- *     This function scans the PCI bus for SK-98xx adapters. Resources for
- *     each adapter are allocated and the adapter is brought into Init 1
- *     state.
+ *     This routine writes a 32 bit value to the pci configuration
+ *     space.
  *
  * Returns:
- *     0, if everything is ok
- *     !=0, on error
+ *     0 - indicate everything worked ok.
+ *     != 0 - error indication
  */
-static int __init skge_probe (void)
+static inline int SkPciWriteCfgDWord(
+SK_AC *pAC,    /* Adapter Control structure pointer */
+int PciAddr,           /* PCI register address */
+SK_U32 Val)            /* pointer to store the read value */
 {
-       int                     boards_found = 0;
-       int                     vendor_flag = SK_FALSE;
-       SK_AC                   *pAC;
-       DEV_NET                 *pNet = NULL;
-       struct pci_dev  *pdev = NULL;
-       struct SK_NET_DEVICE *dev = NULL;
-       SK_BOOL DeviceFound = SK_FALSE;
-       SK_BOOL BootStringCount = SK_FALSE;
-       int                     retval;
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry   *pProcFile;
-#endif
-
-       if (probed)
-               return -ENODEV;
-       probed++;
-
-
-       while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
-
-                if (pci_enable_device(pdev)) {
-                        continue;
-                }
-               dev = NULL;
-               pNet = NULL;
-
-               /* Don't handle Yukon2 cards at the moment */
-               /* 12-feb-2004 ---- mlindner@syskonnect.de */
-               if (pdev->vendor == 0x11ab) {
-                       if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) )
-                               continue;
-               }
-
-               SK_PCI_ISCOMPLIANT(vendor_flag, pdev);
-               if (!vendor_flag)
-                       continue;
-
-               /* Configure DMA attributes. */
-               if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
-                       pci_set_dma_mask(pdev, (u64) 0xffffffff))
-                       continue;
-
-
-               if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
-                       printk(KERN_ERR "Unable to allocate etherdev "
-                              "structure!\n");
-                       break;
-               }
-
-               pNet = dev->priv;
-               pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
-               if (pNet->pAC == NULL){
-                       free_netdev(dev);
-                       printk(KERN_ERR "Unable to allocate adapter "
-                              "structure!\n");
-                       break;
-               }
-
-               /* Print message */
-               if (!BootStringCount) {
-                       /* set display flag to TRUE so that */
-                       /* we only display this string ONCE */
-                       BootStringCount = SK_TRUE;
-                       printk("%s\n", BootString);
-               }
-
-               memset(pNet->pAC, 0, sizeof(SK_AC));
-               pAC = pNet->pAC;
-               pAC->PciDev = pdev;
-               pAC->PciDevId = pdev->device;
-               pAC->dev[0] = dev;
-               pAC->dev[1] = dev;
-               sprintf(pAC->Name, "SysKonnect SK-98xx");
-               pAC->CheckQueue = SK_FALSE;
-
-               pNet->Mtu = 1500;
-               pNet->Up = 0;
-               dev->irq = pdev->irq;
-               retval = SkGeInitPCI(pAC);
-               if (retval) {
-                       printk("SKGE: PCI setup failed: %i\n", retval);
-                       free_netdev(dev);
-                       continue;
-               }
-
-               SET_MODULE_OWNER(dev);
-               dev->open =             &SkGeOpen;
-               dev->stop =             &SkGeClose;
-               dev->hard_start_xmit =  &SkGeXmit;
-               dev->get_stats =        &SkGeStats;
-               dev->last_stats =       &SkGeStats;
-               dev->set_multicast_list = &SkGeSetRxMode;
-               dev->set_mac_address =  &SkGeSetMacAddr;
-               dev->do_ioctl =         &SkGeIoctl;
-               dev->change_mtu =       &SkGeChangeMtu;
-               dev->flags &=           ~IFF_RUNNING;
-               SET_NETDEV_DEV(dev, &pdev->dev);
-
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
-
-               if (pAC->ChipsetType) {
-                       /* Use only if yukon hardware */
-                       /* SK and ZEROCOPY - fly baby... */
-                       dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-               }
-#endif
-#endif
-
-               pAC->Index = boards_found;
-
-               if (SkGeBoardInit(dev, pAC)) {
-                       free_netdev(dev);
-                       continue;
-               }
-
-               /* Register net device */
-               if (register_netdev(dev)) {
-                       printk(KERN_ERR "SKGE: Could not register device.\n");
-                       FreeResources(dev);
-                       free_netdev(dev);
-                       continue;
-               }
-
-               /* Print adapter specific string from vpd */
-               ProductStr(pAC);
-               printk("%s: %s\n", dev->name, pAC->DeviceStr);
-
-               /* Print configuration settings */
-               printk("      PrefPort:%c  RlmtMode:%s\n",
-                       'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
-                       (pAC->RlmtMode==0)  ? "Check Link State" :
-                       ((pAC->RlmtMode==1) ? "Check Link State" :
-                       ((pAC->RlmtMode==3) ? "Check Local Port" :
-                       ((pAC->RlmtMode==7) ? "Check Segmentation" :
-                       ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
-               SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-
-               memcpy((caddr_t) &dev->dev_addr,
-                       (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
-
-               /* First adapter... Create proc and print message */
-#ifdef CONFIG_PROC_FS
-               if (!DeviceFound) {
-                       DeviceFound = SK_TRUE;
-                       SK_MEMCPY(&SK_Root_Dir_entry, BootString,
-                               sizeof(SK_Root_Dir_entry) - 1);
-
-                       /*Create proc (directory)*/
-                       if(!pSkRootDir) {
-                               pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
-                               if (!pSkRootDir) {
-                                       printk(KERN_WARNING "%s: Unable to create /proc/net/%s",
-                                               dev->name, SK_Root_Dir_entry);
-                               } else {
-                                       pSkRootDir->owner = THIS_MODULE;
-                               }
-                       }
-               }
-
-               /* Create proc file */
-               if (pSkRootDir && 
-                       (pProcFile = create_proc_entry(dev->name, S_IRUGO,
-                               pSkRootDir))) {
-                       pProcFile->proc_fops = &sk_proc_fops;
-                       pProcFile->data      = dev;
-               }
-
-#endif
-
-               pNet->PortNr = 0;
-               pNet->NetNr  = 0;
-
-               boards_found++;
-
-               /* More then one port found */
-               if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-                       if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
-                               printk(KERN_ERR "Unable to allocate etherdev "
-                                       "structure!\n");
-                               break;
-                       }
-
-                       pAC->dev[1]   = dev;
-                       pNet          = dev->priv;
-                       pNet->PortNr  = 1;
-                       pNet->NetNr   = 1;
-                       pNet->pAC     = pAC;
-                       pNet->Mtu     = 1500;
-                       pNet->Up      = 0;
-
-                       dev->open               = &SkGeOpen;
-                       dev->stop               = &SkGeClose;
-                       dev->hard_start_xmit    = &SkGeXmit;
-                       dev->get_stats          = &SkGeStats;
-                       dev->last_stats         = &SkGeStats;
-                       dev->set_multicast_list = &SkGeSetRxMode;
-                       dev->set_mac_address    = &SkGeSetMacAddr;
-                       dev->do_ioctl           = &SkGeIoctl;
-                       dev->change_mtu         = &SkGeChangeMtu;
-                       dev->flags             &= ~IFF_RUNNING;
-
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
-                       if (pAC->ChipsetType) {
-                               /* SG and ZEROCOPY - fly baby... */
-                               dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-                       }
-#endif
-#endif
-
-                       if (register_netdev(dev)) {
-                               printk(KERN_ERR "SKGE: Could not register device.\n");
-                               free_netdev(dev);
-                               pAC->dev[1] = pAC->dev[0];
-                       } else {
-#ifdef CONFIG_PROC_FS
-                               if (pSkRootDir 
-                                   && (pProcFile = create_proc_entry(dev->name, 
-                                                               S_IRUGO, pSkRootDir))) {
-                                       pProcFile->proc_fops = &sk_proc_fops;
-                                       pProcFile->data      = dev;
-                               }
-#endif
-
-                       memcpy((caddr_t) &dev->dev_addr,
-                       (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
-       
-                       printk("%s: %s\n", dev->name, pAC->DeviceStr);
-                       printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
-                       }
-               }
-
-               /* Save the hardware revision */
-               pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
-                       (pAC->GIni.GIPciHwRev & 0x0F);
-
-               /* Set driver globals */
-               pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
-               pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
-               SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
-               SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
-                               sizeof(SK_PNMI_STRUCT_DATA));
-
-               /*
-                * This is bollocks, but we need to tell the net-init
-                * code that it shall go for the next device.
-                */
-#ifndef MODULE
-               dev->base_addr = 0;
-#endif
-       }
-
-       /*
-        * If we're at this point we're going through skge_probe() for
-        * the first time.  Return success (0) if we've initialized 1
-        * or more boards. Otherwise, return failure (-ENODEV).
-        */
-
-       return boards_found;
-} /* skge_probe */
-
+       pci_write_config_dword(pAC->PciDev, PciAddr, Val);
+       return(0);
+} /* SkPciWriteCfgDWord */
 
 /*****************************************************************************
  *
@@ -559,26 +282,22 @@ static int __init skge_probe (void)
  * Description:
  *     This function initialize the PCI resources and IO
  *
- * Returns: N/A
- *     
+ * Returns:
+ *     0 - indicate everything worked ok.
+ *     != 0 - error indication
  */
-int SkGeInitPCI(SK_AC *pAC)
+static __devinit int SkGeInitPCI(SK_AC *pAC)
 {
        struct SK_NET_DEVICE *dev = pAC->dev[0];
        struct pci_dev *pdev = pAC->PciDev;
        int retval;
 
-       if (pci_enable_device(pdev) != 0) {
-               return 1;
-       }
-
        dev->mem_start = pci_resource_start (pdev, 0);
        pci_set_master(pdev);
 
-       if (pci_request_regions(pdev, pAC->Name) != 0) {
-               retval = 2;
-               goto out_disable;
-       }
+       retval = pci_request_regions(pdev, "sk98lin");
+       if (retval)
+               goto out;
 
 #ifdef SK_BIG_ENDIAN
        /*
@@ -596,10 +315,9 @@ int SkGeInitPCI(SK_AC *pAC)
        /*
         * Remap the regs into kernel space.
         */
-       pAC->IoBase = (char*)ioremap_nocache(dev->mem_start, 0x4000);
-
-       if (!pAC->IoBase){
-               retval = 3;
+       pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
+       if (!pAC->IoBase) {
+               retval = -EIO;
                goto out_release;
        }
 
@@ -607,8 +325,7 @@ int SkGeInitPCI(SK_AC *pAC)
 
  out_release:
        pci_release_regions(pdev);
- out_disable:
-       pci_disable_device(pdev);
+ out:
        return retval;
 }
 
@@ -630,22 +347,20 @@ SK_U32 AllocFlag;
 DEV_NET                *pNet;
 SK_AC          *pAC;
 
-       if (dev->priv) {
-               pNet = (DEV_NET*) dev->priv;
-               pAC = pNet->pAC;
-               AllocFlag = pAC->AllocFlag;
-               if (pAC->PciDev) {
-                       pci_release_regions(pAC->PciDev);
-               }
-               if (AllocFlag & SK_ALLOC_IRQ) {
-                       free_irq(dev->irq, dev);
-               }
-               if (pAC->IoBase) {
-                       iounmap(pAC->IoBase);
-               }
-               if (pAC->pDescrMem) {
-                       BoardFreeMem(pAC);
-               }
+       pNet = netdev_priv(dev);
+       pAC = pNet->pAC;
+       AllocFlag = pAC->AllocFlag;
+       if (pAC->PciDev) {
+               pci_release_regions(pAC->PciDev);
+       }
+       if (AllocFlag & SK_ALLOC_IRQ) {
+               free_irq(dev->irq, dev);
+       }
+       if (pAC->IoBase) {
+               iounmap(pAC->IoBase);
+       }
+       if (pAC->pDescrMem) {
+               BoardFreeMem(pAC);
        }
        
 } /* FreeResources */
@@ -653,29 +368,6 @@ SK_AC              *pAC;
 MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
 MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM(Speed_A,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(Speed_B,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(AutoNeg_A,  "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(AutoNeg_B,  "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(DupCap_A,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(DupCap_B,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(Role_A,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(Role_B,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(ConType,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(PrefPort,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(RlmtMode,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-/* not used, just there because every driver should have them: */
-MODULE_PARM(options,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
-MODULE_PARM(debug,      "i");
-/* used for interrupt moderation */
-MODULE_PARM(IntsPerSec,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
-MODULE_PARM(Moderation,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(Stats,          "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(ModerationMask, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(AutoSizing,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-
 
 #ifdef LINK_SPEED_A
 static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
@@ -755,122 +447,31 @@ static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
 static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
 #endif
 
-static int debug = 0; /* not used */
-static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
-
 static int   IntsPerSec[SK_MAX_CARD_PARAM];
 static char *Moderation[SK_MAX_CARD_PARAM];
 static char *ModerationMask[SK_MAX_CARD_PARAM];
 static char *AutoSizing[SK_MAX_CARD_PARAM];
 static char *Stats[SK_MAX_CARD_PARAM];
 
-
-/*****************************************************************************
- *
- *     skge_init_module - module initialization function
- *
- * Description:
- *     Very simple, only call skge_probe and return approriate result.
- *
- * Returns:
- *     0, if everything is ok
- *     !=0, on error
- */
-static int __init skge_init_module(void)
-{
-       int cards;
-       SkGeRootDev = NULL;
-       
-       /* just to avoid warnings ... */
-       debug = 0;
-       options[0] = 0;
-
-       cards = skge_probe();
-       if (cards == 0) {
-               printk("sk98lin: No adapter found.\n");
-       }
-       return cards ? 0 : -ENODEV;
-} /* skge_init_module */
-
-
-/*****************************************************************************
- *
- *     skge_cleanup_module - module unload function
- *
- * Description:
- *     Disable adapter if it is still running, free resources,
- *     free device struct.
- *
- * Returns: N/A
- */
-static void __exit skge_cleanup_module(void)
-{
-DEV_NET                *pNet;
-SK_AC          *pAC;
-struct SK_NET_DEVICE *next;
-unsigned long Flags;
-SK_EVPARA EvPara;
-
-       while (SkGeRootDev) {
-               pNet = (DEV_NET*) SkGeRootDev->priv;
-               pAC = pNet->pAC;
-               next = pAC->Next;
-
-               netif_stop_queue(SkGeRootDev);
-               SkGeYellowLED(pAC, pAC->IoBase, 0);
-
-               if(pAC->BoardLevel == SK_INIT_RUN) {
-                       /* board is still alive */
-                       spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-                       EvPara.Para32[0] = 0;
-                       EvPara.Para32[1] = -1;
-                       SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-                       EvPara.Para32[0] = 1;
-                       EvPara.Para32[1] = -1;
-                       SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-                       SkEventDispatcher(pAC, pAC->IoBase);
-                       /* disable interrupts */
-                       SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-                       SkGeDeInit(pAC, pAC->IoBase);
-                       spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-                       pAC->BoardLevel = SK_INIT_DATA;
-                       /* We do NOT check here, if IRQ was pending, of course*/
-               }
-
-               if(pAC->BoardLevel == SK_INIT_IO) {
-                       /* board is still alive */
-                       SkGeDeInit(pAC, pAC->IoBase);
-                       pAC->BoardLevel = SK_INIT_DATA;
-               }
-
-               if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
-                       unregister_netdev(pAC->dev[1]);
-                       free_netdev(pAC->dev[1]);
-               }
-
-               FreeResources(SkGeRootDev);
-
-               SkGeRootDev->get_stats = NULL;
-               /*
-                * otherwise unregister_netdev calls get_stats with
-                * invalid IO ...  :-(
-                */
-               unregister_netdev(SkGeRootDev);
-               free_netdev(SkGeRootDev);
-               kfree(pAC);
-               SkGeRootDev = next;
-       }
-
-#ifdef CONFIG_PROC_FS
-       /* clear proc-dir */
-       remove_proc_entry(pSkRootDir->name, proc_net);
-#endif
-
-} /* skge_cleanup_module */
-
-module_init(skge_init_module);
-module_exit(skge_cleanup_module);
-
+module_param_array(Speed_A, charp, NULL, 0);
+module_param_array(Speed_B, charp, NULL, 0);
+module_param_array(AutoNeg_A, charp, NULL, 0);
+module_param_array(AutoNeg_B, charp, NULL, 0);
+module_param_array(DupCap_A, charp, NULL, 0);
+module_param_array(DupCap_B, charp, NULL, 0);
+module_param_array(FlowCtrl_A, charp, NULL, 0);
+module_param_array(FlowCtrl_B, charp, NULL, 0);
+module_param_array(Role_A, charp, NULL, 0);
+module_param_array(Role_B, charp, NULL, 0);
+module_param_array(ConType, charp, NULL, 0);
+module_param_array(PrefPort, charp, NULL, 0);
+module_param_array(RlmtMode, charp, NULL, 0);
+/* used for interrupt moderation */
+module_param_array(IntsPerSec, int, NULL, 0);
+module_param_array(Moderation, charp, NULL, 0);
+module_param_array(Stats, charp, NULL, 0);
+module_param_array(ModerationMask, charp, NULL, 0);
+module_param_array(AutoSizing, charp, NULL, 0);
 
 /*****************************************************************************
  *
@@ -885,7 +486,7 @@ module_exit(skge_cleanup_module);
  *     0, if everything is ok
  *     !=0, on error
  */
-static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
+static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
 {
 short  i;
 unsigned long Flags;
@@ -910,6 +511,11 @@ SK_BOOL    DualNet;
        }
        spin_lock_init(&pAC->SlowPathLock);
 
+       /* setup phy_id blink timer */
+       pAC->BlinkTimer.function = SkGeBlinkTimer;
+       pAC->BlinkTimer.data = (unsigned long) dev;
+       init_timer(&pAC->BlinkTimer);
+
        /* level 0 init common modules here */
        
        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
@@ -917,7 +523,7 @@ SK_BOOL     DualNet;
        if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
                printk("HWInit (0) failed.\n");
                spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-               return(-EAGAIN);
+               return -EIO;
        }
        SkI2cInit(  pAC, pAC->IoBase, SK_INIT_DATA);
        SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
@@ -939,7 +545,7 @@ SK_BOOL     DualNet;
        if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
                printk("sk98lin: HWInit (1) failed.\n");
                spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-               return(-EAGAIN);
+               return -EIO;
        }
        SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
        SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
@@ -964,34 +570,29 @@ SK_BOOL   DualNet;
        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
 
        if (pAC->GIni.GIMacsFound == 2) {
-                Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+                Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev);
        } else if (pAC->GIni.GIMacsFound == 1) {
                Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ,
-                       pAC->Name, dev);
+                       "sk98lin", dev);
        } else {
                printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
                       pAC->GIni.GIMacsFound);
-               return -EAGAIN;
+               return -EIO;
        }
 
        if (Ret) {
                printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
                       dev->irq);
-               return -EAGAIN;
+               return Ret;
        }
        pAC->AllocFlag |= SK_ALLOC_IRQ;
 
        /* Alloc memory for this board (Mem for RxD/TxD) : */
        if(!BoardAllocMem(pAC)) {
                printk("No memory for descriptor rings.\n");
-                       return(-EAGAIN);
+               return -ENOMEM;
        }
 
-       SkCsSetReceiveFlags(pAC,
-               SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP,
-               &pAC->CsOfs1, &pAC->CsOfs2, 0);
-       pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
-
        BoardInitMem(pAC);
        /* tschilling: New common function with minimum size check. */
        DualNet = SK_FALSE;
@@ -1005,15 +606,9 @@ SK_BOOL   DualNet;
                DualNet)) {
                BoardFreeMem(pAC);
                printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
-               return(-EAGAIN);
+               return -EIO;
        }
 
-       /*
-        * Register the device here
-        */
-       pAC->Next = SkGeRootDev;
-       SkGeRootDev = dev;
-
        return (0);
 } /* SkGeBoardInit */
 
@@ -1032,8 +627,7 @@ SK_BOOL    DualNet;
  *     SK_TRUE, if all memory could be allocated
  *     SK_FALSE, if not
  */
-static SK_BOOL BoardAllocMem(
-SK_AC  *pAC)
+static __devinit SK_BOOL BoardAllocMem(SK_AC   *pAC)
 {
 caddr_t                pDescrMem;      /* pointer to descriptor memory area */
 size_t         AllocLength;    /* length of complete descriptor area */
@@ -1126,8 +720,7 @@ size_t             AllocLength;    /* length of complete descriptor area */
  *
  * Returns:    N/A
  */
-static void BoardInitMem(
-SK_AC  *pAC)   /* pointer to adapter context */
+static __devinit void BoardInitMem(SK_AC *pAC)
 {
 int    i;              /* loop counter */
 int    RxDescrSize;    /* the size of a rx descriptor rounded up to alignment*/
@@ -1215,7 +808,7 @@ uintptr_t VNextDescr;      /* the virtual bus address of the next descriptor */
                /* set the pointers right */
                pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
                pDescr->pNextRxd = pNextDescr;
-               pDescr->TcpSumStarts = pAC->CsOfs;
+               if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
 
                /* advance one step */
                pPrevDescr = pDescr;
@@ -1294,7 +887,7 @@ DEV_NET            *pNet;
 SK_AC          *pAC;
 SK_U32         IntSrc;         /* interrupts source register contents */       
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC = pNet->pAC;
        
        /*
@@ -1443,7 +1036,7 @@ DEV_NET           *pNet;
 SK_AC          *pAC;
 SK_U32         IntSrc;         /* interrupts source register contents */       
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC = pNet->pAC;
        
        /*
@@ -1533,6 +1126,24 @@ SK_U32           IntSrc;         /* interrupts source register contents */
                return SkIsrRetHandled;
 } /* SkGeIsrOnePort */
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/****************************************************************************
+ *
+ *     SkGePollController - polling receive, for netconsole
+ *
+ * Description:
+ *     Polling receive - used by netconsole and other diagnostic tools
+ *     to allow network i/o with interrupts disabled.
+ *
+ * Returns: N/A
+ */
+static void SkGePollController(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       SkGeIsr(dev->irq, dev, NULL);
+       enable_irq(dev->irq);
+}
+#endif
 
 /****************************************************************************
  *
@@ -1559,7 +1170,7 @@ struct SK_NET_DEVICE      *dev)
        int                             i;
        SK_EVPARA               EvPara;         /* an event parameter union */
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC = pNet->pAC;
        
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
@@ -1573,10 +1184,6 @@ struct SK_NET_DEVICE     *dev)
        }
 #endif
 
-       if (!try_module_get(THIS_MODULE)) {
-               return (-1);    /* increase of usage count not possible */
-       }
-
        /* Set blink mode */
        if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
                pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
@@ -1584,7 +1191,6 @@ struct SK_NET_DEVICE      *dev)
        if (pAC->BoardLevel == SK_INIT_DATA) {
                /* level 1 init common modules here */
                if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
-                       module_put(THIS_MODULE); /* decrease usage count */
                        printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
                        return (-1);
                }
@@ -1600,7 +1206,6 @@ struct SK_NET_DEVICE      *dev)
        if (pAC->BoardLevel != SK_INIT_RUN) {
                /* tschilling: Level 2 init modules here, check return value. */
                if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
-                       module_put(THIS_MODULE); /* decrease usage count */
                        printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
                        return (-1);
                }
@@ -1650,7 +1255,6 @@ struct SK_NET_DEVICE      *dev)
        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
 
        pAC->MaxPorts++;
-       pNet->Up = 1;
 
 
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
@@ -1686,19 +1290,18 @@ struct SK_NET_DEVICE    *dev)
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC = pNet->pAC;
 
 #ifdef SK_DIAG_SUPPORT
        if (pAC->DiagModeActive == DIAG_ACTIVE) {
                if (pAC->DiagFlowCtrl == SK_FALSE) {
-                       module_put(THIS_MODULE);
                        /* 
                        ** notify that the interface which has been closed
                        ** by operator interaction must not be started up 
                        ** again when the DIAG has finished. 
                        */
-                       newPtrNet = (DEV_NET *) pAC->dev[0]->priv;
+                       newPtrNet = netdev_priv(pAC->dev[0]);
                        if (newPtrNet == pNet) {
                                pAC->WasIfUp[0] = SK_FALSE;
                        } else {
@@ -1781,9 +1384,7 @@ struct SK_NET_DEVICE      *dev)
                        sizeof(SK_PNMI_STRUCT_DATA));
 
        pAC->MaxPorts--;
-       pNet->Up = 0;
 
-       module_put(THIS_MODULE);
        return (0);
 } /* SkGeClose */
 
@@ -1809,7 +1410,7 @@ DEV_NET           *pNet;
 SK_AC          *pAC;
 int                    Rc;     /* return code of XmitFrame */
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC = pNet->pAC;
 
        if ((!skb_shinfo(skb)->nr_frags) ||
@@ -1887,8 +1488,6 @@ struct sk_buff    *pMessage)      /* pointer to send-message              */
        TXD             *pOldTxd;
        unsigned long    Flags;
        SK_U64           PhysAddr;
-       int              Protocol;
-       int              IpHeaderLength;
        int              BytesSend = pMessage->len;
 
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
@@ -1927,6 +1526,7 @@ struct sk_buff    *pMessage)      /* pointer to send-message              */
        */
        if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
                if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) {
+                       spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
                        return 0;
                }
                pMessage->len = C_LEN_ETHERNET_MINSIZE;
@@ -1960,8 +1560,10 @@ struct sk_buff   *pMessage)      /* pointer to send-message              */
        pTxd->pMBuf     = pMessage;
 
        if (pMessage->ip_summed == CHECKSUM_HW) {
-               Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff);
-               if ((Protocol == C_PROTO_ID_UDP) && 
+               u16 hdrlen = pMessage->h.raw - pMessage->data;
+               u16 offset = hdrlen + pMessage->csum;
+
+               if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) &&
                        (pAC->GIni.GIChipRev == 0) &&
                        (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
                        pTxd->TBControl = BMU_TCP_CHECK;
@@ -1969,14 +1571,9 @@ struct sk_buff   *pMessage)      /* pointer to send-message              */
                        pTxd->TBControl = BMU_UDP_CHECK;
                }
 
-               IpHeaderLength  = (SK_U8)pMessage->data[C_OFFSET_IPHEADER];
-               IpHeaderLength  = (IpHeaderLength & 0xf) * 4;
-               pTxd->TcpSumOfs = 0; /* PH-Checksum already calculated */
-               pTxd->TcpSumSt  = C_LEN_ETHERMAC_HEADER + IpHeaderLength + 
-                                                       (Protocol == C_PROTO_ID_UDP ?
-                                                       C_OFFSET_UDPHEADER_UDPCS : 
-                                                       C_OFFSET_TCPHEADER_TCPCS);
-               pTxd->TcpSumWr  = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
+               pTxd->TcpSumOfs = 0;
+               pTxd->TcpSumSt  = hdrlen;
+               pTxd->TcpSumWr  = offset;
 
                pTxd->TBControl |= BMU_OWN | BMU_STF | 
                                   BMU_SW  | BMU_EOF |
@@ -2039,11 +1636,10 @@ struct sk_buff  *pMessage)      /* pointer to send-message              */
        TXD             *pTxdLst;
        int              CurrFrag;
        int              BytesSend;
-       int              IpHeaderLength; 
-       int              Protocol;
        skb_frag_t      *sk_frag;
        SK_U64           PhysAddr;
        unsigned long    Flags;
+       SK_U32           Control;
 
        spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
 #ifndef USE_TX_COMPLETE
@@ -2066,7 +1662,6 @@ struct sk_buff    *pMessage)      /* pointer to send-message              */
        pTxdFst   = pTxd;
        pTxdLst   = pTxd;
        BytesSend = 0;
-       Protocol  = 0;
 
        /* 
        ** Map the first fragment (header) into the DMA-space
@@ -2084,32 +1679,31 @@ struct sk_buff  *pMessage)      /* pointer to send-message              */
        ** Does the HW need to evaluate checksum for TCP or UDP packets? 
        */
        if (pMessage->ip_summed == CHECKSUM_HW) {
-               pTxd->TBControl = BMU_STF | BMU_STFWD | skb_headlen(pMessage);
+               u16 hdrlen = pMessage->h.raw - pMessage->data;
+               u16 offset = hdrlen + pMessage->csum;
+
+               Control = BMU_STFWD;
+
                /* 
                ** We have to use the opcode for tcp here,  because the
                ** opcode for udp is not working in the hardware yet 
                ** (Revision 2.0)
                */
-               Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff);
-               if ((Protocol == C_PROTO_ID_UDP) && 
+               if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) &&
                        (pAC->GIni.GIChipRev == 0) &&
                        (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-                       pTxd->TBControl |= BMU_TCP_CHECK;
+                       Control |= BMU_TCP_CHECK;
                } else {
-                       pTxd->TBControl |= BMU_UDP_CHECK;
+                       Control |= BMU_UDP_CHECK;
                }
 
-               IpHeaderLength  = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4;
-               pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */
-               pTxd->TcpSumSt  = C_LEN_ETHERMAC_HEADER + IpHeaderLength +
-                                               (Protocol == C_PROTO_ID_UDP ?
-                                               C_OFFSET_UDPHEADER_UDPCS :
-                                               C_OFFSET_TCPHEADER_TCPCS);
-               pTxd->TcpSumWr  = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
-       } else {
-               pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF |
-                                       skb_headlen(pMessage);
-       }
+               pTxd->TcpSumOfs = 0;
+               pTxd->TcpSumSt  = hdrlen;
+               pTxd->TcpSumWr  = offset;
+       } else
+               Control = BMU_CHECK | BMU_SW;
+
+       pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
 
        pTxd = pTxd->pNextTxd;
        pTxPort->TxdRingFree--;
@@ -2133,40 +1727,18 @@ struct sk_buff  *pMessage)      /* pointer to send-message              */
                pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
                pTxd->pMBuf     = pMessage;
                
-               /* 
-               ** Does the HW need to evaluate checksum for TCP or UDP packets? 
-               */
-               if (pMessage->ip_summed == CHECKSUM_HW) {
-                       pTxd->TBControl = BMU_OWN | BMU_SW | BMU_STFWD;
-                       /* 
-                       ** We have to use the opcode for tcp here because the 
-                       ** opcode for udp is not working in the hardware yet 
-                       ** (revision 2.0)
-                       */
-                       if ((Protocol == C_PROTO_ID_UDP) && 
-                               (pAC->GIni.GIChipRev == 0) &&
-                               (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-                               pTxd->TBControl |= BMU_TCP_CHECK;
-                       } else {
-                               pTxd->TBControl |= BMU_UDP_CHECK;
-                       }
-               } else {
-                       pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN;
-               }
+               pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
 
                /* 
                ** Do we have the last fragment? 
                */
                if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags )  {
 #ifdef USE_TX_COMPLETE
-                       pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF | sk_frag->size;
+                       pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
 #else
-                       pTxd->TBControl |= BMU_EOF | sk_frag->size;
+                       pTxd->TBControl |= BMU_EOF;
 #endif
                        pTxdFst->TBControl |= BMU_OWN | BMU_SW;
-
-               } else {
-                       pTxd->TBControl |= sk_frag->size;
                }
                pTxdLst = pTxd;
                pTxd    = pTxd->pNextTxd;
@@ -2413,7 +1985,6 @@ SK_U32                    Control;                /* control field of descriptor */
 struct sk_buff *pMsg;                  /* pointer to message holding frame */
 struct sk_buff *pNewMsg;               /* pointer to a new message for copying frame */
 int                            FrameLength;    /* total length of received frame */
-int                            IpFrameLength;
 SK_MBUF                        *pRlmtMbuf;             /* ptr to a buffer for giving a frame to rlmt */
 SK_EVPARA              EvPara;                 /* an event parameter union */  
 unsigned long  Flags;                  /* for spin lock */
@@ -2426,10 +1997,6 @@ SK_BOOL                  IsMc;
 SK_BOOL  IsBadFrame;                   /* Bad frame */
 
 SK_U32                 FrameStat;
-unsigned short Csum1;
-unsigned short Csum2;
-unsigned short Type;
-int                            Result;
 SK_U64                 PhysAddr;
 
 rx_start:      
@@ -2558,8 +2125,8 @@ rx_start:
                                                    (dma_addr_t) PhysAddr,
                                                    FrameLength,
                                                    PCI_DMA_FROMDEVICE);
-                       eth_copy_and_sum(pNewMsg, pMsg->data,
-                               FrameLength, 0);
+                       memcpy(pNewMsg->data, pMsg, FrameLength);
+
                        pci_dma_sync_single_for_device(pAC->PciDev,
                                                       (dma_addr_t) PhysAddr,
                                                       FrameLength,
@@ -2587,69 +2154,15 @@ rx_start:
 
                        /* set length in message */
                        skb_put(pMsg, FrameLength);
-                       /* hardware checksum */
-                       Type = ntohs(*((short*)&pMsg->data[12]));
+               } /* frame > SK_COPY_TRESHOLD */
 
 #ifdef USE_SK_RX_CHECKSUM
-                       if (Type == 0x800) {
-                               Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
-                               Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
-                               IpFrameLength = (int) ntohs((unsigned short)
-                                                               ((unsigned short *) pMsg->data)[8]);
-
-                               /*
-                                * Test: If frame is padded, a check is not possible!
-                                * Frame not padded? Length difference must be 14 (0xe)!
-                                */
-                               if ((FrameLength - IpFrameLength) != 0xe) {
-                               /* Frame padded => TCP offload not possible! */
-                                       pMsg->ip_summed = CHECKSUM_NONE;
-                               } else {
-                               /* Frame not padded => TCP offload! */
-                                       if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
-                                               (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
-                                               (pAC->ChipsetType)) {
-                                               Result = SkCsGetReceiveInfo(pAC,
-                                                       &pMsg->data[14],
-                                                       Csum1, Csum2, pRxPort->PortIndex);
-                                               if (Result ==
-                                                       SKCS_STATUS_IP_FRAGMENT ||
-                                                       Result ==
-                                                       SKCS_STATUS_IP_CSUM_OK ||
-                                                       Result ==
-                                                       SKCS_STATUS_TCP_CSUM_OK ||
-                                                       Result ==
-                                                       SKCS_STATUS_UDP_CSUM_OK) {
-                                                               pMsg->ip_summed =
-                                                               CHECKSUM_UNNECESSARY;
-                                               }
-                                               else if (Result ==
-                                                       SKCS_STATUS_TCP_CSUM_ERROR ||
-                                                       Result ==
-                                                       SKCS_STATUS_UDP_CSUM_ERROR ||
-                                                       Result ==
-                                                       SKCS_STATUS_IP_CSUM_ERROR_UDP ||
-                                                       Result ==
-                                                       SKCS_STATUS_IP_CSUM_ERROR_TCP ||
-                                                       Result ==
-                                                       SKCS_STATUS_IP_CSUM_ERROR ) {
-                                                       /* HW Checksum error */
-                                                       SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-                                                       SK_DBGCAT_DRV_RX_PROGRESS,
-                                                       ("skge: CRC error. Frame dropped!\n"));
-                                                       goto rx_failed;
-                                               } else {
-                                                               pMsg->ip_summed =
-                                                               CHECKSUM_NONE;
-                                               }
-                                       }/* checksumControl calculation valid */
-                               } /* Frame length check */
-                       } /* IP frame */
+               pMsg->csum = pRxd->TcpSums & 0xffff;
+               pMsg->ip_summed = CHECKSUM_HW;
 #else
-                       pMsg->ip_summed = CHECKSUM_NONE;        
+               pMsg->ip_summed = CHECKSUM_NONE;
 #endif
-               } /* frame > SK_COPY_TRESHOLD */
-               
+
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
                ForRlmt = SK_RLMT_RX_PROTOCOL;
 #if 0
@@ -2904,7 +2417,7 @@ unsigned long     Flags;
 static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
 {
 
-DEV_NET *pNet = (DEV_NET*) dev->priv;
+DEV_NET *pNet = netdev_priv(dev);
 SK_AC  *pAC = pNet->pAC;
 
 struct sockaddr        *addr = p;
@@ -2961,7 +2474,7 @@ unsigned long             Flags;
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeSetRxMode starts now... "));
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC = pNet->pAC;
        if (pAC->RlmtNets == 1)
                PortIdx = pAC->ActivePort;
@@ -3024,7 +2537,7 @@ unsigned long             Flags;
 static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
 {
 DEV_NET                *pNet;
-DEV_NET                *pOtherNet;
+struct net_device *pOtherDev;
 SK_AC          *pAC;
 unsigned long  Flags;
 int            i;
@@ -3033,7 +2546,7 @@ SK_EVPARA         EvPara;
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeChangeMtu starts now...\n"));
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC  = pNet->pAC;
 
        if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
@@ -3054,11 +2567,11 @@ SK_EVPARA       EvPara;
        }
 #endif
 
-       pNet->Mtu = NewMtu;
-       pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv;
-       if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) {
-               return(0);
-       }
+       pOtherDev = pAC->dev[1 - pNet->NetNr];
+
+       if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
+            && (NewMtu <= 1500))
+               return 0;
 
        pAC->RxBufSize = NewMtu + 32;
        dev->mtu = NewMtu;
@@ -3093,8 +2606,7 @@ SK_EVPARA         EvPara;
        SkEventDispatcher(pAC, pAC->IoBase);
 
        for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-               spin_lock_irqsave(
-                       &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
+               spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
                netif_stop_queue(pAC->dev[i]);
 
        }
@@ -3221,7 +2733,8 @@ SK_EVPARA         EvPara;
                EvPara.Para32[1] = -1;
                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
                        
-               if (pOtherNet->Up) {
+               if (netif_running(pOtherDev)) {
+                       DEV_NET *pOtherNet = netdev_priv(pOtherDev);
                        EvPara.Para32[0] = pOtherNet->PortNr;
                        SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
                }
@@ -3262,7 +2775,7 @@ SK_EVPARA         EvPara;
  */
 static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
 {
-DEV_NET *pNet = (DEV_NET*) dev->priv;
+DEV_NET *pNet = netdev_priv(dev);
 SK_AC  *pAC = pNet->pAC;
 SK_PNMI_STRUCT_DATA *pPnmiStruct;       /* structure for all Pnmi-Data */
 SK_PNMI_STAT    *pPnmiStat;             /* pointer to virtual XMAC stat. data */
@@ -3295,7 +2808,7 @@ unsigned long     Flags;                  /* for spin lock */
        pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
        pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
        
-        if (pNet->Mtu <= 1500) {
+        if (dev->mtu <= 1500) {
                 pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
         } else {
                 pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
@@ -3338,7 +2851,7 @@ unsigned long     Flags;                  /* for spin lock */
  * Description:
  *     This function is called if an ioctl is issued on the device.
  *     There are three subfunction for reading, writing and test-writing
- *     the private MIB data structure (usefull for SysKonnect-internal tools).
+ *     the private MIB data structure (useful for SysKonnect-internal tools).
  *
  * Returns:
  *     0, if everything is ok
@@ -3360,7 +2873,7 @@ int               HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeIoctl starts now...\n"));
 
-       pNet = (DEV_NET*) dev->priv;
+       pNet = netdev_priv(dev);
        pAC = pNet->pAC;
        
        if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
@@ -3441,7 +2954,7 @@ fault_gen:
                */
                * ((SK_U32 *)pMemBuf) = 0;
                * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
-               * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pdev->slot_name);
+               * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
                if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
                        Err = -EFAULT;
                        goto fault_diag;
@@ -4246,25 +3759,21 @@ int     Capabilities[3][3] =
  *
  * Returns: N/A
  */
-static void ProductStr(
-SK_AC  *pAC            /* pointer to adapter context */
+static inline int ProductStr(
+       SK_AC   *pAC,           /* pointer to adapter context */
+       char    *DeviceStr,     /* result string */
+       int      StrLen         /* length of the string */
 )
 {
-int    StrLen = 80;            /* length of the string, defined in SK_AC */
 char   Keyword[] = VPD_NAME;   /* vpd productname identifier */
 int    ReturnCode;             /* return code from vpd_read */
 unsigned long Flags;
 
        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-       ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr,
-               &StrLen);
+       ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-       if (ReturnCode != 0) {
-               /* there was an error reading the vpd data */
-               SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
-                       ("Error reading VPD data: %d\n", ReturnCode));
-               pAC->DeviceStr[0] = '\0';
-       }
+
+       return ReturnCode;
 } /* ProductStr */
 
 /*****************************************************************************
@@ -4465,28 +3974,6 @@ SK_U8 *pVal)             /* pointer to store the read value */
 } /* SkPciReadCfgByte */
 
 
-/*****************************************************************************
- *
- *     SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- *     This routine writes a 32 bit value to the pci configuration
- *     space.
- *
- * Returns:
- *     0 - indicate everything worked ok.
- *     != 0 - error indication
- */
-int SkPciWriteCfgDWord(
-SK_AC *pAC,    /* Adapter Control structure pointer */
-int PciAddr,           /* PCI register address */
-SK_U32 Val)            /* pointer to store the read value */
-{
-       pci_write_config_dword(pAC->PciDev, PciAddr, Val);
-       return(0);
-} /* SkPciWriteCfgDWord */
-
-
 /*****************************************************************************
  *
  *     SkPciWriteCfgWord - write a 16 bit value to pci config space
@@ -4595,7 +4082,7 @@ SK_BOOL           DualNet;
                        Flags);
 
                SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
-               pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
+               netif_carrier_off(pAC->dev[Param.Para32[0]]);
                spin_unlock_irqrestore(
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
@@ -4625,6 +4112,7 @@ SK_BOOL           DualNet;
                        Flags);
                break;
        case SK_DRV_NET_UP:      /* SK_U32 PortIdx */
+       {       struct net_device *dev = pAC->dev[Param.Para32[0]];
                /* action list 5 */
                FromPort = Param.Para32[0];
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4708,22 +4196,12 @@ SK_BOOL         DualNet;
                        printk("    irq moderation:  disabled\n");
 
 
-#ifdef SK_ZEROCOPY
-               if (pAC->ChipsetType)
-#ifdef USE_SK_TX_CHECKSUM
-                       printk("    scatter-gather:  enabled\n");
-#else
-                       printk("    tx-checksum:     disabled\n");
-#endif
-               else
-                       printk("    scatter-gather:  disabled\n");
-#else
-                       printk("    scatter-gather:  disabled\n");
-#endif
-
-#ifndef USE_SK_RX_CHECKSUM
-                       printk("    rx-checksum:     disabled\n");
-#endif
+               printk("    scatter-gather:  %s\n",
+                      (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
+               printk("    tx-checksum:     %s\n",
+                      (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
+               printk("    rx-checksum:     %s\n",
+                      pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
 
                } else {
                         DoPrintInterfaceChange = SK_TRUE;
@@ -4738,9 +4216,9 @@ SK_BOOL           DualNet;
                }
 
                /* Inform the world that link protocol is up. */
-               pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
-
+               netif_carrier_on(dev);
                break;
+       }
        case SK_DRV_NET_DOWN:    /* SK_U32 Reason */
                /* action list 7 */
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4751,7 +4229,7 @@ SK_BOOL           DualNet;
                } else {
                        DoPrintInterfaceChange = SK_TRUE;
                }
-               pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
+               netif_carrier_off(pAC->dev[Param.Para32[1]]);
                break;
        case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4773,12 +4251,10 @@ SK_BOOL         DualNet;
                spin_lock_irqsave(
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
-               spin_lock_irqsave(
-                       &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+               spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
                SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
                SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
-               spin_unlock_irqrestore(
-                       &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+               spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
                spin_unlock_irqrestore(
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
@@ -4791,8 +4267,7 @@ SK_BOOL           DualNet;
                spin_lock_irqsave(
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
-               spin_lock_irqsave(
-                       &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+               spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
                pAC->ActivePort = ToPort;
 #if 0
                SetQueueSizes(pAC);
@@ -4807,8 +4282,7 @@ SK_BOOL           DualNet;
                        pAC,
                        pAC->ActivePort,
                        DualNet)) {
-                       spin_unlock_irqrestore(
-                               &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+                       spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
                        spin_unlock_irqrestore(
                                &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                                Flags);
@@ -4834,8 +4308,7 @@ SK_BOOL           DualNet;
                SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
                ClearAndStartRx(pAC, FromPort);
                ClearAndStartRx(pAC, ToPort);
-               spin_unlock_irqrestore(
-                       &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+               spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
                spin_unlock_irqrestore(
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
@@ -4951,18 +4424,15 @@ char    ClassStr[80];
 int SkDrvEnterDiagMode(
 SK_AC   *pAc)   /* pointer to adapter context */
 {
-       SK_AC   *pAC  = NULL;
-       DEV_NET *pNet = NULL;
-
-       pNet = (DEV_NET *) pAc->dev[0]->priv;
-       pAC = pNet->pAC;
+       DEV_NET *pNet = netdev_priv(pAc->dev[0]);
+       SK_AC   *pAC  = pNet->pAC;
 
        SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), 
                        sizeof(SK_PNMI_STRUCT_DATA));
 
        pAC->DiagModeActive = DIAG_ACTIVE;
        if (pAC->BoardLevel > SK_INIT_DATA) {
-               if (pNet->Up) {
+               if (netif_running(pAC->dev[0])) {
                        pAC->WasIfUp[0] = SK_TRUE;
                        pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose      */
                        DoPrintInterfaceChange = SK_FALSE;
@@ -4970,9 +4440,9 @@ SK_AC   *pAc)   /* pointer to adapter context */
                } else {
                        pAC->WasIfUp[0] = SK_FALSE;
                }
-               if (pNet != (DEV_NET *) pAc->dev[1]->priv) {
-                       pNet = (DEV_NET *) pAc->dev[1]->priv;
-                       if (pNet->Up) {
+               if (pNet != netdev_priv(pAC->dev[1])) {
+                       pNet = netdev_priv(pAC->dev[1]);
+                       if (netif_running(pAC->dev[1])) {
                                pAC->WasIfUp[1] = SK_TRUE;
                                pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
                                DoPrintInterfaceChange = SK_FALSE;
@@ -5093,20 +4563,11 @@ int      devNbr)        /* what device is to be handled */
 
        dev = pAC->dev[devNbr];
 
-       /*
-       ** Function SkGeClose() uses MOD_DEC_USE_COUNT (2.2/2.4)
-       ** or module_put() (2.6) to decrease the number of users for
-       ** a device, but if a device is to be put under control of 
-       ** the DIAG, that count is OK already and does not need to 
-       ** be adapted! Hence the opposite MOD_INC_USE_COUNT or 
-       ** try_module_get() needs to be used again to correct that.
+       /* On Linux 2.6 the network driver does NOT mess with reference
+       ** counts.  The driver MUST be able to be unloaded at any time
+       ** due to the possibility of hotplug.
        */
-       if (!try_module_get(THIS_MODULE)) {
-               return (-1);
-       }
-
        if (SkGeClose(dev) != 0) {
-               module_put(THIS_MODULE);
                return (-1);
        }
        return (0);
@@ -5135,17 +4596,6 @@ int      devNbr) /* what device is to be handled */
 
        if (SkGeOpen(dev) != 0) {
                return (-1);
-       } else {
-               /*
-               ** Function SkGeOpen() uses MOD_INC_USE_COUNT (2.2/2.4) 
-               ** or try_module_get() (2.6) to increase the number of 
-               ** users for a device, but if a device was just under 
-               ** control of the DIAG, that count is OK already and 
-               ** does not need to be adapted! Hence the opposite 
-               ** MOD_DEC_USE_COUNT or module_put() needs to be used 
-               ** again to correct that.
-               */
-               module_put(THIS_MODULE);
        }
 
        /*
@@ -5310,8 +4760,386 @@ int     l;
 
 #endif
 
-/*******************************************************************************
- *
- * End of file
- *
- ******************************************************************************/
+static int __devinit skge_probe_one(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
+{
+       SK_AC                   *pAC;
+       DEV_NET                 *pNet = NULL;
+       struct net_device       *dev = NULL;
+       static int boards_found = 0;
+       int error = -ENODEV;
+       int using_dac = 0;
+       char DeviceStr[80];
+
+       if (pci_enable_device(pdev))
+               goto out;
+       /* Configure DMA attributes. */
+       if (sizeof(dma_addr_t) > sizeof(u32) &&
+           !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+               using_dac = 1;
+               error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+               if (error < 0) {
+                       printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
+                              "for consistent allocations\n", pci_name(pdev));
+                       goto out_disable_device;
+               }
+       } else {
+               error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (error) {
+                       printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
+                              pci_name(pdev));
+                       goto out_disable_device;
+               }
+       }
+
+       error = -ENOMEM;
+       dev = alloc_etherdev(sizeof(DEV_NET));
+       if (!dev) {
+               printk(KERN_ERR "sk98lin: unable to allocate etherdev "
+                      "structure!\n");
+               goto out_disable_device;
+       }
+
+       pNet = netdev_priv(dev);
+       pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
+       if (!pNet->pAC) {
+               printk(KERN_ERR "sk98lin: unable to allocate adapter "
+                      "structure!\n");
+               goto out_free_netdev;
+       }
+
+       pAC = pNet->pAC;
+       pAC->PciDev = pdev;
+
+       pAC->dev[0] = dev;
+       pAC->dev[1] = dev;
+       pAC->CheckQueue = SK_FALSE;
+
+       dev->irq = pdev->irq;
+
+       error = SkGeInitPCI(pAC);
+       if (error) {
+               printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
+               goto out_free_netdev;
+       }
+
+       SET_MODULE_OWNER(dev);
+       dev->open =             &SkGeOpen;
+       dev->stop =             &SkGeClose;
+       dev->hard_start_xmit =  &SkGeXmit;
+       dev->get_stats =        &SkGeStats;
+       dev->set_multicast_list = &SkGeSetRxMode;
+       dev->set_mac_address =  &SkGeSetMacAddr;
+       dev->do_ioctl =         &SkGeIoctl;
+       dev->change_mtu =       &SkGeChangeMtu;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller =  &SkGePollController;
+#endif
+       SET_NETDEV_DEV(dev, &pdev->dev);
+       SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
+
+       /* Use only if yukon hardware */
+       if (pAC->ChipsetType) {
+#ifdef USE_SK_TX_CHECKSUM
+               dev->features |= NETIF_F_IP_CSUM;
+#endif
+#ifdef SK_ZEROCOPY
+               dev->features |= NETIF_F_SG;
+#endif
+#ifdef USE_SK_RX_CHECKSUM
+               pAC->RxPort[0].RxCsum = 1;
+#endif
+       }
+
+       if (using_dac)
+               dev->features |= NETIF_F_HIGHDMA;
+
+       pAC->Index = boards_found++;
+
+       error = SkGeBoardInit(dev, pAC);
+       if (error)
+               goto out_free_netdev;
+
+       /* Read Adapter name from VPD */
+       if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
+               error = -EIO;
+               printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
+               goto out_free_resources;
+       }
+
+       /* Register net device */
+       error = register_netdev(dev);
+       if (error) {
+               printk(KERN_ERR "sk98lin: Could not register device.\n");
+               goto out_free_resources;
+       }
+
+       /* Print adapter specific string from vpd */
+       printk("%s: %s\n", dev->name, DeviceStr);
+
+       /* Print configuration settings */
+       printk("      PrefPort:%c  RlmtMode:%s\n",
+               'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
+               (pAC->RlmtMode==0)  ? "Check Link State" :
+               ((pAC->RlmtMode==1) ? "Check Link State" :
+               ((pAC->RlmtMode==3) ? "Check Local Port" :
+               ((pAC->RlmtMode==7) ? "Check Segmentation" :
+               ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
+
+       SkGeYellowLED(pAC, pAC->IoBase, 1);
+
+       memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+       pNet->PortNr = 0;
+       pNet->NetNr  = 0;
+
+       boards_found++;
+
+       pci_set_drvdata(pdev, dev);
+
+       /* More then one port found */
+       if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+               dev = alloc_etherdev(sizeof(DEV_NET));
+               if (!dev) {
+                       printk(KERN_ERR "sk98lin: unable to allocate etherdev "
+                               "structure!\n");
+                       goto single_port;
+               }
+
+               pNet          = netdev_priv(dev);
+               pNet->PortNr  = 1;
+               pNet->NetNr   = 1;
+               pNet->pAC     = pAC;
+
+               dev->open               = &SkGeOpen;
+               dev->stop               = &SkGeClose;
+               dev->hard_start_xmit    = &SkGeXmit;
+               dev->get_stats          = &SkGeStats;
+               dev->set_multicast_list = &SkGeSetRxMode;
+               dev->set_mac_address    = &SkGeSetMacAddr;
+               dev->do_ioctl           = &SkGeIoctl;
+               dev->change_mtu         = &SkGeChangeMtu;
+               SET_NETDEV_DEV(dev, &pdev->dev);
+               SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
+
+               if (pAC->ChipsetType) {
+#ifdef USE_SK_TX_CHECKSUM
+                       dev->features |= NETIF_F_IP_CSUM;
+#endif
+#ifdef SK_ZEROCOPY
+                       dev->features |= NETIF_F_SG;
+#endif
+#ifdef USE_SK_RX_CHECKSUM
+                       pAC->RxPort[1].RxCsum = 1;
+#endif
+               }
+
+               if (using_dac)
+                       dev->features |= NETIF_F_HIGHDMA;
+
+               error = register_netdev(dev);
+               if (error) {
+                       printk(KERN_ERR "sk98lin: Could not register device"
+                              " for second port. (%d)\n", error);
+                       free_netdev(dev);
+                       goto single_port;
+               }
+
+               pAC->dev[1]   = dev;
+               memcpy(&dev->dev_addr,
+                      &pAC->Addr.Net[1].CurrentMacAddress, 6);
+               memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+               printk("%s: %s\n", dev->name, DeviceStr);
+               printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
+       }
+
+single_port:
+
+       /* Save the hardware revision */
+       pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+               (pAC->GIni.GIPciHwRev & 0x0F);
+
+       /* Set driver globals */
+       pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
+       pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+
+       memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
+       memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
+
+       return 0;
+
+ out_free_resources:
+       FreeResources(dev);
+ out_free_netdev:
+       free_netdev(dev);
+ out_disable_device:
+       pci_disable_device(pdev);
+ out:
+       return error;
+}
+
+static void __devexit skge_remove_one(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       DEV_NET *pNet = netdev_priv(dev);
+       SK_AC *pAC = pNet->pAC;
+       struct net_device *otherdev = pAC->dev[1];
+
+       unregister_netdev(dev);
+
+       SkGeYellowLED(pAC, pAC->IoBase, 0);
+
+       if (pAC->BoardLevel == SK_INIT_RUN) {
+               SK_EVPARA EvPara;
+               unsigned long Flags;
+
+               /* board is still alive */
+               spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+               EvPara.Para32[0] = 0;
+               EvPara.Para32[1] = -1;
+               SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+               EvPara.Para32[0] = 1;
+               EvPara.Para32[1] = -1;
+               SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+               SkEventDispatcher(pAC, pAC->IoBase);
+               /* disable interrupts */
+               SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+               SkGeDeInit(pAC, pAC->IoBase);
+               spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+               pAC->BoardLevel = SK_INIT_DATA;
+               /* We do NOT check here, if IRQ was pending, of course*/
+       }
+
+       if (pAC->BoardLevel == SK_INIT_IO) {
+               /* board is still alive */
+               SkGeDeInit(pAC, pAC->IoBase);
+               pAC->BoardLevel = SK_INIT_DATA;
+       }
+
+       FreeResources(dev);
+       free_netdev(dev);
+       if (otherdev != dev)
+               free_netdev(otherdev);
+       kfree(pAC);
+}
+
+#ifdef CONFIG_PM
+static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       DEV_NET *pNet = netdev_priv(dev);
+       SK_AC *pAC = pNet->pAC;
+       struct net_device *otherdev = pAC->dev[1];
+
+       if (netif_running(dev)) {
+               netif_carrier_off(dev);
+               DoPrintInterfaceChange = SK_FALSE;
+               SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
+               netif_device_detach(dev);
+       }
+       if (otherdev != dev) {
+               if (netif_running(otherdev)) {
+                       netif_carrier_off(otherdev);
+                       DoPrintInterfaceChange = SK_FALSE;
+                       SkDrvDeInitAdapter(pAC, 1);  /* performs SkGeClose */
+                       netif_device_detach(otherdev);
+               }
+       }
+
+       pci_save_state(pdev);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+       if (pAC->AllocFlag & SK_ALLOC_IRQ) {
+               free_irq(dev->irq, dev);
+       }
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int skge_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       DEV_NET *pNet = netdev_priv(dev);
+       SK_AC *pAC = pNet->pAC;
+       struct net_device *otherdev = pAC->dev[1];
+       int ret;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_device(pdev);
+       pci_set_master(pdev);
+       if (pAC->GIni.GIMacsFound == 2)
+               ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev);
+       else
+               ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, "sk98lin", dev);
+       if (ret) {
+               printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
+               pAC->AllocFlag &= ~SK_ALLOC_IRQ;
+               dev->irq = 0;
+               pci_disable_device(pdev);
+               return -EBUSY;
+       }
+
+       netif_device_attach(dev);
+       if (netif_running(dev)) {
+               DoPrintInterfaceChange = SK_FALSE;
+               SkDrvInitAdapter(pAC, 0);    /* first device  */
+       }
+       if (otherdev != dev) {
+               netif_device_attach(otherdev);
+               if (netif_running(otherdev)) {
+                       DoPrintInterfaceChange = SK_FALSE;
+                       SkDrvInitAdapter(pAC, 1);    /* second device  */
+               }
+       }
+
+       return 0;
+}
+#else
+#define skge_suspend NULL
+#define skge_resume NULL
+#endif
+
+static struct pci_device_id skge_pci_tbl[] = {
+       { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+/* DLink card does not have valid VPD so this driver gags
+ *     { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ */
+       { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
+       { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
+
+static struct pci_driver skge_driver = {
+       .name           = "sk98lin",
+       .id_table       = skge_pci_tbl,
+       .probe          = skge_probe_one,
+       .remove         = __devexit_p(skge_remove_one),
+       .suspend        = skge_suspend,
+       .resume         = skge_resume,
+};
+
+static int __init skge_init(void)
+{
+       return pci_module_init(&skge_driver);
+}
+
+static void __exit skge_exit(void)
+{
+       pci_unregister_driver(&skge_driver);
+}
+
+module_init(skge_init);
+module_exit(skge_exit);