commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / drivers / net / sk98lin / skge.c
index 067fc2f..95f69ef 100644 (file)
@@ -1,19 +1,22 @@
+
 /******************************************************************************
  *
  * Name:    skge.c
  * Project:    GEnesis, PCI Gigabit Ethernet Adapter
- * Version:    $Revision: 1.29.2.6 $
- * Date:               $Date: 2001/05/21 07:59:29 $
+ * Version:    $Revision: 1.63 $
+ * Date:               $Date: 2003/07/15 09:26:23 $
  * Purpose:    The main driver source module
  *
  ******************************************************************************/
+
 /******************************************************************************
  *
- *     (C)Copyright 1998-2001 SysKonnect GmbH.
+ *     (C)Copyright 1998-2003 SysKonnect GmbH.
  *
  *     Driver for SysKonnect Gigabit Ethernet Server Adapters:
  *
+ *     SK-9871 (single link 1000Base-ZX)
+ *     SK-9872 (dual link   1000Base-ZX)
  *     SK-9861 (single link 1000Base-SX, VF45 Volition Plug)
  *     SK-9862 (dual link   1000Base-SX, VF45 Volition Plug)
  *     SK-9841 (single link 1000Base-LX)
  *     SK-9844 (dual link   1000Base-SX)
  *     SK-9821 (single link 1000Base-T)
  *     SK-9822 (dual link   1000Base-T)
- *
- *     Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and 
+ *     SK-9881 (single link 1000Base-SX V2 LC)
+ *     SK-9871 (single link 1000Base-ZX V2)
+ *     SK-9861 (single link 1000Base-SX V2, VF45 Volition Plug)
+ *     SK-9841 (single link 1000Base-LX V2)
+ *     SK-9843 (single link 1000Base-SX V2)
+ *     SK-9821 (single link 1000Base-T V2)
+ *
+ *     Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
  *     SysKonnects GEnesis Solaris driver
  *     Author: Christoph Goos (cgoos@syskonnect.de)
  *             Mirko Lindner (mlindner@syskonnect.de)
  * History:
  *
  *     $Log: skge.c,v $
- *     Revision x.xx.x.x  2003/06/07 02:31:17  romieu@fr.zoreil.com
- *      pci api style init.
- *
+ *     Revision 1.63  2003/07/15 09:26:23  rroesler
+ *     Fix: Removed memory leak when sending short padded frames
+ *     
+ *     Revision 1.62  2003/07/09 11:11:16  rroesler
+ *     Fix: Call of ReceiveIrq() performed with parameter SK_FALSE in
+ *          order not to hang the system with multiple spinlocks
+ *     
+ *     Revision 1.61  2003/07/08 07:32:41  rroesler
+ *     Fix: Correct Kernel-version
+ *     
+ *     Revision 1.60  2003/07/07 15:42:30  rroesler
+ *     Fix: Removed function pci_present() for 2.5/2.6 kernels (deprecated)
+ *     Fix: Corrected warning in GetConfiguration()
+ *     
+ *     Revision 1.59  2003/07/07 09:44:32  rroesler
+ *     Add: HW checksumming on kernel 2.5/2.6
+ *     Add: padding of short frames (<60 bytes) with 0x00 instead of 0xaa
+ *     Add: ConType parameter combining multiple other parameters into one
+ *     Fix: Corrected bugreport #10721 (warning when changing MTU size)
+ *     Fix: Removed obsolete function SetQueueSize()
+ *     Fix: Function ChangeMtuSize() returns new MTU size in kernel 2.5/2.6
+ *     
+ *     Revision 1.58  2003/06/17 07:14:29  mlindner
+ *     Add: Disable checksum functionality
+ *     Fix: Unload module (Kernel 2.5)
+ *     
+ *     Revision 1.57  2003/06/05 14:55:27  mlindner
+ *     Fix: ProcFS creation (Kernel 2.2.x)
+ *     Fix: ProcFS OWNER (Kernel 2.2.x)
+ *     
+ *     Revision 1.56  2003/06/03 14:34:29  mlindner
+ *     Add: Additions for SK_SLIM
+ *     Fix: SkGeIoctl SK_IOCTL_GEN
+ *     
+ *     Revision 1.55  2003/05/26 13:00:52  mlindner
+ *     Add: Support for Kernel 2.5/2.6
+ *     Add: Support for new IO-control MIB data structure
+ *     Add: New SkOsGetTime function
+ *     Fix: Race condition with broken LM80 chip
+ *     Fix: Race condition with padded frames
+ *     
+ *     Revision 1.54  2003/04/28 13:07:27  mlindner
+ *     Fix: Delay race condition with some server machines
+ *     
+ *     Revision 1.53  2003/04/28 12:49:49  mlindner
+ *     Fix: Code optimization
+ *     
+ *     Revision 1.52  2003/04/28 12:24:32  mlindner
+ *     Fix: Disabled HW Error IRQ on 32-bit Yukon if sensor IRQ occurs
+ *     
+ *     Revision 1.51  2003/04/16 08:31:14  mlindner
+ *     Fix: Kernel 2.2 compilation
+ *     
+ *     Revision 1.49  2003/04/10 09:08:51  mlindner
+ *     Add: Blink mode verification
+ *     Fix: Checksum calculation
+ *     
+ *     Revision 1.48  2003/03/21 14:48:38  rroesler
+ *     Added code for interrupt moderation
+ *     
+ *     Revision 1.47  2003/03/12 13:56:15  mlindner
+ *     Fix: Mac update during SK_DRV_NET_UP
+ *     
+ *     Revision 1.46  2003/02/25 14:16:36  mlindner
+ *     Fix: Copyright statement
+ *     
+ *     Revision 1.45  2003/02/25 13:25:55  mlindner
+ *     Add: Performance improvements
+ *     Add: Support for various vendors
+ *     Fix: Init function
+ *     
+ *     Revision 1.44  2003/01/09 09:25:26  mlindner
+ *     Fix: Remove useless init_module/cleanup_module forward declarations
+ *     
+ *     Revision 1.43  2002/11/29 08:42:41  mlindner
+ *     Fix: Boot message
+ *     
+ *     Revision 1.42  2002/11/28 13:30:23  mlindner
+ *     Add: New frame check
+ *     
+ *     Revision 1.41  2002/11/27 13:55:18  mlindner
+ *     Fix: Drop wrong csum packets
+ *     Fix: Initialize proc_entry after hw check
+ *     
+ *     Revision 1.40  2002/10/31 07:50:37  tschilli
+ *     Function SkGeInitAssignRamToQueues() from common module inserted.
+ *     Autonegotiation is set to ON for all adapters.
+ *     LinkSpeedUsed is used in link up status report.
+ *     Role parameter will show up for 1000 Mbps links only.
+ *     GetConfiguration() inserted after init level 1 in SkGeChangeMtu().
+ *     All return values of SkGeInit() and SkGeInitPort() are checked.
+ *     
+ *     Revision 1.39  2002/10/02 12:56:05  mlindner
+ *     Add: Support for Yukon
+ *     Add: Support for ZEROCOPY, scatter-gather and hw checksum
+ *     Add: New transmit ring function (use SG and TCP/UDP hardware checksumming)
+ *     Add: New init function
+ *     Add: Speed check and setup
+ *     Add: Merge source for kernel 2.2.x and 2.4.x
+ *     Add: Opcode check for tcp
+ *     Add: Frame length check
+ *     Fix: Transmit complete interrupt
+ *     Fix: Interrupt moderation
+ *     
+ *     Revision 1.29.2.13  2002/01/14 12:44:52  mlindner
+ *     Fix: Rlmt modes
+ *     
+ *     Revision 1.29.2.12  2001/12/07 12:06:18  mlindner
+ *     Fix: malloc -> slab changes
+ *     
+ *     Revision 1.29.2.11  2001/12/06 15:19:20  mlindner
+ *     Add: DMA attributes
+ *     Fix: Module initialisation
+ *     Fix: pci_map_single and pci_unmap_single replaced
+ *     
+ *     Revision 1.29.2.10  2001/12/06 09:56:50  mlindner
+ *     Corrected some printk's
+ *     
+ *     Revision 1.29.2.9  2001/09/05 12:15:34  mlindner
+ *     Add: LBFO Changes
+ *     Fix: Counter Errors (Jumbo == to long errors)
+ *     Fix: Changed pAC->PciDev declaration
+ *     Fix: too short counters
+ *     
+ *     Revision 1.29.2.8  2001/06/25 12:10:44  mlindner
+ *     fix: ReceiveIrq() changed.
+ *     
+ *     Revision 1.29.2.7  2001/06/25 08:07:05  mlindner
+ *     fix: RLMT locking in ReceiveIrq() changed.
+ *     
  *     Revision 1.29.2.6  2001/05/21 07:59:29  mlindner
  *     fix: MTU init problems
  *     
  *     Printing "ethX:" before adapter type at adapter init.
  *     
  *
- *     10-Feb-1999 cg  Created, based on Linux' acenic.c, 3c59x.c and 
+ *     10-Feb-1999 cg  Created, based on Linux' acenic.c, 3c59x.c and
  *                     SysKonnects GEnesis Solaris driver
  *
  ******************************************************************************/
  *
  * Possible compiler options (#define xxx / -Dxxx):
  *
- *     debugging can be enable by changing SK_DEBUG_CHKMOD and 
+ *     debugging can be enable by changing SK_DEBUG_CHKMOD and
  *     SK_DEBUG_CHKCAT in makefile (described there).
  *
  ******************************************************************************/
+
 /******************************************************************************
  *
  * Description:
 #include       "h/skdrv1st.h"
 #include       "h/skdrv2nd.h"
 
-/* defines ******************************************************************/
-
-#define DRV_MODULE_NAME                "sk98lin"
-#define PFX DRV_MODULE_NAME    ": "
+/*******************************************************************************
+ *
+ * Defines
+ *
+ ******************************************************************************/
 
 /* for debuging on x86 only */
 /* #define BREAKPOINT() asm(" int $3"); */
 
+/* use the transmit hw checksum driver functionality */
+#define USE_SK_TX_CHECKSUM
+
+/* use the receive hw checksum driver functionality */
+#define USE_SK_RX_CHECKSUM
+
+/* use the scatter-gather functionality with sendfile() */
+#define SK_ZEROCOPY
+
 /* use of a transmit complete interrupt */
 #define USE_TX_COMPLETE
 
-/* use interrupt moderation (for tx complete only) */
-// #define USE_INT_MOD
-#define INTS_PER_SEC   1000
-
 /*
  * threshold for copying small receive frames
  * set to 0 to avoid copying, set to 9001 to copy all frames
  */
-#define SK_COPY_THRESHOLD      200
+#define SK_COPY_THRESHOLD      50
 
 /* number of adapters that can be configured via command line params */
 #define SK_MAX_CARD_PARAM      16
 
+
+
 /*
- * use those defines for a compile-in version of the driver instead 
+ * use those defines for a compile-in version of the driver instead
  * of command line parameters
  */
+// #define LINK_SPEED_A        {"Auto", }
+// #define LINK_SPEED_B        {"Auto", }
 // #define AUTO_NEG_A  {"Sense", }
 // #define AUTO_NEG_B  {"Sense", }
 // #define DUP_CAP_A   {"Both", }
 // #define ROLE_A      {"Auto", }
 // #define ROLE_B      {"Auto", }
 // #define PREF_PORT   {"A", }
+// #define CON_TYPE    {"Auto", }
 // #define RLMT_MODE   {"CheckLinkState", }
 
 #define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
 #define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
 #define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
 
-/* function prototypes ******************************************************/
-static void    FreeResources(struct net_device *dev);
-static int     SkGeBoardInit(struct net_device *dev, SK_AC *pAC);
+
+/* Set blink mode*/
+#define OEM_CONFIG_VALUE (     SK_ACT_LED_BLINK | \
+                               SK_DUP_LED_NORMAL | \
+                               SK_LED_LINK100_ON)
+
+
+/* Isr return value */
+#define SkIsrRetVar    irqreturn_t
+#define SkIsrRetNone   IRQ_NONE
+#define SkIsrRetHandled        IRQ_HANDLED
+
+
+/*******************************************************************************
+ *
+ * Local Function Prototypes
+ *
+ ******************************************************************************/
+
+static void    FreeResources(struct SK_NET_DEVICE *dev);
+static int     SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
 static SK_BOOL BoardAllocMem(SK_AC *pAC);
 static void    BoardFreeMem(SK_AC *pAC);
 static void    BoardInitMem(SK_AC *pAC);
-static void    SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**,
-                       int*, SK_BOOL);
-
-static irqreturn_t SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
-static irqreturn_t SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
-static int     SkGeOpen(struct net_device *dev);
-static int     SkGeClose(struct net_device *dev);
-static int     SkGeXmit(struct sk_buff *skb, struct net_device *dev);
-static int     SkGeSetMacAddr(struct net_device *dev, void *p);
-static void    SkGeSetRxMode(struct net_device *dev);
-static struct net_device_stats *SkGeStats(struct net_device *dev);
-static int     SkGeIoctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void    SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
+static SkIsrRetVar     SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
+static SkIsrRetVar     SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
+static int     SkGeOpen(struct SK_NET_DEVICE *dev);
+static int     SkGeClose(struct SK_NET_DEVICE *dev);
+static int     SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
+static int     SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
+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*);
 static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*);
-static void    ReceiveIrq(SK_AC*, RX_PORT*);
+static void    ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
 static void    ClearAndStartRx(SK_AC*, int);
 static void    ClearTxIrq(SK_AC*, int, int);
 static void    ClearRxRing(SK_AC*, RX_PORT*);
 static void    ClearTxRing(SK_AC*, TX_PORT*);
-static void    SetQueueSizes(SK_AC     *pAC);
-static int     SkGeChangeMtu(struct net_device *dev, int new_mtu);
+static int     SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
 static void    PortReInitBmu(SK_AC*, int);
 static int     SkGeIocMib(DEV_NET*, unsigned int, int);
+static void    StartDrvCleanupTimer(SK_AC *pAC);
+static void    StopDrvCleanupTimer(SK_AC *pAC);
+static int     XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
 
+/*******************************************************************************
+ *
+ * Extern Function Prototypes
+ *
+ ******************************************************************************/
 
-static const char SK_Root_Dir_entry[] = "sk98lin";
-static struct proc_dir_entry *pSkRootDir;
+static const char      SK_Root_Dir_entry[] = "sk98lin";
+static struct          proc_dir_entry *pSkRootDir;
+extern int             sk_proc_read(   char   *buffer,
+                                       char    **buffer_location,
+                                       off_t   offset,
+                                       int     buffer_length,
+                                       int     *eof,
+                                       void    *data);
 
-extern struct file_operations sk_proc_fops;
+extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); 
+extern void SkDimDisplayModerationSettings(SK_AC *pAC);
+extern void SkDimStartModerationTimer(SK_AC *pAC);
+extern void SkDimModerate(SK_AC *pAC);
 
 #ifdef DEBUG
 static void    DumpMsg(struct sk_buff*, char*);
@@ -366,229 +545,302 @@ static void     DumpData(char*, int);
 static void    DumpLong(char*, int);
 #endif
 
-
 /* global variables *********************************************************/
-static int boards_found;
-struct inode_operations SkInodeOps;
-//static struct file_operations SkFileOps;  /* with open/relase */
+static const char *BootString = BOOT_STRING;
+struct SK_NET_DEVICE *SkGeRootDev = NULL;
+static int probed __initdata = 0;
 
 /* local variables **********************************************************/
 static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
 static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
 
-spinlock_t sk_devs_lock = SPIN_LOCK_UNLOCKED;
 
-static int SkGeDevInit(struct net_device *dev)
-{
-       DEV_NET *pNet = dev->priv;
-       int ret = 0;
-
-       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;
-
-       if (register_netdev(dev) != 0) {
-               printk(KERN_ERR "Unable to register etherdev\n");
-               ret = -ENOMEM;
-               goto out;
-       }
-       pNet->proc = create_proc_entry(dev->name, S_IFREG | 0444, pSkRootDir);
-       if (pNet->proc) {
-               pNet->proc->data = dev;
-               pNet->proc->owner = THIS_MODULE;
-               pNet->proc->proc_fops = &sk_proc_fops;
-       }
-out:
-       return ret;
-}
+static struct proc_dir_entry   *pSkRootDir;
 
-static void SkGeDevCleanUp(struct net_device *dev)
-{
-       DEV_NET *pNet = dev->priv;
-       
-       if (pNet->proc) {
-               spin_lock(&sk_devs_lock);
-               pNet->proc->data = NULL;
-               spin_unlock(&sk_devs_lock);
-               remove_proc_entry(dev->name, pSkRootDir);
-       }
-       unregister_netdev(dev);
-}
 
 /*****************************************************************************
  *
- *     skge_init_one - init a single instance of a SK-98xx adapter
+ *     skge_probe - find all SK-98xx adapters
  *
  * Description:
- *     This function allocates resources for an SK-98xx adapter and brings
- *     it into Init 1 state.
+ *     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.
  *
  * Returns:
  *     0, if everything is ok
- *     <0, on error
+ *     !=0, on error
  */
-static int __devinit skge_init_one(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int __init skge_probe (void)
 {
-       SK_AC           *pAC;
-       DEV_NET         *pNet;
-       unsigned long   base_address;
-       struct net_device *dev;
-       int ret;
+       int                     proc_root_initialized = 0;
+       int                     boards_found = 0;
+       int                     vendor_flag = SK_FALSE;
+       SK_AC                   *pAC;
+       DEV_NET                 *pNet = NULL;
+       struct proc_dir_entry   *pProcFile;
+       struct pci_dev  *pdev = NULL;
+       unsigned long           base_address;
+       struct SK_NET_DEVICE *dev = NULL;
+       SK_BOOL DeviceFound = SK_FALSE;
+       SK_BOOL BootStringCount = SK_FALSE;
+
+       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;
+
+
+               SK_PCI_ISCOMPLIANT(vendor_flag, pdev);
+               if (!vendor_flag)
+                       continue;
 
-#ifndef MODULE
-       static int      version_disp = 0;
+               /* Configure DMA attributes. */
+               if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) &&
+                       pci_set_dma_mask(pdev, (u64) 0xffffffff))
+                       continue;
 
-if (!version_disp++)
-               printk(KERN_INFO "%s\n", BOOT_STRING);
-#endif
-       ret = pci_enable_device(pdev);
-       if (ret)
-               goto out;
 
-       /* Configure DMA attributes. */
-       if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) {
-               ret = pci_set_dma_mask(pdev, (u64) 0xffffffff);
-               if (ret) {
-                       printk(KERN_ERR PFX "No usable DMA configuration\n");
-                       goto out_disable;
+               if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) {
+                       printk(KERN_ERR "Unable to allocate etherdev "
+                              "structure!\n");
+                       break;
                }
-       }
 
-       ret = -ENOMEM;
+               if (dev->priv == NULL) {
+                       printk(KERN_ERR "Unable to allocate adapter "
+                              "structure!\n");
+                       break;
+               }
 
-       dev = alloc_etherdev(sizeof(DEV_NET));
-       if (!dev) {
-               printk(KERN_ERR "Unable to allocate etherdev structure!\n");
-               goto out_disable;
-       }
+               pNet = dev->priv;
+               pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+               if (pNet->pAC == NULL){
+                       kfree(dev->priv);
+                       printk(KERN_ERR "Unable to allocate adapter "
+                              "structure!\n");
+                       break;
+               }
 
-       pNet = dev->priv;
+               /* Print message */
+               if (!BootStringCount) {
+                       /* set display flag to TRUE so that */
+                       /* we only display this string ONCE */
+                       BootStringCount = SK_TRUE;
+                       printk("%s\n", BootString);
+               }
 
-       pAC = kmalloc(sizeof(*pAC), GFP_KERNEL);
-       if (pAC == NULL){
-               printk(KERN_ERR "Unable to allocate adapter structure!\n");
-               goto out_free_dev;
-       }
+               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;
 
-       memset(pAC, 0, sizeof(SK_AC));
-       pNet->pAC = 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;
+               pNet->Mtu = 1500;
+               pNet->Up = 0;
+               dev->irq = pdev->irq;
+
+               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;
+               dev->flags &=           ~IFF_RUNNING;
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+
+               if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+                       /* Use only if yukon hardware */
+                       /* SK and ZEROCOPY - fly baby... */
+                       dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+               }
+#endif
+#endif
 
-       SET_MODULE_OWNER(dev);
-       SET_NETDEV_DEV(dev, &pdev->dev);
-       ret = SkGeDevInit(dev);
-       if (ret < 0)
-               goto out_free_priv;
+               /*
+                * Dummy value.
+                */
+               dev->base_addr = 42;
+               pci_set_master(pdev);
 
-       /*
-        * Dummy value.
-        */
-       dev->base_addr = 42;
-       pci_set_master(pdev);
-       base_address = pci_resource_start(pdev, 0);
+               pci_set_master(pdev);
+               base_address = pci_resource_start (pdev, 0);
 
 #ifdef SK_BIG_ENDIAN
-       /*
-        * On big endian machines, we use the adapter's ability of
-        * reading the descriptors as big endian.
-        */
-       {
+               /*
+                * On big endian machines, we use the adapter's aibility of
+                * reading the descriptors as big endian.
+                */
+               {
                SK_U32          our2;
-               SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
-               our2 |= PCI_REV_DESC;
-               SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
-       }
-#endif /* BIG ENDIAN */
-
-       /*
-        * Remap the regs into kernel space.
-        */
+                       SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
+                       our2 |= PCI_REV_DESC;
+                       SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
+               }
+#endif
 
-       pAC->IoBase = (char*)ioremap(base_address, 0x4000);
-       if (!pAC->IoBase) {
-               printk(KERN_ERR PFX "unable to map I/O register. "
-                      "SK 98xx device disabled.\n");
-               ret = -EIO;
-               goto out_dev_uninit;
-       }
-       pAC->Index = boards_found++;
+               /*
+                * Remap the regs into kernel space.
+                */
+               pAC->IoBase = (char*)ioremap(base_address, 0x4000);
 
-       ret = SkGeBoardInit(dev, pAC);
-       if (ret < 0)
-               goto out_free_resources;
+               if (!pAC->IoBase){
+                       printk(KERN_ERR "%s:  Unable to map I/O register, "
+                              "SK 98xx No. %i will be disabled.\n",
+                              dev->name, boards_found);
+                       kfree(dev);
+                       break;
+               }
 
-       memcpy((caddr_t) &dev->dev_addr,
-               (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
+               pAC->Index = boards_found;
+               if (SkGeBoardInit(dev, pAC)) {
+                       FreeResources(dev);
+                       kfree(dev);
+                       continue;
+               }
 
-       pNet->PortNr = 0;
-       pNet->NetNr = 0;
+               memcpy((caddr_t) &dev->dev_addr,
+                       (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
 
-       /* More then one port found */
-       if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-               struct net_device *sec_dev;
+               /* First adapter... Create proc and print message */
+               if (!DeviceFound) {
+                       DeviceFound = SK_TRUE;
+                       SK_MEMCPY(&SK_Root_Dir_entry, BootString,
+                               sizeof(SK_Root_Dir_entry) - 1);
+
+                       /*Create proc (directory)*/
+                       if(!proc_root_initialized) {
+                               pSkRootDir = create_proc_entry(SK_Root_Dir_entry,
+                                       S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net);
+                               pSkRootDir->owner = THIS_MODULE;
+                               proc_root_initialized = 1;
+                       }
 
-               sec_dev = alloc_etherdev(sizeof(DEV_NET));
-               if (!sec_dev) {
-                       printk(KERN_ERR PFX
-                               "Unable to allocate etherdev structure!\n");
-                       ret = -ENOMEM;
-                       goto out_free_resources;
                }
 
-               pAC->dev[1] = sec_dev;
-               pNet = sec_dev->priv;
-               pNet->PortNr = 1;
-               pNet->NetNr = 1;
-               pNet->pAC = pAC;
-               pNet->Mtu = 1500;
-               pNet->Up = 0;
 
-               ret = SkGeDevInit(sec_dev);
-               if (ret < 0)
-                       goto out_free_secondary_dev;
 
-               memcpy((caddr_t) &sec_dev->dev_addr,
-                       (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
+               /* Create proc file */
+               pProcFile = create_proc_entry(dev->name,
+                       S_IFREG | S_IXUSR | S_IWGRP | S_IROTH,
+                       pSkRootDir);
+
+               
+               pProcFile->read_proc = sk_proc_read;
+               pProcFile->write_proc = NULL;
+               pProcFile->nlink = 1;
+               pProcFile->size = sizeof(dev->name + 1);
+               pProcFile->data = (void *)pProcFile;
+               pProcFile->owner = THIS_MODULE;
+
+               pNet->PortNr = 0;
+               pNet->NetNr = 0;
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+                       if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+                               /* SG and ZEROCOPY - fly baby... */
+                               dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+                       }
+#endif
+#endif
+
+               boards_found++;
+
+               /* More then one port found */
+               if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+                       if ((dev = init_etherdev(NULL, 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->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->GIni.GIChipId == CHIP_ID_YUKON) {
+                               /* SG and ZEROCOPY - fly baby... */
+                               dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+                       }
+#endif
+#endif
+
+                       pProcFile = create_proc_entry(dev->name,
+                               S_IFREG | S_IXUSR | S_IWGRP | S_IROTH,
+                               pSkRootDir);
+
+               
+                       pProcFile->read_proc = sk_proc_read;
+                       pProcFile->write_proc = NULL;
+                       pProcFile->nlink = 1;
+                       pProcFile->size = sizeof(dev->name + 1);
+                       pProcFile->data = (void *)pProcFile;
+                       pProcFile->owner = THIS_MODULE;
+
+                       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");
+
+               }
+
 
-               printk("%s: %s\n", sec_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);
+
+               /*
+                * 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
        }
-       pci_set_drvdata(pdev, dev);
 
-       ret = 0;
-out:
-       return ret;
+       /*
+        * 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).
+        */
 
-out_free_secondary_dev:
-       kfree(pAC->dev[1]);
-out_free_resources:
-       FreeResources(dev);
-out_dev_uninit:
-       SkGeDevCleanUp(dev);
-out_free_priv:
-       kfree(pAC);
-out_free_dev:
-       kfree(dev);
-out_disable:
-       pci_disable_device(pdev);
-       goto out;
+       return boards_found;
+} /* skge_probe */
 
-} /* skge_init_one */
 
 /*****************************************************************************
  *
@@ -601,7 +853,7 @@ out_disable:
  * Returns: N/A
  *     
  */
-static void FreeResources(struct net_device *dev)
+static void FreeResources(struct SK_NET_DEVICE *dev)
 {
 SK_U32 AllocFlag;
 DEV_NET                *pNet;
@@ -624,9 +876,11 @@ SK_AC              *pAC;
        
 } /* FreeResources */
 
-MODULE_AUTHOR("Christoph Goos <cgoos@syskonnect.de>");
+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");
@@ -635,12 +889,31 @@ 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;
+#else
+static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef LINK_SPEED_B
+static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
+#else
+static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
 
 #ifdef AUTO_NEG_A
 static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
@@ -690,6 +963,12 @@ static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
 static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
 #endif
 
+#ifdef CON_TYPE
+static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
+#else
+static char *ConType[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
 #ifdef PREF_PORT
 static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
 #else
@@ -702,13 +981,47 @@ 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_remove_one - remove a single instance of a SK-98xx adapter
+ *     skge_cleanup_module - module unload function
  *
  * Description:
  *     Disable adapter if it is still running, free resources,
@@ -716,65 +1029,72 @@ static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
  *
  * Returns: N/A
  */
-static void __devexit skge_remove_one(struct pci_dev *pdev)
+static void __exit skge_cleanup_module(void)
 {
-       struct net_device *dev = pci_get_drvdata(pdev);
-       DEV_NET *pNet = dev->priv;
-       SK_AC *pAC = pNet->pAC;
-       unsigned long Flags;
-       SK_EVPARA EvPara;
+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(dev);
-       SkGeYellowLED(pAC, pAC->IoBase, 0);
-       if (pNet->proc) {
-               spin_lock(&sk_devs_lock);
-               pNet->proc->data = NULL;
-               spin_unlock(&sk_devs_lock);
-               remove_proc_entry(dev->name, pSkRootDir);
-       }
+               netif_stop_queue(SkGeRootDev);
+               SkGeYellowLED(pAC, pAC->IoBase, 0);
 
-       if (pAC->BoardLevel == 2) {
-               /* 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 = 0;
-               /* We do NOT check here, if IRQ was pending, of course*/
-       }
+               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 == 1) {
-               /* board is still alive */
-               SkGeDeInit(pAC, pAC->IoBase); 
-               pAC->BoardLevel = 0;
-       }
+               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]);
+                       kfree(pAC->dev[1]);
+               }
 
-       if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2) {
-               SkGeDevCleanUp(pAC->dev[1]);
-               kfree(pAC->dev[1]);
+               FreeResources(SkGeRootDev);
+
+               SkGeRootDev->get_stats = NULL;
+               /*
+                * otherwise unregister_netdev calls get_stats with
+                * invalid IO ...  :-(
+                */
+               unregister_netdev(SkGeRootDev);
+               kfree(SkGeRootDev);
+               kfree(pAC);
+               SkGeRootDev = next;
        }
 
-       FreeResources(dev);
+       /* clear proc-dir */
+       remove_proc_entry(pSkRootDir->name, proc_net);
+
+} /* skge_cleanup_module */
+
+module_init(skge_init_module);
+module_exit(skge_cleanup_module);
 
-       dev->get_stats = NULL;
-       /* 
-        * otherwise unregister_netdev calls get_stats with
-        * invalid IO ...  :-(
-        */
-       unregister_netdev(dev);
-       kfree(dev);
-       kfree(pAC);
-       boards_found--;
-} /* skge_remove_one */
 
 /*****************************************************************************
  *
@@ -789,13 +1109,14 @@ static void __devexit skge_remove_one(struct pci_dev *pdev)
  *     0, if everything is ok
  *     !=0, on error
  */
-static int __init SkGeBoardInit(struct net_device *dev, SK_AC *pAC)
+static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
 {
 short  i;
 unsigned long Flags;
 char   *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
 char   *VerStr = VER_STRING;
 int    Ret;                    /* return code of request_irq */
+SK_BOOL        DualNet;
 
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
@@ -807,7 +1128,6 @@ int        Ret;                    /* return code of request_irq */
        }
 
        /* Initialize the mutexes */
-
        for (i=0; i<SK_MAX_MACS; i++) {
                spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
                spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
@@ -818,20 +1138,20 @@ int      Ret;                    /* return code of request_irq */
        
        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
        /* Does a RESET on board ...*/
-       if (SkGeInit(pAC, pAC->IoBase, 0) != 0) {
+       if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
                printk("HWInit (0) failed.\n");
                spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
                return(-EAGAIN);
        }
-       SkI2cInit(  pAC, pAC->IoBase, 0);
-       SkEventInit(pAC, pAC->IoBase, 0);
-       SkPnmiInit( pAC, pAC->IoBase, 0);
-       SkAddrInit( pAC, pAC->IoBase, 0);
-       SkRlmtInit( pAC, pAC->IoBase, 0);
-       SkTimerInit(pAC, pAC->IoBase, 0);
+       SkI2cInit(  pAC, pAC->IoBase, SK_INIT_DATA);
+       SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
+       SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
+       SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
+       SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
+       SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
        
-       pAC->BoardLevel = 0;
-       pAC->RxBufSize = ETH_BUF_SIZE;
+       pAC->BoardLevel = SK_INIT_DATA;
+       pAC->RxBufSize  = ETH_BUF_SIZE;
 
        SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
        SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
@@ -840,25 +1160,24 @@ int      Ret;                    /* return code of request_irq */
 
        /* level 1 init common modules here (HW init) */
        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-       if (SkGeInit(pAC, pAC->IoBase, 1) != 0) {
+       if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
                printk("HWInit (1) failed.\n");
                spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
                return(-EAGAIN);
        }
-       SkI2cInit(  pAC, pAC->IoBase, 1);
-       SkEventInit(pAC, pAC->IoBase, 1);
-       SkPnmiInit( pAC, pAC->IoBase, 1);
-       SkAddrInit( pAC, pAC->IoBase, 1);
-       SkRlmtInit( pAC, pAC->IoBase, 1);
-       SkTimerInit(pAC, pAC->IoBase, 1);
+       SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
+       SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+       SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+       SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+       SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+       SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
 
        GetConfiguration(pAC);
        if (pAC->RlmtNets == 2) {
                pAC->GIni.GIPortUsage = SK_MUL_LINK;
        }
 
-
-       pAC->BoardLevel = 1;
+       pAC->BoardLevel = SK_INIT_IO;
        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
 
        if (pAC->GIni.GIMacsFound == 2) {
@@ -867,12 +1186,13 @@ int      Ret;                    /* return code of request_irq */
                Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ,
                        pAC->Name, dev);
        } else {
-               printk(KERN_WARNING "%s: illegal number of ports: %d\n",
+               printk(KERN_WARNING "%s: Invalid number of ports: %d\n",
                       dev->name, pAC->GIni.GIMacsFound);
                return -EAGAIN;
        }
+       
        if (Ret) {
-               printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
+               printk(KERN_WARNING "%s: Requested IRQ %d is busy.\n",
                       dev->name, dev->irq);
                return -EAGAIN;
        }
@@ -880,7 +1200,7 @@ int        Ret;                    /* return code of request_irq */
 
        /* Alloc memory for this board (Mem for RxD/TxD) : */
        if(!BoardAllocMem(pAC)) {
-               printk("No memory for descriptor rings\n");
+               printk("No memory for descriptor rings.\n");
                        return(-EAGAIN);
        }
 
@@ -890,8 +1210,20 @@ int       Ret;                    /* return code of request_irq */
        pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
 
        BoardInitMem(pAC);
-
-       SetQueueSizes(pAC);
+       /* tschilling: New common function with minimum size check. */
+       DualNet = SK_FALSE;
+       if (pAC->RlmtNets == 2) {
+               DualNet = SK_TRUE;
+       }
+       
+       if (SkGeInitAssignRamToQueues(
+               pAC,
+               pAC->ActivePort,
+               DualNet)) {
+               BoardFreeMem(pAC);
+               printk("SkGeInitAssignRamToQueues failed.\n");
+               return(-EAGAIN);
+       }
 
        /* Print adapter specific string from vpd */
        ProductStr(pAC);
@@ -901,14 +1233,19 @@ int      Ret;                    /* return code of request_irq */
        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==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);
 
+       /*
+        * Register the device here
+        */
+       pAC->Next = SkGeRootDev;
+       SkGeRootDev = dev;
+
        return (0);
 } /* SkGeBoardInit */
 
@@ -944,17 +1281,19 @@ unsigned long    BusAddr;
        AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
                + RX_RING_SIZE + 8;
 #endif
-       pDescrMem = pci_alloc_consistent(&pAC->PciDev, AllocLength,
+
+       pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
                                         &pAC->pDescrMemDMA);
+
        if (pDescrMem == NULL) {
                return (SK_FALSE);
        }
        pAC->pDescrMem = pDescrMem;
+       BusAddr = (unsigned long) pAC->pDescrMemDMA;
 
        /* Descriptors need 8 byte alignment, and this is ensured
         * by pci_alloc_consistent.
         */
-       BusAddr = (unsigned long) pAC->pDescrMemDMA;
        for (i=0; i<pAC->GIni.GIMacsFound; i++) {
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
                        ("TX%d/A: pDescrMem: %lX,   PhysDescrMem: %lX\n",
@@ -1002,7 +1341,8 @@ size_t            AllocLength;    /* length of complete descriptor area */
        AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
                + RX_RING_SIZE + 8;
 #endif
-       pci_free_consistent(&pAC->PciDev, AllocLength,
+
+       pci_free_consistent(pAC->PciDev, AllocLength,
                            pAC->pDescrMem, pAC->pDescrMemDMA);
        pAC->pDescrMem = NULL;
 } /* BoardFreeMem */
@@ -1089,8 +1429,7 @@ uintptr_t VNextDescr;     /* the virtual bus address of the next descriptor */
                DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
                        DESCR_ALIGN;
                DescrNum = TX_RING_SIZE / DescrSize;
-       }
-       else {
+       } else {
                DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
                        DESCR_ALIGN;
                DescrNum = RX_RING_SIZE / DescrSize;
@@ -1109,7 +1448,8 @@ uintptr_t VNextDescr;     /* the virtual bus address of the next descriptor */
                pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
                pDescr->pNextRxd = pNextDescr;
                pDescr->TcpSumStarts = pAC->CsOfs;
-               /* advance on step */
+
+               /* advance one step */
                pPrevDescr = pDescr;
                pDescr = pNextDescr;
                pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
@@ -1145,24 +1485,22 @@ int     PortIndex)      /* index of the port for which to re-init */
                ("PortReInitBmu "));
 
        /* set address of first descriptor of ring in BMU */
-       SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+
-               TX_Q_CUR_DESCR_LOW,
+       SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
                (uint32_t)(((caddr_t)
                (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
                pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
                pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
                0xFFFFFFFF));
-       SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+
-               TX_Q_DESCR_HIGH,
+       SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
                (uint32_t)(((caddr_t)
                (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
                pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
                pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
-       SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CUR_DESCR_LOW,
+       SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
                (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
                pAC->RxPort[PortIndex].pRxDescrRing +
                pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
-       SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_DESCR_HIGH,
+       SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
                (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
                pAC->RxPort[PortIndex].pRxDescrRing +
                pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
@@ -1181,10 +1519,9 @@ int      PortIndex)      /* index of the port for which to re-init */
  * Returns: N/A
  *
  */
-static irqreturn_t SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)
+static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)
 {
-struct net_device *dev = (struct net_device *)dev_id;
-
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
 DEV_NET                *pNet;
 SK_AC          *pAC;
 SK_U32         IntSrc;         /* interrupts source register contents */       
@@ -1197,135 +1534,124 @@ SK_U32                IntSrc;         /* interrupts source register contents */
         */
        SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
        if (IntSrc == 0) {
-               return IRQ_NONE;
+               return SkIsrRetNone;
        }
 
        while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
 #if 0 /* software irq currently not used */
-               if (IntSrc & IRQ_SW) {
+               if (IntSrc & IS_IRQ_SW) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("Software IRQ\n"));
                }
 #endif
-               if (IntSrc & IRQ_EOF_RX1) {
+               if (IntSrc & IS_R1_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF RX1 IRQ\n"));
-                       ReceiveIrq(pAC, &pAC->RxPort[0]);
-                       SK_PNMI_CNT_RX_INTR(pAC,0);
+                       ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+                       SK_PNMI_CNT_RX_INTR(pAC, 0);
                }
-               if (IntSrc & IRQ_EOF_RX2) {
+               if (IntSrc & IS_R2_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF RX2 IRQ\n"));
-                       ReceiveIrq(pAC, &pAC->RxPort[1]);
-                       SK_PNMI_CNT_RX_INTR(pAC,1);
+                       ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+                       SK_PNMI_CNT_RX_INTR(pAC, 1);
                }
 #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-               if (IntSrc & IRQ_EOF_AS_TX1) {
+               if (IntSrc & IS_XA1_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF AS TX1 IRQ\n"));
-                       SK_PNMI_CNT_TX_INTR(pAC,0);
+                       SK_PNMI_CNT_TX_INTR(pAC, 0);
                        spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
                        FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
                        spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
                }
-               if (IntSrc & IRQ_EOF_AS_TX2) {
+               if (IntSrc & IS_XA2_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF AS TX2 IRQ\n"));
-                       SK_PNMI_CNT_TX_INTR(pAC,1);
+                       SK_PNMI_CNT_TX_INTR(pAC, 1);
                        spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
                        FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
                        spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
                }
 #if 0 /* only if sync. queues used */
-               if (IntSrc & IRQ_EOF_SY_TX1) {
+               if (IntSrc & IS_XS1_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF SY TX1 IRQ\n"));
-                       SK_PNMI_CNT_TX_INTR(pAC,0);
+                       SK_PNMI_CNT_TX_INTR(pAC, 1);
                        spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
                        FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
                        spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
                        ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
                }
-               if (IntSrc & IRQ_EOF_SY_TX2) {
+               if (IntSrc & IS_XS2_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF SY TX2 IRQ\n"));
-                       SK_PNMI_CNT_TX_INTR(pAC,1);
+                       SK_PNMI_CNT_TX_INTR(pAC, 1);
                        spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
                        FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
                        spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
                        ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
                }
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+#endif
+#endif
 
                /* do all IO at once */
-               if (IntSrc & IRQ_EOF_RX1)
+               if (IntSrc & IS_R1_F)
                        ClearAndStartRx(pAC, 0);
-               if (IntSrc & IRQ_EOF_RX2)
+               if (IntSrc & IS_R2_F)
                        ClearAndStartRx(pAC, 1);
 #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-               if (IntSrc & IRQ_EOF_AS_TX1)
+               if (IntSrc & IS_XA1_F)
                        ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-               if (IntSrc & IRQ_EOF_AS_TX2)
+               if (IntSrc & IS_XA2_F)
                        ClearTxIrq(pAC, 1, TX_PRIO_LOW);
 #endif
                SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
        } /* while (IntSrc & IRQ_MASK != 0) */
 
+       IntSrc &= pAC->GIni.GIValIrqMask;
        if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
-                       ("SPECIAL IRQ\n"));
+                       ("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
                pAC->CheckQueue = SK_FALSE;
                spin_lock(&pAC->SlowPathLock);
                if (IntSrc & SPECIAL_IRQS)
                        SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
                SkEventDispatcher(pAC, pAC->IoBase);
                spin_unlock(&pAC->SlowPathLock);
        }
        /*
-        * do it all again is case we cleared an interrupt that 
+        * do it all again is case we cleared an interrupt that
         * came in after handling the ring (OUTs may be delayed
         * in hardware buffers, but are through after IN)
+        *
+        * rroesler: has been commented out and shifted to
+        *           SkGeDrvEvent(), because it is timer
+        *           guarded now
+        *
+       ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+       ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
         */
-       // ReceiveIrq(pAC, &pAC->RxPort[pAC->ActivePort]);
-       ReceiveIrq(pAC, &pAC->RxPort[0]);
-       ReceiveIrq(pAC, &pAC->RxPort[1]);
-       
-
-
 
-#if 0
-// #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-       spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-       FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
-       spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-
-       spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-       FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
-       spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-
-#if 0  /* only if sync. queues used */
-       spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-       FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
-       spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-       
-       spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-       FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
-       spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+       if (pAC->CheckQueue) {
+               pAC->CheckQueue = SK_FALSE;
+               spin_lock(&pAC->SlowPathLock);
+               SkEventDispatcher(pAC, pAC->IoBase);
+               spin_unlock(&pAC->SlowPathLock);
+       }
 
        /* IRQ is processed - Enable IRQs again*/
-       SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+       SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
 
-       return IRQ_HANDLED;
+               return SkIsrRetHandled;
 } /* SkGeIsr */
 
 
@@ -1342,9 +1668,9 @@ SK_U32            IntSrc;         /* interrupts source register contents */
  * Returns: N/A
  *
  */
-static irqreturn_t SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)
+static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)
 {
-struct net_device *dev = (struct net_device *)dev_id;
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
 DEV_NET                *pNet;
 SK_AC          *pAC;
 SK_U32         IntSrc;         /* interrupts source register contents */       
@@ -1357,93 +1683,86 @@ SK_U32          IntSrc;         /* interrupts source register contents */
         */
        SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
        if (IntSrc == 0) {
-               return IRQ_NONE;
+               return SkIsrRetNone;
        }
-
+       
        while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
 #if 0 /* software irq currently not used */
-               if (IntSrc & IRQ_SW) {
+               if (IntSrc & IS_IRQ_SW) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("Software IRQ\n"));
                }
 #endif
-               if (IntSrc & IRQ_EOF_RX1) {
+               if (IntSrc & IS_R1_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF RX1 IRQ\n"));
-                       ReceiveIrq(pAC, &pAC->RxPort[0]);
-                       SK_PNMI_CNT_RX_INTR(pAC,0);
+                       ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+                       SK_PNMI_CNT_RX_INTR(pAC, 0);
                }
 #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-               if (IntSrc & IRQ_EOF_AS_TX1) {
+               if (IntSrc & IS_XA1_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF AS TX1 IRQ\n"));
-                       SK_PNMI_CNT_TX_INTR(pAC,0);
+                       SK_PNMI_CNT_TX_INTR(pAC, 0);
                        spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
                        FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
                        spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
                }
 #if 0 /* only if sync. queues used */
-               if (IntSrc & IRQ_EOF_SY_TX1) {
+               if (IntSrc & IS_XS1_F) {
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_INT_SRC,
                                ("EOF SY TX1 IRQ\n"));
-                       SK_PNMI_CNT_TX_INTR(pAC,1);
+                       SK_PNMI_CNT_TX_INTR(pAC, 0);
                        spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
                        FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
                        spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
                        ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
                }
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+#endif
+#endif
 
                /* do all IO at once */
-               if (IntSrc & IRQ_EOF_RX1)
+               if (IntSrc & IS_R1_F)
                        ClearAndStartRx(pAC, 0);
 #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-               if (IntSrc & IRQ_EOF_AS_TX1)
+               if (IntSrc & IS_XA1_F)
                        ClearTxIrq(pAC, 0, TX_PRIO_LOW);
 #endif
                SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
        } /* while (IntSrc & IRQ_MASK != 0) */
        
+       IntSrc &= pAC->GIni.GIValIrqMask;
        if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
-                       ("SPECIAL IRQ\n"));
+                       ("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
                pAC->CheckQueue = SK_FALSE;
                spin_lock(&pAC->SlowPathLock);
                if (IntSrc & SPECIAL_IRQS)
                        SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
                SkEventDispatcher(pAC, pAC->IoBase);
                spin_unlock(&pAC->SlowPathLock);
        }
        /*
-        * do it all again is case we cleared an interrupt that 
+        * do it all again is case we cleared an interrupt that
         * came in after handling the ring (OUTs may be delayed
         * in hardware buffers, but are through after IN)
+        *
+        * rroesler: has been commented out and shifted to
+        *           SkGeDrvEvent(), because it is timer
+        *           guarded now
+        *
+       ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
         */
-       ReceiveIrq(pAC, &pAC->RxPort[0]);
-
-#if 0
-// #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-       spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-       FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
-       spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-
-#if 0  /* only if sync. queues used */
-       spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-       FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
-       spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-       
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
 
        /* IRQ is processed - Enable IRQs again*/
-       SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+       SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
 
-       return IRQ_HANDLED;
+               return SkIsrRetHandled;
 } /* SkGeIsrOnePort */
 
 
@@ -1464,13 +1783,13 @@ SK_U32          IntSrc;         /* interrupts source register contents */
  *     != 0 on error
  */
 static int SkGeOpen(
-struct net_device      *dev)
+struct SK_NET_DEVICE   *dev)
 {
-DEV_NET                        *pNet;
-SK_AC                  *pAC;
-unsigned long  Flags;          /* for spin lock */
-int            i;
-SK_EVPARA              EvPara;         /* an event parameter union */
+       DEV_NET                 *pNet;
+       SK_AC                   *pAC;
+       unsigned long   Flags;          /* for spin lock */
+       int                             i;
+       SK_EVPARA               EvPara;         /* an event parameter union */
 
        pNet = (DEV_NET*) dev->priv;
        pAC = pNet->pAC;
@@ -1478,53 +1797,56 @@ SK_EVPARA               EvPara;         /* an event parameter union */
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
 
-       if (pAC->BoardLevel == 0) {
+
+       /* Set blink mode */
+       if (pAC->PciDev->vendor == 0x1186)
+               pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
+
+       if (pAC->BoardLevel == SK_INIT_DATA) {
                /* level 1 init common modules here */
-               if (SkGeInit(pAC, pAC->IoBase, 1) != 0) {
-                       printk("%s: HWInit(1) failed\n", pAC->dev[pNet->PortNr]->name);
+               if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+                       printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
                        return (-1);
                }
-               SkI2cInit       (pAC, pAC->IoBase, 1);
-               SkEventInit     (pAC, pAC->IoBase, 1);
-               SkPnmiInit      (pAC, pAC->IoBase, 1);
-               SkAddrInit      (pAC, pAC->IoBase, 1);
-               SkRlmtInit      (pAC, pAC->IoBase, 1);
-               SkTimerInit     (pAC, pAC->IoBase, 1);
-               pAC->BoardLevel = 1;
-       }
-
-       if (pAC->BoardLevel != 2) {
-               /* level 2 init modules here */
-               SkGeInit        (pAC, pAC->IoBase, 2);
-               SkI2cInit       (pAC, pAC->IoBase, 2);
-               SkEventInit     (pAC, pAC->IoBase, 2);
-               SkPnmiInit      (pAC, pAC->IoBase, 2);
-               SkAddrInit      (pAC, pAC->IoBase, 2);
-               SkRlmtInit      (pAC, pAC->IoBase, 2);
-               SkTimerInit     (pAC, pAC->IoBase, 2);
-               pAC->BoardLevel = 2;
+               SkI2cInit       (pAC, pAC->IoBase, SK_INIT_IO);
+               SkEventInit     (pAC, pAC->IoBase, SK_INIT_IO);
+               SkPnmiInit      (pAC, pAC->IoBase, SK_INIT_IO);
+               SkAddrInit      (pAC, pAC->IoBase, SK_INIT_IO);
+               SkRlmtInit      (pAC, pAC->IoBase, SK_INIT_IO);
+               SkTimerInit     (pAC, pAC->IoBase, SK_INIT_IO);
+               pAC->BoardLevel = SK_INIT_IO;
        }
-       for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-               /* Enable transmit descriptor polling. */
+
+       if (pAC->BoardLevel != SK_INIT_RUN) {
+               /* tschilling: Level 2 init modules here, check return value. */
+               if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
+                       printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
+                       return (-1);
+               }
+               SkI2cInit       (pAC, pAC->IoBase, SK_INIT_RUN);
+               SkEventInit     (pAC, pAC->IoBase, SK_INIT_RUN);
+               SkPnmiInit      (pAC, pAC->IoBase, SK_INIT_RUN);
+               SkAddrInit      (pAC, pAC->IoBase, SK_INIT_RUN);
+               SkRlmtInit      (pAC, pAC->IoBase, SK_INIT_RUN);
+               SkTimerInit     (pAC, pAC->IoBase, SK_INIT_RUN);
+               pAC->BoardLevel = SK_INIT_RUN;
+       }
+
+       for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+               /* Enable transmit descriptor polling. */
                SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
                FillRxRing(pAC, &pAC->RxPort[i]);
        }
        SkGeYellowLED(pAC, pAC->IoBase, 1);
 
-#ifdef USE_INT_MOD
-/* moderate only TX complete interrupts (these are not time critical) */
-#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2)
-       {
-               unsigned long ModBase;
-               ModBase = 53125000 / INTS_PER_SEC;
-               SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
-               SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK);
-               SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
-       }
-#endif
+       StartDrvCleanupTimer(pAC);
+       SkDimEnableModerationIfNeeded(pAC);     
+       SkDimDisplayModerationSettings(pAC);
+
+       pAC->GIni.GIValIrqMask &= IRQ_MASK;
 
        /* enable Interrupts */
-       SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+       SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
        SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
 
        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
@@ -1549,6 +1871,8 @@ SK_EVPARA         EvPara;         /* an event parameter union */
        pAC->MaxPorts++;
        pNet->Up = 1;
 
+       try_module_get(THIS_MODULE);
+
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeOpen suceeded\n"));
 
@@ -1568,18 +1892,17 @@ SK_EVPARA               EvPara;         /* an event parameter union */
  *     error code - on error
  */
 static int SkGeClose(
-struct net_device      *dev)
+struct SK_NET_DEVICE   *dev)
 {
-DEV_NET                *pNet;
-SK_AC          *pAC;
+       DEV_NET                 *pNet;
+       SK_AC                   *pAC;
 
-unsigned long  Flags;          /* for spin lock */
-int                            i;
-int                            PortIdx;
-SK_EVPARA              EvPara;
+       unsigned long   Flags;          /* for spin lock */
+       int                             i;
+       int                             PortIdx;
+       SK_EVPARA               EvPara;
 
        netif_stop_queue(dev);
-
        pNet = (DEV_NET*) dev->priv;
        pAC = pNet->pAC;
 
@@ -1591,10 +1914,11 @@ SK_EVPARA               EvPara;
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
 
-       /* 
+        StopDrvCleanupTimer(pAC);
+
+       /*
         * Clear multicast table, promiscuous mode ....
         */
-        
        SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
        SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
                SK_PROM_MODE_NONE);
@@ -1610,7 +1934,7 @@ SK_EVPARA         EvPara;
                SK_OUT32(pAC->IoBase, B0_IMSK, 0);
                /* stop the hardware */
                SkGeDeInit(pAC, pAC->IoBase);
-               pAC->BoardLevel = 0;
+               pAC->BoardLevel = SK_INIT_DATA;
                spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
        } else {
 
@@ -1624,21 +1948,22 @@ SK_EVPARA               EvPara;
                /* Stop port */
                spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
                        [TX_PRIO_LOW].TxDesRingLock, Flags);
-               SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, 
+               SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
                        SK_STOP_ALL, SK_HARD_RST);
                spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
                        [TX_PRIO_LOW].TxDesRingLock, Flags);
        }
+
        if (pAC->RlmtNets == 1) {
                /* clear all descriptor rings */
                for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-                       ReceiveIrq(pAC, &pAC->RxPort[i]);
+                       ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
                        ClearRxRing(pAC, &pAC->RxPort[i]);
                        ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
                }
        } else {
                /* clear port descriptor rings */
-               ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr]);
+               ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
                ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
                ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
        }
@@ -1648,10 +1973,12 @@ SK_EVPARA               EvPara;
 
        pAC->MaxPorts--;
        pNet->Up = 0;
-       
+
+       module_put(THIS_MODULE);
        return (0);
 } /* SkGeClose */
 
+
 /*****************************************************************************
  *
  *     SkGeXmit - Linux frame transmit function
@@ -1667,23 +1994,47 @@ SK_EVPARA               EvPara;
  * WARNING: returning 1 in 'tbusy' case caused system crashes (double
  *     allocated skb's) !!!
  */
-static int SkGeXmit(struct sk_buff *skb, struct net_device *dev)
+static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
 {
 DEV_NET                *pNet;
 SK_AC          *pAC;
 int                    Rc;     /* return code of XmitFrame */
-       
+
        pNet = (DEV_NET*) dev->priv;
        pAC = pNet->pAC;
 
-       if (pAC->RlmtNets == 2)
-               Rc = XmitFrame(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], skb);
-       else
-               Rc = XmitFrame(pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb);
+       if ((!skb_shinfo(skb)->nr_frags) ||
+               (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
+               /* Don't activate scatter-gather and hardware checksum */
+
+               if (pAC->RlmtNets == 2)
+                       Rc = XmitFrame(
+                               pAC,
+                               &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+                               skb);
+               else
+                       Rc = XmitFrame(
+                               pAC,
+                               &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+                               skb);
+       } else {
+               /* scatter-gather and hardware TCP checksumming anabled*/
+               if (pAC->RlmtNets == 2)
+                       Rc = XmitFrameSG(
+                               pAC,
+                               &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+                               skb);
+               else
+                       Rc = XmitFrameSG(
+                               pAC,
+                               &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+                               skb);
+       }
 
        /* Transmitter out of resources? */
-       if (Rc <= 0)
+       if (Rc <= 0) {
                netif_stop_queue(dev);
+       }
 
        /* If not taken, give buffer ownership back to the
         * queueing layer.
@@ -1713,28 +2064,35 @@ int                     Rc;     /* return code of XmitFrame */
  *     if necessary.
  *
  * Returns:
- *  > 0 - on succes: the number of bytes in the message
- *  = 0 - on resource shortage: this frame sent or dropped, now
- *        the ring is full ( -> set tbusy)
- *  < 0 - on failure: other problems ( -> return failure to upper layers)
+ *     > 0 - on succes: the number of bytes in the message
+ *     = 0 - on resource shortage: this frame sent or dropped, now
+ *             the ring is full ( -> set tbusy)
+ *     < 0 - on failure: other problems ( -> return failure to upper layers)
  */
 static int XmitFrame(
-SK_AC          *pAC,           /* pointer to adapter context */
+SK_AC          *pAC,           /* pointer to adapter context           */
 TX_PORT                *pTxPort,       /* pointer to struct of port to send to */
-struct sk_buff *pMessage)      /* pointer to send-message */
+struct sk_buff *pMessage)      /* pointer to send-message              */
 {
-TXD            *pTxd;          /* the rxd to fill */
-unsigned long  Flags;
-SK_U64         PhysAddr;
-int            BytesSend;
+       TXD             *pTxd;          /* the rxd to fill */
+       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"));
+       SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
 
        spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-
+#ifndef USE_TX_COMPLETE
+       FreeTxDescriptors(pAC, pTxPort);
+#endif
        if (pTxPort->TxdRingFree == 0) {
-               /* no enough free descriptors in ring at the moment */
+               /* 
+               ** no enough free descriptors in ring at the moment.
+               ** Maybe free'ing some old one help?
+               */
                FreeTxDescriptors(pAC, pTxPort);
                if (pTxPort->TxdRingFree == 0) {
                        spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
@@ -1742,63 +2100,279 @@ int            BytesSend;
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_TX_PROGRESS,
                                ("XmitFrame failed\n"));
-                       /* this message can not be sent now */
+                       /* 
+                       ** the desired message can not be sent
+                       ** Because tbusy seems to be set, the message 
+                       ** should not be freed here. It will be used 
+                       ** by the scheduler of the ethernet handler 
+                       */
                        return (-1);
                }
        }
-       /* advance head counter behind descriptor needed for this frame */
+
+       /*
+       ** If the passed socket buffer is of smaller MTU-size than 60,
+       ** copy everything into new buffer and fill all bytes between
+       ** the original packet end and the new packet end of 60 with 0x00.
+       ** This is to resolve faulty padding by the HW with 0xaa bytes.
+       */
+       if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
+           skb_put(pMessage, (C_LEN_ETHERNET_MINSIZE-BytesSend));
+           memset( ((void *)(pMessage->data))+BytesSend,
+                   0, C_LEN_ETHERNET_MINSIZE-BytesSend);
+       }
+
+       /* 
+       ** advance head counter behind descriptor needed for this frame, 
+       ** so that needed descriptor is reserved from that on. The next
+       ** action will be to add the passed buffer to the TX-descriptor
+       */
        pTxd = pTxPort->pTxdRingHead;
        pTxPort->pTxdRingHead = pTxd->pNextTxd;
        pTxPort->TxdRingFree--;
-       /* the needed descriptor is reserved now */
-       
-       /* 
-        * everything allocated ok, so add buffer to descriptor
-        */
 
 #ifdef SK_DUMP_TX
        DumpMsg(pMessage, "XmitFrame");
 #endif
 
-       /* set up descriptor and CONTROL dword */
-       PhysAddr = (SK_U64) pci_map_page(&pAC->PciDev,
-                                        virt_to_page(pMessage->data),
-                                        ((unsigned long) pMessage->data &
-                                         ~PAGE_MASK),
-                                        pMessage->len,
-                                        PCI_DMA_TODEVICE);
-       pTxd->VDataLow = (SK_U32)  (PhysAddr & 0xffffffff);
+       /* 
+       ** First step is to map the data to be sent via the adapter onto
+       ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
+       ** and 2.6 need to use pci_map_page() for that mapping.
+       */
+       PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+                                       virt_to_page(pMessage->data),
+                                       ((unsigned long) pMessage->data & ~PAGE_MASK),
+                                       pMessage->len,
+                                       PCI_DMA_TODEVICE);
+       pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
        pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-       pTxd->pMBuf = pMessage;
-       pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF |
-               TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE |
+       pTxd->pMBuf     = pMessage;
+
+       if (pMessage->ip_summed == CHECKSUM_HW) {
+               Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xf);
+               if ((Protocol == C_PROTO_ID_TCP) && (pAC->GIni.GIChipRev != 0)) {
+                       pTxd->TBControl = BMU_UDP_CHECK;
+               } else {
+                       pTxd->TBControl = BMU_TCP_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 + 
+                                       C_OFFSET_TCPHEADER_TCPCS;
+               pTxd->TcpSumWr  = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
+
+               pTxd->TBControl |= BMU_OWN | BMU_STF | 
+                                  BMU_SW  | BMU_EOF |
 #ifdef USE_TX_COMPLETE
-               TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len;
-#else
-               TX_CTRL_EOF | pMessage->len;
+                                  BMU_IRQ_EOF |
 #endif
-       
-       if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) {
-               /* previous descriptor already done, so give tx start cmd */
-               /* StartTx(pAC, pTxPort->HwAddr); */
-               SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START);
+                                  pMessage->len;
+        } else {
+               pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | 
+                                 BMU_SW  | BMU_EOF |
+#ifdef USE_TX_COMPLETE
+                                  BMU_IRQ_EOF |
+#endif
+                                  pMessage->len;
        }
-       pTxPort->pTxdRingPrev = pTxd;
-       
-       
-       BytesSend = pMessage->len;
-       /* after releasing the lock, the skb may be immidiately freed */
+
+       /* 
+       ** If previous descriptor already done, give TX start cmd 
+       */
+       pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
+       if ((pOldTxd->TBControl & BMU_OWN) == 0) {
+               SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+       }       
+
+       /* 
+       ** after releasing the lock, the skb may immediately be free'd 
+       */
+       spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
        if (pTxPort->TxdRingFree != 0) {
-               spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
                return (BytesSend);
-       }
-       else {
-               /* ring full: set tbusy on return */
-               spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+       } else {
                return (0);
        }
+
 } /* XmitFrame */
 
+/*****************************************************************************
+ *
+ *     XmitFrameSG - fill one socket buffer into the transmit ring
+ *                (use SG and TCP/UDP hardware checksumming)
+ *
+ * Description:
+ *     This function puts a message into the transmit descriptor ring
+ *     if there is a descriptors left.
+ *
+ * Returns:
+ *     > 0 - on succes: the number of bytes in the message
+ *     = 0 - on resource shortage: this frame sent or dropped, now
+ *             the ring is full ( -> set tbusy)
+ *     < 0 - on failure: other problems ( -> return failure to upper layers)
+ */
+static int XmitFrameSG(
+SK_AC          *pAC,           /* pointer to adapter context           */
+TX_PORT                *pTxPort,       /* pointer to struct of port to send to */
+struct sk_buff *pMessage)      /* pointer to send-message              */
+{
+
+       TXD             *pTxd;
+       TXD             *pTxdFst;
+       TXD             *pTxdLst;
+       int              CurrFrag;
+       int              BytesSend;
+       int              IpHeaderLength; 
+       int              Protocol;
+       skb_frag_t      *sk_frag;
+       SK_U64           PhysAddr;
+       unsigned long    Flags;
+
+       spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+#ifndef USE_TX_COMPLETE
+       FreeTxDescriptors(pAC, pTxPort);
+#endif
+       if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
+               FreeTxDescriptors(pAC, pTxPort);
+               if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
+                       spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+                       SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+                       SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+                               SK_DBGCAT_DRV_TX_PROGRESS,
+                               ("XmitFrameSG failed - Ring full\n"));
+                               /* this message can not be sent now */
+                       return(-1);
+               }
+       }
+
+       pTxd      = pTxPort->pTxdRingHead;
+       pTxdFst   = pTxd;
+       pTxdLst   = pTxd;
+       BytesSend = 0;
+       Protocol  = 0;
+
+       /* 
+       ** Map the first fragment (header) into the DMA-space
+       */
+       PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+                       virt_to_page(pMessage->data),
+                       ((unsigned long) pMessage->data & ~PAGE_MASK),
+                       skb_headlen(pMessage),
+                       PCI_DMA_TODEVICE);
+
+       pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+       pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+
+       /* 
+       ** 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);
+               /* 
+               ** 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] & 0xf);
+               if ((Protocol == C_PROTO_ID_TCP) && (pAC->GIni.GIChipRev != 0)) {
+                       pTxd->TBControl |= BMU_UDP_CHECK;
+               } else {
+                       pTxd->TBControl |= BMU_TCP_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 +
+                                       C_OFFSET_TCPHEADER_TCPCS;
+               pTxd->TcpSumWr  = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
+       } else {
+               pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF |
+                                       skb_headlen(pMessage);
+       }
+
+       pTxd = pTxd->pNextTxd;
+       pTxPort->TxdRingFree--;
+       BytesSend += skb_headlen(pMessage);
+
+       /* 
+       ** Browse over all SG fragments and map each of them into the DMA space
+       */
+       for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
+               sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
+               /* 
+               ** we already have the proper value in entry
+               */
+               PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+                                                sk_frag->page,
+                                                sk_frag->page_offset,
+                                                sk_frag->size,
+                                                PCI_DMA_TODEVICE);
+
+               pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+               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_TCP) && 
+                            (pAC->GIni.GIChipRev != 0) ) {
+                               pTxd->TBControl |= BMU_UDP_CHECK ;
+                       } else {
+                               pTxd->TBControl |= BMU_TCP_CHECK ;
+                       }
+               } else {
+                       pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN;
+               }
+
+               /* 
+               ** 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;
+#else
+                       pTxd->TBControl |= BMU_EOF | sk_frag->size;
+#endif
+                       pTxdFst->TBControl |= BMU_OWN | BMU_SW;
+
+               } else {
+                       pTxd->TBControl |= sk_frag->size;
+               }
+               pTxdLst = pTxd;
+               pTxd    = pTxd->pNextTxd;
+               pTxPort->TxdRingFree--;
+               BytesSend += sk_frag->size;
+       }
+
+       /* 
+       ** If previous descriptor already done, give TX start cmd 
+       */
+       if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
+               SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+       }
+
+       pTxPort->pTxdRingPrev = pTxdLst;
+       pTxPort->pTxdRingHead = pTxd;
+
+       spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+
+       if (pTxPort->TxdRingFree > 0) {
+               return (BytesSend);
+       } else {
+               return (0);
+       }
+}
 
 /*****************************************************************************
  *
@@ -1828,49 +2402,52 @@ SK_U32  Control;        /* TBControl field of descriptor */
 SK_U64 PhysAddr;       /* address of DMA mapping */
 
        pNewTail = pTxPort->pTxdRingTail;
-       pTxd = pNewTail;
-       
-       /* 
-        * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame
-        * or TX_CTRL_OWN_BMU bit set in any frame
-        */
+       pTxd     = pNewTail;
+       /*
+       ** loop forever; exits if BMU_SW bit not set in start frame
+       ** or BMU_OWN bit set in any frame
+       */
        while (1) {
                Control = pTxd->TBControl;
-               if ((Control & TX_CTRL_SOFTWARE) == 0) {
-                       /* 
-                        * software controllable bit is set in first
-                        * fragment when given to BMU. Not set means that
-                        * this fragment was never sent or is already 
-                        * freed ( -> ring completely free now).
-                        */
+               if ((Control & BMU_SW) == 0) {
+                       /*
+                       ** software controllable bit is set in first
+                       ** fragment when given to BMU. Not set means that
+                       ** this fragment was never sent or is already
+                       ** freed ( -> ring completely free now).
+                       */
                        pTxPort->pTxdRingTail = pTxd;
-                       netif_start_queue(pAC->dev[pTxPort->PortIndex]);
+                       netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
                        return;
                }
-               if (Control & TX_CTRL_OWN_BMU) {
+               if (Control & BMU_OWN) {
                        pTxPort->pTxdRingTail = pTxd;
                        if (pTxPort->TxdRingFree > 0) {
-                               netif_start_queue(pAC->dev[pTxPort->PortIndex]);
+                               netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
                        }
                        return;
                }
                
-               /* release the DMA mapping */
+               /* 
+               ** release the DMA mapping, because until not unmapped
+               ** this buffer is considered being under control of the
+               ** adapter card!
+               */
                PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
                PhysAddr |= (SK_U64) pTxd->VDataLow;
-               pci_unmap_page(&pAC->PciDev, PhysAddr,
-                              pTxd->pMBuf->len,
-                              PCI_DMA_TODEVICE);
+               pci_unmap_page(pAC->PciDev, PhysAddr,
+                                pTxd->pMBuf->len,
+                                PCI_DMA_TODEVICE);
+
+               if (Control & BMU_EOF)
+                       DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */
 
-               /* free message */
-               DEV_KFREE_SKB_ANY(pTxd->pMBuf);
                pTxPort->TxdRingFree++;
-               pTxd->TBControl &= ~TX_CTRL_SOFTWARE;
+               pTxd->TBControl &= ~BMU_SW;
                pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
        } /* while(forever) */
 } /* FreeTxDescriptors */
 
-
 /*****************************************************************************
  *
  *     FillRxRing - fill the receive ring with valid descriptors
@@ -1939,17 +2516,21 @@ SK_U64          PhysAddr;       /* physical address of a rx buffer */
        pRxPort->pRxdRingTail = pRxd->pNextRxd;
        pRxPort->RxdRingFree--;
        Length = pAC->RxBufSize;
-       PhysAddr = (SK_U64) pci_map_page(&pAC->PciDev,
-                                        virt_to_page(pMsgBlock->data),
-                                        ((unsigned long) pMsgBlock->data &
-                                         ~PAGE_MASK),
-                                        pAC->RxBufSize - 2,
-                                        PCI_DMA_FROMDEVICE);
-       pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+       PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+               virt_to_page(pMsgBlock->data),
+               ((unsigned long) pMsgBlock->data &
+               ~PAGE_MASK),
+               pAC->RxBufSize - 2,
+               PCI_DMA_FROMDEVICE);
+
+       pRxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
        pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-       pRxd->pMBuf = pMsgBlock;
-       pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF |
-               RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length;
+       pRxd->pMBuf     = pMsgBlock;
+       pRxd->RBControl = BMU_OWN       | 
+                         BMU_STF       | 
+                         BMU_IRQ_EOF   | 
+                         BMU_TCP_CHECK | 
+                         Length;
        return (SK_TRUE);
 
 } /* FillRxDescriptor */
@@ -1980,15 +2561,18 @@ SK_U16          Length;         /* data fragment length */
        pRxPort->pRxdRingTail = pRxd->pNextRxd;
        pRxPort->RxdRingFree--;
        Length = pAC->RxBufSize;
-       pRxd->VDataLow = PhysLow;
+
+       pRxd->VDataLow  = PhysLow;
        pRxd->VDataHigh = PhysHigh;
-       pRxd->pMBuf = pMsg;
-       pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF |
-               RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length;
+       pRxd->pMBuf     = pMsg;
+       pRxd->RBControl = BMU_OWN       | 
+                         BMU_STF       |
+                         BMU_IRQ_EOF   | 
+                         BMU_TCP_CHECK | 
+                         Length;
        return;
 } /* ReQueueRxBuffer */
 
-
 /*****************************************************************************
  *
  *     ReceiveIrq - handle a receive IRQ
@@ -2001,31 +2585,36 @@ SK_U16          Length;         /* data fragment length */
  * Returns:    N/A
  */
 static void ReceiveIrq(
-SK_AC          *pAC,           /* pointer to adapter context */
-RX_PORT                *pRxPort)       /* pointer to receive port struct */
+       SK_AC           *pAC,                   /* pointer to adapter context */
+       RX_PORT         *pRxPort,               /* pointer to receive port struct */
+       SK_BOOL         SlowPathLock)   /* indicates if SlowPathLock is needed */
 {
-RXD            *pRxd;          /* pointer to receive descriptors */
-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 */
-SK_MBUF                *pRlmtMbuf;     /* ptr to a buffer for giving a frame to rlmt */
-SK_EVPARA      EvPara;         /* an event parameter union */  
-int            PortIndex = pRxPort->PortIndex;
+RXD                            *pRxd;                  /* pointer to receive descriptors */
+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 */
+int                            PortIndex = pRxPort->PortIndex;
 unsigned int   Offset;
 unsigned int   NumBytes;
 unsigned int   ForRlmt;
-SK_BOOL                IsBc;
-SK_BOOL                IsMc;
-SK_U32         FrameStat;
+SK_BOOL                        IsBc;
+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;
+int                            Result;
+SK_U64                 PhysAddr;
 
 rx_start:      
-       /* do forever; exit if RX_CTRL_OWN_BMU found */
+       /* do forever; exit if BMU_OWN found */
        for ( pRxd = pRxPort->pRxdRingHead ;
                  pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
                  pRxd = pRxd->pNextRxd,
@@ -2033,8 +2622,8 @@ rx_start:
                  pRxPort->RxdRingFree ++) {
 
                /*
-                * For a better understanding of this loop 
-                * Go through every descriptor beginning at the head 
+                * For a better understanding of this loop
+                * Go through every descriptor beginning at the head
                 * Please note: the ring might be completely received so the OWN bit
                 * set is not a good crirteria to leave that loop.
                 * Therefore the RingFree counter is used.
@@ -2045,52 +2634,93 @@ rx_start:
                Control = pRxd->RBControl;
        
                /* check if this descriptor is ready */
-               if ((Control & RX_CTRL_OWN_BMU) != 0) {
+               if ((Control & BMU_OWN) != 0) {
                        /* this descriptor is not yet ready */
                        /* This is the usual end of the loop */
                        /* We don't need to start the ring again */
                        FillRxRing(pAC, pRxPort);
                        return;
                }
+                pAC->DynIrqModInfo.NbrProcessedDescr++;
 
                /* get length of frame and check it */
-               FrameLength = Control & RX_CTRL_LEN_MASK;
+               FrameLength = Control & BMU_BBC;
                if (FrameLength > pAC->RxBufSize) {
                        goto rx_failed;
                }
 
                /* check for STF and EOF */
-               if ((Control & (RX_CTRL_STF | RX_CTRL_EOF)) !=
-                       (RX_CTRL_STF | RX_CTRL_EOF)) {
+               if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
                        goto rx_failed;
                }
-               
+
                /* here we have a complete frame in the ring */
                pMsg = pRxd->pMBuf;
 
                FrameStat = pRxd->FrameStat;
+
+               /* check for frame length mismatch */
+#define XMR_FS_LEN_SHIFT        18
+#define GMR_FS_LEN_SHIFT        16
+               if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+                       if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
+                               SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+                                       SK_DBGCAT_DRV_RX_PROGRESS,
+                                       ("skge: Frame length mismatch (%u/%u).\n",
+                                       FrameLength,
+                                       (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+                               goto rx_failed;
+                       }
+               }
+               else {
+                       if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
+                               SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+                                       SK_DBGCAT_DRV_RX_PROGRESS,
+                                       ("skge: Frame length mismatch (%u/%u).\n",
+                                       FrameLength,
+                                       (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+                               goto rx_failed;
+                       }
+               }
+
+               /* Set Rx Status */
+               if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+                       IsBc = (FrameStat & XMR_FS_BC) != 0;
+                       IsMc = (FrameStat & XMR_FS_MC) != 0;
+                       IsBadFrame = (FrameStat &
+                               (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
+               } else {
+                       IsBc = (FrameStat & GMR_FS_BC) != 0;
+                       IsMc = (FrameStat & GMR_FS_MC) != 0;
+                       IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
+                                                       ((FrameStat & GMR_FS_RX_OK) == 0));
+               }
+
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
                        ("Received frame of length %d on port %d\n",
                        FrameLength, PortIndex));
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
                        ("Number of free rx descriptors: %d\n",
                        pRxPort->RxdRingFree));
-               /*DumpMsg(pMsg, "Rx");  */      
-               
-               if ((Control & RX_CTRL_STAT_VALID) != RX_CTRL_STAT_VALID ||
+/* DumpMsg(pMsg, "Rx");        */
+
+               if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
+#if 0
                        (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
+#endif
                        /* there is a receive error in this frame */
                        SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_RX_PROGRESS,
                                ("skge: Error in received frame, dropped!\n"
                                "Control: %x\nRxStat: %x\n",
                                Control, FrameStat));
+
                        PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
                        PhysAddr |= (SK_U64) pRxd->VDataLow;
-                       pci_dma_sync_single(&pAC->PciDev,
-                                           (dma_addr_t) PhysAddr,
-                                           FrameLength,
-                                           PCI_DMA_FROMDEVICE);
+                       pci_dma_sync_single(pAC->PciDev,
+                                               (dma_addr_t) PhysAddr,
+                                               FrameLength,
+                                               PCI_DMA_FROMDEVICE);
                        ReQueueRxBuffer(pAC, pRxPort, pMsg,
                                pRxd->VDataHigh, pRxd->VDataLow);
 
@@ -2105,20 +2735,21 @@ rx_start:
                        /*
                         * Short frame detected and allocation successfull
                         */
-                       PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-                       PhysAddr |= (SK_U64) pRxd->VDataLow;
-
                        /* use new skb and copy data */
                        skb_reserve(pNewMsg, 2);
                        skb_put(pNewMsg, FrameLength);
-                       pci_dma_sync_single(&pAC->PciDev,
-                                           (dma_addr_t) PhysAddr,
-                                           FrameLength,
-                                           PCI_DMA_FROMDEVICE);
+                       PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+                       PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+                       pci_dma_sync_single(pAC->PciDev,
+                                               (dma_addr_t) PhysAddr,
+                                               FrameLength,
+                                               PCI_DMA_FROMDEVICE);
                        eth_copy_and_sum(pNewMsg, pMsg->data,
                                FrameLength, 0);
                        ReQueueRxBuffer(pAC, pRxPort, pMsg,
                                pRxd->VDataHigh, pRxd->VDataLow);
+
                        pMsg = pNewMsg;
 
                }
@@ -2132,45 +2763,88 @@ rx_start:
                        PhysAddr |= (SK_U64) pRxd->VDataLow;
 
                        /* release the DMA mapping */
-                       pci_unmap_page(&pAC->PciDev,
-                                      PhysAddr,
-                                      pAC->RxBufSize - 2,
-                                      PCI_DMA_FROMDEVICE);
+                       pci_unmap_single(pAC->PciDev,
+                                        PhysAddr,
+                                        pAC->RxBufSize - 2,
+                                        PCI_DMA_FROMDEVICE);
 
                        /* set length in message */
                        skb_put(pMsg, FrameLength);
                        /* hardware checksum */
                        Type = ntohs(*((short*)&pMsg->data[12]));
+
+#ifdef USE_SK_RX_CHECKSUM
                        if (Type == 0x800) {
                                Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
                                Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
-                               if ((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) {
-                                       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;
-                                       }
-                               } /* checksum calculation valid */
+                               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->GIni.GIChipId == CHIP_ID_YUKON)) {
+                                               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 */
+#else
+                       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
                IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
+#endif
                SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
                        IsBc, &Offset, &NumBytes);
                if (NumBytes != 0) {
+#if 0
                        IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
-                       SK_RLMT_LOOKAHEAD(pAC, PortIndex, 
+#endif
+                       SK_RLMT_LOOKAHEAD(pAC, PortIndex,
                                &pMsg->data[Offset],
                                IsBc, IsMc, &ForRlmt);
                }
@@ -2195,7 +2869,7 @@ rx_start:
                        }
                        else {
                                /* drop frame */
-                               SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 
+                               SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                        SK_DBGCAT_DRV_RX_PROGRESS,
                                        ("D"));
                                DEV_KFREE_SKB(pMsg);
@@ -2204,7 +2878,7 @@ rx_start:
                } /* if not for rlmt */
                else {
                        /* packet for rlmt */
-                       SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 
+                       SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
                        pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
                                pAC->IoBase, FrameLength);
@@ -2216,18 +2890,30 @@ rx_start:
                                memcpy((char*)(pRlmtMbuf->pData),
                                           (char*)(pMsg->data),
                                           FrameLength);
-                               SkEventQueue(pAC, SKGE_RLMT,
-                                       SK_RLMT_PACKET_RECEIVED,
-                                       EvPara);
-                               pAC->CheckQueue = SK_TRUE;
-                               SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 
+
+                               /* SlowPathLock needed? */
+                               if (SlowPathLock == SK_TRUE) {
+                                       spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+                                       SkEventQueue(pAC, SKGE_RLMT,
+                                               SK_RLMT_PACKET_RECEIVED,
+                                               EvPara);
+                                       pAC->CheckQueue = SK_TRUE;
+                                       spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+                               } else {
+                                       SkEventQueue(pAC, SKGE_RLMT,
+                                               SK_RLMT_PACKET_RECEIVED,
+                                               EvPara);
+                                       pAC->CheckQueue = SK_TRUE;
+                               }
+
+                               SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
                                        SK_DBGCAT_DRV_RX_PROGRESS,
                                        ("Q"));
                        }
-                       if ((pAC->dev[pRxPort->PortIndex]->flags & 
+                       if ((pAC->dev[pRxPort->PortIndex]->flags &
                                (IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
-                               (ForRlmt & SK_RLMT_RX_PROTOCOL) == 
-                               SK_RLMT_RX_PROTOCOL) { 
+                               (ForRlmt & SK_RLMT_RX_PROTOCOL) ==
+                               SK_RLMT_RX_PROTOCOL) {
                                pMsg->dev = pAC->dev[pRxPort->PortIndex];
                                pMsg->protocol = eth_type_trans(pMsg,
                                        pAC->dev[pRxPort->PortIndex]);
@@ -2244,7 +2930,7 @@ rx_start:
        /* RXD ring is empty -> fill and restart */
        FillRxRing(pAC, pRxPort);
        /* do not start if called from Close */
-       if (pAC->BoardLevel > 0) {
+       if (pAC->BoardLevel > SK_INIT_DATA) {
                ClearAndStartRx(pAC, PortIndex);
        }
        return;
@@ -2255,12 +2941,13 @@ rx_failed:
                ("Schrottdescriptor, length: 0x%x\n", FrameLength));
 
        /* release the DMA mapping */
+
        PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
        PhysAddr |= (SK_U64) pRxd->VDataLow;
-       pci_unmap_page(&pAC->PciDev,
-                      PhysAddr,
-                      pAC->RxBufSize - 2,
-                      PCI_DMA_FROMDEVICE);
+       pci_unmap_page(pAC->PciDev,
+                        PhysAddr,
+                        pAC->RxBufSize - 2,
+                        PCI_DMA_FROMDEVICE);
        DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
        pRxd->pMBuf = NULL;
        pRxPort->RxdRingFree++;
@@ -2285,8 +2972,9 @@ static void ClearAndStartRx(
 SK_AC  *pAC,           /* pointer to the adapter context */
 int    PortIndex)      /* index of the receive port (XMAC) */
 {
-       SK_OUT8(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CTRL,
-               RX_Q_CTRL_START | RX_Q_CTRL_CLR_I_EOF);
+       SK_OUT8(pAC->IoBase,
+               RxQueueAddr[PortIndex]+Q_CSR,
+               CSR_START | CSR_IRQ_CL_F);
 } /* ClearAndStartRx */
 
 
@@ -2305,8 +2993,9 @@ SK_AC     *pAC,           /* pointer to the adapter context */
 int    PortIndex,      /* index of the transmit port (XMAC) */
 int    Prio)           /* priority or normal queue */
 {
-       SK_OUT8(pAC->IoBase, TxQueueAddr[PortIndex][Prio]+TX_Q_CTRL,
-               TX_Q_CTRL_CLR_I_EOF);
+       SK_OUT8(pAC->IoBase, 
+               TxQueueAddr[PortIndex][Prio]+Q_CSR,
+               CSR_IRQ_CL_F);
 } /* ClearTxIrq */
 
 
@@ -2326,7 +3015,7 @@ RX_PORT   *pRxPort)       /* pointer to rx port struct */
 {
 RXD            *pRxd;  /* pointer to the current descriptor */
 unsigned long  Flags;
- SK_U64                PhysAddr;
+SK_U64         PhysAddr;
 
        if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
                return;
@@ -2335,16 +3024,17 @@ unsigned long   Flags;
        pRxd = pRxPort->pRxdRingHead;
        do {
                if (pRxd->pMBuf != NULL) {
+
                        PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
                        PhysAddr |= (SK_U64) pRxd->VDataLow;
-                       pci_unmap_page(&pAC->PciDev,
-                                      PhysAddr,
-                                      pAC->RxBufSize - 2,
-                                      PCI_DMA_FROMDEVICE);
+                       pci_unmap_page(pAC->PciDev,
+                                        PhysAddr,
+                                        pAC->RxBufSize - 2,
+                                        PCI_DMA_FROMDEVICE);
                        DEV_KFREE_SKB(pRxd->pMBuf);
                        pRxd->pMBuf = NULL;
                }
-               pRxd->RBControl &= RX_CTRL_OWN_BMU;
+               pRxd->RBControl &= BMU_OWN;
                pRxd = pRxd->pNextRxd;
                pRxPort->RxdRingFree++;
        } while (pRxd != pRxPort->pRxdRingTail);
@@ -2352,7 +3042,6 @@ unsigned long     Flags;
        spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
 } /* ClearRxRing */
 
-
 /*****************************************************************************
  *
  *     ClearTxRing - remove all buffers from the transmit ring
@@ -2377,107 +3066,13 @@ unsigned long  Flags;
        spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
        pTxd = pTxPort->pTxdRingHead;
        for (i=0; i<pAC->TxDescrPerRing; i++) {
-               pTxd->TBControl &= ~TX_CTRL_OWN_BMU;
+               pTxd->TBControl &= ~BMU_OWN;
                pTxd = pTxd->pNextTxd;
        }
        FreeTxDescriptors(pAC, pTxPort);
        spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
 } /* ClearTxRing */
 
-
-/*****************************************************************************
- *
- *     SetQueueSizes - configure the sizes of rx and tx queues
- *
- * Description:
- *     This function assigns the sizes for active and passive port
- *     to the appropriate HWinit structure variables.
- *     The passive port(s) get standard values, all remaining RAM
- *     is given to the active port.
- *     The queue sizes are in kbyte and must be multiple of 8.
- *     The limits for the number of buffers filled into the rx rings
- *     is also set in this routine.
- *
- * Returns:
- *     none
- */
-static void SetQueueSizes(
-SK_AC  *pAC)   /* pointer to the adapter context */
-{
-int    StandbyRam;     /* adapter RAM used for a standby port */
-int    RemainingRam;   /* adapter RAM available for the active port */
-int    RxRam;          /* RAM used for the active port receive queue */
-int    i;              /* loop counter */
-
-if (pAC->RlmtNets == 1) {
-       StandbyRam = SK_RLMT_STANDBY_QRXSIZE + SK_RLMT_STANDBY_QXASIZE +
-               SK_RLMT_STANDBY_QXSSIZE;
-       RemainingRam = pAC->GIni.GIRamSize - 
-               (pAC->GIni.GIMacsFound-1) * StandbyRam;
-       for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-               pAC->GIni.GP[i].PRxQSize = SK_RLMT_STANDBY_QRXSIZE;
-               pAC->GIni.GP[i].PXSQSize = SK_RLMT_STANDBY_QXSSIZE;
-               pAC->GIni.GP[i].PXAQSize = SK_RLMT_STANDBY_QXASIZE;
-       }
-       RxRam = (RemainingRam * 8 / 10) & ~7;
-       pAC->GIni.GP[pAC->ActivePort].PRxQSize = RxRam;
-       pAC->GIni.GP[pAC->ActivePort].PXSQSize = 0;
-       pAC->GIni.GP[pAC->ActivePort].PXAQSize =
-               (RemainingRam - RxRam) & ~7;
-       pAC->RxQueueSize = RxRam;
-       pAC->TxSQueueSize = 0;
-       pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7;
-       SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-               ("queue sizes settings - rx:%d  txA:%d txS:%d\n",
-               pAC->RxQueueSize,pAC->TxAQueueSize, pAC->TxSQueueSize));
-} else {
-       RemainingRam = pAC->GIni.GIRamSize/pAC->GIni.GIMacsFound;
-       RxRam = (RemainingRam * 8 / 10) & ~7;
-       for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-               pAC->GIni.GP[i].PRxQSize = RxRam;
-               pAC->GIni.GP[i].PXSQSize = 0;
-               pAC->GIni.GP[i].PXAQSize = (RemainingRam - RxRam) & ~7;
-       }
-       
-       pAC->RxQueueSize = RxRam;
-       pAC->TxSQueueSize = 0;
-       pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7;
-}
-       for (i=0; i<SK_MAX_MACS; i++) {
-               pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing;
-       }
-
-       if (pAC->RlmtNets == 2) {
-               for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-                       pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100;
-               }
-       } else {
-               for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-                       pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100;
-               }
-               /*
-                * Do not set the Limit to 0, because this could cause
-                * wrap around with ReQueue'ed buffers (a buffer could
-                * be requeued in the same position, made accessible to
-                * the hardware, and the hardware could change its
-                * contents!
-                */
-               pAC->RxPort[pAC->ActivePort].RxFillLimit = 1;
-       }
-
-#ifdef DEBUG
-       for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-               SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-                       ("i: %d,  RxQSize: %d,  PXSQsize: %d, PXAQSize: %d\n",
-                       i,
-                       pAC->GIni.GP[i].PRxQSize,
-                       pAC->GIni.GP[i].PXSQSize,
-                       pAC->GIni.GP[i].PXAQSize));
-       }
-#endif
-} /* SetQueueSizes */
-
-
 /*****************************************************************************
  *
  *     SkGeSetMacAddr - Set the hardware MAC address
@@ -2489,7 +3084,7 @@ if (pAC->RlmtNets == 1) {
  *     0, if everything is ok
  *     !=0, on error
  */
-static int SkGeSetMacAddr(struct net_device *dev, void *p)
+static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
 {
 
 DEV_NET *pNet = (DEV_NET*) dev->priv;
@@ -2497,12 +3092,12 @@ SK_AC   *pAC = pNet->pAC;
 
 struct sockaddr        *addr = p;
 unsigned long  Flags;
-
+       
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeSetMacAddr starts now...\n"));
-       if(netif_running(dev)) {
+       if(netif_running(dev))
                return -EBUSY;
-       }
+
        memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
        
        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
@@ -2535,7 +3130,7 @@ unsigned long     Flags;
  *     0, if everything is ok
  *     !=0, on error
  */
-static void SkGeSetRxMode(struct net_device *dev)
+static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
 {
 
 DEV_NET                *pNet;
@@ -2589,7 +3184,6 @@ unsigned long             Flags;
                                pMcList->dmi_addr[5]));
                }
                SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
-       
        }
        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
        
@@ -2610,7 +3204,7 @@ unsigned long             Flags;
  *     0, if everything is ok
  *     !=0, on error
  */
-static int SkGeChangeMtu(struct net_device *dev, int NewMtu)
+static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
 {
 DEV_NET                *pNet;
 DEV_NET                *pOtherNet;
@@ -2623,192 +3217,187 @@ SK_EVPARA     EvPara;
                ("SkGeChangeMtu starts now...\n"));
 
        pNet = (DEV_NET*) dev->priv;
-       pAC = pNet->pAC;
+       pAC  = pNet->pAC;
 
        if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
                return -EINVAL;
        }
 
+       if(pAC->BoardLevel != SK_INIT_RUN) {
+               return -EINVAL;
+       }
+
        pNet->Mtu = NewMtu;
        pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv;
-       if ((pOtherNet->Mtu > 1500) && (NewMtu <= 1500) && (pOtherNet->Up==1)) {
+       if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) {
                return(0);
        }
 
-       EvPara.Para32[0] = pNet->NetNr;
-       EvPara.Para32[1] = -1;
-
        pAC->RxBufSize = NewMtu + 32;
        dev->mtu = NewMtu;
 
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("New MTU: %d\n", NewMtu));
 
-       if(pAC->BoardLevel != 2) {
-               return 0;
-       }
-
-       /* prevent reconfiguration while changing the MTU */
-
-       /* disable interrupts */
+       /* 
+       ** Prevent any reconfiguration while changing the MTU 
+       ** by disabling any interrupts 
+       */
        SK_OUT32(pAC->IoBase, B0_IMSK, 0);
        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
 
-       /* Found more than one port */
-       if ((pAC->GIni.GIMacsFound == 2 ) && 
-               (pAC->RlmtNets == 2)) {
-                       /* Stop both ports */
-                       EvPara.Para32[0] = 0;
-                       SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-                       EvPara.Para32[0] = 1;
-                       SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+       /* 
+       ** Notify RLMT that any ports are to be stopped
+       */
+       EvPara.Para32[0] =  0;
+       EvPara.Para32[1] = -1;
+       if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+               SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+               EvPara.Para32[0] =  1;
+               SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
        } else {
                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
        }
 
+       /*
+       ** After calling the SkEventDispatcher(), RLMT is aware about
+       ** the stopped ports -> configuration can take place!
+       */
        SkEventDispatcher(pAC, pAC->IoBase);
 
        for (i=0; i<pAC->GIni.GIMacsFound; i++) {
                spin_lock_irqsave(
                        &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
                netif_stop_queue(pAC->dev[i]);
+
        }
 
-       /* 
-        * adjust number of rx buffers allocated
-        */
+       /*
+       ** Depending on the desired MTU size change, a different number of 
+       ** RX buffers need to be allocated
+       */
        if (NewMtu > 1500) {
-               /* use less rx buffers */
-               for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-                       /* Found more than one port */
-                       if ((pAC->GIni.GIMacsFound == 2 ) && 
-                               (pAC->RlmtNets == 2)) {
-                                       pAC->RxPort[i].RxFillLimit = 
-                                               pAC->RxDescrPerRing - 100;
-                       } else {
-                               if (i == pAC->ActivePort)
-                                       pAC->RxPort[i].RxFillLimit =
-                                               pAC->RxDescrPerRing - 100;
-                               else
-                                       pAC->RxPort[i].RxFillLimit =
-                                               pAC->RxDescrPerRing - 10;
-                       }
+           /* 
+           ** Use less rx buffers 
+           */
+           for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+               if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+                   pAC->RxPort[i].RxFillLimit =  pAC->RxDescrPerRing -
+                                                (pAC->RxDescrPerRing / 4);
+               } else {
+                   if (i == pAC->ActivePort) {
+                       pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
+                                                   (pAC->RxDescrPerRing / 4);
+                   } else {
+                       pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
+                                                   (pAC->RxDescrPerRing / 10);
+                   }
                }
-       }
-       else {
-               /* use normal anoumt of rx buffers */
-               for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-                       /* Found more than one port */
-                       if ((pAC->GIni.GIMacsFound == 2 ) && 
-                               (pAC->RlmtNets == 2)) {
-                                       pAC->RxPort[i].RxFillLimit = 1;
-                       } else {
-                               if (i == pAC->ActivePort)
-                                       pAC->RxPort[i].RxFillLimit = 1;
-                               else
-                                       pAC->RxPort[i].RxFillLimit =
-                                               pAC->RxDescrPerRing - 100;
-                       }
+           }
+       } else {
+           /* 
+           ** Use the normal amount of rx buffers 
+           */
+           for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+               if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+                   pAC->RxPort[i].RxFillLimit = 1;
+               } else {
+                   if (i == pAC->ActivePort) {
+                       pAC->RxPort[i].RxFillLimit = 1;
+                   } else {
+                       pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+                                                   (pAC->RxDescrPerRing / 4);
+                   }
                }
+           }
        }
-        
-       SkGeDeInit(pAC, pAC->IoBase); 
+       
+       SkGeDeInit(pAC, pAC->IoBase);
 
-       /* 
-        * enable/disable hardware support for long frames
-        */
+       /*
+       ** enable/disable hardware support for long frames
+       */
        if (NewMtu > 1500) {
-//             pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
+// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
                pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
-               for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-                       pAC->GIni.GP[i].PRxCmd = 
-                               XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
-               }
-       }
-       else {
-               if ((pAC->GIni.GIMacsFound == 2 ) && 
-                       (pAC->RlmtNets == 2)) {
-                       pAC->GIni.GIPortUsage = SK_MUL_LINK;
-               } else {
-                       pAC->GIni.GIPortUsage = SK_RED_LINK;
-               }
-               for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-                       pAC->GIni.GP[i].PRxCmd = XM_RX_STRIP_FCS;
-               }
+       } else {
+           if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+               pAC->GIni.GIPortUsage = SK_MUL_LINK;
+           } else {
+               pAC->GIni.GIPortUsage = SK_RED_LINK;
+           }
        }
 
-       SkGeInit(   pAC, pAC->IoBase, 1);
-       SkI2cInit(  pAC, pAC->IoBase, 1);
-       SkEventInit(pAC, pAC->IoBase, 1);
-       SkPnmiInit( pAC, pAC->IoBase, 1);
-       SkAddrInit( pAC, pAC->IoBase, 1);
-       SkRlmtInit( pAC, pAC->IoBase, 1);
-       SkTimerInit(pAC, pAC->IoBase, 1);
+       SkGeInit(   pAC, pAC->IoBase, SK_INIT_IO);
+       SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
+       SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+       SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+       SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+       SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+       SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
        
-       SkGeInit(   pAC, pAC->IoBase, 2);
-       SkI2cInit(  pAC, pAC->IoBase, 2);
-       SkEventInit(pAC, pAC->IoBase, 2);
-       SkPnmiInit( pAC, pAC->IoBase, 2);
-       SkAddrInit( pAC, pAC->IoBase, 2);
-       SkRlmtInit( pAC, pAC->IoBase, 2);
-       SkTimerInit(pAC, pAC->IoBase, 2);
+       /*
+       ** tschilling:
+       ** Speed and others are set back to default in level 1 init!
+       */
+       GetConfiguration(pAC);
+       
+       SkGeInit(   pAC, pAC->IoBase, SK_INIT_RUN);
+       SkI2cInit(  pAC, pAC->IoBase, SK_INIT_RUN);
+       SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
+       SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
+       SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
+       SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
+       SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
 
-       /* 
-        * clear and reinit the rx rings here
-        */
+       /*
+       ** clear and reinit the rx rings here
+       */
        for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-               ReceiveIrq(pAC, &pAC->RxPort[i]);
+               ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
                ClearRxRing(pAC, &pAC->RxPort[i]);
                FillRxRing(pAC, &pAC->RxPort[i]);
 
-               /* Enable transmit descriptor polling. */
+               /* 
+               ** Enable transmit descriptor polling
+               */
                SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
                FillRxRing(pAC, &pAC->RxPort[i]);
        };
 
        SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-#ifdef USE_INT_MOD
-       {
-               unsigned long ModBase;
-               ModBase = 53125000 / INTS_PER_SEC;
-               SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
-               SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK);
-               SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
-       }
-#endif
+       SkDimEnableModerationIfNeeded(pAC);     
+       SkDimDisplayModerationSettings(pAC);
 
        netif_start_queue(pAC->dev[pNet->PortNr]);
        for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
                spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
        }
 
-       /* enable Interrupts */
-       SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+       /* 
+       ** Enable Interrupts again 
+       */
+       SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
        SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
 
        SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
        SkEventDispatcher(pAC, pAC->IoBase);
 
-       /* Found more than one port */
-       if ((pAC->GIni.GIMacsFound == 2 ) && 
-               (pAC->RlmtNets == 2)) {
-                       /* Start both ports */
-                       EvPara.Para32[0] = pAC->RlmtNets;
-                       EvPara.Para32[1] = -1;
-                       SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
-                               EvPara);
-                       
+       /* 
+       ** Notify RLMT about the changing and restarting one (or more) ports
+       */
+       if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+               EvPara.Para32[0] = pAC->RlmtNets;
+               EvPara.Para32[1] = -1;
+               SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
+               EvPara.Para32[0] = pNet->PortNr;
+               EvPara.Para32[1] = -1;
+               SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
                        
-                       EvPara.Para32[1] = -1;
-                       EvPara.Para32[0] = pNet->PortNr;
+               if (pOtherNet->Up) {
+                       EvPara.Para32[0] = pOtherNet->PortNr;
                        SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-                       
-                       if (pOtherNet->Up) {
-                               EvPara.Para32[0] = pOtherNet->PortNr;
-                               SkEventQueue(pAC, SKGE_RLMT, 
-                                       SK_RLMT_START, EvPara);
-                       }
+               }
        } else {
                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
        }
@@ -2816,7 +3405,20 @@ SK_EVPARA        EvPara;
        SkEventDispatcher(pAC, pAC->IoBase);
        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
        
-       return 0;
+       /*
+       ** While testing this driver with latest kernel 2.5 (2.5.70), it 
+       ** seems as if upper layers have a problem to handle a successful
+       ** return value of '0'. If such a zero is returned, the complete 
+       ** system hangs for several minutes (!), which is in acceptable.
+       **
+       ** Currently it is not clear, what the exact reason for this problem
+       ** is. The implemented workaround for 2.5 is to return the desired 
+       ** new MTU size if all needed changes for the new MTU size where 
+       ** performed. In kernels 2.2 and 2.4, a zero value is returned,
+       ** which indicates the successful change of the mtu-size.
+       */
+       return NewMtu;
+
 } /* SkGeChangeMtu */
 
 
@@ -2831,12 +3433,13 @@ SK_EVPARA       EvPara;
  * Returns:
  *     pointer to the statistic structure.
  */
-static struct net_device_stats *SkGeStats(struct net_device *dev)
+static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
 {
 DEV_NET *pNet = (DEV_NET*) dev->priv;
 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 */SK_PNMI_CONF    *pPnmiConf;             /* pointer to virtual link config. */
+SK_PNMI_STAT    *pPnmiStat;             /* pointer to virtual XMAC stat. data */
+SK_PNMI_CONF    *pPnmiConf;             /* pointer to virtual link config. */
 unsigned int    Size;                   /* size of pnmi struct */
 unsigned long  Flags;                  /* for spin lock */
 
@@ -2855,7 +3458,18 @@ unsigned long    Flags;                  /* for spin lock */
        pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
        pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
        pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
-       pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+       
+        if (pNet->Mtu <= 1500) {
+                pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+        } else {
+                pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
+                        pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
+       }
+
+
+       if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
+               pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
+
        pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
        pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
        pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
@@ -2894,14 +3508,18 @@ unsigned long   Flags;                  /* for spin lock */
  *     0, if everything is ok
  *     !=0, on error
  */
-static int SkGeIoctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
 {
 DEV_NET                *pNet;
 SK_AC          *pAC;
+void           *pMemBuf;
 
 SK_GE_IOCTL    Ioctl;
 unsigned int   Err = 0;
-int            Size;
+int            Size = 0;
+int             Ret = 0;
+unsigned int   Length = 0;
+int            HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
 
        SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
                ("SkGeIoctl starts now...\n"));
@@ -2918,7 +3536,7 @@ int               Size;
        case SK_IOCTL_PRESETMIB:
                if (!capable(CAP_NET_ADMIN)) return -EPERM;
        case SK_IOCTL_GETMIB:
-               if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData, 
+               if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
                        Ioctl.Len<sizeof(pAC->PnmiStruct)?
                        Ioctl.Len : sizeof(pAC->PnmiStruct))) {
                        return -EFAULT;
@@ -2933,10 +3551,36 @@ int             Size;
                        return -EFAULT;
                }
                break;
+       case SK_IOCTL_GEN:
+               if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+                       Length = Ioctl.Len;
+               } else {
+                       Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+               }
+               if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+                       return -EFAULT;
+               }
+               if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+                       return -EFAULT;
+               }
+               if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
+                       return -EFAULT;
+               }
+               if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+                       return -EFAULT;
+               }
+               Ioctl.Len = Length;
+               if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+                       return -EFAULT;
+               }
+               kfree(pMemBuf); /* cleanup everything */
+               break;
        default:
                Err = -EOPNOTSUPP;
        }
+
        return(Err);
+
 } /* SkGeIoctl */
 
 
@@ -3008,11 +3652,18 @@ static void GetConfiguration(
 SK_AC  *pAC)   /* pointer to the adapter context structure */
 {
 SK_I32 Port;           /* preferred port */
-int    AutoNeg;        /* auto negotiation off (0) or on (1) */
-int    DuplexCap;      /* duplex capabilities (0=both, 1=full, 2=half */
-int    MSMode;         /* master / slave mode selection */
 SK_BOOL        AutoSet;
 SK_BOOL DupSet;
+int    LinkSpeed          = SK_LSPEED_AUTO;    /* Link speed */
+int    AutoNeg            = 1;                 /* autoneg off (0) or on (1) */
+int    DuplexCap          = 0;                 /* 0=both,1=full,2=half */
+int    FlowCtrl           = SK_FLOW_MODE_SYM_OR_REM;   /* FlowControl  */
+int    MSMode             = SK_MS_MODE_AUTO;   /* master/slave mode    */
+SK_BOOL IsConTypeDefined   = SK_TRUE;
+SK_BOOL IsLinkSpeedDefined = SK_TRUE;
+SK_BOOL IsFlowCtrlDefined  = SK_TRUE;
+SK_BOOL IsRoleDefined      = SK_TRUE;
+SK_BOOL IsModeDefined      = SK_TRUE;
 /*
  *     The two parameters AutoNeg. and DuplexCap. map to one configuration
  *     parameter. The mapping is described by this table:
@@ -3025,72 +3676,202 @@ SK_BOOL DupSet;
  *     -----------------------------------------------------------------
  *     Sense           |   AutoSense   |   AutoSense   |   AutoSense   |
  */
-int    Capabilities[3][3] = 
-               { {               -1, SK_LMODE_FULL,     SK_LMODE_HALF}, 
-                 {SK_LMODE_AUTOBOTH, SK_LMODE_AUTOFULL, SK_LMODE_AUTOHALF},
+int    Capabilities[3][3] =
+               { {                -1, SK_LMODE_FULL     , SK_LMODE_HALF     },
+                 {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
                  {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
+
 #define DC_BOTH        0
 #define DC_FULL 1
 #define DC_HALF 2
 #define AN_OFF 0
 #define AN_ON  1
 #define AN_SENS        2
+#define M_CurrPort pAC->GIni.GP[Port]
 
-       /* settings for port A */
-       AutoNeg = AN_SENS; /* default: do auto Sense */
+       /*
+       ** Set the default values first for both ports!
+       */
+       for (Port = 0; Port < SK_MAX_MACS; Port++) {
+               M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+               M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+               M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+               M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
+       }
+
+       /*
+       ** Check merged parameter ConType. If it has not been used,
+       ** verify any other parameter (e.g. AutoNeg) and use default values. 
+       **
+       ** Stating both ConType and other lowlevel link parameters is also
+       ** possible. If this is the case, the passed ConType-parameter is 
+       ** overwritten by the lowlevel link parameter.
+       **
+       ** The following settings are used for a merged ConType-parameter:
+       **
+       ** ConType   DupCap   AutoNeg   FlowCtrl      Role      Speed
+       ** -------   ------   -------   --------   ----------   -----
+       **  Auto      Both      On      SymOrRem      Auto       Auto
+       **  100FD     Full      Off       None      <ignored>    100
+       **  100HD     Half      Off       None      <ignored>    100
+       **  10FD      Full      Off       None      <ignored>    10
+       **  10HD      Half      Off       None      <ignored>    10
+       ** 
+       ** This ConType parameter is used for all ports of the adapter!
+       */
+        if ( (ConType != NULL)                && 
+            (pAC->Index < SK_MAX_CARD_PARAM) &&
+            (ConType[pAC->Index] != NULL) ) {
+                if (strcmp(ConType[pAC->Index],"")==0) {
+                       IsConTypeDefined = SK_FALSE; /* No ConType defined */
+                } else if (strcmp(ConType[pAC->Index],"Auto")==0) {
+                   for (Port = 0; Port < SK_MAX_MACS; Port++) {
+                       M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+                       M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+                       M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+                       M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
+                   }
+                } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
+                   for (Port = 0; Port < SK_MAX_MACS; Port++) {
+                       M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+                       M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+                       M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+                       M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
+                   }
+                } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
+                   for (Port = 0; Port < SK_MAX_MACS; Port++) {
+                       M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+                       M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+                       M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+                       M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
+                   }
+                } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
+                   for (Port = 0; Port < SK_MAX_MACS; Port++) {
+                       M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+                       M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+                       M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+                       M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
+                   }
+                } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
+                   for (Port = 0; Port < SK_MAX_MACS; Port++) {
+                       M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+                       M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+                       M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+                       M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
+                   }
+                } else { 
+                   printk("%s: Illegal value \"%s\" for ConType\n", 
+                       pAC->dev[0]->name, ConType[pAC->Index]);
+                   IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
+               }
+        } else {
+           IsConTypeDefined = SK_FALSE; /* No ConType defined */
+       }
+
+       /*
+       ** Parse any parameter settings for port A:
+       ** a) any LinkSpeed stated?
+       */
+       if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+               Speed_A[pAC->Index] != NULL) {
+               if (strcmp(Speed_A[pAC->Index],"")==0) {
+                   IsLinkSpeedDefined = SK_FALSE;
+               } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
+                   LinkSpeed = SK_LSPEED_AUTO;
+               } else if (strcmp(Speed_A[pAC->Index],"10")==0) {
+                   LinkSpeed = SK_LSPEED_10MBPS;
+               } else if (strcmp(Speed_A[pAC->Index],"100")==0) {
+                   LinkSpeed = SK_LSPEED_100MBPS;
+               } else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
+                   LinkSpeed = SK_LSPEED_1000MBPS;
+               } else {
+                   printk("%s: Illegal value \"%s\" for Speed_A\n",
+                       pAC->dev[0]->name, Speed_A[pAC->Index]);
+                   IsLinkSpeedDefined = SK_FALSE;
+               }
+       } else {
+           IsLinkSpeedDefined = SK_FALSE;
+       }
+
+       /* 
+       ** Check speed parameter: 
+       **    Only copper type adapter and GE V2 cards 
+       */
+       if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) ||
+               (pAC->GIni.GICopperType != SK_TRUE)) &&
+               ((LinkSpeed != SK_LSPEED_AUTO) &&
+               (LinkSpeed != SK_LSPEED_1000MBPS))) {
+               printk("%s: Illegal value for Speed_A. "
+                       "Not a copper card or GE V2 card\n    Using "
+                       "speed 1000\n", pAC->dev[0]->name);
+               LinkSpeed = SK_LSPEED_1000MBPS;
+       }
+       
+       /*      
+       ** Decide whether to set new config value if somethig valid has
+       ** been received.
+       */
+       if (IsLinkSpeedDefined) {
+               pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
+       } 
+
+       /* 
+       ** b) Any Autonegotiation and DuplexCapabilities set?
+       **    Please note that both belong together...
+       */
+       AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
        AutoSet = SK_FALSE;
        if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                AutoNeg_A[pAC->Index] != NULL) {
                AutoSet = SK_TRUE;
                if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
-                       AutoSet = SK_FALSE;
-               }
-               else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
-                       AutoNeg = AN_ON;
-               }
-               else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
-                       AutoNeg = AN_OFF;
-               }
-               else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
-                       AutoNeg = AN_SENS;
+                   AutoSet = SK_FALSE;
+               } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
+                   AutoNeg = AN_ON;
+               } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
+                   AutoNeg = AN_OFF;
+               } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
+                   AutoNeg = AN_SENS;
+               } else {
+                   printk("%s: Illegal value \"%s\" for AutoNeg_A\n",
+                       pAC->dev[0]->name, AutoNeg_A[pAC->Index]);
                }
-               else printk("%s: Illegal value for AutoNeg_A\n",
-                       pAC->dev[0]->name);
        }
 
        DuplexCap = DC_BOTH;
-       DupSet = SK_FALSE;
+       DupSet    = SK_FALSE;
        if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                DupCap_A[pAC->Index] != NULL) {
                DupSet = SK_TRUE;
                if (strcmp(DupCap_A[pAC->Index],"")==0) {
-                       DupSet = SK_FALSE;
-               }
-               else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
-                       DuplexCap = DC_BOTH;
-               }
-               else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
-                       DuplexCap = DC_FULL;
-               }
-               else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
-                       DuplexCap = DC_HALF;
+                   DupSet = SK_FALSE;
+               } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
+                   DuplexCap = DC_BOTH;
+               } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
+                   DuplexCap = DC_FULL;
+               } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
+                   DuplexCap = DC_HALF;
+               } else {
+                   printk("%s: Illegal value \"%s\" for DupCap_A\n",
+                       pAC->dev[0]->name, DupCap_A[pAC->Index]);
                }
-               else printk("%s: Illegal value for DupCap_A\n",
-                       pAC->dev[0]->name);
        }
        
-       /* check for illegal combinations */
-       if (AutoSet && AutoNeg==AN_SENS && DupSet) {
+       /* 
+       ** Check for illegal combinations 
+       */
+       if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
                printk("%s, Port A: DuplexCapabilities"
                        " ignored using Sense mode\n", pAC->dev[0]->name);
        }
+
        if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
                printk("%s, Port A: Illegal combination"
                        " of values AutoNeg. and DuplexCap.\n    Using "
                        "Full Duplex\n", pAC->dev[0]->name);
-
                DuplexCap = DC_FULL;
        }
+
        if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
                DuplexCap = DC_FULL;
        }
@@ -3103,114 +3884,184 @@ int   Capabilities[3][3] =
                AutoNeg = AN_ON;
        }
        
-       /* set the desired mode */
-       pAC->GIni.GP[0].PLinkModeConf =
-               Capabilities[AutoNeg][DuplexCap];
+       /* 
+       ** set the desired mode 
+       */
+       if (AutoSet || DupSet) {
+           pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+       }
        
-       pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+       /* 
+       ** c) Any Flowcontrol-parameter set?
+       */
        if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                FlowCtrl_A[pAC->Index] != NULL) {
                if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
+                   IsFlowCtrlDefined = SK_FALSE;
+               } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
+                   FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+               } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
+                   FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+               } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
+                   FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+               } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
+                   FlowCtrl = SK_FLOW_MODE_NONE;
+               } else {
+                   printk("%s: Illegal value \"%s\" for FlowCtrl_A\n",
+                        pAC->dev[0]->name, FlowCtrl_A[pAC->Index]);
+                   IsFlowCtrlDefined = SK_FALSE;
                }
-               else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
-                       pAC->GIni.GP[0].PFlowCtrlMode =
-                               SK_FLOW_MODE_SYM_OR_REM;
-               }
-               else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
-                       pAC->GIni.GP[0].PFlowCtrlMode =
-                               SK_FLOW_MODE_SYMMETRIC;
-               }
-               else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
-                       pAC->GIni.GP[0].PFlowCtrlMode =
-                               SK_FLOW_MODE_LOC_SEND;
-               }
-               else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
-                       pAC->GIni.GP[0].PFlowCtrlMode =
-                               SK_FLOW_MODE_NONE;
-               }
-               else printk("Illegal value for FlowCtrl_A\n");
+       } else {
+          IsFlowCtrlDefined = SK_FALSE;
        }
-       if (AutoNeg==AN_OFF && pAC->GIni.GP[0].PFlowCtrlMode!=
-               SK_FLOW_MODE_NONE) {
+
+       if (IsFlowCtrlDefined) {
+           if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
                printk("%s, Port A: FlowControl"
                        " impossible without AutoNegotiation,"
                        " disabled\n", pAC->dev[0]->name);
-               pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_NONE;
+               FlowCtrl = SK_FLOW_MODE_NONE;
+           }
+           pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
        }
 
-       MSMode = SK_MS_MODE_AUTO; /* default: do auto select */
+       /*
+       ** d) What is with the RoleParameter?
+       */
        if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                Role_A[pAC->Index] != NULL) {
                if (strcmp(Role_A[pAC->Index],"")==0) {
+                  IsRoleDefined = SK_FALSE;
+               } else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
+                   MSMode = SK_MS_MODE_AUTO;
+               } else if (strcmp(Role_A[pAC->Index],"Master")==0) {
+                   MSMode = SK_MS_MODE_MASTER;
+               } else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
+                   MSMode = SK_MS_MODE_SLAVE;
+               } else {
+                   printk("%s: Illegal value \"%s\" for Role_A\n",
+                       pAC->dev[0]->name, Role_A[pAC->Index]);
+                   IsRoleDefined = SK_FALSE;
                }
-               else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
-                       MSMode = SK_MS_MODE_AUTO;
-               }
-               else if (strcmp(Role_A[pAC->Index],"Master")==0) {
-                       MSMode = SK_MS_MODE_MASTER;
-               }
-               else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
-                       MSMode = SK_MS_MODE_SLAVE;
-               }
-               else printk("%s: Illegal value for Role_A\n",
-                       pAC->dev[0]->name);
+       } else {
+          IsRoleDefined = SK_FALSE;
+       }
+
+       if (IsRoleDefined == SK_TRUE) {
+           pAC->GIni.GP[0].PMSMode = MSMode;
        }
-       pAC->GIni.GP[0].PMSMode = MSMode;
        
+
        
-       /* settings for port B */
+       /* 
+       ** Parse any parameter settings for port B:
+       ** a) any LinkSpeed stated?
+       */
+       IsConTypeDefined   = SK_TRUE;
+       IsLinkSpeedDefined = SK_TRUE;
+       IsFlowCtrlDefined  = SK_TRUE;
+       IsModeDefined      = SK_TRUE;
+
+       if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+               Speed_B[pAC->Index] != NULL) {
+               if (strcmp(Speed_B[pAC->Index],"")==0) {
+                   IsLinkSpeedDefined = SK_FALSE;
+               } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
+                   LinkSpeed = SK_LSPEED_AUTO;
+               } else if (strcmp(Speed_B[pAC->Index],"10")==0) {
+                   LinkSpeed = SK_LSPEED_10MBPS;
+               } else if (strcmp(Speed_B[pAC->Index],"100")==0) {
+                   LinkSpeed = SK_LSPEED_100MBPS;
+               } else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
+                   LinkSpeed = SK_LSPEED_1000MBPS;
+               } else {
+                   printk("%s: Illegal value \"%s\" for Speed_B\n",
+                       pAC->dev[1]->name, Speed_B[pAC->Index]);
+                   IsLinkSpeedDefined = SK_FALSE;
+               }
+       } else {
+           IsLinkSpeedDefined = SK_FALSE;
+       }
+
+       /* 
+       ** Check speed parameter:
+       **    Only copper type adapter and GE V2 cards 
+       */
+       if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) ||
+               (pAC->GIni.GICopperType != SK_TRUE)) &&
+               ((LinkSpeed != SK_LSPEED_AUTO) &&
+               (LinkSpeed != SK_LSPEED_1000MBPS))) {
+               printk("%s: Illegal value for Speed_B. "
+                       "Not a copper card or GE V2 card\n    Using "
+                       "speed 1000\n", pAC->dev[1]->name);
+               LinkSpeed = SK_LSPEED_1000MBPS;
+       }
+
+       /*      
+       ** Decide whether to set new config value if somethig valid has
+       ** been received.
+       */
+        if (IsLinkSpeedDefined) {
+           pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
+       }
+
+       /* 
+       ** b) Any Autonegotiation and DuplexCapabilities set?
+       **    Please note that both belong together...
+       */
        AutoNeg = AN_SENS; /* default: do auto Sense */
        AutoSet = SK_FALSE;
        if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                AutoNeg_B[pAC->Index] != NULL) {
                AutoSet = SK_TRUE;
                if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
-                       AutoSet = SK_FALSE;
-               }
-               else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
-                       AutoNeg = AN_ON;
-               }
-               else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
-                       AutoNeg = AN_OFF;
-               }
-               else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
-                       AutoNeg = AN_SENS;
+                   AutoSet = SK_FALSE;
+               } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
+                   AutoNeg = AN_ON;
+               } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
+                   AutoNeg = AN_OFF;
+               } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
+                   AutoNeg = AN_SENS;
+               } else {
+                   printk("%s: Illegal value \"%s\" for AutoNeg_B\n",
+                       pAC->dev[0]->name, AutoNeg_B[pAC->Index]);
                }
-               else printk("Illegal value for AutoNeg_B\n");
        }
 
        DuplexCap = DC_BOTH;
-       DupSet = SK_FALSE;
+       DupSet    = SK_FALSE;
        if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                DupCap_B[pAC->Index] != NULL) {
                DupSet = SK_TRUE;
                if (strcmp(DupCap_B[pAC->Index],"")==0) {
-                       DupSet = SK_FALSE;
-               }
-               else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
-                       DuplexCap = DC_BOTH;
-               }
-               else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
-                       DuplexCap = DC_FULL;
-               }
-               else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
-                       DuplexCap = DC_HALF;
+                   DupSet = SK_FALSE;
+               } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
+                   DuplexCap = DC_BOTH;
+               } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
+                   DuplexCap = DC_FULL;
+               } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
+                   DuplexCap = DC_HALF;
+               } else {
+                   printk("%s: Illegal value \"%s\" for DupCap_B\n",
+                       pAC->dev[0]->name, DupCap_B[pAC->Index]);
                }
-               else printk("Illegal value for DupCap_B\n");
        }
        
-       /* check for illegal combinations */
+       /* 
+       ** Check for illegal combinations 
+       */
        if (AutoSet && AutoNeg==AN_SENS && DupSet) {
                printk("%s, Port B: DuplexCapabilities"
                        " ignored using Sense mode\n", pAC->dev[1]->name);
        }
+
        if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
                printk("%s, Port B: Illegal combination"
                        " of values AutoNeg. and DuplexCap.\n    Using "
                        "Full Duplex\n", pAC->dev[1]->name);
-
                DuplexCap = DC_FULL;
        }
+
        if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
                DuplexCap = DC_FULL;
        }
@@ -3223,129 +4074,231 @@ int   Capabilities[3][3] =
                AutoNeg = AN_ON;
        }
 
-       /* set the desired mode */
-       pAC->GIni.GP[1].PLinkModeConf =
-               Capabilities[AutoNeg][DuplexCap];
+       /* 
+       ** set the desired mode 
+       */
+       if (AutoSet || DupSet) {
+           pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+       }
 
-       pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+       /*
+       ** c) Any FlowCtrl parameter set?
+       */
        if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                FlowCtrl_B[pAC->Index] != NULL) {
                if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
+                   IsFlowCtrlDefined = SK_FALSE;
+               } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
+                   FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+               } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
+                   FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+               } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
+                   FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+               } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
+                   FlowCtrl = SK_FLOW_MODE_NONE;
+               } else {
+                   printk("%s: Illegal value \"%s\" for FlowCtrl_B\n",
+                       pAC->dev[0]->name, FlowCtrl_B[pAC->Index]);
+                   IsFlowCtrlDefined = SK_FALSE;
                }
-               else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
-                       pAC->GIni.GP[1].PFlowCtrlMode =
-                               SK_FLOW_MODE_SYM_OR_REM;
-               }
-               else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
-                       pAC->GIni.GP[1].PFlowCtrlMode =
-                               SK_FLOW_MODE_SYMMETRIC;
-               }
-               else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
-                       pAC->GIni.GP[1].PFlowCtrlMode =
-                               SK_FLOW_MODE_LOC_SEND;
-               }
-               else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
-                       pAC->GIni.GP[1].PFlowCtrlMode =
-                               SK_FLOW_MODE_NONE;
-               }
-               else printk("Illegal value for FlowCtrl_B\n");
+       } else {
+               IsFlowCtrlDefined = SK_FALSE;
        }
-       if (AutoNeg==AN_OFF && pAC->GIni.GP[1].PFlowCtrlMode!=
-               SK_FLOW_MODE_NONE) {
+
+       if (IsFlowCtrlDefined) {
+           if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
                printk("%s, Port B: FlowControl"
                        " impossible without AutoNegotiation,"
                        " disabled\n", pAC->dev[1]->name);
-               pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_NONE;
+               FlowCtrl = SK_FLOW_MODE_NONE;
+           }
+           pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
        }
 
-       MSMode = SK_MS_MODE_AUTO; /* default: do auto select */
+       /*
+       ** d) What is the RoleParameter?
+       */
        if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                Role_B[pAC->Index] != NULL) {
                if (strcmp(Role_B[pAC->Index],"")==0) {
+                   IsRoleDefined = SK_FALSE;
+               } else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
+                   MSMode = SK_MS_MODE_AUTO;
+               } else if (strcmp(Role_B[pAC->Index],"Master")==0) {
+                   MSMode = SK_MS_MODE_MASTER;
+               } else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
+                   MSMode = SK_MS_MODE_SLAVE;
+               } else {
+                   printk("%s: Illegal value \"%s\" for Role_B\n",
+                       pAC->dev[1]->name, Role_B[pAC->Index]);
+                   IsRoleDefined = SK_FALSE;
                }
-               else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
-                       MSMode = SK_MS_MODE_AUTO;
-               }
-               else if (strcmp(Role_B[pAC->Index],"Master")==0) {
-                       MSMode = SK_MS_MODE_MASTER;
-               }
-               else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
-                       MSMode = SK_MS_MODE_SLAVE;
-               }
-               else printk("%s: Illegal value for Role_B\n",
-                       pAC->dev[1]->name);
+       } else {
+           IsRoleDefined = SK_FALSE;
+       }
+
+       if (IsRoleDefined) {
+           pAC->GIni.GP[1].PMSMode = MSMode;
        }
-       pAC->GIni.GP[1].PMSMode = MSMode;
-       
        
-       /* settings for both ports */
+       /*
+       ** Evaluate settings for both ports
+       */
        pAC->ActivePort = 0;
        if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                PrefPort[pAC->Index] != NULL) {
                if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
-                       pAC->ActivePort = 0;
-                       pAC->Rlmt.Net[0].Preference = -1; /* auto */
-                       pAC->Rlmt.Net[0].PrefPort = 0;
-               }
-               else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
-                       /*
-                        * do not set ActivePort here, thus a port
-                        * switch is issued after net up.
-                        */
-                       Port = 0;
-                       pAC->Rlmt.Net[0].Preference = Port;
-                       pAC->Rlmt.Net[0].PrefPort = Port;
-               }
-               else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
-                       /*
-                        * do not set ActivePort here, thus a port
-                        * switch is issued after net up.
-                        */
-                       Port = 1;
-                       pAC->Rlmt.Net[0].Preference = Port;
-                       pAC->Rlmt.Net[0].PrefPort = Port;
+                   pAC->ActivePort             =  0;
+                   pAC->Rlmt.Net[0].Preference = -1; /* auto */
+                   pAC->Rlmt.Net[0].PrefPort   =  0;
+               } else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
+                   /*
+                   ** do not set ActivePort here, thus a port
+                   ** switch is issued after net up.
+                   */
+                   Port                        = 0;
+                   pAC->Rlmt.Net[0].Preference = Port;
+                   pAC->Rlmt.Net[0].PrefPort   = Port;
+               } else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
+                   /*
+                   ** do not set ActivePort here, thus a port
+                   ** switch is issued after net up.
+                   */
+                   Port                        = 1;
+                   pAC->Rlmt.Net[0].Preference = Port;
+                   pAC->Rlmt.Net[0].PrefPort   = Port;
+               } else {
+                   printk("%s: Illegal value \"%s\" for PrefPort\n",
+                       pAC->dev[0]->name, PrefPort[pAC->Index]);
                }
-               else printk("%s: Illegal value for PrefPort\n",
-                       pAC->dev[0]->name);
        }
 
        pAC->RlmtNets = 1;
-       
+
        if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
                RlmtMode[pAC->Index] != NULL) {
                if (strcmp(RlmtMode[pAC->Index], "") == 0) {
                        pAC->RlmtMode = 0;
-               }
-               else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
+               } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
                        pAC->RlmtMode = SK_RLMT_CHECK_LINK;
-               }
-               else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
-                       pAC->RlmtMode = SK_RLMT_CHECK_LINK |
-                               SK_RLMT_CHECK_LOC_LINK;
-               }
-               else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
+               } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
                        pAC->RlmtMode = SK_RLMT_CHECK_LINK |
-                               SK_RLMT_CHECK_LOC_LINK | 
-                               SK_RLMT_CHECK_SEG;
-               }
-               else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
+                                       SK_RLMT_CHECK_LOC_LINK;
+               } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
+                       pAC->RlmtMode = SK_RLMT_CHECK_LINK     |
+                                       SK_RLMT_CHECK_LOC_LINK |
+                                       SK_RLMT_CHECK_SEG;
+               } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
                        (pAC->GIni.GIMacsFound == 2)) {
-                               pAC->RlmtMode = SK_RLMT_CHECK_LINK;
-                               pAC->RlmtNets = 2;
-               }
-               else {
-                       printk("%s: Illegal value for"
-                               " RlmtMode, using default\n", pAC->dev[0]->name);
-
-printk("MacFound = %d\nRlmtMode = %s", pAC->GIni.GIMacsFound, RlmtMode[pAC->Index]);
-       
-
+                       pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+                       pAC->RlmtNets = 2;
+               } else {
+                   printk("%s: Illegal value \"%s\" for"
+                       " RlmtMode, using default\n", 
+                       pAC->dev[0]->name, RlmtMode[pAC->Index]);
                        pAC->RlmtMode = 0;
                }
-       }
-       else {
+       } else {
                pAC->RlmtMode = 0;
        }
+       
+       /*
+       ** Check the interrupt moderation parameters
+       */
+       if (Moderation[pAC->Index] != NULL) {
+           if (strcmp(Moderation[pAC->Index], "Static") == 0) {
+                pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
+           } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
+               pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
+           } else {
+               pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+           }
+       } else {
+           pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+       }
+
+       if (Stats[pAC->Index] != NULL) {
+           if (strcmp(Stats[pAC->Index], "Yes") == 0) {
+               pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
+           } else {
+               pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+           }
+       } else {
+           pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+       }
+
+        if (ModerationMask[pAC->Index] != NULL) {
+           if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+           } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
+           } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
+           } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+           } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+           } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+           } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+           } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+           } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+           } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+           } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+           } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+           } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+           } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+           } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+           } else { /* some rubbish */
+               pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+           }
+        } else {  /* operator has stated nothing */
+           pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+        }
+
+        if (AutoSizing[pAC->Index] != NULL) {
+           if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
+               pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+           } else {
+               pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+           }
+        } else {  /* operator has stated nothing */
+           pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+        }
+
+        if (IntsPerSec[pAC->Index] != 0) {
+           if ((IntsPerSec[pAC->Index]< 30)&&(IntsPerSec[pAC->Index]> 40000)) {
+              pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+           } else {
+              pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
+           }
+        } else {
+           pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+        }
+
+        /*
+       ** Evaluate upper and lower moderation threshold
+       */
+        pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
+            pAC->DynIrqModInfo.MaxModIntsPerSec +
+            (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+
+        pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
+            pAC->DynIrqModInfo.MaxModIntsPerSec -
+            (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+
+        pAC->DynIrqModInfo.PrevTimeVal = jiffies;  /* initial value */
+
+
 } /* GetConfiguration */
 
 
@@ -3380,8 +4333,44 @@ unsigned long Flags;
        }
 } /* ProductStr */
 
+/*****************************************************************************
+ *
+ *      StartDrvCleanupTimer - Start timer to check for descriptors which
+ *                             might be placed in descriptor ring, but
+ *                             havent been handled up to now
+ *
+ * Description:
+ *      This function requests a HW-timer fo the Yukon card. The actions to
+ *      perform when this timer expires, are located in the SkDrvEvent().
+ *
+ * Returns: N/A
+ */
+static void
+StartDrvCleanupTimer(SK_AC *pAC) {
+    SK_EVPARA    EventParam;   /* Event struct for timer event */
+
+    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+    EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
+    SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
+                 SK_DRV_RX_CLEANUP_TIMER_LENGTH,
+                 SKGE_DRV, SK_DRV_TIMER, EventParam);
+}
 
-
+/*****************************************************************************
+ *
+ *      StopDrvCleanupTimer - Stop timer to check for descriptors
+ *
+ * Description:
+ *      This function requests a HW-timer fo the Yukon card. The actions to
+ *      perform when this timer expires, are located in the SkDrvEvent().
+ *
+ * Returns: N/A
+ */
+static void
+StopDrvCleanupTimer(SK_AC *pAC) {
+    SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
+    SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
+}
 
 /****************************************************************************/
 /* functions for common modules *********************************************/
@@ -3440,8 +4429,8 @@ struct sk_buff    *pMsgBlock;     /* pointer to a new message block */
  *     Nothing
  */
 void  SkDrvFreeRlmtMbuf(
-SK_AC          *pAC,           /* pointer to adapter context */  
-SK_IOC         IoC,            /* the IO-context */              
+SK_AC          *pAC,           /* pointer to adapter context */
+SK_IOC         IoC,            /* the IO-context */
 SK_MBUF                *pMbuf)         /* size of the requested buffer */
 {
 SK_MBUF                *pFreeMbuf;
@@ -3470,7 +4459,9 @@ SK_MBUF           *pNextMbuf;
  */
 SK_U64 SkOsGetTime(SK_AC *pAC)
 {
-       return jiffies;
+       SK_U64  PrivateJiffies;
+       SkOsGetTimeCurrent(pAC, &PrivateJiffies);
+       return PrivateJiffies;
 } /* SkOsGetTime */
 
 
@@ -3491,7 +4482,7 @@ SK_AC *pAC,               /* Adapter Control structure pointer */
 int PciAddr,           /* PCI register address */
 SK_U32 *pVal)          /* pointer to store the read value */
 {
-       pci_read_config_dword(&pAC->PciDev, PciAddr, pVal);
+       pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
        return(0);
 } /* SkPciReadCfgDWord */
 
@@ -3513,7 +4504,7 @@ SK_AC *pAC,       /* Adapter Control structure pointer */
 int PciAddr,           /* PCI register address */
 SK_U16 *pVal)          /* pointer to store the read value */
 {
-       pci_read_config_word(&pAC->PciDev, PciAddr, pVal);
+       pci_read_config_word(pAC->PciDev, PciAddr, pVal);
        return(0);
 } /* SkPciReadCfgWord */
 
@@ -3535,7 +4526,7 @@ SK_AC *pAC,       /* Adapter Control structure pointer */
 int PciAddr,           /* PCI register address */
 SK_U8 *pVal)           /* pointer to store the read value */
 {
-       pci_read_config_byte(&pAC->PciDev, PciAddr, pVal);
+       pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
        return(0);
 } /* SkPciReadCfgByte */
 
@@ -3557,7 +4548,7 @@ 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);
+       pci_write_config_dword(pAC->PciDev, PciAddr, Val);
        return(0);
 } /* SkPciWriteCfgDWord */
 
@@ -3569,7 +4560,7 @@ SK_U32 Val)               /* pointer to store the read value */
  * Description:
  *     This routine writes a 16 bit value to the pci configuration
  *     space. The flag PciConfigUp indicates whether the config space
- *     is accessible or must be set up first.
+ *     is accesible or must be set up first.
  *
  * Returns:
  *     0 - indicate everything worked ok.
@@ -3580,7 +4571,7 @@ SK_AC *pAC,       /* Adapter Control structure pointer */
 int PciAddr,           /* PCI register address */
 SK_U16 Val)            /* pointer to store the read value */
 {
-       pci_write_config_word(&pAC->PciDev, PciAddr, Val);
+       pci_write_config_word(pAC->PciDev, PciAddr, Val);
        return(0);
 } /* SkPciWriteCfgWord */
 
@@ -3592,7 +4583,7 @@ SK_U16 Val)               /* pointer to store the read value */
  * Description:
  *     This routine writes a 8 bit value to the pci configuration
  *     space. The flag PciConfigUp indicates whether the config space
- *     is accessible or must be set up first.
+ *     is accesible or must be set up first.
  *
  * Returns:
  *     0 - indicate everything worked ok.
@@ -3603,7 +4594,7 @@ SK_AC *pAC,       /* Adapter Control structure pointer */
 int PciAddr,           /* PCI register address */
 SK_U8 Val)             /* pointer to store the read value */
 {
-       pci_write_config_byte(&pAC->PciDev, PciAddr, Val);
+       pci_write_config_byte(pAC->PciDev, PciAddr, Val);
        return(0);
 } /* SkPciWriteCfgByte */
 
@@ -3636,6 +4627,7 @@ int               ToPort;         /* the port we switch to */
 SK_EVPARA      NewPara;        /* parameter for further events */
 int            Stat;
 unsigned long  Flags;
+SK_BOOL                DualNet;
 
        switch (Event) {
        case SK_DRV_ADAP_FAIL:
@@ -3668,18 +4660,27 @@ unsigned long   Flags;
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
                SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
+               pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
                spin_unlock_irqrestore(
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
                
                /* clear rx ring from received frames */
-               ReceiveIrq(pAC, &pAC->RxPort[FromPort]);
+               ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
                
                ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
                spin_lock_irqsave(
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
-               SkGeInitPort(pAC, IoC, FromPort);
+               
+               /* tschilling: Handling of return value inserted. */
+               if (SkGeInitPort(pAC, IoC, FromPort)) {
+                       if (FromPort == 0) {
+                               printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
+                       } else {
+                               printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
+                       }
+               }
                SkAddrMcUpdate(pAC,IoC, FromPort);
                PortReInitBmu(pAC, FromPort);
                SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
@@ -3695,7 +4696,22 @@ unsigned long    Flags;
                        ("NET UP EVENT, Port: %d ", Param.Para32[0]));
                printk("%s: network connection up using"
                        " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
-               printk("    speed:           1000\n");
+
+               /* tschilling: Values changed according to LinkSpeedUsed. */
+               Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
+               if (Stat == SK_LSPEED_STAT_10MBPS) {
+                       printk("    speed:           10\n");
+               } else if (Stat == SK_LSPEED_STAT_100MBPS) {
+                       printk("    speed:           100\n");
+               } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
+                       printk("    speed:           1000\n");
+               } else {
+                       printk("    speed:           unknown\n");
+               }
+
+               /* Mac update */
+               SkAddrMcUpdate(pAC,IoC, FromPort);
+
                Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
                if (Stat == SK_LMODE_STAT_AUTOHALF ||
                        Stat == SK_LMODE_STAT_AUTOFULL) {
@@ -3724,8 +4740,12 @@ unsigned long    Flags;
                else {
                        printk("    flowctrl:        none\n");
                }
-               if (pAC->GIni.GP[FromPort].PhyType != SK_PHY_XMAC) {
-               Stat = pAC->GIni.GP[FromPort].PMSStatus;
+               
+               /* tschilling: Check against CopperType now. */
+               if ((pAC->GIni.GICopperType == SK_TRUE) &&
+                       (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
+                       SK_LSPEED_STAT_1000MBPS)) {
+                       Stat = pAC->GIni.GP[FromPort].PMSStatus;
                        if (Stat == SK_MS_STAT_MASTER ) {
                                printk("    role:            master\n");
                        }
@@ -3736,20 +4756,43 @@ unsigned long   Flags;
                                printk("    role:            ???\n");
                        }
                }
-               
-               if ((Param.Para32[0] != pAC->ActivePort) && 
+#ifdef SK_ZEROCOPY
+               if (pAC->GIni.GIChipId == CHIP_ID_YUKON)
+#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
+
+       
+               if ((Param.Para32[0] != pAC->ActivePort) &&
                        (pAC->RlmtNets == 1)) {
                        NewPara.Para32[0] = pAC->ActivePort;
                        NewPara.Para32[1] = Param.Para32[0];
                        SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
                                NewPara);
                }
+
+               /* Inform the world that link protocol is up. */
+               pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
+
                break;
        case SK_DRV_NET_DOWN:    /* SK_U32 Reason */
                /* action list 7 */
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
                        ("NET DOWN EVENT "));
                printk("%s: network connection down\n", pAC->dev[Param.Para32[1]]->name);
+               pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
                break;
        case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
                SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -3781,24 +4824,48 @@ unsigned long   Flags;
                        &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
 
-               ReceiveIrq(pAC, &pAC->RxPort[FromPort]); /* clears rx ring */
-               ReceiveIrq(pAC, &pAC->RxPort[ToPort]); /* clears rx ring */
+               ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
+               ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
                
                ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
                ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
                spin_lock_irqsave(
-                       &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, 
+                       &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
                        Flags);
                spin_lock_irqsave(
                        &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
                pAC->ActivePort = ToPort;
+#if 0
                SetQueueSizes(pAC);
-               SkGeInitPort(pAC, IoC, FromPort);
-               SkGeInitPort(pAC, IoC, ToPort);
+#else
+               /* tschilling: New common function with minimum size check. */
+               DualNet = SK_FALSE;
+               if (pAC->RlmtNets == 2) {
+                       DualNet = SK_TRUE;
+               }
+               
+               if (SkGeInitAssignRamToQueues(
+                       pAC,
+                       pAC->ActivePort,
+                       DualNet)) {
+                       spin_unlock_irqrestore(
+                               &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+                       spin_unlock_irqrestore(
+                               &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+                               Flags);
+                       printk("SkGeInitAssignRamToQueues failed.\n");
+                       break;
+               }
+#endif
+               /* tschilling: Handling of return values inserted. */
+               if (SkGeInitPort(pAC, IoC, FromPort) ||
+                       SkGeInitPort(pAC, IoC, ToPort)) {
+                       printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
+               }
                if (Event == SK_DRV_SWITCH_SOFT) {
-                       SkXmRxTxEnable(pAC, IoC, FromPort);
+                       SkMacRxTxEnable(pAC, IoC, FromPort);
                }
-               SkXmRxTxEnable(pAC, IoC, ToPort);
+               SkMacRxTxEnable(pAC, IoC, ToPort);
                SkAddrSwap(pAC, IoC, FromPort, ToPort);
                SkAddrMcUpdate(pAC, IoC, FromPort);
                SkAddrMcUpdate(pAC, IoC, ToPort);
@@ -3821,9 +4888,35 @@ unsigned long    Flags;
                pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
                skb_put(pMsg, pRlmtMbuf->Length);
                if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
-                             pMsg) < 0)
+                       pMsg) < 0)
+
                        DEV_KFREE_SKB_ANY(pMsg);
                break;
+       case SK_DRV_TIMER:
+               if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
+                       /*
+                       ** expiration of the moderation timer implies that
+                       ** dynamic moderation is to be applied
+                       */
+                       SkDimStartModerationTimer(pAC);
+                       SkDimModerate(pAC);
+                        if (pAC->DynIrqModInfo.DisplayStats) {
+                           SkDimDisplayModerationSettings(pAC);
+                        }
+                } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
+                       /*
+                       ** check if we need to check for descriptors which
+                       ** haven't been handled the last millisecs
+                       */
+                       StartDrvCleanupTimer(pAC);
+                       if (pAC->GIni.GIMacsFound == 2) {
+                               ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
+                       }
+                       ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
+               } else {
+                       printk("Expiration of unknown timer\n");
+               }
+               break;
        default:
                break;
        }
@@ -3883,7 +4976,8 @@ char      ClassStr[80];
 
 } /* SkErrorLog */
 
-#ifdef DEBUG /***************************************************************/
+#ifdef DEBUG
+/****************************************************************************/
 /* "debug only" section *****************************************************/
 /****************************************************************************/
 
@@ -3930,7 +5024,7 @@ static void DumpMsg(struct sk_buff *skb, char *str)
  *     DumpData - print a data area
  *
  * Description:
- *     This function prints a area of data to the system logfile/to the 
+ *     This function prints a area of data to the system logfile/to the
  *     console.
  *
  * Returns: N/A
@@ -3978,7 +5072,7 @@ char      HEXCHAR[] = "0123456789ABCDEF";
  *     DumpLong - print a data area as long values
  *
  * Description:
- *     This function prints a area of data to the system logfile/to the 
+ *     This function prints a area of data to the system logfile/to the
  *     console.
  *
  * Returns: N/A
@@ -4030,64 +5124,10 @@ int     l;
        printk("------------------------\n");
 } /* DumpLong */
 
-#endif /* DEBUG */
-
-static struct pci_device_id skge_pci_tbl[] __devinitdata = {
-       { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       { 0,}
-};
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
-static struct pci_driver skge_driver = {
-       .name           = DRV_MODULE_NAME,
-       .id_table       = skge_pci_tbl,
-       .probe          = skge_init_one,
-       .remove         = __devexit_p(skge_remove_one),
-};
+#endif
 
-/*****************************************************************************
- *
- *     skge_init - module initialization function
+/*******************************************************************************
  *
- * Description:
- *     root /proc directory allocation and pci driver invocation.
+ * End of file
  *
- * Returns:
- *     0, if everything is ok
- *     !=0, on error
- */
-static int __init skge_init(void)
-{
-       int ret = -ENOMEM;
-       
-       /* just to avoid warnings ... */
-       debug = 0;
-       options[0] = 0;
-
-       pSkRootDir = create_proc_entry(DRV_MODULE_NAME,
-                       S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net);
-       if (pSkRootDir) {
-               pSkRootDir->owner = THIS_MODULE;
-               ret = pci_module_init(&skge_driver);
-               if (ret)
-                       remove_proc_entry(pSkRootDir->name, proc_net);
-       }
-       return ret;
-} /* skge_init */
-
-
-static void __exit skge_cleanup(void)
-{
-       remove_proc_entry(pSkRootDir->name, proc_net);
-       pci_unregister_driver(&skge_driver);
-}
-
-module_init(skge_init);
-module_exit(skge_cleanup);
-
-/*
- * Local variables:
- * compile-command: "make"
- * End:
- */
+ ******************************************************************************/