Merge branch 'upstream-net26' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

Conflicts:

	drivers/s390/net/qeth_main.c
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 9119d03..1d171fe 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -213,14 +213,6 @@
 
 ---------------------------
 
-What:   sk98lin network driver
-When:   Feburary 2008
-Why:    In kernel tree version of driver is unmaintained. Sk98lin driver
-	replaced by the skge driver. 
-Who:    Stephen Hemminger <shemminger@linux-foundation.org>
-
----------------------------
-
 What:	i386/x86_64 bzImage symlinks
 When:	April 2008
 
@@ -231,8 +223,6 @@
 
 ---------------------------
 
----------------------------
-
 What:	i2c-i810, i2c-prosavage and i2c-savage4
 When:	May 2008
 Why:	These drivers are superseded by i810fb, intelfb and savagefb.
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 62f6b5a..cb93bf2 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -537,11 +537,9 @@
 # CONFIG_SMSGIUCV is not set
 # CONFIG_CLAW is not set
 CONFIG_QETH=y
-
-#
-# Gigabit Ethernet default settings
-#
-# CONFIG_QETH_IPV6 is not set
+CONFIG_QETH_L2=y
+CONFIG_QETH_L3=y
+CONFIG_QETH_IPV6=y
 CONFIG_CCWGROUP=y
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index a828076..0ed41a3 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -48,14 +48,16 @@
 
 #if defined(MODULE)
 
-int init_module(void)
+static int __init ns8390_module_init(void)
 {
 	return 0;
 }
 
-void cleanup_module(void)
+static void __exit ns8390_module_exit(void)
 {
 }
 
+module_init(ns8390_init_module);
+module_exit(ns8390_module_exit);
 #endif /* MODULE */
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index fe7b5ec..978e72a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2220,93 +2220,6 @@
 
 	 If unsure, say N.
 
-config SK98LIN
-	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
-	depends on PCI
-	---help---
-	  Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
-	  compliant Gigabit Ethernet Adapter.
-
-	  This driver supports the original Yukon chipset. This driver is
-	  deprecated and will be removed from the kernel in the near future,
-	  it has been replaced by the skge driver. skge is cleaner and
-	  seems to work better.
-
-	  This driver does not support the newer Yukon2 chipset. A separate
-	  driver, sky2, is provided to support Yukon2-based adapters.
-
-	  The following adapters are supported by this driver:
-	    - 3Com 3C940 Gigabit LOM Ethernet Adapter
-	    - 3Com 3C941 Gigabit LOM Ethernet Adapter
-	    - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
-	    - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
-	    - EG1032 v2 Instant Gigabit Network Adapter
-	    - EG1064 v2 Instant Gigabit Network Adapter
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
-	    - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
-	    - Marvell RDK-8001 Adapter
-	    - Marvell RDK-8002 Adapter
-	    - Marvell RDK-8003 Adapter
-	    - Marvell RDK-8004 Adapter
-	    - Marvell RDK-8006 Adapter
-	    - Marvell RDK-8007 Adapter
-	    - Marvell RDK-8008 Adapter
-	    - Marvell RDK-8009 Adapter
-	    - Marvell RDK-8010 Adapter
-	    - Marvell RDK-8011 Adapter
-	    - Marvell RDK-8012 Adapter
-	    - Marvell RDK-8052 Adapter
-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
-	    - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
-	    - SK-9521 10/100/1000Base-T Adapter
-	    - SK-9521 V2.0 10/100/1000Base-T Adapter
-	    - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
-	    - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
-	    - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
-	    - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
-	    - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
-	    - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
-	    - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
-	    - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
-	    - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
-	    - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
-	    - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
-	    - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
-	    - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
-	    - SMC EZ Card 1000 (SMC9452TXV.2)
-	  
-	  The adapters support Jumbo Frames.
-	  The dual link adapters support link-failover and dual port features.
-	  Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support 
-	  the scatter-gather functionality with sendfile(). Please refer to 
-	  <file:Documentation/networking/sk98lin.txt> for more information about
-	  optional driver parameters.
-	  Questions concerning this driver may be addressed to:
-	      <linux@syskonnect.de>
-	  
-	  If you want to compile this driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/kbuild/modules.txt>. The module will
-	  be called sk98lin. This is recommended.
-
 config VIA_VELOCITY
 	tristate "VIA Velocity support"
 	depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3b1ea32..960999c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,7 +15,7 @@
 obj-$(CONFIG_EHEA) += ehea/
 obj-$(CONFIG_CAN) += can/
 obj-$(CONFIG_BONDING) += bonding/
-obj-$(CONFIG_ATL1) += atl1/
+obj-$(CONFIG_ATL1) += atlx/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 obj-$(CONFIG_TEHUTI) += tehuti.o
 
@@ -75,7 +75,6 @@
 obj-$(CONFIG_TC35815) += tc35815.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
-obj-$(CONFIG_SK98LIN) += sk98lin/
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 92c3a4c..65b901e 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -1010,7 +1010,7 @@
 module_param(irq, int, 0);
 module_param(board_type, int, 0);
 
-int __init init_module(void)
+static int __init cops_module_init(void)
 {
 	if (io == 0)
 		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
@@ -1021,12 +1021,14 @@
         return 0;
 }
 
-void __exit cleanup_module(void)
+static void __exit cops_module_exit(void)
 {
 	unregister_netdev(cops_dev);
 	cleanup_card(cops_dev);
 	free_netdev(cops_dev);
 }
+module_init(cops_module_init);
+module_exit(cops_module_exit);
 #endif /* MODULE */
 
 /*
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 7cf0a25..8b51313 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -348,14 +348,15 @@
 
 #ifdef MODULE
 
-int init_module(void)
+static int __init com20020_module_init(void)
 {
 	BUGLVL(D_NORMAL) printk(VERSION);
 	return 0;
 }
 
-void cleanup_module(void)
+static void __exit com20020_module_exit(void)
 {
 }
-
+module_init(com20020_module_init);
+module_exit(com20020_module_exit);
 #endif				/* MODULE */
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 24d81f9..7e874d4 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -881,7 +881,7 @@
 MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
 MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
 
-int __init init_module(void)
+static int __init at1700_module_init(void)
 {
 	if (io == 0)
 		printk("at1700: You should not use auto-probing with insmod!\n");
@@ -891,13 +891,14 @@
 	return 0;
 }
 
-void __exit
-cleanup_module(void)
+static void __exit at1700_module_exit(void)
 {
 	unregister_netdev(dev_at1700);
 	cleanup_card(dev_at1700);
 	free_netdev(dev_at1700);
 }
+module_init(at1700_module_init);
+module_exit(at1700_module_exit);
 #endif /* MODULE */
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index 13c293b..4cceaac 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -1155,7 +1155,7 @@
 #ifdef MODULE
 static struct net_device *atarilance_dev;
 
-int __init init_module(void)
+static int __init atarilance_module_init(void)
 {
 	atarilance_dev = atarilance_probe(-1);
 	if (IS_ERR(atarilance_dev))
@@ -1163,13 +1163,14 @@
 	return 0;
 }
 
-void __exit cleanup_module(void)
+static void __exit atarilance_module_exit(void)
 {
 	unregister_netdev(atarilance_dev);
 	free_irq(atarilance_dev->irq, atarilance_dev);
 	free_netdev(atarilance_dev);
 }
-
+module_init(atarilance_module_init);
+module_exit(atarilance_module_exit);
 #endif /* MODULE */
 
 
diff --git a/drivers/net/atl1/Makefile b/drivers/net/atl1/Makefile
deleted file mode 100644
index a6b707e..0000000
--- a/drivers/net/atl1/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_ATL1)	+= atl1.o
-atl1-y			+= atl1_main.o atl1_hw.o atl1_ethtool.o atl1_param.o
diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
deleted file mode 100644
index ff4765f6..0000000
--- a/drivers/net/atl1/atl1.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef _ATL1_H_
-#define _ATL1_H_
-
-#include <linux/types.h>
-#include <linux/if_vlan.h>
-
-#include "atl1_hw.h"
-
-/* function prototypes needed by multiple files */
-s32 atl1_up(struct atl1_adapter *adapter);
-void atl1_down(struct atl1_adapter *adapter);
-int atl1_reset(struct atl1_adapter *adapter);
-s32 atl1_setup_ring_resources(struct atl1_adapter *adapter);
-void atl1_free_ring_resources(struct atl1_adapter *adapter);
-
-extern char atl1_driver_name[];
-extern char atl1_driver_version[];
-extern const struct ethtool_ops atl1_ethtool_ops;
-
-struct atl1_adapter;
-
-#define ATL1_MAX_INTR		3
-#define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */
-
-#define ATL1_DEFAULT_TPD	256
-#define ATL1_MAX_TPD		1024
-#define ATL1_MIN_TPD		64
-#define ATL1_DEFAULT_RFD	512
-#define ATL1_MIN_RFD		128
-#define ATL1_MAX_RFD		2048
-
-#define ATL1_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
-#define ATL1_RFD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_free_desc)
-#define ATL1_TPD_DESC(R, i)	ATL1_GET_DESC(R, i, struct tx_packet_desc)
-#define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
-
-/*
- * This detached comment is preserved for documentation purposes only.
- * It was originally attached to some code that got deleted, but seems
- * important enough to keep around...
- *
- * <begin detached comment>
- * Some workarounds require millisecond delays and are run during interrupt
- * context.  Most notably, when establishing link, the phy may need tweaking
- * but cannot process phy register reads/writes faster than millisecond
- * intervals...and we establish link due to a "link status change" interrupt.
- * <end detached comment>
- */
-
-/*
- * atl1_ring_header represents a single, contiguous block of DMA space
- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
- * message blocks (cmb, smb) described below
- */
-struct atl1_ring_header {
-	void *desc;		/* virtual address */
-	dma_addr_t dma;		/* physical address*/
-	unsigned int size;	/* length in bytes */
-};
-
-/*
- * atl1_buffer is wrapper around a pointer to a socket buffer
- * so a DMA handle can be stored along with the skb
- */
-struct atl1_buffer {
-	struct sk_buff *skb;	/* socket buffer */
-	u16 length;		/* rx buffer length */
-	u16 alloced;		/* 1 if skb allocated */
-	dma_addr_t dma;
-};
-
-/* transmit packet descriptor (tpd) ring */
-struct atl1_tpd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	u16 size;		/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	u16 hw_idx;		/* hardware index */
-	atomic_t next_to_clean;
-	atomic_t next_to_use;
-	struct atl1_buffer *buffer_info;
-};
-
-/* receive free descriptor (rfd) ring */
-struct atl1_rfd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	u16 size;		/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	atomic_t next_to_use;
-	u16 next_to_clean;
-	struct atl1_buffer *buffer_info;
-};
-
-/* receive return descriptor (rrd) ring */
-struct atl1_rrd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	unsigned int size;	/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	u16 next_to_use;
-	atomic_t next_to_clean;
-};
-
-/* coalescing message block (cmb) */
-struct atl1_cmb {
-	struct coals_msg_block *cmb;
-	dma_addr_t dma;
-};
-
-/* statistics message block (smb) */
-struct atl1_smb {
-	struct stats_msg_block *smb;
-	dma_addr_t dma;
-};
-
-/* Statistics counters */
-struct atl1_sft_stats {
-	u64 rx_packets;
-	u64 tx_packets;
-	u64 rx_bytes;
-	u64 tx_bytes;
-	u64 multicast;
-	u64 collisions;
-	u64 rx_errors;
-	u64 rx_length_errors;
-	u64 rx_crc_errors;
-	u64 rx_frame_errors;
-	u64 rx_fifo_errors;
-	u64 rx_missed_errors;
-	u64 tx_errors;
-	u64 tx_fifo_errors;
-	u64 tx_aborted_errors;
-	u64 tx_window_errors;
-	u64 tx_carrier_errors;
-	u64 tx_pause;		/* num pause packets transmitted. */
-	u64 excecol;		/* num tx packets w/ excessive collisions. */
-	u64 deffer;		/* num tx packets deferred */
-	u64 scc;		/* num packets subsequently transmitted
-				 * successfully w/ single prior collision. */
-	u64 mcc;		/* num packets subsequently transmitted
-				 * successfully w/ multiple prior collisions. */
-	u64 latecol;		/* num tx packets  w/ late collisions. */
-	u64 tx_underun;		/* num tx packets aborted due to transmit
-				 * FIFO underrun, or TRD FIFO underrun */
-	u64 tx_trunc;		/* num tx packets truncated due to size
-				 * exceeding MTU, regardless whether truncated
-				 * by the chip or not. (The name doesn't really
-				 * reflect the meaning in this case.) */
-	u64 rx_pause;		/* num Pause packets received. */
-	u64 rx_rrd_ov;
-	u64 rx_trunc;
-};
-
-/* hardware structure */
-struct atl1_hw {
-	u8 __iomem *hw_addr;
-	struct atl1_adapter *back;
-	enum atl1_dma_order dma_ord;
-	enum atl1_dma_rcb rcb_value;
-	enum atl1_dma_req_block dmar_block;
-	enum atl1_dma_req_block dmaw_block;
-	u8 preamble_len;
-	u8 max_retry;		/* Retransmission maximum, after which the
-				 * packet will be discarded */
-	u8 jam_ipg;		/* IPG to start JAM for collision based flow
-				 * control in half-duplex mode. In units of
-				 * 8-bit time */
-	u8 ipgt;		/* Desired back to back inter-packet gap.
-				 * The default is 96-bit time */
-	u8 min_ifg;		/* Minimum number of IFG to enforce in between
-				 * receive frames. Frame gap below such IFP
-				 * is dropped */
-	u8 ipgr1;		/* 64bit Carrier-Sense window */
-	u8 ipgr2;		/* 96-bit IPG window */
-	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
-				 * burst. Each TPD is 16 bytes long */
-	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
-				 * burst. Each RFD is 12 bytes long */
-	u8 rfd_fetch_gap;
-	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
-				 * in a burst. Each RRD is 16 bytes long */
-	u8 tpd_fetch_th;
-	u8 tpd_fetch_gap;
-	u16 tx_jumbo_task_th;
-	u16 txf_burst;		/* Number of data bytes to read in a cache-
-				 * aligned burst. Each SRAM entry is 8 bytes */
-	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
-				 * packets should add 4 bytes */
-	u16 rx_jumbo_lkah;
-	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
-				 * every 512ns passes. */
-	u16 lcol;		/* Collision Window */
-
-	u16 cmb_tpd;
-	u16 cmb_rrd;
-	u16 cmb_rx_timer;
-	u16 cmb_tx_timer;
-	u32 smb_timer;
-	u16 media_type;
-	u16 autoneg_advertised;
-
-	u16 mii_autoneg_adv_reg;
-	u16 mii_1000t_ctrl_reg;
-
-	u32 max_frame_size;
-	u32 min_frame_size;
-
-	u16 dev_rev;
-
-	/* spi flash */
-	u8 flash_vendor;
-
-	u8 mac_addr[ETH_ALEN];
-	u8 perm_mac_addr[ETH_ALEN];
-
-	bool phy_configured;
-};
-
-struct atl1_adapter {
-	struct net_device *netdev;
-	struct pci_dev *pdev;
-	struct net_device_stats net_stats;
-	struct atl1_sft_stats soft_stats;
-	struct vlan_group *vlgrp;
-	u32 rx_buffer_len;
-	u32 wol;
-	u16 link_speed;
-	u16 link_duplex;
-	spinlock_t lock;
-	struct work_struct tx_timeout_task;
-	struct work_struct link_chg_task;
-	struct work_struct pcie_dma_to_rst_task;
-	struct timer_list watchdog_timer;
-	struct timer_list phy_config_timer;
-	bool phy_timer_pending;
-
-	/* all descriptor rings' memory */
-	struct atl1_ring_header ring_header;
-
-	/* TX */
-	struct atl1_tpd_ring tpd_ring;
-	spinlock_t mb_lock;
-
-	/* RX */
-	struct atl1_rfd_ring rfd_ring;
-	struct atl1_rrd_ring rrd_ring;
-	u64 hw_csum_err;
-	u64 hw_csum_good;
-
-	u16 imt;	/* interrupt moderator timer (2us resolution */
-	u16 ict;	/* interrupt clear timer (2us resolution */
-	struct mii_if_info mii;		/* MII interface info */
-
-	/* structs defined in atl1_hw.h */
-	u32 bd_number;			/* board number */
-	bool pci_using_64;
-	struct atl1_hw hw;
-	struct atl1_smb smb;
-	struct atl1_cmb cmb;
-};
-
-#endif	/* _ATL1_H_ */
diff --git a/drivers/net/atl1/atl1_ethtool.c b/drivers/net/atl1/atl1_ethtool.c
deleted file mode 100644
index 68a83be..0000000
--- a/drivers/net/atl1/atl1_ethtool.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/ethtool.h>
-#include <linux/netdevice.h>
-#include <linux/mii.h>
-#include <asm/uaccess.h>
-
-#include "atl1.h"
-
-struct atl1_stats {
-	char stat_string[ETH_GSTRING_LEN];
-	int sizeof_stat;
-	int stat_offset;
-};
-
-#define ATL1_STAT(m) sizeof(((struct atl1_adapter *)0)->m), \
-	offsetof(struct atl1_adapter, m)
-
-static struct atl1_stats atl1_gstrings_stats[] = {
-	{"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
-	{"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
-	{"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
-	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
-	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
-	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
-	{"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
-	{"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
-	{"multicast", ATL1_STAT(soft_stats.multicast)},
-	{"collisions", ATL1_STAT(soft_stats.collisions)},
-	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
-	{"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
-	{"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
-	{"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
-	{"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
-	{"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
-	{"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
-	{"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
-	{"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
-	{"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
-	{"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
-	{"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
-	{"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
-	{"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
-	{"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
-	{"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
-	{"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
-	{"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
-	{"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
-	{"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
-	{"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
-};
-
-static void atl1_get_ethtool_stats(struct net_device *netdev,
-				struct ethtool_stats *stats, u64 *data)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int i;
-	char *p;
-
-	for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
-		p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
-		data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
-			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
-	}
-
-}
-
-static int atl1_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(atl1_gstrings_stats);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static int atl1_get_settings(struct net_device *netdev,
-				struct ethtool_cmd *ecmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	ecmd->supported = (SUPPORTED_10baseT_Half |
-			   SUPPORTED_10baseT_Full |
-			   SUPPORTED_100baseT_Half |
-			   SUPPORTED_100baseT_Full |
-			   SUPPORTED_1000baseT_Full |
-			   SUPPORTED_Autoneg | SUPPORTED_TP);
-	ecmd->advertising = ADVERTISED_TP;
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
-		ecmd->advertising |= ADVERTISED_Autoneg;
-		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
-			ecmd->advertising |= ADVERTISED_Autoneg;
-			ecmd->advertising |=
-			    (ADVERTISED_10baseT_Half |
-			     ADVERTISED_10baseT_Full |
-			     ADVERTISED_100baseT_Half |
-			     ADVERTISED_100baseT_Full |
-			     ADVERTISED_1000baseT_Full);
-		}
-		else
-			ecmd->advertising |= (ADVERTISED_1000baseT_Full);
-	}
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (netif_carrier_ok(adapter->netdev)) {
-		u16 link_speed, link_duplex;
-		atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
-		ecmd->speed = link_speed;
-		if (link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
-		else
-			ecmd->duplex = DUPLEX_HALF;
-	} else {
-		ecmd->speed = -1;
-		ecmd->duplex = -1;
-	}
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
-		ecmd->autoneg = AUTONEG_ENABLE;
-	else
-		ecmd->autoneg = AUTONEG_DISABLE;
-
-	return 0;
-}
-
-static int atl1_set_settings(struct net_device *netdev,
-				struct ethtool_cmd *ecmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	u16 phy_data;
-	int ret_val = 0;
-	u16 old_media_type = hw->media_type;
-
-	if (netif_running(adapter->netdev)) {
-		dev_dbg(&adapter->pdev->dev, "ethtool shutting down adapter\n");
-		atl1_down(adapter);
-	}
-
-	if (ecmd->autoneg == AUTONEG_ENABLE)
-		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
-	else {
-		if (ecmd->speed == SPEED_1000) {
-			if (ecmd->duplex != DUPLEX_FULL) {
-				dev_warn(&adapter->pdev->dev,
-					"can't force to 1000M half duplex\n");
-				ret_val = -EINVAL;
-				goto exit_sset;
-			}
-			hw->media_type = MEDIA_TYPE_1000M_FULL;
-		} else if (ecmd->speed == SPEED_100) {
-			if (ecmd->duplex == DUPLEX_FULL) {
-				hw->media_type = MEDIA_TYPE_100M_FULL;
-			} else
-				hw->media_type = MEDIA_TYPE_100M_HALF;
-		} else {
-			if (ecmd->duplex == DUPLEX_FULL)
-				hw->media_type = MEDIA_TYPE_10M_FULL;
-			else
-				hw->media_type = MEDIA_TYPE_10M_HALF;
-		}
-	}
-	switch (hw->media_type) {
-	case MEDIA_TYPE_AUTO_SENSOR:
-		ecmd->advertising =
-		    ADVERTISED_10baseT_Half |
-		    ADVERTISED_10baseT_Full |
-		    ADVERTISED_100baseT_Half |
-		    ADVERTISED_100baseT_Full |
-		    ADVERTISED_1000baseT_Full |
-		    ADVERTISED_Autoneg | ADVERTISED_TP;
-		break;
-	case MEDIA_TYPE_1000M_FULL:
-		ecmd->advertising =
-		    ADVERTISED_1000baseT_Full |
-		    ADVERTISED_Autoneg | ADVERTISED_TP;
-		break;
-	default:
-		ecmd->advertising = 0;
-		break;
-	}
-	if (atl1_phy_setup_autoneg_adv(hw)) {
-		ret_val = -EINVAL;
-		dev_warn(&adapter->pdev->dev,
-			"invalid ethtool speed/duplex setting\n");
-		goto exit_sset;
-	}
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
-		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
-	else {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			    MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:	/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-	}
-	atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-exit_sset:
-	if (ret_val)
-		hw->media_type = old_media_type;
-
-	if (netif_running(adapter->netdev)) {
-		dev_dbg(&adapter->pdev->dev, "ethtool starting adapter\n");
-		atl1_up(adapter);
-	} else if (!ret_val) {
-		dev_dbg(&adapter->pdev->dev, "ethtool resetting adapter\n");
-		atl1_reset(adapter);
-	}
-	return ret_val;
-}
-
-static void atl1_get_drvinfo(struct net_device *netdev,
-				struct ethtool_drvinfo *drvinfo)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	strncpy(drvinfo->driver, atl1_driver_name, sizeof(drvinfo->driver));
-	strncpy(drvinfo->version, atl1_driver_version,
-		sizeof(drvinfo->version));
-	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
-		sizeof(drvinfo->bus_info));
-	drvinfo->eedump_len = ATL1_EEDUMP_LEN;
-}
-
-static void atl1_get_wol(struct net_device *netdev,
-			    struct ethtool_wolinfo *wol)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
-	wol->wolopts = 0;
-	if (adapter->wol & ATL1_WUFC_EX)
-		wol->wolopts |= WAKE_UCAST;
-	if (adapter->wol & ATL1_WUFC_MC)
-		wol->wolopts |= WAKE_MCAST;
-	if (adapter->wol & ATL1_WUFC_BC)
-		wol->wolopts |= WAKE_BCAST;
-	if (adapter->wol & ATL1_WUFC_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-	return;
-}
-
-static int atl1_set_wol(struct net_device *netdev,
-			struct ethtool_wolinfo *wol)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
-		return -EOPNOTSUPP;
-	adapter->wol = 0;
-	if (wol->wolopts & WAKE_UCAST)
-		adapter->wol |= ATL1_WUFC_EX;
-	if (wol->wolopts & WAKE_MCAST)
-		adapter->wol |= ATL1_WUFC_MC;
-	if (wol->wolopts & WAKE_BCAST)
-		adapter->wol |= ATL1_WUFC_BC;
-	if (wol->wolopts & WAKE_MAGIC)
-		adapter->wol |= ATL1_WUFC_MAG;
-	return 0;
-}
-
-static void atl1_get_ringparam(struct net_device *netdev,
-			    struct ethtool_ringparam *ring)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
-
-	ring->rx_max_pending = ATL1_MAX_RFD;
-	ring->tx_max_pending = ATL1_MAX_TPD;
-	ring->rx_mini_max_pending = 0;
-	ring->rx_jumbo_max_pending = 0;
-	ring->rx_pending = rxdr->count;
-	ring->tx_pending = txdr->count;
-	ring->rx_mini_pending = 0;
-	ring->rx_jumbo_pending = 0;
-}
-
-static int atl1_set_ringparam(struct net_device *netdev,
-				struct ethtool_ringparam *ring)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
-	struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
-	struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
-
-	struct atl1_tpd_ring tpd_old, tpd_new;
-	struct atl1_rfd_ring rfd_old, rfd_new;
-	struct atl1_rrd_ring rrd_old, rrd_new;
-	struct atl1_ring_header rhdr_old, rhdr_new;
-	int err;
-
-	tpd_old = adapter->tpd_ring;
-	rfd_old = adapter->rfd_ring;
-	rrd_old = adapter->rrd_ring;
-	rhdr_old = adapter->ring_header;
-
-	if (netif_running(adapter->netdev))
-		atl1_down(adapter);
-
-	rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
-	rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
-			rfdr->count;
-	rfdr->count = (rfdr->count + 3) & ~3;
-	rrdr->count = rfdr->count;
-
-	tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
-	tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
-			tpdr->count;
-	tpdr->count = (tpdr->count + 3) & ~3;
-
-	if (netif_running(adapter->netdev)) {
-		/* try to get new resources before deleting old */
-		err = atl1_setup_ring_resources(adapter);
-		if (err)
-			goto err_setup_ring;
-
-		/*
-		 * save the new, restore the old in order to free it,
-		 * then restore the new back again
-		 */
-
-		rfd_new = adapter->rfd_ring;
-		rrd_new = adapter->rrd_ring;
-		tpd_new = adapter->tpd_ring;
-		rhdr_new = adapter->ring_header;
-		adapter->rfd_ring = rfd_old;
-		adapter->rrd_ring = rrd_old;
-		adapter->tpd_ring = tpd_old;
-		adapter->ring_header = rhdr_old;
-		atl1_free_ring_resources(adapter);
-		adapter->rfd_ring = rfd_new;
-		adapter->rrd_ring = rrd_new;
-		adapter->tpd_ring = tpd_new;
-		adapter->ring_header = rhdr_new;
-
-		err = atl1_up(adapter);
-		if (err)
-			return err;
-	}
-	return 0;
-
-err_setup_ring:
-	adapter->rfd_ring = rfd_old;
-	adapter->rrd_ring = rrd_old;
-	adapter->tpd_ring = tpd_old;
-	adapter->ring_header = rhdr_old;
-	atl1_up(adapter);
-	return err;
-}
-
-static void atl1_get_pauseparam(struct net_device *netdev,
-			     struct ethtool_pauseparam *epause)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
-		epause->autoneg = AUTONEG_ENABLE;
-	} else {
-		epause->autoneg = AUTONEG_DISABLE;
-	}
-	epause->rx_pause = 1;
-	epause->tx_pause = 1;
-}
-
-static int atl1_set_pauseparam(struct net_device *netdev,
-			     struct ethtool_pauseparam *epause)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
-		epause->autoneg = AUTONEG_ENABLE;
-	} else {
-		epause->autoneg = AUTONEG_DISABLE;
-	}
-
-	epause->rx_pause = 1;
-	epause->tx_pause = 1;
-
-	return 0;
-}
-
-static u32 atl1_get_rx_csum(struct net_device *netdev)
-{
-	return 1;
-}
-
-static void atl1_get_strings(struct net_device *netdev, u32 stringset,
-				u8 *data)
-{
-	u8 *p = data;
-	int i;
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
-			memcpy(p, atl1_gstrings_stats[i].stat_string,
-				ETH_GSTRING_LEN);
-			p += ETH_GSTRING_LEN;
-		}
-		break;
-	}
-}
-
-static int atl1_nway_reset(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	if (netif_running(netdev)) {
-		u16 phy_data;
-		atl1_down(adapter);
-
-		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-			hw->media_type == MEDIA_TYPE_1000M_FULL) {
-			phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
-		} else {
-			switch (hw->media_type) {
-			case MEDIA_TYPE_100M_FULL:
-				phy_data = MII_CR_FULL_DUPLEX |
-					MII_CR_SPEED_100 | MII_CR_RESET;
-				break;
-			case MEDIA_TYPE_100M_HALF:
-				phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-				break;
-			case MEDIA_TYPE_10M_FULL:
-				phy_data = MII_CR_FULL_DUPLEX |
-					MII_CR_SPEED_10 | MII_CR_RESET;
-				break;
-			default:  /* MEDIA_TYPE_10M_HALF */
-				phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			}
-		}
-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-		atl1_up(adapter);
-	}
-	return 0;
-}
-
-const struct ethtool_ops atl1_ethtool_ops = {
-	.get_settings		= atl1_get_settings,
-	.set_settings		= atl1_set_settings,
-	.get_drvinfo		= atl1_get_drvinfo,
-	.get_wol		= atl1_get_wol,
-	.set_wol		= atl1_set_wol,
-	.get_ringparam		= atl1_get_ringparam,
-	.set_ringparam		= atl1_set_ringparam,
-	.get_pauseparam		= atl1_get_pauseparam,
-	.set_pauseparam 	= atl1_set_pauseparam,
-	.get_rx_csum		= atl1_get_rx_csum,
-	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
-	.get_link		= ethtool_op_get_link,
-	.set_sg			= ethtool_op_set_sg,
-	.get_strings		= atl1_get_strings,
-	.nway_reset		= atl1_nway_reset,
-	.get_ethtool_stats	= atl1_get_ethtool_stats,
-	.get_sset_count		= atl1_get_sset_count,
-	.set_tso		= ethtool_op_set_tso,
-};
diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c
deleted file mode 100644
index 9d3bd22..0000000
--- a/drivers/net/atl1/atl1_hw.c
+++ /dev/null
@@ -1,720 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/if_vlan.h>
-#include <linux/etherdevice.h>
-#include <linux/crc32.h>
-#include <asm/byteorder.h>
-
-#include "atl1.h"
-
-/*
- * Reset the transmit and receive units; mask and clear all interrupts.
- * hw - Struct containing variables accessed by shared code
- * return : ATL1_SUCCESS  or  idle status (if error)
- */
-s32 atl1_reset_hw(struct atl1_hw *hw)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	u32 icr;
-	int i;
-
-	/*
-	 * Clear Interrupt mask to stop board from generating
-	 * interrupts & Clear any pending interrupt events
-	 */
-	/*
-	 * iowrite32(0, hw->hw_addr + REG_IMR);
-	 * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
-	 */
-
-	/*
-	 * Issue Soft Reset to the MAC.  This will reset the chip's
-	 * transmit, receive, DMA.  It will not effect
-	 * the current PCI configuration.  The global reset bit is self-
-	 * clearing, and should clear within a microsecond.
-	 */
-	iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
-	ioread32(hw->hw_addr + REG_MASTER_CTRL);
-
-	iowrite16(1, hw->hw_addr + REG_GPHY_ENABLE);
-	ioread16(hw->hw_addr + REG_GPHY_ENABLE);
-
-	msleep(1);		/* delay about 1ms */
-
-	/* Wait at least 10ms for All module to be Idle */
-	for (i = 0; i < 10; i++) {
-		icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
-		if (!icr)
-			break;
-		msleep(1);	/* delay 1 ms */
-		cpu_relax();	/* FIXME: is this still the right way to do this? */
-	}
-
-	if (icr) {
-		dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
-		return icr;
-	}
-
-	return ATL1_SUCCESS;
-}
-
-/* function about EEPROM
- *
- * check_eeprom_exist
- * return 0 if eeprom exist
- */
-static int atl1_check_eeprom_exist(struct atl1_hw *hw)
-{
-	u32 value;
-	value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
-	if (value & SPI_FLASH_CTRL_EN_VPD) {
-		value &= ~SPI_FLASH_CTRL_EN_VPD;
-		iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
-	}
-
-	value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
-	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
-}
-
-static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
-{
-	int i;
-	u32 control;
-
-	if (offset & 3)
-		return false;	/* address do not align */
-
-	iowrite32(0, hw->hw_addr + REG_VPD_DATA);
-	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
-	iowrite32(control, hw->hw_addr + REG_VPD_CAP);
-	ioread32(hw->hw_addr + REG_VPD_CAP);
-
-	for (i = 0; i < 10; i++) {
-		msleep(2);
-		control = ioread32(hw->hw_addr + REG_VPD_CAP);
-		if (control & VPD_CAP_VPD_FLAG)
-			break;
-	}
-	if (control & VPD_CAP_VPD_FLAG) {
-		*p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
-		return true;
-	}
-	return false;		/* timeout */
-}
-
-/*
- * Reads the value from a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to read
- */
-s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
-{
-	u32 val;
-	int i;
-
-	val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
-		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
-		MDIO_CLK_SEL_SHIFT;
-	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
-	ioread32(hw->hw_addr + REG_MDIO_CTRL);
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-	}
-	if (!(val & (MDIO_START | MDIO_BUSY))) {
-		*phy_data = (u16) val;
-		return ATL1_SUCCESS;
-	}
-	return ATL1_ERR_PHY;
-}
-
-#define CUSTOM_SPI_CS_SETUP	2
-#define CUSTOM_SPI_CLK_HI	2
-#define CUSTOM_SPI_CLK_LO	2
-#define CUSTOM_SPI_CS_HOLD	2
-#define CUSTOM_SPI_CS_HI	3
-
-static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
-{
-	int i;
-	u32 value;
-
-	iowrite32(0, hw->hw_addr + REG_SPI_DATA);
-	iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
-
-	value = SPI_FLASH_CTRL_WAIT_READY |
-	    (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
-	    SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
-					     SPI_FLASH_CTRL_CLK_HI_MASK) <<
-	    SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
-					   SPI_FLASH_CTRL_CLK_LO_MASK) <<
-	    SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
-					   SPI_FLASH_CTRL_CS_HOLD_MASK) <<
-	    SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
-					    SPI_FLASH_CTRL_CS_HI_MASK) <<
-	    SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
-	    SPI_FLASH_CTRL_INS_SHIFT;
-
-	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
-
-	value |= SPI_FLASH_CTRL_START;
-	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
-	ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
-
-	for (i = 0; i < 10; i++) {
-		msleep(1);	/* 1ms */
-		value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
-		if (!(value & SPI_FLASH_CTRL_START))
-			break;
-	}
-
-	if (value & SPI_FLASH_CTRL_START)
-		return false;
-
-	*buf = ioread32(hw->hw_addr + REG_SPI_DATA);
-
-	return true;
-}
-
-/*
- * get_permanent_address
- * return 0 if get valid mac address,
- */
-static int atl1_get_permanent_address(struct atl1_hw *hw)
-{
-	u32 addr[2];
-	u32 i, control;
-	u16 reg;
-	u8 eth_addr[ETH_ALEN];
-	bool key_valid;
-
-	if (is_valid_ether_addr(hw->perm_mac_addr))
-		return 0;
-
-	/* init */
-	addr[0] = addr[1] = 0;
-
-	if (!atl1_check_eeprom_exist(hw)) {	/* eeprom exist */
-		reg = 0;
-		key_valid = false;
-		/* Read out all EEPROM content */
-		i = 0;
-		while (1) {
-			if (atl1_read_eeprom(hw, i + 0x100, &control)) {
-				if (key_valid) {
-					if (reg == REG_MAC_STA_ADDR)
-						addr[0] = control;
-					else if (reg == (REG_MAC_STA_ADDR + 4))
-						addr[1] = control;
-					key_valid = false;
-				} else if ((control & 0xff) == 0x5A) {
-					key_valid = true;
-					reg = (u16) (control >> 16);
-				} else
-					break;	/* assume data end while encount an invalid KEYWORD */
-			} else
-				break;	/* read error */
-			i += 4;
-		}
-
-		*(u32 *) &eth_addr[2] = swab32(addr[0]);
-		*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
-		if (is_valid_ether_addr(eth_addr)) {
-			memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-			return 0;
-		}
-		return 1;
-	}
-
-	/* see if SPI FLAGS exist ? */
-	addr[0] = addr[1] = 0;
-	reg = 0;
-	key_valid = false;
-	i = 0;
-	while (1) {
-		if (atl1_spi_read(hw, i + 0x1f000, &control)) {
-			if (key_valid) {
-				if (reg == REG_MAC_STA_ADDR)
-					addr[0] = control;
-				else if (reg == (REG_MAC_STA_ADDR + 4))
-					addr[1] = control;
-				key_valid = false;
-			} else if ((control & 0xff) == 0x5A) {
-				key_valid = true;
-				reg = (u16) (control >> 16);
-			} else
-				break;	/* data end */
-		} else
-			break;	/* read error */
-		i += 4;
-	}
-
-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
-	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
-	if (is_valid_ether_addr(eth_addr)) {
-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-		return 0;
-	}
-
-	/*
-	 * On some motherboards, the MAC address is written by the
-	 * BIOS directly to the MAC register during POST, and is
-	 * not stored in eeprom.  If all else thus far has failed
-	 * to fetch the permanent MAC address, try reading it directly.
-	 */
-	addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
-	addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
-	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
-	if (is_valid_ether_addr(eth_addr)) {
-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-		return 0;
-	}
-
-	return 1;
-}
-
-/*
- * Reads the adapter's MAC address from the EEPROM
- * hw - Struct containing variables accessed by shared code
- */
-s32 atl1_read_mac_addr(struct atl1_hw *hw)
-{
-	u16 i;
-
-	if (atl1_get_permanent_address(hw))
-		random_ether_addr(hw->perm_mac_addr);
-
-	for (i = 0; i < ETH_ALEN; i++)
-		hw->mac_addr[i] = hw->perm_mac_addr[i];
-	return ATL1_SUCCESS;
-}
-
-/*
- * Hashes an address to determine its location in the multicast table
- * hw - Struct containing variables accessed by shared code
- * mc_addr - the multicast address to hash
- *
- * atl1_hash_mc_addr
- *  purpose
- *      set hash value for a multicast address
- *      hash calcu processing :
- *          1. calcu 32bit CRC for multicast address
- *          2. reverse crc with MSB to LSB
- */
-u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
-{
-	u32 crc32, value = 0;
-	int i;
-
-	crc32 = ether_crc_le(6, mc_addr);
-	for (i = 0; i < 32; i++)
-		value |= (((crc32 >> i) & 1) << (31 - i));
-
-	return value;
-}
-
-/*
- * Sets the bit in the multicast table corresponding to the hash value.
- * hw - Struct containing variables accessed by shared code
- * hash_value - Multicast address hash value
- */
-void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
-{
-	u32 hash_bit, hash_reg;
-	u32 mta;
-
-	/*
-	 * The HASH Table  is a register array of 2 32-bit registers.
-	 * It is treated like an array of 64 bits.  We want to set
-	 * bit BitArray[hash_value]. So we figure out what register
-	 * the bit is in, read it, OR in the new bit, then write
-	 * back the new value.  The register is determined by the
-	 * upper 7 bits of the hash value and the bit within that
-	 * register are determined by the lower 5 bits of the value.
-	 */
-	hash_reg = (hash_value >> 31) & 0x1;
-	hash_bit = (hash_value >> 26) & 0x1F;
-	mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
-	mta |= (1 << hash_bit);
-	iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
-}
-
-/*
- * Writes a value to a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to write
- * data - data to write to the PHY
- */
-s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
-{
-	int i;
-	u32 val;
-
-	val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
-	    (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
-	    MDIO_SUP_PREAMBLE |
-	    MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
-	ioread32(hw->hw_addr + REG_MDIO_CTRL);
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-	}
-
-	if (!(val & (MDIO_START | MDIO_BUSY)))
-		return ATL1_SUCCESS;
-
-	return ATL1_ERR_PHY;
-}
-
-/*
- * Make L001's PHY out of Power Saving State (bug)
- * hw - Struct containing variables accessed by shared code
- * when power on, L001's PHY always on Power saving State
- * (Gigabit Link forbidden)
- */
-static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
-{
-	s32 ret;
-	ret = atl1_write_phy_reg(hw, 29, 0x0029);
-	if (ret)
-		return ret;
-	return atl1_write_phy_reg(hw, 30, 0);
-}
-
-/*
- *TODO: do something or get rid of this
- */
-s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
-{
-/*    s32 ret_val;
- *    u16 phy_data;
- */
-
-/*
-    ret_val = atl1_write_phy_reg(hw, ...);
-    ret_val = atl1_write_phy_reg(hw, ...);
-    ....
-*/
-	return ATL1_SUCCESS;
-}
-
-/*
- * Resets the PHY and make all config validate
- * hw - Struct containing variables accessed by shared code
- *
- * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
- */
-static s32 atl1_phy_reset(struct atl1_hw *hw)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	s32 ret_val;
-	u16 phy_data;
-
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
-		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
-	else {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			    MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:	/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-	}
-
-	ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-	if (ret_val) {
-		u32 val;
-		int i;
-		/* pcie serdes link may be down! */
-		dev_dbg(&pdev->dev, "pcie phy link down\n");
-
-		for (i = 0; i < 25; i++) {
-			msleep(1);
-			val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
-			if (!(val & (MDIO_START | MDIO_BUSY)))
-				break;
-		}
-
-		if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
-			dev_warn(&pdev->dev, "pcie link down at least 25ms\n");
-			return ret_val;
-		}
-	}
-	return ATL1_SUCCESS;
-}
-
-/*
- * Configures PHY autoneg and flow control advertisement settings
- * hw - Struct containing variables accessed by shared code
- */
-s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
-{
-	s32 ret_val;
-	s16 mii_autoneg_adv_reg;
-	s16 mii_1000t_ctrl_reg;
-
-	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
-	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
-
-	/* Read the MII 1000Base-T Control Register (Address 9). */
-	mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
-
-	/*
-	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
-	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
-	 * the  1000Base-T Control Register (Address 9).
-	 */
-	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
-	mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
-
-	/*
-	 * Need to parse media_type  and set up
-	 * the appropriate PHY registers.
-	 */
-	switch (hw->media_type) {
-	case MEDIA_TYPE_AUTO_SENSOR:
-		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
-					MII_AR_10T_FD_CAPS |
-					MII_AR_100TX_HD_CAPS |
-					MII_AR_100TX_FD_CAPS);
-		mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
-		break;
-
-	case MEDIA_TYPE_1000M_FULL:
-		mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
-		break;
-
-	case MEDIA_TYPE_100M_FULL:
-		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
-		break;
-
-	case MEDIA_TYPE_100M_HALF:
-		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
-		break;
-
-	case MEDIA_TYPE_10M_FULL:
-		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
-		break;
-
-	default:
-		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
-		break;
-	}
-
-	/* flow control fixed to enable all */
-	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
-
-	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
-	hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
-
-	ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = atl1_write_phy_reg(hw, MII_AT001_CR, mii_1000t_ctrl_reg);
-	if (ret_val)
-		return ret_val;
-
-	return ATL1_SUCCESS;
-}
-
-/*
- * Configures link settings.
- * hw - Struct containing variables accessed by shared code
- * Assumes the hardware has previously been reset and the
- * transmitter and receiver are not enabled.
- */
-static s32 atl1_setup_link(struct atl1_hw *hw)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	s32 ret_val;
-
-	/*
-	 * Options:
-	 *  PHY will advertise value(s) parsed from
-	 *  autoneg_advertised and fc
-	 *  no matter what autoneg is , We will not wait link result.
-	 */
-	ret_val = atl1_phy_setup_autoneg_adv(hw);
-	if (ret_val) {
-		dev_dbg(&pdev->dev, "error setting up autonegotiation\n");
-		return ret_val;
-	}
-	/* SW.Reset , En-Auto-Neg if needed */
-	ret_val = atl1_phy_reset(hw);
-	if (ret_val) {
-		dev_dbg(&pdev->dev, "error resetting phy\n");
-		return ret_val;
-	}
-	hw->phy_configured = true;
-	return ret_val;
-}
-
-static struct atl1_spi_flash_dev flash_table[] = {
-/*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SECTOR_ERASE CHIP_ERASE */
-	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,        0x62},
-	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,        0x60},
-	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,        0xC7},
-};
-
-static void atl1_init_flash_opcode(struct atl1_hw *hw)
-{
-	if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
-		hw->flash_vendor = 0;	/* ATMEL */
-
-	/* Init OP table */
-	iowrite8(flash_table[hw->flash_vendor].cmd_program,
-		hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
-	iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
-		hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
-	iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
-		hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
-	iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
-		hw->hw_addr + REG_SPI_FLASH_OP_RDID);
-	iowrite8(flash_table[hw->flash_vendor].cmd_wren,
-		hw->hw_addr + REG_SPI_FLASH_OP_WREN);
-	iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
-		hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
-	iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
-		hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
-	iowrite8(flash_table[hw->flash_vendor].cmd_read,
-		hw->hw_addr + REG_SPI_FLASH_OP_READ);
-}
-
-/*
- * Performs basic configuration of the adapter.
- * hw - Struct containing variables accessed by shared code
- * Assumes that the controller has previously been reset and is in a
- * post-reset uninitialized state. Initializes multicast table,
- * and  Calls routines to setup link
- * Leaves the transmit and receive units disabled and uninitialized.
- */
-s32 atl1_init_hw(struct atl1_hw *hw)
-{
-	u32 ret_val = 0;
-
-	/* Zero out the Multicast HASH table */
-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
-	/* clear the old settings from the multicast hash table */
-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
-
-	atl1_init_flash_opcode(hw);
-
-	if (!hw->phy_configured) {
-		/* enable GPHY LinkChange Interrrupt */
-		ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
-		if (ret_val)
-			return ret_val;
-		/* make PHY out of power-saving state */
-		ret_val = atl1_phy_leave_power_saving(hw);
-		if (ret_val)
-			return ret_val;
-		/* Call a subroutine to configure the link */
-		ret_val = atl1_setup_link(hw);
-	}
-	return ret_val;
-}
-
-/*
- * Detects the current speed and duplex settings of the hardware.
- * hw - Struct containing variables accessed by shared code
- * speed - Speed of the connection
- * duplex - Duplex setting of the connection
- */
-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	s32 ret_val;
-	u16 phy_data;
-
-	/* ; --- Read   PHY Specific Status Register (17) */
-	ret_val = atl1_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
-		return ATL1_ERR_PHY_RES;
-
-	switch (phy_data & MII_AT001_PSSR_SPEED) {
-	case MII_AT001_PSSR_1000MBS:
-		*speed = SPEED_1000;
-		break;
-	case MII_AT001_PSSR_100MBS:
-		*speed = SPEED_100;
-		break;
-	case MII_AT001_PSSR_10MBS:
-		*speed = SPEED_10;
-		break;
-	default:
-		dev_dbg(&pdev->dev, "error getting speed\n");
-		return ATL1_ERR_PHY_SPEED;
-		break;
-	}
-	if (phy_data & MII_AT001_PSSR_DPLX)
-		*duplex = FULL_DUPLEX;
-	else
-		*duplex = HALF_DUPLEX;
-
-	return ATL1_SUCCESS;
-}
-
-void atl1_set_mac_addr(struct atl1_hw *hw)
-{
-	u32 value;
-	/*
-	 * 00-0B-6A-F6-00-DC
-	 * 0:  6AF600DC   1: 000B
-	 * low dword
-	 */
-	value = (((u32) hw->mac_addr[2]) << 24) |
-	    (((u32) hw->mac_addr[3]) << 16) |
-	    (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
-	/* high dword */
-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
-	iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
-}
diff --git a/drivers/net/atl1/atl1_hw.h b/drivers/net/atl1/atl1_hw.h
deleted file mode 100644
index 939aa0f..0000000
--- a/drivers/net/atl1/atl1_hw.h
+++ /dev/null
@@ -1,946 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * There are a lot of defines in here that are unused and/or have cryptic
- * names.  Please leave them alone, as they're the closest thing we have
- * to a spec from Attansic at present. *ahem* -- CHS
- */
-
-#ifndef _ATL1_HW_H_
-#define _ATL1_HW_H_
-
-#include <linux/types.h>
-#include <linux/mii.h>
-
-struct atl1_adapter;
-struct atl1_hw;
-
-/* function prototypes needed by multiple files */
-s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw);
-s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data);
-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
-s32 atl1_read_mac_addr(struct atl1_hw *hw);
-s32 atl1_init_hw(struct atl1_hw *hw);
-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
-s32 atl1_set_speed_and_duplex(struct atl1_hw *hw, u16 speed, u16 duplex);
-u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
-void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
-s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
-void atl1_set_mac_addr(struct atl1_hw *hw);
-s32 atl1_phy_enter_power_saving(struct atl1_hw *hw);
-s32 atl1_reset_hw(struct atl1_hw *hw);
-void atl1_check_options(struct atl1_adapter *adapter);
-
-/* register definitions */
-#define REG_PCIE_CAP_LIST			0x58
-
-#define REG_VPD_CAP				0x6C
-#define VPD_CAP_ID_MASK				0xff
-#define VPD_CAP_ID_SHIFT			0
-#define VPD_CAP_NEXT_PTR_MASK			0xFF
-#define VPD_CAP_NEXT_PTR_SHIFT			8
-#define VPD_CAP_VPD_ADDR_MASK			0x7FFF
-#define VPD_CAP_VPD_ADDR_SHIFT			16
-#define VPD_CAP_VPD_FLAG			0x80000000
-
-#define REG_VPD_DATA				0x70
-
-#define REG_SPI_FLASH_CTRL			0x200
-#define SPI_FLASH_CTRL_STS_NON_RDY		0x1
-#define SPI_FLASH_CTRL_STS_WEN			0x2
-#define SPI_FLASH_CTRL_STS_WPEN			0x80
-#define SPI_FLASH_CTRL_DEV_STS_MASK		0xFF
-#define SPI_FLASH_CTRL_DEV_STS_SHIFT		0
-#define SPI_FLASH_CTRL_INS_MASK			0x7
-#define SPI_FLASH_CTRL_INS_SHIFT		8
-#define SPI_FLASH_CTRL_START			0x800
-#define SPI_FLASH_CTRL_EN_VPD			0x2000
-#define SPI_FLASH_CTRL_LDSTART			0x8000
-#define SPI_FLASH_CTRL_CS_HI_MASK		0x3
-#define SPI_FLASH_CTRL_CS_HI_SHIFT		16
-#define SPI_FLASH_CTRL_CS_HOLD_MASK		0x3
-#define SPI_FLASH_CTRL_CS_HOLD_SHIFT		18
-#define SPI_FLASH_CTRL_CLK_LO_MASK		0x3
-#define SPI_FLASH_CTRL_CLK_LO_SHIFT		20
-#define SPI_FLASH_CTRL_CLK_HI_MASK		0x3
-#define SPI_FLASH_CTRL_CLK_HI_SHIFT		22
-#define SPI_FLASH_CTRL_CS_SETUP_MASK		0x3
-#define SPI_FLASH_CTRL_CS_SETUP_SHIFT		24
-#define SPI_FLASH_CTRL_EROM_PGSZ_MASK		0x3
-#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT		26
-#define SPI_FLASH_CTRL_WAIT_READY		0x10000000
-
-#define REG_SPI_ADDR				0x204
-
-#define REG_SPI_DATA				0x208
-
-#define REG_SPI_FLASH_CONFIG			0x20C
-#define SPI_FLASH_CONFIG_LD_ADDR_MASK		0xFFFFFF
-#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT		0
-#define SPI_FLASH_CONFIG_VPD_ADDR_MASK		0x3
-#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT		24
-#define SPI_FLASH_CONFIG_LD_EXIST		0x4000000
-
-#define REG_SPI_FLASH_OP_PROGRAM		0x210
-#define REG_SPI_FLASH_OP_SC_ERASE		0x211
-#define REG_SPI_FLASH_OP_CHIP_ERASE		0x212
-#define REG_SPI_FLASH_OP_RDID			0x213
-#define REG_SPI_FLASH_OP_WREN			0x214
-#define REG_SPI_FLASH_OP_RDSR			0x215
-#define REG_SPI_FLASH_OP_WRSR			0x216
-#define REG_SPI_FLASH_OP_READ			0x217
-
-#define REG_TWSI_CTRL				0x218
-#define TWSI_CTRL_LD_OFFSET_MASK		0xFF
-#define TWSI_CTRL_LD_OFFSET_SHIFT		0
-#define TWSI_CTRL_LD_SLV_ADDR_MASK		0x7
-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT		8
-#define TWSI_CTRL_SW_LDSTART			0x800
-#define TWSI_CTRL_HW_LDSTART			0x1000
-#define TWSI_CTRL_SMB_SLV_ADDR_MASK		0x7F
-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT		15
-#define TWSI_CTRL_LD_EXIST			0x400000
-#define TWSI_CTRL_READ_FREQ_SEL_MASK		0x3
-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT		23
-#define TWSI_CTRL_FREQ_SEL_100K			0
-#define TWSI_CTRL_FREQ_SEL_200K			1
-#define TWSI_CTRL_FREQ_SEL_300K			2
-#define TWSI_CTRL_FREQ_SEL_400K			3
-#define TWSI_CTRL_SMB_SLV_ADDR
-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK		0x3
-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT		24
-
-#define REG_PCIE_DEV_MISC_CTRL			0x21C
-#define PCIE_DEV_MISC_CTRL_EXT_PIPE		0x2
-#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS		0x1
-#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST		0x4
-#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN	0x8
-#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN	0x10
-
-/* Selene Master Control Register */
-#define REG_MASTER_CTRL				0x1400
-#define MASTER_CTRL_SOFT_RST			0x1
-#define MASTER_CTRL_MTIMER_EN			0x2
-#define MASTER_CTRL_ITIMER_EN			0x4
-#define MASTER_CTRL_MANUAL_INT			0x8
-#define MASTER_CTRL_REV_NUM_SHIFT		16
-#define MASTER_CTRL_REV_NUM_MASK		0xff
-#define MASTER_CTRL_DEV_ID_SHIFT		24
-#define MASTER_CTRL_DEV_ID_MASK			0xff
-
-/* Timer Initial Value Register */
-#define REG_MANUAL_TIMER_INIT			0x1404
-
-/* IRQ ModeratorTimer Initial Value Register */
-#define REG_IRQ_MODU_TIMER_INIT			0x1408
-
-#define REG_GPHY_ENABLE				0x140C
-
-/* IRQ Anti-Lost Timer Initial Value Register */
-#define REG_CMBDISDMA_TIMER			0x140E
-
-/* Block IDLE Status Register */
-#define REG_IDLE_STATUS				0x1410
-#define IDLE_STATUS_RXMAC			1
-#define IDLE_STATUS_TXMAC			2
-#define IDLE_STATUS_RXQ				4
-#define IDLE_STATUS_TXQ				8
-#define IDLE_STATUS_DMAR			0x10
-#define IDLE_STATUS_DMAW			0x20
-#define IDLE_STATUS_SMB				0x40
-#define IDLE_STATUS_CMB				0x80
-
-/* MDIO Control Register */
-#define REG_MDIO_CTRL				0x1414
-#define MDIO_DATA_MASK				0xffff
-#define MDIO_DATA_SHIFT				0
-#define MDIO_REG_ADDR_MASK			0x1f
-#define MDIO_REG_ADDR_SHIFT			16
-#define MDIO_RW					0x200000
-#define MDIO_SUP_PREAMBLE			0x400000
-#define MDIO_START				0x800000
-#define MDIO_CLK_SEL_SHIFT			24
-#define MDIO_CLK_25_4				0
-#define MDIO_CLK_25_6				2
-#define MDIO_CLK_25_8				3
-#define MDIO_CLK_25_10				4
-#define MDIO_CLK_25_14				5
-#define MDIO_CLK_25_20				6
-#define MDIO_CLK_25_28				7
-#define MDIO_BUSY				0x8000000
-#define MDIO_WAIT_TIMES				30
-
-/* MII PHY Status Register */
-#define REG_PHY_STATUS				0x1418
-
-/* BIST Control and Status Register0 (for the Packet Memory) */
-#define REG_BIST0_CTRL				0x141c
-#define BIST0_NOW				0x1
-#define BIST0_SRAM_FAIL				0x2
-#define BIST0_FUSE_FLAG				0x4
-#define REG_BIST1_CTRL				0x1420
-#define BIST1_NOW				0x1
-#define BIST1_SRAM_FAIL				0x2
-#define BIST1_FUSE_FLAG				0x4
-
-/* MAC Control Register */
-#define REG_MAC_CTRL				0x1480
-#define MAC_CTRL_TX_EN				1
-#define MAC_CTRL_RX_EN				2
-#define MAC_CTRL_TX_FLOW			4
-#define MAC_CTRL_RX_FLOW			8
-#define MAC_CTRL_LOOPBACK			0x10
-#define MAC_CTRL_DUPLX				0x20
-#define MAC_CTRL_ADD_CRC			0x40
-#define MAC_CTRL_PAD				0x80
-#define MAC_CTRL_LENCHK				0x100
-#define MAC_CTRL_HUGE_EN			0x200
-#define MAC_CTRL_PRMLEN_SHIFT			10
-#define MAC_CTRL_PRMLEN_MASK			0xf
-#define MAC_CTRL_RMV_VLAN			0x4000
-#define MAC_CTRL_PROMIS_EN			0x8000
-#define MAC_CTRL_TX_PAUSE			0x10000
-#define MAC_CTRL_SCNT				0x20000
-#define MAC_CTRL_SRST_TX			0x40000
-#define MAC_CTRL_TX_SIMURST			0x80000
-#define MAC_CTRL_SPEED_SHIFT			20
-#define MAC_CTRL_SPEED_MASK			0x300000
-#define MAC_CTRL_SPEED_1000			2
-#define MAC_CTRL_SPEED_10_100			1
-#define MAC_CTRL_DBG_TX_BKPRESURE		0x400000
-#define MAC_CTRL_TX_HUGE			0x800000
-#define MAC_CTRL_RX_CHKSUM_EN			0x1000000
-#define MAC_CTRL_MC_ALL_EN			0x2000000
-#define MAC_CTRL_BC_EN				0x4000000
-#define MAC_CTRL_DBG				0x8000000
-
-/* MAC IPG/IFG Control Register */
-#define REG_MAC_IPG_IFG				0x1484
-#define MAC_IPG_IFG_IPGT_SHIFT			0
-#define MAC_IPG_IFG_IPGT_MASK			0x7f
-#define MAC_IPG_IFG_MIFG_SHIFT			8
-#define MAC_IPG_IFG_MIFG_MASK			0xff
-#define MAC_IPG_IFG_IPGR1_SHIFT			16
-#define MAC_IPG_IFG_IPGR1_MASK			0x7f
-#define MAC_IPG_IFG_IPGR2_SHIFT			24
-#define MAC_IPG_IFG_IPGR2_MASK			0x7f
-
-/* MAC STATION ADDRESS */
-#define REG_MAC_STA_ADDR			0x1488
-
-/* Hash table for multicast address */
-#define REG_RX_HASH_TABLE			0x1490
-
-/* MAC Half-Duplex Control Register */
-#define REG_MAC_HALF_DUPLX_CTRL			0x1498
-#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT		0
-#define MAC_HALF_DUPLX_CTRL_LCOL_MASK		0x3ff
-#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT		12
-#define MAC_HALF_DUPLX_CTRL_RETRY_MASK		0xf
-#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN		0x10000
-#define MAC_HALF_DUPLX_CTRL_NO_BACK_C		0x20000
-#define MAC_HALF_DUPLX_CTRL_NO_BACK_P		0x40000
-#define MAC_HALF_DUPLX_CTRL_ABEBE		0x80000
-#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT		20
-#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK		0xf
-#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT	24
-#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK		0xf
-
-/* Maximum Frame Length Control Register */
-#define REG_MTU					0x149c
-
-/* Wake-On-Lan control register */
-#define REG_WOL_CTRL				0x14a0
-#define WOL_PATTERN_EN				0x00000001
-#define WOL_PATTERN_PME_EN			0x00000002
-#define WOL_MAGIC_EN				0x00000004
-#define WOL_MAGIC_PME_EN			0x00000008
-#define WOL_LINK_CHG_EN				0x00000010
-#define WOL_LINK_CHG_PME_EN			0x00000020
-#define WOL_PATTERN_ST				0x00000100
-#define WOL_MAGIC_ST				0x00000200
-#define WOL_LINKCHG_ST				0x00000400
-#define WOL_CLK_SWITCH_EN			0x00008000
-#define WOL_PT0_EN				0x00010000
-#define WOL_PT1_EN				0x00020000
-#define WOL_PT2_EN				0x00040000
-#define WOL_PT3_EN				0x00080000
-#define WOL_PT4_EN				0x00100000
-#define WOL_PT5_EN				0x00200000
-#define WOL_PT6_EN				0x00400000
-
-/* WOL Length ( 2 DWORD ) */
-#define REG_WOL_PATTERN_LEN			0x14a4
-#define WOL_PT_LEN_MASK				0x7f
-#define WOL_PT0_LEN_SHIFT			0
-#define WOL_PT1_LEN_SHIFT			8
-#define WOL_PT2_LEN_SHIFT			16
-#define WOL_PT3_LEN_SHIFT			24
-#define WOL_PT4_LEN_SHIFT			0
-#define WOL_PT5_LEN_SHIFT			8
-#define WOL_PT6_LEN_SHIFT			16
-
-/* Internal SRAM Partition Register */
-#define REG_SRAM_RFD_ADDR			0x1500
-#define REG_SRAM_RFD_LEN			(REG_SRAM_RFD_ADDR+ 4)
-#define REG_SRAM_RRD_ADDR			(REG_SRAM_RFD_ADDR+ 8)
-#define REG_SRAM_RRD_LEN			(REG_SRAM_RFD_ADDR+12)
-#define REG_SRAM_TPD_ADDR			(REG_SRAM_RFD_ADDR+16)
-#define REG_SRAM_TPD_LEN			(REG_SRAM_RFD_ADDR+20)
-#define REG_SRAM_TRD_ADDR			(REG_SRAM_RFD_ADDR+24)
-#define REG_SRAM_TRD_LEN			(REG_SRAM_RFD_ADDR+28)
-#define REG_SRAM_RXF_ADDR			(REG_SRAM_RFD_ADDR+32)
-#define REG_SRAM_RXF_LEN			(REG_SRAM_RFD_ADDR+36)
-#define REG_SRAM_TXF_ADDR			(REG_SRAM_RFD_ADDR+40)
-#define REG_SRAM_TXF_LEN			(REG_SRAM_RFD_ADDR+44)
-#define REG_SRAM_TCPH_PATH_ADDR			(REG_SRAM_RFD_ADDR+48)
-#define SRAM_TCPH_ADDR_MASK			0x0fff
-#define SRAM_TCPH_ADDR_SHIFT			0
-#define SRAM_PATH_ADDR_MASK			0x0fff
-#define SRAM_PATH_ADDR_SHIFT			16
-
-/* Load Ptr Register */
-#define REG_LOAD_PTR				(REG_SRAM_RFD_ADDR+52)
-
-/* Descriptor Control register */
-#define REG_DESC_BASE_ADDR_HI			0x1540
-#define REG_DESC_RFD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+4)
-#define REG_DESC_RRD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+8)
-#define REG_DESC_TPD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+12)
-#define REG_DESC_CMB_ADDR_LO			(REG_DESC_BASE_ADDR_HI+16)
-#define REG_DESC_SMB_ADDR_LO			(REG_DESC_BASE_ADDR_HI+20)
-#define REG_DESC_RFD_RRD_RING_SIZE		(REG_DESC_BASE_ADDR_HI+24)
-#define DESC_RFD_RING_SIZE_MASK			0x7ff
-#define DESC_RFD_RING_SIZE_SHIFT		0
-#define DESC_RRD_RING_SIZE_MASK			0x7ff
-#define DESC_RRD_RING_SIZE_SHIFT		16
-#define REG_DESC_TPD_RING_SIZE			(REG_DESC_BASE_ADDR_HI+28)
-#define DESC_TPD_RING_SIZE_MASK			0x3ff
-#define DESC_TPD_RING_SIZE_SHIFT		0
-
-/* TXQ Control Register */
-#define REG_TXQ_CTRL				0x1580
-#define TXQ_CTRL_TPD_BURST_NUM_SHIFT		0
-#define TXQ_CTRL_TPD_BURST_NUM_MASK		0x1f
-#define TXQ_CTRL_EN				0x20
-#define TXQ_CTRL_ENH_MODE			0x40
-#define TXQ_CTRL_TPD_FETCH_TH_SHIFT		8
-#define TXQ_CTRL_TPD_FETCH_TH_MASK		0x3f
-#define TXQ_CTRL_TXF_BURST_NUM_SHIFT		16
-#define TXQ_CTRL_TXF_BURST_NUM_MASK		0xffff
-
-/* Jumbo packet Threshold for task offload */
-#define REG_TX_JUMBO_TASK_TH_TPD_IPG		0x1584
-#define TX_JUMBO_TASK_TH_MASK			0x7ff
-#define TX_JUMBO_TASK_TH_SHIFT			0
-#define TX_TPD_MIN_IPG_MASK			0x1f
-#define TX_TPD_MIN_IPG_SHIFT			16
-
-/* RXQ Control Register */
-#define REG_RXQ_CTRL				0x15a0
-#define RXQ_CTRL_RFD_BURST_NUM_SHIFT		0
-#define RXQ_CTRL_RFD_BURST_NUM_MASK		0xff
-#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT		8
-#define RXQ_CTRL_RRD_BURST_THRESH_MASK		0xff
-#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT		16
-#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK		0x1f
-#define RXQ_CTRL_CUT_THRU_EN			0x40000000
-#define RXQ_CTRL_EN				0x80000000
-
-/* Rx jumbo packet threshold and rrd  retirement timer */
-#define REG_RXQ_JMBOSZ_RRDTIM			(REG_RXQ_CTRL+ 4)
-#define RXQ_JMBOSZ_TH_MASK			0x7ff
-#define RXQ_JMBOSZ_TH_SHIFT			0
-#define RXQ_JMBO_LKAH_MASK			0xf
-#define RXQ_JMBO_LKAH_SHIFT			11
-#define RXQ_RRD_TIMER_MASK			0xffff
-#define RXQ_RRD_TIMER_SHIFT			16
-
-/* RFD flow control register */
-#define REG_RXQ_RXF_PAUSE_THRESH		(REG_RXQ_CTRL+ 8)
-#define RXQ_RXF_PAUSE_TH_HI_SHIFT		16
-#define RXQ_RXF_PAUSE_TH_HI_MASK		0xfff
-#define RXQ_RXF_PAUSE_TH_LO_SHIFT		0
-#define RXQ_RXF_PAUSE_TH_LO_MASK		0xfff
-
-/* RRD flow control register */
-#define REG_RXQ_RRD_PAUSE_THRESH		(REG_RXQ_CTRL+12)
-#define RXQ_RRD_PAUSE_TH_HI_SHIFT		0
-#define RXQ_RRD_PAUSE_TH_HI_MASK		0xfff
-#define RXQ_RRD_PAUSE_TH_LO_SHIFT		16
-#define RXQ_RRD_PAUSE_TH_LO_MASK		0xfff
-
-/* DMA Engine Control Register */
-#define REG_DMA_CTRL				0x15c0
-#define DMA_CTRL_DMAR_IN_ORDER			0x1
-#define DMA_CTRL_DMAR_ENH_ORDER			0x2
-#define DMA_CTRL_DMAR_OUT_ORDER			0x4
-#define DMA_CTRL_RCB_VALUE			0x8
-#define DMA_CTRL_DMAR_BURST_LEN_SHIFT		4
-#define DMA_CTRL_DMAR_BURST_LEN_MASK		7
-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT		7
-#define DMA_CTRL_DMAW_BURST_LEN_MASK		7
-#define DMA_CTRL_DMAR_EN				0x400
-#define DMA_CTRL_DMAW_EN				0x800
-
-/* CMB/SMB Control Register */
-#define REG_CSMB_CTRL				0x15d0
-#define CSMB_CTRL_CMB_NOW			1
-#define CSMB_CTRL_SMB_NOW			2
-#define CSMB_CTRL_CMB_EN			4
-#define CSMB_CTRL_SMB_EN			8
-
-/* CMB DMA Write Threshold Register */
-#define REG_CMB_WRITE_TH			(REG_CSMB_CTRL+ 4)
-#define CMB_RRD_TH_SHIFT			0
-#define CMB_RRD_TH_MASK				0x7ff
-#define CMB_TPD_TH_SHIFT			16
-#define CMB_TPD_TH_MASK				0x7ff
-
-/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
-#define REG_CMB_WRITE_TIMER			(REG_CSMB_CTRL+ 8)
-#define CMB_RX_TM_SHIFT				0
-#define CMB_RX_TM_MASK				0xffff
-#define CMB_TX_TM_SHIFT				16
-#define CMB_TX_TM_MASK				0xffff
-
-/* Number of packet received since last CMB write */
-#define REG_CMB_RX_PKT_CNT			(REG_CSMB_CTRL+12)
-
-/* Number of packet transmitted since last CMB write */
-#define REG_CMB_TX_PKT_CNT			(REG_CSMB_CTRL+16)
-
-/* SMB auto DMA timer register */
-#define REG_SMB_TIMER				(REG_CSMB_CTRL+20)
-
-/* Mailbox Register */
-#define REG_MAILBOX				0x15f0
-#define MB_RFD_PROD_INDX_SHIFT			0
-#define MB_RFD_PROD_INDX_MASK			0x7ff
-#define MB_RRD_CONS_INDX_SHIFT			11
-#define MB_RRD_CONS_INDX_MASK			0x7ff
-#define MB_TPD_PROD_INDX_SHIFT			22
-#define MB_TPD_PROD_INDX_MASK			0x3ff
-
-/* Interrupt Status Register */
-#define REG_ISR					0x1600
-#define ISR_SMB					1
-#define ISR_TIMER				2
-#define ISR_MANUAL				4
-#define ISR_RXF_OV				8
-#define ISR_RFD_UNRUN				0x10
-#define ISR_RRD_OV				0x20
-#define ISR_TXF_UNRUN				0x40
-#define ISR_LINK				0x80
-#define ISR_HOST_RFD_UNRUN			0x100
-#define ISR_HOST_RRD_OV				0x200
-#define ISR_DMAR_TO_RST				0x400
-#define ISR_DMAW_TO_RST				0x800
-#define ISR_GPHY				0x1000
-#define ISR_RX_PKT				0x10000
-#define ISR_TX_PKT				0x20000
-#define ISR_TX_DMA				0x40000
-#define ISR_RX_DMA				0x80000
-#define ISR_CMB_RX				0x100000
-#define ISR_CMB_TX				0x200000
-#define ISR_MAC_RX				0x400000
-#define ISR_MAC_TX				0x800000
-#define ISR_UR_DETECTED				0x1000000
-#define ISR_FERR_DETECTED			0x2000000
-#define ISR_NFERR_DETECTED			0x4000000
-#define ISR_CERR_DETECTED			0x8000000
-#define ISR_PHY_LINKDOWN			0x10000000
-#define ISR_DIS_SMB				0x20000000
-#define ISR_DIS_DMA				0x40000000
-#define ISR_DIS_INT				0x80000000
-
-/* Interrupt Mask Register */
-#define REG_IMR					0x1604
-
-/* Normal Interrupt mask  */
-#define IMR_NORMAL_MASK	(\
-	ISR_SMB		|\
-	ISR_GPHY	|\
-	ISR_PHY_LINKDOWN|\
-	ISR_DMAR_TO_RST	|\
-	ISR_DMAW_TO_RST	|\
-	ISR_CMB_TX	|\
-	ISR_CMB_RX	)
-
-/* Debug Interrupt Mask  (enable all interrupt) */
-#define IMR_DEBUG_MASK	(\
-	ISR_SMB		|\
-	ISR_TIMER	|\
-	ISR_MANUAL	|\
-	ISR_RXF_OV	|\
-	ISR_RFD_UNRUN	|\
-	ISR_RRD_OV	|\
-	ISR_TXF_UNRUN	|\
-	ISR_LINK	|\
-	ISR_CMB_TX	|\
-	ISR_CMB_RX	|\
-	ISR_RX_PKT	|\
-	ISR_TX_PKT	|\
-	ISR_MAC_RX	|\
-	ISR_MAC_TX	)
-
-/* Interrupt Status Register */
-#define REG_RFD_RRD_IDX				0x1800
-#define REG_TPD_IDX				0x1804
-
-/*  MII definition */
-/* PHY Common Register */
-#define MII_AT001_CR					0x09
-#define MII_AT001_SR					0x0A
-#define MII_AT001_ESR					0x0F
-#define MII_AT001_PSCR					0x10
-#define MII_AT001_PSSR					0x11
-
-/* PHY Control Register */
-#define MII_CR_SPEED_SELECT_MSB				0x0040	/* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE				0x0080	/* Collision test enable */
-#define MII_CR_FULL_DUPLEX				0x0100	/* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG				0x0200	/* Restart auto negotiation */
-#define MII_CR_ISOLATE					0x0400	/* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN				0x0800	/* Power down */
-#define MII_CR_AUTO_NEG_EN				0x1000	/* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB				0x2000	/* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK					0x4000	/* 0 = normal, 1 = loopback */
-#define MII_CR_RESET					0x8000	/* 0 = normal, 1 = PHY reset */
-#define MII_CR_SPEED_MASK				0x2040
-#define MII_CR_SPEED_1000				0x0040
-#define MII_CR_SPEED_100				0x2000
-#define MII_CR_SPEED_10					0x0000
-
-/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS				0x0001	/* Extended register capabilities */
-#define MII_SR_JABBER_DETECT				0x0002	/* Jabber Detected */
-#define MII_SR_LINK_STATUS				0x0004	/* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS				0x0008	/* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT				0x0010	/* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE				0x0020	/* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS			0x0040	/* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS				0x0100	/* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS				0x0200	/* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS				0x0400	/* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS				0x0800	/* 10T   Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS				0x1000	/* 10T   Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS				0x2000	/* 100X  Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS				0x4000	/* 100X  Full Duplex Capable */
-#define MII_SR_100T4_CAPS				0x8000	/* 100T4 Capable */
-
-/* Link partner ability register. */
-#define MII_LPA_SLCT					0x001f	/* Same as advertise selector  */
-#define MII_LPA_10HALF					0x0020	/* Can do 10mbps half-duplex   */
-#define MII_LPA_10FULL					0x0040	/* Can do 10mbps full-duplex   */
-#define MII_LPA_100HALF					0x0080	/* Can do 100mbps half-duplex  */
-#define MII_LPA_100FULL					0x0100	/* Can do 100mbps full-duplex  */
-#define MII_LPA_100BASE4				0x0200	/* 100BASE-T4  */
-#define MII_LPA_PAUSE					0x0400	/* PAUSE */
-#define MII_LPA_ASYPAUSE				0x0800	/* Asymmetrical PAUSE */
-#define MII_LPA_RFAULT					0x2000	/* Link partner faulted        */
-#define MII_LPA_LPACK					0x4000	/* Link partner acked us       */
-#define MII_LPA_NPAGE					0x8000	/* Next page bit               */
-
-/* Autoneg Advertisement Register */
-#define MII_AR_SELECTOR_FIELD				0x0001	/* indicates IEEE 802.3 CSMA/CD */
-#define MII_AR_10T_HD_CAPS				0x0020	/* 10T   Half Duplex Capable */
-#define MII_AR_10T_FD_CAPS				0x0040	/* 10T   Full Duplex Capable */
-#define MII_AR_100TX_HD_CAPS				0x0080	/* 100TX Half Duplex Capable */
-#define MII_AR_100TX_FD_CAPS				0x0100	/* 100TX Full Duplex Capable */
-#define MII_AR_100T4_CAPS				0x0200	/* 100T4 Capable */
-#define MII_AR_PAUSE					0x0400	/* Pause operation desired */
-#define MII_AR_ASM_DIR					0x0800	/* Asymmetric Pause Direction bit */
-#define MII_AR_REMOTE_FAULT				0x2000	/* Remote Fault detected */
-#define MII_AR_NEXT_PAGE				0x8000	/* Next Page ability supported */
-#define MII_AR_SPEED_MASK				0x01E0
-#define MII_AR_DEFAULT_CAP_MASK				0x0DE0
-
-/* 1000BASE-T Control Register */
-#define MII_AT001_CR_1000T_HD_CAPS			0x0100	/* Advertise 1000T HD capability */
-#define MII_AT001_CR_1000T_FD_CAPS			0x0200	/* Advertise 1000T FD capability  */
-#define MII_AT001_CR_1000T_REPEATER_DTE			0x0400	/* 1=Repeater/switch device port, 0=DTE device */
-#define MII_AT001_CR_1000T_MS_VALUE			0x0800	/* 1=Configure PHY as Master, 0=Configure PHY as Slave */
-#define MII_AT001_CR_1000T_MS_ENABLE			0x1000	/* 1=Master/Slave manual config value, 0=Automatic Master/Slave config */
-#define MII_AT001_CR_1000T_TEST_MODE_NORMAL		0x0000	/* Normal Operation */
-#define MII_AT001_CR_1000T_TEST_MODE_1			0x2000	/* Transmit Waveform test */
-#define MII_AT001_CR_1000T_TEST_MODE_2			0x4000	/* Master Transmit Jitter test */
-#define MII_AT001_CR_1000T_TEST_MODE_3			0x6000	/* Slave Transmit Jitter test */
-#define MII_AT001_CR_1000T_TEST_MODE_4			0x8000	/* Transmitter Distortion test */
-#define MII_AT001_CR_1000T_SPEED_MASK			0x0300
-#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK		0x0300
-
-/* 1000BASE-T Status Register */
-#define MII_AT001_SR_1000T_LP_HD_CAPS			0x0400	/* LP is 1000T HD capable */
-#define MII_AT001_SR_1000T_LP_FD_CAPS			0x0800	/* LP is 1000T FD capable */
-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS		0x1000	/* Remote receiver OK */
-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS		0x2000	/* Local receiver OK */
-#define MII_AT001_SR_1000T_MS_CONFIG_RES		0x4000	/* 1=Local TX is Master, 0=Slave */
-#define MII_AT001_SR_1000T_MS_CONFIG_FAULT		0x8000	/* Master/Slave config fault */
-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT	12
-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT	13
-
-/* Extended Status Register */
-#define MII_AT001_ESR_1000T_HD_CAPS			0x1000	/* 1000T HD capable */
-#define MII_AT001_ESR_1000T_FD_CAPS			0x2000	/* 1000T FD capable */
-#define MII_AT001_ESR_1000X_HD_CAPS			0x4000	/* 1000X HD capable */
-#define MII_AT001_ESR_1000X_FD_CAPS			0x8000	/* 1000X FD capable */
-
-/* AT001 PHY Specific Control Register */
-#define MII_AT001_PSCR_JABBER_DISABLE			0x0001	/* 1=Jabber Function disabled */
-#define MII_AT001_PSCR_POLARITY_REVERSAL		0x0002	/* 1=Polarity Reversal enabled */
-#define MII_AT001_PSCR_SQE_TEST				0x0004	/* 1=SQE Test enabled */
-#define MII_AT001_PSCR_MAC_POWERDOWN			0x0008
-#define MII_AT001_PSCR_CLK125_DISABLE			0x0010	/* 1=CLK125 low, 0=CLK125 toggling */
-#define MII_AT001_PSCR_MDI_MANUAL_MODE			0x0000	/* MDI Crossover Mode bits 6:5, Manual MDI configuration */
-#define MII_AT001_PSCR_MDIX_MANUAL_MODE			0x0020	/* Manual MDIX configuration */
-#define MII_AT001_PSCR_AUTO_X_1000T			0x0040	/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
-#define MII_AT001_PSCR_AUTO_X_MODE			0x0060	/* Auto crossover enabled all speeds. */
-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE		0x0080	/* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T RX Threshold), 0=Normal 10BASE-T RX Threshold */
-#define MII_AT001_PSCR_MII_5BIT_ENABLE			0x0100	/* 1=5-Bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
-#define MII_AT001_PSCR_SCRAMBLER_DISABLE		0x0200	/* 1=Scrambler disable */
-#define MII_AT001_PSCR_FORCE_LINK_GOOD			0x0400	/* 1=Force link good */
-#define MII_AT001_PSCR_ASSERT_CRS_ON_TX			0x0800	/* 1=Assert CRS on Transmit */
-#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT		1
-#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT		5
-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT	7
-
-/* AT001 PHY Specific Status Register */
-#define MII_AT001_PSSR_SPD_DPLX_RESOLVED		0x0800	/* 1=Speed & Duplex resolved */
-#define MII_AT001_PSSR_DPLX				0x2000	/* 1=Duplex 0=Half Duplex */
-#define MII_AT001_PSSR_SPEED				0xC000	/* Speed, bits 14:15 */
-#define MII_AT001_PSSR_10MBS				0x0000	/* 00=10Mbs */
-#define MII_AT001_PSSR_100MBS				0x4000	/* 01=100Mbs */
-#define MII_AT001_PSSR_1000MBS				0x8000	/* 10=1000Mbs */
-
-/* PCI Command Register Bit Definitions */
-#define PCI_REG_COMMAND					0x04	/* PCI Command Register */
-#define CMD_IO_SPACE					0x0001
-#define CMD_MEMORY_SPACE				0x0002
-#define CMD_BUS_MASTER					0x0004
-
-/* Wake Up Filter Control */
-#define ATL1_WUFC_LNKC	0x00000001	/* Link Status Change Wakeup Enable */
-#define ATL1_WUFC_MAG	0x00000002	/* Magic Packet Wakeup Enable */
-#define ATL1_WUFC_EX	0x00000004	/* Directed Exact Wakeup Enable */
-#define ATL1_WUFC_MC	0x00000008	/* Multicast Wakeup Enable */
-#define ATL1_WUFC_BC	0x00000010	/* Broadcast Wakeup Enable */
-
-/* Error Codes */
-#define ATL1_SUCCESS			0
-#define ATL1_ERR_EEPROM			1
-#define ATL1_ERR_PHY			2
-#define ATL1_ERR_CONFIG			3
-#define ATL1_ERR_PARAM			4
-#define ATL1_ERR_MAC_TYPE		5
-#define ATL1_ERR_PHY_TYPE		6
-#define ATL1_ERR_PHY_SPEED		7
-#define ATL1_ERR_PHY_RES		8
-
-#define SPEED_0		0xffff
-#define SPEED_10	10
-#define SPEED_100	100
-#define SPEED_1000	1000
-#define HALF_DUPLEX	1
-#define FULL_DUPLEX	2
-
-#define MEDIA_TYPE_AUTO_SENSOR	0
-#define MEDIA_TYPE_1000M_FULL	1
-#define MEDIA_TYPE_100M_FULL	2
-#define MEDIA_TYPE_100M_HALF	3
-#define MEDIA_TYPE_10M_FULL	4
-#define MEDIA_TYPE_10M_HALF	5
-
-#define ADVERTISE_10_HALF		0x0001
-#define ADVERTISE_10_FULL		0x0002
-#define ADVERTISE_100_HALF		0x0004
-#define ADVERTISE_100_FULL		0x0008
-#define ADVERTISE_1000_HALF		0x0010
-#define ADVERTISE_1000_FULL		0x0020
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT	0x002F	/* Everything but 1000-Half */
-#define AUTONEG_ADVERTISE_10_100_ALL	0x000F	/* All 10/100 speeds */
-#define AUTONEG_ADVERTISE_10_ALL	0x0003	/* 10Mbps Full & Half speeds */
-
-#define MAX_JUMBO_FRAME_SIZE		0x2800
-
-#define PHY_AUTO_NEG_TIME	45	/* 4.5 Seconds */
-#define PHY_FORCE_TIME		20	/* 2.0 Seconds */
-
-/* For checksumming , the sum of all words in the EEPROM should equal 0xBABA */
-#define EEPROM_SUM		0xBABA
-
-#define ATL1_EEDUMP_LEN		48
-
-/* Statistics counters collected by the MAC */
-struct stats_msg_block {
-	/* rx */
-	u32 rx_ok;		/* The number of good packet received. */
-	u32 rx_bcast;		/* The number of good broadcast packet received. */
-	u32 rx_mcast;		/* The number of good multicast packet received. */
-	u32 rx_pause;		/* The number of Pause packet received. */
-	u32 rx_ctrl;		/* The number of Control packet received other than Pause frame. */
-	u32 rx_fcs_err;		/* The number of packets with bad FCS. */
-	u32 rx_len_err;		/* The number of packets with mismatch of length field and actual size. */
-	u32 rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */
-	u32 rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */
-	u32 rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */
-	u32 rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */
-	u32 rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */
-	u32 rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */
-	u32 rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */
-	u32 rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */
-	u32 rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */
-	u32 rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */
-	u32 rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size šC truncated by Selene. */
-	u32 rx_rxf_ov;		/* The number of frame dropped due to occurrence of RX FIFO overflow. */
-	u32 rx_rrd_ov;		/* The number of frame dropped due to occurrence of RRD overflow. */
-	u32 rx_align_err;	/* Alignment Error */
-	u32 rx_bcast_byte_cnt;	/* The byte count of broadcast packet received, excluding FCS. */
-	u32 rx_mcast_byte_cnt;	/* The byte count of multicast packet received, excluding FCS. */
-	u32 rx_err_addr;	/* The number of packets dropped due to address filtering. */
-
-	/* tx */
-	u32 tx_ok;		/* The number of good packet transmitted. */
-	u32 tx_bcast;		/* The number of good broadcast packet transmitted. */
-	u32 tx_mcast;		/* The number of good multicast packet transmitted. */
-	u32 tx_pause;		/* The number of Pause packet transmitted. */
-	u32 tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */
-	u32 tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */
-	u32 tx_defer;		/* The number of packets transmitted that is deferred. */
-	u32 tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */
-	u32 tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */
-	u32 tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
-	u32 tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
-	u32 tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
-	u32 tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
-	u32 tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
-	u32 tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
-	u32 tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */
-	u32 tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */
-	u32 tx_late_col;	/* The number of packets transmitted with late collisions. */
-	u32 tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */
-	u32 tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
-	u32 tx_rd_eop;		/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
-	u32 tx_len_err;		/* The number of transmit packets with length field does NOT match the actual frame size. */
-	u32 tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */
-	u32 tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */
-	u32 tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */
-	u32 smb_updated;	/* 1: SMB Updated. This is used by software as the indication of the statistics update.
-				 * Software should clear this bit as soon as retrieving the statistics information. */
-};
-
-/* Coalescing Message Block */
-struct coals_msg_block {
-	u32 int_stats;		/* interrupt status */
-	u16 rrd_prod_idx;	/* TRD Producer Index. */
-	u16 rfd_cons_idx;	/* RFD Consumer Index. */
-	u16 update;		/* Selene sets this bit every time it DMA the CMB to host memory.
-				 * Software supposes to clear this bit when CMB information is processed. */
-	u16 tpd_cons_idx;	/* TPD Consumer Index. */
-};
-
-/* RRD descriptor */
-struct rx_return_desc {
-	u8 num_buf;		/* Number of RFD buffers used by the received packet */
-	u8 resved;
-	u16 buf_indx;		/* RFD Index of the first buffer */
-	union {
-		u32 valid;
-		struct {
-			u16 rx_chksum;
-			u16 pkt_size;
-		} xsum_sz;
-	} xsz;
-
-	u16 pkt_flg;		/* Packet flags */
-	u16 err_flg;		/* Error flags */
-	u16 resved2;
-	u16 vlan_tag;		/* VLAN TAG */
-};
-
-#define PACKET_FLAG_ETH_TYPE	0x0080
-#define PACKET_FLAG_VLAN_INS	0x0100
-#define PACKET_FLAG_ERR		0x0200
-#define PACKET_FLAG_IPV4	0x0400
-#define PACKET_FLAG_UDP		0x0800
-#define PACKET_FLAG_TCP		0x1000
-#define PACKET_FLAG_BCAST	0x2000
-#define PACKET_FLAG_MCAST	0x4000
-#define PACKET_FLAG_PAUSE	0x8000
-
-#define ERR_FLAG_CRC		0x0001
-#define ERR_FLAG_CODE		0x0002
-#define ERR_FLAG_DRIBBLE	0x0004
-#define ERR_FLAG_RUNT		0x0008
-#define ERR_FLAG_OV		0x0010
-#define ERR_FLAG_TRUNC		0x0020
-#define ERR_FLAG_IP_CHKSUM	0x0040
-#define ERR_FLAG_L4_CHKSUM	0x0080
-#define ERR_FLAG_LEN		0x0100
-#define ERR_FLAG_DES_ADDR	0x0200
-
-/* RFD descriptor */
-struct rx_free_desc {
-	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
-	__le16 buf_len;		/* Size of the receive buffer in host memory, in byte */
-	u16 coalese;		/* Update consumer index to host after the reception of this frame */
-	/* __attribute__ ((packed)) is required */
-} __attribute__ ((packed));
-
-/* tsopu defines */
-#define TSO_PARAM_BUFLEN_MASK           0x3FFF
-#define TSO_PARAM_BUFLEN_SHIFT          0
-#define TSO_PARAM_DMAINT_MASK           0x0001
-#define TSO_PARAM_DMAINT_SHIFT          14
-#define TSO_PARAM_PKTNT_MASK            0x0001
-#define TSO_PARAM_PKTINT_SHIFT          15
-#define TSO_PARAM_VLANTAG_MASK          0xFFFF
-#define TSO_PARAM_VLAN_SHIFT            16
-
-/* tsopl defines */
-#define TSO_PARAM_EOP_MASK              0x0001
-#define TSO_PARAM_EOP_SHIFT             0
-#define TSO_PARAM_COALESCE_MASK         0x0001
-#define TSO_PARAM_COALESCE_SHIFT        1
-#define TSO_PARAM_INSVLAG_MASK          0x0001
-#define TSO_PARAM_INSVLAG_SHIFT         2
-#define TSO_PARAM_CUSTOMCKSUM_MASK      0x0001
-#define TSO_PARAM_CUSTOMCKSUM_SHIFT     3
-#define TSO_PARAM_SEGMENT_MASK          0x0001
-#define TSO_PARAM_SEGMENT_SHIFT         4
-#define TSO_PARAM_IPCKSUM_MASK          0x0001
-#define TSO_PARAM_IPCKSUM_SHIFT         5
-#define TSO_PARAM_TCPCKSUM_MASK         0x0001
-#define TSO_PARAM_TCPCKSUM_SHIFT        6
-#define TSO_PARAM_UDPCKSUM_MASK         0x0001
-#define TSO_PARAM_UDPCKSUM_SHIFT        7
-#define TSO_PARAM_VLANTAGGED_MASK       0x0001
-#define TSO_PARAM_VLANTAGGED_SHIFT      8
-#define TSO_PARAM_ETHTYPE_MASK          0x0001
-#define TSO_PARAM_ETHTYPE_SHIFT         9
-#define TSO_PARAM_IPHL_MASK             0x000F
-#define TSO_PARAM_IPHL_SHIFT            10
-#define TSO_PARAM_TCPHDRLEN_MASK        0x000F
-#define TSO_PARAM_TCPHDRLEN_SHIFT       14
-#define TSO_PARAM_HDRFLAG_MASK          0x0001
-#define TSO_PARAM_HDRFLAG_SHIFT         18
-#define TSO_PARAM_MSS_MASK              0x1FFF
-#define TSO_PARAM_MSS_SHIFT             19
-
-/* csumpu defines */
-#define CSUM_PARAM_BUFLEN_MASK          0x3FFF
-#define CSUM_PARAM_BUFLEN_SHIFT         0
-#define CSUM_PARAM_DMAINT_MASK          0x0001
-#define CSUM_PARAM_DMAINT_SHIFT         14
-#define CSUM_PARAM_PKTINT_MASK          0x0001
-#define CSUM_PARAM_PKTINT_SHIFT         15
-#define CSUM_PARAM_VALANTAG_MASK        0xFFFF
-#define CSUM_PARAM_VALAN_SHIFT          16
-
-/* csumpl defines*/
-#define CSUM_PARAM_EOP_MASK             0x0001
-#define CSUM_PARAM_EOP_SHIFT            0
-#define CSUM_PARAM_COALESCE_MASK        0x0001
-#define CSUM_PARAM_COALESCE_SHIFT       1
-#define CSUM_PARAM_INSVLAG_MASK         0x0001
-#define CSUM_PARAM_INSVLAG_SHIFT        2
-#define CSUM_PARAM_CUSTOMCKSUM_MASK     0x0001
-#define CSUM_PARAM_CUSTOMCKSUM_SHIFT    3
-#define CSUM_PARAM_SEGMENT_MASK         0x0001
-#define CSUM_PARAM_SEGMENT_SHIFT        4
-#define CSUM_PARAM_IPCKSUM_MASK         0x0001
-#define CSUM_PARAM_IPCKSUM_SHIFT        5
-#define CSUM_PARAM_TCPCKSUM_MASK        0x0001
-#define CSUM_PARAM_TCPCKSUM_SHIFT       6
-#define CSUM_PARAM_UDPCKSUM_MASK        0x0001
-#define CSUM_PARAM_UDPCKSUM_SHIFT       7
-#define CSUM_PARAM_VLANTAGGED_MASK      0x0001
-#define CSUM_PARAM_VLANTAGGED_SHIFT     8
-#define CSUM_PARAM_ETHTYPE_MASK         0x0001
-#define CSUM_PARAM_ETHTYPE_SHIFT        9
-#define CSUM_PARAM_IPHL_MASK            0x000F
-#define CSUM_PARAM_IPHL_SHIFT           10
-#define CSUM_PARAM_PLOADOFFSET_MASK     0x00FF
-#define CSUM_PARAM_PLOADOFFSET_SHIFT    16
-#define CSUM_PARAM_XSUMOFFSET_MASK      0x00FF
-#define CSUM_PARAM_XSUMOFFSET_SHIFT     24
-
-/* TPD descriptor */
-struct tso_param {
-        /* The order of these declarations is important -- don't change it */
-        u32 tsopu;      /* tso_param upper word */
-        u32 tsopl;      /* tso_param lower word */
-};
-
-struct csum_param {
-        /* The order of these declarations is important -- don't change it */
-        u32 csumpu;     /* csum_param upper word */
-        u32 csumpl;     /* csum_param lower word */
-};
-
-union tpd_descr {
-	u64 data;
-	struct csum_param csum;
-	struct tso_param tso;
-};
-
-struct tx_packet_desc {
-	__le64 buffer_addr;
-	union tpd_descr desc;
-};
-
-/* DMA Order Settings */
-enum atl1_dma_order {
-	atl1_dma_ord_in = 1,
-	atl1_dma_ord_enh = 2,
-	atl1_dma_ord_out = 4
-};
-
-enum atl1_dma_rcb {
-	atl1_rcb_64 = 0,
-	atl1_rcb_128 = 1
-};
-
-enum atl1_dma_req_block {
-	atl1_dma_req_128 = 0,
-	atl1_dma_req_256 = 1,
-	atl1_dma_req_512 = 2,
-	atl1_dma_req_1024 = 3,
-	atl1_dma_req_2048 = 4,
-	atl1_dma_req_4096 = 5
-};
-
-struct atl1_spi_flash_dev {
-	const char *manu_name;	/* manufacturer id */
-	/* op-code */
-	u8 cmd_wrsr;
-	u8 cmd_read;
-	u8 cmd_program;
-	u8 cmd_wren;
-	u8 cmd_wrdi;
-	u8 cmd_rdsr;
-	u8 cmd_rdid;
-	u8 cmd_sector_erase;
-	u8 cmd_chip_erase;
-};
-
-#endif	/* _ATL1_HW_H_ */
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
deleted file mode 100644
index 129b8b3..0000000
--- a/drivers/net/atl1/atl1_main.c
+++ /dev/null
@@ -1,2450 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called COPYING.
- *
- * Contact Information:
- * Xiong Huang <xiong_huang@attansic.com>
- * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
- * Xinzhu  302, TAIWAN, REPUBLIC OF CHINA
- *
- * Chris Snook <csnook@redhat.com>
- * Jay Cliburn <jcliburn@gmail.com>
- *
- * This version is adapted from the Attansic reference driver for
- * inclusion in the Linux kernel.  It is currently under heavy development.
- * A very incomplete list of things that need to be dealt with:
- *
- * TODO:
- * Fix TSO; tx performance is horrible with TSO enabled.
- * Wake on LAN.
- * Add more ethtool functions.
- * Fix abstruse irq enable/disable condition described here:
- *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
- *
- * NEEDS TESTING:
- * VLAN
- * multicast
- * promiscuous mode
- * interrupt coalescing
- * SMP torture testing
- */
-
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/if_ether.h>
-#include <linux/irqreturn.h>
-#include <linux/workqueue.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/hardirq.h>
-#include <linux/interrupt.h>
-#include <linux/irqflags.h>
-#include <linux/dma-mapping.h>
-#include <linux/net.h>
-#include <linux/pm.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/mii.h>
-#include <net/checksum.h>
-
-#include <asm/atomic.h>
-#include <asm/byteorder.h>
-
-#include "atl1.h"
-
-#define DRIVER_VERSION "2.0.7"
-
-char atl1_driver_name[] = "atl1";
-static const char atl1_driver_string[] = "Attansic L1 Ethernet Network Driver";
-static const char atl1_copyright[] = "Copyright(c) 2005-2006 Attansic Corporation.";
-char atl1_driver_version[] = DRIVER_VERSION;
-
-MODULE_AUTHOR
-    ("Attansic Corporation <xiong_huang@attansic.com>, Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
-MODULE_DESCRIPTION("Attansic 1000M Ethernet Network Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
-
-/*
- * atl1_pci_tbl - PCI Device ID Table
- */
-static const struct pci_device_id atl1_pci_tbl[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
-	/* required last entry */
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
-
-/*
- * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
- * @adapter: board private structure to initialize
- *
- * atl1_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- */
-static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-
-	hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-	hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
-
-	adapter->wol = 0;
-	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
-	adapter->ict = 50000;	/* 100ms */
-	adapter->link_speed = SPEED_0;	/* hardware init */
-	adapter->link_duplex = FULL_DUPLEX;
-
-	hw->phy_configured = false;
-	hw->preamble_len = 7;
-	hw->ipgt = 0x60;
-	hw->min_ifg = 0x50;
-	hw->ipgr1 = 0x40;
-	hw->ipgr2 = 0x60;
-	hw->max_retry = 0xf;
-	hw->lcol = 0x37;
-	hw->jam_ipg = 7;
-	hw->rfd_burst = 8;
-	hw->rrd_burst = 8;
-	hw->rfd_fetch_gap = 1;
-	hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
-	hw->rx_jumbo_lkah = 1;
-	hw->rrd_ret_timer = 16;
-	hw->tpd_burst = 4;
-	hw->tpd_fetch_th = 16;
-	hw->txf_burst = 0x100;
-	hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
-	hw->tpd_fetch_gap = 1;
-	hw->rcb_value = atl1_rcb_64;
-	hw->dma_ord = atl1_dma_ord_enh;
-	hw->dmar_block = atl1_dma_req_256;
-	hw->dmaw_block = atl1_dma_req_256;
-	hw->cmb_rrd = 4;
-	hw->cmb_tpd = 4;
-	hw->cmb_rx_timer = 1;	/* about 2us */
-	hw->cmb_tx_timer = 1;	/* about 2us */
-	hw->smb_timer = 100000;	/* about 200ms */
-
-	spin_lock_init(&adapter->lock);
-	spin_lock_init(&adapter->mb_lock);
-
-	return 0;
-}
-
-static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u16 result;
-
-	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
-
-	return result;
-}
-
-static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
-	int val)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	atl1_write_phy_reg(&adapter->hw, reg_num, val);
-}
-
-/*
- * atl1_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	int retval;
-
-	if (!netif_running(netdev))
-		return -EINVAL;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-
-	return retval;
-}
-
-/*
- * atl1_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return atl1_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/*
- * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- */
-s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_ring_header *ring_header = &adapter->ring_header;
-	struct pci_dev *pdev = adapter->pdev;
-	int size;
-	u8 offset = 0;
-
-	size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
-	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
-	if (unlikely(!tpd_ring->buffer_info)) {
-		dev_err(&pdev->dev, "kzalloc failed , size = D%d\n", size);
-		goto err_nomem;
-	}
-	rfd_ring->buffer_info =
-		(struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
-
-	/* real ring DMA buffer
-	 * each ring/block may need up to 8 bytes for alignment, hence the
-	 * additional 40 bytes tacked onto the end.
-	 */
-	ring_header->size = size =
-		sizeof(struct tx_packet_desc) * tpd_ring->count
-		+ sizeof(struct rx_free_desc) * rfd_ring->count
-		+ sizeof(struct rx_return_desc) * rrd_ring->count
-		+ sizeof(struct coals_msg_block)
-		+ sizeof(struct stats_msg_block)
-		+ 40;
-
-	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
-		&ring_header->dma);
-	if (unlikely(!ring_header->desc)) {
-		dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
-		goto err_nomem;
-	}
-
-	memset(ring_header->desc, 0, ring_header->size);
-
-	/* init TPD ring */
-	tpd_ring->dma = ring_header->dma;
-	offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
-	tpd_ring->dma += offset;
-	tpd_ring->desc = (u8 *) ring_header->desc + offset;
-	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
-
-	/* init RFD ring */
-	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
-	offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
-	rfd_ring->dma += offset;
-	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
-	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
-
-
-	/* init RRD ring */
-	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
-	offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
-	rrd_ring->dma += offset;
-	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
-	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
-
-
-	/* init CMB */
-	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
-	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
-	adapter->cmb.dma += offset;
-	adapter->cmb.cmb = (struct coals_msg_block *)
-		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
-
-	/* init SMB */
-	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
-	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
-	adapter->smb.dma += offset;
-	adapter->smb.smb = (struct stats_msg_block *)
-		((u8 *) adapter->cmb.cmb +
-		(sizeof(struct coals_msg_block) + offset));
-
-	return ATL1_SUCCESS;
-
-err_nomem:
-	kfree(tpd_ring->buffer_info);
-	return -ENOMEM;
-}
-
-static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
-
-	rfd_ring->next_to_clean = 0;
-	atomic_set(&rfd_ring->next_to_use, 0);
-
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
-}
-
-/*
- * atl1_clean_rx_ring - Free RFD Buffers
- * @adapter: board private structure
- */
-static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
-{
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
-
-	/* Free all the Rx ring sk_buffs */
-	for (i = 0; i < rfd_ring->count; i++) {
-		buffer_info = &rfd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev, buffer_info->dma,
-				buffer_info->length, PCI_DMA_FROMDEVICE);
-			buffer_info->dma = 0;
-		}
-		if (buffer_info->skb) {
-			dev_kfree_skb(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * rfd_ring->count;
-	memset(rfd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(rfd_ring->desc, 0, rfd_ring->size);
-
-	rfd_ring->next_to_clean = 0;
-	atomic_set(&rfd_ring->next_to_use, 0);
-
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
-}
-
-/*
- * atl1_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
- */
-static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
-
-	/* Free all the Tx ring sk_buffs */
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev, buffer_info->dma,
-				buffer_info->length, PCI_DMA_TODEVICE);
-			buffer_info->dma = 0;
-		}
-	}
-
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->skb) {
-			dev_kfree_skb_any(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * tpd_ring->count;
-	memset(tpd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(tpd_ring->desc, 0, tpd_ring->size);
-
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
-}
-
-/*
- * atl1_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-void atl1_free_ring_resources(struct atl1_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_ring_header *ring_header = &adapter->ring_header;
-
-	atl1_clean_tx_ring(adapter);
-	atl1_clean_rx_ring(adapter);
-
-	kfree(tpd_ring->buffer_info);
-	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
-		ring_header->dma);
-
-	tpd_ring->buffer_info = NULL;
-	tpd_ring->desc = NULL;
-	tpd_ring->dma = 0;
-
-	rfd_ring->buffer_info = NULL;
-	rfd_ring->desc = NULL;
-	rfd_ring->dma = 0;
-
-	rrd_ring->desc = NULL;
-	rrd_ring->dma = 0;
-}
-
-static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
-{
-	u32 value;
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	/* Config MAC CTRL Register */
-	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
-	/* duplex */
-	if (FULL_DUPLEX == adapter->link_duplex)
-		value |= MAC_CTRL_DUPLX;
-	/* speed */
-	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
-			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
-		  MAC_CTRL_SPEED_SHIFT);
-	/* flow control */
-	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-	/* PAD & CRC */
-	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-	/* preamble length */
-	value |= (((u32) adapter->hw.preamble_len
-		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-	/* vlan */
-	if (adapter->vlgrp)
-		value |= MAC_CTRL_RMV_VLAN;
-	/* rx checksum
-	   if (adapter->rx_csum)
-	   value |= MAC_CTRL_RX_CHKSUM_EN;
-	 */
-	/* filter mode */
-	value |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		value |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI)
-		value |= MAC_CTRL_MC_ALL_EN;
-	/* value |= MAC_CTRL_LOOPBACK; */
-	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
-}
-
-/*
- * atl1_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_set_mac(struct net_device *netdev, void *p)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
-	atl1_set_mac_addr(&adapter->hw);
-	return 0;
-}
-
-static u32 atl1_check_link(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 ret_val;
-	u16 speed, duplex, phy_data;
-	int reconfig = 0;
-
-	/* MII_BMSR must read twice */
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */
-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
-			dev_info(&adapter->pdev->dev, "link is down\n");
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-		return ATL1_SUCCESS;
-	}
-
-	/* Link Up */
-	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
-	if (ret_val)
-		return ret_val;
-
-	switch (hw->media_type) {
-	case MEDIA_TYPE_1000M_FULL:
-		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_FULL:
-		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_HALF:
-		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_FULL:
-		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_HALF:
-		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	}
-
-	/* link result is our setting */
-	if (!reconfig) {
-		if (adapter->link_speed != speed
-		    || adapter->link_duplex != duplex) {
-			adapter->link_speed = speed;
-			adapter->link_duplex = duplex;
-			atl1_setup_mac_ctrl(adapter);
-			dev_info(&adapter->pdev->dev,
-				"%s link is up %d Mbps %s\n",
-				netdev->name, adapter->link_speed,
-				adapter->link_duplex == FULL_DUPLEX ?
-				"full duplex" : "half duplex");
-		}
-		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */
-			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
-		}
-		return ATL1_SUCCESS;
-	}
-
-	/* change orignal link status */
-	if (netif_carrier_ok(netdev)) {
-		adapter->link_speed = SPEED_0;
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-	}
-
-	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
-	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			           MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:	/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-		return ATL1_SUCCESS;
-	}
-
-	/* auto-neg, insert timer to re-config phy */
-	if (!adapter->phy_timer_pending) {
-		adapter->phy_timer_pending = true;
-		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
-	}
-
-	return ATL1_SUCCESS;
-}
-
-static void atl1_check_for_link(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u16 phy_data = 0;
-
-	spin_lock(&adapter->lock);
-	adapter->phy_timer_pending = false;
-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	spin_unlock(&adapter->lock);
-
-	/* notify upper layer link down ASAP */
-	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */
-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
-			dev_info(&adapter->pdev->dev, "%s link is down\n",
-				netdev->name);
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-	}
-	schedule_work(&adapter->link_chg_task);
-}
-
-/*
- * atl1_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- */
-static void atl1_set_multi(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	struct dev_mc_list *mc_ptr;
-	u32 rctl;
-	u32 hash_value;
-
-	/* Check for Promiscuous and All Multicast modes */
-	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
-	if (netdev->flags & IFF_PROMISC)
-		rctl |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI) {
-		rctl |= MAC_CTRL_MC_ALL_EN;
-		rctl &= ~MAC_CTRL_PROMIS_EN;
-	} else
-		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
-
-	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
-
-	/* clear the old settings from the multicast hash table */
-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
-
-	/* compute mc addresses' hash value ,and put it into hash table */
-	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
-		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
-		atl1_hash_set(hw, hash_value);
-	}
-}
-
-/*
- * atl1_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int old_mtu = netdev->mtu;
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-
-	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-		return -EINVAL;
-	}
-
-	adapter->hw.max_frame_size = max_frame;
-	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
-	adapter->rx_buffer_len = (max_frame + 7) & ~7;
-	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
-
-	netdev->mtu = new_mtu;
-	if ((old_mtu != new_mtu) && netif_running(netdev)) {
-		atl1_down(adapter);
-		atl1_up(adapter);
-	}
-
-	return 0;
-}
-
-static void set_flow_ctrl_old(struct atl1_adapter *adapter)
-{
-	u32 hi, lo, value;
-
-	/* RFD Flow Control */
-	value = adapter->rfd_ring.count;
-	hi = value / 16;
-	if (hi < 2)
-		hi = 2;
-	lo = value * 7 / 8;
-
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = adapter->rrd_ring.count;
-	lo = value / 16;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-static void set_flow_ctrl_new(struct atl1_hw *hw)
-{
-	u32 hi, lo, value;
-
-	/* RXF Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
-	lo = value / 16;
-	if (lo < 192)
-		lo = 192;
-	hi = value * 7 / 8;
-	if (hi < lo)
-		hi = lo + 16;
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
-	lo = value / 8;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	if (hi < lo)
-		hi = lo + 3;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-/*
- * atl1_configure - Configure Transmit&Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx /Rx unit of the MAC after a reset.
- */
-static u32 atl1_configure(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	u32 value;
-
-	/* clear interrupt status */
-	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
-
-	/* set MAC Address */
-	value = (((u32) hw->mac_addr[2]) << 24) |
-		(((u32) hw->mac_addr[3]) << 16) |
-		(((u32) hw->mac_addr[4]) << 8) |
-		(((u32) hw->mac_addr[5]));
-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
-	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
-
-	/* tx / rx ring */
-
-	/* HI base address */
-	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
-		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
-	/* LO base address */
-	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
-	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
-	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
-	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
-	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
-
-	/* element count */
-	value = adapter->rrd_ring.count;
-	value <<= 16;
-	value += adapter->rfd_ring.count;
-	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
-	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
-		REG_DESC_TPD_RING_SIZE);
-
-	/* Load Ptr */
-	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
-
-	/* config Mailbox */
-	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
-		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
-		((atomic_read(&adapter->rrd_ring.next_to_clean)
-		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
-		((atomic_read(&adapter->rfd_ring.next_to_use)
-		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAILBOX);
-
-	/* config IPG/IFG */
-	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
-		 << MAC_IPG_IFG_IPGT_SHIFT) |
-		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
-		<< MAC_IPG_IFG_MIFG_SHIFT) |
-		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
-		<< MAC_IPG_IFG_IPGR1_SHIFT) |
-		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
-		<< MAC_IPG_IFG_IPGR2_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
-
-	/* config  Half-Duplex Control */
-	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
-		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
-		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
-		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
-		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
-		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
-		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
-
-	/* set Interrupt Moderator Timer */
-	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
-	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
-
-	/* set Interrupt Clear Timer */
-	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
-
-	/* set max frame size hw will accept */
-	iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
-
-	/* jumbo size & rrd retirement timer */
-	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
-		 << RXQ_JMBOSZ_TH_SHIFT) |
-		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
-		<< RXQ_JMBO_LKAH_SHIFT) |
-		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
-		<< RXQ_RRD_TIMER_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
-
-	/* Flow Control */
-	switch (hw->dev_rev) {
-	case 0x8001:
-	case 0x9001:
-	case 0x9002:
-	case 0x9003:
-		set_flow_ctrl_old(adapter);
-		break;
-	default:
-		set_flow_ctrl_new(hw);
-		break;
-	}
-
-	/* config TXQ */
-	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
-		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
-		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
-		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
-		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
-		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
-		TXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
-
-	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
-	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
-		<< TX_JUMBO_TASK_TH_SHIFT) |
-		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
-		<< TX_TPD_MIN_IPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
-
-	/* config RXQ */
-	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
-		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
-		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
-		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
-		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
-		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
-		RXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
-
-	/* config DMA Engine */
-	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
-		((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
-		DMA_CTRL_DMAW_EN;
-	value |= (u32) hw->dma_ord;
-	if (atl1_rcb_128 == hw->rcb_value)
-		value |= DMA_CTRL_RCB_VALUE;
-	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
-
-	/* config CMB / SMB */
-	value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
-		hw->cmb_tpd : adapter->tpd_ring.count;
-	value <<= 16;
-	value |= hw->cmb_rrd;
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
-	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
-	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
-
-	/* --- enable CMB / SMB */
-	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
-	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
-
-	value = ioread32(adapter->hw.hw_addr + REG_ISR);
-	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
-		value = 1;	/* config failed */
-	else
-		value = 0;
-
-	/* clear all interrupt status */
-	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
-	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
-	return value;
-}
-
-/*
- * atl1_pcie_patch - Patch for PCIE module
- */
-static void atl1_pcie_patch(struct atl1_adapter *adapter)
-{
-	u32 value;
-
-	/* much vendor magic here */
-	value = 0x6500;
-	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
-	/* pcie flow control mode change */
-	value = ioread32(adapter->hw.hw_addr + 0x1008);
-	value |= 0x8000;
-	iowrite32(value, adapter->hw.hw_addr + 0x1008);
-}
-
-/*
- * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
- * on PCI Command register is disable.
- * The function enable this bit.
- * Brackett, 2006/03/15
- */
-static void atl1_via_workaround(struct atl1_adapter *adapter)
-{
-	unsigned long value;
-
-	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
-	if (value & PCI_COMMAND_INTX_DISABLE)
-		value &= ~PCI_COMMAND_INTX_DISABLE;
-	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
-}
-
-/*
- * atl1_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- */
-static void atl1_irq_enable(struct atl1_adapter *adapter)
-{
-	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
-	ioread32(adapter->hw.hw_addr + REG_IMR);
-}
-
-/*
- * atl1_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- */
-static void atl1_irq_disable(struct atl1_adapter *adapter)
-{
-	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-	ioread32(adapter->hw.hw_addr + REG_IMR);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-static void atl1_clear_phy_int(struct atl1_adapter *adapter)
-{
-	u16 phy_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	atl1_read_phy_reg(&adapter->hw, 19, &phy_data);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static void atl1_inc_smb(struct atl1_adapter *adapter)
-{
-	struct stats_msg_block *smb = adapter->smb.smb;
-
-	/* Fill out the OS statistics structure */
-	adapter->soft_stats.rx_packets += smb->rx_ok;
-	adapter->soft_stats.tx_packets += smb->tx_ok;
-	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
-	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
-	adapter->soft_stats.multicast += smb->rx_mcast;
-	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
-		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
-
-	/* Rx Errors */
-	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
-		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
-		smb->rx_rrd_ov + smb->rx_align_err);
-	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
-	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
-	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
-	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
-	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
-		smb->rx_rxf_ov);
-
-	adapter->soft_stats.rx_pause += smb->rx_pause;
-	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
-	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
-
-	/* Tx Errors */
-	adapter->soft_stats.tx_errors += (smb->tx_late_col +
-		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
-	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
-	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
-	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
-
-	adapter->soft_stats.excecol += smb->tx_abort_col;
-	adapter->soft_stats.deffer += smb->tx_defer;
-	adapter->soft_stats.scc += smb->tx_1_col;
-	adapter->soft_stats.mcc += smb->tx_2_col;
-	adapter->soft_stats.latecol += smb->tx_late_col;
-	adapter->soft_stats.tx_underun += smb->tx_underrun;
-	adapter->soft_stats.tx_trunc += smb->tx_trunc;
-	adapter->soft_stats.tx_pause += smb->tx_pause;
-
-	adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
-	adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
-	adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
-	adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
-	adapter->net_stats.multicast = adapter->soft_stats.multicast;
-	adapter->net_stats.collisions = adapter->soft_stats.collisions;
-	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
-	adapter->net_stats.rx_over_errors =
-		adapter->soft_stats.rx_missed_errors;
-	adapter->net_stats.rx_length_errors =
-		adapter->soft_stats.rx_length_errors;
-	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
-	adapter->net_stats.rx_frame_errors =
-		adapter->soft_stats.rx_frame_errors;
-	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
-	adapter->net_stats.rx_missed_errors =
-		adapter->soft_stats.rx_missed_errors;
-	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
-	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
-	adapter->net_stats.tx_aborted_errors =
-		adapter->soft_stats.tx_aborted_errors;
-	adapter->net_stats.tx_window_errors =
-		adapter->soft_stats.tx_window_errors;
-	adapter->net_stats.tx_carrier_errors =
-		adapter->soft_stats.tx_carrier_errors;
-}
-
-/*
- * atl1_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- */
-static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	return &adapter->net_stats;
-}
-
-static void atl1_update_mailbox(struct atl1_adapter *adapter)
-{
-	unsigned long flags;
-	u32 tpd_next_to_use;
-	u32 rfd_next_to_use;
-	u32 rrd_next_to_clean;
-	u32 value;
-
-	spin_lock_irqsave(&adapter->mb_lock, flags);
-
-	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
-	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
-	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
-
-	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
-		MB_RFD_PROD_INDX_SHIFT) |
-		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
-		MB_RRD_CONS_INDX_SHIFT) |
-		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
-		MB_TPD_PROD_INDX_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
-
-	spin_unlock_irqrestore(&adapter->mb_lock, flags);
-}
-
-static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
-	struct rx_return_desc *rrd, u16 offset)
-{
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-
-	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
-		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
-		if (++rfd_ring->next_to_clean == rfd_ring->count) {
-			rfd_ring->next_to_clean = 0;
-		}
-	}
-}
-
-static void atl1_update_rfd_index(struct atl1_adapter *adapter,
-	struct rx_return_desc *rrd)
-{
-	u16 num_buf;
-
-	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
-		adapter->rx_buffer_len;
-	if (rrd->num_buf == num_buf)
-		/* clean alloc flag for bad rrd */
-		atl1_clean_alloc_flag(adapter, rrd, num_buf);
-}
-
-static void atl1_rx_checksum(struct atl1_adapter *adapter,
-	struct rx_return_desc *rrd, struct sk_buff *skb)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	skb->ip_summed = CHECKSUM_NONE;
-
-	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
-		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
-					ERR_FLAG_CODE | ERR_FLAG_OV)) {
-			adapter->hw_csum_err++;
-			dev_printk(KERN_DEBUG, &pdev->dev,
-				"rx checksum error\n");
-			return;
-		}
-	}
-
-	/* not IPv4 */
-	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
-		/* checksum is invalid, but it's not an IPv4 pkt, so ok */
-		return;
-
-	/* IPv4 packet */
-	if (likely(!(rrd->err_flg &
-		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		adapter->hw_csum_good++;
-		return;
-	}
-
-	/* IPv4, but hardware thinks its checksum is wrong */
-	dev_printk(KERN_DEBUG, &pdev->dev,
-		"hw csum wrong, pkt_flag:%x, err_flag:%x\n",
-		rrd->pkt_flg, rrd->err_flg);
-	skb->ip_summed = CHECKSUM_COMPLETE;
-	skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
-	adapter->hw_csum_err++;
-	return;
-}
-
-/*
- * atl1_alloc_rx_buffers - Replace used receive buffers
- * @adapter: address of board private structure
- */
-static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
-{
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	struct page *page;
-	unsigned long offset;
-	struct atl1_buffer *buffer_info, *next_info;
-	struct sk_buff *skb;
-	u16 num_alloc = 0;
-	u16 rfd_next_to_use, next_next;
-	struct rx_free_desc *rfd_desc;
-
-	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
-	if (++next_next == rfd_ring->count)
-		next_next = 0;
-	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
-	next_info = &rfd_ring->buffer_info[next_next];
-
-	while (!buffer_info->alloced && !next_info->alloced) {
-		if (buffer_info->skb) {
-			buffer_info->alloced = 1;
-			goto next;
-		}
-
-		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
-
-		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
-		if (unlikely(!skb)) {	/* Better luck next round */
-			adapter->net_stats.rx_dropped++;
-			break;
-		}
-
-		/*
-		 * Make buffer alignment 2 beyond a 16 byte boundary
-		 * this will result in a 16 byte aligned IP header after
-		 * the 14 byte MAC header is removed
-		 */
-		skb_reserve(skb, NET_IP_ALIGN);
-
-		buffer_info->alloced = 1;
-		buffer_info->skb = skb;
-		buffer_info->length = (u16) adapter->rx_buffer_len;
-		page = virt_to_page(skb->data);
-		offset = (unsigned long)skb->data & ~PAGE_MASK;
-		buffer_info->dma = pci_map_page(pdev, page, offset,
-						adapter->rx_buffer_len,
-						PCI_DMA_FROMDEVICE);
-		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
-		rfd_desc->coalese = 0;
-
-next:
-		rfd_next_to_use = next_next;
-		if (unlikely(++next_next == rfd_ring->count))
-			next_next = 0;
-
-		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
-		next_info = &rfd_ring->buffer_info[next_next];
-		num_alloc++;
-	}
-
-	if (num_alloc) {
-		/*
-		 * Force memory writes to complete before letting h/w
-		 * know there are new descriptors to fetch.  (Only
-		 * applicable for weak-ordered memory model archs,
-		 * such as IA-64).
-		 */
-		wmb();
-		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
-	}
-	return num_alloc;
-}
-
-static void atl1_intr_rx(struct atl1_adapter *adapter)
-{
-	int i, count;
-	u16 length;
-	u16 rrd_next_to_clean;
-	u32 value;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_buffer *buffer_info;
-	struct rx_return_desc *rrd;
-	struct sk_buff *skb;
-
-	count = 0;
-
-	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
-
-	while (1) {
-		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
-		i = 1;
-		if (likely(rrd->xsz.valid)) {	/* packet valid */
-chk_rrd:
-			/* check rrd status */
-			if (likely(rrd->num_buf == 1))
-				goto rrd_ok;
-
-			/* rrd seems to be bad */
-			if (unlikely(i-- > 0)) {
-				/* rrd may not be DMAed completely */
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"incomplete RRD DMA transfer\n");
-				udelay(1);
-				goto chk_rrd;
-			}
-			/* bad rrd */
-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-				"bad RRD\n");
-			/* see if update RFD index */
-			if (rrd->num_buf > 1)
-				atl1_update_rfd_index(adapter, rrd);
-
-			/* update rrd */
-			rrd->xsz.valid = 0;
-			if (++rrd_next_to_clean == rrd_ring->count)
-				rrd_next_to_clean = 0;
-			count++;
-			continue;
-		} else {	/* current rrd still not be updated */
-
-			break;
-		}
-rrd_ok:
-		/* clean alloc flag for bad rrd */
-		atl1_clean_alloc_flag(adapter, rrd, 0);
-
-		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
-		if (++rfd_ring->next_to_clean == rfd_ring->count)
-			rfd_ring->next_to_clean = 0;
-
-		/* update rrd next to clean */
-		if (++rrd_next_to_clean == rrd_ring->count)
-			rrd_next_to_clean = 0;
-		count++;
-
-		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
-			if (!(rrd->err_flg &
-				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
-				| ERR_FLAG_LEN))) {
-				/* packet error, don't need upstream */
-				buffer_info->alloced = 0;
-				rrd->xsz.valid = 0;
-				continue;
-			}
-		}
-
-		/* Good Receive */
-		pci_unmap_page(adapter->pdev, buffer_info->dma,
-			       buffer_info->length, PCI_DMA_FROMDEVICE);
-		skb = buffer_info->skb;
-		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
-
-		skb_put(skb, length - ETH_FCS_LEN);
-
-		/* Receive Checksum Offload */
-		atl1_rx_checksum(adapter, rrd, skb);
-		skb->protocol = eth_type_trans(skb, adapter->netdev);
-
-		if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
-			u16 vlan_tag = (rrd->vlan_tag >> 4) |
-					((rrd->vlan_tag & 7) << 13) |
-					((rrd->vlan_tag & 8) << 9);
-			vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
-		} else
-			netif_rx(skb);
-
-		/* let protocol layer free skb */
-		buffer_info->skb = NULL;
-		buffer_info->alloced = 0;
-		rrd->xsz.valid = 0;
-
-		adapter->netdev->last_rx = jiffies;
-	}
-
-	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
-
-	atl1_alloc_rx_buffers(adapter);
-
-	/* update mailbox ? */
-	if (count) {
-		u32 tpd_next_to_use;
-		u32 rfd_next_to_use;
-
-		spin_lock(&adapter->mb_lock);
-
-		tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
-		rfd_next_to_use =
-		    atomic_read(&adapter->rfd_ring.next_to_use);
-		rrd_next_to_clean =
-		    atomic_read(&adapter->rrd_ring.next_to_clean);
-		value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
-			MB_RFD_PROD_INDX_SHIFT) |
-                        ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
-			MB_RRD_CONS_INDX_SHIFT) |
-                        ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
-			MB_TPD_PROD_INDX_SHIFT);
-		iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
-		spin_unlock(&adapter->mb_lock);
-	}
-}
-
-static void atl1_intr_tx(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	u16 sw_tpd_next_to_clean;
-	u16 cmb_tpd_next_to_clean;
-
-	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
-	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
-
-	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
-		struct tx_packet_desc *tpd;
-
-		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
-		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
-		if (buffer_info->dma) {
-			pci_unmap_page(adapter->pdev, buffer_info->dma,
-				       buffer_info->length, PCI_DMA_TODEVICE);
-			buffer_info->dma = 0;
-		}
-
-		if (buffer_info->skb) {
-			dev_kfree_skb_irq(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-		tpd->buffer_addr = 0;
-		tpd->desc.data = 0;
-
-		if (++sw_tpd_next_to_clean == tpd_ring->count)
-			sw_tpd_next_to_clean = 0;
-	}
-	atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
-
-	if (netif_queue_stopped(adapter->netdev)
-	    && netif_carrier_ok(adapter->netdev))
-		netif_wake_queue(adapter->netdev);
-}
-
-static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
-{
-	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
-	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
-	return ((next_to_clean > next_to_use) ?
-		next_to_clean - next_to_use - 1 :
-		tpd_ring->count + next_to_clean - next_to_use - 1);
-}
-
-static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
-			 struct tso_param *tso)
-{
-	/* We enter this function holding a spinlock. */
-	u8 ipofst;
-	int err;
-
-	if (skb_shinfo(skb)->gso_size) {
-		if (skb_header_cloned(skb)) {
-			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-			if (unlikely(err))
-				return err;
-		}
-
-		if (skb->protocol == ntohs(ETH_P_IP)) {
-			struct iphdr *iph = ip_hdr(skb);
-
-			iph->tot_len = 0;
-			iph->check = 0;
-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-				iph->daddr, 0, IPPROTO_TCP, 0);
-			ipofst = skb_network_offset(skb);
-			if (ipofst != ETH_HLEN) /* 802.3 frame */
-				tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
-
-			tso->tsopl |= (iph->ihl &
-				CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
-			tso->tsopl |= (tcp_hdrlen(skb) &
-				TSO_PARAM_TCPHDRLEN_MASK) <<
-				TSO_PARAM_TCPHDRLEN_SHIFT;
-			tso->tsopl |= (skb_shinfo(skb)->gso_size &
-				TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
-			tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
-			tso->tsopl |= 1 << TSO_PARAM_TCPCKSUM_SHIFT;
-			tso->tsopl |= 1 << TSO_PARAM_SEGMENT_SHIFT;
-			return true;
-		}
-	}
-	return false;
-}
-
-static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
-	struct csum_param *csum)
-{
-	u8 css, cso;
-
-	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-		cso = skb_transport_offset(skb);
-		css = cso + skb->csum_offset;
-		if (unlikely(cso & 0x1)) {
-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-				"payload offset not an even number\n");
-			return -1;
-		}
-		csum->csumpl |= (cso & CSUM_PARAM_PLOADOFFSET_MASK) <<
-			CSUM_PARAM_PLOADOFFSET_SHIFT;
-		csum->csumpl |= (css & CSUM_PARAM_XSUMOFFSET_MASK) <<
-			CSUM_PARAM_XSUMOFFSET_SHIFT;
-		csum->csumpl |= 1 << CSUM_PARAM_CUSTOMCKSUM_SHIFT;
-		return true;
-	}
-
-	return true;
-}
-
-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
-	bool tcp_seg)
-{
-	/* We enter this function holding a spinlock. */
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	struct page *page;
-	int first_buf_len = skb->len;
-	unsigned long offset;
-	unsigned int nr_frags;
-	unsigned int f;
-	u16 tpd_next_to_use;
-	u16 proto_hdr_len;
-	u16 len12;
-
-	first_buf_len -= skb->data_len;
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
-	buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
-	if (unlikely(buffer_info->skb))
-		BUG();
-	buffer_info->skb = NULL;	/* put skb in last TPD */
-
-	if (tcp_seg) {
-		/* TSO/GSO */
-		proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		buffer_info->length = proto_hdr_len;
-		page = virt_to_page(skb->data);
-		offset = (unsigned long)skb->data & ~PAGE_MASK;
-		buffer_info->dma = pci_map_page(adapter->pdev, page,
-						offset, proto_hdr_len,
-						PCI_DMA_TODEVICE);
-
-		if (++tpd_next_to_use == tpd_ring->count)
-			tpd_next_to_use = 0;
-
-		if (first_buf_len > proto_hdr_len) {
-			int i, m;
-
-			len12 = first_buf_len - proto_hdr_len;
-			m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) /
-				ATL1_MAX_TX_BUF_LEN;
-			for (i = 0; i < m; i++) {
-				buffer_info =
-				    &tpd_ring->buffer_info[tpd_next_to_use];
-				buffer_info->skb = NULL;
-				buffer_info->length =
-				    (ATL1_MAX_TX_BUF_LEN >=
-				     len12) ? ATL1_MAX_TX_BUF_LEN : len12;
-				len12 -= buffer_info->length;
-				page = virt_to_page(skb->data +
-					(proto_hdr_len +
-					i * ATL1_MAX_TX_BUF_LEN));
-				offset = (unsigned long)(skb->data +
-					(proto_hdr_len +
-					i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK;
-				buffer_info->dma = pci_map_page(adapter->pdev,
-					page, offset, buffer_info->length,
-					PCI_DMA_TODEVICE);
-				if (++tpd_next_to_use == tpd_ring->count)
-					tpd_next_to_use = 0;
-			}
-		}
-	} else {
-		/* not TSO/GSO */
-		buffer_info->length = first_buf_len;
-		page = virt_to_page(skb->data);
-		offset = (unsigned long)skb->data & ~PAGE_MASK;
-		buffer_info->dma = pci_map_page(adapter->pdev, page,
-			offset, first_buf_len, PCI_DMA_TODEVICE);
-		if (++tpd_next_to_use == tpd_ring->count)
-			tpd_next_to_use = 0;
-	}
-
-	for (f = 0; f < nr_frags; f++) {
-		struct skb_frag_struct *frag;
-		u16 lenf, i, m;
-
-		frag = &skb_shinfo(skb)->frags[f];
-		lenf = frag->size;
-
-		m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN;
-		for (i = 0; i < m; i++) {
-			buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
-			if (unlikely(buffer_info->skb))
-				BUG();
-			buffer_info->skb = NULL;
-			buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ?
-				ATL1_MAX_TX_BUF_LEN : lenf;
-			lenf -= buffer_info->length;
-			buffer_info->dma = pci_map_page(adapter->pdev,
-				frag->page,
-				frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
-				buffer_info->length, PCI_DMA_TODEVICE);
-
-			if (++tpd_next_to_use == tpd_ring->count)
-				tpd_next_to_use = 0;
-		}
-	}
-
-	/* last tpd's buffer-info */
-	buffer_info->skb = skb;
-}
-
-static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
-       union tpd_descr *descr)
-{
-	/* We enter this function holding a spinlock. */
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	int j;
-	u32 val;
-	struct atl1_buffer *buffer_info;
-	struct tx_packet_desc *tpd;
-	u16 tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
-
-	for (j = 0; j < count; j++) {
-		buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
-		tpd = ATL1_TPD_DESC(&adapter->tpd_ring, tpd_next_to_use);
-		tpd->desc.csum.csumpu = descr->csum.csumpu;
-		tpd->desc.csum.csumpl = descr->csum.csumpl;
-		tpd->desc.tso.tsopu = descr->tso.tsopu;
-		tpd->desc.tso.tsopl = descr->tso.tsopl;
-		tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
-		tpd->desc.data = descr->data;
-		tpd->desc.csum.csumpu |= (cpu_to_le16(buffer_info->length) &
-			CSUM_PARAM_BUFLEN_MASK) << CSUM_PARAM_BUFLEN_SHIFT;
-
-		val = (descr->tso.tsopl >> TSO_PARAM_SEGMENT_SHIFT) &
-			TSO_PARAM_SEGMENT_MASK;
-		if (val && !j)
-			tpd->desc.tso.tsopl |= 1 << TSO_PARAM_HDRFLAG_SHIFT;
-
-		if (j == (count - 1))
-			tpd->desc.csum.csumpl |= 1 << CSUM_PARAM_EOP_SHIFT;
-
-		if (++tpd_next_to_use == tpd_ring->count)
-			tpd_next_to_use = 0;
-	}
-	/*
-	 * Force memory writes to complete before letting h/w
-	 * know there are new descriptors to fetch.  (Only
-	 * applicable for weak-ordered memory model archs,
-	 * such as IA-64).
-	 */
-	wmb();
-
-	atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
-}
-
-static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int len = skb->len;
-	int tso;
-	int count = 1;
-	int ret_val;
-	u32 val;
-	union tpd_descr param;
-	u16 frag_size;
-	u16 vlan_tag;
-	unsigned long flags;
-	unsigned int nr_frags = 0;
-	unsigned int mss = 0;
-	unsigned int f;
-	unsigned int proto_hdr_len;
-
-	len -= skb->data_len;
-
-	if (unlikely(skb->len == 0)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	param.data = 0;
-	param.tso.tsopu = 0;
-	param.tso.tsopl = 0;
-	param.csum.csumpu = 0;
-	param.csum.csumpl = 0;
-
-	/* nr_frags will be nonzero if we're doing scatter/gather (SG) */
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	for (f = 0; f < nr_frags; f++) {
-		frag_size = skb_shinfo(skb)->frags[f].size;
-		if (frag_size)
-			count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
-				ATL1_MAX_TX_BUF_LEN;
-	}
-
-	/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
-	mss = skb_shinfo(skb)->gso_size;
-	if (mss) {
-		if (skb->protocol == htons(ETH_P_IP)) {
-			proto_hdr_len = (skb_transport_offset(skb) +
-					 tcp_hdrlen(skb));
-			if (unlikely(proto_hdr_len > len)) {
-				dev_kfree_skb_any(skb);
-				return NETDEV_TX_OK;
-			}
-			/* need additional TPD ? */
-			if (proto_hdr_len != len)
-				count += (len - proto_hdr_len +
-					ATL1_MAX_TX_BUF_LEN - 1) /
-					ATL1_MAX_TX_BUF_LEN;
-		}
-	}
-
-	if (!spin_trylock_irqsave(&adapter->lock, flags)) {
-		/* Can't get lock - tell upper layer to requeue */
-		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n");
-		return NETDEV_TX_LOCKED;
-	}
-
-	if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
-		/* not enough descriptors */
-		netif_stop_queue(netdev);
-		spin_unlock_irqrestore(&adapter->lock, flags);
-		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n");
-		return NETDEV_TX_BUSY;
-	}
-
-	param.data = 0;
-
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
-		vlan_tag = vlan_tx_tag_get(skb);
-		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
-			((vlan_tag >> 9) & 0x8);
-		param.csum.csumpl |= 1 << CSUM_PARAM_INSVLAG_SHIFT;
-		param.csum.csumpu |= (vlan_tag & CSUM_PARAM_VALANTAG_MASK) <<
-			CSUM_PARAM_VALAN_SHIFT;
-	}
-
-	tso = atl1_tso(adapter, skb, &param.tso);
-	if (tso < 0) {
-		spin_unlock_irqrestore(&adapter->lock, flags);
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (!tso) {
-		ret_val = atl1_tx_csum(adapter, skb, &param.csum);
-		if (ret_val < 0) {
-			spin_unlock_irqrestore(&adapter->lock, flags);
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		}
-	}
-
-	val = (param.csum.csumpl >> CSUM_PARAM_SEGMENT_SHIFT) &
-		CSUM_PARAM_SEGMENT_MASK;
-	atl1_tx_map(adapter, skb, 1 == val);
-	atl1_tx_queue(adapter, count, &param);
-	netdev->trans_start = jiffies;
-	spin_unlock_irqrestore(&adapter->lock, flags);
-	atl1_update_mailbox(adapter);
-	return NETDEV_TX_OK;
-}
-
-/*
- * atl1_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl1_intr(int irq, void *data)
-{
-	struct atl1_adapter *adapter = netdev_priv(data);
-	u32 status;
-	int max_ints = 10;
-
-	status = adapter->cmb.cmb->int_stats;
-	if (!status)
-		return IRQ_NONE;
-
-	do {
-		/* clear CMB interrupt status at once */
-		adapter->cmb.cmb->int_stats = 0;
-
-		if (status & ISR_GPHY)	/* clear phy status */
-			atl1_clear_phy_int(adapter);
-
-		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
-		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
-
-		/* check if SMB intr */
-		if (status & ISR_SMB)
-			atl1_inc_smb(adapter);
-
-		/* check if PCIE PHY Link down */
-		if (status & ISR_PHY_LINKDOWN) {
-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-				"pcie phy link down %x\n", status);
-			if (netif_running(adapter->netdev)) {	/* reset MAC */
-				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-				schedule_work(&adapter->pcie_dma_to_rst_task);
-				return IRQ_HANDLED;
-			}
-		}
-
-		/* check if DMA read/write error ? */
-		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-				"pcie DMA r/w error (status = 0x%x)\n",
-				status);
-			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-			schedule_work(&adapter->pcie_dma_to_rst_task);
-			return IRQ_HANDLED;
-		}
-
-		/* link event */
-		if (status & ISR_GPHY) {
-			adapter->soft_stats.tx_carrier_errors++;
-			atl1_check_for_link(adapter);
-		}
-
-		/* transmit event */
-		if (status & ISR_CMB_TX)
-			atl1_intr_tx(adapter);
-
-		/* rx exception */
-		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
-			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-				ISR_HOST_RRD_OV))
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"rx exception, ISR = 0x%x\n", status);
-			atl1_intr_rx(adapter);
-		}
-
-		if (--max_ints < 0)
-			break;
-
-	} while ((status = adapter->cmb.cmb->int_stats));
-
-	/* re-enable Interrupt */
-	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
-	return IRQ_HANDLED;
-}
-
-/*
- * atl1_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_watchdog(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-
-	/* Reset the timer */
-	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-}
-
-/*
- * atl1_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_phy_config(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-	struct atl1_hw *hw = &adapter->hw;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	adapter->phy_timer_pending = false;
-	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
-	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
-	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-/*
- * atl1_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atl1_tx_timeout(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->tx_timeout_task);
-}
-
-/*
- * Orphaned vendor comment left intact here:
- * <vendor comment>
- * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
- * will assert. We do soft reset <0x1400=1> according
- * with the SPEC. BUT, it seemes that PCIE or DMA
- * state-machine will not be reset. DMAR_TO_INT will
- * assert again and again.
- * </vendor comment>
- */
-static void atl1_tx_timeout_task(struct work_struct *work)
-{
-	struct atl1_adapter *adapter =
-		container_of(work, struct atl1_adapter, tx_timeout_task);
-	struct net_device *netdev = adapter->netdev;
-
-	netif_device_detach(netdev);
-	atl1_down(adapter);
-	atl1_up(adapter);
-	netif_device_attach(netdev);
-}
-
-/*
- * atl1_link_chg_task - deal with link change event Out of interrupt context
- */
-static void atl1_link_chg_task(struct work_struct *work)
-{
-	struct atl1_adapter *adapter =
-               container_of(work, struct atl1_adapter, link_chg_task);
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	atl1_check_link(adapter);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static void atl1_vlan_rx_register(struct net_device *netdev,
-	struct vlan_group *grp)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	u32 ctrl;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	/* atl1_irq_disable(adapter); */
-	adapter->vlgrp = grp;
-
-	if (grp) {
-		/* enable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl |= MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	} else {
-		/* disable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	}
-
-	/* atl1_irq_enable(adapter); */
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static void atl1_restore_vlan(struct atl1_adapter *adapter)
-{
-	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
-}
-
-int atl1_reset(struct atl1_adapter *adapter)
-{
-	int ret;
-
-	ret = atl1_reset_hw(&adapter->hw);
-	if (ret != ATL1_SUCCESS)
-		return ret;
-	return atl1_init_hw(&adapter->hw);
-}
-
-s32 atl1_up(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int err;
-	int irq_flags = IRQF_SAMPLE_RANDOM;
-
-	/* hardware has been reset, we need to reload some things */
-	atl1_set_multi(netdev);
-	atl1_init_ring_ptrs(adapter);
-	atl1_restore_vlan(adapter);
-	err = atl1_alloc_rx_buffers(adapter);
-	if (unlikely(!err))		/* no RX BUFFER allocated */
-		return -ENOMEM;
-
-	if (unlikely(atl1_configure(adapter))) {
-		err = -EIO;
-		goto err_up;
-	}
-
-	err = pci_enable_msi(adapter->pdev);
-	if (err) {
-		dev_info(&adapter->pdev->dev,
-			"Unable to enable MSI: %d\n", err);
-		irq_flags |= IRQF_SHARED;
-	}
-
-	err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
-			netdev->name, netdev);
-	if (unlikely(err))
-		goto err_up;
-
-	mod_timer(&adapter->watchdog_timer, jiffies);
-	atl1_irq_enable(adapter);
-	atl1_check_link(adapter);
-	return 0;
-
-err_up:
-	pci_disable_msi(adapter->pdev);
-	/* free rx_buffers */
-	atl1_clean_rx_ring(adapter);
-	return err;
-}
-
-void atl1_down(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	del_timer_sync(&adapter->watchdog_timer);
-	del_timer_sync(&adapter->phy_config_timer);
-	adapter->phy_timer_pending = false;
-
-	atl1_irq_disable(adapter);
-	free_irq(adapter->pdev->irq, netdev);
-	pci_disable_msi(adapter->pdev);
-	atl1_reset_hw(&adapter->hw);
-	adapter->cmb.cmb->int_stats = 0;
-
-	adapter->link_speed = SPEED_0;
-	adapter->link_duplex = -1;
-	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-
-	atl1_clean_tx_ring(adapter);
-	atl1_clean_rx_ring(adapter);
-}
-
-/*
- * atl1_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * The open entry point is called when a network interface is made
- * active by the system (IFF_UP).  At this point all resources needed
- * for transmit and receive operations are allocated, the interrupt
- * handler is registered with the OS, the watchdog timer is started,
- * and the stack is notified that the interface is ready.
- */
-static int atl1_open(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int err;
-
-	/* allocate transmit descriptors */
-	err = atl1_setup_ring_resources(adapter);
-	if (err)
-		return err;
-
-	err = atl1_up(adapter);
-	if (err)
-		goto err_up;
-
-	return 0;
-
-err_up:
-	atl1_reset(adapter);
-	return err;
-}
-
-/*
- * atl1_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * Returns 0, this is not allowed to fail
- *
- * The close entry point is called when an interface is de-activated
- * by the OS.  The hardware is still under the drivers control, but
- * needs to be disabled.  A global MAC reset is issued to stop the
- * hardware, and all transmit and receive resources are freed.
- */
-static int atl1_close(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	atl1_down(adapter);
-	atl1_free_ring_resources(adapter);
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	u32 ctrl = 0;
-	u32 wufc = adapter->wol;
-
-	netif_device_detach(netdev);
-	if (netif_running(netdev))
-		atl1_down(adapter);
-
-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
-	if (ctrl & BMSR_LSTATUS)
-		wufc &= ~ATL1_WUFC_LNKC;
-
-	/* reduce speed to 10/100M */
-	if (wufc) {
-		atl1_phy_enter_power_saving(hw);
-		/* if resume, let driver to re- setup link */
-		hw->phy_configured = false;
-		atl1_set_mac_addr(hw);
-		atl1_set_multi(netdev);
-
-		ctrl = 0;
-		/* turn on magic packet wol */
-		if (wufc & ATL1_WUFC_MAG)
-			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-
-		/* turn on Link change WOL */
-		if (wufc & ATL1_WUFC_LNKC)
-			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
-		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
-
-		/* turn on all-multi mode if wake on multicast is enabled */
-		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_DBG;
-		ctrl &= ~MAC_CTRL_PROMIS_EN;
-		if (wufc & ATL1_WUFC_MC)
-			ctrl |= MAC_CTRL_MC_ALL_EN;
-		else
-			ctrl &= ~MAC_CTRL_MC_ALL_EN;
-
-		/* turn on broadcast mode if wake on-BC is enabled */
-		if (wufc & ATL1_WUFC_BC)
-			ctrl |= MAC_CTRL_BC_EN;
-		else
-			ctrl &= ~MAC_CTRL_BC_EN;
-
-		/* enable RX */
-		ctrl |= MAC_CTRL_RX_EN;
-		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
-		pci_enable_wake(pdev, PCI_D3hot, 1);
-		pci_enable_wake(pdev, PCI_D3cold, 1);
-	} else {
-		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_enable_wake(pdev, PCI_D3cold, 0);
-	}
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int atl1_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u32 ret_val;
-
-	pci_set_power_state(pdev, 0);
-	pci_restore_state(pdev);
-
-	ret_val = pci_enable_device(pdev);
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
-	atl1_reset(adapter);
-
-	if (netif_running(netdev))
-		atl1_up(adapter);
-	netif_device_attach(netdev);
-
-	atl1_via_workaround(adapter);
-
-	return 0;
-}
-#else
-#define atl1_suspend NULL
-#define atl1_resume NULL
-#endif
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void atl1_poll_controller(struct net_device *netdev)
-{
-	disable_irq(netdev->irq);
-	atl1_intr(netdev->irq, netdev);
-	enable_irq(netdev->irq);
-}
-#endif
-
-/*
- * atl1_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in atl1_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * atl1_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- */
-static int __devinit atl1_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct atl1_adapter *adapter;
-	static int cards_found = 0;
-	int err;
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-
-	/*
-	 * The atl1 chip can DMA to 64-bit addresses, but it uses a single
-	 * shared register for the high 32 bits, so only a single, aligned,
-	 * 4 GB physical address range can be used at a time.
-	 *
-	 * Supporting 64-bit DMA on this hardware is more trouble than it's
-	 * worth.  It is far easier to limit to 32-bit DMA than update
-	 * various kernel subsystems to support the mechanics required by a
-	 * fixed-high-32-bit system.
-	 */
-	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-	if (err) {
-		dev_err(&pdev->dev, "no usable DMA configuration\n");
-		goto err_dma;
-	}
-	/* Mark all PCI regions associated with PCI device
-	 * pdev as being reserved by owner atl1_driver_name
-	 */
-	err = pci_request_regions(pdev, atl1_driver_name);
-	if (err)
-		goto err_request_regions;
-
-	/* Enables bus-mastering on the device and calls
-	 * pcibios_set_master to do the needed arch specific settings
-	 */
-	pci_set_master(pdev);
-
-	netdev = alloc_etherdev(sizeof(struct atl1_adapter));
-	if (!netdev) {
-		err = -ENOMEM;
-		goto err_alloc_etherdev;
-	}
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	pci_set_drvdata(pdev, netdev);
-	adapter = netdev_priv(netdev);
-	adapter->netdev = netdev;
-	adapter->pdev = pdev;
-	adapter->hw.back = adapter;
-
-	adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
-	if (!adapter->hw.hw_addr) {
-		err = -EIO;
-		goto err_pci_iomap;
-	}
-	/* get device revision number */
-	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
-		(REG_MASTER_CTRL + 2));
-	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
-
-	/* set default ring resource counts */
-	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
-	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
-
-	adapter->mii.dev = netdev;
-	adapter->mii.mdio_read = mdio_read;
-	adapter->mii.mdio_write = mdio_write;
-	adapter->mii.phy_id_mask = 0x1f;
-	adapter->mii.reg_num_mask = 0x1f;
-
-	netdev->open = &atl1_open;
-	netdev->stop = &atl1_close;
-	netdev->hard_start_xmit = &atl1_xmit_frame;
-	netdev->get_stats = &atl1_get_stats;
-	netdev->set_multicast_list = &atl1_set_multi;
-	netdev->set_mac_address = &atl1_set_mac;
-	netdev->change_mtu = &atl1_change_mtu;
-	netdev->do_ioctl = &atl1_ioctl;
-	netdev->tx_timeout = &atl1_tx_timeout;
-	netdev->watchdog_timeo = 5 * HZ;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	netdev->poll_controller = atl1_poll_controller;
-#endif
-	netdev->vlan_rx_register = atl1_vlan_rx_register;
-
-	netdev->ethtool_ops = &atl1_ethtool_ops;
-	adapter->bd_number = cards_found;
-
-	/* setup the private structure */
-	err = atl1_sw_init(adapter);
-	if (err)
-		goto err_common;
-
-	netdev->features = NETIF_F_HW_CSUM;
-	netdev->features |= NETIF_F_SG;
-	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
-
-	/*
-	 * FIXME - Until tso performance gets fixed, disable the feature.
-	 * Enable it with ethtool -K if desired.
-	 */
-	/* netdev->features |= NETIF_F_TSO; */
-
-	netdev->features |= NETIF_F_LLTX;
-
-	/*
-	 * patch for some L1 of old version,
-	 * the final version of L1 may not need these
-	 * patches
-	 */
-	/* atl1_pcie_patch(adapter); */
-
-	/* really reset GPHY core */
-	iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
-
-	/*
-	 * reset the controller to
-	 * put the device in a known good starting state
-	 */
-	if (atl1_reset_hw(&adapter->hw)) {
-		err = -EIO;
-		goto err_common;
-	}
-
-	/* copy the MAC address out of the EEPROM */
-	atl1_read_mac_addr(&adapter->hw);
-	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
-
-	if (!is_valid_ether_addr(netdev->dev_addr)) {
-		err = -EIO;
-		goto err_common;
-	}
-
-	atl1_check_options(adapter);
-
-	/* pre-init the MAC, and setup link */
-	err = atl1_init_hw(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		goto err_common;
-	}
-
-	atl1_pcie_patch(adapter);
-	/* assume we have no link for now */
-	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-
-	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &atl1_watchdog;
-	adapter->watchdog_timer.data = (unsigned long)adapter;
-
-	init_timer(&adapter->phy_config_timer);
-	adapter->phy_config_timer.function = &atl1_phy_config;
-	adapter->phy_config_timer.data = (unsigned long)adapter;
-	adapter->phy_timer_pending = false;
-
-	INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
-
-	INIT_WORK(&adapter->link_chg_task, atl1_link_chg_task);
-
-	INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
-
-	err = register_netdev(netdev);
-	if (err)
-		goto err_common;
-
-	cards_found++;
-	atl1_via_workaround(adapter);
-	return 0;
-
-err_common:
-	pci_iounmap(pdev, adapter->hw.hw_addr);
-err_pci_iomap:
-	free_netdev(netdev);
-err_alloc_etherdev:
-	pci_release_regions(pdev);
-err_dma:
-err_request_regions:
-	pci_disable_device(pdev);
-	return err;
-}
-
-/*
- * atl1_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * atl1_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.  The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- */
-static void __devexit atl1_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter;
-	/* Device not available. Return. */
-	if (!netdev)
-		return;
-
-	adapter = netdev_priv(netdev);
-
-	/* Some atl1 boards lack persistent storage for their MAC, and get it
-	 * from the BIOS during POST.  If we've been messing with the MAC
-	 * address, we need to save the permanent one.
-	 */
-	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
-		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
-			ETH_ALEN);
-		atl1_set_mac_addr(&adapter->hw);
-	}
-
-	iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
-	unregister_netdev(netdev);
-	pci_iounmap(pdev, adapter->hw.hw_addr);
-	pci_release_regions(pdev);
-	free_netdev(netdev);
-	pci_disable_device(pdev);
-}
-
-static struct pci_driver atl1_driver = {
-	.name = atl1_driver_name,
-	.id_table = atl1_pci_tbl,
-	.probe = atl1_probe,
-	.remove = __devexit_p(atl1_remove),
-	.suspend = atl1_suspend,
-	.resume = atl1_resume
-};
-
-/*
- * atl1_exit_module - Driver Exit Cleanup Routine
- *
- * atl1_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl1_exit_module(void)
-{
-	pci_unregister_driver(&atl1_driver);
-}
-
-/*
- * atl1_init_module - Driver Registration Routine
- *
- * atl1_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl1_init_module(void)
-{
-	return pci_register_driver(&atl1_driver);
-}
-
-module_init(atl1_init_module);
-module_exit(atl1_exit_module);
diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c
deleted file mode 100644
index 4246bb9..0000000
--- a/drivers/net/atl1/atl1_param.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/types.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include "atl1.h"
-
-/*
- * This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-#define ATL1_MAX_NIC 4
-
-#define OPTION_UNSET    -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
-
-/*
- * Interrupt Moderate Timer in units of 2 us
- *
- * Valid Range: 10-65535
- *
- * Default Value: 100 (200us)
- */
-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
-static int num_int_mod_timer = 0;
-module_param_array_named(int_mod_timer, int_mod_timer, int, &num_int_mod_timer, 0);
-MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
-
-/*
- * flash_vendor
- *
- * Valid Range: 0-2
- *
- * 0 - Atmel
- * 1 - SST
- * 2 - ST
- *
- * Default Value: 0
- */
-static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
-static int num_flash_vendor = 0;
-module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
-MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
-
-#define DEFAULT_INT_MOD_CNT	100	/* 200us */
-#define MAX_INT_MOD_CNT		65000
-#define MIN_INT_MOD_CNT		50
-
-#define FLASH_VENDOR_DEFAULT	0
-#define FLASH_VENDOR_MIN	0
-#define FLASH_VENDOR_MAX	2
-
-struct atl1_option {
-	enum { enable_option, range_option, list_option } type;
-	char *name;
-	char *err;
-	int def;
-	union {
-		struct {	/* range_option info */
-			int min;
-			int max;
-		} r;
-		struct {	/* list_option info */
-			int nr;
-			struct atl1_opt_list {
-				int i;
-				char *str;
-			} *p;
-		} l;
-	} arg;
-};
-
-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, struct pci_dev *pdev)
-{
-	if (*value == OPTION_UNSET) {
-		*value = opt->def;
-		return 0;
-	}
-
-	switch (opt->type) {
-	case enable_option:
-		switch (*value) {
-		case OPTION_ENABLED:
-			dev_info(&pdev->dev, "%s enabled\n", opt->name);
-			return 0;
-		case OPTION_DISABLED:
-			dev_info(&pdev->dev, "%s disabled\n", opt->name);
-			return 0;
-		}
-		break;
-	case range_option:
-		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-			dev_info(&pdev->dev, "%s set to %i\n", opt->name,
-				*value);
-			return 0;
-		}
-		break;
-	case list_option:{
-			int i;
-			struct atl1_opt_list *ent;
-
-			for (i = 0; i < opt->arg.l.nr; i++) {
-				ent = &opt->arg.l.p[i];
-				if (*value == ent->i) {
-					if (ent->str[0] != '\0')
-						dev_info(&pdev->dev, "%s\n",
-							ent->str);
-					return 0;
-				}
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
-		opt->name, *value, opt->err);
-	*value = opt->def;
-	return -1;
-}
-
-/*
- * atl1_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- */
-void __devinit atl1_check_options(struct atl1_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	int bd = adapter->bd_number;
-	if (bd >= ATL1_MAX_NIC) {
-		dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
-		dev_notice(&pdev->dev, "using defaults for all values\n");
-	}
-	{			/* Interrupt Moderate Timer */
-		struct atl1_option opt = {
-			.type = range_option,
-			.name = "Interrupt Moderator Timer",
-			.err = "using default of "
-				__MODULE_STRING(DEFAULT_INT_MOD_CNT),
-			.def = DEFAULT_INT_MOD_CNT,
-			.arg = {.r =
-				{.min = MIN_INT_MOD_CNT,.max = MAX_INT_MOD_CNT}}
-		};
-		int val;
-		if (num_int_mod_timer > bd) {
-			val = int_mod_timer[bd];
-			atl1_validate_option(&val, &opt, pdev);
-			adapter->imt = (u16) val;
-		} else
-			adapter->imt = (u16) (opt.def);
-	}
-
-	{			/* Flash Vendor */
-		struct atl1_option opt = {
-			.type = range_option,
-			.name = "SPI Flash Vendor",
-			.err = "using default of "
-				__MODULE_STRING(FLASH_VENDOR_DEFAULT),
-			.def = DEFAULT_INT_MOD_CNT,
-			.arg = {.r =
-				{.min = FLASH_VENDOR_MIN,.max =
-				 FLASH_VENDOR_MAX}}
-		};
-		int val;
-		if (num_flash_vendor > bd) {
-			val = flash_vendor[bd];
-			atl1_validate_option(&val, &opt, pdev);
-			adapter->hw.flash_vendor = (u8) val;
-		} else
-			adapter->hw.flash_vendor = (u8) (opt.def);
-	}
-}
diff --git a/drivers/net/atlx/Makefile b/drivers/net/atlx/Makefile
new file mode 100644
index 0000000..ca45553
--- /dev/null
+++ b/drivers/net/atlx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ATL1)	+= atl1.o
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
new file mode 100644
index 0000000..5586fc6
--- /dev/null
+++ b/drivers/net/atlx/atl1.c
@@ -0,0 +1,3564 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * Contact Information:
+ * Xiong Huang <xiong_huang@attansic.com>
+ * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
+ * Xinzhu  302, TAIWAN, REPUBLIC OF CHINA
+ *
+ * Chris Snook <csnook@redhat.com>
+ * Jay Cliburn <jcliburn@gmail.com>
+ *
+ * This version is adapted from the Attansic reference driver for
+ * inclusion in the Linux kernel.  It is currently under heavy development.
+ * A very incomplete list of things that need to be dealt with:
+ *
+ * TODO:
+ * Wake on LAN.
+ * Add more ethtool functions.
+ * Fix abstruse irq enable/disable condition described here:
+ *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
+ *
+ * NEEDS TESTING:
+ * VLAN
+ * multicast
+ * promiscuous mode
+ * interrupt coalescing
+ * SMP torture testing
+ */
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+#include <linux/compiler.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+#include <linux/ip.h>
+#include <linux/irqflags.h>
+#include <linux/irqreturn.h>
+#include <linux/jiffies.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/pm.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/tcp.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include <net/checksum.h>
+
+#include "atl1.h"
+
+/* Temporary hack for merging atl1 and atl2 */
+#include "atlx.c"
+
+/*
+ * atl1_pci_tbl - PCI Device ID Table
+ */
+static const struct pci_device_id atl1_pci_tbl[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
+	/* required last entry */
+	{0,}
+};
+MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
+
+static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
+	NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
+
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+static s32 atl1_reset_hw(struct atl1_hw *hw)
+{
+	struct pci_dev *pdev = hw->back->pdev;
+	struct atl1_adapter *adapter = hw->back;
+	u32 icr;
+	int i;
+
+	/*
+	 * Clear Interrupt mask to stop board from generating
+	 * interrupts & Clear any pending interrupt events
+	 */
+	/*
+	 * iowrite32(0, hw->hw_addr + REG_IMR);
+	 * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
+	 */
+
+	/*
+	 * Issue Soft Reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
+	ioread32(hw->hw_addr + REG_MASTER_CTRL);
+
+	iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
+	ioread16(hw->hw_addr + REG_PHY_ENABLE);
+
+	/* delay about 1ms */
+	msleep(1);
+
+	/* Wait at least 10ms for All module to be Idle */
+	for (i = 0; i < 10; i++) {
+		icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
+		if (!icr)
+			break;
+		/* delay 1 ms */
+		msleep(1);
+		/* FIXME: still the right way to do this? */
+		cpu_relax();
+	}
+
+	if (icr) {
+		if (netif_msg_hw(adapter))
+			dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
+		return icr;
+	}
+
+	return 0;
+}
+
+/* function about EEPROM
+ *
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+static int atl1_check_eeprom_exist(struct atl1_hw *hw)
+{
+	u32 value;
+	value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+	if (value & SPI_FLASH_CTRL_EN_VPD) {
+		value &= ~SPI_FLASH_CTRL_EN_VPD;
+		iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+	}
+
+	value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
+	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
+{
+	int i;
+	u32 control;
+
+	if (offset & 3)
+		/* address do not align */
+		return false;
+
+	iowrite32(0, hw->hw_addr + REG_VPD_DATA);
+	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+	iowrite32(control, hw->hw_addr + REG_VPD_CAP);
+	ioread32(hw->hw_addr + REG_VPD_CAP);
+
+	for (i = 0; i < 10; i++) {
+		msleep(2);
+		control = ioread32(hw->hw_addr + REG_VPD_CAP);
+		if (control & VPD_CAP_VPD_FLAG)
+			break;
+	}
+	if (control & VPD_CAP_VPD_FLAG) {
+		*p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
+		return true;
+	}
+	/* timeout */
+	return false;
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	u32 val;
+	int i;
+
+	val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
+		MDIO_CLK_SEL_SHIFT;
+	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+	ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+	if (!(val & (MDIO_START | MDIO_BUSY))) {
+		*phy_data = (u16) val;
+		return 0;
+	}
+	return ATLX_ERR_PHY;
+}
+
+#define CUSTOM_SPI_CS_SETUP	2
+#define CUSTOM_SPI_CLK_HI	2
+#define CUSTOM_SPI_CLK_LO	2
+#define CUSTOM_SPI_CS_HOLD	2
+#define CUSTOM_SPI_CS_HI	3
+
+static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
+{
+	int i;
+	u32 value;
+
+	iowrite32(0, hw->hw_addr + REG_SPI_DATA);
+	iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
+
+	value = SPI_FLASH_CTRL_WAIT_READY |
+	    (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
+	    SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
+					     SPI_FLASH_CTRL_CLK_HI_MASK) <<
+	    SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
+					   SPI_FLASH_CTRL_CLK_LO_MASK) <<
+	    SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
+					   SPI_FLASH_CTRL_CS_HOLD_MASK) <<
+	    SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
+					    SPI_FLASH_CTRL_CS_HI_MASK) <<
+	    SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
+	    SPI_FLASH_CTRL_INS_SHIFT;
+
+	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+	value |= SPI_FLASH_CTRL_START;
+	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+	ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+	for (i = 0; i < 10; i++) {
+		msleep(1);
+		value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+		if (!(value & SPI_FLASH_CTRL_START))
+			break;
+	}
+
+	if (value & SPI_FLASH_CTRL_START)
+		return false;
+
+	*buf = ioread32(hw->hw_addr + REG_SPI_DATA);
+
+	return true;
+}
+
+/*
+ * get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1_get_permanent_address(struct atl1_hw *hw)
+{
+	u32 addr[2];
+	u32 i, control;
+	u16 reg;
+	u8 eth_addr[ETH_ALEN];
+	bool key_valid;
+
+	if (is_valid_ether_addr(hw->perm_mac_addr))
+		return 0;
+
+	/* init */
+	addr[0] = addr[1] = 0;
+
+	if (!atl1_check_eeprom_exist(hw)) {
+		reg = 0;
+		key_valid = false;
+		/* Read out all EEPROM content */
+		i = 0;
+		while (1) {
+			if (atl1_read_eeprom(hw, i + 0x100, &control)) {
+				if (key_valid) {
+					if (reg == REG_MAC_STA_ADDR)
+						addr[0] = control;
+					else if (reg == (REG_MAC_STA_ADDR + 4))
+						addr[1] = control;
+					key_valid = false;
+				} else if ((control & 0xff) == 0x5A) {
+					key_valid = true;
+					reg = (u16) (control >> 16);
+				} else
+					break;
+			} else
+				/* read error */
+				break;
+			i += 4;
+		}
+
+		*(u32 *) &eth_addr[2] = swab32(addr[0]);
+		*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+		if (is_valid_ether_addr(eth_addr)) {
+			memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+			return 0;
+		}
+		return 1;
+	}
+
+	/* see if SPI FLAGS exist ? */
+	addr[0] = addr[1] = 0;
+	reg = 0;
+	key_valid = false;
+	i = 0;
+	while (1) {
+		if (atl1_spi_read(hw, i + 0x1f000, &control)) {
+			if (key_valid) {
+				if (reg == REG_MAC_STA_ADDR)
+					addr[0] = control;
+				else if (reg == (REG_MAC_STA_ADDR + 4))
+					addr[1] = control;
+				key_valid = false;
+			} else if ((control & 0xff) == 0x5A) {
+				key_valid = true;
+				reg = (u16) (control >> 16);
+			} else
+				/* data end */
+				break;
+		} else
+			/* read error */
+			break;
+		i += 4;
+	}
+
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+	/*
+	 * On some motherboards, the MAC address is written by the
+	 * BIOS directly to the MAC register during POST, and is
+	 * not stored in eeprom.  If all else thus far has failed
+	 * to fetch the permanent MAC address, try reading it directly.
+	 */
+	addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
+	addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ * hw - Struct containing variables accessed by shared code
+ */
+s32 atl1_read_mac_addr(struct atl1_hw *hw)
+{
+	u16 i;
+
+	if (atl1_get_permanent_address(hw))
+		random_ether_addr(hw->perm_mac_addr);
+
+	for (i = 0; i < ETH_ALEN; i++)
+		hw->mac_addr[i] = hw->perm_mac_addr[i];
+	return 0;
+}
+
+/*
+ * Hashes an address to determine its location in the multicast table
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *
+ * atl1_hash_mc_addr
+ *  purpose
+ *      set hash value for a multicast address
+ *      hash calcu processing :
+ *          1. calcu 32bit CRC for multicast address
+ *          2. reverse crc with MSB to LSB
+ */
+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
+{
+	u32 crc32, value = 0;
+	int i;
+
+	crc32 = ether_crc_le(6, mc_addr);
+	for (i = 0; i < 32; i++)
+		value |= (((crc32 >> i) & 1) << (31 - i));
+
+	return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
+{
+	u32 hash_bit, hash_reg;
+	u32 mta;
+
+	/*
+	 * The HASH Table  is a register array of 2 32-bit registers.
+	 * It is treated like an array of 64 bits.  We want to set
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the
+	 * upper 7 bits of the hash value and the bit within that
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 31) & 0x1;
+	hash_bit = (hash_value >> 26) & 0x1F;
+	mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+	mta |= (1 << hash_bit);
+	iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+static s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
+{
+	int i;
+	u32 val;
+
+	val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+	    (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+	    MDIO_SUP_PREAMBLE |
+	    MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+	ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+
+	if (!(val & (MDIO_START | MDIO_BUSY)))
+		return 0;
+
+	return ATLX_ERR_PHY;
+}
+
+/*
+ * Make L001's PHY out of Power Saving State (bug)
+ * hw - Struct containing variables accessed by shared code
+ * when power on, L001's PHY always on Power saving State
+ * (Gigabit Link forbidden)
+ */
+static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
+{
+	s32 ret;
+	ret = atl1_write_phy_reg(hw, 29, 0x0029);
+	if (ret)
+		return ret;
+	return atl1_write_phy_reg(hw, 30, 0);
+}
+
+/*
+ *TODO: do something or get rid of this
+ */
+#ifdef CONFIG_PM
+static s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
+{
+/*    s32 ret_val;
+ *    u16 phy_data;
+ */
+
+/*
+    ret_val = atl1_write_phy_reg(hw, ...);
+    ret_val = atl1_write_phy_reg(hw, ...);
+    ....
+*/
+	return 0;
+}
+#endif
+
+/*
+ * Resets the PHY and make all config validate
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
+ */
+static s32 atl1_phy_reset(struct atl1_hw *hw)
+{
+	struct pci_dev *pdev = hw->back->pdev;
+	struct atl1_adapter *adapter = hw->back;
+	s32 ret_val;
+	u16 phy_data;
+
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+	else {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			    MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:
+			/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+	}
+
+	ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+	if (ret_val) {
+		u32 val;
+		int i;
+		/* pcie serdes link may be down! */
+		if (netif_msg_hw(adapter))
+			dev_dbg(&pdev->dev, "pcie phy link down\n");
+
+		for (i = 0; i < 25; i++) {
+			msleep(1);
+			val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+			if (!(val & (MDIO_START | MDIO_BUSY)))
+				break;
+		}
+
+		if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
+			if (netif_msg_hw(adapter))
+				dev_warn(&pdev->dev,
+					"pcie link down at least 25ms\n");
+			return ret_val;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ * hw - Struct containing variables accessed by shared code
+ */
+static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
+{
+	s32 ret_val;
+	s16 mii_autoneg_adv_reg;
+	s16 mii_1000t_ctrl_reg;
+
+	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
+	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+
+	/* Read the MII 1000Base-T Control Register (Address 9). */
+	mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
+
+	/*
+	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
+	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
+	 * the  1000Base-T Control Register (Address 9).
+	 */
+	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+	mii_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK;
+
+	/*
+	 * Need to parse media_type  and set up
+	 * the appropriate PHY registers.
+	 */
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+					MII_AR_10T_FD_CAPS |
+					MII_AR_100TX_HD_CAPS |
+					MII_AR_100TX_FD_CAPS);
+		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
+		break;
+
+	case MEDIA_TYPE_1000M_FULL:
+		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
+		break;
+
+	case MEDIA_TYPE_100M_FULL:
+		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+		break;
+
+	case MEDIA_TYPE_100M_HALF:
+		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+		break;
+
+	case MEDIA_TYPE_10M_FULL:
+		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+		break;
+
+	default:
+		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+		break;
+	}
+
+	/* flow control fixed to enable all */
+	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+	hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+	ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
+	if (ret_val)
+		return ret_val;
+
+	return 0;
+}
+
+/*
+ * Configures link settings.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes the hardware has previously been reset and the
+ * transmitter and receiver are not enabled.
+ */
+static s32 atl1_setup_link(struct atl1_hw *hw)
+{
+	struct pci_dev *pdev = hw->back->pdev;
+	struct atl1_adapter *adapter = hw->back;
+	s32 ret_val;
+
+	/*
+	 * Options:
+	 *  PHY will advertise value(s) parsed from
+	 *  autoneg_advertised and fc
+	 *  no matter what autoneg is , We will not wait link result.
+	 */
+	ret_val = atl1_phy_setup_autoneg_adv(hw);
+	if (ret_val) {
+		if (netif_msg_link(adapter))
+			dev_dbg(&pdev->dev,
+				"error setting up autonegotiation\n");
+		return ret_val;
+	}
+	/* SW.Reset , En-Auto-Neg if needed */
+	ret_val = atl1_phy_reset(hw);
+	if (ret_val) {
+		if (netif_msg_link(adapter))
+			dev_dbg(&pdev->dev, "error resetting phy\n");
+		return ret_val;
+	}
+	hw->phy_configured = true;
+	return ret_val;
+}
+
+static void atl1_init_flash_opcode(struct atl1_hw *hw)
+{
+	if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
+		/* Atmel */
+		hw->flash_vendor = 0;
+
+	/* Init OP table */
+	iowrite8(flash_table[hw->flash_vendor].cmd_program,
+		hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
+	iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
+		hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
+	iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
+		hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
+	iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
+		hw->hw_addr + REG_SPI_FLASH_OP_RDID);
+	iowrite8(flash_table[hw->flash_vendor].cmd_wren,
+		hw->hw_addr + REG_SPI_FLASH_OP_WREN);
+	iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
+		hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
+	iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
+		hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
+	iowrite8(flash_table[hw->flash_vendor].cmd_read,
+		hw->hw_addr + REG_SPI_FLASH_OP_READ);
+}
+
+/*
+ * Performs basic configuration of the adapter.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and  Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+static s32 atl1_init_hw(struct atl1_hw *hw)
+{
+	u32 ret_val = 0;
+
+	/* Zero out the Multicast HASH table */
+	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+	/* clear the old settings from the multicast hash table */
+	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+	atl1_init_flash_opcode(hw);
+
+	if (!hw->phy_configured) {
+		/* enable GPHY LinkChange Interrrupt */
+		ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
+		if (ret_val)
+			return ret_val;
+		/* make PHY out of power-saving state */
+		ret_val = atl1_phy_leave_power_saving(hw);
+		if (ret_val)
+			return ret_val;
+		/* Call a subroutine to configure the link */
+		ret_val = atl1_setup_link(hw);
+	}
+	return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
+{
+	struct pci_dev *pdev = hw->back->pdev;
+	struct atl1_adapter *adapter = hw->back;
+	s32 ret_val;
+	u16 phy_data;
+
+	/* ; --- Read   PHY Specific Status Register (17) */
+	ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
+	if (ret_val)
+		return ret_val;
+
+	if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
+		return ATLX_ERR_PHY_RES;
+
+	switch (phy_data & MII_ATLX_PSSR_SPEED) {
+	case MII_ATLX_PSSR_1000MBS:
+		*speed = SPEED_1000;
+		break;
+	case MII_ATLX_PSSR_100MBS:
+		*speed = SPEED_100;
+		break;
+	case MII_ATLX_PSSR_10MBS:
+		*speed = SPEED_10;
+		break;
+	default:
+		if (netif_msg_hw(adapter))
+			dev_dbg(&pdev->dev, "error getting speed\n");
+		return ATLX_ERR_PHY_SPEED;
+		break;
+	}
+	if (phy_data & MII_ATLX_PSSR_DPLX)
+		*duplex = FULL_DUPLEX;
+	else
+		*duplex = HALF_DUPLEX;
+
+	return 0;
+}
+
+void atl1_set_mac_addr(struct atl1_hw *hw)
+{
+	u32 value;
+	/*
+	 * 00-0B-6A-F6-00-DC
+	 * 0:  6AF600DC   1: 000B
+	 * low dword
+	 */
+	value = (((u32) hw->mac_addr[2]) << 24) |
+	    (((u32) hw->mac_addr[3]) << 16) |
+	    (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
+	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+	/* high dword */
+	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+	iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
+}
+
+/*
+ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+
+	hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+	hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+
+	adapter->wol = 0;
+	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
+	adapter->ict = 50000;		/* 100ms */
+	adapter->link_speed = SPEED_0;	/* hardware init */
+	adapter->link_duplex = FULL_DUPLEX;
+
+	hw->phy_configured = false;
+	hw->preamble_len = 7;
+	hw->ipgt = 0x60;
+	hw->min_ifg = 0x50;
+	hw->ipgr1 = 0x40;
+	hw->ipgr2 = 0x60;
+	hw->max_retry = 0xf;
+	hw->lcol = 0x37;
+	hw->jam_ipg = 7;
+	hw->rfd_burst = 8;
+	hw->rrd_burst = 8;
+	hw->rfd_fetch_gap = 1;
+	hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
+	hw->rx_jumbo_lkah = 1;
+	hw->rrd_ret_timer = 16;
+	hw->tpd_burst = 4;
+	hw->tpd_fetch_th = 16;
+	hw->txf_burst = 0x100;
+	hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
+	hw->tpd_fetch_gap = 1;
+	hw->rcb_value = atl1_rcb_64;
+	hw->dma_ord = atl1_dma_ord_enh;
+	hw->dmar_block = atl1_dma_req_256;
+	hw->dmaw_block = atl1_dma_req_256;
+	hw->cmb_rrd = 4;
+	hw->cmb_tpd = 4;
+	hw->cmb_rx_timer = 1;	/* about 2us */
+	hw->cmb_tx_timer = 1;	/* about 2us */
+	hw->smb_timer = 100000;	/* about 200ms */
+
+	spin_lock_init(&adapter->lock);
+	spin_lock_init(&adapter->mb_lock);
+
+	return 0;
+}
+
+static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+
+	return result;
+}
+
+static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
+	int val)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	atl1_write_phy_reg(&adapter->hw, reg_num, val);
+}
+
+/*
+ * atl1_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	int retval;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+
+	return retval;
+}
+
+/*
+ * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_ring_header *ring_header = &adapter->ring_header;
+	struct pci_dev *pdev = adapter->pdev;
+	int size;
+	u8 offset = 0;
+
+	size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
+	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+	if (unlikely(!tpd_ring->buffer_info)) {
+		if (netif_msg_drv(adapter))
+			dev_err(&pdev->dev, "kzalloc failed , size = D%d\n",
+				size);
+		goto err_nomem;
+	}
+	rfd_ring->buffer_info =
+		(struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+
+	/*
+	 * real ring DMA buffer
+	 * each ring/block may need up to 8 bytes for alignment, hence the
+	 * additional 40 bytes tacked onto the end.
+	 */
+	ring_header->size = size =
+		sizeof(struct tx_packet_desc) * tpd_ring->count
+		+ sizeof(struct rx_free_desc) * rfd_ring->count
+		+ sizeof(struct rx_return_desc) * rrd_ring->count
+		+ sizeof(struct coals_msg_block)
+		+ sizeof(struct stats_msg_block)
+		+ 40;
+
+	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+		&ring_header->dma);
+	if (unlikely(!ring_header->desc)) {
+		if (netif_msg_drv(adapter))
+			dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
+		goto err_nomem;
+	}
+
+	memset(ring_header->desc, 0, ring_header->size);
+
+	/* init TPD ring */
+	tpd_ring->dma = ring_header->dma;
+	offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
+	tpd_ring->dma += offset;
+	tpd_ring->desc = (u8 *) ring_header->desc + offset;
+	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
+
+	/* init RFD ring */
+	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
+	offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
+	rfd_ring->dma += offset;
+	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
+	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
+
+
+	/* init RRD ring */
+	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
+	offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
+	rrd_ring->dma += offset;
+	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
+	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
+
+
+	/* init CMB */
+	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
+	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
+	adapter->cmb.dma += offset;
+	adapter->cmb.cmb = (struct coals_msg_block *)
+		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
+
+	/* init SMB */
+	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
+	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
+	adapter->smb.dma += offset;
+	adapter->smb.smb = (struct stats_msg_block *)
+		((u8 *) adapter->cmb.cmb +
+		(sizeof(struct coals_msg_block) + offset));
+
+	return 0;
+
+err_nomem:
+	kfree(tpd_ring->buffer_info);
+	return -ENOMEM;
+}
+
+static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+
+	rfd_ring->next_to_clean = 0;
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_rx_ring - Free RFD Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Rx ring sk_buffs */
+	for (i = 0; i < rfd_ring->count; i++) {
+		buffer_info = &rfd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_FROMDEVICE);
+			buffer_info->dma = 0;
+		}
+		if (buffer_info->skb) {
+			dev_kfree_skb(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * rfd_ring->count;
+	memset(rfd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(rfd_ring->desc, 0, rfd_ring->size);
+
+	rfd_ring->next_to_clean = 0;
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Tx ring sk_buffs */
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = 0;
+		}
+	}
+
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->skb) {
+			dev_kfree_skb_any(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * tpd_ring->count;
+	memset(tpd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(tpd_ring->desc, 0, tpd_ring->size);
+
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1_free_ring_resources(struct atl1_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_ring_header *ring_header = &adapter->ring_header;
+
+	atl1_clean_tx_ring(adapter);
+	atl1_clean_rx_ring(adapter);
+
+	kfree(tpd_ring->buffer_info);
+	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+		ring_header->dma);
+
+	tpd_ring->buffer_info = NULL;
+	tpd_ring->desc = NULL;
+	tpd_ring->dma = 0;
+
+	rfd_ring->buffer_info = NULL;
+	rfd_ring->desc = NULL;
+	rfd_ring->dma = 0;
+
+	rrd_ring->desc = NULL;
+	rrd_ring->dma = 0;
+}
+
+static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+{
+	u32 value;
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	/* Config MAC CTRL Register */
+	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+	/* duplex */
+	if (FULL_DUPLEX == adapter->link_duplex)
+		value |= MAC_CTRL_DUPLX;
+	/* speed */
+	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+		  MAC_CTRL_SPEED_SHIFT);
+	/* flow control */
+	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+	/* PAD & CRC */
+	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+	/* preamble length */
+	value |= (((u32) adapter->hw.preamble_len
+		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+	/* vlan */
+	if (adapter->vlgrp)
+		value |= MAC_CTRL_RMV_VLAN;
+	/* rx checksum
+	   if (adapter->rx_csum)
+	   value |= MAC_CTRL_RX_CHKSUM_EN;
+	 */
+	/* filter mode */
+	value |= MAC_CTRL_BC_EN;
+	if (netdev->flags & IFF_PROMISC)
+		value |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI)
+		value |= MAC_CTRL_MC_ALL_EN;
+	/* value |= MAC_CTRL_LOOPBACK; */
+	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+}
+
+static u32 atl1_check_link(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	u32 ret_val;
+	u16 speed, duplex, phy_data;
+	int reconfig = 0;
+
+	/* MII_BMSR must read twice */
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	if (!(phy_data & BMSR_LSTATUS)) {
+		/* link down */
+		if (netif_carrier_ok(netdev)) {
+			/* old link state: Up */
+			if (netif_msg_link(adapter))
+				dev_info(&adapter->pdev->dev, "link is down\n");
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+		return 0;
+	}
+
+	/* Link Up */
+	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+	if (ret_val)
+		return ret_val;
+
+	switch (hw->media_type) {
+	case MEDIA_TYPE_1000M_FULL:
+		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_FULL:
+		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_HALF:
+		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_FULL:
+		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_HALF:
+		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	}
+
+	/* link result is our setting */
+	if (!reconfig) {
+		if (adapter->link_speed != speed
+		    || adapter->link_duplex != duplex) {
+			adapter->link_speed = speed;
+			adapter->link_duplex = duplex;
+			atl1_setup_mac_ctrl(adapter);
+			if (netif_msg_link(adapter))
+				dev_info(&adapter->pdev->dev,
+					"%s link is up %d Mbps %s\n",
+					netdev->name, adapter->link_speed,
+					adapter->link_duplex == FULL_DUPLEX ?
+					"full duplex" : "half duplex");
+		}
+		if (!netif_carrier_ok(netdev)) {
+			/* Link down -> Up */
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+		return 0;
+	}
+
+	/* change original link status */
+	if (netif_carrier_ok(netdev)) {
+		adapter->link_speed = SPEED_0;
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+	}
+
+	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			           MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:
+			/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+		return 0;
+	}
+
+	/* auto-neg, insert timer to re-config phy */
+	if (!adapter->phy_timer_pending) {
+		adapter->phy_timer_pending = true;
+		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+	}
+
+	return 0;
+}
+
+static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+{
+	u32 hi, lo, value;
+
+	/* RFD Flow Control */
+	value = adapter->rfd_ring.count;
+	hi = value / 16;
+	if (hi < 2)
+		hi = 2;
+	lo = value * 7 / 8;
+
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = adapter->rrd_ring.count;
+	lo = value / 16;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+static void set_flow_ctrl_new(struct atl1_hw *hw)
+{
+	u32 hi, lo, value;
+
+	/* RXF Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+	lo = value / 16;
+	if (lo < 192)
+		lo = 192;
+	hi = value * 7 / 8;
+	if (hi < lo)
+		hi = lo + 16;
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+	lo = value / 8;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	if (hi < lo)
+		hi = lo + 3;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+/*
+ * atl1_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static u32 atl1_configure(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	u32 value;
+
+	/* clear interrupt status */
+	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+
+	/* set MAC Address */
+	value = (((u32) hw->mac_addr[2]) << 24) |
+		(((u32) hw->mac_addr[3]) << 16) |
+		(((u32) hw->mac_addr[4]) << 8) |
+		(((u32) hw->mac_addr[5]));
+	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+
+	/* tx / rx ring */
+
+	/* HI base address */
+	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+	/* LO base address */
+	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+
+	/* element count */
+	value = adapter->rrd_ring.count;
+	value <<= 16;
+	value += adapter->rfd_ring.count;
+	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
+		REG_DESC_TPD_RING_SIZE);
+
+	/* Load Ptr */
+	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+
+	/* config Mailbox */
+	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+		((atomic_read(&adapter->rrd_ring.next_to_clean)
+		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+		((atomic_read(&adapter->rfd_ring.next_to_use)
+		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAILBOX);
+
+	/* config IPG/IFG */
+	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+		 << MAC_IPG_IFG_IPGT_SHIFT) |
+		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+		<< MAC_IPG_IFG_MIFG_SHIFT) |
+		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+		<< MAC_IPG_IFG_IPGR1_SHIFT) |
+		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+		<< MAC_IPG_IFG_IPGR2_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+
+	/* config  Half-Duplex Control */
+	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+
+	/* set Interrupt Moderator Timer */
+	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+
+	/* set Interrupt Clear Timer */
+	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+
+	/* set max frame size hw will accept */
+	iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
+
+	/* jumbo size & rrd retirement timer */
+	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+		 << RXQ_JMBOSZ_TH_SHIFT) |
+		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+		<< RXQ_JMBO_LKAH_SHIFT) |
+		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+		<< RXQ_RRD_TIMER_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+
+	/* Flow Control */
+	switch (hw->dev_rev) {
+	case 0x8001:
+	case 0x9001:
+	case 0x9002:
+	case 0x9003:
+		set_flow_ctrl_old(adapter);
+		break;
+	default:
+		set_flow_ctrl_new(hw);
+		break;
+	}
+
+	/* config TXQ */
+	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
+		TXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+
+	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+		<< TX_JUMBO_TASK_TH_SHIFT) |
+		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+		<< TX_TPD_MIN_IPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+
+	/* config RXQ */
+	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
+		RXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+
+	/* config DMA Engine */
+	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+		((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
+		DMA_CTRL_DMAW_EN;
+	value |= (u32) hw->dma_ord;
+	if (atl1_rcb_128 == hw->rcb_value)
+		value |= DMA_CTRL_RCB_VALUE;
+	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+
+	/* config CMB / SMB */
+	value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
+		hw->cmb_tpd : adapter->tpd_ring.count;
+	value <<= 16;
+	value |= hw->cmb_rrd;
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+
+	/* --- enable CMB / SMB */
+	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+
+	value = ioread32(adapter->hw.hw_addr + REG_ISR);
+	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+		value = 1;	/* config failed */
+	else
+		value = 0;
+
+	/* clear all interrupt status */
+	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+	return value;
+}
+
+/*
+ * atl1_pcie_patch - Patch for PCIE module
+ */
+static void atl1_pcie_patch(struct atl1_adapter *adapter)
+{
+	u32 value;
+
+	/* much vendor magic here */
+	value = 0x6500;
+	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+	/* pcie flow control mode change */
+	value = ioread32(adapter->hw.hw_addr + 0x1008);
+	value |= 0x8000;
+	iowrite32(value, adapter->hw.hw_addr + 0x1008);
+}
+
+/*
+ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+ * on PCI Command register is disable.
+ * The function enable this bit.
+ * Brackett, 2006/03/15
+ */
+static void atl1_via_workaround(struct atl1_adapter *adapter)
+{
+	unsigned long value;
+
+	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+	if (value & PCI_COMMAND_INTX_DISABLE)
+		value &= ~PCI_COMMAND_INTX_DISABLE;
+	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+}
+
+static void atl1_inc_smb(struct atl1_adapter *adapter)
+{
+	struct stats_msg_block *smb = adapter->smb.smb;
+
+	/* Fill out the OS statistics structure */
+	adapter->soft_stats.rx_packets += smb->rx_ok;
+	adapter->soft_stats.tx_packets += smb->tx_ok;
+	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
+	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
+	adapter->soft_stats.multicast += smb->rx_mcast;
+	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
+		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
+
+	/* Rx Errors */
+	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
+		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
+		smb->rx_rrd_ov + smb->rx_align_err);
+	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
+	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
+	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
+	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
+	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
+		smb->rx_rxf_ov);
+
+	adapter->soft_stats.rx_pause += smb->rx_pause;
+	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
+	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
+
+	/* Tx Errors */
+	adapter->soft_stats.tx_errors += (smb->tx_late_col +
+		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
+	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
+	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
+	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
+
+	adapter->soft_stats.excecol += smb->tx_abort_col;
+	adapter->soft_stats.deffer += smb->tx_defer;
+	adapter->soft_stats.scc += smb->tx_1_col;
+	adapter->soft_stats.mcc += smb->tx_2_col;
+	adapter->soft_stats.latecol += smb->tx_late_col;
+	adapter->soft_stats.tx_underun += smb->tx_underrun;
+	adapter->soft_stats.tx_trunc += smb->tx_trunc;
+	adapter->soft_stats.tx_pause += smb->tx_pause;
+
+	adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
+	adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
+	adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
+	adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
+	adapter->net_stats.multicast = adapter->soft_stats.multicast;
+	adapter->net_stats.collisions = adapter->soft_stats.collisions;
+	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
+	adapter->net_stats.rx_over_errors =
+		adapter->soft_stats.rx_missed_errors;
+	adapter->net_stats.rx_length_errors =
+		adapter->soft_stats.rx_length_errors;
+	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+	adapter->net_stats.rx_frame_errors =
+		adapter->soft_stats.rx_frame_errors;
+	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+	adapter->net_stats.rx_missed_errors =
+		adapter->soft_stats.rx_missed_errors;
+	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
+	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+	adapter->net_stats.tx_aborted_errors =
+		adapter->soft_stats.tx_aborted_errors;
+	adapter->net_stats.tx_window_errors =
+		adapter->soft_stats.tx_window_errors;
+	adapter->net_stats.tx_carrier_errors =
+		adapter->soft_stats.tx_carrier_errors;
+}
+
+static void atl1_update_mailbox(struct atl1_adapter *adapter)
+{
+	unsigned long flags;
+	u32 tpd_next_to_use;
+	u32 rfd_next_to_use;
+	u32 rrd_next_to_clean;
+	u32 value;
+
+	spin_lock_irqsave(&adapter->mb_lock, flags);
+
+	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+
+	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+		MB_RFD_PROD_INDX_SHIFT) |
+		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+		MB_RRD_CONS_INDX_SHIFT) |
+		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+		MB_TPD_PROD_INDX_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+
+	spin_unlock_irqrestore(&adapter->mb_lock, flags);
+}
+
+static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
+	struct rx_return_desc *rrd, u16 offset)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+
+	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
+		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
+		if (++rfd_ring->next_to_clean == rfd_ring->count) {
+			rfd_ring->next_to_clean = 0;
+		}
+	}
+}
+
+static void atl1_update_rfd_index(struct atl1_adapter *adapter,
+	struct rx_return_desc *rrd)
+{
+	u16 num_buf;
+
+	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
+		adapter->rx_buffer_len;
+	if (rrd->num_buf == num_buf)
+		/* clean alloc flag for bad rrd */
+		atl1_clean_alloc_flag(adapter, rrd, num_buf);
+}
+
+static void atl1_rx_checksum(struct atl1_adapter *adapter,
+	struct rx_return_desc *rrd, struct sk_buff *skb)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
+					ERR_FLAG_CODE | ERR_FLAG_OV)) {
+			adapter->hw_csum_err++;
+			if (netif_msg_rx_err(adapter))
+				dev_printk(KERN_DEBUG, &pdev->dev,
+					"rx checksum error\n");
+			return;
+		}
+	}
+
+	/* not IPv4 */
+	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
+		/* checksum is invalid, but it's not an IPv4 pkt, so ok */
+		return;
+
+	/* IPv4 packet */
+	if (likely(!(rrd->err_flg &
+		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_good++;
+		return;
+	}
+
+	/* IPv4, but hardware thinks its checksum is wrong */
+	if (netif_msg_rx_err(adapter))
+		dev_printk(KERN_DEBUG, &pdev->dev,
+			"hw csum wrong, pkt_flag:%x, err_flag:%x\n",
+			rrd->pkt_flg, rrd->err_flg);
+	skb->ip_summed = CHECKSUM_COMPLETE;
+	skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
+	adapter->hw_csum_err++;
+	return;
+}
+
+/*
+ * atl1_alloc_rx_buffers - Replace used receive buffers
+ * @adapter: address of board private structure
+ */
+static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	struct page *page;
+	unsigned long offset;
+	struct atl1_buffer *buffer_info, *next_info;
+	struct sk_buff *skb;
+	u16 num_alloc = 0;
+	u16 rfd_next_to_use, next_next;
+	struct rx_free_desc *rfd_desc;
+
+	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
+	if (++next_next == rfd_ring->count)
+		next_next = 0;
+	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+	next_info = &rfd_ring->buffer_info[next_next];
+
+	while (!buffer_info->alloced && !next_info->alloced) {
+		if (buffer_info->skb) {
+			buffer_info->alloced = 1;
+			goto next;
+		}
+
+		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+		if (unlikely(!skb)) {
+			/* Better luck next round */
+			adapter->net_stats.rx_dropped++;
+			break;
+		}
+
+		/*
+		 * Make buffer alignment 2 beyond a 16 byte boundary
+		 * this will result in a 16 byte aligned IP header after
+		 * the 14 byte MAC header is removed
+		 */
+		skb_reserve(skb, NET_IP_ALIGN);
+
+		buffer_info->alloced = 1;
+		buffer_info->skb = skb;
+		buffer_info->length = (u16) adapter->rx_buffer_len;
+		page = virt_to_page(skb->data);
+		offset = (unsigned long)skb->data & ~PAGE_MASK;
+		buffer_info->dma = pci_map_page(pdev, page, offset,
+						adapter->rx_buffer_len,
+						PCI_DMA_FROMDEVICE);
+		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
+		rfd_desc->coalese = 0;
+
+next:
+		rfd_next_to_use = next_next;
+		if (unlikely(++next_next == rfd_ring->count))
+			next_next = 0;
+
+		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+		next_info = &rfd_ring->buffer_info[next_next];
+		num_alloc++;
+	}
+
+	if (num_alloc) {
+		/*
+		 * Force memory writes to complete before letting h/w
+		 * know there are new descriptors to fetch.  (Only
+		 * applicable for weak-ordered memory model archs,
+		 * such as IA-64).
+		 */
+		wmb();
+		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
+	}
+	return num_alloc;
+}
+
+static void atl1_intr_rx(struct atl1_adapter *adapter)
+{
+	int i, count;
+	u16 length;
+	u16 rrd_next_to_clean;
+	u32 value;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_buffer *buffer_info;
+	struct rx_return_desc *rrd;
+	struct sk_buff *skb;
+
+	count = 0;
+
+	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+
+	while (1) {
+		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
+		i = 1;
+		if (likely(rrd->xsz.valid)) {	/* packet valid */
+chk_rrd:
+			/* check rrd status */
+			if (likely(rrd->num_buf == 1))
+				goto rrd_ok;
+			else if (netif_msg_rx_err(adapter)) {
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"unexpected RRD buffer count\n");
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"rx_buf_len = %d\n",
+					adapter->rx_buffer_len);
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"RRD num_buf = %d\n",
+					rrd->num_buf);
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"RRD pkt_len = %d\n",
+					rrd->xsz.xsum_sz.pkt_size);
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"RRD pkt_flg = 0x%08X\n",
+					rrd->pkt_flg);
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"RRD err_flg = 0x%08X\n",
+					rrd->err_flg);
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"RRD vlan_tag = 0x%08X\n",
+					rrd->vlan_tag);
+			}
+
+			/* rrd seems to be bad */
+			if (unlikely(i-- > 0)) {
+				/* rrd may not be DMAed completely */
+				udelay(1);
+				goto chk_rrd;
+			}
+			/* bad rrd */
+			if (netif_msg_rx_err(adapter))
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"bad RRD\n");
+			/* see if update RFD index */
+			if (rrd->num_buf > 1)
+				atl1_update_rfd_index(adapter, rrd);
+
+			/* update rrd */
+			rrd->xsz.valid = 0;
+			if (++rrd_next_to_clean == rrd_ring->count)
+				rrd_next_to_clean = 0;
+			count++;
+			continue;
+		} else {	/* current rrd still not be updated */
+
+			break;
+		}
+rrd_ok:
+		/* clean alloc flag for bad rrd */
+		atl1_clean_alloc_flag(adapter, rrd, 0);
+
+		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
+		if (++rfd_ring->next_to_clean == rfd_ring->count)
+			rfd_ring->next_to_clean = 0;
+
+		/* update rrd next to clean */
+		if (++rrd_next_to_clean == rrd_ring->count)
+			rrd_next_to_clean = 0;
+		count++;
+
+		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+			if (!(rrd->err_flg &
+				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
+				| ERR_FLAG_LEN))) {
+				/* packet error, don't need upstream */
+				buffer_info->alloced = 0;
+				rrd->xsz.valid = 0;
+				continue;
+			}
+		}
+
+		/* Good Receive */
+		pci_unmap_page(adapter->pdev, buffer_info->dma,
+			       buffer_info->length, PCI_DMA_FROMDEVICE);
+		skb = buffer_info->skb;
+		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
+
+		skb_put(skb, length - ETH_FCS_LEN);
+
+		/* Receive Checksum Offload */
+		atl1_rx_checksum(adapter, rrd, skb);
+		skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+		if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+			u16 vlan_tag = (rrd->vlan_tag >> 4) |
+					((rrd->vlan_tag & 7) << 13) |
+					((rrd->vlan_tag & 8) << 9);
+			vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
+		} else
+			netif_rx(skb);
+
+		/* let protocol layer free skb */
+		buffer_info->skb = NULL;
+		buffer_info->alloced = 0;
+		rrd->xsz.valid = 0;
+
+		adapter->netdev->last_rx = jiffies;
+	}
+
+	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
+
+	atl1_alloc_rx_buffers(adapter);
+
+	/* update mailbox ? */
+	if (count) {
+		u32 tpd_next_to_use;
+		u32 rfd_next_to_use;
+
+		spin_lock(&adapter->mb_lock);
+
+		tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+		rfd_next_to_use =
+		    atomic_read(&adapter->rfd_ring.next_to_use);
+		rrd_next_to_clean =
+		    atomic_read(&adapter->rrd_ring.next_to_clean);
+		value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+			MB_RFD_PROD_INDX_SHIFT) |
+                        ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+			MB_RRD_CONS_INDX_SHIFT) |
+                        ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+			MB_TPD_PROD_INDX_SHIFT);
+		iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+		spin_unlock(&adapter->mb_lock);
+	}
+}
+
+static void atl1_intr_tx(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	u16 sw_tpd_next_to_clean;
+	u16 cmb_tpd_next_to_clean;
+
+	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
+
+	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
+		struct tx_packet_desc *tpd;
+
+		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
+		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+		if (buffer_info->dma) {
+			pci_unmap_page(adapter->pdev, buffer_info->dma,
+				       buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = 0;
+		}
+
+		if (buffer_info->skb) {
+			dev_kfree_skb_irq(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+
+		if (++sw_tpd_next_to_clean == tpd_ring->count)
+			sw_tpd_next_to_clean = 0;
+	}
+	atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
+
+	if (netif_queue_stopped(adapter->netdev)
+	    && netif_carrier_ok(adapter->netdev))
+		netif_wake_queue(adapter->netdev);
+}
+
+static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
+{
+	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
+	return ((next_to_clean > next_to_use) ?
+		next_to_clean - next_to_use - 1 :
+		tpd_ring->count + next_to_clean - next_to_use - 1);
+}
+
+static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
+	struct tx_packet_desc *ptpd)
+{
+	/* spinlock held */
+	u8 hdr_len, ip_off;
+	u32 real_len;
+	int err;
+
+	if (skb_shinfo(skb)->gso_size) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (unlikely(err))
+				return -1;
+		}
+
+		if (skb->protocol == ntohs(ETH_P_IP)) {
+			struct iphdr *iph = ip_hdr(skb);
+
+			real_len = (((unsigned char *)iph - skb->data) +
+				ntohs(iph->tot_len));
+			if (real_len < skb->len)
+				pskb_trim(skb, real_len);
+			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+			if (skb->len == hdr_len) {
+				iph->check = 0;
+				tcp_hdr(skb)->check =
+					~csum_tcpudp_magic(iph->saddr,
+					iph->daddr, tcp_hdrlen(skb),
+					IPPROTO_TCP, 0);
+				ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
+					TPD_IPHL_SHIFT;
+				ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
+					TPD_TCPHDRLEN_MASK) <<
+					TPD_TCPHDRLEN_SHIFT;
+				ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT;
+				ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT;
+				return 1;
+			}
+
+			iph->check = 0;
+			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+					iph->daddr, 0, IPPROTO_TCP, 0);
+			ip_off = (unsigned char *)iph -
+				(unsigned char *) skb_network_header(skb);
+			if (ip_off == 8) /* 802.3-SNAP frame */
+				ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT;
+			else if (ip_off != 0)
+				return -2;
+
+			ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
+				TPD_IPHL_SHIFT;
+			ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
+				TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT;
+			ptpd->word3 |= (skb_shinfo(skb)->gso_size &
+				TPD_MSS_MASK) << TPD_MSS_SHIFT;
+			ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+			return 3;
+		}
+	}
+	return false;
+}
+
+static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
+	struct tx_packet_desc *ptpd)
+{
+	u8 css, cso;
+
+	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+		css = (u8) (skb->csum_start - skb_headroom(skb));
+		cso = css + (u8) skb->csum_offset;
+		if (unlikely(css & 0x1)) {
+			/* L1 hardware requires an even number here */
+			if (netif_msg_tx_err(adapter))
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"payload offset not an even number\n");
+			return -1;
+		}
+		ptpd->word3 |= (css & TPD_PLOADOFFSET_MASK) <<
+			TPD_PLOADOFFSET_SHIFT;
+		ptpd->word3 |= (cso & TPD_CCSUMOFFSET_MASK) <<
+			TPD_CCSUMOFFSET_SHIFT;
+		ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT;
+		return true;
+	}
+	return 0;
+}
+
+static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+	struct tx_packet_desc *ptpd)
+{
+	/* spinlock held */
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	u16 buf_len = skb->len;
+	struct page *page;
+	unsigned long offset;
+	unsigned int nr_frags;
+	unsigned int f;
+	int retval;
+	u16 next_to_use;
+	u16 data_len;
+	u8 hdr_len;
+
+	buf_len -= skb->data_len;
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	next_to_use = atomic_read(&tpd_ring->next_to_use);
+	buffer_info = &tpd_ring->buffer_info[next_to_use];
+	if (unlikely(buffer_info->skb))
+		BUG();
+	/* put skb in last TPD */
+	buffer_info->skb = NULL;
+
+	retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
+	if (retval) {
+		/* TSO */
+		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		buffer_info->length = hdr_len;
+		page = virt_to_page(skb->data);
+		offset = (unsigned long)skb->data & ~PAGE_MASK;
+		buffer_info->dma = pci_map_page(adapter->pdev, page,
+						offset, hdr_len,
+						PCI_DMA_TODEVICE);
+
+		if (++next_to_use == tpd_ring->count)
+			next_to_use = 0;
+
+		if (buf_len > hdr_len) {
+			int i, nseg;
+
+			data_len = buf_len - hdr_len;
+			nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
+				ATL1_MAX_TX_BUF_LEN;
+			for (i = 0; i < nseg; i++) {
+				buffer_info =
+				    &tpd_ring->buffer_info[next_to_use];
+				buffer_info->skb = NULL;
+				buffer_info->length =
+				    (ATL1_MAX_TX_BUF_LEN >=
+				     data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
+				data_len -= buffer_info->length;
+				page = virt_to_page(skb->data +
+					(hdr_len + i * ATL1_MAX_TX_BUF_LEN));
+				offset = (unsigned long)(skb->data +
+					(hdr_len + i * ATL1_MAX_TX_BUF_LEN)) &
+					~PAGE_MASK;
+				buffer_info->dma = pci_map_page(adapter->pdev,
+					page, offset, buffer_info->length,
+					PCI_DMA_TODEVICE);
+				if (++next_to_use == tpd_ring->count)
+					next_to_use = 0;
+			}
+		}
+	} else {
+		/* not TSO */
+		buffer_info->length = buf_len;
+		page = virt_to_page(skb->data);
+		offset = (unsigned long)skb->data & ~PAGE_MASK;
+		buffer_info->dma = pci_map_page(adapter->pdev, page,
+			offset, buf_len, PCI_DMA_TODEVICE);
+		if (++next_to_use == tpd_ring->count)
+			next_to_use = 0;
+	}
+
+	for (f = 0; f < nr_frags; f++) {
+		struct skb_frag_struct *frag;
+		u16 i, nseg;
+
+		frag = &skb_shinfo(skb)->frags[f];
+		buf_len = frag->size;
+
+		nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
+			ATL1_MAX_TX_BUF_LEN;
+		for (i = 0; i < nseg; i++) {
+			buffer_info = &tpd_ring->buffer_info[next_to_use];
+			if (unlikely(buffer_info->skb))
+				BUG();
+			buffer_info->skb = NULL;
+			buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
+				ATL1_MAX_TX_BUF_LEN : buf_len;
+			buf_len -= buffer_info->length;
+			buffer_info->dma = pci_map_page(adapter->pdev,
+				frag->page,
+				frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
+				buffer_info->length, PCI_DMA_TODEVICE);
+
+			if (++next_to_use == tpd_ring->count)
+				next_to_use = 0;
+		}
+	}
+
+	/* last tpd's buffer-info */
+	buffer_info->skb = skb;
+}
+
+static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
+       struct tx_packet_desc *ptpd)
+{
+	/* spinlock held */
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	struct tx_packet_desc *tpd;
+	u16 j;
+	u32 val;
+	u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
+
+	for (j = 0; j < count; j++) {
+		buffer_info = &tpd_ring->buffer_info[next_to_use];
+		tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
+		if (tpd != ptpd)
+			memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
+		tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		tpd->word2 = (cpu_to_le16(buffer_info->length) &
+			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
+
+		/*
+		 * if this is the first packet in a TSO chain, set
+		 * TPD_HDRFLAG, otherwise, clear it.
+		 */
+		val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
+			TPD_SEGMENT_EN_MASK;
+		if (val) {
+			if (!j)
+				tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
+			else
+				tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
+		}
+
+		if (j == (count - 1))
+			tpd->word3 |= 1 << TPD_EOP_SHIFT;
+
+		if (++next_to_use == tpd_ring->count)
+			next_to_use = 0;
+	}
+	/*
+	 * Force memory writes to complete before letting h/w
+	 * know there are new descriptors to fetch.  (Only
+	 * applicable for weak-ordered memory model archs,
+	 * such as IA-64).
+	 */
+	wmb();
+
+	atomic_set(&tpd_ring->next_to_use, next_to_use);
+}
+
+static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	int len = skb->len;
+	int tso;
+	int count = 1;
+	int ret_val;
+	struct tx_packet_desc *ptpd;
+	u16 frag_size;
+	u16 vlan_tag;
+	unsigned long flags;
+	unsigned int nr_frags = 0;
+	unsigned int mss = 0;
+	unsigned int f;
+	unsigned int proto_hdr_len;
+
+	len -= skb->data_len;
+
+	if (unlikely(skb->len <= 0)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	for (f = 0; f < nr_frags; f++) {
+		frag_size = skb_shinfo(skb)->frags[f].size;
+		if (frag_size)
+			count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
+				ATL1_MAX_TX_BUF_LEN;
+	}
+
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss) {
+		if (skb->protocol == ntohs(ETH_P_IP)) {
+			proto_hdr_len = (skb_transport_offset(skb) +
+					 tcp_hdrlen(skb));
+			if (unlikely(proto_hdr_len > len)) {
+				dev_kfree_skb_any(skb);
+				return NETDEV_TX_OK;
+			}
+			/* need additional TPD ? */
+			if (proto_hdr_len != len)
+				count += (len - proto_hdr_len +
+					ATL1_MAX_TX_BUF_LEN - 1) /
+					ATL1_MAX_TX_BUF_LEN;
+		}
+	}
+
+	if (!spin_trylock_irqsave(&adapter->lock, flags)) {
+		/* Can't get lock - tell upper layer to requeue */
+		if (netif_msg_tx_queued(adapter))
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"tx locked\n");
+		return NETDEV_TX_LOCKED;
+	}
+
+	if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
+		/* not enough descriptors */
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->lock, flags);
+		if (netif_msg_tx_queued(adapter))
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"tx busy\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	ptpd = ATL1_TPD_DESC(tpd_ring,
+		(u16) atomic_read(&tpd_ring->next_to_use));
+	memset(ptpd, 0, sizeof(struct tx_packet_desc));
+
+	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+		vlan_tag = vlan_tx_tag_get(skb);
+		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
+			((vlan_tag >> 9) & 0x8);
+		ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
+		ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) <<
+			TPD_VL_TAGGED_SHIFT;
+	}
+
+	tso = atl1_tso(adapter, skb, ptpd);
+	if (tso < 0) {
+		spin_unlock_irqrestore(&adapter->lock, flags);
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (!tso) {
+		ret_val = atl1_tx_csum(adapter, skb, ptpd);
+		if (ret_val < 0) {
+			spin_unlock_irqrestore(&adapter->lock, flags);
+			dev_kfree_skb_any(skb);
+			return NETDEV_TX_OK;
+		}
+	}
+
+	atl1_tx_map(adapter, skb, ptpd);
+	atl1_tx_queue(adapter, count, ptpd);
+	atl1_update_mailbox(adapter);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+	netdev->trans_start = jiffies;
+	return NETDEV_TX_OK;
+}
+
+/*
+ * atl1_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1_intr(int irq, void *data)
+{
+	struct atl1_adapter *adapter = netdev_priv(data);
+	u32 status;
+	int max_ints = 10;
+
+	status = adapter->cmb.cmb->int_stats;
+	if (!status)
+		return IRQ_NONE;
+
+	do {
+		/* clear CMB interrupt status at once */
+		adapter->cmb.cmb->int_stats = 0;
+
+		if (status & ISR_GPHY)	/* clear phy status */
+			atlx_clear_phy_int(adapter);
+
+		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+
+		/* check if SMB intr */
+		if (status & ISR_SMB)
+			atl1_inc_smb(adapter);
+
+		/* check if PCIE PHY Link down */
+		if (status & ISR_PHY_LINKDOWN) {
+			if (netif_msg_intr(adapter))
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"pcie phy link down %x\n", status);
+			if (netif_running(adapter->netdev)) {	/* reset MAC */
+				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+				schedule_work(&adapter->pcie_dma_to_rst_task);
+				return IRQ_HANDLED;
+			}
+		}
+
+		/* check if DMA read/write error ? */
+		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+			if (netif_msg_intr(adapter))
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"pcie DMA r/w error (status = 0x%x)\n",
+					status);
+			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+			schedule_work(&adapter->pcie_dma_to_rst_task);
+			return IRQ_HANDLED;
+		}
+
+		/* link event */
+		if (status & ISR_GPHY) {
+			adapter->soft_stats.tx_carrier_errors++;
+			atl1_check_for_link(adapter);
+		}
+
+		/* transmit event */
+		if (status & ISR_CMB_TX)
+			atl1_intr_tx(adapter);
+
+		/* rx exception */
+		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+				ISR_HOST_RRD_OV))
+				if (netif_msg_intr(adapter))
+					dev_printk(KERN_DEBUG,
+						&adapter->pdev->dev,
+						"rx exception, ISR = 0x%x\n",
+						status);
+			atl1_intr_rx(adapter);
+		}
+
+		if (--max_ints < 0)
+			break;
+
+	} while ((status = adapter->cmb.cmb->int_stats));
+
+	/* re-enable Interrupt */
+	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+	return IRQ_HANDLED;
+}
+
+/*
+ * atl1_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_watchdog(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+/*
+ * atl1_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_phy_config(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+	struct atl1_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	adapter->phy_timer_pending = false;
+	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+	atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
+	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/*
+ * Orphaned vendor comment left intact here:
+ * <vendor comment>
+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+ * will assert. We do soft reset <0x1400=1> according
+ * with the SPEC. BUT, it seemes that PCIE or DMA
+ * state-machine will not be reset. DMAR_TO_INT will
+ * assert again and again.
+ * </vendor comment>
+ */
+
+static int atl1_reset(struct atl1_adapter *adapter)
+{
+	int ret;
+	ret = atl1_reset_hw(&adapter->hw);
+	if (ret)
+		return ret;
+	return atl1_init_hw(&adapter->hw);
+}
+
+static s32 atl1_up(struct atl1_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int err;
+	int irq_flags = IRQF_SAMPLE_RANDOM;
+
+	/* hardware has been reset, we need to reload some things */
+	atlx_set_multi(netdev);
+	atl1_init_ring_ptrs(adapter);
+	atlx_restore_vlan(adapter);
+	err = atl1_alloc_rx_buffers(adapter);
+	if (unlikely(!err))
+		/* no RX BUFFER allocated */
+		return -ENOMEM;
+
+	if (unlikely(atl1_configure(adapter))) {
+		err = -EIO;
+		goto err_up;
+	}
+
+	err = pci_enable_msi(adapter->pdev);
+	if (err) {
+		if (netif_msg_ifup(adapter))
+			dev_info(&adapter->pdev->dev,
+				"Unable to enable MSI: %d\n", err);
+		irq_flags |= IRQF_SHARED;
+	}
+
+	err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
+			netdev->name, netdev);
+	if (unlikely(err))
+		goto err_up;
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+	atlx_irq_enable(adapter);
+	atl1_check_link(adapter);
+	return 0;
+
+err_up:
+	pci_disable_msi(adapter->pdev);
+	/* free rx_buffers */
+	atl1_clean_rx_ring(adapter);
+	return err;
+}
+
+static void atl1_down(struct atl1_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	del_timer_sync(&adapter->watchdog_timer);
+	del_timer_sync(&adapter->phy_config_timer);
+	adapter->phy_timer_pending = false;
+
+	atlx_irq_disable(adapter);
+	free_irq(adapter->pdev->irq, netdev);
+	pci_disable_msi(adapter->pdev);
+	atl1_reset_hw(&adapter->hw);
+	adapter->cmb.cmb->int_stats = 0;
+
+	adapter->link_speed = SPEED_0;
+	adapter->link_duplex = -1;
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	atl1_clean_tx_ring(adapter);
+	atl1_clean_rx_ring(adapter);
+}
+
+static void atl1_tx_timeout_task(struct work_struct *work)
+{
+	struct atl1_adapter *adapter =
+		container_of(work, struct atl1_adapter, tx_timeout_task);
+	struct net_device *netdev = adapter->netdev;
+
+	netif_device_detach(netdev);
+	atl1_down(adapter);
+	atl1_up(adapter);
+	netif_device_attach(netdev);
+}
+
+/*
+ * atl1_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int old_mtu = netdev->mtu;
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		if (netif_msg_link(adapter))
+			dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+		return -EINVAL;
+	}
+
+	adapter->hw.max_frame_size = max_frame;
+	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+	adapter->rx_buffer_len = (max_frame + 7) & ~7;
+	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+
+	netdev->mtu = new_mtu;
+	if ((old_mtu != new_mtu) && netif_running(netdev)) {
+		atl1_down(adapter);
+		atl1_up(adapter);
+	}
+
+	return 0;
+}
+
+/*
+ * atl1_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1_open(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int err;
+
+	/* allocate transmit descriptors */
+	err = atl1_setup_ring_resources(adapter);
+	if (err)
+		return err;
+
+	err = atl1_up(adapter);
+	if (err)
+		goto err_up;
+
+	return 0;
+
+err_up:
+	atl1_reset(adapter);
+	return err;
+}
+
+/*
+ * atl1_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1_close(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	atl1_down(adapter);
+	atl1_free_ring_resources(adapter);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	u32 ctrl = 0;
+	u32 wufc = adapter->wol;
+
+	netif_device_detach(netdev);
+	if (netif_running(netdev))
+		atl1_down(adapter);
+
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	if (ctrl & BMSR_LSTATUS)
+		wufc &= ~ATLX_WUFC_LNKC;
+
+	/* reduce speed to 10/100M */
+	if (wufc) {
+		atl1_phy_enter_power_saving(hw);
+		/* if resume, let driver to re- setup link */
+		hw->phy_configured = false;
+		atl1_set_mac_addr(hw);
+		atlx_set_multi(netdev);
+
+		ctrl = 0;
+		/* turn on magic packet wol */
+		if (wufc & ATLX_WUFC_MAG)
+			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+		/* turn on Link change WOL */
+		if (wufc & ATLX_WUFC_LNKC)
+			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+
+		/* turn on all-multi mode if wake on multicast is enabled */
+		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_DBG;
+		ctrl &= ~MAC_CTRL_PROMIS_EN;
+		if (wufc & ATLX_WUFC_MC)
+			ctrl |= MAC_CTRL_MC_ALL_EN;
+		else
+			ctrl &= ~MAC_CTRL_MC_ALL_EN;
+
+		/* turn on broadcast mode if wake on-BC is enabled */
+		if (wufc & ATLX_WUFC_BC)
+			ctrl |= MAC_CTRL_BC_EN;
+		else
+			ctrl &= ~MAC_CTRL_BC_EN;
+
+		/* enable RX */
+		ctrl |= MAC_CTRL_RX_EN;
+		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_enable_wake(pdev, PCI_D3cold, 1);
+	} else {
+		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_enable_wake(pdev, PCI_D3cold, 0);
+	}
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int atl1_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u32 err;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	/* FIXME: check and handle */
+	err = pci_enable_device(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+	atl1_reset(adapter);
+
+	if (netif_running(netdev))
+		atl1_up(adapter);
+	netif_device_attach(netdev);
+
+	atl1_via_workaround(adapter);
+
+	return 0;
+}
+#else
+#define atl1_suspend NULL
+#define atl1_resume NULL
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void atl1_poll_controller(struct net_device *netdev)
+{
+	disable_irq(netdev->irq);
+	atl1_intr(netdev->irq, netdev);
+	enable_irq(netdev->irq);
+}
+#endif
+
+/*
+ * atl1_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct atl1_adapter *adapter;
+	static int cards_found = 0;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	/*
+	 * The atl1 chip can DMA to 64-bit addresses, but it uses a single
+	 * shared register for the high 32 bits, so only a single, aligned,
+	 * 4 GB physical address range can be used at a time.
+	 *
+	 * Supporting 64-bit DMA on this hardware is more trouble than it's
+	 * worth.  It is far easier to limit to 32-bit DMA than update
+	 * various kernel subsystems to support the mechanics required by a
+	 * fixed-high-32-bit system.
+	 */
+	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (err) {
+		dev_err(&pdev->dev, "no usable DMA configuration\n");
+		goto err_dma;
+	}
+	/*
+	 * Mark all PCI regions associated with PCI device
+	 * pdev as being reserved by owner atl1_driver_name
+	 */
+	err = pci_request_regions(pdev, ATLX_DRIVER_NAME);
+	if (err)
+		goto err_request_regions;
+
+	/*
+	 * Enables bus-mastering on the device and calls
+	 * pcibios_set_master to do the needed arch specific settings
+	 */
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct atl1_adapter));
+	if (!netdev) {
+		err = -ENOMEM;
+		goto err_alloc_etherdev;
+	}
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	pci_set_drvdata(pdev, netdev);
+	adapter = netdev_priv(netdev);
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.back = adapter;
+	adapter->msg_enable = netif_msg_init(debug, atl1_default_msg);
+
+	adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
+	if (!adapter->hw.hw_addr) {
+		err = -EIO;
+		goto err_pci_iomap;
+	}
+	/* get device revision number */
+	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
+		(REG_MASTER_CTRL + 2));
+	if (netif_msg_probe(adapter))
+		dev_info(&pdev->dev, "version %s\n", ATLX_DRIVER_VERSION);
+
+	/* set default ring resource counts */
+	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
+	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
+
+	adapter->mii.dev = netdev;
+	adapter->mii.mdio_read = mdio_read;
+	adapter->mii.mdio_write = mdio_write;
+	adapter->mii.phy_id_mask = 0x1f;
+	adapter->mii.reg_num_mask = 0x1f;
+
+	netdev->open = &atl1_open;
+	netdev->stop = &atl1_close;
+	netdev->hard_start_xmit = &atl1_xmit_frame;
+	netdev->get_stats = &atlx_get_stats;
+	netdev->set_multicast_list = &atlx_set_multi;
+	netdev->set_mac_address = &atl1_set_mac;
+	netdev->change_mtu = &atl1_change_mtu;
+	netdev->do_ioctl = &atlx_ioctl;
+	netdev->tx_timeout = &atlx_tx_timeout;
+	netdev->watchdog_timeo = 5 * HZ;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = atl1_poll_controller;
+#endif
+	netdev->vlan_rx_register = atlx_vlan_rx_register;
+
+	netdev->ethtool_ops = &atl1_ethtool_ops;
+	adapter->bd_number = cards_found;
+
+	/* setup the private structure */
+	err = atl1_sw_init(adapter);
+	if (err)
+		goto err_common;
+
+	netdev->features = NETIF_F_HW_CSUM;
+	netdev->features |= NETIF_F_SG;
+	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+	netdev->features |= NETIF_F_TSO;
+	netdev->features |= NETIF_F_LLTX;
+
+	/*
+	 * patch for some L1 of old version,
+	 * the final version of L1 may not need these
+	 * patches
+	 */
+	/* atl1_pcie_patch(adapter); */
+
+	/* really reset GPHY core */
+	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
+
+	/*
+	 * reset the controller to
+	 * put the device in a known good starting state
+	 */
+	if (atl1_reset_hw(&adapter->hw)) {
+		err = -EIO;
+		goto err_common;
+	}
+
+	/* copy the MAC address out of the EEPROM */
+	atl1_read_mac_addr(&adapter->hw);
+	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		err = -EIO;
+		goto err_common;
+	}
+
+	atl1_check_options(adapter);
+
+	/* pre-init the MAC, and setup link */
+	err = atl1_init_hw(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		goto err_common;
+	}
+
+	atl1_pcie_patch(adapter);
+	/* assume we have no link for now */
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	init_timer(&adapter->watchdog_timer);
+	adapter->watchdog_timer.function = &atl1_watchdog;
+	adapter->watchdog_timer.data = (unsigned long)adapter;
+
+	init_timer(&adapter->phy_config_timer);
+	adapter->phy_config_timer.function = &atl1_phy_config;
+	adapter->phy_config_timer.data = (unsigned long)adapter;
+	adapter->phy_timer_pending = false;
+
+	INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+
+	INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
+
+	INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
+
+	err = register_netdev(netdev);
+	if (err)
+		goto err_common;
+
+	cards_found++;
+	atl1_via_workaround(adapter);
+	return 0;
+
+err_common:
+	pci_iounmap(pdev, adapter->hw.hw_addr);
+err_pci_iomap:
+	free_netdev(netdev);
+err_alloc_etherdev:
+	pci_release_regions(pdev);
+err_dma:
+err_request_regions:
+	pci_disable_device(pdev);
+	return err;
+}
+
+/*
+ * atl1_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter;
+	/* Device not available. Return. */
+	if (!netdev)
+		return;
+
+	adapter = netdev_priv(netdev);
+
+	/*
+	 * Some atl1 boards lack persistent storage for their MAC, and get it
+	 * from the BIOS during POST.  If we've been messing with the MAC
+	 * address, we need to save the permanent one.
+	 */
+	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
+		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
+			ETH_ALEN);
+		atl1_set_mac_addr(&adapter->hw);
+	}
+
+	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
+	unregister_netdev(netdev);
+	pci_iounmap(pdev, adapter->hw.hw_addr);
+	pci_release_regions(pdev);
+	free_netdev(netdev);
+	pci_disable_device(pdev);
+}
+
+static struct pci_driver atl1_driver = {
+	.name = ATLX_DRIVER_NAME,
+	.id_table = atl1_pci_tbl,
+	.probe = atl1_probe,
+	.remove = __devexit_p(atl1_remove),
+	.suspend = atl1_suspend,
+	.resume = atl1_resume
+};
+
+/*
+ * atl1_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1_exit_module(void)
+{
+	pci_unregister_driver(&atl1_driver);
+}
+
+/*
+ * atl1_init_module - Driver Registration Routine
+ *
+ * atl1_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1_init_module(void)
+{
+	return pci_register_driver(&atl1_driver);
+}
+
+module_init(atl1_init_module);
+module_exit(atl1_exit_module);
+
+struct atl1_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int sizeof_stat;
+	int stat_offset;
+};
+
+#define ATL1_STAT(m) \
+	sizeof(((struct atl1_adapter *)0)->m), offsetof(struct atl1_adapter, m)
+
+static struct atl1_stats atl1_gstrings_stats[] = {
+	{"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
+	{"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
+	{"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
+	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
+	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
+	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
+	{"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
+	{"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
+	{"multicast", ATL1_STAT(soft_stats.multicast)},
+	{"collisions", ATL1_STAT(soft_stats.collisions)},
+	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
+	{"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+	{"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
+	{"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
+	{"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
+	{"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+	{"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
+	{"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
+	{"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
+	{"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
+	{"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
+	{"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
+	{"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
+	{"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
+	{"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
+	{"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
+	{"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
+	{"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
+	{"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
+	{"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
+	{"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
+};
+
+static void atl1_get_ethtool_stats(struct net_device *netdev,
+	struct ethtool_stats *stats, u64 *data)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int i;
+	char *p;
+
+	for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+		p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
+		data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
+			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+	}
+
+}
+
+static int atl1_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(atl1_gstrings_stats);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int atl1_get_settings(struct net_device *netdev,
+	struct ethtool_cmd *ecmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half |
+			   SUPPORTED_10baseT_Full |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_Autoneg | SUPPORTED_TP);
+	ecmd->advertising = ADVERTISED_TP;
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+		ecmd->advertising |= ADVERTISED_Autoneg;
+		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
+			ecmd->advertising |= ADVERTISED_Autoneg;
+			ecmd->advertising |=
+			    (ADVERTISED_10baseT_Half |
+			     ADVERTISED_10baseT_Full |
+			     ADVERTISED_100baseT_Half |
+			     ADVERTISED_100baseT_Full |
+			     ADVERTISED_1000baseT_Full);
+		} else
+			ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+	}
+	ecmd->port = PORT_TP;
+	ecmd->phy_address = 0;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (netif_carrier_ok(adapter->netdev)) {
+		u16 link_speed, link_duplex;
+		atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
+		ecmd->speed = link_speed;
+		if (link_duplex == FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+		ecmd->autoneg = AUTONEG_ENABLE;
+	else
+		ecmd->autoneg = AUTONEG_DISABLE;
+
+	return 0;
+}
+
+static int atl1_set_settings(struct net_device *netdev,
+	struct ethtool_cmd *ecmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	u16 phy_data;
+	int ret_val = 0;
+	u16 old_media_type = hw->media_type;
+
+	if (netif_running(adapter->netdev)) {
+		if (netif_msg_link(adapter))
+			dev_dbg(&adapter->pdev->dev,
+				"ethtool shutting down adapter\n");
+		atl1_down(adapter);
+	}
+
+	if (ecmd->autoneg == AUTONEG_ENABLE)
+		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+	else {
+		if (ecmd->speed == SPEED_1000) {
+			if (ecmd->duplex != DUPLEX_FULL) {
+				if (netif_msg_link(adapter))
+					dev_warn(&adapter->pdev->dev,
+						"1000M half is invalid\n");
+				ret_val = -EINVAL;
+				goto exit_sset;
+			}
+			hw->media_type = MEDIA_TYPE_1000M_FULL;
+		} else if (ecmd->speed == SPEED_100) {
+			if (ecmd->duplex == DUPLEX_FULL)
+				hw->media_type = MEDIA_TYPE_100M_FULL;
+			else
+				hw->media_type = MEDIA_TYPE_100M_HALF;
+		} else {
+			if (ecmd->duplex == DUPLEX_FULL)
+				hw->media_type = MEDIA_TYPE_10M_FULL;
+			else
+				hw->media_type = MEDIA_TYPE_10M_HALF;
+		}
+	}
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		ecmd->advertising =
+		    ADVERTISED_10baseT_Half |
+		    ADVERTISED_10baseT_Full |
+		    ADVERTISED_100baseT_Half |
+		    ADVERTISED_100baseT_Full |
+		    ADVERTISED_1000baseT_Full |
+		    ADVERTISED_Autoneg | ADVERTISED_TP;
+		break;
+	case MEDIA_TYPE_1000M_FULL:
+		ecmd->advertising =
+		    ADVERTISED_1000baseT_Full |
+		    ADVERTISED_Autoneg | ADVERTISED_TP;
+		break;
+	default:
+		ecmd->advertising = 0;
+		break;
+	}
+	if (atl1_phy_setup_autoneg_adv(hw)) {
+		ret_val = -EINVAL;
+		if (netif_msg_link(adapter))
+			dev_warn(&adapter->pdev->dev,
+				"invalid ethtool speed/duplex setting\n");
+		goto exit_sset;
+	}
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+	else {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			    MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:
+			/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+	}
+	atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+exit_sset:
+	if (ret_val)
+		hw->media_type = old_media_type;
+
+	if (netif_running(adapter->netdev)) {
+		if (netif_msg_link(adapter))
+			dev_dbg(&adapter->pdev->dev,
+				"ethtool starting adapter\n");
+		atl1_up(adapter);
+	} else if (!ret_val) {
+		if (netif_msg_link(adapter))
+			dev_dbg(&adapter->pdev->dev,
+				"ethtool resetting adapter\n");
+		atl1_reset(adapter);
+	}
+	return ret_val;
+}
+
+static void atl1_get_drvinfo(struct net_device *netdev,
+	struct ethtool_drvinfo *drvinfo)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	strncpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
+	strncpy(drvinfo->version, ATLX_DRIVER_VERSION,
+		sizeof(drvinfo->version));
+	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		sizeof(drvinfo->bus_info));
+	drvinfo->eedump_len = ATL1_EEDUMP_LEN;
+}
+
+static void atl1_get_wol(struct net_device *netdev,
+	struct ethtool_wolinfo *wol)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+	wol->wolopts = 0;
+	if (adapter->wol & ATLX_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if (adapter->wol & ATLX_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if (adapter->wol & ATLX_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if (adapter->wol & ATLX_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+	return;
+}
+
+static int atl1_set_wol(struct net_device *netdev,
+	struct ethtool_wolinfo *wol)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+		return -EOPNOTSUPP;
+	adapter->wol = 0;
+	if (wol->wolopts & WAKE_UCAST)
+		adapter->wol |= ATLX_WUFC_EX;
+	if (wol->wolopts & WAKE_MCAST)
+		adapter->wol |= ATLX_WUFC_MC;
+	if (wol->wolopts & WAKE_BCAST)
+		adapter->wol |= ATLX_WUFC_BC;
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= ATLX_WUFC_MAG;
+	return 0;
+}
+
+static u32 atl1_get_msglevel(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	return adapter->msg_enable;
+}
+
+static void atl1_set_msglevel(struct net_device *netdev, u32 value)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	adapter->msg_enable = value;
+}
+
+static int atl1_get_regs_len(struct net_device *netdev)
+{
+	return ATL1_REG_COUNT * sizeof(u32);
+}
+
+static void atl1_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
+	void *p)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	unsigned int i;
+	u32 *regbuf = p;
+
+	for (i = 0; i < ATL1_REG_COUNT; i++) {
+		/*
+		 * This switch statement avoids reserved regions
+		 * of register space.
+		 */
+		switch (i) {
+		case 6 ... 9:
+		case 14:
+		case 29 ... 31:
+		case 34 ... 63:
+		case 75 ... 127:
+		case 136 ... 1023:
+		case 1027 ... 1087:
+		case 1091 ... 1151:
+		case 1194 ... 1195:
+		case 1200 ... 1201:
+		case 1206 ... 1213:
+		case 1216 ... 1279:
+		case 1290 ... 1311:
+		case 1323 ... 1343:
+		case 1358 ... 1359:
+		case 1368 ... 1375:
+		case 1378 ... 1383:
+		case 1388 ... 1391:
+		case 1393 ... 1395:
+		case 1402 ... 1403:
+		case 1410 ... 1471:
+		case 1522 ... 1535:
+			/* reserved region; don't read it */
+			regbuf[i] = 0;
+			break;
+		default:
+			/* unreserved region */
+			regbuf[i] = ioread32(hw->hw_addr + (i * sizeof(u32)));
+		}
+	}
+}
+
+static void atl1_get_ringparam(struct net_device *netdev,
+	struct ethtool_ringparam *ring)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
+
+	ring->rx_max_pending = ATL1_MAX_RFD;
+	ring->tx_max_pending = ATL1_MAX_TPD;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = rxdr->count;
+	ring->tx_pending = txdr->count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static int atl1_set_ringparam(struct net_device *netdev,
+	struct ethtool_ringparam *ring)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
+	struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
+	struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
+
+	struct atl1_tpd_ring tpd_old, tpd_new;
+	struct atl1_rfd_ring rfd_old, rfd_new;
+	struct atl1_rrd_ring rrd_old, rrd_new;
+	struct atl1_ring_header rhdr_old, rhdr_new;
+	int err;
+
+	tpd_old = adapter->tpd_ring;
+	rfd_old = adapter->rfd_ring;
+	rrd_old = adapter->rrd_ring;
+	rhdr_old = adapter->ring_header;
+
+	if (netif_running(adapter->netdev))
+		atl1_down(adapter);
+
+	rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
+	rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
+			rfdr->count;
+	rfdr->count = (rfdr->count + 3) & ~3;
+	rrdr->count = rfdr->count;
+
+	tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
+	tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
+			tpdr->count;
+	tpdr->count = (tpdr->count + 3) & ~3;
+
+	if (netif_running(adapter->netdev)) {
+		/* try to get new resources before deleting old */
+		err = atl1_setup_ring_resources(adapter);
+		if (err)
+			goto err_setup_ring;
+
+		/*
+		 * save the new, restore the old in order to free it,
+		 * then restore the new back again
+		 */
+
+		rfd_new = adapter->rfd_ring;
+		rrd_new = adapter->rrd_ring;
+		tpd_new = adapter->tpd_ring;
+		rhdr_new = adapter->ring_header;
+		adapter->rfd_ring = rfd_old;
+		adapter->rrd_ring = rrd_old;
+		adapter->tpd_ring = tpd_old;
+		adapter->ring_header = rhdr_old;
+		atl1_free_ring_resources(adapter);
+		adapter->rfd_ring = rfd_new;
+		adapter->rrd_ring = rrd_new;
+		adapter->tpd_ring = tpd_new;
+		adapter->ring_header = rhdr_new;
+
+		err = atl1_up(adapter);
+		if (err)
+			return err;
+	}
+	return 0;
+
+err_setup_ring:
+	adapter->rfd_ring = rfd_old;
+	adapter->rrd_ring = rrd_old;
+	adapter->tpd_ring = tpd_old;
+	adapter->ring_header = rhdr_old;
+	atl1_up(adapter);
+	return err;
+}
+
+static void atl1_get_pauseparam(struct net_device *netdev,
+	struct ethtool_pauseparam *epause)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+		epause->autoneg = AUTONEG_ENABLE;
+	} else {
+		epause->autoneg = AUTONEG_DISABLE;
+	}
+	epause->rx_pause = 1;
+	epause->tx_pause = 1;
+}
+
+static int atl1_set_pauseparam(struct net_device *netdev,
+	struct ethtool_pauseparam *epause)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+		epause->autoneg = AUTONEG_ENABLE;
+	} else {
+		epause->autoneg = AUTONEG_DISABLE;
+	}
+
+	epause->rx_pause = 1;
+	epause->tx_pause = 1;
+
+	return 0;
+}
+
+/* FIXME: is this right? -- CHS */
+static u32 atl1_get_rx_csum(struct net_device *netdev)
+{
+	return 1;
+}
+
+static void atl1_get_strings(struct net_device *netdev, u32 stringset,
+	u8 *data)
+{
+	u8 *p = data;
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+			memcpy(p, atl1_gstrings_stats[i].stat_string,
+				ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	}
+}
+
+static int atl1_nway_reset(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	if (netif_running(netdev)) {
+		u16 phy_data;
+		atl1_down(adapter);
+
+		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+			hw->media_type == MEDIA_TYPE_1000M_FULL) {
+			phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+		} else {
+			switch (hw->media_type) {
+			case MEDIA_TYPE_100M_FULL:
+				phy_data = MII_CR_FULL_DUPLEX |
+					MII_CR_SPEED_100 | MII_CR_RESET;
+				break;
+			case MEDIA_TYPE_100M_HALF:
+				phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+				break;
+			case MEDIA_TYPE_10M_FULL:
+				phy_data = MII_CR_FULL_DUPLEX |
+					MII_CR_SPEED_10 | MII_CR_RESET;
+				break;
+			default:
+				/* MEDIA_TYPE_10M_HALF */
+				phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			}
+		}
+		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+		atl1_up(adapter);
+	}
+	return 0;
+}
+
+const struct ethtool_ops atl1_ethtool_ops = {
+	.get_settings		= atl1_get_settings,
+	.set_settings		= atl1_set_settings,
+	.get_drvinfo		= atl1_get_drvinfo,
+	.get_wol		= atl1_get_wol,
+	.set_wol		= atl1_set_wol,
+	.get_msglevel		= atl1_get_msglevel,
+	.set_msglevel		= atl1_set_msglevel,
+	.get_regs_len		= atl1_get_regs_len,
+	.get_regs		= atl1_get_regs,
+	.get_ringparam		= atl1_get_ringparam,
+	.set_ringparam		= atl1_set_ringparam,
+	.get_pauseparam		= atl1_get_pauseparam,
+	.set_pauseparam		= atl1_set_pauseparam,
+	.get_rx_csum		= atl1_get_rx_csum,
+	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
+	.get_link		= ethtool_op_get_link,
+	.set_sg			= ethtool_op_set_sg,
+	.get_strings		= atl1_get_strings,
+	.nway_reset		= atl1_nway_reset,
+	.get_ethtool_stats	= atl1_get_ethtool_stats,
+	.get_sset_count		= atl1_get_sset_count,
+	.set_tso		= ethtool_op_set_tso,
+};
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
new file mode 100644
index 0000000..51893d6
--- /dev/null
+++ b/drivers/net/atlx/atl1.h
@@ -0,0 +1,796 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef ATL1_H
+#define ATL1_H
+
+#include <linux/compiler.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "atlx.h"
+
+#define ATLX_DRIVER_NAME "atl1"
+
+MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver");
+
+#define atlx_adapter		atl1_adapter
+#define atlx_check_for_link	atl1_check_for_link
+#define atlx_check_link		atl1_check_link
+#define atlx_hash_mc_addr	atl1_hash_mc_addr
+#define atlx_hash_set		atl1_hash_set
+#define atlx_hw			atl1_hw
+#define atlx_mii_ioctl		atl1_mii_ioctl
+#define atlx_read_phy_reg	atl1_read_phy_reg
+#define atlx_set_mac		atl1_set_mac
+#define atlx_set_mac_addr	atl1_set_mac_addr
+
+struct atl1_adapter;
+struct atl1_hw;
+
+/* function prototypes needed by multiple files */
+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
+s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
+void atl1_set_mac_addr(struct atl1_hw *hw);
+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+	int cmd);
+static u32 atl1_check_link(struct atl1_adapter *adapter);
+
+extern const struct ethtool_ops atl1_ethtool_ops;
+
+/* hardware definitions specific to L1 */
+
+/* Block IDLE Status Register */
+#define IDLE_STATUS_RXMAC			0x1
+#define IDLE_STATUS_TXMAC			0x2
+#define IDLE_STATUS_RXQ				0x4
+#define IDLE_STATUS_TXQ				0x8
+#define IDLE_STATUS_DMAR			0x10
+#define IDLE_STATUS_DMAW			0x20
+#define IDLE_STATUS_SMB				0x40
+#define IDLE_STATUS_CMB				0x80
+
+/* MDIO Control Register */
+#define MDIO_WAIT_TIMES				30
+
+/* MAC Control Register */
+#define MAC_CTRL_TX_PAUSE			0x10000
+#define MAC_CTRL_SCNT				0x20000
+#define MAC_CTRL_SRST_TX			0x40000
+#define MAC_CTRL_TX_SIMURST			0x80000
+#define MAC_CTRL_SPEED_SHIFT			20
+#define MAC_CTRL_SPEED_MASK			0x300000
+#define MAC_CTRL_SPEED_1000			0x2
+#define MAC_CTRL_SPEED_10_100			0x1
+#define MAC_CTRL_DBG_TX_BKPRESURE		0x400000
+#define MAC_CTRL_TX_HUGE			0x800000
+#define MAC_CTRL_RX_CHKSUM_EN			0x1000000
+#define MAC_CTRL_DBG				0x8000000
+
+/* Wake-On-Lan control register */
+#define WOL_CLK_SWITCH_EN			0x8000
+#define WOL_PT5_EN				0x200000
+#define WOL_PT6_EN				0x400000
+#define WOL_PT5_MATCH				0x8000000
+#define WOL_PT6_MATCH				0x10000000
+
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN			0x14A4
+#define WOL_PT_LEN_MASK				0x7F
+#define WOL_PT0_LEN_SHIFT			0
+#define WOL_PT1_LEN_SHIFT			8
+#define WOL_PT2_LEN_SHIFT			16
+#define WOL_PT3_LEN_SHIFT			24
+#define WOL_PT4_LEN_SHIFT			0
+#define WOL_PT5_LEN_SHIFT			8
+#define WOL_PT6_LEN_SHIFT			16
+
+/* Internal SRAM Partition Registers, low 32 bits */
+#define REG_SRAM_RFD_LEN			0x1504
+#define REG_SRAM_RRD_ADDR			0x1508
+#define REG_SRAM_RRD_LEN			0x150C
+#define REG_SRAM_TPD_ADDR			0x1510
+#define REG_SRAM_TPD_LEN			0x1514
+#define REG_SRAM_TRD_ADDR			0x1518
+#define REG_SRAM_TRD_LEN			0x151C
+#define REG_SRAM_RXF_ADDR			0x1520
+#define REG_SRAM_RXF_LEN			0x1524
+#define REG_SRAM_TXF_ADDR			0x1528
+#define REG_SRAM_TXF_LEN			0x152C
+#define REG_SRAM_TCPH_PATH_ADDR			0x1530
+#define SRAM_TCPH_ADDR_MASK			0xFFF
+#define SRAM_TCPH_ADDR_SHIFT			0
+#define SRAM_PATH_ADDR_MASK			0xFFF
+#define SRAM_PATH_ADDR_SHIFT			16
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR				0x1534
+
+/* Descriptor Control registers, low 32 bits */
+#define REG_DESC_RFD_ADDR_LO			0x1544
+#define REG_DESC_RRD_ADDR_LO			0x1548
+#define REG_DESC_TPD_ADDR_LO			0x154C
+#define REG_DESC_CMB_ADDR_LO			0x1550
+#define REG_DESC_SMB_ADDR_LO			0x1554
+#define REG_DESC_RFD_RRD_RING_SIZE		0x1558
+#define DESC_RFD_RING_SIZE_MASK			0x7FF
+#define DESC_RFD_RING_SIZE_SHIFT		0
+#define DESC_RRD_RING_SIZE_MASK			0x7FF
+#define DESC_RRD_RING_SIZE_SHIFT		16
+#define REG_DESC_TPD_RING_SIZE			0x155C
+#define DESC_TPD_RING_SIZE_MASK			0x3FF
+#define DESC_TPD_RING_SIZE_SHIFT		0
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL				0x1580
+#define TXQ_CTRL_TPD_BURST_NUM_SHIFT		0
+#define TXQ_CTRL_TPD_BURST_NUM_MASK		0x1F
+#define TXQ_CTRL_EN				0x20
+#define TXQ_CTRL_ENH_MODE			0x40
+#define TXQ_CTRL_TPD_FETCH_TH_SHIFT		8
+#define TXQ_CTRL_TPD_FETCH_TH_MASK		0x3F
+#define TXQ_CTRL_TXF_BURST_NUM_SHIFT		16
+#define TXQ_CTRL_TXF_BURST_NUM_MASK		0xFFFF
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_JUMBO_TASK_TH_TPD_IPG		0x1584
+#define TX_JUMBO_TASK_TH_MASK			0x7FF
+#define TX_JUMBO_TASK_TH_SHIFT			0
+#define TX_TPD_MIN_IPG_MASK			0x1F
+#define TX_TPD_MIN_IPG_SHIFT			16
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL				0x15A0
+#define RXQ_CTRL_RFD_BURST_NUM_SHIFT		0
+#define RXQ_CTRL_RFD_BURST_NUM_MASK		0xFF
+#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT		8
+#define RXQ_CTRL_RRD_BURST_THRESH_MASK		0xFF
+#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT		16
+#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK		0x1F
+#define RXQ_CTRL_CUT_THRU_EN			0x40000000
+#define RXQ_CTRL_EN				0x80000000
+
+/* Rx jumbo packet threshold and rrd  retirement timer */
+#define REG_RXQ_JMBOSZ_RRDTIM			0x15A4
+#define RXQ_JMBOSZ_TH_MASK			0x7FF
+#define RXQ_JMBOSZ_TH_SHIFT			0
+#define RXQ_JMBO_LKAH_MASK			0xF
+#define RXQ_JMBO_LKAH_SHIFT			11
+#define RXQ_RRD_TIMER_MASK			0xFFFF
+#define RXQ_RRD_TIMER_SHIFT			16
+
+/* RFD flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH		0x15A8
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT		16
+#define RXQ_RXF_PAUSE_TH_HI_MASK		0xFFF
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT		0
+#define RXQ_RXF_PAUSE_TH_LO_MASK		0xFFF
+
+/* RRD flow control register */
+#define REG_RXQ_RRD_PAUSE_THRESH		0x15AC
+#define RXQ_RRD_PAUSE_TH_HI_SHIFT		0
+#define RXQ_RRD_PAUSE_TH_HI_MASK		0xFFF
+#define RXQ_RRD_PAUSE_TH_LO_SHIFT		16
+#define RXQ_RRD_PAUSE_TH_LO_MASK		0xFFF
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL				0x15C0
+#define DMA_CTRL_DMAR_IN_ORDER			0x1
+#define DMA_CTRL_DMAR_ENH_ORDER			0x2
+#define DMA_CTRL_DMAR_OUT_ORDER			0x4
+#define DMA_CTRL_RCB_VALUE			0x8
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT		4
+#define DMA_CTRL_DMAR_BURST_LEN_MASK		7
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT		7
+#define DMA_CTRL_DMAW_BURST_LEN_MASK		7
+#define DMA_CTRL_DMAR_EN			0x400
+#define DMA_CTRL_DMAW_EN			0x800
+
+/* CMB/SMB Control Register */
+#define REG_CSMB_CTRL				0x15D0
+#define CSMB_CTRL_CMB_NOW			1
+#define CSMB_CTRL_SMB_NOW			2
+#define CSMB_CTRL_CMB_EN			4
+#define CSMB_CTRL_SMB_EN			8
+
+/* CMB DMA Write Threshold Register */
+#define REG_CMB_WRITE_TH			0x15D4
+#define CMB_RRD_TH_SHIFT			0
+#define CMB_RRD_TH_MASK				0x7FF
+#define CMB_TPD_TH_SHIFT			16
+#define CMB_TPD_TH_MASK				0x7FF
+
+/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
+#define REG_CMB_WRITE_TIMER			0x15D8
+#define CMB_RX_TM_SHIFT				0
+#define CMB_RX_TM_MASK				0xFFFF
+#define CMB_TX_TM_SHIFT				16
+#define CMB_TX_TM_MASK				0xFFFF
+
+/* Number of packet received since last CMB write */
+#define REG_CMB_RX_PKT_CNT			0x15DC
+
+/* Number of packet transmitted since last CMB write */
+#define REG_CMB_TX_PKT_CNT			0x15E0
+
+/* SMB auto DMA timer register */
+#define REG_SMB_TIMER				0x15E4
+
+/* Mailbox Register */
+#define REG_MAILBOX				0x15F0
+#define MB_RFD_PROD_INDX_SHIFT			0
+#define MB_RFD_PROD_INDX_MASK			0x7FF
+#define MB_RRD_CONS_INDX_SHIFT			11
+#define MB_RRD_CONS_INDX_MASK			0x7FF
+#define MB_TPD_PROD_INDX_SHIFT			22
+#define MB_TPD_PROD_INDX_MASK			0x3FF
+
+/* Interrupt Status Register */
+#define ISR_SMB					0x1
+#define ISR_TIMER				0x2
+#define ISR_MANUAL				0x4
+#define ISR_RXF_OV				0x8
+#define ISR_RFD_UNRUN				0x10
+#define ISR_RRD_OV				0x20
+#define ISR_TXF_UNRUN				0x40
+#define ISR_LINK				0x80
+#define ISR_HOST_RFD_UNRUN			0x100
+#define ISR_HOST_RRD_OV				0x200
+#define ISR_DMAR_TO_RST				0x400
+#define ISR_DMAW_TO_RST				0x800
+#define ISR_GPHY				0x1000
+#define ISR_RX_PKT				0x10000
+#define ISR_TX_PKT				0x20000
+#define ISR_TX_DMA				0x40000
+#define ISR_RX_DMA				0x80000
+#define ISR_CMB_RX				0x100000
+#define ISR_CMB_TX				0x200000
+#define ISR_MAC_RX				0x400000
+#define ISR_MAC_TX				0x800000
+#define ISR_DIS_SMB				0x20000000
+#define ISR_DIS_DMA				0x40000000
+
+/* Normal Interrupt mask  */
+#define IMR_NORMAL_MASK	(\
+	ISR_SMB		|\
+	ISR_GPHY	|\
+	ISR_PHY_LINKDOWN|\
+	ISR_DMAR_TO_RST	|\
+	ISR_DMAW_TO_RST	|\
+	ISR_CMB_TX	|\
+	ISR_CMB_RX)
+
+/* Debug Interrupt Mask  (enable all interrupt) */
+#define IMR_DEBUG_MASK	(\
+	ISR_SMB		|\
+	ISR_TIMER	|\
+	ISR_MANUAL	|\
+	ISR_RXF_OV	|\
+	ISR_RFD_UNRUN	|\
+	ISR_RRD_OV	|\
+	ISR_TXF_UNRUN	|\
+	ISR_LINK	|\
+	ISR_CMB_TX	|\
+	ISR_CMB_RX	|\
+	ISR_RX_PKT	|\
+	ISR_TX_PKT	|\
+	ISR_MAC_RX	|\
+	ISR_MAC_TX)
+
+#define MEDIA_TYPE_1000M_FULL			1
+#define MEDIA_TYPE_100M_FULL			2
+#define MEDIA_TYPE_100M_HALF			3
+#define MEDIA_TYPE_10M_FULL			4
+#define MEDIA_TYPE_10M_HALF			5
+
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT		0x002F	/* All but 1000-Half */
+
+#define MAX_JUMBO_FRAME_SIZE			10240
+
+#define ATL1_EEDUMP_LEN				48
+
+/* Statistics counters collected by the MAC */
+struct stats_msg_block {
+	/* rx */
+	u32 rx_ok;		/* good RX packets */
+	u32 rx_bcast;		/* good RX broadcast packets */
+	u32 rx_mcast;		/* good RX multicast packets */
+	u32 rx_pause;		/* RX pause frames */
+	u32 rx_ctrl;		/* RX control packets other than pause frames */
+	u32 rx_fcs_err;		/* RX packets with bad FCS */
+	u32 rx_len_err;		/* RX packets with length != actual size */
+	u32 rx_byte_cnt;	/* good bytes received. FCS is NOT included */
+	u32 rx_runt;		/* RX packets < 64 bytes with good FCS */
+	u32 rx_frag;		/* RX packets < 64 bytes with bad FCS */
+	u32 rx_sz_64;		/* 64 byte RX packets */
+	u32 rx_sz_65_127;
+	u32 rx_sz_128_255;
+	u32 rx_sz_256_511;
+	u32 rx_sz_512_1023;
+	u32 rx_sz_1024_1518;
+	u32 rx_sz_1519_max;	/* 1519 byte to MTU RX packets */
+	u32 rx_sz_ov;		/* truncated RX packets > MTU */
+	u32 rx_rxf_ov;		/* frames dropped due to RX FIFO overflow */
+	u32 rx_rrd_ov;		/* frames dropped due to RRD overflow */
+	u32 rx_align_err;	/* alignment errors */
+	u32 rx_bcast_byte_cnt;	/* RX broadcast bytes, excluding FCS */
+	u32 rx_mcast_byte_cnt;	/* RX multicast bytes, excluding FCS */
+	u32 rx_err_addr;	/* packets dropped due to address filtering */
+
+	/* tx */
+	u32 tx_ok;		/* good TX packets */
+	u32 tx_bcast;		/* good TX broadcast packets */
+	u32 tx_mcast;		/* good TX multicast packets */
+	u32 tx_pause;		/* TX pause frames */
+	u32 tx_exc_defer;	/* TX packets deferred excessively */
+	u32 tx_ctrl;		/* TX control frames, excluding pause frames */
+	u32 tx_defer;		/* TX packets deferred */
+	u32 tx_byte_cnt;	/* bytes transmitted, FCS is NOT included */
+	u32 tx_sz_64;		/* 64 byte TX packets */
+	u32 tx_sz_65_127;
+	u32 tx_sz_128_255;
+	u32 tx_sz_256_511;
+	u32 tx_sz_512_1023;
+	u32 tx_sz_1024_1518;
+	u32 tx_sz_1519_max;	/* 1519 byte to MTU TX packets */
+	u32 tx_1_col;		/* packets TX after a single collision */
+	u32 tx_2_col;		/* packets TX after multiple collisions */
+	u32 tx_late_col;	/* TX packets with late collisions */
+	u32 tx_abort_col;	/* TX packets aborted w/excessive collisions */
+	u32 tx_underrun;	/* TX packets aborted due to TX FIFO underrun
+				 * or TRD FIFO underrun */
+	u32 tx_rd_eop;		/* reads beyond the EOP into the next frame
+				 * when TRD was not written timely */
+	u32 tx_len_err;		/* TX packets where length != actual size */
+	u32 tx_trunc;		/* TX packets truncated due to size > MTU */
+	u32 tx_bcast_byte;	/* broadcast bytes transmitted, excluding FCS */
+	u32 tx_mcast_byte;	/* multicast bytes transmitted, excluding FCS */
+	u32 smb_updated;	/* 1: SMB Updated. This is used by software to
+				 * indicate the statistics update. Software
+				 * should clear this bit after retrieving the
+				 * statistics information. */
+};
+
+/* Coalescing Message Block */
+struct coals_msg_block {
+	u32 int_stats;		/* interrupt status */
+	u16 rrd_prod_idx;	/* TRD Producer Index. */
+	u16 rfd_cons_idx;	/* RFD Consumer Index. */
+	u16 update;		/* Selene sets this bit every time it DMAs the
+				 * CMB to host memory. Software should clear
+				 * this bit when CMB info is processed. */
+	u16 tpd_cons_idx;	/* TPD Consumer Index. */
+};
+
+/* RRD descriptor */
+struct rx_return_desc {
+	u8 num_buf;	/* Number of RFD buffers used by the received packet */
+	u8 resved;
+	u16 buf_indx;	/* RFD Index of the first buffer */
+	union {
+		u32 valid;
+		struct {
+			u16 rx_chksum;
+			u16 pkt_size;
+		} xsum_sz;
+	} xsz;
+
+	u16 pkt_flg;	/* Packet flags */
+	u16 err_flg;	/* Error flags */
+	u16 resved2;
+	u16 vlan_tag;	/* VLAN TAG */
+};
+
+#define PACKET_FLAG_ETH_TYPE	0x0080
+#define PACKET_FLAG_VLAN_INS	0x0100
+#define PACKET_FLAG_ERR		0x0200
+#define PACKET_FLAG_IPV4	0x0400
+#define PACKET_FLAG_UDP		0x0800
+#define PACKET_FLAG_TCP		0x1000
+#define PACKET_FLAG_BCAST	0x2000
+#define PACKET_FLAG_MCAST	0x4000
+#define PACKET_FLAG_PAUSE	0x8000
+
+#define ERR_FLAG_CRC		0x0001
+#define ERR_FLAG_CODE		0x0002
+#define ERR_FLAG_DRIBBLE	0x0004
+#define ERR_FLAG_RUNT		0x0008
+#define ERR_FLAG_OV		0x0010
+#define ERR_FLAG_TRUNC		0x0020
+#define ERR_FLAG_IP_CHKSUM	0x0040
+#define ERR_FLAG_L4_CHKSUM	0x0080
+#define ERR_FLAG_LEN		0x0100
+#define ERR_FLAG_DES_ADDR	0x0200
+
+/* RFD descriptor */
+struct rx_free_desc {
+	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
+	__le16 buf_len;		/* Size of the receive buffer in host memory */
+	u16 coalese;		/* Update consumer index to host after the
+				 * reception of this frame */
+	/* __attribute__ ((packed)) is required */
+} __attribute__ ((packed));
+
+/*
+ * The L1 transmit packet descriptor is comprised of four 32-bit words.
+ *
+ *	31					0
+ *	+---------------------------------------+
+ *      |	Word 0: Buffer addr lo 		|
+ *      +---------------------------------------+
+ *      |	Word 1: Buffer addr hi		|
+ *      +---------------------------------------+
+ *      |		Word 2			|
+ *      +---------------------------------------+
+ *      |		Word 3			|
+ *      +---------------------------------------+
+ *
+ * Words 0 and 1 combine to form a 64-bit buffer address.
+ *
+ * Word 2 is self explanatory in the #define block below.
+ *
+ * Word 3 has two forms, depending upon the state of bits 3 and 4.
+ * If bits 3 and 4 are both zero, then bits 14:31 are unused by the
+ * hardware.  Otherwise, if either bit 3 or 4 is set, the definition
+ * of bits 14:31 vary according to the following depiction.
+ *
+ *	0	End of packet			0	End of packet
+ *	1	Coalesce			1	Coalesce
+ *	2	Insert VLAN tag			2	Insert VLAN tag
+ *	3	Custom csum enable = 0		3	Custom csum enable = 1
+ *	4	Segment enable = 1		4	Segment enable = 0
+ *	5	Generate IP checksum		5	Generate IP checksum
+ *	6	Generate TCP checksum		6	Generate TCP checksum
+ *	7	Generate UDP checksum		7	Generate UDP checksum
+ *	8	VLAN tagged			8	VLAN tagged
+ *	9	Ethernet frame type		9	Ethernet frame type
+ *	10-+ 					10-+
+ *	11 |	IP hdr length (10:13)		11 |	IP hdr length (10:13)
+ *	12 |	(num 32-bit words)		12 |	(num 32-bit words)
+ *	13-+					13-+
+ *	14-+					14	Unused
+ *	15 |	TCP hdr length (14:17)		15	Unused
+ *	16 |	(num 32-bit words)		16-+
+ *	17-+					17 |
+ *	18	Header TPD flag			18 |
+ *	19-+					19 |	Payload offset
+ *	20 |					20 |	    (16:23)
+ *	21 |					21 |
+ *	22 |					22 |
+ *	23 |					23-+
+ *	24 |					24-+
+ *	25 |	MSS (19:31)			25 |
+ *	26 |					26 |
+ *	27 |					27 |	Custom csum offset
+ *	28 |					28 |	     (24:31)
+ *	29 |					29 |
+ *	30 |					30 |
+ *	31-+					31-+
+ */
+
+/* tpd word 2 */
+#define TPD_BUFLEN_MASK		0x3FFF
+#define TPD_BUFLEN_SHIFT	0
+#define TPD_DMAINT_MASK		0x0001
+#define TPD_DMAINT_SHIFT	14
+#define TPD_PKTNT_MASK		0x0001
+#define TPD_PKTINT_SHIFT	15
+#define TPD_VLANTAG_MASK	0xFFFF
+#define TPD_VLAN_SHIFT		16
+
+/* tpd word 3 bits 0:13 */
+#define TPD_EOP_MASK		0x0001
+#define TPD_EOP_SHIFT		0
+#define TPD_COALESCE_MASK	0x0001
+#define TPD_COALESCE_SHIFT	1
+#define TPD_INS_VL_TAG_MASK	0x0001
+#define TPD_INS_VL_TAG_SHIFT	2
+#define TPD_CUST_CSUM_EN_MASK	0x0001
+#define TPD_CUST_CSUM_EN_SHIFT	3
+#define TPD_SEGMENT_EN_MASK	0x0001
+#define TPD_SEGMENT_EN_SHIFT	4
+#define TPD_IP_CSUM_MASK	0x0001
+#define TPD_IP_CSUM_SHIFT	5
+#define TPD_TCP_CSUM_MASK	0x0001
+#define TPD_TCP_CSUM_SHIFT	6
+#define TPD_UDP_CSUM_MASK	0x0001
+#define TPD_UDP_CSUM_SHIFT	7
+#define TPD_VL_TAGGED_MASK	0x0001
+#define TPD_VL_TAGGED_SHIFT	8
+#define TPD_ETHTYPE_MASK	0x0001
+#define TPD_ETHTYPE_SHIFT	9
+#define TPD_IPHL_MASK		0x000F
+#define TPD_IPHL_SHIFT		10
+
+/* tpd word 3 bits 14:31 if segment enabled */
+#define TPD_TCPHDRLEN_MASK	0x000F
+#define TPD_TCPHDRLEN_SHIFT	14
+#define TPD_HDRFLAG_MASK	0x0001
+#define TPD_HDRFLAG_SHIFT	18
+#define TPD_MSS_MASK		0x1FFF
+#define TPD_MSS_SHIFT		19
+
+/* tpd word 3 bits 16:31 if custom csum enabled */
+#define TPD_PLOADOFFSET_MASK	0x00FF
+#define TPD_PLOADOFFSET_SHIFT	16
+#define TPD_CCSUMOFFSET_MASK	0x00FF
+#define TPD_CCSUMOFFSET_SHIFT	24
+
+struct tx_packet_desc {
+	__le64 buffer_addr;
+	__le32 word2;
+	__le32 word3;
+};
+
+/* DMA Order Settings */
+enum atl1_dma_order {
+	atl1_dma_ord_in = 1,
+	atl1_dma_ord_enh = 2,
+	atl1_dma_ord_out = 4
+};
+
+enum atl1_dma_rcb {
+	atl1_rcb_64 = 0,
+	atl1_rcb_128 = 1
+};
+
+enum atl1_dma_req_block {
+	atl1_dma_req_128 = 0,
+	atl1_dma_req_256 = 1,
+	atl1_dma_req_512 = 2,
+	atl1_dma_req_1024 = 3,
+	atl1_dma_req_2048 = 4,
+	atl1_dma_req_4096 = 5
+};
+
+#define ATL1_MAX_INTR		3
+#define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */
+
+#define ATL1_DEFAULT_TPD	256
+#define ATL1_MAX_TPD		1024
+#define ATL1_MIN_TPD		64
+#define ATL1_DEFAULT_RFD	512
+#define ATL1_MIN_RFD		128
+#define ATL1_MAX_RFD		2048
+#define ATL1_REG_COUNT		1538
+
+#define ATL1_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
+#define ATL1_RFD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_free_desc)
+#define ATL1_TPD_DESC(R, i)	ATL1_GET_DESC(R, i, struct tx_packet_desc)
+#define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
+
+/*
+ * atl1_ring_header represents a single, contiguous block of DMA space
+ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+ * message blocks (cmb, smb) described below
+ */
+struct atl1_ring_header {
+	void *desc;		/* virtual address */
+	dma_addr_t dma;		/* physical address*/
+	unsigned int size;	/* length in bytes */
+};
+
+/*
+ * atl1_buffer is wrapper around a pointer to a socket buffer
+ * so a DMA handle can be stored along with the skb
+ */
+struct atl1_buffer {
+	struct sk_buff *skb;	/* socket buffer */
+	u16 length;		/* rx buffer length */
+	u16 alloced;		/* 1 if skb allocated */
+	dma_addr_t dma;
+};
+
+/* transmit packet descriptor (tpd) ring */
+struct atl1_tpd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 hw_idx;		/* hardware index */
+	atomic_t next_to_clean;
+	atomic_t next_to_use;
+	struct atl1_buffer *buffer_info;
+};
+
+/* receive free descriptor (rfd) ring */
+struct atl1_rfd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	atomic_t next_to_use;
+	u16 next_to_clean;
+	struct atl1_buffer *buffer_info;
+};
+
+/* receive return descriptor (rrd) ring */
+struct atl1_rrd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	unsigned int size;	/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 next_to_use;
+	atomic_t next_to_clean;
+};
+
+/* coalescing message block (cmb) */
+struct atl1_cmb {
+	struct coals_msg_block *cmb;
+	dma_addr_t dma;
+};
+
+/* statistics message block (smb) */
+struct atl1_smb {
+	struct stats_msg_block *smb;
+	dma_addr_t dma;
+};
+
+/* Statistics counters */
+struct atl1_sft_stats {
+	u64 rx_packets;
+	u64 tx_packets;
+	u64 rx_bytes;
+	u64 tx_bytes;
+	u64 multicast;
+	u64 collisions;
+	u64 rx_errors;
+	u64 rx_length_errors;
+	u64 rx_crc_errors;
+	u64 rx_frame_errors;
+	u64 rx_fifo_errors;
+	u64 rx_missed_errors;
+	u64 tx_errors;
+	u64 tx_fifo_errors;
+	u64 tx_aborted_errors;
+	u64 tx_window_errors;
+	u64 tx_carrier_errors;
+	u64 tx_pause;		/* TX pause frames */
+	u64 excecol;		/* TX packets w/ excessive collisions */
+	u64 deffer;		/* TX packets deferred */
+	u64 scc;		/* packets TX after a single collision */
+	u64 mcc;		/* packets TX after multiple collisions */
+	u64 latecol;		/* TX packets w/ late collisions */
+	u64 tx_underun;		/* TX packets aborted due to TX FIFO underrun
+				 * or TRD FIFO underrun */
+	u64 tx_trunc;		/* TX packets truncated due to size > MTU */
+	u64 rx_pause;		/* num Pause packets received. */
+	u64 rx_rrd_ov;
+	u64 rx_trunc;
+};
+
+/* hardware structure */
+struct atl1_hw {
+	u8 __iomem *hw_addr;
+	struct atl1_adapter *back;
+	enum atl1_dma_order dma_ord;
+	enum atl1_dma_rcb rcb_value;
+	enum atl1_dma_req_block dmar_block;
+	enum atl1_dma_req_block dmaw_block;
+	u8 preamble_len;
+	u8 max_retry;
+	u8 jam_ipg;		/* IPG to start JAM for collision based flow
+				 * control in half-duplex mode. In units of
+				 * 8-bit time */
+	u8 ipgt;		/* Desired back to back inter-packet gap.
+				 * The default is 96-bit time */
+	u8 min_ifg;		/* Minimum number of IFG to enforce in between
+				 * receive frames. Frame gap below such IFP
+				 * is dropped */
+	u8 ipgr1;		/* 64bit Carrier-Sense window */
+	u8 ipgr2;		/* 96-bit IPG window */
+	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
+				 * burst. Each TPD is 16 bytes long */
+	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
+				 * burst. Each RFD is 12 bytes long */
+	u8 rfd_fetch_gap;
+	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
+				 * in a burst. Each RRD is 16 bytes long */
+	u8 tpd_fetch_th;
+	u8 tpd_fetch_gap;
+	u16 tx_jumbo_task_th;
+	u16 txf_burst;		/* Number of data bytes to read in a cache-
+				 * aligned burst. Each SRAM entry is 8 bytes */
+	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
+				 * packets should add 4 bytes */
+	u16 rx_jumbo_lkah;
+	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
+				 * every 512ns passes. */
+	u16 lcol;		/* Collision Window */
+
+	u16 cmb_tpd;
+	u16 cmb_rrd;
+	u16 cmb_rx_timer;
+	u16 cmb_tx_timer;
+	u32 smb_timer;
+	u16 media_type;
+	u16 autoneg_advertised;
+
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	u32 max_frame_size;
+	u32 min_frame_size;
+
+	u16 dev_rev;
+
+	/* spi flash */
+	u8 flash_vendor;
+
+	u8 mac_addr[ETH_ALEN];
+	u8 perm_mac_addr[ETH_ALEN];
+
+	bool phy_configured;
+};
+
+struct atl1_adapter {
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+	struct net_device_stats net_stats;
+	struct atl1_sft_stats soft_stats;
+	struct vlan_group *vlgrp;
+	u32 rx_buffer_len;
+	u32 wol;
+	u16 link_speed;
+	u16 link_duplex;
+	spinlock_t lock;
+	struct work_struct tx_timeout_task;
+	struct work_struct link_chg_task;
+	struct work_struct pcie_dma_to_rst_task;
+	struct timer_list watchdog_timer;
+	struct timer_list phy_config_timer;
+	bool phy_timer_pending;
+
+	/* all descriptor rings' memory */
+	struct atl1_ring_header ring_header;
+
+	/* TX */
+	struct atl1_tpd_ring tpd_ring;
+	spinlock_t mb_lock;
+
+	/* RX */
+	struct atl1_rfd_ring rfd_ring;
+	struct atl1_rrd_ring rrd_ring;
+	u64 hw_csum_err;
+	u64 hw_csum_good;
+	u32 msg_enable;
+	u16 imt;		/* interrupt moderator timer (2us resolution) */
+	u16 ict;		/* interrupt clear timer (2us resolution */
+	struct mii_if_info mii;	/* MII interface info */
+
+	u32 bd_number;		/* board number */
+	bool pci_using_64;
+	struct atl1_hw hw;
+	struct atl1_smb smb;
+	struct atl1_cmb cmb;
+};
+
+#endif /* ATL1_H */
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
new file mode 100644
index 0000000..4186326
--- /dev/null
+++ b/drivers/net/atlx/atlx.c
@@ -0,0 +1,433 @@
+/* atlx.c -- common functions for Attansic network drivers
+ *
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/* Including this file like a header is a temporary hack, I promise. -- CHS */
+#ifndef ATLX_C
+#define ATLX_C
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/etherdevice.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "atlx.h"
+
+static struct atlx_spi_flash_dev flash_table[] = {
+/*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SEC_ERS CHIP_ERS */
+	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,   0x62},
+	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,   0x60},
+	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,   0xC7},
+};
+
+static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atlx_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/*
+ * atlx_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atlx_set_mac(struct net_device *netdev, void *p)
+{
+	struct atlx_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atlx_set_mac_addr(&adapter->hw);
+	return 0;
+}
+
+static void atlx_check_for_link(struct atlx_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	u16 phy_data = 0;
+
+	spin_lock(&adapter->lock);
+	adapter->phy_timer_pending = false;
+	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->lock);
+
+	/* notify upper layer link down ASAP */
+	if (!(phy_data & BMSR_LSTATUS)) {
+		/* Link Down */
+		if (netif_carrier_ok(netdev)) {
+			/* old link state: Up */
+			dev_info(&adapter->pdev->dev, "%s link is down\n",
+				netdev->name);
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	}
+	schedule_work(&adapter->link_chg_task);
+}
+
+/*
+ * atlx_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atlx_set_multi(struct net_device *netdev)
+{
+	struct atlx_adapter *adapter = netdev_priv(netdev);
+	struct atlx_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr;
+	u32 rctl;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+	if (netdev->flags & IFF_PROMISC)
+		rctl |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI) {
+		rctl |= MAC_CTRL_MC_ALL_EN;
+		rctl &= ~MAC_CTRL_PROMIS_EN;
+	} else
+		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+
+	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+
+	/* clear the old settings from the multicast hash table */
+	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+	/* compute mc addresses' hash value ,and put it into hash table */
+	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+		hash_value = atlx_hash_mc_addr(hw, mc_ptr->dmi_addr);
+		atlx_hash_set(hw, hash_value);
+	}
+}
+
+/*
+ * atlx_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static void atlx_irq_enable(struct atlx_adapter *adapter)
+{
+	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+	ioread32(adapter->hw.hw_addr + REG_IMR);
+}
+
+/*
+ * atlx_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static void atlx_irq_disable(struct atlx_adapter *adapter)
+{
+	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+	ioread32(adapter->hw.hw_addr + REG_IMR);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+static void atlx_clear_phy_int(struct atlx_adapter *adapter)
+{
+	u16 phy_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/*
+ * atlx_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atlx_get_stats(struct net_device *netdev)
+{
+	struct atlx_adapter *adapter = netdev_priv(netdev);
+	return &adapter->net_stats;
+}
+
+/*
+ * atlx_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atlx_tx_timeout(struct net_device *netdev)
+{
+	struct atlx_adapter *adapter = netdev_priv(netdev);
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->tx_timeout_task);
+}
+
+/*
+ * atlx_link_chg_task - deal with link change event Out of interrupt context
+ */
+static void atlx_link_chg_task(struct work_struct *work)
+{
+	struct atlx_adapter *adapter;
+	unsigned long flags;
+
+	adapter = container_of(work, struct atlx_adapter, link_chg_task);
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	atlx_check_link(adapter);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+static void atlx_vlan_rx_register(struct net_device *netdev,
+	struct vlan_group *grp)
+{
+	struct atlx_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	u32 ctrl;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	/* atlx_irq_disable(adapter); FIXME: confirm/remove */
+	adapter->vlgrp = grp;
+
+	if (grp) {
+		/* enable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl |= MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	} else {
+		/* disable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	}
+
+	/* atlx_irq_enable(adapter); FIXME */
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+static void atlx_restore_vlan(struct atlx_adapter *adapter)
+{
+	atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+
+/*
+ * This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+#define ATL1_MAX_NIC 4
+
+#define OPTION_UNSET    -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+
+/*
+ * Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 100 (200us)
+ */
+static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_int_mod_timer;
+module_param_array_named(int_mod_timer, int_mod_timer, int,
+	&num_int_mod_timer, 0);
+MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+
+/*
+ * flash_vendor
+ *
+ * Valid Range: 0-2
+ *
+ * 0 - Atmel
+ * 1 - SST
+ * 2 - ST
+ *
+ * Default Value: 0
+ */
+static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_flash_vendor;
+module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
+MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
+
+#define DEFAULT_INT_MOD_CNT	100	/* 200us */
+#define MAX_INT_MOD_CNT		65000
+#define MIN_INT_MOD_CNT		50
+
+#define FLASH_VENDOR_DEFAULT	0
+#define FLASH_VENDOR_MIN	0
+#define FLASH_VENDOR_MAX	2
+
+struct atl1_option {
+	enum { enable_option, range_option, list_option } type;
+	char *name;
+	char *err;
+	int def;
+	union {
+		struct {	/* range_option info */
+			int min;
+			int max;
+		} r;
+		struct {	/* list_option info */
+			int nr;
+			struct atl1_opt_list {
+				int i;
+				char *str;
+			} *p;
+		} l;
+	} arg;
+};
+
+static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
+	struct pci_dev *pdev)
+{
+	if (*value == OPTION_UNSET) {
+		*value = opt->def;
+		return 0;
+	}
+
+	switch (opt->type) {
+	case enable_option:
+		switch (*value) {
+		case OPTION_ENABLED:
+			dev_info(&pdev->dev, "%s enabled\n", opt->name);
+			return 0;
+		case OPTION_DISABLED:
+			dev_info(&pdev->dev, "%s disabled\n", opt->name);
+			return 0;
+		}
+		break;
+	case range_option:
+		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+			dev_info(&pdev->dev, "%s set to %i\n", opt->name,
+				*value);
+			return 0;
+		}
+		break;
+	case list_option:{
+			int i;
+			struct atl1_opt_list *ent;
+
+			for (i = 0; i < opt->arg.l.nr; i++) {
+				ent = &opt->arg.l.p[i];
+				if (*value == ent->i) {
+					if (ent->str[0] != '\0')
+						dev_info(&pdev->dev, "%s\n",
+							ent->str);
+					return 0;
+				}
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
+		opt->name, *value, opt->err);
+	*value = opt->def;
+	return -1;
+}
+
+/*
+ * atl1_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input.  If an invalid value is given, or if no user specified
+ * value exists, a default value is used.  The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1_check_options(struct atl1_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	int bd = adapter->bd_number;
+	if (bd >= ATL1_MAX_NIC) {
+		dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
+		dev_notice(&pdev->dev, "using defaults for all values\n");
+	}
+	{			/* Interrupt Moderate Timer */
+		struct atl1_option opt = {
+			.type = range_option,
+			.name = "Interrupt Moderator Timer",
+			.err = "using default of "
+				__MODULE_STRING(DEFAULT_INT_MOD_CNT),
+			.def = DEFAULT_INT_MOD_CNT,
+			.arg = {.r = {.min = MIN_INT_MOD_CNT,
+					.max = MAX_INT_MOD_CNT} }
+		};
+		int val;
+		if (num_int_mod_timer > bd) {
+			val = int_mod_timer[bd];
+			atl1_validate_option(&val, &opt, pdev);
+			adapter->imt = (u16) val;
+		} else
+			adapter->imt = (u16) (opt.def);
+	}
+
+	{			/* Flash Vendor */
+		struct atl1_option opt = {
+			.type = range_option,
+			.name = "SPI Flash Vendor",
+			.err = "using default of "
+				__MODULE_STRING(FLASH_VENDOR_DEFAULT),
+			.def = DEFAULT_INT_MOD_CNT,
+			.arg = {.r = {.min = FLASH_VENDOR_MIN,
+					.max = FLASH_VENDOR_MAX} }
+		};
+		int val;
+		if (num_flash_vendor > bd) {
+			val = flash_vendor[bd];
+			atl1_validate_option(&val, &opt, pdev);
+			adapter->hw.flash_vendor = (u8) val;
+		} else
+			adapter->hw.flash_vendor = (u8) (opt.def);
+	}
+}
+
+#endif /* ATLX_C */
diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h
new file mode 100644
index 0000000..3be7c09
--- /dev/null
+++ b/drivers/net/atlx/atlx.h
@@ -0,0 +1,506 @@
+/* atlx_hw.h -- common hardware definitions for Attansic network drivers
+ *
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef ATLX_H
+#define ATLX_H
+
+#include <linux/module.h>
+#include <linux/types.h>
+
+#define ATLX_DRIVER_VERSION "2.1.1"
+MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, \
+	Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ATLX_DRIVER_VERSION);
+
+#define ATLX_ERR_PHY			2
+#define ATLX_ERR_PHY_SPEED		7
+#define ATLX_ERR_PHY_RES		8
+
+#define SPEED_0				0xffff
+#define SPEED_10			10
+#define SPEED_100			100
+#define SPEED_1000			1000
+#define HALF_DUPLEX			1
+#define FULL_DUPLEX			2
+
+#define MEDIA_TYPE_AUTO_SENSOR		0
+
+/* register definitions */
+#define REG_PM_CTRLSTAT			0x44
+
+#define REG_PCIE_CAP_LIST		0x58
+
+#define REG_VPD_CAP			0x6C
+#define VPD_CAP_ID_MASK			0xFF
+#define VPD_CAP_ID_SHIFT		0
+#define VPD_CAP_NEXT_PTR_MASK		0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT		8
+#define VPD_CAP_VPD_ADDR_MASK		0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT		16
+#define VPD_CAP_VPD_FLAG		0x80000000
+
+#define REG_VPD_DATA			0x70
+
+#define REG_SPI_FLASH_CTRL		0x200
+#define SPI_FLASH_CTRL_STS_NON_RDY	0x1
+#define SPI_FLASH_CTRL_STS_WEN		0x2
+#define SPI_FLASH_CTRL_STS_WPEN		0x80
+#define SPI_FLASH_CTRL_DEV_STS_MASK	0xFF
+#define SPI_FLASH_CTRL_DEV_STS_SHIFT	0
+#define SPI_FLASH_CTRL_INS_MASK		0x7
+#define SPI_FLASH_CTRL_INS_SHIFT	8
+#define SPI_FLASH_CTRL_START		0x800
+#define SPI_FLASH_CTRL_EN_VPD		0x2000
+#define SPI_FLASH_CTRL_LDSTART		0x8000
+#define SPI_FLASH_CTRL_CS_HI_MASK	0x3
+#define SPI_FLASH_CTRL_CS_HI_SHIFT	16
+#define SPI_FLASH_CTRL_CS_HOLD_MASK	0x3
+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT	18
+#define SPI_FLASH_CTRL_CLK_LO_MASK	0x3
+#define SPI_FLASH_CTRL_CLK_LO_SHIFT	20
+#define SPI_FLASH_CTRL_CLK_HI_MASK	0x3
+#define SPI_FLASH_CTRL_CLK_HI_SHIFT	22
+#define SPI_FLASH_CTRL_CS_SETUP_MASK	0x3
+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT	24
+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK	0x3
+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT	26
+#define SPI_FLASH_CTRL_WAIT_READY	0x10000000
+
+#define REG_SPI_ADDR			0x204
+
+#define REG_SPI_DATA			0x208
+
+#define REG_SPI_FLASH_CONFIG		0x20C
+#define SPI_FLASH_CONFIG_LD_ADDR_MASK	0xFFFFFF
+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT	0
+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK	0x3
+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT	24
+#define SPI_FLASH_CONFIG_LD_EXIST	0x4000000
+
+#define REG_SPI_FLASH_OP_PROGRAM	0x210
+#define REG_SPI_FLASH_OP_SC_ERASE	0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE	0x212
+#define REG_SPI_FLASH_OP_RDID		0x213
+#define REG_SPI_FLASH_OP_WREN		0x214
+#define REG_SPI_FLASH_OP_RDSR		0x215
+#define REG_SPI_FLASH_OP_WRSR		0x216
+#define REG_SPI_FLASH_OP_READ		0x217
+
+#define REG_TWSI_CTRL			0x218
+#define TWSI_CTRL_LD_OFFSET_MASK	0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT	0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK	0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT	8
+#define TWSI_CTRL_SW_LDSTART		0x800
+#define TWSI_CTRL_HW_LDSTART		0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK	0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT	15
+#define TWSI_CTRL_LD_EXIST		0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK	0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT	23
+#define TWSI_CTRL_FREQ_SEL_100K		0
+#define TWSI_CTRL_FREQ_SEL_200K		1
+#define TWSI_CTRL_FREQ_SEL_300K		2
+#define TWSI_CTRL_FREQ_SEL_400K		3
+#define TWSI_CTRL_SMB_SLV_ADDR		/* FIXME: define or remove */
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK	0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT	24
+
+#define REG_PCIE_DEV_MISC_CTRL			0x21C
+#define PCIE_DEV_MISC_CTRL_EXT_PIPE		0x2
+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS		0x1
+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST		0x4
+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN	0x8
+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN	0x10
+
+#define REG_PCIE_PHYMISC		0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
+
+#define REG_PCIE_DLL_TX_CTRL1		0x1104
+#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK	0x400
+#define PCIE_DLL_TX_CTRL1_DEF		0x568
+
+#define REG_LTSSM_TEST_MODE		0x12FC
+#define LTSSM_TEST_MODE_DEF		0x6500
+
+/* Master Control Register */
+#define REG_MASTER_CTRL			0x1400
+#define MASTER_CTRL_SOFT_RST		0x1
+#define MASTER_CTRL_MTIMER_EN		0x2
+#define MASTER_CTRL_ITIMER_EN		0x4
+#define MASTER_CTRL_MANUAL_INT		0x8
+#define MASTER_CTRL_REV_NUM_SHIFT	16
+#define MASTER_CTRL_REV_NUM_MASK	0xFF
+#define MASTER_CTRL_DEV_ID_SHIFT	24
+#define MASTER_CTRL_DEV_ID_MASK		0xFF
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT		0x1404
+
+/* IRQ Moderator Timer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT		0x1408
+
+#define REG_PHY_ENABLE			0x140C
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER		0x140E
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS			0x1410
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL			0x1414
+#define MDIO_DATA_MASK			0xFFFF
+#define MDIO_DATA_SHIFT			0
+#define MDIO_REG_ADDR_MASK		0x1F
+#define MDIO_REG_ADDR_SHIFT		16
+#define MDIO_RW				0x200000
+#define MDIO_SUP_PREAMBLE		0x400000
+#define MDIO_START			0x800000
+#define MDIO_CLK_SEL_SHIFT		24
+#define MDIO_CLK_25_4			0
+#define MDIO_CLK_25_6			2
+#define MDIO_CLK_25_8			3
+#define MDIO_CLK_25_10			4
+#define MDIO_CLK_25_14			5
+#define MDIO_CLK_25_20			6
+#define MDIO_CLK_25_28			7
+#define MDIO_BUSY			0x8000000
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS			0x1418
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL			0x141C
+#define BIST0_NOW			0x1
+#define BIST0_SRAM_FAIL			0x2
+#define BIST0_FUSE_FLAG			0x4
+#define REG_BIST1_CTRL			0x1420
+#define BIST1_NOW			0x1
+#define BIST1_SRAM_FAIL			0x2
+#define BIST1_FUSE_FLAG			0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK			0x1424
+#define SERDES_LOCK_DETECT		1
+#define SERDES_LOCK_DETECT_EN		2
+
+/* MAC Control Register */
+#define REG_MAC_CTRL			0x1480
+#define MAC_CTRL_TX_EN			1
+#define MAC_CTRL_RX_EN			2
+#define MAC_CTRL_TX_FLOW		4
+#define MAC_CTRL_RX_FLOW		8
+#define MAC_CTRL_LOOPBACK		0x10
+#define MAC_CTRL_DUPLX			0x20
+#define MAC_CTRL_ADD_CRC		0x40
+#define MAC_CTRL_PAD			0x80
+#define MAC_CTRL_LENCHK			0x100
+#define MAC_CTRL_HUGE_EN		0x200
+#define MAC_CTRL_PRMLEN_SHIFT		10
+#define MAC_CTRL_PRMLEN_MASK		0xF
+#define MAC_CTRL_RMV_VLAN		0x4000
+#define MAC_CTRL_PROMIS_EN		0x8000
+#define MAC_CTRL_MC_ALL_EN		0x2000000
+#define MAC_CTRL_BC_EN			0x4000000
+
+/* MAC IPG/IFG Control Register */
+#define REG_MAC_IPG_IFG			0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT		0
+#define MAC_IPG_IFG_IPGT_MASK		0x7F
+#define MAC_IPG_IFG_MIFG_SHIFT		8
+#define MAC_IPG_IFG_MIFG_MASK		0xFF
+#define MAC_IPG_IFG_IPGR1_SHIFT		16
+#define MAC_IPG_IFG_IPGR1_MASK		0x7F
+#define MAC_IPG_IFG_IPGR2_SHIFT		24
+#define MAC_IPG_IFG_IPGR2_MASK		0x7F
+
+/* MAC STATION ADDRESS */
+#define REG_MAC_STA_ADDR		0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE		0x1490
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL			0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT		0
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK		0x3FF
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT		12
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK		0xF
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN		0x10000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C		0x20000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P		0x40000
+#define MAC_HALF_DUPLX_CTRL_ABEBE		0x80000
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT		20
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK		0xF
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT	24
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK		0xF
+
+/* Maximum Frame Length Control Register */
+#define REG_MTU				0x149C
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL			0x14A0
+#define WOL_PATTERN_EN			0x1
+#define WOL_PATTERN_PME_EN		0x2
+#define WOL_MAGIC_EN			0x4
+#define WOL_MAGIC_PME_EN		0x8
+#define WOL_LINK_CHG_EN			0x10
+#define WOL_LINK_CHG_PME_EN		0x20
+#define WOL_PATTERN_ST			0x100
+#define WOL_MAGIC_ST			0x200
+#define WOL_LINKCHG_ST			0x400
+#define WOL_PT0_EN			0x10000
+#define WOL_PT1_EN			0x20000
+#define WOL_PT2_EN			0x40000
+#define WOL_PT3_EN			0x80000
+#define WOL_PT4_EN			0x100000
+#define WOL_PT0_MATCH			0x1000000
+#define WOL_PT1_MATCH			0x2000000
+#define WOL_PT2_MATCH			0x4000000
+#define WOL_PT3_MATCH			0x8000000
+#define WOL_PT4_MATCH			0x10000000
+
+/* Internal SRAM Partition Register, high 32 bits */
+#define REG_SRAM_RFD_ADDR		0x1500
+
+/* Descriptor Control register, high 32 bits */
+#define REG_DESC_BASE_ADDR_HI		0x1540
+
+/* Interrupt Status Register */
+#define REG_ISR				0x1600
+#define ISR_UR_DETECTED			0x1000000
+#define ISR_FERR_DETECTED		0x2000000
+#define ISR_NFERR_DETECTED		0x4000000
+#define ISR_CERR_DETECTED		0x8000000
+#define ISR_PHY_LINKDOWN		0x10000000
+#define ISR_DIS_INT			0x80000000
+
+/* Interrupt Mask Register */
+#define REG_IMR				0x1604
+
+#define REG_RFD_RRD_IDX			0x1800
+#define REG_TPD_IDX			0x1804
+
+/* MII definitions */
+
+/* PHY Common Register */
+#define MII_ATLX_CR			0x09
+#define MII_ATLX_SR			0x0A
+#define MII_ATLX_ESR			0x0F
+#define MII_ATLX_PSCR			0x10
+#define MII_ATLX_PSSR			0x11
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB		0x0040	/* bits 6,13: 10=1000, 01=100,
+						 * 00=10
+						 */
+#define MII_CR_COLL_TEST_ENABLE		0x0080	/* Collision test enable */
+#define MII_CR_FULL_DUPLEX		0x0100	/* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG		0x0200	/* Restart auto negotiation */
+#define MII_CR_ISOLATE			0x0400	/* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN		0x0800	/* Power down */
+#define MII_CR_AUTO_NEG_EN		0x1000	/* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB		0x2000	/* bits 6,13: 10=1000, 01=100,
+						 * 00=10
+						 */
+#define MII_CR_LOOPBACK			0x4000	/* 0 = normal, 1 = loopback */
+#define MII_CR_RESET			0x8000	/* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_MASK		0x2040
+#define MII_CR_SPEED_1000		0x0040
+#define MII_CR_SPEED_100		0x2000
+#define MII_CR_SPEED_10			0x0000
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS		0x0001	/* Ext register capabilities */
+#define MII_SR_JABBER_DETECT		0x0002	/* Jabber Detected */
+#define MII_SR_LINK_STATUS		0x0004	/* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS		0x0008	/* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT		0x0010	/* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE		0x0020	/* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS	0x0040	/* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS		0x0100	/* Ext stat info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS		0x0200	/* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS		0x0400	/* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS		0x0800	/* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS		0x1000	/* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS		0x2000	/* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS		0x4000	/* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS		0x8000	/* 100T4 Capable */
+
+/* Link partner ability register */
+#define MII_LPA_SLCT			0x001f	/* Same as advertise selector */
+#define MII_LPA_10HALF			0x0020	/* Can do 10mbps half-duplex */
+#define MII_LPA_10FULL			0x0040	/* Can do 10mbps full-duplex */
+#define MII_LPA_100HALF			0x0080	/* Can do 100mbps half-duplex */
+#define MII_LPA_100FULL			0x0100	/* Can do 100mbps full-duplex */
+#define MII_LPA_100BASE4		0x0200	/* 100BASE-T4 */
+#define MII_LPA_PAUSE			0x0400	/* PAUSE */
+#define MII_LPA_ASYPAUSE		0x0800	/* Asymmetrical PAUSE */
+#define MII_LPA_RFAULT			0x2000	/* Link partner faulted */
+#define MII_LPA_LPACK			0x4000	/* Link partner acked us */
+#define MII_LPA_NPAGE			0x8000	/* Next page bit */
+
+/* Autoneg Advertisement Register */
+#define MII_AR_SELECTOR_FIELD		0x0001	/* IEEE 802.3 CSMA/CD */
+#define MII_AR_10T_HD_CAPS		0x0020	/* 10T   Half Duplex Capable */
+#define MII_AR_10T_FD_CAPS		0x0040	/* 10T   Full Duplex Capable */
+#define MII_AR_100TX_HD_CAPS		0x0080	/* 100TX Half Duplex Capable */
+#define MII_AR_100TX_FD_CAPS		0x0100	/* 100TX Full Duplex Capable */
+#define MII_AR_100T4_CAPS		0x0200	/* 100T4 Capable */
+#define MII_AR_PAUSE			0x0400	/* Pause operation desired */
+#define MII_AR_ASM_DIR			0x0800	/* Asymmetric Pause Dir bit */
+#define MII_AR_REMOTE_FAULT		0x2000	/* Remote Fault detected */
+#define MII_AR_NEXT_PAGE		0x8000	/* Next Page ability support */
+#define MII_AR_SPEED_MASK		0x01E0
+#define MII_AR_DEFAULT_CAP_MASK		0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_ATLX_CR_1000T_HD_CAPS	0x0100	/* Adv 1000T HD cap */
+#define MII_ATLX_CR_1000T_FD_CAPS	0x0200	/* Adv 1000T FD cap */
+#define MII_ATLX_CR_1000T_REPEATER_DTE	0x0400	/* 1=Repeater/switch device,
+						 * 0=DTE device */
+#define MII_ATLX_CR_1000T_MS_VALUE	0x0800	/* 1=Config PHY as Master,
+						 * 0=Configure PHY as Slave */
+#define MII_ATLX_CR_1000T_MS_ENABLE	0x1000	/* 1=Man Master/Slave config,
+						 * 0=Auto Master/Slave config
+						 */
+#define MII_ATLX_CR_1000T_TEST_MODE_NORMAL	0x0000	/* Normal Operation */
+#define MII_ATLX_CR_1000T_TEST_MODE_1	0x2000	/* Transmit Waveform test */
+#define MII_ATLX_CR_1000T_TEST_MODE_2	0x4000	/* Master Xmit Jitter test */
+#define MII_ATLX_CR_1000T_TEST_MODE_3	0x6000	/* Slave Xmit Jitter test */
+#define MII_ATLX_CR_1000T_TEST_MODE_4	0x8000	/* Xmitter Distortion test */
+#define MII_ATLX_CR_1000T_SPEED_MASK	0x0300
+#define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK	0x0300
+
+/* 1000BASE-T Status Register */
+#define MII_ATLX_SR_1000T_LP_HD_CAPS	0x0400	/* LP is 1000T HD capable */
+#define MII_ATLX_SR_1000T_LP_FD_CAPS	0x0800	/* LP is 1000T FD capable */
+#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS	0x1000	/* Remote receiver OK */
+#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS	0x2000	/* Local receiver OK */
+#define MII_ATLX_SR_1000T_MS_CONFIG_RES		0x4000	/* 1=Local TX is Master
+							 * 0=Slave
+							 */
+#define MII_ATLX_SR_1000T_MS_CONFIG_FAULT	0x8000	/* Master/Slave config
+							 * fault */
+#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT	12
+#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT		13
+
+/* Extended Status Register */
+#define MII_ATLX_ESR_1000T_HD_CAPS	0x1000	/* 1000T HD capable */
+#define MII_ATLX_ESR_1000T_FD_CAPS	0x2000	/* 1000T FD capable */
+#define MII_ATLX_ESR_1000X_HD_CAPS	0x4000	/* 1000X HD capable */
+#define MII_ATLX_ESR_1000X_FD_CAPS	0x8000	/* 1000X FD capable */
+
+/* ATLX PHY Specific Control Register */
+#define MII_ATLX_PSCR_JABBER_DISABLE	0x0001	/* 1=Jabber Func disabled */
+#define MII_ATLX_PSCR_POLARITY_REVERSAL	0x0002	/* 1=Polarity Reversal enbld */
+#define MII_ATLX_PSCR_SQE_TEST		0x0004	/* 1=SQE Test enabled */
+#define MII_ATLX_PSCR_MAC_POWERDOWN	0x0008
+#define MII_ATLX_PSCR_CLK125_DISABLE	0x0010	/* 1=CLK125 low
+						 * 0=CLK125 toggling
+						 */
+#define MII_ATLX_PSCR_MDI_MANUAL_MODE	0x0000	/* MDI Crossover Mode bits 6:5,
+						 * Manual MDI configuration
+						 */
+#define MII_ATLX_PSCR_MDIX_MANUAL_MODE	0x0020	/* Manual MDIX configuration */
+#define MII_ATLX_PSCR_AUTO_X_1000T	0x0040	/* 1000BASE-T: Auto crossover
+						 * 100BASE-TX/10BASE-T: MDI
+						 * Mode */
+#define MII_ATLX_PSCR_AUTO_X_MODE	0x0060	/* Auto crossover enabled
+						 * all speeds.
+						 */
+#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE	0x0080	/* 1=Enable Extended
+							 * 10BASE-T distance
+							 * (Lower 10BASE-T RX
+							 * Threshold)
+							 * 0=Normal 10BASE-T RX
+							 * Threshold
+							 */
+#define MII_ATLX_PSCR_MII_5BIT_ENABLE	0x0100	/* 1=5-Bit interface in
+						 * 100BASE-TX
+						 * 0=MII interface in
+						 * 100BASE-TX
+						 */
+#define MII_ATLX_PSCR_SCRAMBLER_DISABLE	0x0200	/* 1=Scrambler dsbl */
+#define MII_ATLX_PSCR_FORCE_LINK_GOOD	0x0400	/* 1=Force link good */
+#define MII_ATLX_PSCR_ASSERT_CRS_ON_TX	0x0800	/* 1=Assert CRS on Transmit */
+#define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT		1
+#define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT			5
+#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT	7
+
+/* ATLX PHY Specific Status Register */
+#define MII_ATLX_PSSR_SPD_DPLX_RESOLVED	0x0800	/* 1=Speed & Duplex resolved */
+#define MII_ATLX_PSSR_DPLX		0x2000	/* 1=Duplex 0=Half Duplex */
+#define MII_ATLX_PSSR_SPEED		0xC000	/* Speed, bits 14:15 */
+#define MII_ATLX_PSSR_10MBS		0x0000	/* 00=10Mbs */
+#define MII_ATLX_PSSR_100MBS		0x4000	/* 01=100Mbs */
+#define MII_ATLX_PSSR_1000MBS		0x8000	/* 10=1000Mbs */
+
+/* PCI Command Register Bit Definitions */
+#define PCI_REG_COMMAND			0x04	/* PCI Command Register */
+#define CMD_IO_SPACE			0x0001
+#define CMD_MEMORY_SPACE		0x0002
+#define CMD_BUS_MASTER			0x0004
+
+/* Wake Up Filter Control */
+#define ATLX_WUFC_LNKC	0x00000001	/* Link Status Change Wakeup Enable */
+#define ATLX_WUFC_MAG	0x00000002	/* Magic Packet Wakeup Enable */
+#define ATLX_WUFC_EX	0x00000004	/* Directed Exact Wakeup Enable */
+#define ATLX_WUFC_MC	0x00000008	/* Multicast Wakeup Enable */
+#define ATLX_WUFC_BC	0x00000010	/* Broadcast Wakeup Enable */
+
+#define ADVERTISE_10_HALF		0x0001
+#define ADVERTISE_10_FULL		0x0002
+#define ADVERTISE_100_HALF		0x0004
+#define ADVERTISE_100_FULL		0x0008
+#define ADVERTISE_1000_HALF		0x0010
+#define ADVERTISE_1000_FULL		0x0020
+#define AUTONEG_ADVERTISE_10_100_ALL	0x000F	/* All 10/100 speeds */
+#define AUTONEG_ADVERTISE_10_ALL	0x0003	/* 10Mbps Full & Half speeds */
+
+#define PHY_AUTO_NEG_TIME		45	/* 4.5 Seconds */
+#define PHY_FORCE_TIME			20	/* 2.0 Seconds */
+
+/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA */
+#define EEPROM_SUM			0xBABA
+#define NODE_ADDRESS_SIZE		6
+
+struct atlx_spi_flash_dev {
+	const char *manu_name;	/* manufacturer id */
+	/* op-code */
+	u8 cmd_wrsr;
+	u8 cmd_read;
+	u8 cmd_program;
+	u8 cmd_wren;
+	u8 cmd_wrdi;
+	u8 cmd_rdsr;
+	u8 cmd_rdid;
+	u8 cmd_sector_erase;
+	u8 cmd_chip_erase;
+};
+
+#endif /* ATLX_H */
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index d0bf206..d981134 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -36,6 +36,9 @@
 #include "ixgbe_type.h"
 #include "ixgbe_common.h"
 
+#ifdef CONFIG_DCA
+#include <linux/dca.h>
+#endif
 
 #define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)
 
@@ -120,7 +123,6 @@
 };
 
 struct ixgbe_ring {
-	struct ixgbe_adapter *adapter;	/* backlink */
 	void *desc;			/* descriptor ring memory */
 	dma_addr_t dma;			/* phys. address of descriptor ring */
 	unsigned int size;		/* length in bytes */
@@ -128,6 +130,7 @@
 	unsigned int next_to_use;
 	unsigned int next_to_clean;
 
+	int queue_index; /* needed for multiqueue queue management */
 	union {
 		struct ixgbe_tx_buffer *tx_buffer_info;
 		struct ixgbe_rx_buffer *rx_buffer_info;
@@ -136,8 +139,21 @@
 	u16 head;
 	u16 tail;
 
+	unsigned int total_bytes;
+	unsigned int total_packets;
 
+	u16 reg_idx; /* holds the special value that gets the hardware register
+		      * offset associated with this ring, which is different
+		      * for DCE and RSS modes */
+
+#ifdef CONFIG_DCA
+	/* cpu for tx queue */
+	int cpu;
+#endif
 	struct ixgbe_queue_stats stats;
+	u8 v_idx; /* maps directly to the index for this ring in the hardware
+		   * vector array, can also be used for finding the bit in EICR
+		   * and friends that represents the vector for this ring */
 
 	u32 eims_value;
 	u16 itr_register;
@@ -146,6 +162,33 @@
 	u16 work_limit;                /* max work per interrupt */
 };
 
+#define RING_F_VMDQ 1
+#define RING_F_RSS  2
+#define IXGBE_MAX_RSS_INDICES  16
+#define IXGBE_MAX_VMDQ_INDICES 16
+struct ixgbe_ring_feature {
+	int indices;
+	int mask;
+};
+
+#define MAX_RX_QUEUES 64
+#define MAX_TX_QUEUES 32
+
+/* MAX_MSIX_Q_VECTORS of these are allocated,
+ * but we only use one per queue-specific vector.
+ */
+struct ixgbe_q_vector {
+	struct ixgbe_adapter *adapter;
+	struct napi_struct napi;
+	DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
+	DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
+	u8 rxr_count;     /* Rx ring count assigned to this vector */
+	u8 txr_count;     /* Tx ring count assigned to this vector */
+	u8 tx_eitr;
+	u8 rx_eitr;
+	u32 eitr;
+};
+
 /* Helper macros to switch between ints/sec and what the register uses.
  * And yes, it's the same math going both ways.
  */
@@ -166,6 +209,14 @@
 
 #define IXGBE_MAX_JUMBO_FRAME_SIZE        16128
 
+#define OTHER_VECTOR 1
+#define NON_Q_VECTORS (OTHER_VECTOR)
+
+#define MAX_MSIX_Q_VECTORS 16
+#define MIN_MSIX_Q_VECTORS 2
+#define MAX_MSIX_COUNT (MAX_MSIX_Q_VECTORS + NON_Q_VECTORS)
+#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS)
+
 /* board specific private data structure */
 struct ixgbe_adapter {
 	struct timer_list watchdog_timer;
@@ -173,10 +224,16 @@
 	u16 bd_number;
 	u16 rx_buf_len;
 	struct work_struct reset_task;
+	struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
+	char name[MAX_MSIX_COUNT][IFNAMSIZ + 5];
+
+	/* Interrupt Throttle Rate */
+	u32 itr_setting;
+	u16 eitr_low;
+	u16 eitr_high;
 
 	/* TX */
 	struct ixgbe_ring *tx_ring;	/* One per active queue */
-	struct napi_struct napi;
 	u64 restart_queue;
 	u64 lsc_int;
 	u64 hw_tso_ctxt;
@@ -192,22 +249,27 @@
 	u64 non_eop_descs;
 	int num_tx_queues;
 	int num_rx_queues;
+	int num_msix_vectors;
+	struct ixgbe_ring_feature ring_feature[3];
 	struct msix_entry *msix_entries;
 
 	u64 rx_hdr_split;
 	u32 alloc_rx_page_failed;
 	u32 alloc_rx_buff_failed;
 
+	/* Some features need tri-state capability,
+	 * thus the additional *_CAPABLE flags.
+	 */
 	u32 flags;
-#define IXGBE_FLAG_RX_CSUM_ENABLED              (u32)(1)
+#define IXGBE_FLAG_RX_CSUM_ENABLED              (u32)(1 << 0)
 #define IXGBE_FLAG_MSI_ENABLED                  (u32)(1 << 1)
-#define IXGBE_FLAG_MSIX_ENABLED			(u32)(1 << 2)
-#define IXGBE_FLAG_RX_PS_ENABLED		(u32)(1 << 3)
-#define IXGBE_FLAG_IN_NETPOLL			(u32)(1 << 4)
-
-	/* Interrupt Throttle Rate */
-	u32 rx_eitr;
-	u32 tx_eitr;
+#define IXGBE_FLAG_MSIX_ENABLED                 (u32)(1 << 2)
+#define IXGBE_FLAG_RX_PS_ENABLED                (u32)(1 << 3)
+#define IXGBE_FLAG_IN_NETPOLL                   (u32)(1 << 4)
+#define IXGBE_FLAG_IMIR_ENABLED                 (u32)(1 << 5)
+#define IXGBE_FLAG_RSS_ENABLED                  (u32)(1 << 6)
+#define IXGBE_FLAG_VMDQ_ENABLED                 (u32)(1 << 7)
+#define IXGBE_FLAG_DCA_ENABLED                  (u32)(1 << 8)
 
 	/* OS defined structs */
 	struct net_device *netdev;
@@ -218,7 +280,10 @@
 	struct ixgbe_hw hw;
 	u16 msg_enable;
 	struct ixgbe_hw_stats stats;
-	char lsc_name[IFNAMSIZ + 5];
+
+	/* Interrupt Throttle Rate */
+	u32 rx_eitr;
+	u32 tx_eitr;
 
 	unsigned long state;
 	u64 tx_busy;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index a119cbd..4e46377 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -246,13 +246,26 @@
 
 static int ixgbe_set_tso(struct net_device *netdev, u32 data)
 {
-
 	if (data) {
 		netdev->features |= NETIF_F_TSO;
 		netdev->features |= NETIF_F_TSO6;
 	} else {
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+		struct ixgbe_adapter *adapter = netdev_priv(netdev);
+		int i;
+#endif
+		netif_stop_queue(netdev);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			netif_stop_subqueue(netdev, i);
+#endif
 		netdev->features &= ~NETIF_F_TSO;
 		netdev->features &= ~NETIF_F_TSO6;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			netif_start_subqueue(netdev, i);
+#endif
+		netif_start_queue(netdev);
 	}
 	return 0;
 }
@@ -873,13 +886,13 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	if (adapter->rx_eitr == 0)
-		ec->rx_coalesce_usecs = 0;
+	if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
+		ec->rx_coalesce_usecs = adapter->rx_eitr;
 	else
 		ec->rx_coalesce_usecs = 1000000 / adapter->rx_eitr;
 
-	if (adapter->tx_eitr == 0)
-		ec->tx_coalesce_usecs = 0;
+	if (adapter->tx_eitr < IXGBE_MIN_ITR_USECS)
+		ec->tx_coalesce_usecs = adapter->tx_eitr;
 	else
 		ec->tx_coalesce_usecs = 1000000 / adapter->tx_eitr;
 
@@ -893,22 +906,26 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
 	if ((ec->rx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
-	    ((ec->rx_coalesce_usecs > 0) &&
+	    ((ec->rx_coalesce_usecs != 0) &&
+	     (ec->rx_coalesce_usecs != 1) &&
+	     (ec->rx_coalesce_usecs != 3) &&
 	     (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
 		return -EINVAL;
 	if ((ec->tx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
-	    ((ec->tx_coalesce_usecs > 0) &&
+	    ((ec->tx_coalesce_usecs != 0) &&
+	     (ec->tx_coalesce_usecs != 1) &&
+	     (ec->tx_coalesce_usecs != 3) &&
 	     (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
 		return -EINVAL;
 
 	/* convert to rate of irq's per second */
-	if (ec->rx_coalesce_usecs == 0)
-		adapter->rx_eitr = 0;
+	if (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
+		adapter->rx_eitr = ec->rx_coalesce_usecs;
 	else
 		adapter->rx_eitr = (1000000 / ec->rx_coalesce_usecs);
 
-	if (ec->tx_coalesce_usecs == 0)
-		adapter->tx_eitr = 0;
+	if (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
+		adapter->tx_eitr = ec->rx_coalesce_usecs;
 	else
 		adapter->tx_eitr = (1000000 / ec->tx_coalesce_usecs);
 
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index c2095ce..7ad2993 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -48,7 +48,7 @@
 static const char ixgbe_driver_string[] =
 	"Intel(R) 10 Gigabit PCI Express Network Driver";
 
-#define DRV_VERSION "1.1.18"
+#define DRV_VERSION "1.3.18-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
 	 "Copyright (c) 1999-2007 Intel Corporation.";
@@ -80,6 +80,16 @@
 };
 MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
 
+#ifdef CONFIG_DCA
+static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
+			    void *p);
+static struct notifier_block dca_notifier = {
+	.notifier_call = ixgbe_notify_dca,
+	.next          = NULL,
+	.priority      = 0
+};
+#endif
+
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
 MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
 MODULE_LICENSE("GPL");
@@ -256,26 +266,125 @@
 		 * sees the new next_to_clean.
 		 */
 		smp_mb();
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+		if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
+		    !test_bit(__IXGBE_DOWN, &adapter->state)) {
+			netif_wake_subqueue(netdev, tx_ring->queue_index);
+			adapter->restart_queue++;
+		}
+#else
 		if (netif_queue_stopped(netdev) &&
 		    !test_bit(__IXGBE_DOWN, &adapter->state)) {
 			netif_wake_queue(netdev);
 			adapter->restart_queue++;
 		}
+#endif
 	}
 
 	if (adapter->detect_tx_hung)
 		if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc))
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+			netif_stop_subqueue(netdev, tx_ring->queue_index);
+#else
 			netif_stop_queue(netdev);
+#endif
 
 	if (total_tx_packets >= tx_ring->work_limit)
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value);
 
+	tx_ring->total_bytes += total_tx_bytes;
+	tx_ring->total_packets += total_tx_packets;
 	adapter->net_stats.tx_bytes += total_tx_bytes;
 	adapter->net_stats.tx_packets += total_tx_packets;
 	cleaned = total_tx_packets ? true : false;
 	return cleaned;
 }
 
+#ifdef CONFIG_DCA
+static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
+				struct ixgbe_ring *rxr)
+{
+	u32 rxctrl;
+	int cpu = get_cpu();
+	int q = rxr - adapter->rx_ring;
+
+	if (rxr->cpu != cpu) {
+		rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q));
+		rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
+		rxctrl |= dca_get_tag(cpu);
+		rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
+		rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
+		rxr->cpu = cpu;
+	}
+	put_cpu();
+}
+
+static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
+				struct ixgbe_ring *txr)
+{
+	u32 txctrl;
+	int cpu = get_cpu();
+	int q = txr - adapter->tx_ring;
+
+	if (txr->cpu != cpu) {
+		txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q));
+		txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
+		txctrl |= dca_get_tag(cpu);
+		txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl);
+		txr->cpu = cpu;
+	}
+	put_cpu();
+}
+
+static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
+{
+	int i;
+
+	if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
+		return;
+
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		adapter->tx_ring[i].cpu = -1;
+		ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]);
+	}
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		adapter->rx_ring[i].cpu = -1;
+		ixgbe_update_rx_dca(adapter, &adapter->rx_ring[i]);
+	}
+}
+
+static int __ixgbe_notify_dca(struct device *dev, void *data)
+{
+	struct net_device *netdev = dev_get_drvdata(dev);
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	unsigned long event = *(unsigned long *)data;
+
+	switch (event) {
+	case DCA_PROVIDER_ADD:
+		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
+		/* Always use CB2 mode, difference is masked
+		 * in the CB driver. */
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
+		if (dca_add_requester(dev) == IXGBE_SUCCESS) {
+			ixgbe_setup_dca(adapter);
+			break;
+		}
+		/* Fall Through since DCA is disabled. */
+	case DCA_PROVIDER_REMOVE:
+		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
+			dca_remove_requester(dev);
+			adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
+		}
+		break;
+	}
+
+	return IXGBE_SUCCESS;
+}
+
+#endif /* CONFIG_DCA */
 /**
  * ixgbe_receive_skb - Send a completed packet up the stack
  * @adapter: board private structure
@@ -556,10 +665,15 @@
 	adapter->net_stats.rx_bytes += total_rx_bytes;
 	adapter->net_stats.rx_packets += total_rx_packets;
 
+	rx_ring->total_packets += total_rx_packets;
+	rx_ring->total_bytes += total_rx_bytes;
+	adapter->net_stats.rx_bytes += total_rx_bytes;
+	adapter->net_stats.rx_packets += total_rx_packets;
+
 	return cleaned;
 }
 
-#define IXGBE_MAX_INTR 10
+static int ixgbe_clean_rxonly(struct napi_struct *, int);
 /**
  * ixgbe_configure_msix - Configure MSI-X hardware
  * @adapter: board private structure
@@ -569,28 +683,195 @@
  **/
 static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 {
-	int i, vector = 0;
+	struct ixgbe_q_vector *q_vector;
+	int i, j, q_vectors, v_idx, r_idx;
+	u32 mask;
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i),
-			       IXGBE_MSIX_VECTOR(vector));
-		writel(EITR_INTS_PER_SEC_TO_REG(adapter->tx_eitr),
-		       adapter->hw.hw_addr + adapter->tx_ring[i].itr_register);
-		vector++;
+	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
+	/* Populate the IVAR table and set the ITR values to the
+	 * corresponding register.
+	 */
+	for (v_idx = 0; v_idx < q_vectors; v_idx++) {
+		q_vector = &adapter->q_vector[v_idx];
+		/* XXX for_each_bit(...) */
+		r_idx = find_first_bit(q_vector->rxr_idx,
+				      adapter->num_rx_queues);
+
+		for (i = 0; i < q_vector->rxr_count; i++) {
+			j = adapter->rx_ring[r_idx].reg_idx;
+			ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(j), v_idx);
+			r_idx = find_next_bit(q_vector->rxr_idx,
+					      adapter->num_rx_queues,
+					      r_idx + 1);
+		}
+		r_idx = find_first_bit(q_vector->txr_idx,
+				       adapter->num_tx_queues);
+
+		for (i = 0; i < q_vector->txr_count; i++) {
+			j = adapter->tx_ring[r_idx].reg_idx;
+			ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(j), v_idx);
+			r_idx = find_next_bit(q_vector->txr_idx,
+					      adapter->num_tx_queues,
+					      r_idx + 1);
+		}
+
+		/* if this is a tx only vector use half the irq (tx) rate */
+		if (q_vector->txr_count && !q_vector->rxr_count)
+			q_vector->eitr = adapter->tx_eitr;
+		else
+			/* rx only or mixed */
+			q_vector->eitr = adapter->rx_eitr;
+
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx),
+				EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
 	}
 
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(i),
-			       IXGBE_MSIX_VECTOR(vector));
-		writel(EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr),
-		       adapter->hw.hw_addr + adapter->rx_ring[i].itr_register);
-		vector++;
+	ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950);
+
+	/* set up to autoclear timer, lsc, and the vectors */
+	mask = IXGBE_EIMS_ENABLE_MASK;
+	mask &= ~IXGBE_EIMS_OTHER;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask);
+}
+
+enum latency_range {
+	lowest_latency = 0,
+	low_latency = 1,
+	bulk_latency = 2,
+	latency_invalid = 255
+};
+
+/**
+ * ixgbe_update_itr - update the dynamic ITR value based on statistics
+ * @adapter: pointer to adapter
+ * @eitr: eitr setting (ints per sec) to give last timeslice
+ * @itr_setting: current throttle rate in ints/second
+ * @packets: the number of packets during this measurement interval
+ * @bytes: the number of bytes during this measurement interval
+ *
+ *      Stores a new ITR value based on packets and byte
+ *      counts during the last interrupt.  The advantage of per interrupt
+ *      computation is faster updates and more accurate ITR for the current
+ *      traffic pattern.  Constants in this function were computed
+ *      based on theoretical maximum wire speed and thresholds were set based
+ *      on testing data as well as attempting to minimize response time
+ *      while increasing bulk throughput.
+ *      this functionality is controlled by the InterruptThrottleRate module
+ *      parameter (see ixgbe_param.c)
+ **/
+static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
+			   u32 eitr, u8 itr_setting,
+			   int packets, int bytes)
+{
+	unsigned int retval = itr_setting;
+	u32 timepassed_us;
+	u64 bytes_perint;
+
+	if (packets == 0)
+		goto update_itr_done;
+
+
+	/* simple throttlerate management
+	 *    0-20MB/s lowest (100000 ints/s)
+	 *   20-100MB/s low   (20000 ints/s)
+	 *  100-1249MB/s bulk (8000 ints/s)
+	 */
+	/* what was last interrupt timeslice? */
+	timepassed_us = 1000000/eitr;
+	bytes_perint = bytes / timepassed_us; /* bytes/usec */
+
+	switch (itr_setting) {
+	case lowest_latency:
+		if (bytes_perint > adapter->eitr_low)
+			retval = low_latency;
+		break;
+	case low_latency:
+		if (bytes_perint > adapter->eitr_high)
+			retval = bulk_latency;
+		else if (bytes_perint <= adapter->eitr_low)
+			retval = lowest_latency;
+		break;
+	case bulk_latency:
+		if (bytes_perint <= adapter->eitr_high)
+			retval = low_latency;
+		break;
 	}
 
-	vector = adapter->num_tx_queues + adapter->num_rx_queues;
-	ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX,
-		       IXGBE_MSIX_VECTOR(vector));
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(vector), 1950);
+update_itr_done:
+	return retval;
+}
+
+static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
+{
+	struct ixgbe_adapter *adapter = q_vector->adapter;
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 new_itr;
+	u8 current_itr, ret_itr;
+	int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) /
+			      sizeof(struct ixgbe_q_vector);
+	struct ixgbe_ring *rx_ring, *tx_ring;
+
+	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->txr_count; i++) {
+		tx_ring = &(adapter->tx_ring[r_idx]);
+		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
+					   q_vector->tx_eitr,
+					   tx_ring->total_packets,
+					   tx_ring->total_bytes);
+		/* if the result for this queue would decrease interrupt
+		 * rate for this vector then use that result */
+		q_vector->tx_eitr = ((q_vector->tx_eitr > ret_itr) ?
+				    q_vector->tx_eitr - 1 : ret_itr);
+		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+				      r_idx + 1);
+	}
+
+	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	for (i = 0; i < q_vector->rxr_count; i++) {
+		rx_ring = &(adapter->rx_ring[r_idx]);
+		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
+					   q_vector->rx_eitr,
+					   rx_ring->total_packets,
+					   rx_ring->total_bytes);
+		/* if the result for this queue would decrease interrupt
+		 * rate for this vector then use that result */
+		q_vector->rx_eitr = ((q_vector->rx_eitr > ret_itr) ?
+				    q_vector->rx_eitr - 1 : ret_itr);
+		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+				      r_idx + 1);
+	}
+
+	current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
+
+	switch (current_itr) {
+	/* counts and packets in update_itr are dependent on these numbers */
+	case lowest_latency:
+		new_itr = 100000;
+		break;
+	case low_latency:
+		new_itr = 20000; /* aka hwitr = ~200 */
+		break;
+	case bulk_latency:
+	default:
+		new_itr = 8000;
+		break;
+	}
+
+	if (new_itr != q_vector->eitr) {
+		u32 itr_reg;
+		/* do an exponential smoothing */
+		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
+		q_vector->eitr = new_itr;
+		itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
+		/* must write high and low 16 bits to reset counter */
+		DPRINTK(TX_ERR, DEBUG, "writing eitr(%d): %08X\n", v_idx,
+			itr_reg);
+		IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg | (itr_reg)<<16);
+	}
+
+	return;
 }
 
 static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
@@ -614,153 +895,302 @@
 
 static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
 {
-	struct ixgbe_ring *txr = data;
-	struct ixgbe_adapter *adapter = txr->adapter;
+	struct ixgbe_q_vector *q_vector = data;
+	struct ixgbe_adapter  *adapter = q_vector->adapter;
+	struct ixgbe_ring     *txr;
+	int i, r_idx;
 
-	ixgbe_clean_tx_irq(adapter, txr);
+	if (!q_vector->txr_count)
+		return IRQ_HANDLED;
+
+	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->txr_count; i++) {
+		txr = &(adapter->tx_ring[r_idx]);
+#ifdef CONFIG_DCA
+		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+			ixgbe_update_tx_dca(adapter, txr);
+#endif
+		txr->total_bytes = 0;
+		txr->total_packets = 0;
+		ixgbe_clean_tx_irq(adapter, txr);
+		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+				      r_idx + 1);
+	}
 
 	return IRQ_HANDLED;
 }
 
+/**
+ * ixgbe_msix_clean_rx - single unshared vector rx clean (all queues)
+ * @irq: unused
+ * @data: pointer to our q_vector struct for this interrupt vector
+ **/
 static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
 {
-	struct ixgbe_ring *rxr = data;
-	struct ixgbe_adapter *adapter = rxr->adapter;
+	struct ixgbe_q_vector *q_vector = data;
+	struct ixgbe_adapter  *adapter = q_vector->adapter;
+	struct ixgbe_ring  *rxr;
+	int r_idx;
 
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims_value);
-	netif_rx_schedule(adapter->netdev, &adapter->napi);
+	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	if (!q_vector->rxr_count)
+		return IRQ_HANDLED;
+
+	rxr = &(adapter->rx_ring[r_idx]);
+	/* disable interrupts on this vector only */
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->v_idx);
+	rxr->total_bytes = 0;
+	rxr->total_packets = 0;
+	netif_rx_schedule(adapter->netdev, &q_vector->napi);
+
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
+{
+	ixgbe_msix_clean_rx(irq, data);
+	ixgbe_msix_clean_tx(irq, data);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * ixgbe_clean_rxonly - msix (aka one shot) rx clean routine
+ * @napi: napi struct with our devices info in it
+ * @budget: amount of work driver is allowed to do this pass, in packets
+ *
+ **/
 static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
 {
-	struct ixgbe_adapter *adapter = container_of(napi,
-					struct ixgbe_adapter, napi);
-	struct net_device *netdev = adapter->netdev;
+	struct ixgbe_q_vector *q_vector =
+			       container_of(napi, struct ixgbe_q_vector, napi);
+	struct ixgbe_adapter *adapter = q_vector->adapter;
+	struct ixgbe_ring *rxr;
 	int work_done = 0;
-	struct ixgbe_ring *rxr = adapter->rx_ring;
+	long r_idx;
 
-	/* Keep link state information with original netdev */
-	if (!netif_carrier_ok(netdev))
-		goto quit_polling;
+	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	rxr = &(adapter->rx_ring[r_idx]);
+#ifdef CONFIG_DCA
+	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+		ixgbe_update_rx_dca(adapter, rxr);
+#endif
 
 	ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);
 
-	/* If no Tx and not enough Rx work done, exit the polling mode */
-	if ((work_done < budget) || !netif_running(netdev)) {
-quit_polling:
-		netif_rx_complete(netdev, napi);
+	/* If all Rx work done, exit the polling mode */
+	if (work_done < budget) {
+		netif_rx_complete(adapter->netdev, napi);
+		if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
+			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
-			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
-					rxr->eims_value);
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rxr->v_idx);
 	}
 
 	return work_done;
 }
 
-/**
- * ixgbe_setup_msix - Initialize MSI-X interrupts
- *
- * ixgbe_setup_msix allocates MSI-X vectors and requests
- * interrutps from the kernel.
- **/
-static int ixgbe_setup_msix(struct ixgbe_adapter *adapter)
+static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
+				     int r_idx)
 {
-	struct net_device *netdev = adapter->netdev;
-	int i, int_vector = 0, err = 0;
-	int max_msix_count;
+	a->q_vector[v_idx].adapter = a;
+	set_bit(r_idx, a->q_vector[v_idx].rxr_idx);
+	a->q_vector[v_idx].rxr_count++;
+	a->rx_ring[r_idx].v_idx = 1 << v_idx;
+}
 
-	/* +1 for the LSC interrupt */
-	max_msix_count = adapter->num_rx_queues + adapter->num_tx_queues + 1;
-	adapter->msix_entries = kcalloc(max_msix_count,
-					sizeof(struct msix_entry), GFP_KERNEL);
-	if (!adapter->msix_entries)
-		return -ENOMEM;
+static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
+				     int r_idx)
+{
+	a->q_vector[v_idx].adapter = a;
+	set_bit(r_idx, a->q_vector[v_idx].txr_idx);
+	a->q_vector[v_idx].txr_count++;
+	a->tx_ring[r_idx].v_idx = 1 << v_idx;
+}
 
-	for (i = 0; i < max_msix_count; i++)
-		adapter->msix_entries[i].entry = i;
+/**
+ * ixgbe_map_rings_to_vectors - Maps descriptor rings to vectors
+ * @adapter: board private structure to initialize
+ * @vectors: allotted vector count for descriptor rings
+ *
+ * This function maps descriptor rings to the queue-specific vectors
+ * we were allotted through the MSI-X enabling code.  Ideally, we'd have
+ * one vector per ring/queue, but on a constrained vector budget, we
+ * group the rings as "efficiently" as possible.  You would add new
+ * mapping configurations in here.
+ **/
+static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter,
+				      int vectors)
+{
+	int v_start = 0;
+	int rxr_idx = 0, txr_idx = 0;
+	int rxr_remaining = adapter->num_rx_queues;
+	int txr_remaining = adapter->num_tx_queues;
+	int i, j;
+	int rqpv, tqpv;
+	int err = 0;
 
-	err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
-			      max_msix_count);
-	if (err)
+	/* No mapping required if MSI-X is disabled. */
+	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
 		goto out;
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		sprintf(adapter->tx_ring[i].name, "%s-tx%d", netdev->name, i);
-		err = request_irq(adapter->msix_entries[int_vector].vector,
-				  &ixgbe_msix_clean_tx,
-				  0,
-				  adapter->tx_ring[i].name,
-				  &(adapter->tx_ring[i]));
-		if (err) {
-			DPRINTK(PROBE, ERR,
-				"request_irq failed for MSIX interrupt "
-				"Error: %d\n", err);
-			goto release_irqs;
+	/*
+	 * The ideal configuration...
+	 * We have enough vectors to map one per queue.
+	 */
+	if (vectors == adapter->num_rx_queues + adapter->num_tx_queues) {
+		for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++)
+			map_vector_to_rxq(adapter, v_start, rxr_idx);
+
+		for (; txr_idx < txr_remaining; v_start++, txr_idx++)
+			map_vector_to_txq(adapter, v_start, txr_idx);
+
+		goto out;
+	}
+
+	/*
+	 * If we don't have enough vectors for a 1-to-1
+	 * mapping, we'll have to group them so there are
+	 * multiple queues per vector.
+	 */
+	/* Re-adjusting *qpv takes care of the remainder. */
+	for (i = v_start; i < vectors; i++) {
+		rqpv = DIV_ROUND_UP(rxr_remaining, vectors - i);
+		for (j = 0; j < rqpv; j++) {
+			map_vector_to_rxq(adapter, i, rxr_idx);
+			rxr_idx++;
+			rxr_remaining--;
 		}
-		adapter->tx_ring[i].eims_value =
-		    (1 << IXGBE_MSIX_VECTOR(int_vector));
-		adapter->tx_ring[i].itr_register = IXGBE_EITR(int_vector);
-		int_vector++;
 	}
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		if (strlen(netdev->name) < (IFNAMSIZ - 5))
-			sprintf(adapter->rx_ring[i].name,
-				"%s-rx%d", netdev->name, i);
-		else
-			memcpy(adapter->rx_ring[i].name,
-			       netdev->name, IFNAMSIZ);
-		err = request_irq(adapter->msix_entries[int_vector].vector,
-				  &ixgbe_msix_clean_rx, 0,
-				  adapter->rx_ring[i].name,
-				  &(adapter->rx_ring[i]));
-		if (err) {
-			DPRINTK(PROBE, ERR,
-				"request_irq failed for MSIX interrupt "
-				"Error: %d\n", err);
-			goto release_irqs;
+	for (i = v_start; i < vectors; i++) {
+		tqpv = DIV_ROUND_UP(txr_remaining, vectors - i);
+		for (j = 0; j < tqpv; j++) {
+			map_vector_to_txq(adapter, i, txr_idx);
+			txr_idx++;
+			txr_remaining--;
 		}
-
-		adapter->rx_ring[i].eims_value =
-		    (1 << IXGBE_MSIX_VECTOR(int_vector));
-		adapter->rx_ring[i].itr_register = IXGBE_EITR(int_vector);
-		int_vector++;
 	}
 
-	sprintf(adapter->lsc_name, "%s-lsc", netdev->name);
-	err = request_irq(adapter->msix_entries[int_vector].vector,
-			  &ixgbe_msix_lsc, 0, adapter->lsc_name, netdev);
-	if (err) {
-		DPRINTK(PROBE, ERR,
-			"request_irq for msix_lsc failed: %d\n", err);
-		goto release_irqs;
-	}
-
-	/* FIXME: implement netif_napi_remove() instead */
-	adapter->napi.poll = ixgbe_clean_rxonly;
-	adapter->flags |= IXGBE_FLAG_MSIX_ENABLED;
-	return 0;
-
-release_irqs:
-	int_vector--;
-	for (; int_vector >= adapter->num_tx_queues; int_vector--)
-		free_irq(adapter->msix_entries[int_vector].vector,
-			 &(adapter->rx_ring[int_vector -
-					    adapter->num_tx_queues]));
-
-	for (; int_vector >= 0; int_vector--)
-		free_irq(adapter->msix_entries[int_vector].vector,
-			 &(adapter->tx_ring[int_vector]));
 out:
-	kfree(adapter->msix_entries);
-	adapter->msix_entries = NULL;
-	adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
 	return err;
 }
 
 /**
- * ixgbe_intr - Interrupt Handler
+ * ixgbe_request_msix_irqs - Initialize MSI-X interrupts
+ * @adapter: board private structure
+ *
+ * ixgbe_request_msix_irqs allocates MSI-X vectors and requests
+ * interrupts from the kernel.
+ **/
+static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	irqreturn_t (*handler)(int, void *);
+	int i, vector, q_vectors, err;
+
+	/* Decrement for Other and TCP Timer vectors */
+	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
+	/* Map the Tx/Rx rings to the vectors we were allotted. */
+	err = ixgbe_map_rings_to_vectors(adapter, q_vectors);
+	if (err)
+		goto out;
+
+#define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
+			 (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
+			 &ixgbe_msix_clean_many)
+	for (vector = 0; vector < q_vectors; vector++) {
+		handler = SET_HANDLER(&adapter->q_vector[vector]);
+		sprintf(adapter->name[vector], "%s:v%d-%s",
+			netdev->name, vector,
+			(handler == &ixgbe_msix_clean_rx) ? "Rx" :
+			 ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx"));
+		err = request_irq(adapter->msix_entries[vector].vector,
+				  handler, 0, adapter->name[vector],
+				  &(adapter->q_vector[vector]));
+		if (err) {
+			DPRINTK(PROBE, ERR,
+				"request_irq failed for MSIX interrupt "
+				"Error: %d\n", err);
+			goto free_queue_irqs;
+		}
+	}
+
+	sprintf(adapter->name[vector], "%s:lsc", netdev->name);
+	err = request_irq(adapter->msix_entries[vector].vector,
+			  &ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
+	if (err) {
+		DPRINTK(PROBE, ERR,
+			"request_irq for msix_lsc failed: %d\n", err);
+		goto free_queue_irqs;
+	}
+
+	return 0;
+
+free_queue_irqs:
+	for (i = vector - 1; i >= 0; i--)
+		free_irq(adapter->msix_entries[--vector].vector,
+			 &(adapter->q_vector[i]));
+	adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
+	pci_disable_msix(adapter->pdev);
+	kfree(adapter->msix_entries);
+	adapter->msix_entries = NULL;
+out:
+	return err;
+}
+
+static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_q_vector *q_vector = adapter->q_vector;
+	u8 current_itr;
+	u32 new_itr = q_vector->eitr;
+	struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
+	struct ixgbe_ring *tx_ring = &adapter->tx_ring[0];
+
+	q_vector->tx_eitr = ixgbe_update_itr(adapter, new_itr,
+					     q_vector->tx_eitr,
+					     tx_ring->total_packets,
+					     tx_ring->total_bytes);
+	q_vector->rx_eitr = ixgbe_update_itr(adapter, new_itr,
+					     q_vector->rx_eitr,
+					     rx_ring->total_packets,
+					     rx_ring->total_bytes);
+
+	current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
+
+	switch (current_itr) {
+	/* counts and packets in update_itr are dependent on these numbers */
+	case lowest_latency:
+		new_itr = 100000;
+		break;
+	case low_latency:
+		new_itr = 20000; /* aka hwitr = ~200 */
+		break;
+	case bulk_latency:
+		new_itr = 8000;
+		break;
+	default:
+		break;
+	}
+
+	if (new_itr != q_vector->eitr) {
+		u32 itr_reg;
+		/* do an exponential smoothing */
+		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
+		q_vector->eitr = new_itr;
+		itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
+		/* must write high and low 16 bits to reset counter */
+		IXGBE_WRITE_REG(hw, IXGBE_EITR(0), itr_reg | (itr_reg)<<16);
+	}
+
+	return;
+}
+
+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter);
+
+/**
+ * ixgbe_intr - legacy mode Interrupt Handler
  * @irq: interrupt number
  * @data: pointer to a network interface device structure
  * @pt_regs: CPU registers structure
@@ -772,8 +1202,10 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 eicr;
 
-	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
 
+	/* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read
+	 * therefore no explict interrupt disable is necessary */
+	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
 	if (!eicr)
 		return IRQ_NONE;	/* Not our interrupt */
 
@@ -782,16 +1214,33 @@
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			mod_timer(&adapter->watchdog_timer, jiffies);
 	}
-	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
-		/* Disable interrupts and register for poll. The flush of the
-		 * posted write is intentionally left out. */
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
-		__netif_rx_schedule(netdev, &adapter->napi);
+
+
+	if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) {
+		adapter->tx_ring[0].total_packets = 0;
+		adapter->tx_ring[0].total_bytes = 0;
+		adapter->rx_ring[0].total_packets = 0;
+		adapter->rx_ring[0].total_bytes = 0;
+		/* would disable interrupts here but EIAM disabled it */
+		__netif_rx_schedule(netdev, &adapter->q_vector[0].napi);
 	}
 
 	return IRQ_HANDLED;
 }
 
+static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
+{
+	int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
+	for (i = 0; i < q_vectors; i++) {
+		struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
+		bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES);
+		bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES);
+		q_vector->rxr_count = 0;
+		q_vector->txr_count = 0;
+	}
+}
+
 /**
  * ixgbe_request_irq - initialize interrupts
  * @adapter: board private structure
@@ -799,40 +1248,24 @@
  * Attempts to configure interrupts using the best available
  * capabilities of the hardware and kernel.
  **/
-static int ixgbe_request_irq(struct ixgbe_adapter *adapter, u32 *num_rx_queues)
+static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	int flags, err;
-	irq_handler_t handler = ixgbe_intr;
+	int err;
 
-	flags = IRQF_SHARED;
-
-	err = ixgbe_setup_msix(adapter);
-	if (!err)
-		goto request_done;
-
-	/*
-	 * if we can't do MSI-X, fall through and try MSI
-	 * No need to reallocate memory since we're decreasing the number of
-	 * queues. We just won't use the other ones, also it is freed correctly
-	 * on ixgbe_remove.
-	 */
-	*num_rx_queues = 1;
-
-	/* do MSI */
-	err = pci_enable_msi(adapter->pdev);
-	if (!err) {
-		adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
-		flags &= ~IRQF_SHARED;
-		handler = &ixgbe_intr;
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		err = ixgbe_request_msix_irqs(adapter);
+	} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+		err = request_irq(adapter->pdev->irq, &ixgbe_intr, 0,
+				  netdev->name, netdev);
+	} else {
+		err = request_irq(adapter->pdev->irq, &ixgbe_intr, IRQF_SHARED,
+				  netdev->name, netdev);
 	}
 
-	err = request_irq(adapter->pdev->irq, handler, flags,
-			  netdev->name, netdev);
 	if (err)
 		DPRINTK(PROBE, ERR, "request_irq failed, Error %d\n", err);
 
-request_done:
 	return err;
 }
 
@@ -841,28 +1274,22 @@
 	struct net_device *netdev = adapter->netdev;
 
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
-		int i;
+		int i, q_vectors;
 
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			free_irq(adapter->msix_entries[i].vector,
-				 &(adapter->tx_ring[i]));
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			free_irq(adapter->msix_entries[i +
-						adapter->num_tx_queues].vector,
-				&(adapter->rx_ring[i]));
-		i = adapter->num_rx_queues + adapter->num_tx_queues;
+		q_vectors = adapter->num_msix_vectors;
+
+		i = q_vectors - 1;
 		free_irq(adapter->msix_entries[i].vector, netdev);
-		pci_disable_msix(adapter->pdev);
-		kfree(adapter->msix_entries);
-		adapter->msix_entries = NULL;
-		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
-		return;
-	}
 
-	free_irq(adapter->pdev->irq, netdev);
-	if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
-		pci_disable_msi(adapter->pdev);
-		adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
+		i--;
+		for (; i >= 0; i--) {
+			free_irq(adapter->msix_entries[i].vector,
+				 &(adapter->q_vector[i]));
+		}
+
+		ixgbe_reset_q_vectors(adapter);
+	} else {
+		free_irq(adapter->pdev->irq, netdev);
 	}
 }
 
@@ -874,7 +1301,13 @@
 {
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
 	IXGBE_WRITE_FLUSH(&adapter->hw);
-	synchronize_irq(adapter->pdev->irq);
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		int i;
+		for (i = 0; i < adapter->num_msix_vectors; i++)
+			synchronize_irq(adapter->msix_entries[i].vector);
+	} else {
+		synchronize_irq(adapter->pdev->irq);
+	}
 }
 
 /**
@@ -883,12 +1316,9 @@
  **/
 static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
 {
-	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC,
-				(IXGBE_EIMS_ENABLE_MASK &
-				 ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC)));
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
-			IXGBE_EIMS_ENABLE_MASK);
+	u32 mask;
+	mask = IXGBE_EIMS_ENABLE_MASK;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 }
 
@@ -898,20 +1328,18 @@
  **/
 static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
 {
-	int i;
 	struct ixgbe_hw *hw = &adapter->hw;
 
-	if (adapter->rx_eitr)
-		IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
-				EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));
-
-	/* for re-triggering the interrupt in non-NAPI mode */
-	adapter->rx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));
-	adapter->tx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));
+	IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
+			EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));
 
 	ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0);
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i), i);
+	ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(0), 0);
+
+	map_vector_to_rxq(adapter, 0, 0);
+	map_vector_to_txq(adapter, 0, 0);
+
+	DPRINTK(HW, INFO, "Legacy interrupt IVAR setup done\n");
 }
 
 /**
@@ -924,23 +1352,29 @@
 {
 	u64 tdba;
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 i, tdlen;
+	u32 i, j, tdlen, txctrl;
 
 	/* Setup the HW Tx Head and Tail descriptor pointers */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
+		j = adapter->tx_ring[i].reg_idx;
 		tdba = adapter->tx_ring[i].dma;
 		tdlen = adapter->tx_ring[i].count *
-		    sizeof(union ixgbe_adv_tx_desc);
-		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i), (tdba & DMA_32BIT_MASK));
-		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(i), (tdba >> 32));
-		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i), tdlen);
-		IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);
-		adapter->tx_ring[i].head = IXGBE_TDH(i);
-		adapter->tx_ring[i].tail = IXGBE_TDT(i);
+			sizeof(union ixgbe_adv_tx_desc);
+		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
+				(tdba & DMA_32BIT_MASK));
+		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
+		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen);
+		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
+		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
+		adapter->tx_ring[i].head = IXGBE_TDH(j);
+		adapter->tx_ring[i].tail = IXGBE_TDT(j);
+		/* Disable Tx Head Writeback RO bit, since this hoses
+		 * bookkeeping if things aren't delivered in order.
+		 */
+		txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
+		txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
 	}
-
-	IXGBE_WRITE_REG(hw, IXGBE_TIPG, IXGBE_TIPG_FIBER_DEFAULT);
 }
 
 #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
@@ -959,13 +1393,12 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+	int i, j;
 	u32 rdlen, rxctrl, rxcsum;
 	u32 random[10];
-	u32 reta, mrqc;
-	int i;
 	u32 fctrl, hlreg0;
-	u32 srrctl;
 	u32 pages;
+	u32 reta = 0, mrqc, srrctl;
 
 	/* Decide whether to use packet split mode or not */
 	if (netdev->mtu > ETH_DATA_LEN)
@@ -985,6 +1418,7 @@
 
 	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
 	fctrl |= IXGBE_FCTRL_BAM;
+	fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
 
 	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
@@ -1036,37 +1470,23 @@
 		adapter->rx_ring[i].tail = IXGBE_RDT(i);
 	}
 
-	if (adapter->num_rx_queues > 1) {
-		/* Random 40bytes used as random key in RSS hash function */
-		get_random_bytes(&random[0], 40);
-
-		switch (adapter->num_rx_queues) {
-		case 8:
-		case 4:
-			/* Bits [3:0] in each byte refers the Rx queue no */
-			reta = 0x00010203;
-			break;
-		case 2:
-			reta = 0x00010001;
-			break;
-		default:
-			reta = 0x00000000;
-			break;
-		}
-
+	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
 		/* Fill out redirection table */
-		for (i = 0; i < 32; i++) {
-			IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RETA(0), i, reta);
-			if (adapter->num_rx_queues > 4) {
-				i++;
-				IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RETA(0), i,
-						      0x04050607);
-			}
+		for (i = 0, j = 0; i < 128; i++, j++) {
+			if (j == adapter->ring_feature[RING_F_RSS].indices)
+				j = 0;
+			/* reta = 4-byte sliding window of
+			 * 0x00..(indices-1)(indices-1)00..etc. */
+			reta = (reta << 8) | (j * 0x11);
+			if ((i & 3) == 3)
+				IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
 		}
 
 		/* Fill out hash function seeds */
+		/* XXX use a random constant here to glue certain flows */
+		get_random_bytes(&random[0], 40);
 		for (i = 0; i < 10; i++)
-			IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, random[i]);
+			IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), random[i]);
 
 		mrqc = IXGBE_MRQC_RSSEN
 		    /* Perform hash on these packet types */
@@ -1080,26 +1500,23 @@
 		    | IXGBE_MRQC_RSS_FIELD_IPV6_UDP
 		    | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
 		IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
-
-		/* Multiqueue and packet checksumming are mutually exclusive. */
-		rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
-		rxcsum |= IXGBE_RXCSUM_PCSD;
-		IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
-	} else {
-		/* Enable Receive Checksum Offload for TCP and UDP */
-		rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
-		if (adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) {
-			/* Enable IPv4 payload checksum for UDP fragments
-			 * Must be used in conjunction with packet-split. */
-			rxcsum |= IXGBE_RXCSUM_IPPCSE;
-		} else {
-			/* don't need to clear IPPCSE as it defaults to 0 */
-		}
-		IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
 	}
-	/* Enable Receives */
-	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
-	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+
+	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+
+	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED ||
+	    adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) {
+		/* Disable indicating checksum in descriptor, enables
+		 * RSS hash */
+		rxcsum |= IXGBE_RXCSUM_PCSD;
+	}
+	if (!(rxcsum & IXGBE_RXCSUM_PCSD)) {
+		/* Enable IPv4 payload checksum for UDP fragments
+		 * if PCSD is not set */
+		rxcsum |= IXGBE_RXCSUM_IPPCSE;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
 }
 
 static void ixgbe_vlan_rx_register(struct net_device *netdev,
@@ -1219,6 +1636,42 @@
 
 }
 
+static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
+{
+	int q_idx;
+	struct ixgbe_q_vector *q_vector;
+	int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
+	/* legacy and MSI only use one vector */
+	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
+		q_vectors = 1;
+
+	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+		q_vector = &adapter->q_vector[q_idx];
+		if (!q_vector->rxr_count)
+			continue;
+		napi_enable(&q_vector->napi);
+	}
+}
+
+static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
+{
+	int q_idx;
+	struct ixgbe_q_vector *q_vector;
+	int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
+	/* legacy and MSI only use one vector */
+	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
+		q_vectors = 1;
+
+	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+		q_vector = &adapter->q_vector[q_idx];
+		if (!q_vector->rxr_count)
+			continue;
+		napi_disable(&q_vector->napi);
+	}
+}
+
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -1238,30 +1691,35 @@
 static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	int i;
-	u32 gpie = 0;
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 txdctl, rxdctl, mhadd;
+	int i, j = 0;
 	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+	u32 txdctl, rxdctl, mhadd;
+	u32 gpie;
 
 	ixgbe_get_hw_control(adapter);
 
-	if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED |
-			      IXGBE_FLAG_MSI_ENABLED)) {
+	if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) ||
+	    (adapter->flags & IXGBE_FLAG_MSI_ENABLED)) {
 		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
 			gpie = (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME |
 				IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD);
 		} else {
 			/* MSI only */
-			gpie = (IXGBE_GPIE_EIAME |
-				IXGBE_GPIE_PBA_SUPPORT);
+			gpie = 0;
 		}
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_GPIE, gpie);
-		gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
+		/* XXX: to interrupt immediately for EICS writes, enable this */
+		/* gpie |= IXGBE_GPIE_EIMEN; */
+		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+	}
+
+	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+		/* legacy interrupts, use EIAM to auto-mask when reading EICR,
+		 * specifically only auto mask tx and rx interrupts */
+		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
 	}
 
 	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
-
 	if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
 		mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT;
@@ -1270,15 +1728,21 @@
 	}
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		txdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(i));
+		j = adapter->tx_ring[i].reg_idx;
+		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
 		txdctl |= IXGBE_TXDCTL_ENABLE;
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(i), txdctl);
+		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
 	}
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		rxdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(i));
+		j = adapter->rx_ring[i].reg_idx;
+		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
+		/* enable PTHRESH=32 descriptors (half the internal cache)
+		 * and HTHRESH=0 descriptors (to minimize latency on fetch),
+		 * this also removes a pesky rx_no_buffer_count increment */
+		rxdctl |= 0x0020;
 		rxdctl |= IXGBE_RXDCTL_ENABLE;
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(i), rxdctl);
+		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), rxdctl);
 	}
 	/* enable all receives */
 	rxdctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
@@ -1291,7 +1755,11 @@
 		ixgbe_configure_msi_and_legacy(adapter);
 
 	clear_bit(__IXGBE_DOWN, &adapter->state);
-	napi_enable(&adapter->napi);
+	ixgbe_napi_enable_all(adapter);
+
+	/* clear any pending interrupts, may auto mask */
+	IXGBE_READ_REG(hw, IXGBE_EICR);
+
 	ixgbe_irq_enable(adapter);
 
 	/* bring the link up in the watchdog, this could race with our first
@@ -1333,7 +1801,7 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u32 err, num_rx_queues = adapter->num_rx_queues;
+	u32 err;
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
@@ -1349,7 +1817,7 @@
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	if (netif_running(netdev)) {
-		err = ixgbe_request_irq(adapter, &num_rx_queues);
+		err = ixgbe_request_irq(adapter);
 		if (err)
 			return err;
 	}
@@ -1449,18 +1917,6 @@
 }
 
 /**
- * ixgbe_clean_all_tx_rings - Free Tx Buffers for all queues
- * @adapter: board private structure
- **/
-static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
-{
-	int i;
-
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
-}
-
-/**
  * ixgbe_clean_all_rx_rings - Free Rx Buffers for all queues
  * @adapter: board private structure
  **/
@@ -1472,6 +1928,18 @@
 		ixgbe_clean_rx_ring(adapter, &adapter->rx_ring[i]);
 }
 
+/**
+ * ixgbe_clean_all_tx_rings - Free Tx Buffers for all queues
+ * @adapter: board private structure
+ **/
+static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
+}
+
 void ixgbe_down(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -1493,10 +1961,9 @@
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 	msleep(10);
 
-	napi_disable(&adapter->napi);
-
 	ixgbe_irq_disable(adapter);
 
+	ixgbe_napi_disable_all(adapter);
 	del_timer_sync(&adapter->watchdog_timer);
 
 	netif_carrier_off(netdev);
@@ -1547,27 +2014,37 @@
 }
 
 /**
- * ixgbe_clean - NAPI Rx polling callback
- * @adapter: board private structure
+ * ixgbe_poll - NAPI Rx polling callback
+ * @napi: structure for representing this polling device
+ * @budget: how many packets driver is allowed to clean
+ *
+ * This function is used for legacy and MSI, NAPI mode
  **/
-static int ixgbe_clean(struct napi_struct *napi, int budget)
+static int ixgbe_poll(struct napi_struct *napi, int budget)
 {
-	struct ixgbe_adapter *adapter = container_of(napi,
-					struct ixgbe_adapter, napi);
-	struct net_device *netdev = adapter->netdev;
+	struct ixgbe_q_vector *q_vector = container_of(napi,
+					  struct ixgbe_q_vector, napi);
+	struct ixgbe_adapter *adapter = q_vector->adapter;
 	int tx_cleaned = 0, work_done = 0;
 
-	/* In non-MSIX case, there is no multi-Tx/Rx queue */
+#ifdef CONFIG_DCA
+	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
+		ixgbe_update_tx_dca(adapter, adapter->tx_ring);
+		ixgbe_update_rx_dca(adapter, adapter->rx_ring);
+	}
+#endif
+
 	tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
-	ixgbe_clean_rx_irq(adapter, &adapter->rx_ring[0], &work_done,
-			   budget);
+	ixgbe_clean_rx_irq(adapter, adapter->rx_ring, &work_done, budget);
 
 	if (tx_cleaned)
 		work_done = budget;
 
 	/* If budget not fully consumed, exit the polling mode */
 	if (work_done < budget) {
-		netif_rx_complete(netdev, napi);
+		netif_rx_complete(adapter->netdev, napi);
+		if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
+			ixgbe_set_itr(adapter);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable(adapter);
 	}
@@ -1597,6 +2074,136 @@
 	ixgbe_reinit_locked(adapter);
 }
 
+static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
+				       int vectors)
+{
+	int err, vector_threshold;
+
+	/* We'll want at least 3 (vector_threshold):
+	 * 1) TxQ[0] Cleanup
+	 * 2) RxQ[0] Cleanup
+	 * 3) Other (Link Status Change, etc.)
+	 * 4) TCP Timer (optional)
+	 */
+	vector_threshold = MIN_MSIX_COUNT;
+
+	/* The more we get, the more we will assign to Tx/Rx Cleanup
+	 * for the separate queues...where Rx Cleanup >= Tx Cleanup.
+	 * Right now, we simply care about how many we'll get; we'll
+	 * set them up later while requesting irq's.
+	 */
+	while (vectors >= vector_threshold) {
+		err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
+				      vectors);
+		if (!err) /* Success in acquiring all requested vectors. */
+			break;
+		else if (err < 0)
+			vectors = 0; /* Nasty failure, quit now */
+		else /* err == number of vectors we should try again with */
+			vectors = err;
+	}
+
+	if (vectors < vector_threshold) {
+		/* Can't allocate enough MSI-X interrupts?  Oh well.
+		 * This just means we'll go with either a single MSI
+		 * vector or fall back to legacy interrupts.
+		 */
+		DPRINTK(HW, DEBUG, "Unable to allocate MSI-X interrupts\n");
+		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
+		kfree(adapter->msix_entries);
+		adapter->msix_entries = NULL;
+		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+		adapter->num_tx_queues = 1;
+		adapter->num_rx_queues = 1;
+	} else {
+		adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */
+		adapter->num_msix_vectors = vectors;
+	}
+}
+
+static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
+{
+	int nrq, ntq;
+	int feature_mask = 0, rss_i, rss_m;
+
+	/* Number of supported queues */
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
+		rss_i = adapter->ring_feature[RING_F_RSS].indices;
+		rss_m = 0;
+		feature_mask |= IXGBE_FLAG_RSS_ENABLED;
+
+		switch (adapter->flags & feature_mask) {
+		case (IXGBE_FLAG_RSS_ENABLED):
+			rss_m = 0xF;
+			nrq = rss_i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+			ntq = rss_i;
+#else
+			ntq = 1;
+#endif
+			break;
+		case 0:
+		default:
+			rss_i = 0;
+			rss_m = 0;
+			nrq = 1;
+			ntq = 1;
+			break;
+		}
+
+		adapter->ring_feature[RING_F_RSS].indices = rss_i;
+		adapter->ring_feature[RING_F_RSS].mask = rss_m;
+		break;
+	default:
+		nrq = 1;
+		ntq = 1;
+		break;
+	}
+
+	adapter->num_rx_queues = nrq;
+	adapter->num_tx_queues = ntq;
+}
+
+/**
+ * ixgbe_cache_ring_register - Descriptor ring to register mapping
+ * @adapter: board private structure to initialize
+ *
+ * Once we know the feature-set enabled for the device, we'll cache
+ * the register offset the descriptor ring is assigned to.
+ **/
+static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
+{
+	/* TODO: Remove all uses of the indices in the cases where multiple
+	 *       features are OR'd together, if the feature set makes sense.
+	 */
+	int feature_mask = 0, rss_i;
+	int i, txr_idx, rxr_idx;
+
+	/* Number of supported queues */
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
+		rss_i = adapter->ring_feature[RING_F_RSS].indices;
+		txr_idx = 0;
+		rxr_idx = 0;
+		feature_mask |= IXGBE_FLAG_RSS_ENABLED;
+		switch (adapter->flags & feature_mask) {
+		case (IXGBE_FLAG_RSS_ENABLED):
+			for (i = 0; i < adapter->num_rx_queues; i++)
+				adapter->rx_ring[i].reg_idx = i;
+			for (i = 0; i < adapter->num_tx_queues; i++)
+				adapter->tx_ring[i].reg_idx = i;
+			break;
+		case 0:
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
 /**
  * ixgbe_alloc_queues - Allocate memory for all rings
  * @adapter: board private structure to initialize
@@ -1612,25 +2219,167 @@
 	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
 				   sizeof(struct ixgbe_ring), GFP_KERNEL);
 	if (!adapter->tx_ring)
-		return -ENOMEM;
-
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD;
+		goto err_tx_ring_allocation;
 
 	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
 				   sizeof(struct ixgbe_ring), GFP_KERNEL);
-	if (!adapter->rx_ring) {
-		kfree(adapter->tx_ring);
-		return -ENOMEM;
+	if (!adapter->rx_ring)
+		goto err_rx_ring_allocation;
+
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD;
+		adapter->tx_ring[i].queue_index = i;
+	}
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		adapter->rx_ring[i].count = IXGBE_DEFAULT_RXD;
+		adapter->rx_ring[i].queue_index = i;
 	}
 
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		adapter->rx_ring[i].adapter = adapter;
-		adapter->rx_ring[i].itr_register = IXGBE_EITR(i);
-		adapter->rx_ring[i].count = IXGBE_DEFAULT_RXD;
-	}
+	ixgbe_cache_ring_register(adapter);
 
 	return 0;
+
+err_rx_ring_allocation:
+	kfree(adapter->tx_ring);
+err_tx_ring_allocation:
+	return -ENOMEM;
+}
+
+/**
+ * ixgbe_set_interrupt_capability - set MSI-X or MSI if supported
+ * @adapter: board private structure to initialize
+ *
+ * Attempt to configure the interrupts using the best available
+ * capabilities of the hardware and the kernel.
+ **/
+static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
+						    *adapter)
+{
+	int err = 0;
+	int vector, v_budget;
+
+	/*
+	 * It's easy to be greedy for MSI-X vectors, but it really
+	 * doesn't do us much good if we have a lot more vectors
+	 * than CPU's.  So let's be conservative and only ask for
+	 * (roughly) twice the number of vectors as there are CPU's.
+	 */
+	v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues,
+		       (int)(num_online_cpus() * 2)) + NON_Q_VECTORS;
+
+	/*
+	 * At the same time, hardware can only support a maximum of
+	 * MAX_MSIX_COUNT vectors.  With features such as RSS and VMDq,
+	 * we can easily reach upwards of 64 Rx descriptor queues and
+	 * 32 Tx queues.  Thus, we cap it off in those rare cases where
+	 * the cpu count also exceeds our vector limit.
+	 */
+	v_budget = min(v_budget, MAX_MSIX_COUNT);
+
+	/* A failure in MSI-X entry allocation isn't fatal, but it does
+	 * mean we disable MSI-X capabilities of the adapter. */
+	adapter->msix_entries = kcalloc(v_budget,
+					sizeof(struct msix_entry), GFP_KERNEL);
+	if (!adapter->msix_entries) {
+		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+		ixgbe_set_num_queues(adapter);
+		kfree(adapter->tx_ring);
+		kfree(adapter->rx_ring);
+		err = ixgbe_alloc_queues(adapter);
+		if (err) {
+			DPRINTK(PROBE, ERR, "Unable to allocate memory "
+					    "for queues\n");
+			goto out;
+		}
+
+		goto try_msi;
+	}
+
+	for (vector = 0; vector < v_budget; vector++)
+		adapter->msix_entries[vector].entry = vector;
+
+	ixgbe_acquire_msix_vectors(adapter, v_budget);
+
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+		goto out;
+
+try_msi:
+	err = pci_enable_msi(adapter->pdev);
+	if (!err) {
+		adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
+	} else {
+		DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, "
+				   "falling back to legacy.  Error: %d\n", err);
+		/* reset err */
+		err = 0;
+	}
+
+out:
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	/* Notify the stack of the (possibly) reduced Tx Queue count. */
+	adapter->netdev->egress_subqueue_count = adapter->num_tx_queues;
+#endif
+
+	return err;
+}
+
+static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
+{
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
+		pci_disable_msix(adapter->pdev);
+		kfree(adapter->msix_entries);
+		adapter->msix_entries = NULL;
+	} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+		adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
+		pci_disable_msi(adapter->pdev);
+	}
+	return;
+}
+
+/**
+ * ixgbe_init_interrupt_scheme - Determine proper interrupt scheme
+ * @adapter: board private structure to initialize
+ *
+ * We determine which interrupt scheme to use based on...
+ * - Kernel support (MSI, MSI-X)
+ *   - which can be user-defined (via MODULE_PARAM)
+ * - Hardware queue count (num_*_queues)
+ *   - defined by miscellaneous hardware support/features (RSS, etc.)
+ **/
+static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
+{
+	int err;
+
+	/* Number of supported queues */
+	ixgbe_set_num_queues(adapter);
+
+	err = ixgbe_alloc_queues(adapter);
+	if (err) {
+		DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+		goto err_alloc_queues;
+	}
+
+	err = ixgbe_set_interrupt_capability(adapter);
+	if (err) {
+		DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n");
+		goto err_set_interrupt;
+	}
+
+	DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, "
+			   "Tx Queue count = %u\n",
+		(adapter->num_rx_queues > 1) ? "Enabled" :
+		"Disabled", adapter->num_rx_queues, adapter->num_tx_queues);
+
+	set_bit(__IXGBE_DOWN, &adapter->state);
+
+	return 0;
+
+err_set_interrupt:
+	kfree(adapter->tx_ring);
+	kfree(adapter->rx_ring);
+err_alloc_queues:
+	return err;
 }
 
 /**
@@ -1645,11 +2394,22 @@
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
+	unsigned int rss;
+
+	/* Set capability flags */
+	rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
+	adapter->ring_feature[RING_F_RSS].indices = rss;
+	adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+
+	/* Enable Dynamic interrupt throttling by default */
+	adapter->rx_eitr = 1;
+	adapter->tx_eitr = 1;
 
 	/* default flow control settings */
 	hw->fc.original_type = ixgbe_fc_full;
 	hw->fc.type = ixgbe_fc_full;
 
+	/* select 10G link by default */
 	hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN;
 	if (hw->mac.ops.reset(hw)) {
 		dev_err(&pdev->dev, "HW Init failed\n");
@@ -1667,16 +2427,9 @@
 		return -EIO;
 	}
 
-	/* Set the default values */
-	adapter->num_rx_queues = IXGBE_DEFAULT_RXQ;
-	adapter->num_tx_queues = 1;
+	/* enable rx csum by default */
 	adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
 
-	if (ixgbe_alloc_queues(adapter)) {
-		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
-		return -ENOMEM;
-	}
-
 	set_bit(__IXGBE_DOWN, &adapter->state);
 
 	return 0;
@@ -1716,7 +2469,6 @@
 		return -ENOMEM;
 	}
 
-	txdr->adapter = adapter;
 	txdr->next_to_use = 0;
 	txdr->next_to_clean = 0;
 	txdr->work_limit = txdr->count;
@@ -1735,7 +2487,7 @@
 			     struct ixgbe_ring *rxdr)
 {
 	struct pci_dev *pdev = adapter->pdev;
-	int size, desc_len;
+	int size;
 
 	size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
 	rxdr->rx_buffer_info = vmalloc(size);
@@ -1746,10 +2498,8 @@
 	}
 	memset(rxdr->rx_buffer_info, 0, size);
 
-	desc_len = sizeof(union ixgbe_adv_rx_desc);
-
 	/* Round up to nearest 4K */
-	rxdr->size = rxdr->count * desc_len;
+	rxdr->size = rxdr->count * sizeof(union ixgbe_adv_rx_desc);
 	rxdr->size = ALIGN(rxdr->size, 4096);
 
 	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
@@ -1763,7 +2513,6 @@
 
 	rxdr->next_to_clean = 0;
 	rxdr->next_to_use = 0;
-	rxdr->adapter = adapter;
 
 	return 0;
 }
@@ -1841,8 +2590,7 @@
 }
 
 /**
- * ixgbe_setup_all_tx_resources - wrapper to allocate Tx resources
- *				  (Descriptors) for all queues
+ * ixgbe_setup_all_tx_resources - allocate all queues Tx resources
  * @adapter: board private structure
  *
  * If this function returns with an error, then it's possible one or
@@ -1868,8 +2616,7 @@
 }
 
 /**
- * ixgbe_setup_all_rx_resources - wrapper to allocate Rx resources
- *				  (Descriptors) for all queues
+ * ixgbe_setup_all_rx_resources - allocate all queues Rx resources
  * @adapter: board private structure
  *
  * If this function returns with an error, then it's possible one or
@@ -1911,6 +2658,9 @@
 	    (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
 		return -EINVAL;
 
+	DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n",
+		netdev->mtu, new_mtu);
+	/* must set new MTU before calling down or up */
 	netdev->mtu = new_mtu;
 
 	if (netif_running(netdev))
@@ -1935,23 +2685,16 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	int err;
-	u32 num_rx_queues = adapter->num_rx_queues;
 
 	/* disallow open during test */
 	if (test_bit(__IXGBE_TESTING, &adapter->state))
 		return -EBUSY;
 
-try_intr_reinit:
 	/* allocate transmit descriptors */
 	err = ixgbe_setup_all_tx_resources(adapter);
 	if (err)
 		goto err_setup_tx;
 
-	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
-		num_rx_queues = 1;
-		adapter->num_rx_queues = num_rx_queues;
-	}
-
 	/* allocate receive descriptors */
 	err = ixgbe_setup_all_rx_resources(adapter);
 	if (err)
@@ -1959,31 +2702,10 @@
 
 	ixgbe_configure(adapter);
 
-	err = ixgbe_request_irq(adapter, &num_rx_queues);
+	err = ixgbe_request_irq(adapter);
 	if (err)
 		goto err_req_irq;
 
-	/* ixgbe_request might have reduced num_rx_queues */
-	if (num_rx_queues < adapter->num_rx_queues) {
-		/* We didn't get MSI-X, so we need to release everything,
-		 * set our Rx queue count to num_rx_queues, and redo the
-		 * whole init process.
-		 */
-		ixgbe_free_irq(adapter);
-		if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
-			pci_disable_msi(adapter->pdev);
-			adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
-		}
-		ixgbe_free_all_rx_resources(adapter);
-		ixgbe_free_all_tx_resources(adapter);
-		adapter->num_rx_queues = num_rx_queues;
-
-		/* Reset the hardware, and start over. */
-		ixgbe_reset(adapter);
-
-		goto try_intr_reinit;
-	}
-
 	err = ixgbe_up_complete(adapter);
 	if (err)
 		goto err_up;
@@ -2119,6 +2841,9 @@
 	struct net_device *netdev = adapter->netdev;
 	bool link_up;
 	u32 link_speed = 0;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	int i;
+#endif
 
 	adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up);
 
@@ -2140,6 +2865,10 @@
 
 			netif_carrier_on(netdev);
 			netif_wake_queue(netdev);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+			for (i = 0; i < adapter->num_tx_queues; i++)
+				netif_wake_subqueue(netdev, i);
+#endif
 		} else {
 			/* Force detection of hung controller */
 			adapter->detect_tx_hung = true;
@@ -2154,10 +2883,23 @@
 
 	ixgbe_update_stats(adapter);
 
-	/* Reset the timer */
-	if (!test_bit(__IXGBE_DOWN, &adapter->state))
+	if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+		/* Cause software interrupt to ensure rx rings are cleaned */
+		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+			u32 eics =
+			 (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1;
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, eics);
+		} else {
+			/* for legacy and MSI interrupts don't set any bits that
+			 * are enabled for EIAM, because this operation would
+			 * set *both* EIMS and EICS for any bit in EIAM */
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
+				     (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
+		}
+		/* Reset the timer */
 		mod_timer(&adapter->watchdog_timer,
 			  round_jiffies(jiffies + 2 * HZ));
+	}
 }
 
 static int ixgbe_tso(struct ixgbe_adapter *adapter,
@@ -2170,7 +2912,6 @@
 	struct ixgbe_tx_buffer *tx_buffer_info;
 	u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
 	u32 mss_l4len_idx = 0, l4len;
-	*hdr_len = 0;
 
 	if (skb_is_gso(skb)) {
 		if (skb_header_cloned(skb)) {
@@ -2454,7 +3195,11 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	netif_stop_subqueue(netdev, tx_ring->queue_index);
+#else
 	netif_stop_queue(netdev);
+#endif
 	/* Herbert's original patch had:
 	 *  smp_mb__after_netif_stop_queue();
 	 * but since that doesn't exist yet, just open code it. */
@@ -2466,7 +3211,11 @@
 		return -EBUSY;
 
 	/* A reprieve! - use start_queue because it doesn't call schedule */
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	netif_wake_subqueue(netdev, tx_ring->queue_index);
+#else
 	netif_wake_queue(netdev);
+#endif
 	++adapter->restart_queue;
 	return 0;
 }
@@ -2487,15 +3236,18 @@
 	unsigned int len = skb->len;
 	unsigned int first;
 	unsigned int tx_flags = 0;
-	u8 hdr_len;
-	int tso;
+	u8 hdr_len = 0;
+	int r_idx = 0, tso;
 	unsigned int mss = 0;
 	int count = 0;
 	unsigned int f;
 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
 	len -= skb->data_len;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	r_idx = (adapter->num_tx_queues - 1) & skb->queue_mapping;
+#endif
+	tx_ring = &adapter->tx_ring[r_idx];
 
-	tx_ring = adapter->tx_ring;
 
 	if (skb->len <= 0) {
 		dev_kfree_skb(skb);
@@ -2604,6 +3356,31 @@
 #endif
 
 /**
+ * ixgbe_napi_add_all - prep napi structs for use
+ * @adapter: private struct
+ * helper function to napi_add each possible q_vector->napi
+ */
+static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
+{
+	int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+	int (*poll)(struct napi_struct *, int);
+
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		poll = &ixgbe_clean_rxonly;
+	} else {
+		poll = &ixgbe_poll;
+		/* only one q_vector for legacy modes */
+		q_vectors = 1;
+	}
+
+	for (i = 0; i < q_vectors; i++) {
+		struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
+		netif_napi_add(adapter->netdev, &q_vector->napi,
+			       (*poll), 64);
+	}
+}
+
+/**
  * ixgbe_probe - Device Initialization Routine
  * @pdev: PCI device information struct
  * @ent: entry in ixgbe_pci_tbl
@@ -2655,7 +3432,11 @@
 
 	pci_set_master(pdev);
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES);
+#else
 	netdev = alloc_etherdev(sizeof(struct ixgbe_adapter));
+#endif
 	if (!netdev) {
 		err = -ENOMEM;
 		goto err_alloc_etherdev;
@@ -2696,7 +3477,6 @@
 	ixgbe_set_ethtool_ops(netdev);
 	netdev->tx_timeout = &ixgbe_tx_timeout;
 	netdev->watchdog_timeo = 5 * HZ;
-	netif_napi_add(netdev, &adapter->napi, ixgbe_clean, 64);
 	netdev->vlan_rx_register = ixgbe_vlan_rx_register;
 	netdev->vlan_rx_add_vid = ixgbe_vlan_rx_add_vid;
 	netdev->vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid;
@@ -2719,6 +3499,7 @@
 
 	/* Setup hw api */
 	memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops));
+	hw->mac.type  = ii->mac;
 
 	err = ii->get_invariants(hw);
 	if (err)
@@ -2741,6 +3522,9 @@
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	netdev->features |= NETIF_F_MULTI_QUEUE;
+#endif
 
 	/* make sure the EEPROM is good */
 	if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) {
@@ -2770,9 +3554,9 @@
 	hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
 	hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
 
-	/* Interrupt Throttle Rate */
-	adapter->rx_eitr = (1000000 / IXGBE_DEFAULT_ITR_RX_USECS);
-	adapter->tx_eitr = (1000000 / IXGBE_DEFAULT_ITR_TX_USECS);
+	err = ixgbe_init_interrupt_scheme(adapter);
+	if (err)
+		goto err_sw_init;
 
 	/* print bus type/speed/width info */
 	pci_read_config_word(pdev, IXGBE_PCI_LINK_STATUS, &link_status);
@@ -2808,12 +3592,27 @@
 
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		netif_stop_subqueue(netdev, i);
+#endif
+
+	ixgbe_napi_add_all(adapter);
 
 	strcpy(netdev->name, "eth%d");
 	err = register_netdev(netdev);
 	if (err)
 		goto err_register;
 
+#ifdef CONFIG_DCA
+	if (dca_add_requester(&pdev->dev) == IXGBE_SUCCESS) {
+		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
+		/* always use CB2 mode, difference is masked
+		 * in the CB driver */
+		IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2);
+		ixgbe_setup_dca(adapter);
+	}
+#endif
 
 	dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n");
 	cards_found++;
@@ -2823,6 +3622,7 @@
 	ixgbe_release_hw_control(adapter);
 err_hw_init:
 err_sw_init:
+	ixgbe_reset_interrupt_capability(adapter);
 err_eeprom:
 	iounmap(hw->hw_addr);
 err_ioremap:
@@ -2854,16 +3654,27 @@
 
 	flush_scheduled_work();
 
+#ifdef CONFIG_DCA
+	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
+		adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
+		dca_remove_requester(&pdev->dev);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
+	}
+
+#endif
 	unregister_netdev(netdev);
 
+	ixgbe_reset_interrupt_capability(adapter);
+
 	ixgbe_release_hw_control(adapter);
 
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
-
 	iounmap(adapter->hw.hw_addr);
 	pci_release_regions(pdev);
 
+	DPRINTK(PROBE, INFO, "complete\n");
+	kfree(adapter->tx_ring);
+	kfree(adapter->rx_ring);
+
 	free_netdev(netdev);
 
 	pci_disable_device(pdev);
@@ -2975,6 +3786,10 @@
 
 	printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
 
+#ifdef CONFIG_DCA
+	dca_register_notify(&dca_notifier);
+
+#endif
 	ret = pci_register_driver(&ixgbe_driver);
 	return ret;
 }
@@ -2988,8 +3803,25 @@
  **/
 static void __exit ixgbe_exit_module(void)
 {
+#ifdef CONFIG_DCA
+	dca_unregister_notify(&dca_notifier);
+#endif
 	pci_unregister_driver(&ixgbe_driver);
 }
+
+#ifdef CONFIG_DCA
+static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
+			    void *p)
+{
+	int ret_val;
+
+	ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
+					 __ixgbe_notify_dca);
+
+	return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
+}
+#endif /* CONFIG_DCA */
+
 module_exit(ixgbe_exit_module);
 
 /* ixgbe_main.c */
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index c72787a..6d8e5c4 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -50,6 +50,8 @@
  *                 Possible values '1' for enable , '0' for disable.
  *                 Default is '2' - which means disable in promisc mode
  *                 and enable in non-promiscuous mode.
+ * multiq: This parameter used to enable/disable MULTIQUEUE support.
+ *      Possible values '1' for enable and '0' for disable. Default is '0'
  ************************************************************************/
 
 #include <linux/module.h>
@@ -84,7 +86,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.15-2"
+#define DRV_VERSION "2.0.26.19"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -386,6 +388,26 @@
 /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
 static int vlan_strip_flag;
 
+/* Unregister the vlan */
+static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
+{
+	int i;
+	struct s2io_nic *nic = dev->priv;
+	unsigned long flags[MAX_TX_FIFOS];
+	struct mac_info *mac_control = &nic->mac_control;
+	struct config_param *config = &nic->config;
+
+	for (i = 0; i < config->tx_fifo_num; i++)
+		spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags[i]);
+
+	if (nic->vlgrp)
+		vlan_group_set_device(nic->vlgrp, vid, NULL);
+
+	for (i = config->tx_fifo_num - 1; i >= 0; i--)
+		spin_unlock_irqrestore(&mac_control->fifos[i].tx_lock,
+			flags[i]);
+}
+
 /*
  * Constants to be programmed into the Xena's registers, to configure
  * the XAUI.
@@ -456,10 +478,9 @@
 
 
 /* Module Loadable parameters. */
-S2IO_PARM_INT(tx_fifo_num, 1);
+S2IO_PARM_INT(tx_fifo_num, FIFO_DEFAULT_NUM);
 S2IO_PARM_INT(rx_ring_num, 1);
-
-
+S2IO_PARM_INT(multiq, 0);
 S2IO_PARM_INT(rx_ring_mode, 1);
 S2IO_PARM_INT(use_continuous_tx_intrs, 1);
 S2IO_PARM_INT(rmac_pause_time, 0x100);
@@ -469,6 +490,8 @@
 S2IO_PARM_INT(tmac_util_period, 5);
 S2IO_PARM_INT(rmac_util_period, 5);
 S2IO_PARM_INT(l3l4hdr_size, 128);
+/* 0 is no steering, 1 is Priority steering, 2 is Default steering */
+S2IO_PARM_INT(tx_steering_type, TX_DEFAULT_STEERING);
 /* Frequency of Rx desc syncs expressed as power of 2 */
 S2IO_PARM_INT(rxsync_frequency, 3);
 /* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
@@ -533,6 +556,101 @@
 /* A simplifier macro used both by init and free shared_mem Fns(). */
 #define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each)
 
+/* netqueue manipulation helper functions */
+static inline void s2io_stop_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			netif_stop_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_STOP;
+		netif_stop_queue(sp->dev);
+	}
+}
+
+static inline void s2io_stop_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq)
+		netif_stop_subqueue(sp->dev, fifo_no);
+	else
+#endif
+	{
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_STOP;
+		netif_stop_queue(sp->dev);
+	}
+}
+
+static inline void s2io_start_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			netif_start_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+		netif_start_queue(sp->dev);
+	}
+}
+
+static inline void s2io_start_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq)
+		netif_start_subqueue(sp->dev, fifo_no);
+	else
+#endif
+	{
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_START;
+		netif_start_queue(sp->dev);
+	}
+}
+
+static inline void s2io_wake_all_tx_queue(struct s2io_nic *sp)
+{
+	int i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			netif_wake_subqueue(sp->dev, i);
+	} else
+#endif
+	{
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+		netif_wake_queue(sp->dev);
+	}
+}
+
+static inline void s2io_wake_tx_queue(
+	struct fifo_info *fifo, int cnt, u8 multiq)
+{
+
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq) {
+		if (cnt && __netif_subqueue_stopped(fifo->dev, fifo->fifo_no))
+			netif_wake_subqueue(fifo->dev, fifo->fifo_no);
+	} else
+#endif
+	if (cnt && (fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(fifo->dev)) {
+			fifo->queue_state = FIFO_QUEUE_START;
+			netif_wake_queue(fifo->dev);
+		}
+	}
+}
+
 /**
  * init_shared_mem - Allocation and Initialization of Memory
  * @nic: Device private variable.
@@ -614,6 +732,7 @@
 		mac_control->fifos[i].fifo_no = i;
 		mac_control->fifos[i].nic = nic;
 		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
+		mac_control->fifos[i].dev = dev;
 
 		for (j = 0; j < page_num; j++) {
 			int k = 0;
@@ -2948,7 +3067,7 @@
 			struct lro *lro = &nic->lro0_n[i];
 			if (lro->in_use) {
 				update_L3L4_header(nic, lro);
-				queue_rx_frame(lro->parent);
+				queue_rx_frame(lro->parent, lro->vlan_tag);
 				clear_lro_session(lro);
 			}
 		}
@@ -2972,10 +3091,10 @@
 static void tx_intr_handler(struct fifo_info *fifo_data)
 {
 	struct s2io_nic *nic = fifo_data->nic;
-	struct net_device *dev = (struct net_device *) nic->dev;
 	struct tx_curr_get_info get_info, put_info;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct TxD *txdlp;
+	int pkt_cnt = 0;
 	unsigned long flags = 0;
 	u8 err_mask;
 
@@ -3036,6 +3155,7 @@
 			DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
 			return;
 		}
+		pkt_cnt++;
 
 		/* Updating the statistics block */
 		nic->stats.tx_bytes += skb->len;
@@ -3051,8 +3171,7 @@
 		    get_info.offset;
 	}
 
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
+	s2io_wake_tx_queue(fifo_data, pkt_cnt, nic->config.multiq);
 
 	spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
 }
@@ -3933,8 +4052,7 @@
 		err = -ENODEV;
 		goto hw_init_failed;
 	}
-
-	netif_start_queue(dev);
+	s2io_start_all_tx_queue(sp);
 	return 0;
 
 hw_init_failed:
@@ -3979,8 +4097,7 @@
 	if (!is_s2io_card_up(sp))
 		return 0;
 
-	netif_stop_queue(dev);
-
+	s2io_stop_all_tx_queue(sp);
 	/* delete all populated mac entries */
 	for (offset = 1; offset < config->max_mc_addr; offset++) {
 		tmp64 = do_s2io_read_unicast_mc(sp, offset);
@@ -4016,11 +4133,12 @@
 	struct TxFIFO_element __iomem *tx_fifo;
 	unsigned long flags = 0;
 	u16 vlan_tag = 0;
-	int vlan_priority = 0;
 	struct fifo_info *fifo = NULL;
 	struct mac_info *mac_control;
 	struct config_param *config;
+	int do_spin_lock = 1;
 	int offload_type;
+	int enable_per_list_interrupt = 0;
 	struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
 
 	mac_control = &sp->mac_control;
@@ -4042,15 +4160,67 @@
 	}
 
 	queue = 0;
-	/* Get Fifo number to Transmit based on vlan priority */
-	if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+	if (sp->vlgrp && vlan_tx_tag_present(skb))
 		vlan_tag = vlan_tx_tag_get(skb);
-		vlan_priority = vlan_tag >> 13;
-		queue = config->fifo_mapping[vlan_priority];
+	if (sp->config.tx_steering_type == TX_DEFAULT_STEERING) {
+		if (skb->protocol == htons(ETH_P_IP)) {
+			struct iphdr *ip;
+			struct tcphdr *th;
+			ip = ip_hdr(skb);
+
+			if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+				th = (struct tcphdr *)(((unsigned char *)ip) +
+						ip->ihl*4);
+
+				if (ip->protocol == IPPROTO_TCP) {
+					queue_len = sp->total_tcp_fifos;
+					queue = (ntohs(th->source) +
+							ntohs(th->dest)) &
+					    sp->fifo_selector[queue_len - 1];
+					if (queue >= queue_len)
+						queue = queue_len - 1;
+				} else if (ip->protocol == IPPROTO_UDP) {
+					queue_len = sp->total_udp_fifos;
+					queue = (ntohs(th->source) +
+							ntohs(th->dest)) &
+					    sp->fifo_selector[queue_len - 1];
+					if (queue >= queue_len)
+						queue = queue_len - 1;
+					queue += sp->udp_fifo_idx;
+					if (skb->len > 1024)
+						enable_per_list_interrupt = 1;
+					do_spin_lock = 0;
+				}
+			}
+		}
+	} else if (sp->config.tx_steering_type == TX_PRIORITY_STEERING)
+		/* get fifo number based on skb->priority value */
+		queue = config->fifo_mapping
+					[skb->priority & (MAX_TX_FIFOS - 1)];
+	fifo = &mac_control->fifos[queue];
+
+	if (do_spin_lock)
+		spin_lock_irqsave(&fifo->tx_lock, flags);
+	else {
+		if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags)))
+			return NETDEV_TX_LOCKED;
 	}
 
-	fifo = &mac_control->fifos[queue];
-	spin_lock_irqsave(&fifo->tx_lock, flags);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (sp->config.multiq) {
+		if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	} else
+#endif
+	if (unlikely(fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(dev)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	}
+
 	put_off = (u16) fifo->tx_curr_put_info.offset;
 	get_off = (u16) fifo->tx_curr_get_info.offset;
 	txdp = (struct TxD *) fifo->list_info[put_off].list_virt_addr;
@@ -4060,7 +4230,7 @@
 	if (txdp->Host_Control ||
 		   ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
 		DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 		dev_kfree_skb(skb);
 		spin_unlock_irqrestore(&fifo->tx_lock, flags);
 		return 0;
@@ -4079,8 +4249,10 @@
 	txdp->Control_1 |= TXD_GATHER_CODE_FIRST;
 	txdp->Control_1 |= TXD_LIST_OWN_XENA;
 	txdp->Control_2 |= TXD_INT_NUMBER(fifo->fifo_no);
-
-	if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+	if (enable_per_list_interrupt)
+		if (put_off & (queue_len >> 5))
+			txdp->Control_2 |= TXD_INT_TYPE_PER_LIST;
+	if (vlan_tag) {
 		txdp->Control_2 |= TXD_VLAN_ENABLE;
 		txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
 	}
@@ -4166,7 +4338,7 @@
 		DBG_PRINT(TX_DBG,
 			  "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
 			  put_off, get_off);
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 	}
 	mac_control->stats_info->sw_stat.mem_allocated += skb->truesize;
 	dev->trans_start = jiffies;
@@ -4175,7 +4347,7 @@
 	return 0;
 pci_map_failed:
 	stats->pci_map_fail_cnt++;
-	netif_stop_queue(dev);
+	s2io_stop_tx_queue(sp, fifo->fifo_no);
 	stats->mem_freed += skb->truesize;
 	dev_kfree_skb(skb);
 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
@@ -4587,7 +4759,7 @@
 	return;
 
 reset:
-	netif_stop_queue(dev);
+	s2io_stop_all_tx_queue(sp);
 	schedule_work(&sp->rst_timer_task);
 	sw_stat->soft_reset_cnt++;
 	return;
@@ -6574,16 +6746,15 @@
 
 	dev->mtu = new_mtu;
 	if (netif_running(dev)) {
+		s2io_stop_all_tx_queue(sp);
 		s2io_card_down(sp);
-		netif_stop_queue(dev);
 		ret = s2io_card_up(sp);
 		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
 				  __FUNCTION__);
 			return ret;
 		}
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
+		s2io_wake_all_tx_queue(sp);
 	} else { /* Device is down */
 		struct XENA_dev_config __iomem *bar0 = sp->bar0;
 		u64 val64 = new_mtu;
@@ -6691,7 +6862,7 @@
 			} else {
 				DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
 				DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
-				netif_stop_queue(dev);
+				s2io_stop_all_tx_queue(nic);
 			}
 		}
 		val64 = readq(&bar0->adapter_control);
@@ -7181,7 +7352,7 @@
 		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
 			  dev->name);
 	}
-	netif_wake_queue(dev);
+	s2io_wake_all_tx_queue(sp);
 	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
 		  dev->name);
 out_unlock:
@@ -7371,7 +7542,8 @@
 					{
 						lro_append_pkt(sp, lro,
 							skb, tcp_len);
-						queue_rx_frame(lro->parent);
+						queue_rx_frame(lro->parent,
+							lro->vlan_tag);
 						clear_lro_session(lro);
 						sp->mac_control.stats_info->
 						    sw_stat.flush_max_pkts++;
@@ -7382,7 +7554,8 @@
 							lro->frags_len;
 						sp->mac_control.stats_info->
 						     sw_stat.sending_both++;
-						queue_rx_frame(lro->parent);
+						queue_rx_frame(lro->parent,
+							lro->vlan_tag);
 						clear_lro_session(lro);
 						goto send_up;
 					case 0: /* sessions exceeded */
@@ -7408,31 +7581,12 @@
 			 */
 			skb->ip_summed = CHECKSUM_NONE;
 		}
-	} else {
+	} else
 		skb->ip_summed = CHECKSUM_NONE;
-	}
+
 	sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
-	if (!sp->lro) {
-		skb->protocol = eth_type_trans(skb, dev);
-		if ((sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2) &&
-			vlan_strip_flag)) {
-			/* Queueing the vlan frame to the upper layer */
-			if (napi)
-				vlan_hwaccel_receive_skb(skb, sp->vlgrp,
-					RXD_GET_VLAN_TAG(rxdp->Control_2));
-			else
-				vlan_hwaccel_rx(skb, sp->vlgrp,
-					RXD_GET_VLAN_TAG(rxdp->Control_2));
-		} else {
-			if (napi)
-				netif_receive_skb(skb);
-			else
-				netif_rx(skb);
-		}
-	} else {
 send_up:
-		queue_rx_frame(skb);
-	}
+	queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2));
 	dev->last_rx = jiffies;
 aggregate:
 	atomic_dec(&sp->rx_bufs_left[ring_no]);
@@ -7460,6 +7614,7 @@
 		init_tti(sp, link);
 		if (link == LINK_DOWN) {
 			DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name);
+			s2io_stop_all_tx_queue(sp);
 			netif_carrier_off(dev);
 			if(sp->mac_control.stats_info->sw_stat.link_up_cnt)
 			sp->mac_control.stats_info->sw_stat.link_up_time =
@@ -7472,6 +7627,7 @@
 				jiffies - sp->start_time;
 			sp->mac_control.stats_info->sw_stat.link_up_cnt++;
 			netif_carrier_on(dev);
+			s2io_wake_all_tx_queue(sp);
 		}
 	}
 	sp->last_link_state = link;
@@ -7508,20 +7664,48 @@
 	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
 }
 
-static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
+static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
+	u8 *dev_multiq)
 {
 	if ((tx_fifo_num > MAX_TX_FIFOS) ||
-		(tx_fifo_num < FIFO_DEFAULT_NUM)) {
+		(tx_fifo_num < 1)) {
 		DBG_PRINT(ERR_DBG, "s2io: Requested number of tx fifos "
 			"(%d) not supported\n", tx_fifo_num);
-		tx_fifo_num =
-			((tx_fifo_num > MAX_TX_FIFOS)? MAX_TX_FIFOS :
-			((tx_fifo_num < FIFO_DEFAULT_NUM) ? FIFO_DEFAULT_NUM :
-			tx_fifo_num));
+
+		if (tx_fifo_num < 1)
+			tx_fifo_num = 1;
+		else
+			tx_fifo_num = MAX_TX_FIFOS;
+
 		DBG_PRINT(ERR_DBG, "s2io: Default to %d ", tx_fifo_num);
 		DBG_PRINT(ERR_DBG, "tx fifos\n");
 	}
 
+#ifndef CONFIG_NETDEVICES_MULTIQUEUE
+	if (multiq) {
+		DBG_PRINT(ERR_DBG, "s2io: Multiqueue support not enabled\n");
+		multiq = 0;
+	}
+#endif
+	if (multiq)
+		*dev_multiq = multiq;
+
+	if (tx_steering_type && (1 == tx_fifo_num)) {
+		if (tx_steering_type != TX_DEFAULT_STEERING)
+			DBG_PRINT(ERR_DBG,
+				"s2io: Tx steering is not supported with "
+				"one fifo. Disabling Tx steering.\n");
+		tx_steering_type = NO_STEERING;
+	}
+
+	if ((tx_steering_type < NO_STEERING) ||
+		(tx_steering_type > TX_DEFAULT_STEERING)) {
+		DBG_PRINT(ERR_DBG, "s2io: Requested transmit steering not "
+			 "supported\n");
+		DBG_PRINT(ERR_DBG, "s2io: Disabling transmit steering\n");
+		tx_steering_type = NO_STEERING;
+	}
+
 	if ( rx_ring_num > 8) {
 		DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
 			 "supported\n");
@@ -7613,9 +7797,11 @@
 	struct config_param *config;
 	int mode;
 	u8 dev_intr_type = intr_type;
+	u8 dev_multiq = 0;
 	DECLARE_MAC_BUF(mac);
 
-	if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
+	ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
+	if (ret)
 		return ret;
 
 	if ((ret = pci_enable_device(pdev))) {
@@ -7646,7 +7832,11 @@
 		pci_disable_device(pdev);
 		return -ENODEV;
 	}
-
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (dev_multiq)
+		dev = alloc_etherdev_mq(sizeof(struct s2io_nic), tx_fifo_num);
+	else
+#endif
 	dev = alloc_etherdev(sizeof(struct s2io_nic));
 	if (dev == NULL) {
 		DBG_PRINT(ERR_DBG, "Device allocation failed\n");
@@ -7695,17 +7885,45 @@
 	config = &sp->config;
 
 	config->napi = napi;
+	config->tx_steering_type = tx_steering_type;
 
 	/* Tx side parameters. */
-	config->tx_fifo_num = tx_fifo_num;
-	for (i = 0; i < MAX_TX_FIFOS; i++) {
+	if (config->tx_steering_type == TX_PRIORITY_STEERING)
+		config->tx_fifo_num = MAX_TX_FIFOS;
+	else
+		config->tx_fifo_num = tx_fifo_num;
+
+	/* Initialize the fifos used for tx steering */
+	if (config->tx_fifo_num < 5) {
+			if (config->tx_fifo_num  == 1)
+				sp->total_tcp_fifos = 1;
+			else
+				sp->total_tcp_fifos = config->tx_fifo_num - 1;
+			sp->udp_fifo_idx = config->tx_fifo_num - 1;
+			sp->total_udp_fifos = 1;
+			sp->other_fifo_idx = sp->total_tcp_fifos - 1;
+	} else {
+		sp->total_tcp_fifos = (tx_fifo_num - FIFO_UDP_MAX_NUM -
+						FIFO_OTHER_MAX_NUM);
+		sp->udp_fifo_idx = sp->total_tcp_fifos;
+		sp->total_udp_fifos = FIFO_UDP_MAX_NUM;
+		sp->other_fifo_idx = sp->udp_fifo_idx + FIFO_UDP_MAX_NUM;
+	}
+
+	config->multiq = dev_multiq;
+	for (i = 0; i < config->tx_fifo_num; i++) {
 		config->tx_cfg[i].fifo_len = tx_fifo_len[i];
 		config->tx_cfg[i].fifo_priority = i;
 	}
 
 	/* mapping the QoS priority to the configured fifos */
 	for (i = 0; i < MAX_TX_FIFOS; i++)
-		config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i];
+		config->fifo_mapping[i] = fifo_map[config->tx_fifo_num - 1][i];
+
+	/* map the hashing selector table to the configured fifos */
+	for (i = 0; i < config->tx_fifo_num; i++)
+		sp->fifo_selector[i] = fifo_selector[i];
+
 
 	config->tx_intr_type = TXD_INT_TYPE_UTILZ;
 	for (i = 0; i < config->tx_fifo_num; i++) {
@@ -7790,6 +8008,7 @@
 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = s2io_vlan_rx_register;
+	dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
 
 	/*
 	 * will use eth_mac_addr() for  dev->set_mac_address
@@ -7810,7 +8029,10 @@
 		dev->features |= NETIF_F_UFO;
 		dev->features |= NETIF_F_HW_CSUM;
 	}
-
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	if (config->multiq)
+		dev->features |= NETIF_F_MULTI_QUEUE;
+#endif
 	dev->tx_timeout = &s2io_tx_watchdog;
 	dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
 	INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
@@ -7959,6 +8181,10 @@
 
 	if (napi)
 		DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
+
+	DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name,
+		sp->config.tx_fifo_num);
+
 	switch(sp->config.intr_type) {
 		case INTA:
 		    DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
@@ -7967,6 +8193,29 @@
 		    DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
 		    break;
 	}
+	if (sp->config.multiq) {
+	for (i = 0; i < sp->config.tx_fifo_num; i++)
+		mac_control->fifos[i].multiq = config->multiq;
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
+			dev->name);
+	} else
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
+			dev->name);
+
+	switch (sp->config.tx_steering_type) {
+	case NO_STEERING:
+		DBG_PRINT(ERR_DBG, "%s: No steering enabled for"
+			" transmit\n", dev->name);
+			break;
+	case TX_PRIORITY_STEERING:
+		DBG_PRINT(ERR_DBG, "%s: Priority steering enabled for"
+			" transmit\n", dev->name);
+		break;
+	case TX_DEFAULT_STEERING:
+		DBG_PRINT(ERR_DBG, "%s: Default steering enabled for"
+			" transmit\n", dev->name);
+	}
+
 	if (sp->lro)
 		DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
 			  dev->name);
@@ -8061,7 +8310,8 @@
 module_exit(s2io_closer);
 
 static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
-		struct tcphdr **tcp, struct RxD_t *rxdp)
+		struct tcphdr **tcp, struct RxD_t *rxdp,
+		struct s2io_nic *sp)
 {
 	int ip_off;
 	u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len;
@@ -8072,19 +8322,20 @@
 		return -1;
 	}
 
-	/* TODO:
-	 * By default the VLAN field in the MAC is stripped by the card, if this
-	 * feature is turned off in rx_pa_cfg register, then the ip_off field
-	 * has to be shifted by a further 2 bytes
-	 */
-	switch (l2_type) {
-		case 0: /* DIX type */
-		case 4: /* DIX type with VLAN */
-			ip_off = HEADER_ETHERNET_II_802_3_SIZE;
-			break;
+	/* Checking for DIX type or DIX type with VLAN */
+	if ((l2_type == 0)
+		|| (l2_type == 4)) {
+		ip_off = HEADER_ETHERNET_II_802_3_SIZE;
+		/*
+		 * If vlan stripping is disabled and the frame is VLAN tagged,
+		 * shift the offset by the VLAN header size bytes.
+		 */
+		if ((!vlan_strip_flag) &&
+			(rxdp->Control_1 & RXD_FRAME_VLAN_TAG))
+			ip_off += HEADER_VLAN_SIZE;
+	} else {
 		/* LLC, SNAP etc are considered non-mergeable */
-		default:
-			return -1;
+		return -1;
 	}
 
 	*ip = (struct iphdr *)((u8 *)buffer + ip_off);
@@ -8111,7 +8362,7 @@
 }
 
 static void initiate_new_session(struct lro *lro, u8 *l2h,
-		     struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len)
+	struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len, u16 vlan_tag)
 {
 	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
 	lro->l2h = l2h;
@@ -8122,6 +8373,7 @@
 	lro->sg_num = 1;
 	lro->total_len = ntohs(ip->tot_len);
 	lro->frags_len = 0;
+	lro->vlan_tag = vlan_tag;
 	/*
 	 * check if we saw TCP timestamp. Other consistency checks have
 	 * already been done.
@@ -8253,15 +8505,16 @@
 	struct iphdr *ip;
 	struct tcphdr *tcph;
 	int ret = 0, i;
+	u16 vlan_tag = 0;
 
 	if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
-					 rxdp))) {
+					 rxdp, sp))) {
 		DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n",
 			  ip->saddr, ip->daddr);
-	} else {
+	} else
 		return ret;
-	}
 
+	vlan_tag = RXD_GET_VLAN_TAG(rxdp->Control_2);
 	tcph = (struct tcphdr *)*tcp;
 	*tcp_len = get_l4_pyld_length(ip, tcph);
 	for (i=0; i<MAX_LRO_SESSIONS; i++) {
@@ -8321,7 +8574,8 @@
 
 	switch (ret) {
 		case 3:
-			initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
+			initiate_new_session(*lro, buffer, ip, tcph, *tcp_len,
+								vlan_tag);
 			break;
 		case 2:
 			update_L3L4_header(sp, *lro);
@@ -8349,15 +8603,25 @@
 	memset(lro, 0, lro_struct_size);
 }
 
-static void queue_rx_frame(struct sk_buff *skb)
+static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
 {
 	struct net_device *dev = skb->dev;
+	struct s2io_nic *sp = dev->priv;
 
 	skb->protocol = eth_type_trans(skb, dev);
-	if (napi)
-		netif_receive_skb(skb);
-	else
-		netif_rx(skb);
+	if (sp->vlgrp && vlan_tag
+		&& (vlan_strip_flag)) {
+		/* Queueing the vlan frame to the upper layer */
+		if (sp->config.napi)
+			vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
+		else
+			vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag);
+	} else {
+		if (sp->config.napi)
+			netif_receive_skb(skb);
+		else
+			netif_rx(skb);
+	}
 }
 
 static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 64b88eb..e68fdf7 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -360,7 +360,10 @@
 #define MAX_TX_FIFOS 8
 #define MAX_RX_RINGS 8
 
-#define FIFO_DEFAULT_NUM	1
+#define FIFO_DEFAULT_NUM	5
+#define FIFO_UDP_MAX_NUM			2 /* 0 - even, 1 -odd ports */
+#define FIFO_OTHER_MAX_NUM			1
+
 
 #define MAX_RX_DESC_1  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 )
 #define MAX_RX_DESC_2  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
@@ -379,6 +382,8 @@
 	{0, 1, 2, 3, 4, 5, 6, 7},
 };
 
+static u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7};
+
 /* Maintains Per FIFO related information. */
 struct tx_fifo_config {
 #define	MAX_AVAILABLE_TXDS	8192
@@ -431,6 +436,12 @@
 /* Tx Side */
 	u32 tx_fifo_num;	/*Number of Tx FIFOs */
 
+	/* 0-No steering, 1-Priority steering, 2-Default fifo map */
+#define	NO_STEERING				0
+#define	TX_PRIORITY_STEERING			0x1
+#define TX_DEFAULT_STEERING 			0x2
+	u8 tx_steering_type;
+
 	u8 fifo_mapping[MAX_TX_FIFOS];
 	struct tx_fifo_config tx_cfg[MAX_TX_FIFOS];	/*Per-Tx FIFO config */
 	u32 max_txds;		/*Max no. of Tx buffer descriptor per TxDL */
@@ -464,6 +475,7 @@
 	int max_mc_addr;	/* xena=64 herc=256 */
 	int max_mac_addr;	/* xena=16 herc=64 */
 	int mc_start_offset;	/* xena=16 herc=64 */
+	u8 multiq;
 };
 
 /* Structure representing MAC Addrs */
@@ -534,6 +546,7 @@
 #define RXD_OWN_XENA            s2BIT(7)
 #define RXD_T_CODE              (s2BIT(12)|s2BIT(13)|s2BIT(14)|s2BIT(15))
 #define RXD_FRAME_PROTO         vBIT(0xFFFF,24,8)
+#define RXD_FRAME_VLAN_TAG      s2BIT(24)
 #define RXD_FRAME_PROTO_IPV4    s2BIT(27)
 #define RXD_FRAME_PROTO_IPV6    s2BIT(28)
 #define RXD_FRAME_IP_FRAG	s2BIT(29)
@@ -720,6 +733,15 @@
 	 * the buffers
 	 */
 	struct tx_curr_get_info tx_curr_get_info;
+#define FIFO_QUEUE_START 0
+#define FIFO_QUEUE_STOP 1
+	int queue_state;
+
+	/* copy of sp->dev pointer */
+	struct net_device *dev;
+
+	/* copy of multiq status */
+	u8 multiq;
 
 	/* Per fifo lock */
 	spinlock_t tx_lock;
@@ -808,10 +830,11 @@
 	int		sg_num;
 	int		in_use;
 	__be16		window;
+	u16             vlan_tag;
 	u32		cur_tsval;
 	__be32		cur_tsecr;
 	u8		saw_ts;
-};
+} ____cacheline_aligned;
 
 /* These flags represent the devices temporary state */
 enum s2io_device_state_t
@@ -885,6 +908,27 @@
 	 */
 	int rx_csum;
 
+	/* Below variables are used for fifo selection to transmit a packet */
+	u16 fifo_selector[MAX_TX_FIFOS];
+
+	/* Total fifos for tcp packets */
+	u8 total_tcp_fifos;
+
+	/*
+	* Beginning index of udp for udp packets
+	* Value will be equal to
+	* (tx_fifo_num - FIFO_UDP_MAX_NUM - FIFO_OTHER_MAX_NUM)
+	*/
+	u8 udp_fifo_idx;
+
+	u8 total_udp_fifos;
+
+	/*
+	 * Beginning index of fifo for all other packets
+	 * Value will be equal to (tx_fifo_num - FIFO_OTHER_MAX_NUM)
+	*/
+	u8 other_fifo_idx;
+
 	/*  after blink, the adapter must be restored with original
 	 *  values.
 	 */
@@ -1087,7 +1131,7 @@
 s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
 		      struct RxD_t *rxdp, struct s2io_nic *sp);
 static void clear_lro_session(struct lro *lro);
-static void queue_rx_frame(struct sk_buff *skb);
+static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag);
 static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro);
 static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
 			   struct sk_buff *skb, u32 tcp_len);
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
deleted file mode 100644
index afd900d..0000000
--- a/drivers/net/sk98lin/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Makefile for the SysKonnect SK-98xx device driver.
-#
-
-
-#
-# Standalone driver params
-# SKPARAM += -DSK_KERNEL_24
-# SKPARAM += -DSK_KERNEL_24_26
-# SKPARAM += -DSK_KERNEL_26
-# SKPARAM += -DSK_KERNEL_22_24
-
-obj-$(CONFIG_SK98LIN) += sk98lin.o
-sk98lin-objs    :=	\
-		skge.o		\
-		skethtool.o	\
-		skdim.o		\
-		skaddr.o	\
-		skgehwt.o	\
-		skgeinit.o	\
-		skgepnmi.o	\
-		skgesirq.o	\
-		ski2c.o		\
-		sklm80.o	\
-		skqueue.o	\
-		skrlmt.o	\
-		sktimer.o	\
-		skvpd.o		\
-		skxmac2.o
-
-# DBGDEF =  \
-# -DDEBUG
-
-ifdef DEBUG
-DBGDEF +=  \
--DSK_DEBUG_CHKMOD=0x00000000L \
--DSK_DEBUG_CHKCAT=0x00000000L
-endif
-
-
-# **** possible debug modules for SK_DEBUG_CHKMOD *****************
-# SK_DBGMOD_MERR        0x00000001L     /* general module error indication */
-# SK_DBGMOD_HWM         0x00000002L     /* Hardware init module */
-# SK_DBGMOD_RLMT        0x00000004L     /* RLMT module */
-# SK_DBGMOD_VPD         0x00000008L     /* VPD module */
-# SK_DBGMOD_I2C         0x00000010L     /* I2C module */
-# SK_DBGMOD_PNMI        0x00000020L     /* PNMI module */
-# SK_DBGMOD_CSUM        0x00000040L     /* CSUM module */
-# SK_DBGMOD_ADDR        0x00000080L     /* ADDR module */
-# SK_DBGMOD_DRV         0x00010000L     /* DRV module */
-
-# **** possible debug categories for SK_DEBUG_CHKCAT **************
-# *** common modules ***
-# SK_DBGCAT_INIT        0x00000001L     module/driver initialization
-# SK_DBGCAT_CTRL        0x00000002L     controlling: add/rmv MCA/MAC and other controls (IOCTL)
-# SK_DBGCAT_ERR         0x00000004L     error handling paths
-# SK_DBGCAT_TX          0x00000008L     transmit path
-# SK_DBGCAT_RX          0x00000010L     receive path
-# SK_DBGCAT_IRQ         0x00000020L     general IRQ handling
-# SK_DBGCAT_QUEUE       0x00000040L     any queue management
-# SK_DBGCAT_DUMP        0x00000080L     large data output e.g. hex dump
-# SK_DBGCAT_FATAL       0x00000100L     large data output e.g. hex dump
-
-# *** driver (file skge.c) ***
-# SK_DBGCAT_DRV_ENTRY           0x00010000      entry points
-# SK_DBGCAT_DRV_???             0x00020000      not used
-# SK_DBGCAT_DRV_MCA             0x00040000      multicast
-# SK_DBGCAT_DRV_TX_PROGRESS     0x00080000      tx path
-# SK_DBGCAT_DRV_RX_PROGRESS     0x00100000      rx path
-# SK_DBGCAT_DRV_PROGRESS        0x00200000      general runtime
-# SK_DBGCAT_DRV_???             0x00400000      not used
-# SK_DBGCAT_DRV_PROM            0x00800000      promiscuous mode
-# SK_DBGCAT_DRV_TX_FRAME        0x01000000      display tx frames
-# SK_DBGCAT_DRV_ERROR           0x02000000      error conditions
-# SK_DBGCAT_DRV_INT_SRC         0x04000000      interrupts sources
-# SK_DBGCAT_DRV_EVENT           0x08000000      driver events
-
-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
-
-clean:
-	rm -f core *.o *.a *.s
-
-
-
-
-
-
diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
deleted file mode 100644
index 4e2dbbf..0000000
--- a/drivers/net/sk98lin/h/lm80.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name:	lm80.h	
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.6 $
- * Date:	$Date: 2003/05/13 17:26:52 $
- * Purpose:	Contains all defines for the LM80 Chip
- *		(National Semiconductor).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_LM80_H
-#define __INC_LM80_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * LM80 register definition
- *
- * All registers are 8 bit wide
- */
-#define LM80_CFG			0x00	/* Configuration Register */
-#define LM80_ISRC_1			0x01	/* Interrupt Status Register 1 */
-#define LM80_ISRC_2			0x02	/* Interrupt Status Register 2 */
-#define LM80_IMSK_1			0x03	/* Interrupt Mask Register 1 */
-#define LM80_IMSK_2			0x04	/* Interrupt Mask Register 2 */
-#define LM80_FAN_CTRL		0x05	/* Fan Devisor/RST#/OS# Register */
-#define LM80_TEMP_CTRL		0x06	/* OS# Config, Temp Res. Reg */
-	/* 0x07 - 0x1f reserved	*/
-	/* current values */
-#define LM80_VT0_IN			0x20	/* current Voltage 0 value */
-#define LM80_VT1_IN			0x21	/* current Voltage 1 value */
-#define LM80_VT2_IN			0x22	/* current Voltage 2 value */
-#define LM80_VT3_IN			0x23	/* current Voltage 3 value */
-#define LM80_VT4_IN			0x24	/* current Voltage 4 value */
-#define LM80_VT5_IN			0x25	/* current Voltage 5 value */
-#define LM80_VT6_IN			0x26	/* current Voltage 6 value */
-#define LM80_TEMP_IN		0x27	/* current Temperature value */
-#define LM80_FAN1_IN		0x28	/* current Fan 1 count */
-#define LM80_FAN2_IN		0x29	/* current Fan 2 count */
-	/* limit values */
-#define LM80_VT0_HIGH_LIM	0x2a	/* high limit val for Voltage 0 */
-#define LM80_VT0_LOW_LIM	0x2b	/* low limit val for Voltage 0 */
-#define LM80_VT1_HIGH_LIM	0x2c	/* high limit val for Voltage 1 */
-#define LM80_VT1_LOW_LIM	0x2d	/* low limit val for Voltage 1 */
-#define LM80_VT2_HIGH_LIM	0x2e	/* high limit val for Voltage 2 */
-#define LM80_VT2_LOW_LIM	0x2f	/* low limit val for Voltage 2 */
-#define LM80_VT3_HIGH_LIM	0x30	/* high limit val for Voltage 3 */
-#define LM80_VT3_LOW_LIM	0x31	/* low limit val for Voltage 3 */
-#define LM80_VT4_HIGH_LIM	0x32	/* high limit val for Voltage 4 */
-#define LM80_VT4_LOW_LIM	0x33	/* low limit val for Voltage 4 */
-#define LM80_VT5_HIGH_LIM	0x34	/* high limit val for Voltage 5 */
-#define LM80_VT5_LOW_LIM	0x35	/* low limit val for Voltage 5 */
-#define LM80_VT6_HIGH_LIM	0x36	/* high limit val for Voltage 6 */
-#define LM80_VT6_LOW_LIM	0x37	/* low limit val for Voltage 6 */
-#define LM80_THOT_LIM_UP	0x38	/* hot temperature limit (high) */
-#define LM80_THOT_LIM_LO	0x39	/* hot temperature limit (low) */
-#define LM80_TOS_LIM_UP		0x3a	/* OS temperature limit (high) */
-#define LM80_TOS_LIM_LO		0x3b	/* OS temperature limit (low) */
-#define LM80_FAN1_COUNT_LIM	0x3c	/* Fan 1 count limit (high) */
-#define LM80_FAN2_COUNT_LIM	0x3d	/* Fan 2 count limit (low) */
-	/* 0x3e - 0x3f reserved	*/
-
-/*
- * LM80 bit definitions
- */
-
-/*	LM80_CFG		Configuration Register */
-#define LM80_CFG_START		(1<<0)	/* start monitoring operation */
-#define LM80_CFG_INT_ENA	(1<<1)	/* enables the INT# Interrupt output */
-#define LM80_CFG_INT_POL	(1<<2)	/* INT# pol: 0 act low, 1 act high */
-#define LM80_CFG_INT_CLR	(1<<3)	/* disables INT#/RST_OUT#/OS# outputs */
-#define LM80_CFG_RESET		(1<<4)	/* signals a reset */
-#define LM80_CFG_CHASS_CLR	(1<<5)	/* clears Chassis Intrusion (CI) pin */
-#define LM80_CFG_GPO		(1<<6)	/* drives the GPO# pin */
-#define LM80_CFG_INIT		(1<<7)	/* restore power on defaults */
-
-/*	LM80_ISRC_1		Interrupt Status Register 1 */
-/*	LM80_IMSK_1		Interrupt Mask Register 1 */
-#define LM80_IS_VT0			(1<<0)	/* limit exceeded for Voltage 0 */
-#define LM80_IS_VT1			(1<<1)	/* limit exceeded for Voltage 1 */
-#define LM80_IS_VT2			(1<<2)	/* limit exceeded for Voltage 2 */
-#define LM80_IS_VT3			(1<<3)	/* limit exceeded for Voltage 3 */
-#define LM80_IS_VT4			(1<<4)	/* limit exceeded for Voltage 4 */
-#define LM80_IS_VT5			(1<<5)	/* limit exceeded for Voltage 5 */
-#define LM80_IS_VT6			(1<<6)	/* limit exceeded for Voltage 6 */
-#define LM80_IS_INT_IN		(1<<7)	/* state of INT_IN# */
-
-/*	LM80_ISRC_2		Interrupt Status Register 2 */
-/*	LM80_IMSK_2		Interrupt Mask Register 2 */
-#define LM80_IS_TEMP		(1<<0)	/* HOT temperature limit exceeded */
-#define LM80_IS_BTI			(1<<1)	/* state of BTI# pin */
-#define LM80_IS_FAN1		(1<<2)	/* count limit exceeded for Fan 1 */
-#define LM80_IS_FAN2		(1<<3)	/* count limit exceeded for Fan 2 */
-#define LM80_IS_CI			(1<<4)	/* Chassis Intrusion occured */
-#define LM80_IS_OS			(1<<5)	/* OS temperature limit exceeded */
-	/* bit 6 and 7 are reserved in LM80_ISRC_2 */
-#define LM80_IS_HT_IRQ_MD	(1<<6)	/* Hot temperature interrupt mode */
-#define LM80_IS_OT_IRQ_MD	(1<<7)	/* OS temperature interrupt mode */
-
-/*	LM80_FAN_CTRL		Fan Devisor/RST#/OS# Register */
-#define LM80_FAN1_MD_SEL	(1<<0)	/* Fan 1 mode select */
-#define LM80_FAN2_MD_SEL	(1<<1)	/* Fan 2 mode select */
-#define LM80_FAN1_PRM_CTL	(3<<2)	/* Fan 1 speed control */
-#define LM80_FAN2_PRM_CTL	(3<<4)	/* Fan 2 speed control */
-#define LM80_FAN_OS_ENA		(1<<6)	/* enable OS mode on RST_OUT#/OS# pins*/
-#define LM80_FAN_RST_ENA	(1<<7)	/* sets RST_OUT#/OS# pins in RST mode */
-
-/*	LM80_TEMP_CTRL		OS# Config, Temp Res. Reg */
-#define LM80_TEMP_OS_STAT	(1<<0)	/* mirrors the state of RST_OUT#/OS# */
-#define LM80_TEMP_OS_POL	(1<<1)	/* select OS# polarity */
-#define LM80_TEMP_OS_MODE	(1<<2)	/* selects Interrupt mode */
-#define LM80_TEMP_RES		(1<<3)	/* selects 9 or 11 bit temp resulution*/
-#define LM80_TEMP_LSB		(0xf<<4)/* 4 LSBs of 11 bit temp data */
-#define LM80_TEMP_LSB_9		(1<<7)	/* LSB of 9 bit temperature data */
-
-	/* 0x07 - 0x1f reserved	*/
-/*	LM80_VT0_IN		current Voltage 0 value */
-/*	LM80_VT1_IN		current Voltage 1 value */
-/*	LM80_VT2_IN		current Voltage 2 value */
-/*	LM80_VT3_IN		current Voltage 3 value */
-/*	LM80_VT4_IN		current Voltage 4 value */
-/*	LM80_VT5_IN		current Voltage 5 value */
-/*	LM80_VT6_IN		current Voltage 6 value */
-/*	LM80_TEMP_IN		current temperature value */
-/*	LM80_FAN1_IN		current Fan 1 count */
-/*	LM80_FAN2_IN		current Fan 2 count */
-/*	LM80_VT0_HIGH_LIM	high limit val for Voltage 0 */
-/*	LM80_VT0_LOW_LIM	low limit val for Voltage 0 */
-/*	LM80_VT1_HIGH_LIM	high limit val for Voltage 1 */
-/*	LM80_VT1_LOW_LIM	low limit val for Voltage 1 */
-/*	LM80_VT2_HIGH_LIM	high limit val for Voltage 2 */
-/*	LM80_VT2_LOW_LIM	low limit val for Voltage 2 */
-/*	LM80_VT3_HIGH_LIM	high limit val for Voltage 3 */
-/*	LM80_VT3_LOW_LIM	low limit val for Voltage 3 */
-/*	LM80_VT4_HIGH_LIM	high limit val for Voltage 4 */
-/*	LM80_VT4_LOW_LIM	low limit val for Voltage 4 */
-/*	LM80_VT5_HIGH_LIM	high limit val for Voltage 5 */
-/*	LM80_VT5_LOW_LIM	low limit val for Voltage 5 */
-/*	LM80_VT6_HIGH_LIM	high limit val for Voltage 6 */
-/*	LM80_VT6_LOW_LIM	low limit val for Voltage 6 */
-/*	LM80_THOT_LIM_UP	hot temperature limit (high) */
-/*	LM80_THOT_LIM_LO	hot temperature limit (low) */
-/*	LM80_TOS_LIM_UP		OS temperature limit (high) */
-/*	LM80_TOS_LIM_LO		OS temperature limit (low) */
-/*	LM80_FAN1_COUNT_LIM	Fan 1 count limit (high) */
-/*	LM80_FAN2_COUNT_LIM	Fan 2 count limit (low) */
-	/* 0x3e - 0x3f reserved	*/
-
-#define LM80_ADDR		0x28	/* LM80 default addr */
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_LM80_H */
diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
deleted file mode 100644
index 423ad06..0000000
--- a/drivers/net/sk98lin/h/skaddr.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/******************************************************************************
- *
- * Name:	skaddr.h
- * Project:	Gigabit Ethernet Adapters, ADDR-Modul
- * Version:	$Revision: 1.29 $
- * Date:	$Date: 2003/05/13 16:57:24 $
- * Purpose:	Header file for Address Management (MC, UC, Prom).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses and promiscuous mode
- * on GEnesis adapters.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	...
- *	"sktypes.h"
- *	"skqueue.h"
- *	"skaddr.h"
- *	...
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKADDR_H
-#define __INC_SKADDR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_MAC_ADDR_LEN				6	/* Length of MAC address. */
-#define	SK_MAX_ADDRS				14	/* #Addrs for exact match. */
-
-/* ----- Common return values ----- */
-
-#define SK_ADDR_SUCCESS				0	/* Function returned successfully. */
-#define SK_ADDR_ILLEGAL_PORT			100	/* Port number too high. */
-#define SK_ADDR_TOO_EARLY			101	/* Function called too early. */
-
-/* ----- Clear/Add flag bits ----- */
-
-#define SK_ADDR_PERMANENT			1	/* RLMT Address */
-
-/* ----- Additional Clear flag bits ----- */
-
-#define SK_MC_SW_ONLY				2	/* Do not update HW when clearing. */
-
-/* ----- Override flag bits ----- */
-
-#define SK_ADDR_LOGICAL_ADDRESS		0
-#define SK_ADDR_VIRTUAL_ADDRESS		(SK_ADDR_LOGICAL_ADDRESS)	/* old */
-#define SK_ADDR_PHYSICAL_ADDRESS	1
-#define SK_ADDR_CLEAR_LOGICAL		2
-#define SK_ADDR_SET_LOGICAL			4
-
-/* ----- Override return values ----- */
-
-#define SK_ADDR_OVERRIDE_SUCCESS	(SK_ADDR_SUCCESS)
-#define SK_ADDR_DUPLICATE_ADDRESS	1
-#define SK_ADDR_MULTICAST_ADDRESS	2
-
-/* ----- Partitioning of excact match table ----- */
-
-#define SK_ADDR_EXACT_MATCHES		16	/* #Exact match entries. */
-
-#define SK_ADDR_FIRST_MATCH_RLMT	1
-#define SK_ADDR_LAST_MATCH_RLMT		2
-#define SK_ADDR_FIRST_MATCH_DRV		3
-#define SK_ADDR_LAST_MATCH_DRV		(SK_ADDR_EXACT_MATCHES - 1)
-
-/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
-
-#define SK_MC_FILTERING_EXACT		0	/* Exact filtering. */
-#define SK_MC_FILTERING_INEXACT		1	/* Inexact filtering. */
-
-/* ----- Additional SkAddrMcAdd return values ----- */
-
-#define SK_MC_ILLEGAL_ADDRESS		2	/* Illegal address. */
-#define SK_MC_ILLEGAL_PORT			3	/* Illegal port (not the active one). */
-#define SK_MC_RLMT_OVERFLOW			4	/* Too many RLMT mc addresses. */
-
-/* Promiscuous mode bits ----- */
-
-#define SK_PROM_MODE_NONE			0	/* Normal receive. */
-#define SK_PROM_MODE_LLC			1	/* Receive all LLC frames. */
-#define SK_PROM_MODE_ALL_MC			2	/* Receive all multicast frames. */
-/* #define SK_PROM_MODE_NON_LLC		4 */	/* Receive all non-LLC frames. */
-
-/* Macros */
-
-#ifdef OLD_STUFF
-#ifndef SK_ADDR_EQUAL
-/*
- * "&" instead of "&&" allows better optimization on IA-64.
- * The replacement is safe here, as all bytes exist.
- */
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
-	(((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
-	(((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
-	(((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
-	(((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
-	(((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
-#else	/* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
-	(*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
-#endif	/* SK_ADDR_DWORD_COMPARE */
-#endif	/* SK_ADDR_EQUAL */
-#endif /* 0 */
-
-#ifndef SK_ADDR_EQUAL
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
-	(((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
-	(((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
-	(((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
-	(((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
-	(((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
-#else	/* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
-	*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
-	(*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
-	*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
-#endif	/* SK_ADDR_DWORD_COMPARE */
-#endif	/* SK_ADDR_EQUAL */
-
-/* typedefs *******************************************************************/
-
-typedef struct s_MacAddr {
-	SK_U8	a[SK_MAC_ADDR_LEN];
-} SK_MAC_ADDR;
-
-
-/* SK_FILTER is used to ensure alignment of the filter. */
-typedef union s_InexactFilter {
-	SK_U8	Bytes[8];
-	SK_U64	Val;	/* Dummy entry for alignment only. */
-} SK_FILTER64;
-
-
-typedef struct s_AddrNet SK_ADDR_NET;
-
-
-typedef struct s_AddrPort {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_MAC_ADDR	CurrentMacAddress;	/* Current physical MAC Address. */
-	SK_MAC_ADDR	PermanentMacAddress;	/* Permanent physical MAC Address. */
-	int		PromMode;		/* Promiscuous Mode. */
-
-/* ----- Private part ----- */
-
-	SK_MAC_ADDR	PreviousMacAddress;	/* Prev. phys. MAC Address. */
-	SK_BOOL		CurrentMacAddressSet;	/* CurrentMacAddress is set. */
-	SK_U8		Align01;
-
-	SK_U32		FirstExactMatchRlmt;
-	SK_U32		NextExactMatchRlmt;
-	SK_U32		FirstExactMatchDrv;
-	SK_U32		NextExactMatchDrv;
-	SK_MAC_ADDR	Exact[SK_ADDR_EXACT_MATCHES];
-	SK_FILTER64	InexactFilter;			/* For 64-bit hash register. */
-	SK_FILTER64	InexactRlmtFilter;		/* For 64-bit hash register. */
-	SK_FILTER64	InexactDrvFilter;		/* For 64-bit hash register. */
-} SK_ADDR_PORT;
-
-
-struct s_AddrNet {
-/* ----- Public part (read-only) ----- */
-
-	SK_MAC_ADDR		CurrentMacAddress;	/* Logical MAC Address. */
-	SK_MAC_ADDR		PermanentMacAddress;	/* Logical MAC Address. */
-
-/* ----- Private part ----- */
-
-	SK_U32			ActivePort;		/* View of module ADDR. */
-	SK_BOOL			CurrentMacAddressSet;	/* CurrentMacAddress is set. */
-	SK_U8			Align01;
-	SK_U16			Align02;
-};
-
-
-typedef struct s_Addr {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_ADDR_NET		Net[SK_MAX_NETS];
-	SK_ADDR_PORT	Port[SK_MAX_MACS];
-
-/* ----- Private part ----- */
-} SK_ADDR;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkAddr */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern	int	SkAddrInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int	Level);
-
-extern	int	SkAddrMcClear(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber,
-	int	Flags);
-
-extern	int	SkAddrMcAdd(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		PortNumber,
-	SK_MAC_ADDR	*pMc,
-	int		Flags);
-
-extern	int	SkAddrMcUpdate(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber);
-
-extern	int	SkAddrOverride(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		PortNumber,
-	SK_MAC_ADDR	SK_FAR *pNewAddr,
-	int		Flags);
-
-extern	int	SkAddrPromiscuousChange(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber,
-	int	NewPromMode);
-
-#ifndef SK_SLIM
-extern	int	SkAddrSwap(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	FromPortNumber,
-	SK_U32	ToPortNumber);
-#endif
-
-#else	/* defined(SK_KR_PROTO)) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style prototypes are not yet provided.
-
-#endif	/* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKADDR_H */
diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
deleted file mode 100644
index 6e256bd..0000000
--- a/drivers/net/sk98lin/h/skcsum.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/******************************************************************************
- *
- * Name:	skcsum.h
- * Project:	GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/08/20 13:59:57 $
- * Purpose:	Store/verify Internet checksum in send/receive packets.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2001 SysKonnect GmbH.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * Public header file for the "GEnesis" common module "CSUM".
- *
- * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
- * and is the code name of this SysKonnect project.
- *
- * Compilation Options:
- *
- *	SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
- *	empty module.
- *
- *	SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
- *	definitions. In this case, all SKCS_PROTO_xxx definitions must be made
- *	external.
- *
- *	SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
- *	definitions. In this case, all SKCS_STATUS_xxx definitions must be made
- *	external.
- *
- * Include File Hierarchy:
- *
- *	"h/skcsum.h"
- *	 "h/sktypes.h"
- *	 "h/skqueue.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKCSUM_H
-#define __INC_SKCSUM_H
-
-#include "h/sktypes.h"
-#include "h/skqueue.h"
-
-/* defines ********************************************************************/
-
-/*
- * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags'  if no user
- * overwrite.
- */
-#ifndef SKCS_OVERWRITE_PROTO	/* User overwrite? */
-#define SKCS_PROTO_IP	0x1	/* IP (Internet Protocol version 4) */
-#define SKCS_PROTO_TCP	0x2	/* TCP (Transmission Control Protocol) */
-#define SKCS_PROTO_UDP	0x4	/* UDP (User Datagram Protocol) */
-
-/* Indices for protocol statistics. */
-#define SKCS_PROTO_STATS_IP	0
-#define SKCS_PROTO_STATS_UDP	1
-#define SKCS_PROTO_STATS_TCP	2
-#define SKCS_NUM_PROTOCOLS	3	/* Number of supported protocols. */
-#endif	/* !SKCS_OVERWRITE_PROTO */
-
-/*
- * Define the default SKCS_STATUS type and values if no user overwrite.
- *
- *	SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
- *	SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
- *	SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
- *	SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
- *	SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
- *	SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
- *	SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
- *	SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
- *	SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
- *	SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
- *	SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. 
- */
-#ifndef SKCS_OVERWRITE_STATUS	/* User overwrite? */
-#define SKCS_STATUS	int	/* Define status type. */
-
-#define SKCS_STATUS_UNKNOWN_IP_VERSION	1
-#define SKCS_STATUS_IP_CSUM_ERROR		2
-#define SKCS_STATUS_IP_FRAGMENT			3
-#define SKCS_STATUS_IP_CSUM_OK			4
-#define SKCS_STATUS_TCP_CSUM_ERROR		5
-#define SKCS_STATUS_UDP_CSUM_ERROR		6
-#define SKCS_STATUS_TCP_CSUM_OK			7
-#define SKCS_STATUS_UDP_CSUM_OK			8
-/* needed for Microsoft */
-#define SKCS_STATUS_IP_CSUM_ERROR_UDP	9
-#define SKCS_STATUS_IP_CSUM_ERROR_TCP	10
-/* UDP checksum may be omitted */
-#define SKCS_STATUS_IP_CSUM_OK_NO_UDP	11
-#endif	/* !SKCS_OVERWRITE_STATUS */
-
-/* Clear protocol statistics event. */
-#define SK_CSUM_EVENT_CLEAR_PROTO_STATS	1
-
-/*
- * Add two values in one's complement.
- *
- * Note: One of the two input values may be "longer" than 16-bit, but then the
- * resulting sum may be 17 bits long. In this case, add zero to the result using
- * SKCS_OC_ADD() again.
- *
- *	Result = Value1 + Value2
- */
-#define SKCS_OC_ADD(Result, Value1, Value2) {				\
-	unsigned long Sum;						\
-									\
-	Sum = (unsigned long) (Value1) + (unsigned long) (Value2);	\
-	/* Add-in any carry. */						\
-	(Result) = (Sum & 0xffff) + (Sum >> 16);			\
-}
-
-/*
- * Subtract two values in one's complement.
- *
- *	Result = Value1 - Value2
- */
-#define SKCS_OC_SUB(Result, Value1, Value2)	\
-	SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
-
-/* typedefs *******************************************************************/
-
-/*
- * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
- *
- * There is one instance of this structure for each protocol supported.
- */
-typedef struct s_CsProtocolStatistics {
-	SK_U64 RxOkCts;		/* Receive checksum ok. */
-	SK_U64 RxUnableCts;	/* Unable to verify receive checksum. */
-	SK_U64 RxErrCts;	/* Receive checksum error. */
-	SK_U64 TxOkCts;		/* Transmit checksum ok. */
-	SK_U64 TxUnableCts;	/* Unable to calculate checksum in hw. */
-} SKCS_PROTO_STATS;
-
-/*
- * s_Csum - The CSUM module context structure.
- */
-typedef struct s_Csum {
-	/* Enabled receive SK_PROTO_XXX bit flags. */
-	unsigned ReceiveFlags[SK_MAX_NETS];
-#ifdef TX_CSUM
-	unsigned TransmitFlags[SK_MAX_NETS];
-#endif /* TX_CSUM */
-
-	/* The protocol statistics structure; one per supported protocol. */
-	SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
-} SK_CSUM;
-
-/*
- * SKCS_PACKET_INFO - The packet information structure.
- */
-typedef struct s_CsPacketInfo {
-	/* Bit field specifiying the desired/found protocols. */
-	unsigned ProtocolFlags;
-
-	/* Length of complete IP header, including any option fields. */
-	unsigned IpHeaderLength;
-
-	/* IP header checksum. */
-	unsigned IpHeaderChecksum;
-
-	/* TCP/UDP pseudo header checksum. */
-	unsigned PseudoHeaderChecksum;
-} SKCS_PACKET_INFO;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_CS_CALCULATE_CHECKSUM
-extern unsigned SkCsCalculateChecksum(
-	void		*pData,
-	unsigned	Length);
-#endif /* SK_CS_CALCULATE_CHECKSUM */
-
-extern int SkCsEvent(
-	SK_AC		*pAc,
-	SK_IOC		Ioc,
-	SK_U32		Event,
-	SK_EVPARA	Param);
-
-extern SKCS_STATUS SkCsGetReceiveInfo(
-	SK_AC		*pAc,
-	void		*pIpHeader,
-	unsigned	Checksum1,
-	unsigned	Checksum2,
-	int			NetNumber);
-
-extern void SkCsSetReceiveFlags(
-	SK_AC		*pAc,
-	unsigned	ReceiveFlags,
-	unsigned	*pChecksum1Offset,
-	unsigned	*pChecksum2Offset,
-	int			NetNumber);
-
-#endif	/* __INC_SKCSUM_H */
diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
deleted file mode 100644
index 3cba171..0000000
--- a/drivers/net/sk98lin/h/skdebug.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdebug.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/05/13 17:26:00 $
- * Purpose:	SK specific DEBUG support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDEBUG_H
-#define __INC_SKDEBUG_H
-
-#ifdef	DEBUG
-#ifndef SK_DBG_MSG
-#define SK_DBG_MSG(pAC,comp,cat,arg) \
-		if ( ((comp) & SK_DBG_CHKMOD(pAC)) && 	\
-		      ((cat) & SK_DBG_CHKCAT(pAC)) ) { 	\
-			SK_DBG_PRINTF arg ;		\
-		}
-#endif
-#else
-#define SK_DBG_MSG(pAC,comp,lev,arg)
-#endif
-
-/* PLS NOTE:
- * =========
- * Due to any restrictions of kernel printf routines do not use other
- * format identifiers as: %x %d %c %s .
- * Never use any combined format identifiers such as: %lx %ld in your
- * printf - argument (arg) because some OS specific kernel printfs may
- * only support some basic identifiers.
- */
-
-/* Debug modules */
-
-#define SK_DBGMOD_MERR	0x00000001L	/* general module error indication */
-#define SK_DBGMOD_HWM	0x00000002L	/* Hardware init module */
-#define SK_DBGMOD_RLMT	0x00000004L	/* RLMT module */
-#define SK_DBGMOD_VPD	0x00000008L	/* VPD module */
-#define SK_DBGMOD_I2C	0x00000010L	/* I2C module */
-#define SK_DBGMOD_PNMI	0x00000020L	/* PNMI module */
-#define SK_DBGMOD_CSUM	0x00000040L	/* CSUM module */
-#define SK_DBGMOD_ADDR	0x00000080L	/* ADDR module */
-#define SK_DBGMOD_PECP	0x00000100L	/* PECP module */
-#define SK_DBGMOD_POWM	0x00000200L	/* Power Management module */
-
-/* Debug events */
-
-#define SK_DBGCAT_INIT	0x00000001L	/* module/driver initialization */
-#define SK_DBGCAT_CTRL	0x00000002L	/* controlling devices */
-#define SK_DBGCAT_ERR	0x00000004L	/* error handling paths */
-#define SK_DBGCAT_TX	0x00000008L	/* transmit path */
-#define SK_DBGCAT_RX	0x00000010L	/* receive path */
-#define SK_DBGCAT_IRQ	0x00000020L	/* general IRQ handling */
-#define SK_DBGCAT_QUEUE	0x00000040L	/* any queue management */
-#define SK_DBGCAT_DUMP	0x00000080L	/* large data output e.g. hex dump */
-#define SK_DBGCAT_FATAL	0x00000100L	/* fatal error */
-
-#endif	/* __INC_SKDEBUG_H */
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
deleted file mode 100644
index 91b8d4f..0000000
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdrv1st.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.4 $
- * Date:	$Date: 2003/11/12 14:28:14 $
- * Purpose:	First header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the first include file of the driver, which includes all
- * neccessary system header files and some of the GEnesis header files.
- * It also defines some basic items.
- *
- * Include File Hierarchy:
- *
- *	see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#define __INC_SKDRV1ST_H
-
-typedef struct s_AC	SK_AC;
-
-/* Set card versions */
-#define SK_FAR
-
-/* override some default functions with optimized linux functions */
-
-#define SK_PNMI_STORE_U16(p,v)		memcpy((char*)(p),(char*)&(v),2)
-#define SK_PNMI_STORE_U32(p,v)		memcpy((char*)(p),(char*)&(v),4)
-#define SK_PNMI_STORE_U64(p,v)		memcpy((char*)(p),(char*)&(v),8)
-#define SK_PNMI_READ_U16(p,v)		memcpy((char*)&(v),(char*)(p),2)
-#define SK_PNMI_READ_U32(p,v)		memcpy((char*)&(v),(char*)(p),4)
-#define SK_PNMI_READ_U64(p,v)		memcpy((char*)&(v),(char*)(p),8)
-
-#define SK_ADDR_EQUAL(a1,a2)		(!memcmp(a1,a2,6))
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-
-#define SK_CS_CALCULATE_CHECKSUM
-#ifndef CONFIG_X86_64
-#define SkCsCalculateChecksum(p,l)	((~ip_compute_csum(p, l)) & 0xffff)
-#else
-#define SkCsCalculateChecksum(p,l)	((~ip_fast_csum(p, l)) & 0xffff)
-#endif
-
-#include	"h/sktypes.h"
-#include	"h/skerror.h"
-#include	"h/skdebug.h"
-#include	"h/lm80.h"
-#include	"h/xmac_ii.h"
-
-#ifdef __LITTLE_ENDIAN
-#define SK_LITTLE_ENDIAN
-#else
-#define SK_BIG_ENDIAN
-#endif
-
-#define SK_NET_DEVICE	net_device
-
-
-/* we use gethrtime(), return unit: nanoseconds */
-#define SK_TICKS_PER_SEC	100
-
-#define	SK_MEM_MAPPED_IO
-
-// #define SK_RLMT_SLOW_LOOKAHEAD
-
-#define SK_MAX_MACS		2
-#define SK_MAX_NETS		2
-
-#define SK_IOC			char __iomem *
-
-typedef struct s_DrvRlmtMbuf SK_MBUF;
-
-#define	SK_CONST64	INT64_C
-#define	SK_CONSTU64	UINT64_C
-
-#define SK_MEMCPY(dest,src,size)	memcpy(dest,src,size)
-#define SK_MEMCMP(s1,s2,size)		memcmp(s1,s2,size)
-#define SK_MEMSET(dest,val,size)	memset(dest,val,size)
-#define SK_STRLEN(pStr)			strlen((char*)(pStr))
-#define SK_STRNCPY(pDest,pSrc,size)	strncpy((char*)(pDest),(char*)(pSrc),size)
-#define SK_STRCMP(pStr1,pStr2)		strcmp((char*)(pStr1),(char*)(pStr2))
-
-/* macros to access the adapter */
-#define SK_OUT8(b,a,v)		writeb((v), ((b)+(a)))	
-#define SK_OUT16(b,a,v)		writew((v), ((b)+(a)))	
-#define SK_OUT32(b,a,v)		writel((v), ((b)+(a)))	
-#define SK_IN8(b,a,pv)		(*(pv) = readb((b)+(a)))
-#define SK_IN16(b,a,pv)		(*(pv) = readw((b)+(a)))
-#define SK_IN32(b,a,pv)		(*(pv) = readl((b)+(a)))
-
-#define int8_t		char
-#define int16_t		short
-#define int32_t		long
-#define int64_t		long long
-#define uint8_t		u_char
-#define uint16_t	u_short
-#define uint32_t	u_long
-#define uint64_t	unsigned long long
-#define t_scalar_t	int
-#define t_uscalar_t	unsigned int
-#define uintptr_t	unsigned long
-
-#define __CONCAT__(A,B) A##B
-
-#define INT32_C(a)		__CONCAT__(a,L)
-#define INT64_C(a)		__CONCAT__(a,LL)
-#define UINT32_C(a)		__CONCAT__(a,UL)
-#define UINT64_C(a)		__CONCAT__(a,ULL)
-
-#ifdef DEBUG
-#define SK_DBG_PRINTF		printk
-#ifndef SK_DEBUG_CHKMOD
-#define SK_DEBUG_CHKMOD		0
-#endif
-#ifndef SK_DEBUG_CHKCAT
-#define SK_DEBUG_CHKCAT		0
-#endif
-/* those come from the makefile */
-#define SK_DBG_CHKMOD(pAC)	(SK_DEBUG_CHKMOD)
-#define SK_DBG_CHKCAT(pAC)	(SK_DEBUG_CHKCAT)
-
-extern void SkDbgPrintf(const char *format,...);
-
-#define SK_DBGMOD_DRV			0x00010000
-
-/**** possible driver debug categories ********************************/
-#define SK_DBGCAT_DRV_ENTRY		0x00010000
-#define SK_DBGCAT_DRV_SAP		0x00020000
-#define SK_DBGCAT_DRV_MCA		0x00040000
-#define SK_DBGCAT_DRV_TX_PROGRESS	0x00080000
-#define SK_DBGCAT_DRV_RX_PROGRESS	0x00100000
-#define SK_DBGCAT_DRV_PROGRESS		0x00200000
-#define SK_DBGCAT_DRV_MSG		0x00400000
-#define SK_DBGCAT_DRV_PROM		0x00800000
-#define SK_DBGCAT_DRV_TX_FRAME		0x01000000
-#define SK_DBGCAT_DRV_ERROR		0x02000000
-#define SK_DBGCAT_DRV_INT_SRC		0x04000000
-#define SK_DBGCAT_DRV_EVENT		0x08000000
-
-#endif
-
-#define SK_ERR_LOG		SkErrorLog
-
-extern void SkErrorLog(SK_AC*, int, int, char*);
-
-#endif
-
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
deleted file mode 100644
index 3fa6717..0000000
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdrv2nd.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/12/11 16:04:45 $
- * Purpose:	Second header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the second include file of the driver, which includes all other
- * neccessary files and defines all structures and constants used by the
- * driver and the common modules.
- *
- * Include File Hierarchy:
- *
- *	see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV2ND_H
-#define __INC_SKDRV2ND_H
-
-#include "h/skqueue.h"
-#include "h/skgehwt.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skgepnmi.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skaddr.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skrlmt.h"
-#include "h/skgedrv.h"
-
-
-extern SK_MBUF		*SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
-extern void		SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
-extern SK_U64		SkOsGetTime(SK_AC*);
-extern int		SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
-extern int		SkPciReadCfgWord(SK_AC*, int, SK_U16*);
-extern int		SkPciReadCfgByte(SK_AC*, int, SK_U8*);
-extern int		SkPciWriteCfgWord(SK_AC*, int, SK_U16);
-extern int		SkPciWriteCfgByte(SK_AC*, int, SK_U8);
-extern int		SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
-
-#ifdef SK_DIAG_SUPPORT
-extern int		SkDrvEnterDiagMode(SK_AC *pAc);
-extern int		SkDrvLeaveDiagMode(SK_AC *pAc);
-#endif
-
-struct s_DrvRlmtMbuf {
-	SK_MBUF		*pNext;		/* Pointer to next RLMT Mbuf. */
-	SK_U8		*pData;		/* Data buffer (virtually contig.). */
-	unsigned	Size;		/* Data buffer size. */
-	unsigned	Length;		/* Length of packet (<= Size). */
-	SK_U32		PortIdx;	/* Receiving/transmitting port. */
-#ifdef SK_RLMT_MBUF_PRIVATE
-	SK_RLMT_MBUF	Rlmt;		/* Private part for RLMT. */
-#endif  /* SK_RLMT_MBUF_PRIVATE */
-	struct sk_buff	*pOs;		/* Pointer to message block */
-};
-
-
-/*
- * Time macros
- */
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t)	((((unsigned long)t) * 100) / \
-										(SK_TICKS_PER_SEC))
-#endif
-
-/*
- * New SkOsGetTime
- */
-#define SkOsGetTimeCurrent(pAC, pUsec) {\
-	struct timeval t;\
-	do_gettimeofday(&t);\
-	*pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
-}
-
-
-/*
- * ioctl definitions
- */
-#define		SK_IOCTL_BASE		(SIOCDEVPRIVATE)
-#define		SK_IOCTL_GETMIB		(SK_IOCTL_BASE + 0)
-#define		SK_IOCTL_SETMIB		(SK_IOCTL_BASE + 1)
-#define		SK_IOCTL_PRESETMIB	(SK_IOCTL_BASE + 2)
-#define		SK_IOCTL_GEN		(SK_IOCTL_BASE + 3)
-#define		SK_IOCTL_DIAG		(SK_IOCTL_BASE + 4)
-
-typedef struct s_IOCTL	SK_GE_IOCTL;
-
-struct s_IOCTL {
-	char __user *	pData;
-	unsigned int	Len;
-};
-
-
-/*
- * define sizes of descriptor rings in bytes
- */
-
-#define		TX_RING_SIZE	(8*1024)
-#define		RX_RING_SIZE	(24*1024)
-
-/*
- * Buffer size for ethernet packets
- */
-#define	ETH_BUF_SIZE	1540
-#define	ETH_MAX_MTU	1514
-#define ETH_MIN_MTU	60
-#define ETH_MULTICAST_BIT	0x01
-#define SK_JUMBO_MTU	9000
-
-/*
- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
- */
-#define TX_PRIO_LOW	0
-#define TX_PRIO_HIGH	1
-
-/*
- * alignment of rx/tx descriptors
- */
-#define DESCR_ALIGN	64
-
-/*
- * definitions for pnmi. TODO
- */
-#define SK_DRIVER_RESET(pAC, IoC)	0
-#define SK_DRIVER_SENDEVENT(pAC, IoC)	0
-#define SK_DRIVER_SELFTEST(pAC, IoC)	0
-/* For get mtu you must add an own function */
-#define SK_DRIVER_GET_MTU(pAc,IoC,i)	0
-#define SK_DRIVER_SET_MTU(pAc,IoC,i,v)	0
-#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v)	0
-
-/*
-** Interim definition of SK_DRV_TIMER placed in this file until 
-** common modules have been finalized
-*/
-#define SK_DRV_TIMER			11 
-#define	SK_DRV_MODERATION_TIMER		1
-#define SK_DRV_MODERATION_TIMER_LENGTH  1000000  /* 1 second */
-#define SK_DRV_RX_CLEANUP_TIMER		2
-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH	1000000	 /* 100 millisecs */
-
-/*
-** Definitions regarding transmitting frames 
-** any calculating any checksum.
-*/
-#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
-#define C_LEN_ETHERMAC_HEADER_SRC_ADDR  6
-#define C_LEN_ETHERMAC_HEADER_LENTYPE   2
-#define C_LEN_ETHERMAC_HEADER           ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
-                                          (C_LEN_ETHERMAC_HEADER_SRC_ADDR)  + \
-                                          (C_LEN_ETHERMAC_HEADER_LENTYPE) )
-
-#define C_LEN_ETHERMTU_MINSIZE          46
-#define C_LEN_ETHERMTU_MAXSIZE_STD      1500
-#define C_LEN_ETHERMTU_MAXSIZE_JUMBO    9000
-
-#define C_LEN_ETHERNET_MINSIZE          ( (C_LEN_ETHERMAC_HEADER) + \
-                                          (C_LEN_ETHERMTU_MINSIZE) )
-
-#define C_OFFSET_IPHEADER               C_LEN_ETHERMAC_HEADER
-#define C_OFFSET_IPHEADER_IPPROTO       9
-#define C_OFFSET_TCPHEADER_TCPCS        16
-#define C_OFFSET_UDPHEADER_UDPCS        6
-
-#define C_OFFSET_IPPROTO                ( (C_LEN_ETHERMAC_HEADER) + \
-                                          (C_OFFSET_IPHEADER_IPPROTO) )
-
-#define C_PROTO_ID_UDP                  17       /* refer to RFC 790 or Stevens'   */
-#define C_PROTO_ID_TCP                  6        /* TCP/IP illustrated for details */
-
-/* TX and RX descriptors *****************************************************/
-
-typedef struct s_RxD RXD; /* the receive descriptor */
-
-struct s_RxD {
-	volatile SK_U32	RBControl;	/* Receive Buffer Control */
-	SK_U32		VNextRxd;	/* Next receive descriptor,low dword */
-	SK_U32		VDataLow;	/* Receive buffer Addr, low dword */
-	SK_U32		VDataHigh;	/* Receive buffer Addr, high dword */
-	SK_U32		FrameStat;	/* Receive Frame Status word */
-	SK_U32		TimeStamp;	/* Time stamp from XMAC */
-	SK_U32		TcpSums;	/* TCP Sum 2 / TCP Sum 1 */
-	SK_U32		TcpSumStarts;	/* TCP Sum Start 2 / TCP Sum Start 1 */
-	RXD		*pNextRxd;	/* Pointer to next Rxd */
-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
-};
-
-typedef struct s_TxD TXD; /* the transmit descriptor */
-
-struct s_TxD {
-	volatile SK_U32	TBControl;	/* Transmit Buffer Control */
-	SK_U32		VNextTxd;	/* Next transmit descriptor,low dword */
-	SK_U32		VDataLow;	/* Transmit Buffer Addr, low dword */
-	SK_U32		VDataHigh;	/* Transmit Buffer Addr, high dword */
-	SK_U32		FrameStat;	/* Transmit Frame Status Word */
-	SK_U32		TcpSumOfs;	/* Reserved / TCP Sum Offset */
-	SK_U16		TcpSumSt;	/* TCP Sum Start */
-	SK_U16		TcpSumWr;	/* TCP Sum Write */
-	SK_U32		TcpReserved;	/* not used */
-	TXD		*pNextTxd;	/* Pointer to next Txd */
-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
-};
-
-/* Used interrupt bits in the interrupts source register *********************/
-
-#define DRIVER_IRQS	((IS_IRQ_SW)   | \
-			(IS_R1_F)      |(IS_R2_F)  | \
-			(IS_XS1_F)     |(IS_XA1_F) | \
-			(IS_XS2_F)     |(IS_XA2_F))
-
-#define SPECIAL_IRQS	((IS_HW_ERR)   |(IS_I2C_READY)  | \
-			(IS_EXT_REG)   |(IS_TIMINT)     | \
-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)  | \
-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)  | \
-			(IS_MAC1)      |(IS_LNK_SYNC_M1)| \
-			(IS_MAC2)      |(IS_LNK_SYNC_M2)| \
-			(IS_R1_C)      |(IS_R2_C)       | \
-			(IS_XS1_C)     |(IS_XA1_C)      | \
-			(IS_XS2_C)     |(IS_XA2_C))
-
-#define IRQ_MASK	((IS_IRQ_SW)   | \
-			(IS_R1_B)      |(IS_R1_F)     |(IS_R2_B) |(IS_R2_F) | \
-			(IS_XS1_B)     |(IS_XS1_F)    |(IS_XA1_B)|(IS_XA1_F)| \
-			(IS_XS2_B)     |(IS_XS2_F)    |(IS_XA2_B)|(IS_XA2_F)| \
-			(IS_HW_ERR)    |(IS_I2C_READY)| \
-			(IS_EXT_REG)   |(IS_TIMINT)   | \
-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
-			(IS_MAC1)      |(IS_MAC2)     | \
-			(IS_R1_C)      |(IS_R2_C)     | \
-			(IS_XS1_C)     |(IS_XA1_C)    | \
-			(IS_XS2_C)     |(IS_XA2_C))
-
-#define IRQ_HWE_MASK	(IS_ERR_MSK) /* enable all HW irqs */
-
-typedef struct s_DevNet DEV_NET;
-
-struct s_DevNet {
-	int             PortNr;
-	int             NetNr;
-	SK_AC   *pAC;
-};  
-
-typedef struct s_TxPort		TX_PORT;
-
-struct s_TxPort {
-	/* the transmit descriptor rings */
-	caddr_t		pTxDescrRing;	/* descriptor area memory */
-	SK_U64		VTxDescrRing;	/* descr. area bus virt. addr. */
-	TXD		*pTxdRingHead;	/* Head of Tx rings */
-	TXD		*pTxdRingTail;	/* Tail of Tx rings */
-	TXD		*pTxdRingPrev;	/* descriptor sent previously */
-	int		TxdRingFree;	/* # of free entrys */
-	spinlock_t	TxDesRingLock;	/* serialize descriptor accesses */
-	SK_IOC		HwAddr;		/* bmu registers address */
-	int		PortIndex;	/* index number of port (0 or 1) */
-};
-
-typedef struct s_RxPort		RX_PORT;
-
-struct s_RxPort {
-	/* the receive descriptor rings */
-	caddr_t		pRxDescrRing;	/* descriptor area memory */
-	SK_U64		VRxDescrRing;   /* descr. area bus virt. addr. */
-	RXD		*pRxdRingHead;	/* Head of Rx rings */
-	RXD		*pRxdRingTail;	/* Tail of Rx rings */
-	RXD		*pRxdRingPrev;	/* descriptor given to BMU previously */
-	int		RxdRingFree;	/* # of free entrys */
-	int		RxCsum;		/* use receive checksum hardware */
-	spinlock_t	RxDesRingLock;	/* serialize descriptor accesses */
-	int		RxFillLimit;	/* limit for buffers in ring */
-	SK_IOC		HwAddr;		/* bmu registers address */
-	int		PortIndex;	/* index number of port (0 or 1) */
-};
-
-/* Definitions needed for interrupt moderation *******************************/
-
-#define IRQ_EOF_AS_TX     ((IS_XA1_F)     | (IS_XA2_F))
-#define IRQ_EOF_SY_TX     ((IS_XS1_F)     | (IS_XS2_F))
-#define IRQ_MASK_TX_ONLY  ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
-#define IRQ_MASK_RX_ONLY  ((IS_R1_F)      | (IS_R2_F))
-#define IRQ_MASK_SP_ONLY  (SPECIAL_IRQS)
-#define IRQ_MASK_TX_RX    ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_RX    ((SPECIAL_IRQS)    | (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_TX    ((SPECIAL_IRQS)    | (IRQ_MASK_TX_ONLY))
-#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS)    | (IRQ_MASK_TX_RX))
-
-#define C_INT_MOD_NONE                 1
-#define C_INT_MOD_STATIC               2
-#define C_INT_MOD_DYNAMIC              4
-
-#define C_CLK_FREQ_GENESIS      53215000 /* shorter: 53.125 MHz  */
-#define C_CLK_FREQ_YUKON        78215000 /* shorter: 78.125 MHz  */
-
-#define C_INTS_PER_SEC_DEFAULT      2000 
-#define C_INT_MOD_ENABLE_PERCENTAGE   50 /* if higher 50% enable */
-#define C_INT_MOD_DISABLE_PERCENTAGE  50 /* if lower 50% disable */
-#define C_INT_MOD_IPS_LOWER_RANGE     30
-#define C_INT_MOD_IPS_UPPER_RANGE     40000
-
-
-typedef struct s_DynIrqModInfo  DIM_INFO;
-struct s_DynIrqModInfo {
-	unsigned long   PrevTimeVal;
-	unsigned int    PrevSysLoad;
-	unsigned int    PrevUsedTime;
-	unsigned int    PrevTotalTime;
-	int             PrevUsedDescrRatio;
-	int             NbrProcessedDescr;
-        SK_U64          PrevPort0RxIntrCts;
-        SK_U64          PrevPort1RxIntrCts;
-        SK_U64          PrevPort0TxIntrCts;
-        SK_U64          PrevPort1TxIntrCts;
-	SK_BOOL         ModJustEnabled;     /* Moderation just enabled yes/no */
-
-	int             MaxModIntsPerSec;            /* Moderation Threshold */
-	int             MaxModIntsPerSecUpperLimit;  /* Upper limit for DIM  */
-	int             MaxModIntsPerSecLowerLimit;  /* Lower limit for DIM  */
-
-	long            MaskIrqModeration;   /* ModIrqType (eg. 'TxRx')      */
-	SK_BOOL         DisplayStats;        /* Stats yes/no                 */
-	SK_BOOL         AutoSizing;          /* Resize DIM-timer on/off      */
-	int             IntModTypeSelect;    /* EnableIntMod (eg. 'dynamic') */
-
-	SK_TIMER        ModTimer; /* just some timer */
-};
-
-typedef struct s_PerStrm	PER_STRM;
-
-#define SK_ALLOC_IRQ	0x00000001
-
-#ifdef SK_DIAG_SUPPORT
-#define	DIAG_ACTIVE		1
-#define	DIAG_NOTACTIVE		0
-#endif
-
-/****************************************************************************
- * Per board structure / Adapter Context structure:
- *	Allocated within attach(9e) and freed within detach(9e).
- *	Contains all 'per device' necessary handles, flags, locks etc.:
- */
-struct s_AC  {
-	SK_GEINIT	GIni;		/* GE init struct */
-	SK_PNMI		Pnmi;		/* PNMI data struct */
-	SK_VPD		vpd;		/* vpd data struct */
-	SK_QUEUE	Event;		/* Event queue */
-	SK_HWT		Hwt;		/* Hardware Timer control struct */
-	SK_TIMCTRL	Tim;		/* Software Timer control struct */
-	SK_I2C		I2c;		/* I2C relevant data structure */
-	SK_ADDR		Addr;		/* for Address module */
-	SK_CSUM		Csum;		/* for checksum module */
-	SK_RLMT		Rlmt;		/* for rlmt module */
-	spinlock_t	SlowPathLock;	/* Normal IRQ lock */
-	struct timer_list BlinkTimer;	/* for LED blinking */
-	int		LedsOn;
-	SK_PNMI_STRUCT_DATA PnmiStruct;	/* structure to get all Pnmi-Data */
-	int			RlmtMode;	/* link check mode to set */
-	int			RlmtNets;	/* Number of nets */
-	
-	SK_IOC		IoBase;		/* register set of adapter */
-	int		BoardLevel;	/* level of active hw init (0-2) */
-
-	SK_U32		AllocFlag;	/* flag allocation of resources */
-	struct pci_dev	*PciDev;	/* for access to pci config space */
-	struct SK_NET_DEVICE	*dev[2];	/* pointer to device struct */
-
-	int		RxBufSize;	/* length of receive buffers */
-        struct net_device_stats stats;	/* linux 'netstat -i' statistics */
-	int		Index;		/* internal board index number */
-
-	/* adapter RAM sizes for queues of active port */
-	int		RxQueueSize;	/* memory used for receive queue */
-	int		TxSQueueSize;	/* memory used for sync. tx queue */
-	int		TxAQueueSize;	/* memory used for async. tx queue */
-
-	int		PromiscCount;	/* promiscuous mode counter  */
-	int		AllMultiCount;  /* allmulticast mode counter */
-	int		MulticCount;	/* number of different MC    */
-					/*  addresses for this board */
-					/*  (may be more than HW can)*/
-
-	int		HWRevision;	/* Hardware revision */
-	int		ActivePort;	/* the active XMAC port */
-	int		MaxPorts;		/* number of activated ports */
-	int		TxDescrPerRing;	/* # of descriptors per tx ring */
-	int		RxDescrPerRing;	/* # of descriptors per rx ring */
-
-	caddr_t		pDescrMem;	/* Pointer to the descriptor area */
-	dma_addr_t	pDescrMemDMA;	/* PCI DMA address of area */
-
-	/* the port structures with descriptor rings */
-	TX_PORT		TxPort[SK_MAX_MACS][2];
-	RX_PORT		RxPort[SK_MAX_MACS];
-
-	SK_BOOL		CheckQueue;	/* check event queue soon */
-	SK_TIMER        DrvCleanupTimer;/* to check for pending descriptors */
-	DIM_INFO        DynIrqModInfo;  /* all data related to DIM */
-
-	/* Only for tests */
-	int		PortDown;
-	int		ChipsetType;	/*  Chipset family type 
-					 *  0 == Genesis family support
-					 *  1 == Yukon family support
-					 */
-#ifdef SK_DIAG_SUPPORT
-	SK_U32		DiagModeActive;		/* is diag active?	*/
-	SK_BOOL		DiagFlowCtrl;		/* for control purposes	*/
-	SK_PNMI_STRUCT_DATA PnmiBackup;		/* backup structure for all Pnmi-Data */
-	SK_BOOL         WasIfUp[SK_MAX_MACS];   /* for OpenClose while 
-						 * DIAG is busy with NIC 
-						 */
-#endif
-
-};
-
-
-#endif /* __INC_SKDRV2ND_H */
-
diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
deleted file mode 100644
index da062f7..0000000
--- a/drivers/net/sk98lin/h/skerror.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/******************************************************************************
- *
- * Name:	skerror.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/05/13 17:25:13 $
- * Purpose:	SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKERROR_H_
-#define _INC_SKERROR_H_
-
-/*
- * Define Error Classes
- */
-#define	SK_ERRCL_OTHER		(0)		/* Other error */
-#define	SK_ERRCL_CONFIG		(1L<<0)	/* Configuration error */
-#define	SK_ERRCL_INIT		(1L<<1)	/* Initialization error */
-#define	SK_ERRCL_NORES		(1L<<2)	/* Out of Resources error */
-#define	SK_ERRCL_SW			(1L<<3)	/* Internal Software error */
-#define	SK_ERRCL_HW			(1L<<4)	/* Hardware Failure */
-#define	SK_ERRCL_COMM		(1L<<5)	/* Communication error */
-
-
-/*
- * Define Error Code Bases
- */
-#define	SK_ERRBASE_RLMT		 100	/* Base Error number for RLMT */
-#define	SK_ERRBASE_HWINIT	 200	/* Base Error number for HWInit */
-#define	SK_ERRBASE_VPD		 300	/* Base Error number for VPD */
-#define	SK_ERRBASE_PNMI		 400	/* Base Error number for PNMI */
-#define	SK_ERRBASE_CSUM		 500	/* Base Error number for Checksum */
-#define	SK_ERRBASE_SIRQ		 600	/* Base Error number for Special IRQ */
-#define	SK_ERRBASE_I2C		 700	/* Base Error number for I2C module */
-#define	SK_ERRBASE_QUEUE	 800	/* Base Error number for Scheduler */
-#define	SK_ERRBASE_ADDR		 900	/* Base Error number for Address module */
-#define SK_ERRBASE_PECP		1000    /* Base Error number for PECP */
-#define	SK_ERRBASE_DRV		1100	/* Base Error number for Driver */
-
-#endif	/* _INC_SKERROR_H_ */
diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
deleted file mode 100644
index 44fd4c3..0000000
--- a/drivers/net/sk98lin/h/skgedrv.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgedrv.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/07/04 12:25:01 $
- * Purpose:	Interface with the driver
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEDRV_H_
-#define __INC_SKGEDRV_H_
-
-/* defines ********************************************************************/
-
-/*
- * Define the driver events.
- * Usually the events are defined by the destination module.
- * In case of the driver we put the definition of the events here.
- */
-#define SK_DRV_PORT_RESET		 1	/* The port needs to be reset */
-#define SK_DRV_NET_UP   		 2	/* The net is operational */
-#define SK_DRV_NET_DOWN			 3	/* The net is down */
-#define SK_DRV_SWITCH_SOFT		 4	/* Ports switch with both links connected */
-#define SK_DRV_SWITCH_HARD		 5	/* Port switch due to link failure */
-#define SK_DRV_RLMT_SEND		 6	/* Send a RLMT packet */
-#define SK_DRV_ADAP_FAIL		 7	/* The whole adapter fails */
-#define SK_DRV_PORT_FAIL		 8	/* One port fails */
-#define SK_DRV_SWITCH_INTERN	 9	/* Port switch by the driver itself */
-#define SK_DRV_POWER_DOWN		10	/* Power down mode */
-#define SK_DRV_TIMER			11	/* Timer for free use */
-#ifdef SK_NO_RLMT
-#define SK_DRV_LINK_UP  		12	/* Link Up event for driver */
-#define SK_DRV_LINK_DOWN		13	/* Link Down event for driver */
-#endif
-#define SK_DRV_DOWNSHIFT_DET	14	/* Downshift 4-Pair / 2-Pair (YUKON only) */
-#endif /* __INC_SKGEDRV_H_ */
diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
deleted file mode 100644
index f6282b7..0000000
--- a/drivers/net/sk98lin/h/skgehw.h
+++ /dev/null
@@ -1,2126 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgehw.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.56 $
- * Date:	$Date: 2003/09/23 09:01:00 $
- * Purpose:	Defines and Macros for the Gigabit Ethernet Adapter Product Family
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEHW_H
-#define __INC_SKGEHW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define BIT_31		(1UL << 31)
-#define BIT_30		(1L << 30)
-#define BIT_29		(1L << 29)
-#define BIT_28		(1L << 28)
-#define BIT_27		(1L << 27)
-#define BIT_26		(1L << 26)
-#define BIT_25		(1L << 25)
-#define BIT_24		(1L << 24)
-#define BIT_23		(1L << 23)
-#define BIT_22		(1L << 22)
-#define BIT_21		(1L << 21)
-#define BIT_20		(1L << 20)
-#define BIT_19		(1L << 19)
-#define BIT_18		(1L << 18)
-#define BIT_17		(1L << 17)
-#define BIT_16		(1L << 16)
-#define BIT_15		(1L << 15)
-#define BIT_14		(1L << 14)
-#define BIT_13		(1L << 13)
-#define BIT_12		(1L << 12)
-#define BIT_11		(1L << 11)
-#define BIT_10		(1L << 10)
-#define BIT_9		(1L << 9)
-#define BIT_8		(1L << 8)
-#define BIT_7		(1L << 7)
-#define BIT_6		(1L << 6)
-#define BIT_5		(1L << 5)
-#define BIT_4		(1L << 4)
-#define BIT_3		(1L << 3)
-#define BIT_2		(1L << 2)
-#define BIT_1		(1L << 1)
-#define BIT_0		1L
-
-#define BIT_15S		(1U << 15)
-#define BIT_14S		(1 << 14)
-#define BIT_13S		(1 << 13)
-#define BIT_12S		(1 << 12)
-#define BIT_11S		(1 << 11)
-#define BIT_10S		(1 << 10)
-#define BIT_9S		(1 << 9)
-#define BIT_8S		(1 << 8)
-#define BIT_7S 		(1 << 7)
-#define BIT_6S		(1 << 6)
-#define BIT_5S		(1 << 5)
-#define BIT_4S		(1 << 4)
-#define BIT_3S		(1 << 3)
-#define BIT_2S		(1 << 2)
-#define BIT_1S		(1 << 1)
-#define BIT_0S		1
-
-#define SHIFT31(x)	((x) << 31)
-#define SHIFT30(x)	((x) << 30)
-#define SHIFT29(x)	((x) << 29)
-#define SHIFT28(x)	((x) << 28)
-#define SHIFT27(x)	((x) << 27)
-#define SHIFT26(x)	((x) << 26)
-#define SHIFT25(x)	((x) << 25)
-#define SHIFT24(x)	((x) << 24)
-#define SHIFT23(x)	((x) << 23)
-#define SHIFT22(x)	((x) << 22)
-#define SHIFT21(x)	((x) << 21)
-#define SHIFT20(x)	((x) << 20)
-#define SHIFT19(x)	((x) << 19)
-#define SHIFT18(x)	((x) << 18)
-#define SHIFT17(x)	((x) << 17)
-#define SHIFT16(x)	((x) << 16)
-#define SHIFT15(x)	((x) << 15)
-#define SHIFT14(x)	((x) << 14)
-#define SHIFT13(x)	((x) << 13)
-#define SHIFT12(x)	((x) << 12)
-#define SHIFT11(x)	((x) << 11)
-#define SHIFT10(x)	((x) << 10)
-#define SHIFT9(x)	((x) << 9)
-#define SHIFT8(x)	((x) << 8)
-#define SHIFT7(x)	((x) << 7)
-#define SHIFT6(x)	((x) << 6)
-#define SHIFT5(x)	((x) << 5)
-#define SHIFT4(x)	((x) << 4)
-#define SHIFT3(x)	((x) << 3)
-#define SHIFT2(x)	((x) << 2)
-#define SHIFT1(x)	((x) << 1)
-#define SHIFT0(x)	((x) << 0)
-
-/*
- * Configuration Space header
- * Since this module is used for different OS', those may be
- * duplicate on some of them (e.g. Linux). But to keep the
- * common source, we have to live with this...
- */
-#define PCI_VENDOR_ID	0x00	/* 16 bit	Vendor ID */
-#define PCI_DEVICE_ID	0x02	/* 16 bit	Device ID */
-#define PCI_COMMAND		0x04	/* 16 bit	Command */
-#define PCI_STATUS		0x06	/* 16 bit	Status */
-#define PCI_REV_ID		0x08	/*  8 bit	Revision ID */
-#define PCI_CLASS_CODE	0x09	/* 24 bit	Class Code */
-#define PCI_CACHE_LSZ	0x0c	/*  8 bit	Cache Line Size */
-#define PCI_LAT_TIM		0x0d	/*  8 bit	Latency Timer */
-#define PCI_HEADER_T	0x0e	/*  8 bit	Header Type */
-#define PCI_BIST		0x0f	/*  8 bit	Built-in selftest */
-#define PCI_BASE_1ST	0x10	/* 32 bit	1st Base address */
-#define PCI_BASE_2ND	0x14	/* 32 bit	2nd Base address */
-	/* Byte 0x18..0x2b:	reserved */
-#define PCI_SUB_VID		0x2c	/* 16 bit	Subsystem Vendor ID */
-#define PCI_SUB_ID		0x2e	/* 16 bit	Subsystem ID */
-#define PCI_BASE_ROM	0x30	/* 32 bit	Expansion ROM Base Address */
-#define PCI_CAP_PTR		0x34	/*  8 bit 	Capabilities Ptr */
-	/* Byte 0x35..0x3b:	reserved */
-#define PCI_IRQ_LINE	0x3c	/*  8 bit	Interrupt Line */
-#define PCI_IRQ_PIN		0x3d	/*  8 bit	Interrupt Pin */
-#define PCI_MIN_GNT		0x3e	/*  8 bit	Min_Gnt */
-#define PCI_MAX_LAT		0x3f	/*  8 bit	Max_Lat */
-	/* Device Dependent Region */
-#define PCI_OUR_REG_1	0x40	/* 32 bit 	Our Register 1 */
-#define PCI_OUR_REG_2	0x44	/* 32 bit 	Our Register 2 */
-	/* Power Management Region */
-#define PCI_PM_CAP_ID	0x48	/*  8 bit 	Power Management Cap. ID */
-#define PCI_PM_NITEM	0x49	/*  8 bit 	Next Item Ptr */
-#define PCI_PM_CAP_REG	0x4a	/* 16 bit 	Power Management Capabilities */
-#define PCI_PM_CTL_STS	0x4c	/* 16 bit 	Power Manag. Control/Status */
-	/* Byte 0x4e:	reserved */
-#define PCI_PM_DAT_REG	0x4f	/*  8 bit 	Power Manag. Data Register */
-	/* VPD Region */
-#define PCI_VPD_CAP_ID	0x50	/*  8 bit 	VPD Cap. ID */
-#define PCI_VPD_NITEM	0x51	/*  8 bit 	Next Item Ptr */
-#define PCI_VPD_ADR_REG	0x52	/* 16 bit 	VPD Address Register */
-#define PCI_VPD_DAT_REG	0x54	/* 32 bit 	VPD Data Register */
-	/* Byte 0x58..0x59:	reserved */
-#define PCI_SER_LD_CTRL	0x5a	/* 16 bit 	SEEPROM Loader Ctrl (YUKON only) */
-	/* Byte 0x5c..0xff:	reserved */
-
-/*
- * I2C Address (PCI Config)
- *
- * Note: The temperature and voltage sensors are relocated on a different
- *	 I2C bus.
- */
-#define I2C_ADDR_VPD	0xa0	/* I2C address for the VPD EEPROM */
-
-/*
- * Define Bits and Values of the registers
- */
-/*	PCI_COMMAND	16 bit	Command */
-								/* Bit 15..11:	reserved */
-#define PCI_INT_DIS		BIT_10S		/* Interrupt INTx# disable (PCI 2.3) */
-#define PCI_FBTEN		BIT_9S		/* Fast Back-To-Back enable */
-#define PCI_SERREN		BIT_8S		/* SERR enable */
-#define PCI_ADSTEP		BIT_7S		/* Address Stepping */
-#define PCI_PERREN		BIT_6S		/* Parity Report Response enable */
-#define PCI_VGA_SNOOP	BIT_5S		/* VGA palette snoop */
-#define PCI_MWIEN		BIT_4S		/* Memory write an inv cycl ena */
-#define PCI_SCYCEN		BIT_3S		/* Special Cycle enable */
-#define PCI_BMEN		BIT_2S		/* Bus Master enable */
-#define PCI_MEMEN		BIT_1S		/* Memory Space Access enable */
-#define PCI_IOEN		BIT_0S		/* I/O Space Access enable */
-
-#define PCI_COMMAND_VAL	(PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
-						 PCI_BMEN | PCI_MEMEN | PCI_IOEN)
-
-/*	PCI_STATUS	16 bit	Status */
-#define PCI_PERR		BIT_15S		/* Parity Error */
-#define PCI_SERR		BIT_14S		/* Signaled SERR */
-#define PCI_RMABORT		BIT_13S		/* Received Master Abort */
-#define PCI_RTABORT		BIT_12S		/* Received Target Abort */
-								/* Bit 11:	reserved */
-#define PCI_DEVSEL		(3<<9)		/* Bit 10.. 9:	DEVSEL Timing */
-#define PCI_DEV_FAST	(0<<9)		/*		fast */
-#define PCI_DEV_MEDIUM	(1<<9)		/*		medium */
-#define PCI_DEV_SLOW	(2<<9)		/*		slow */
-#define PCI_DATAPERR	BIT_8S		/* DATA Parity error detected */
-#define PCI_FB2BCAP		BIT_7S		/* Fast Back-to-Back Capability */
-#define PCI_UDF			BIT_6S		/* User Defined Features */
-#define PCI_66MHZCAP	BIT_5S		/* 66 MHz PCI bus clock capable */
-#define PCI_NEWCAP		BIT_4S		/* New cap. list implemented */
-#define PCI_INT_STAT	BIT_3S		/* Interrupt INTx# Status (PCI 2.3) */
-								/* Bit  2.. 0:	reserved */
-
-#define PCI_ERRBITS	(PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
-			PCI_DATAPERR)
-
-/*	PCI_CLASS_CODE	24 bit	Class Code */
-/*	Byte 2:		Base Class		(02) */
-/*	Byte 1:		SubClass		(00) */
-/*	Byte 0:		Programming Interface	(00) */
-
-/*	PCI_CACHE_LSZ	8 bit	Cache Line Size */
-/*	Possible values: 0,2,4,8,16,32,64,128	*/
-
-/*	PCI_HEADER_T	8 bit	Header Type */
-#define PCI_HD_MF_DEV	BIT_7S	/* 0= single, 1= multi-func dev */
-#define PCI_HD_TYPE		0x7f	/* Bit 6..0:	Header Layout 0= normal */
-
-/*	PCI_BIST	8 bit	Built-in selftest */
-/*	Built-in Self test not supported (optional) */
-
-/*	PCI_BASE_1ST	32 bit	1st Base address */
-#define PCI_MEMSIZE		0x4000L		/* use 16 kB Memory Base */
-#define PCI_MEMBASE_MSK 0xffffc000L	/* Bit 31..14:	Memory Base Address */
-#define PCI_MEMSIZE_MSK 0x00003ff0L	/* Bit 13.. 4:	Memory Size Req. */
-#define PCI_PREFEN		BIT_3		/* Prefetchable */
-#define PCI_MEM_TYP		(3L<<2)		/* Bit	2.. 1:	Memory Type */
-#define PCI_MEM32BIT	(0L<<1)		/* Base addr anywhere in 32 Bit range */
-#define PCI_MEM1M		(1L<<1)		/* Base addr below 1 MegaByte */
-#define PCI_MEM64BIT	(2L<<1)		/* Base addr anywhere in 64 Bit range */
-#define PCI_MEMSPACE	BIT_0		/* Memory Space Indicator */
-
-/*	PCI_BASE_2ND	32 bit	2nd Base address */
-#define PCI_IOBASE		0xffffff00L	/* Bit 31.. 8:	I/O Base address */
-#define PCI_IOSIZE		0x000000fcL	/* Bit	7.. 2:	I/O Size Requirements */
-									/* Bit	1:	reserved */
-#define PCI_IOSPACE		BIT_0		/* I/O Space Indicator */
-
-/*	PCI_BASE_ROM	32 bit	Expansion ROM Base Address */
-#define PCI_ROMBASE_MSK	0xfffe0000L	/* Bit 31..17:	ROM Base address */
-#define PCI_ROMBASE_SIZ	(0x1cL<<14)	/* Bit 16..14:	Treat as Base or Size */
-#define PCI_ROMSIZE		(0x38L<<11)	/* Bit 13..11:	ROM Size Requirements */
-									/* Bit 10.. 1:	reserved */
-#define PCI_ROMEN		BIT_0		/* Address Decode enable */
-
-/* Device Dependent Region */
-/*	PCI_OUR_REG_1		32 bit	Our Register 1 */
-									/* Bit 31..29:	reserved */
-#define PCI_PHY_COMA	BIT_28		/* Set PHY to Coma Mode (YUKON only) */
-#define PCI_TEST_CAL	BIT_27		/* Test PCI buffer calib. (YUKON only) */
-#define PCI_EN_CAL		BIT_26		/* Enable PCI buffer calib. (YUKON only) */
-#define PCI_VIO			BIT_25		/* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
-#define PCI_DIS_BOOT	BIT_24		/* Disable BOOT via ROM */
-#define PCI_EN_IO		BIT_23		/* Mapping to I/O space */
-#define PCI_EN_FPROM	BIT_22		/* Enable FLASH mapping to memory */
-									/*		1 = Map Flash to memory */
-									/*		0 = Disable addr. dec */
-#define PCI_PAGESIZE	(3L<<20)	/* Bit 21..20:	FLASH Page Size	*/
-#define PCI_PAGE_16		(0L<<20)	/*		16 k pages	*/
-#define PCI_PAGE_32K	(1L<<20)	/*		32 k pages	*/
-#define PCI_PAGE_64K	(2L<<20)	/*		64 k pages	*/
-#define PCI_PAGE_128K	(3L<<20)	/*		128 k pages	*/
-									/* Bit 19:	reserved	*/
-#define PCI_PAGEREG		(7L<<16)	/* Bit 18..16:	Page Register	*/
-#define PCI_NOTAR		BIT_15		/* No turnaround cycle */
-#define PCI_FORCE_BE	BIT_14		/* Assert all BEs on MR */
-#define PCI_DIS_MRL		BIT_13		/* Disable Mem Read Line */
-#define PCI_DIS_MRM		BIT_12		/* Disable Mem Read Multiple */
-#define PCI_DIS_MWI		BIT_11		/* Disable Mem Write & Invalidate */
-#define PCI_DISC_CLS	BIT_10		/* Disc: cacheLsz bound */
-#define PCI_BURST_DIS	BIT_9		/* Burst Disable */
-#define PCI_DIS_PCI_CLK	BIT_8		/* Disable PCI clock driving */
-#define PCI_SKEW_DAS	(0xfL<<4)	/* Bit	7.. 4:	Skew Ctrl, DAS Ext */
-#define PCI_SKEW_BASE	0xfL		/* Bit	3.. 0:	Skew Ctrl, Base	*/
-
-
-/*	PCI_OUR_REG_2		32 bit	Our Register 2 */
-#define PCI_VPD_WR_THR	(0xffL<<24)	/* Bit 31..24:	VPD Write Threshold */
-#define PCI_DEV_SEL		(0x7fL<<17)	/* Bit 23..17:	EEPROM Device Select */
-#define PCI_VPD_ROM_SZ	(7L<<14)	/* Bit 16..14:	VPD ROM Size	*/
-									/* Bit 13..12:	reserved	*/
-#define PCI_PATCH_DIR	(0xfL<<8)	/* Bit 11.. 8:	Ext Patches dir 3..0 */
-#define PCI_PATCH_DIR_3	BIT_11
-#define PCI_PATCH_DIR_2	BIT_10
-#define PCI_PATCH_DIR_1	BIT_9
-#define PCI_PATCH_DIR_0	BIT_8
-#define PCI_EXT_PATCHS	(0xfL<<4)	/* Bit	7.. 4:	Extended Patches 3..0 */
-#define PCI_EXT_PATCH_3	BIT_7
-#define PCI_EXT_PATCH_2	BIT_6
-#define PCI_EXT_PATCH_1	BIT_5
-#define PCI_EXT_PATCH_0	BIT_4
-#define PCI_EN_DUMMY_RD	BIT_3		/* Enable Dummy Read */
-#define PCI_REV_DESC	BIT_2		/* Reverse Desc. Bytes */
-									/* Bit	1:	reserved */
-#define PCI_USEDATA64	BIT_0		/* Use 64Bit Data bus ext */
-
-
-/* Power Management Region */
-/*	PCI_PM_CAP_REG		16 bit	Power Management Capabilities */
-#define PCI_PME_SUP_MSK	(0x1f<<11)	/* Bit 15..11:	PM Event Support Mask */
-#define PCI_PME_D3C_SUP	BIT_15S		/* PME from D3cold Support (if Vaux) */
-#define PCI_PME_D3H_SUP	BIT_14S		/* PME from D3hot Support */
-#define PCI_PME_D2_SUP	BIT_13S		/* PME from D2 Support */
-#define PCI_PME_D1_SUP	BIT_12S		/* PME from D1 Support */
-#define PCI_PME_D0_SUP	BIT_11S		/* PME from D0 Support */
-#define PCI_PM_D2_SUP	BIT_10S		/* D2 Support in 33 MHz mode */
-#define PCI_PM_D1_SUP	BIT_9S		/* D1 Support */
-									/* Bit	8.. 6:	reserved */
-#define PCI_PM_DSI		BIT_5S		/* Device Specific Initialization */
-#define PCI_PM_APS		BIT_4S		/* Auxialiary Power Source */
-#define PCI_PME_CLOCK	BIT_3S		/* PM Event Clock */
-#define PCI_PM_VER_MSK		7		/* Bit	2.. 0:	PM PCI Spec. version */
-
-/*	PCI_PM_CTL_STS		16 bit	Power Management Control/Status */
-#define PCI_PME_STATUS	BIT_15S		/* PME Status (YUKON only) */
-#define PCI_PM_DAT_SCL	(3<<13)		/* Bit 14..13:	Data Reg. scaling factor */
-#define PCI_PM_DAT_SEL	(0xf<<9)	/* Bit 12.. 9:	PM data selector field */
-#define PCI_PME_EN		BIT_8S		/* Enable PME# generation (YUKON only) */
-									/* Bit	7.. 2:	reserved */
-#define PCI_PM_STATE_MSK	3		/* Bit	1.. 0:	Power Management State */
-
-#define PCI_PM_STATE_D0		0		/* D0:	Operational (default) */
-#define PCI_PM_STATE_D1		1		/* D1:	(YUKON only) */
-#define PCI_PM_STATE_D2		2		/* D2:	(YUKON only) */
-#define PCI_PM_STATE_D3 	3		/* D3:	HOT, Power Down and Reset */
-
-/* VPD Region */
-/*	PCI_VPD_ADR_REG		16 bit	VPD Address Register */
-#define PCI_VPD_FLAG	BIT_15S		/* starts VPD rd/wr cycle */
-#define PCI_VPD_ADR_MSK	0x7fffL		/* Bit 14.. 0:	VPD address mask */
-
-/*	Control Register File (Address Map) */
-
-/*
- *	Bank 0
- */
-#define B0_RAP			0x0000	/*  8 bit	Register Address Port */
-	/* 0x0001 - 0x0003:	reserved */
-#define B0_CTST			0x0004	/* 16 bit	Control/Status register */
-#define B0_LED			0x0006	/*  8 Bit	LED register */
-#define B0_POWER_CTRL	0x0007	/*  8 Bit	Power Control reg (YUKON only) */
-#define B0_ISRC			0x0008	/* 32 bit	Interrupt Source Register */
-#define B0_IMSK			0x000c	/* 32 bit	Interrupt Mask Register */
-#define B0_HWE_ISRC		0x0010	/* 32 bit	HW Error Interrupt Src Reg */
-#define B0_HWE_IMSK		0x0014	/* 32 bit	HW Error Interrupt Mask Reg */
-#define B0_SP_ISRC		0x0018	/* 32 bit	Special Interrupt Source Reg */
-	/* 0x001c:		reserved */
-
-/* B0 XMAC 1 registers (GENESIS only) */
-#define B0_XM1_IMSK		0x0020	/* 16 bit r/w	XMAC 1 Interrupt Mask Register*/
-	/* 0x0022 - 0x0027:	reserved */
-#define B0_XM1_ISRC		0x0028	/* 16 bit ro	XMAC 1 Interrupt Status Reg */
-	/* 0x002a - 0x002f:	reserved */
-#define B0_XM1_PHY_ADDR 0x0030	/* 16 bit r/w	XMAC 1 PHY Address Register */
-	/* 0x0032 - 0x0033:	reserved */
-#define B0_XM1_PHY_DATA 0x0034	/* 16 bit r/w	XMAC 1 PHY Data Register */
-	/* 0x0036 - 0x003f:	reserved */
-
-/* B0 XMAC 2 registers (GENESIS only) */
-#define B0_XM2_IMSK		0x0040	/* 16 bit r/w	XMAC 2 Interrupt Mask Register*/
-	/* 0x0042 - 0x0047:	reserved */
-#define B0_XM2_ISRC		0x0048	/* 16 bit ro	XMAC 2 Interrupt Status Reg */
-	/* 0x004a - 0x004f:	reserved */
-#define B0_XM2_PHY_ADDR 0x0050	/* 16 bit r/w	XMAC 2 PHY Address Register */
-	/* 0x0052 - 0x0053:	reserved */
-#define B0_XM2_PHY_DATA 0x0054	/* 16 bit r/w	XMAC 2 PHY Data Register */
-	/* 0x0056 - 0x005f:	reserved */
-
-/* BMU Control Status Registers */
-#define B0_R1_CSR		0x0060	/* 32 bit	BMU Ctrl/Stat Rx Queue 1 */
-#define B0_R2_CSR		0x0064	/* 32 bit	BMU Ctrl/Stat Rx Queue 2 */
-#define B0_XS1_CSR		0x0068	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
-#define B0_XA1_CSR		0x006c	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 1*/
-#define B0_XS2_CSR		0x0070	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
-#define B0_XA2_CSR		0x0074	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 2*/
-	/* 0x0078 - 0x007f:	reserved */
-
-/*
- *	Bank 1
- *	- completely empty (this is the RAP Block window)
- *	Note: if RAP = 1 this page is reserved
- */
-
-/*
- *	Bank 2
- */
-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
-#define B2_MAC_1		0x0100	/* NA reg	 MAC Address 1 */
-	/* 0x0106 - 0x0107:	reserved */
-#define B2_MAC_2		0x0108	/* NA reg	 MAC Address 2 */
-	/* 0x010e - 0x010f:	reserved */
-#define B2_MAC_3		0x0110	/* NA reg	 MAC Address 3 */
-	/* 0x0116 - 0x0117:	reserved */
-#define B2_CONN_TYP		0x0118	/*  8 bit	Connector type */
-#define B2_PMD_TYP		0x0119	/*  8 bit	PMD type */
-#define B2_MAC_CFG		0x011a	/*  8 bit	MAC Configuration / Chip Revision */
-#define B2_CHIP_ID		0x011b	/*  8 bit 	Chip Identification Number */
-	/* Eprom registers are currently of no use */
-#define B2_E_0			0x011c	/*  8 bit	EPROM Byte 0 (ext. SRAM size */
-#define B2_E_1			0x011d	/*  8 bit	EPROM Byte 1 (PHY type) */
-#define B2_E_2			0x011e	/*  8 bit	EPROM Byte 2 */
-#define B2_E_3			0x011f	/*  8 bit	EPROM Byte 3 */
-#define B2_FAR			0x0120	/* 32 bit	Flash-Prom Addr Reg/Cnt */
-#define B2_FDP			0x0124	/*  8 bit	Flash-Prom Data Port */
-	/* 0x0125 - 0x0127:	reserved */
-#define B2_LD_CTRL		0x0128	/*  8 bit	EPROM loader control register */
-#define B2_LD_TEST		0x0129	/*  8 bit	EPROM loader test register */
-	/* 0x012a - 0x012f:	reserved */
-#define B2_TI_INI		0x0130	/* 32 bit	Timer Init Value */
-#define B2_TI_VAL		0x0134	/* 32 bit	Timer Value */
-#define B2_TI_CTRL		0x0138	/*  8 bit	Timer Control */
-#define B2_TI_TEST		0x0139	/*  8 Bit	Timer Test */
-	/* 0x013a - 0x013f:	reserved */
-#define B2_IRQM_INI		0x0140	/* 32 bit	IRQ Moderation Timer Init Reg.*/
-#define B2_IRQM_VAL		0x0144	/* 32 bit	IRQ Moderation Timer Value */
-#define B2_IRQM_CTRL	0x0148	/*  8 bit	IRQ Moderation Timer Control */
-#define B2_IRQM_TEST	0x0149	/*  8 bit	IRQ Moderation Timer Test */
-#define B2_IRQM_MSK 	0x014c	/* 32 bit	IRQ Moderation Mask */
-#define B2_IRQM_HWE_MSK 0x0150	/* 32 bit	IRQ Moderation HW Error Mask */
-	/* 0x0154 - 0x0157:	reserved */
-#define B2_TST_CTRL1	0x0158	/*  8 bit	Test Control Register 1 */
-#define B2_TST_CTRL2	0x0159	/*  8 bit	Test Control Register 2 */
-	/* 0x015a - 0x015b:	reserved */
-#define B2_GP_IO		0x015c	/* 32 bit	General Purpose I/O Register */
-#define B2_I2C_CTRL		0x0160	/* 32 bit	I2C HW Control Register */
-#define B2_I2C_DATA		0x0164	/* 32 bit	I2C HW Data Register */
-#define B2_I2C_IRQ		0x0168	/* 32 bit	I2C HW IRQ Register */
-#define B2_I2C_SW		0x016c	/* 32 bit	I2C SW Port Register */
-
-/* Blink Source Counter (GENESIS only) */
-#define B2_BSC_INI		0x0170	/* 32 bit	Blink Source Counter Init Val */
-#define B2_BSC_VAL		0x0174	/* 32 bit	Blink Source Counter Value */
-#define B2_BSC_CTRL		0x0178	/*  8 bit	Blink Source Counter Control */
-#define B2_BSC_STAT		0x0179	/*  8 bit	Blink Source Counter Status */
-#define B2_BSC_TST		0x017a	/* 16 bit	Blink Source Counter Test Reg */
-	/* 0x017c - 0x017f:	reserved */
-
-/*
- *	Bank 3
- */
-/* RAM Random Registers */
-#define B3_RAM_ADDR		0x0180	/* 32 bit	RAM Address, to read or write */
-#define B3_RAM_DATA_LO	0x0184	/* 32 bit	RAM Data Word (low dWord) */
-#define B3_RAM_DATA_HI	0x0188	/* 32 bit	RAM Data Word (high dWord) */
-	/* 0x018c - 0x018f:	reserved */
-
-/* RAM Interface Registers */
-/*
- * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
- * not usable in SW. Please notice these are NOT real timeouts, these are
- * the number of qWords transferred continuously.
- */
-#define B3_RI_WTO_R1	0x0190	/*  8 bit	WR Timeout Queue R1		(TO0) */
-#define B3_RI_WTO_XA1	0x0191	/*  8 bit	WR Timeout Queue XA1	(TO1) */
-#define B3_RI_WTO_XS1	0x0192	/*  8 bit	WR Timeout Queue XS1	(TO2) */
-#define B3_RI_RTO_R1	0x0193	/*  8 bit	RD Timeout Queue R1		(TO3) */
-#define B3_RI_RTO_XA1	0x0194	/*  8 bit	RD Timeout Queue XA1	(TO4) */
-#define B3_RI_RTO_XS1	0x0195	/*  8 bit	RD Timeout Queue XS1	(TO5) */
-#define B3_RI_WTO_R2	0x0196	/*  8 bit	WR Timeout Queue R2		(TO6) */
-#define B3_RI_WTO_XA2	0x0197	/*  8 bit	WR Timeout Queue XA2	(TO7) */
-#define B3_RI_WTO_XS2	0x0198	/*  8 bit	WR Timeout Queue XS2	(TO8) */
-#define B3_RI_RTO_R2	0x0199	/*  8 bit	RD Timeout Queue R2		(TO9) */
-#define B3_RI_RTO_XA2	0x019a	/*  8 bit	RD Timeout Queue XA2	(TO10)*/
-#define B3_RI_RTO_XS2	0x019b	/*  8 bit	RD Timeout Queue XS2	(TO11)*/
-#define B3_RI_TO_VAL	0x019c	/*  8 bit	Current Timeout Count Val */
-	/* 0x019d - 0x019f:	reserved */
-#define B3_RI_CTRL		0x01a0	/* 16 bit	RAM Interface Control Register */
-#define B3_RI_TEST		0x01a2	/*  8 bit	RAM Interface Test Register */
-	/* 0x01a3 - 0x01af:	reserved */
-
-/* MAC Arbiter Registers (GENESIS only) */
-/* these are the no. of qWord transferred continuously and NOT real timeouts */
-#define B3_MA_TOINI_RX1	0x01b0	/*  8 bit	Timeout Init Val Rx Path MAC 1 */
-#define B3_MA_TOINI_RX2	0x01b1	/*  8 bit	Timeout Init Val Rx Path MAC 2 */
-#define B3_MA_TOINI_TX1	0x01b2	/*  8 bit	Timeout Init Val Tx Path MAC 1 */
-#define B3_MA_TOINI_TX2	0x01b3	/*  8 bit	Timeout Init Val Tx Path MAC 2 */
-#define B3_MA_TOVAL_RX1	0x01b4	/*  8 bit	Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_RX2	0x01b5	/*  8 bit	Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_TX1	0x01b6	/*  8 bit	Timeout Value Tx Path MAC 2 */
-#define B3_MA_TOVAL_TX2	0x01b7	/*  8 bit	Timeout Value Tx Path MAC 2 */
-#define B3_MA_TO_CTRL	0x01b8	/* 16 bit	MAC Arbiter Timeout Ctrl Reg */
-#define B3_MA_TO_TEST	0x01ba	/* 16 bit	MAC Arbiter Timeout Test Reg */
-	/* 0x01bc - 0x01bf:	reserved */
-#define B3_MA_RCINI_RX1	0x01c0	/*  8 bit	Recovery Init Val Rx Path MAC 1 */
-#define B3_MA_RCINI_RX2	0x01c1	/*  8 bit	Recovery Init Val Rx Path MAC 2 */
-#define B3_MA_RCINI_TX1	0x01c2	/*  8 bit	Recovery Init Val Tx Path MAC 1 */
-#define B3_MA_RCINI_TX2	0x01c3	/*  8 bit	Recovery Init Val Tx Path MAC 2 */
-#define B3_MA_RCVAL_RX1	0x01c4	/*  8 bit	Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_RX2	0x01c5	/*  8 bit	Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_TX1	0x01c6	/*  8 bit	Recovery Value Tx Path MAC 2 */
-#define B3_MA_RCVAL_TX2	0x01c7	/*  8 bit	Recovery Value Tx Path MAC 2 */
-#define B3_MA_RC_CTRL	0x01c8	/* 16 bit	MAC Arbiter Recovery Ctrl Reg */
-#define B3_MA_RC_TEST	0x01ca	/* 16 bit	MAC Arbiter Recovery Test Reg */
-	/* 0x01cc - 0x01cf:	reserved */
-
-/* Packet Arbiter Registers (GENESIS only) */
-/* these are real timeouts */
-#define B3_PA_TOINI_RX1	0x01d0	/* 16 bit	Timeout Init Val Rx Path MAC 1 */
-	/* 0x01d2 - 0x01d3:	reserved */
-#define B3_PA_TOINI_RX2	0x01d4	/* 16 bit	Timeout Init Val Rx Path MAC 2 */
-	/* 0x01d6 - 0x01d7:	reserved */
-#define B3_PA_TOINI_TX1	0x01d8	/* 16 bit	Timeout Init Val Tx Path MAC 1 */
-	/* 0x01da - 0x01db:	reserved */
-#define B3_PA_TOINI_TX2	0x01dc	/* 16 bit	Timeout Init Val Tx Path MAC 2 */
-	/* 0x01de - 0x01df:	reserved */
-#define B3_PA_TOVAL_RX1	0x01e0	/* 16 bit	Timeout Val Rx Path MAC 1 */
-	/* 0x01e2 - 0x01e3:	reserved */
-#define B3_PA_TOVAL_RX2	0x01e4	/* 16 bit	Timeout Val Rx Path MAC 2 */
-	/* 0x01e6 - 0x01e7:	reserved */
-#define B3_PA_TOVAL_TX1	0x01e8	/* 16 bit	Timeout Val Tx Path MAC 1 */
-	/* 0x01ea - 0x01eb:	reserved */
-#define B3_PA_TOVAL_TX2	0x01ec	/* 16 bit	Timeout Val Tx Path MAC 2 */
-	/* 0x01ee - 0x01ef:	reserved */
-#define B3_PA_CTRL	0x01f0	/* 16 bit	Packet Arbiter Ctrl Register */
-#define B3_PA_TEST	0x01f2	/* 16 bit	Packet Arbiter Test Register */
-	/* 0x01f4 - 0x01ff:	reserved */
-
-/*
- *	Bank 4 - 5
- */
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-#define TXA_ITI_INI		0x0200	/* 32 bit	Tx Arb Interval Timer Init Val*/
-#define TXA_ITI_VAL		0x0204	/* 32 bit	Tx Arb Interval Timer Value */
-#define TXA_LIM_INI		0x0208	/* 32 bit	Tx Arb Limit Counter Init Val */
-#define TXA_LIM_VAL		0x020c	/* 32 bit	Tx Arb Limit Counter Value */
-#define TXA_CTRL		0x0210	/*  8 bit	Tx Arbiter Control Register */
-#define TXA_TEST		0x0211	/*  8 bit	Tx Arbiter Test Register */
-#define TXA_STAT		0x0212	/*  8 bit	Tx Arbiter Status Register */
-	/* 0x0213 - 0x027f:	reserved */
-	/* 0x0280 - 0x0292:	MAC 2 */
-	/* 0x0213 - 0x027f:	reserved */
-
-/*
- *	Bank 6
- */
-/* External registers (GENESIS only) */
-#define B6_EXT_REG		0x0300
-
-/*
- *	Bank 7
- */
-/* This is a copy of the Configuration register file (lower half) */
-#define B7_CFG_SPC		0x0380
-
-/*
- *	Bank 8 - 15
- */
-/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
-#define B8_Q_REGS		0x0400
-
-/* Queue Register Offsets, use Q_ADDR() to access */
-#define Q_D		0x00	/* 8*32	bit	Current Descriptor */
-#define Q_DA_L	0x20	/* 32 bit	Current Descriptor Address Low dWord */
-#define Q_DA_H	0x24	/* 32 bit	Current Descriptor Address High dWord */
-#define Q_AC_L	0x28	/* 32 bit	Current Address Counter Low dWord */
-#define Q_AC_H	0x2c	/* 32 bit	Current Address Counter High dWord */
-#define Q_BC	0x30	/* 32 bit	Current Byte Counter */
-#define Q_CSR	0x34	/* 32 bit	BMU Control/Status Register */
-#define Q_F		0x38	/* 32 bit	Flag Register */
-#define Q_T1	0x3c	/* 32 bit	Test Register 1 */
-#define Q_T1_TR	0x3c	/*  8 bit	Test Register 1 Transfer SM */
-#define Q_T1_WR	0x3d	/*  8 bit	Test Register 1 Write Descriptor SM */
-#define Q_T1_RD	0x3e	/*  8 bit	Test Register 1 Read Descriptor SM */
-#define Q_T1_SV	0x3f	/*  8 bit	Test Register 1 Supervisor SM */
-#define Q_T2	0x40	/* 32 bit	Test Register 2	*/
-#define Q_T3	0x44	/* 32 bit	Test Register 3	*/
-	/* 0x48 - 0x7f:	reserved */
-
-/*
- *	Bank 16 - 23
- */
-/* RAM Buffer Registers */
-#define B16_RAM_REGS	0x0800
-
-/* RAM Buffer Register Offsets, use RB_ADDR() to access */
-#define RB_START		0x00	/* 32 bit	RAM Buffer Start Address */
-#define RB_END			0x04	/* 32 bit	RAM Buffer End Address */
-#define RB_WP			0x08	/* 32 bit	RAM Buffer Write Pointer */
-#define RB_RP			0x0c	/* 32 bit	RAM Buffer Read Pointer */
-#define RB_RX_UTPP		0x10	/* 32 bit	Rx Upper Threshold, Pause Pack */
-#define RB_RX_LTPP		0x14	/* 32 bit	Rx Lower Threshold, Pause Pack */
-#define RB_RX_UTHP		0x18	/* 32 bit	Rx Upper Threshold, High Prio */
-#define RB_RX_LTHP		0x1c	/* 32 bit	Rx Lower Threshold, High Prio */
-	/* 0x10 - 0x1f:	reserved at Tx RAM Buffer Registers */
-#define RB_PC			0x20	/* 32 bit	RAM Buffer Packet Counter */
-#define RB_LEV			0x24	/* 32 bit	RAM Buffer Level Register */
-#define RB_CTRL			0x28	/*  8 bit	RAM Buffer Control Register */
-#define RB_TST1			0x29	/*  8 bit	RAM Buffer Test Register 1 */
-#define RB_TST2			0x2A	/*  8 bit	RAM Buffer Test Register 2 */
-	/* 0x2c - 0x7f:	reserved */
-
-/*
- *	Bank 24
- */
-/*
- * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
- * use MR_ADDR() to access
- */
-#define RX_MFF_EA		0x0c00	/* 32 bit	Receive MAC FIFO End Address */
-#define RX_MFF_WP		0x0c04	/* 32 bit 	Receive MAC FIFO Write Pointer */
-	/* 0x0c08 - 0x0c0b:	reserved */
-#define RX_MFF_RP		0x0c0c	/* 32 bit	Receive MAC FIFO Read Pointer */
-#define RX_MFF_PC		0x0c10	/* 32 bit	Receive MAC FIFO Packet Cnt */
-#define RX_MFF_LEV		0x0c14	/* 32 bit	Receive MAC FIFO Level */
-#define RX_MFF_CTRL1	0x0c18	/* 16 bit	Receive MAC FIFO Control Reg 1*/
-#define RX_MFF_STAT_TO	0x0c1a	/*  8 bit	Receive MAC Status Timeout */
-#define RX_MFF_TIST_TO	0x0c1b	/*  8 bit	Receive MAC Time Stamp Timeout */
-#define RX_MFF_CTRL2	0x0c1c	/*  8 bit	Receive MAC FIFO Control Reg 2*/
-#define RX_MFF_TST1		0x0c1d	/*  8 bit	Receive MAC FIFO Test Reg 1 */
-#define RX_MFF_TST2		0x0c1e	/*  8 bit	Receive MAC FIFO Test Reg 2 */
-	/* 0x0c1f:	reserved */
-#define RX_LED_INI		0x0c20	/* 32 bit	Receive LED Cnt Init Value */
-#define RX_LED_VAL		0x0c24	/* 32 bit	Receive LED Cnt Current Value */
-#define RX_LED_CTRL		0x0c28	/*  8 bit	Receive LED Cnt Control Reg */
-#define RX_LED_TST		0x0c29	/*  8 bit	Receive LED Cnt Test Register */
-	/* 0x0c2a - 0x0c2f:	reserved */
-#define LNK_SYNC_INI	0x0c30	/* 32 bit	Link Sync Cnt Init Value */
-#define LNK_SYNC_VAL	0x0c34	/* 32 bit	Link Sync Cnt Current Value */
-#define LNK_SYNC_CTRL	0x0c38	/*  8 bit	Link Sync Cnt Control Register */
-#define LNK_SYNC_TST	0x0c39	/*  8 bit	Link Sync Cnt Test Register */
-	/* 0x0c3a - 0x0c3b:	reserved */
-#define LNK_LED_REG		0x0c3c	/*  8 bit	Link LED Register */
-	/* 0x0c3d - 0x0c3f:	reserved */
-
-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define RX_GMF_EA		0x0c40	/* 32 bit	Rx GMAC FIFO End Address */
-#define RX_GMF_AF_THR	0x0c44	/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
-#define RX_GMF_CTRL_T	0x0c48	/* 32 bit	Rx GMAC FIFO Control/Test */
-#define RX_GMF_FL_MSK	0x0c4c	/* 32 bit	Rx GMAC FIFO Flush Mask */
-#define RX_GMF_FL_THR	0x0c50	/* 32 bit	Rx GMAC FIFO Flush Threshold */
-	/* 0x0c54 - 0x0c5f:	reserved */
-#define RX_GMF_WP		0x0c60	/* 32 bit 	Rx GMAC FIFO Write Pointer */
-	/* 0x0c64 - 0x0c67:	reserved */
-#define RX_GMF_WLEV		0x0c68	/* 32 bit 	Rx GMAC FIFO Write Level */
-	/* 0x0c6c - 0x0c6f:	reserved */
-#define RX_GMF_RP		0x0c70	/* 32 bit 	Rx GMAC FIFO Read Pointer */
-	/* 0x0c74 - 0x0c77:	reserved */
-#define RX_GMF_RLEV		0x0c78	/* 32 bit 	Rx GMAC FIFO Read Level */
-	/* 0x0c7c - 0x0c7f:	reserved */
-
-/*
- *	Bank 25
- */
-	/* 0x0c80 - 0x0cbf:	MAC 2 */
-	/* 0x0cc0 - 0x0cff:	reserved */
-
-/*
- *	Bank 26
- */
-/*
- * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
- * use MR_ADDR() to access
- */
-#define TX_MFF_EA		0x0d00	/* 32 bit	Transmit MAC FIFO End Address */
-#define TX_MFF_WP		0x0d04	/* 32 bit 	Transmit MAC FIFO WR Pointer */
-#define TX_MFF_WSP		0x0d08	/* 32 bit	Transmit MAC FIFO WR Shadow Ptr */
-#define TX_MFF_RP		0x0d0c	/* 32 bit	Transmit MAC FIFO RD Pointer */
-#define TX_MFF_PC		0x0d10	/* 32 bit	Transmit MAC FIFO Packet Cnt */
-#define TX_MFF_LEV		0x0d14	/* 32 bit	Transmit MAC FIFO Level */
-#define TX_MFF_CTRL1	0x0d18	/* 16 bit	Transmit MAC FIFO Ctrl Reg 1 */
-#define TX_MFF_WAF		0x0d1a	/*  8 bit	Transmit MAC Wait after flush */
-	/* 0x0c1b:	reserved */
-#define TX_MFF_CTRL2	0x0d1c	/*  8 bit	Transmit MAC FIFO Ctrl Reg 2 */
-#define TX_MFF_TST1		0x0d1d	/*  8 bit	Transmit MAC FIFO Test Reg 1 */
-#define TX_MFF_TST2		0x0d1e	/*  8 bit	Transmit MAC FIFO Test Reg 2 */
-	/* 0x0d1f:	reserved */
-#define TX_LED_INI		0x0d20	/* 32 bit	Transmit LED Cnt Init Value */
-#define TX_LED_VAL		0x0d24	/* 32 bit	Transmit LED Cnt Current Val */
-#define TX_LED_CTRL		0x0d28	/*  8 bit	Transmit LED Cnt Control Reg */
-#define TX_LED_TST		0x0d29	/*  8 bit	Transmit LED Cnt Test Reg */
-	/* 0x0d2a - 0x0d3f:	reserved */
-
-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define TX_GMF_EA		0x0d40	/* 32 bit	Tx GMAC FIFO End Address */
-#define TX_GMF_AE_THR	0x0d44	/* 32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
-#define TX_GMF_CTRL_T	0x0d48	/* 32 bit	Tx GMAC FIFO Control/Test */
-	/* 0x0d4c - 0x0d5f:	reserved */
-#define TX_GMF_WP		0x0d60	/* 32 bit 	Tx GMAC FIFO Write Pointer */
-#define TX_GMF_WSP		0x0d64	/* 32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
-#define TX_GMF_WLEV		0x0d68	/* 32 bit 	Tx GMAC FIFO Write Level */
-	/* 0x0d6c - 0x0d6f:	reserved */
-#define TX_GMF_RP		0x0d70	/* 32 bit 	Tx GMAC FIFO Read Pointer */
-#define TX_GMF_RSTP		0x0d74	/* 32 bit 	Tx GMAC FIFO Restart Pointer */
-#define TX_GMF_RLEV		0x0d78	/* 32 bit 	Tx GMAC FIFO Read Level */
-	/* 0x0d7c - 0x0d7f:	reserved */
-
-/*
- *	Bank 27
- */
-	/* 0x0d80 - 0x0dbf:	MAC 2 */
-	/* 0x0daa - 0x0dff:	reserved */
-
-/*
- *	Bank 28
- */
-/* Descriptor Poll Timer Registers */
-#define B28_DPT_INI		0x0e00	/* 24 bit	Descriptor Poll Timer Init Val */
-#define B28_DPT_VAL		0x0e04	/* 24 bit	Descriptor Poll Timer Curr Val */
-#define B28_DPT_CTRL	0x0e08	/*  8 bit	Descriptor Poll Timer Ctrl Reg */
-	/* 0x0e09:	reserved */
-#define B28_DPT_TST		0x0e0a	/*  8 bit	Descriptor Poll Timer Test Reg */
-	/* 0x0e0b:	reserved */
-
-/* Time Stamp Timer Registers (YUKON only) */
-	/* 0x0e10:	reserved */
-#define GMAC_TI_ST_VAL	0x0e14	/* 32 bit	Time Stamp Timer Curr Val */
-#define GMAC_TI_ST_CTRL	0x0e18	/*  8 bit	Time Stamp Timer Ctrl Reg */
-	/* 0x0e19:	reserved */
-#define GMAC_TI_ST_TST	0x0e1a	/*  8 bit	Time Stamp Timer Test Reg */
-	/* 0x0e1b - 0x0e7f:	reserved */
-
-/*
- *	Bank 29
- */
-	/* 0x0e80 - 0x0efc:	reserved */
-
-/*
- *	Bank 30
- */
-/* GMAC and GPHY Control Registers (YUKON only) */
-#define GMAC_CTRL		0x0f00	/* 32 bit	GMAC Control Reg */
-#define GPHY_CTRL		0x0f04	/* 32 bit	GPHY Control Reg */
-#define GMAC_IRQ_SRC	0x0f08	/*  8 bit	GMAC Interrupt Source Reg */
-	/* 0x0f09 - 0x0f0b:	reserved */
-#define GMAC_IRQ_MSK	0x0f0c	/*  8 bit	GMAC Interrupt Mask Reg */
-	/* 0x0f0d - 0x0f0f:	reserved */
-#define GMAC_LINK_CTRL	0x0f10	/* 16 bit	Link Control Reg */
-	/* 0x0f14 - 0x0f1f:	reserved */
-
-/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
-
-#define WOL_REG_OFFS	0x20	/* HW-Bug: Address is + 0x20 against spec. */
-
-#define WOL_CTRL_STAT	0x0f20	/* 16 bit	WOL Control/Status Reg */
-#define WOL_MATCH_CTL	0x0f22	/*  8 bit	WOL Match Control Reg */
-#define WOL_MATCH_RES	0x0f23	/*  8 bit	WOL Match Result Reg */
-#define WOL_MAC_ADDR_LO	0x0f24	/* 32 bit	WOL MAC Address Low */
-#define WOL_MAC_ADDR_HI	0x0f28	/* 16 bit	WOL MAC Address High */
-#define WOL_PATT_RPTR	0x0f2c	/*  8 bit	WOL Pattern Read Ptr */
-
-/* use this macro to access above registers */
-#define WOL_REG(Reg)	((Reg) + (pAC->GIni.GIWolOffs))
-
-
-/* WOL Pattern Length Registers (YUKON only) */
-
-#define WOL_PATT_LEN_LO	0x0f30		/* 32 bit	WOL Pattern Length 3..0 */
-#define WOL_PATT_LEN_HI	0x0f34		/* 24 bit	WOL Pattern Length 6..4 */
-
-/* WOL Pattern Counter Registers (YUKON only) */
-
-#define WOL_PATT_CNT_0	0x0f38		/* 32 bit	WOL Pattern Counter 3..0 */
-#define WOL_PATT_CNT_4	0x0f3c		/* 24 bit	WOL Pattern Counter 6..4 */
-	/* 0x0f40 - 0x0f7f:	reserved */
-
-/*
- *	Bank 31
- */
-/* 0x0f80 - 0x0fff:	reserved */
-
-/*
- *	Bank 32	- 33
- */
-#define WOL_PATT_RAM_1	0x1000	/*  WOL Pattern RAM Link 1 */
-
-/*
- *	Bank 0x22 - 0x3f
- */
-/* 0x1100 - 0x1fff:	reserved */
-
-/*
- *	Bank 0x40 - 0x4f
- */
-#define BASE_XMAC_1		0x2000	/* XMAC 1 registers */
-
-/*
- *	Bank 0x50 - 0x5f
- */
-
-#define BASE_GMAC_1		0x2800	/* GMAC 1 registers */
-
-/*
- *	Bank 0x60 - 0x6f
- */
-#define BASE_XMAC_2		0x3000	/* XMAC 2 registers */
-
-/*
- *	Bank 0x70 - 0x7f
- */
-#define BASE_GMAC_2		0x3800	/* GMAC 2 registers */
-
-/*
- *	Control Register Bit Definitions:
- */
-/*	B0_RAP		8 bit	Register Address Port */
-								/* Bit 7:	reserved */
-#define RAP_RAP			0x3f	/* Bit 6..0:	0 = block 0,..,6f = block 6f */
-
-/*	B0_CTST			16 bit	Control/Status register */
-								/* Bit 15..14:	reserved */
-#define CS_CLK_RUN_HOT	BIT_13S		/* CLK_RUN hot m. (YUKON-Lite only) */
-#define CS_CLK_RUN_RST	BIT_12S		/* CLK_RUN reset  (YUKON-Lite only) */
-#define CS_CLK_RUN_ENA	BIT_11S		/* CLK_RUN enable (YUKON-Lite only) */
-#define CS_VAUX_AVAIL	BIT_10S		/* VAUX available (YUKON only) */
-#define CS_BUS_CLOCK	BIT_9S		/* Bus Clock 0/1 = 33/66 MHz */
-#define CS_BUS_SLOT_SZ	BIT_8S		/* Slot Size 0/1 = 32/64 bit slot */
-#define CS_ST_SW_IRQ	BIT_7S		/* Set IRQ SW Request */
-#define CS_CL_SW_IRQ	BIT_6S		/* Clear IRQ SW Request */
-#define CS_STOP_DONE	BIT_5S		/* Stop Master is finished */
-#define CS_STOP_MAST	BIT_4S		/* Command Bit to stop the master */
-#define CS_MRST_CLR		BIT_3S		/* Clear Master reset	*/
-#define CS_MRST_SET		BIT_2S		/* Set Master reset	*/
-#define CS_RST_CLR		BIT_1S		/* Clear Software reset	*/
-#define CS_RST_SET		BIT_0S		/* Set   Software reset	*/
-
-/*	B0_LED			 8 Bit	LED register */
-								/* Bit  7.. 2:	reserved */
-#define LED_STAT_ON		BIT_1S		/* Status LED on	*/
-#define LED_STAT_OFF	BIT_0S		/* Status LED off	*/
-
-/*	B0_POWER_CTRL	 8 Bit	Power Control reg (YUKON only) */
-#define PC_VAUX_ENA		BIT_7		/* Switch VAUX Enable  */
-#define PC_VAUX_DIS		BIT_6       /* Switch VAUX Disable */
-#define PC_VCC_ENA		BIT_5       /* Switch VCC Enable  */
-#define PC_VCC_DIS		BIT_4       /* Switch VCC Disable */
-#define PC_VAUX_ON		BIT_3       /* Switch VAUX On  */
-#define PC_VAUX_OFF		BIT_2       /* Switch VAUX Off */
-#define PC_VCC_ON		BIT_1       /* Switch VCC On  */
-#define PC_VCC_OFF		BIT_0       /* Switch VCC Off */
-
-/*	B0_ISRC			32 bit	Interrupt Source Register */
-/*	B0_IMSK			32 bit	Interrupt Mask Register */
-/*	B0_SP_ISRC		32 bit	Special Interrupt Source Reg */
-/*	B2_IRQM_MSK 	32 bit	IRQ Moderation Mask */
-#define IS_ALL_MSK		0xbfffffffUL	/* All Interrupt bits */
-#define IS_HW_ERR		BIT_31		/* Interrupt HW Error */
-								/* Bit 30:	reserved */
-#define IS_PA_TO_RX1	BIT_29		/* Packet Arb Timeout Rx1 */
-#define IS_PA_TO_RX2	BIT_28		/* Packet Arb Timeout Rx2 */
-#define IS_PA_TO_TX1	BIT_27		/* Packet Arb Timeout Tx1 */
-#define IS_PA_TO_TX2	BIT_26		/* Packet Arb Timeout Tx2 */
-#define IS_I2C_READY	BIT_25		/* IRQ on end of I2C Tx */
-#define IS_IRQ_SW		BIT_24		/* SW forced IRQ	*/
-#define IS_EXT_REG		BIT_23		/* IRQ from LM80 or PHY (GENESIS only) */
-									/* IRQ from PHY (YUKON only) */
-#define IS_TIMINT		BIT_22		/* IRQ from Timer	*/
-#define IS_MAC1			BIT_21		/* IRQ from MAC 1	*/
-#define IS_LNK_SYNC_M1	BIT_20		/* Link Sync Cnt wrap MAC 1 */
-#define IS_MAC2			BIT_19		/* IRQ from MAC 2	*/
-#define IS_LNK_SYNC_M2	BIT_18		/* Link Sync Cnt wrap MAC 2 */
-/* Receive Queue 1 */
-#define IS_R1_B			BIT_17		/* Q_R1 End of Buffer */
-#define IS_R1_F			BIT_16		/* Q_R1 End of Frame */
-#define IS_R1_C			BIT_15		/* Q_R1 Encoding Error */
-/* Receive Queue 2 */
-#define IS_R2_B			BIT_14		/* Q_R2 End of Buffer */
-#define IS_R2_F			BIT_13		/* Q_R2 End of Frame */
-#define IS_R2_C			BIT_12		/* Q_R2 Encoding Error */
-/* Synchronous Transmit Queue 1 */
-#define IS_XS1_B		BIT_11		/* Q_XS1 End of Buffer */
-#define IS_XS1_F		BIT_10		/* Q_XS1 End of Frame */
-#define IS_XS1_C		BIT_9		/* Q_XS1 Encoding Error */
-/* Asynchronous Transmit Queue 1 */
-#define IS_XA1_B		BIT_8		/* Q_XA1 End of Buffer */
-#define IS_XA1_F		BIT_7		/* Q_XA1 End of Frame */
-#define IS_XA1_C		BIT_6		/* Q_XA1 Encoding Error */
-/* Synchronous Transmit Queue 2 */
-#define IS_XS2_B		BIT_5		/* Q_XS2 End of Buffer */
-#define IS_XS2_F		BIT_4		/* Q_XS2 End of Frame */
-#define IS_XS2_C		BIT_3		/* Q_XS2 Encoding Error */
-/* Asynchronous Transmit Queue 2 */
-#define IS_XA2_B		BIT_2		/* Q_XA2 End of Buffer */
-#define IS_XA2_F		BIT_1		/* Q_XA2 End of Frame */
-#define IS_XA2_C		BIT_0		/* Q_XA2 Encoding Error */
-
-
-/*	B0_HWE_ISRC		32 bit	HW Error Interrupt Src Reg */
-/*	B0_HWE_IMSK		32 bit	HW Error Interrupt Mask Reg */
-/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
-#define IS_ERR_MSK		0x00000fffL	/* 		All Error bits */
-								/* Bit 31..14:	reserved */
-#define IS_IRQ_TIST_OV	BIT_13	/* Time Stamp Timer Overflow (YUKON only) */
-#define IS_IRQ_SENSOR	BIT_12	/* IRQ from Sensor (YUKON only) */
-#define IS_IRQ_MST_ERR	BIT_11	/* IRQ master error detected */
-#define IS_IRQ_STAT		BIT_10	/* IRQ status exception */
-#define IS_NO_STAT_M1	BIT_9	/* No Rx Status from MAC 1 */
-#define IS_NO_STAT_M2	BIT_8	/* No Rx Status from MAC 2 */
-#define IS_NO_TIST_M1	BIT_7	/* No Time Stamp from MAC 1 */
-#define IS_NO_TIST_M2	BIT_6	/* No Time Stamp from MAC 2 */
-#define IS_RAM_RD_PAR	BIT_5	/* RAM Read  Parity Error */
-#define IS_RAM_WR_PAR	BIT_4	/* RAM Write Parity Error */
-#define IS_M1_PAR_ERR	BIT_3	/* MAC 1 Parity Error */
-#define IS_M2_PAR_ERR	BIT_2	/* MAC 2 Parity Error */
-#define IS_R1_PAR_ERR	BIT_1	/* Queue R1 Parity Error */
-#define IS_R2_PAR_ERR	BIT_0	/* Queue R2 Parity Error */
-
-/*	B2_CONN_TYP		 8 bit	Connector type */
-/*	B2_PMD_TYP		 8 bit	PMD type */
-/*	Values of connector and PMD type comply to SysKonnect internal std */
-
-/*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
-#define CFG_CHIP_R_MSK	(0xf<<4)	/* Bit 7.. 4: Chip Revision */
-									/* Bit 3.. 2:	reserved */
-#define CFG_DIS_M2_CLK	BIT_1S		/* Disable Clock for 2nd MAC */
-#define CFG_SNG_MAC		BIT_0S		/* MAC Config: 0=2 MACs / 1=1 MAC*/
-
-/*	B2_CHIP_ID		 8 bit 	Chip Identification Number */
-#define CHIP_ID_GENESIS		0x0a	/* Chip ID for GENESIS */
-#define CHIP_ID_YUKON		0xb0	/* Chip ID for YUKON */
-#define CHIP_ID_YUKON_LITE	0xb1	/* Chip ID for YUKON-Lite (Rev. A1-A3) */
-#define CHIP_ID_YUKON_LP	0xb2	/* Chip ID for YUKON-LP */
-
-#define CHIP_REV_YU_LITE_A1	3		/* Chip Rev. for YUKON-Lite A1,A2 */
-#define CHIP_REV_YU_LITE_A3	7		/* Chip Rev. for YUKON-Lite A3 */
-
-/*	B2_FAR			32 bit	Flash-Prom Addr Reg/Cnt */
-#define FAR_ADDR		0x1ffffL	/* Bit 16.. 0:	FPROM Address mask */
-
-/*	B2_LD_CTRL		 8 bit	EPROM loader control register */
-/*	Bits are currently reserved */
-
-/*	B2_LD_TEST		 8 bit	EPROM loader test register */
-								/* Bit 7.. 4:	reserved */
-#define LD_T_ON			BIT_3S	/* Loader Test mode on */
-#define LD_T_OFF		BIT_2S	/* Loader Test mode off */
-#define LD_T_STEP		BIT_1S	/* Decrement FPROM addr. Counter */
-#define LD_START		BIT_0S	/* Start loading FPROM */
-
-/*
- *	Timer Section
- */
-/*	B2_TI_CTRL		 8 bit	Timer control */
-/*	B2_IRQM_CTRL	 8 bit	IRQ Moderation Timer Control */
-								/* Bit 7.. 3:	reserved */
-#define TIM_START		BIT_2S	/* Start Timer */
-#define TIM_STOP		BIT_1S	/* Stop  Timer */
-#define TIM_CLR_IRQ		BIT_0S	/* Clear Timer IRQ (!IRQM) */
-
-/*	B2_TI_TEST		 8 Bit	Timer Test */
-/*	B2_IRQM_TEST	 8 bit	IRQ Moderation Timer Test */
-/*	B28_DPT_TST		 8 bit	Descriptor Poll Timer Test Reg */
-								/* Bit 7.. 3:	reserved */
-#define TIM_T_ON		BIT_2S	/* Test mode on */
-#define TIM_T_OFF		BIT_1S	/* Test mode off */
-#define TIM_T_STEP		BIT_0S	/* Test step */
-
-/*	B28_DPT_INI	32 bit	Descriptor Poll Timer Init Val */
-/*	B28_DPT_VAL	32 bit	Descriptor Poll Timer Curr Val */
-								/* Bit 31..24:	reserved */
-#define DPT_MSK		0x00ffffffL	/* Bit 23.. 0:	Desc Poll Timer Bits */
-
-/*	B28_DPT_CTRL	 8 bit	Descriptor Poll Timer Ctrl Reg */
-								/* Bit  7.. 2:	reserved */
-#define DPT_START		BIT_1S	/* Start Descriptor Poll Timer */
-#define DPT_STOP		BIT_0S	/* Stop  Descriptor Poll Timer */
-
-/*	B2_E_3			 8 bit 	lower 4 bits used for HW self test result */
-#define B2_E3_RES_MASK	0x0f
-
-/*	B2_TST_CTRL1	 8 bit	Test Control Register 1 */
-#define TST_FRC_DPERR_MR	BIT_7S	/* force DATAPERR on MST RD */
-#define TST_FRC_DPERR_MW	BIT_6S	/* force DATAPERR on MST WR */
-#define TST_FRC_DPERR_TR	BIT_5S	/* force DATAPERR on TRG RD */
-#define TST_FRC_DPERR_TW	BIT_4S	/* force DATAPERR on TRG WR */
-#define TST_FRC_APERR_M		BIT_3S	/* force ADDRPERR on MST */
-#define TST_FRC_APERR_T		BIT_2S	/* force ADDRPERR on TRG */
-#define TST_CFG_WRITE_ON	BIT_1S	/* Enable  Config Reg WR */
-#define TST_CFG_WRITE_OFF	BIT_0S	/* Disable Config Reg WR */
-
-/*	B2_TST_CTRL2	 8 bit	Test Control Register 2 */
-									/* Bit 7.. 4:	reserved */
-			/* force the following error on the next master read/write	*/
-#define TST_FRC_DPERR_MR64	BIT_3S	/* DataPERR RD 64	*/
-#define TST_FRC_DPERR_MW64	BIT_2S	/* DataPERR WR 64	*/
-#define TST_FRC_APERR_1M64	BIT_1S	/* AddrPERR on 1. phase */
-#define TST_FRC_APERR_2M64	BIT_0S	/* AddrPERR on 2. phase */
-
-/*	B2_GP_IO		32 bit	General Purpose I/O Register */
-							/* Bit 31..26:	reserved */
-#define GP_DIR_9	BIT_25	/* IO_9 direct, 0=In/1=Out */
-#define GP_DIR_8	BIT_24	/* IO_8 direct, 0=In/1=Out */
-#define GP_DIR_7	BIT_23	/* IO_7 direct, 0=In/1=Out */
-#define GP_DIR_6	BIT_22	/* IO_6 direct, 0=In/1=Out */
-#define GP_DIR_5	BIT_21	/* IO_5 direct, 0=In/1=Out */
-#define GP_DIR_4	BIT_20	/* IO_4 direct, 0=In/1=Out */
-#define GP_DIR_3	BIT_19	/* IO_3 direct, 0=In/1=Out */
-#define GP_DIR_2	BIT_18	/* IO_2 direct, 0=In/1=Out */
-#define GP_DIR_1	BIT_17	/* IO_1 direct, 0=In/1=Out */
-#define GP_DIR_0	BIT_16	/* IO_0 direct, 0=In/1=Out */
-						/* Bit 15..10:	reserved */
-#define GP_IO_9		BIT_9	/* IO_9 pin */
-#define GP_IO_8		BIT_8	/* IO_8 pin */
-#define GP_IO_7		BIT_7	/* IO_7 pin */
-#define GP_IO_6		BIT_6	/* IO_6 pin */
-#define GP_IO_5		BIT_5	/* IO_5 pin */
-#define GP_IO_4		BIT_4	/* IO_4 pin */
-#define GP_IO_3		BIT_3	/* IO_3 pin */
-#define GP_IO_2		BIT_2	/* IO_2 pin */
-#define GP_IO_1		BIT_1	/* IO_1 pin */
-#define GP_IO_0		BIT_0	/* IO_0 pin */
-
-/*	B2_I2C_CTRL		32 bit	I2C HW Control Register */
-#define I2C_FLAG		BIT_31		/* Start read/write if WR */
-#define I2C_ADDR		(0x7fffL<<16)	/* Bit 30..16:	Addr to be RD/WR */
-#define I2C_DEV_SEL		(0x7fL<<9)		/* Bit 15.. 9:	I2C Device Select */
-								/* Bit	8.. 5:	reserved	*/
-#define I2C_BURST_LEN	BIT_4		/* Burst Len, 1/4 bytes */
-#define I2C_DEV_SIZE	(7<<1)		/* Bit	3.. 1:	I2C Device Size	*/
-#define I2C_025K_DEV	(0<<1)		/*		0: 256 Bytes or smal. */
-#define I2C_05K_DEV		(1<<1)		/* 		1: 512	Bytes	*/
-#define I2C_1K_DEV		(2<<1)		/*		2: 1024 Bytes	*/
-#define I2C_2K_DEV		(3<<1)		/*		3: 2048	Bytes	*/
-#define I2C_4K_DEV		(4<<1)		/*		4: 4096 Bytes	*/
-#define I2C_8K_DEV		(5<<1)		/*		5: 8192 Bytes	*/
-#define I2C_16K_DEV		(6<<1)		/*		6: 16384 Bytes	*/
-#define I2C_32K_DEV		(7<<1)		/*		7: 32768 Bytes	*/
-#define I2C_STOP		BIT_0		/* Interrupt I2C transfer */
-
-/*	B2_I2C_IRQ		32 bit	I2C HW IRQ Register */
-								/* Bit 31.. 1	reserved */
-#define I2C_CLR_IRQ		BIT_0	/* Clear I2C IRQ */
-
-/*	B2_I2C_SW		32 bit (8 bit access)	I2C HW SW Port Register */
-								/* Bit  7.. 3:	reserved */
-#define I2C_DATA_DIR	BIT_2S		/* direction of I2C_DATA */
-#define I2C_DATA		BIT_1S		/* I2C Data Port	*/
-#define I2C_CLK			BIT_0S		/* I2C Clock Port	*/
-
-/*
- * I2C Address
- */
-#define I2C_SENS_ADDR	LM80_ADDR	/* I2C Sensor Address, (Volt and Temp)*/
-
-
-/*	B2_BSC_CTRL		 8 bit	Blink Source Counter Control */
-							/* Bit  7.. 2:	reserved */
-#define BSC_START	BIT_1S		/* Start Blink Source Counter */
-#define BSC_STOP	BIT_0S		/* Stop  Blink Source Counter */
-
-/*	B2_BSC_STAT		 8 bit	Blink Source Counter Status */
-							/* Bit  7.. 1:	reserved */
-#define BSC_SRC		BIT_0S		/* Blink Source, 0=Off / 1=On */
-
-/*	B2_BSC_TST		16 bit	Blink Source Counter Test Reg */
-#define BSC_T_ON	BIT_2S		/* Test mode on */
-#define BSC_T_OFF	BIT_1S		/* Test mode off */
-#define BSC_T_STEP	BIT_0S		/* Test step */
-
-
-/*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
-					/* Bit 31..19:	reserved */
-#define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
-
-/* RAM Interface Registers */
-/*	B3_RI_CTRL		16 bit	RAM Iface Control Register */
-								/* Bit 15..10:	reserved */
-#define RI_CLR_RD_PERR	BIT_9S	/* Clear IRQ RAM Read Parity Err */
-#define RI_CLR_WR_PERR	BIT_8S	/* Clear IRQ RAM Write Parity Err*/
-								/* Bit	7.. 2:	reserved */
-#define RI_RST_CLR		BIT_1S	/* Clear RAM Interface Reset */
-#define RI_RST_SET		BIT_0S	/* Set   RAM Interface Reset */
-
-/*	B3_RI_TEST		 8 bit	RAM Iface Test Register */
-								/* Bit 15.. 4:	reserved */
-#define RI_T_EV			BIT_3S	/* Timeout Event occured */
-#define RI_T_ON			BIT_2S	/* Timeout Timer Test On */
-#define RI_T_OFF		BIT_1S	/* Timeout Timer Test Off */
-#define RI_T_STEP		BIT_0S	/* Timeout Timer Step */
-
-/* MAC Arbiter Registers */
-/*	B3_MA_TO_CTRL	16 bit	MAC Arbiter Timeout Ctrl Reg */
-								/* Bit 15.. 4:	reserved */
-#define MA_FOE_ON		BIT_3S	/* XMAC Fast Output Enable ON */
-#define MA_FOE_OFF		BIT_2S	/* XMAC Fast Output Enable OFF */
-#define MA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
-#define MA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
-
-/*	B3_MA_RC_CTRL	16 bit	MAC Arbiter Recovery Ctrl Reg */
-								/* Bit 15.. 8:	reserved */
-#define MA_ENA_REC_TX2	BIT_7S	/* Enable  Recovery Timer TX2 */
-#define MA_DIS_REC_TX2	BIT_6S	/* Disable Recovery Timer TX2 */
-#define MA_ENA_REC_TX1	BIT_5S	/* Enable  Recovery Timer TX1 */
-#define MA_DIS_REC_TX1	BIT_4S	/* Disable Recovery Timer TX1 */
-#define MA_ENA_REC_RX2	BIT_3S	/* Enable  Recovery Timer RX2 */
-#define MA_DIS_REC_RX2	BIT_2S	/* Disable Recovery Timer RX2 */
-#define MA_ENA_REC_RX1	BIT_1S	/* Enable  Recovery Timer RX1 */
-#define MA_DIS_REC_RX1	BIT_0S	/* Disable Recovery Timer RX1 */
-
-/* Packet Arbiter Registers */
-/*	B3_PA_CTRL		16 bit	Packet Arbiter Ctrl Register */
-								/* Bit 15..14:	reserved */
-#define PA_CLR_TO_TX2	BIT_13S	/* Clear IRQ Packet Timeout TX2 */
-#define PA_CLR_TO_TX1	BIT_12S	/* Clear IRQ Packet Timeout TX1 */
-#define PA_CLR_TO_RX2	BIT_11S	/* Clear IRQ Packet Timeout RX2 */
-#define PA_CLR_TO_RX1	BIT_10S	/* Clear IRQ Packet Timeout RX1 */
-#define PA_ENA_TO_TX2	BIT_9S	/* Enable  Timeout Timer TX2 */
-#define PA_DIS_TO_TX2	BIT_8S	/* Disable Timeout Timer TX2 */
-#define PA_ENA_TO_TX1	BIT_7S	/* Enable  Timeout Timer TX1 */
-#define PA_DIS_TO_TX1	BIT_6S	/* Disable Timeout Timer TX1 */
-#define PA_ENA_TO_RX2	BIT_5S	/* Enable  Timeout Timer RX2 */
-#define PA_DIS_TO_RX2	BIT_4S	/* Disable Timeout Timer RX2 */
-#define PA_ENA_TO_RX1	BIT_3S	/* Enable  Timeout Timer RX1 */
-#define PA_DIS_TO_RX1	BIT_2S	/* Disable Timeout Timer RX1 */
-#define PA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
-#define PA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
-
-#define PA_ENA_TO_ALL	(PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
-						PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
-
-/* Rx/Tx Path related Arbiter Test Registers */
-/*	B3_MA_TO_TEST	16 bit	MAC Arbiter Timeout Test Reg */
-/*	B3_MA_RC_TEST	16 bit	MAC Arbiter Recovery Test Reg */
-/*	B3_PA_TEST		16 bit	Packet Arbiter Test Register */
-/*			Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
-#define TX2_T_EV	BIT_15S		/* TX2 Timeout/Recv Event occured */
-#define TX2_T_ON	BIT_14S		/* TX2 Timeout/Recv Timer Test On */
-#define TX2_T_OFF	BIT_13S		/* TX2 Timeout/Recv Timer Tst Off */
-#define TX2_T_STEP	BIT_12S		/* TX2 Timeout/Recv Timer Step */
-#define TX1_T_EV	BIT_11S		/* TX1 Timeout/Recv Event occured */
-#define TX1_T_ON	BIT_10S		/* TX1 Timeout/Recv Timer Test On */
-#define TX1_T_OFF	BIT_9S		/* TX1 Timeout/Recv Timer Tst Off */
-#define TX1_T_STEP	BIT_8S		/* TX1 Timeout/Recv Timer Step */
-#define RX2_T_EV	BIT_7S		/* RX2 Timeout/Recv Event occured */
-#define RX2_T_ON	BIT_6S		/* RX2 Timeout/Recv Timer Test On */
-#define RX2_T_OFF	BIT_5S		/* RX2 Timeout/Recv Timer Tst Off */
-#define RX2_T_STEP	BIT_4S		/* RX2 Timeout/Recv Timer Step */
-#define RX1_T_EV	BIT_3S		/* RX1 Timeout/Recv Event occured */
-#define RX1_T_ON	BIT_2S		/* RX1 Timeout/Recv Timer Test On */
-#define RX1_T_OFF	BIT_1S		/* RX1 Timeout/Recv Timer Tst Off */
-#define RX1_T_STEP	BIT_0S		/* RX1 Timeout/Recv Timer Step */
-
-
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-/*	TXA_ITI_INI		32 bit	Tx Arb Interval Timer Init Val */
-/*	TXA_ITI_VAL		32 bit	Tx Arb Interval Timer Value */
-/*	TXA_LIM_INI		32 bit	Tx Arb Limit Counter Init Val */
-/*	TXA_LIM_VAL		32 bit	Tx Arb Limit Counter Value */
-								/* Bit 31..24:	reserved */
-#define TXA_MAX_VAL	0x00ffffffUL/* Bit 23.. 0:	Max TXA Timer/Cnt Val */
-
-/*	TXA_CTRL		 8 bit	Tx Arbiter Control Register */
-#define TXA_ENA_FSYNC	BIT_7S	/* Enable  force of sync Tx queue */
-#define TXA_DIS_FSYNC	BIT_6S	/* Disable force of sync Tx queue */
-#define TXA_ENA_ALLOC	BIT_5S	/* Enable  alloc of free bandwidth */
-#define TXA_DIS_ALLOC	BIT_4S	/* Disable alloc of free bandwidth */
-#define TXA_START_RC	BIT_3S	/* Start sync Rate Control */
-#define TXA_STOP_RC		BIT_2S	/* Stop  sync Rate Control */
-#define TXA_ENA_ARB		BIT_1S	/* Enable  Tx Arbiter */
-#define TXA_DIS_ARB		BIT_0S	/* Disable Tx Arbiter */
-
-/*	TXA_TEST		 8 bit	Tx Arbiter Test Register */
-								/* Bit 7.. 6:	reserved */
-#define TXA_INT_T_ON	BIT_5S	/* Tx Arb Interval Timer Test On */
-#define TXA_INT_T_OFF	BIT_4S	/* Tx Arb Interval Timer Test Off */
-#define TXA_INT_T_STEP	BIT_3S	/* Tx Arb Interval Timer Step */
-#define TXA_LIM_T_ON	BIT_2S	/* Tx Arb Limit Timer Test On */
-#define TXA_LIM_T_OFF	BIT_1S	/* Tx Arb Limit Timer Test Off */
-#define TXA_LIM_T_STEP	BIT_0S	/* Tx Arb Limit Timer Step */
-
-/*	TXA_STAT		 8 bit	Tx Arbiter Status Register */
-								/* Bit 7.. 1:	reserved */
-#define TXA_PRIO_XS		BIT_0S	/* sync queue has prio to send */
-
-/*	Q_BC			32 bit	Current Byte Counter */
-								/* Bit 31..16:	reserved */
-#define BC_MAX			0xffff	/* Bit 15.. 0:	Byte counter */
-
-/* BMU Control Status Registers */
-/*	B0_R1_CSR		32 bit	BMU Ctrl/Stat Rx Queue 1 */
-/*	B0_R2_CSR		32 bit	BMU Ctrl/Stat Rx Queue 2 */
-/*	B0_XA1_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
-/*	B0_XS1_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 1 */
-/*	B0_XA2_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
-/*	B0_XS2_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 2 */
-/*	Q_CSR			32 bit	BMU Control/Status Register */
-								/* Bit 31..25:	reserved */
-#define CSR_SV_IDLE		BIT_24		/* BMU SM Idle */
-								/* Bit 23..22:	reserved */
-#define CSR_DESC_CLR	BIT_21		/* Clear Reset for Descr */
-#define CSR_DESC_SET	BIT_20		/* Set   Reset for Descr */
-#define CSR_FIFO_CLR	BIT_19		/* Clear Reset for FIFO */
-#define CSR_FIFO_SET	BIT_18		/* Set   Reset for FIFO */
-#define CSR_HPI_RUN		BIT_17		/* Release HPI SM */
-#define CSR_HPI_RST		BIT_16		/* Reset   HPI SM to Idle */
-#define CSR_SV_RUN		BIT_15		/* Release Supervisor SM */
-#define CSR_SV_RST		BIT_14		/* Reset   Supervisor SM */
-#define CSR_DREAD_RUN	BIT_13		/* Release Descr Read SM */
-#define CSR_DREAD_RST	BIT_12		/* Reset   Descr Read SM */
-#define CSR_DWRITE_RUN	BIT_11		/* Release Descr Write SM */
-#define CSR_DWRITE_RST	BIT_10		/* Reset   Descr Write SM */
-#define CSR_TRANS_RUN	BIT_9		/* Release Transfer SM */
-#define CSR_TRANS_RST	BIT_8		/* Reset   Transfer SM */
-#define CSR_ENA_POL		BIT_7		/* Enable  Descr Polling */
-#define CSR_DIS_POL		BIT_6		/* Disable Descr Polling */
-#define CSR_STOP		BIT_5		/* Stop  Rx/Tx Queue */
-#define CSR_START		BIT_4		/* Start Rx/Tx Queue */
-#define CSR_IRQ_CL_P	BIT_3		/* (Rx)	Clear Parity IRQ */
-#define CSR_IRQ_CL_B	BIT_2		/* Clear EOB IRQ */
-#define CSR_IRQ_CL_F	BIT_1		/* Clear EOF IRQ */
-#define CSR_IRQ_CL_C	BIT_0		/* Clear ERR IRQ */
-
-#define CSR_SET_RESET	(CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
-						CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
-						CSR_TRANS_RST)
-#define CSR_CLR_RESET	(CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
-						CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
-						CSR_TRANS_RUN)
-
-/*	Q_F				32 bit	Flag Register */
-									/* Bit 31..28:	reserved */
-#define F_ALM_FULL		BIT_27		/* Rx FIFO: almost full */
-#define F_EMPTY			BIT_27		/* Tx FIFO: empty flag */
-#define F_FIFO_EOF		BIT_26		/* Tag (EOF Flag) bit in FIFO */
-#define F_WM_REACHED	BIT_25		/* Watermark reached */
-									/* reserved */
-#define F_FIFO_LEVEL	(0x1fL<<16)	/* Bit 23..16:	# of Qwords in FIFO */
-									/* Bit 15..11: 	reserved */
-#define F_WATER_MARK	0x0007ffL	/* Bit 10.. 0:	Watermark */
-
-/*	Q_T1			32 bit	Test Register 1 */
-/*		Holds four State Machine control Bytes */
-#define SM_CTRL_SV_MSK	(0xffL<<24)	/* Bit 31..24:	Control Supervisor SM */
-#define SM_CTRL_RD_MSK	(0xffL<<16)	/* Bit 23..16:	Control Read Desc SM */
-#define SM_CTRL_WR_MSK	(0xffL<<8)	/* Bit 15.. 8:	Control Write Desc SM */
-#define SM_CTRL_TR_MSK	0xffL		/* Bit	7.. 0:	Control Transfer SM */
-
-/*	Q_T1_TR			 8 bit	Test Register 1 Transfer SM */
-/*	Q_T1_WR			 8 bit	Test Register 1 Write Descriptor SM */
-/*	Q_T1_RD			 8 bit	Test Register 1 Read Descriptor SM */
-/*	Q_T1_SV			 8 bit	Test Register 1 Supervisor SM */
-
-/* The control status byte of each machine looks like ... */
-#define SM_STATE		0xf0	/* Bit 7.. 4:	State which shall be loaded */
-#define SM_LOAD			BIT_3S	/* Load the SM with SM_STATE */
-#define SM_TEST_ON		BIT_2S	/* Switch on SM Test Mode */
-#define SM_TEST_OFF		BIT_1S	/* Go off the Test Mode */
-#define SM_STEP			BIT_0S	/* Step the State Machine */
-/* The encoding of the states is not supported by the Diagnostics Tool */
-
-/*	Q_T2			32 bit	Test Register 2	*/
-								/* Bit 31.. 8:	reserved */
-#define T2_AC_T_ON		BIT_7	/* Address Counter Test Mode on */
-#define T2_AC_T_OFF		BIT_6	/* Address Counter Test Mode off */
-#define T2_BC_T_ON		BIT_5	/* Byte Counter Test Mode on */
-#define T2_BC_T_OFF		BIT_4	/* Byte Counter Test Mode off */
-#define T2_STEP04		BIT_3	/* Inc AC/Dec BC by 4 */
-#define T2_STEP03		BIT_2	/* Inc AC/Dec BC by 3 */
-#define T2_STEP02		BIT_1	/* Inc AC/Dec BC by 2 */
-#define T2_STEP01		BIT_0	/* Inc AC/Dec BC by 1 */
-
-/*	Q_T3			32 bit	Test Register 3	*/
-								/* Bit 31.. 7:	reserved */
-#define T3_MUX_MSK		(7<<4)	/* Bit  6.. 4:	Mux Position */
-								/* Bit  3:	reserved */
-#define T3_VRAM_MSK		7		/* Bit  2.. 0:	Virtual RAM Buffer Address */
-
-/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
-/*	RB_START		32 bit	RAM Buffer Start Address */
-/*	RB_END			32 bit	RAM Buffer End Address */
-/*	RB_WP			32 bit	RAM Buffer Write Pointer */
-/*	RB_RP			32 bit	RAM Buffer Read Pointer */
-/*	RB_RX_UTPP		32 bit	Rx Upper Threshold, Pause Pack */
-/*	RB_RX_LTPP		32 bit	Rx Lower Threshold, Pause Pack */
-/*	RB_RX_UTHP		32 bit	Rx Upper Threshold, High Prio */
-/*	RB_RX_LTHP		32 bit	Rx Lower Threshold, High Prio */
-/*	RB_PC			32 bit	RAM Buffer Packet Counter */
-/*	RB_LEV			32 bit	RAM Buffer Level Register */
-				/* Bit 31..19:	reserved */
-#define RB_MSK	0x0007ffff	/* Bit 18.. 0:	RAM Buffer Pointer Bits */
-
-/*	RB_TST2			 8 bit	RAM Buffer Test Register 2 */
-								/* Bit 7.. 4:	reserved */
-#define RB_PC_DEC		BIT_3S	/* Packet Counter Decrem */
-#define RB_PC_T_ON		BIT_2S	/* Packet Counter Test On */
-#define RB_PC_T_OFF		BIT_1S	/* Packet Counter Tst Off */
-#define RB_PC_INC		BIT_0S	/* Packet Counter Increm */
-
-/*	RB_TST1			 8 bit	RAM Buffer Test Register 1 */
-							/* Bit 7:	reserved */
-#define RB_WP_T_ON		BIT_6S	/* Write Pointer Test On */
-#define RB_WP_T_OFF		BIT_5S	/* Write Pointer Test Off */
-#define RB_WP_INC		BIT_4S	/* Write Pointer Increm */
-								/* Bit 3:	reserved */
-#define RB_RP_T_ON		BIT_2S	/* Read Pointer Test On */
-#define RB_RP_T_OFF		BIT_1S	/* Read Pointer Test Off */
-#define RB_RP_DEC		BIT_0S	/* Read Pointer Decrement */
-
-/*	RB_CTRL			 8 bit	RAM Buffer Control Register */
-								/* Bit 7.. 6:	reserved */
-#define RB_ENA_STFWD	BIT_5S	/* Enable  Store & Forward */
-#define RB_DIS_STFWD	BIT_4S	/* Disable Store & Forward */
-#define RB_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
-#define RB_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
-#define RB_RST_CLR		BIT_1S	/* Clear RAM Buf STM Reset */
-#define RB_RST_SET		BIT_0S	/* Set   RAM Buf STM Reset */
-
-
-/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
-
-/*	RX_MFF_EA		32 bit	Receive MAC FIFO End Address */
-/*	RX_MFF_WP		32 bit 	Receive MAC FIFO Write Pointer */
-/*	RX_MFF_RP		32 bit	Receive MAC FIFO Read Pointer */
-/*	RX_MFF_PC		32 bit	Receive MAC FIFO Packet Counter */
-/*	RX_MFF_LEV		32 bit	Receive MAC FIFO Level */
-/*	TX_MFF_EA		32 bit	Transmit MAC FIFO End Address */
-/*	TX_MFF_WP		32 bit 	Transmit MAC FIFO Write Pointer */
-/*	TX_MFF_WSP		32 bit	Transmit MAC FIFO WR Shadow Pointer */
-/*	TX_MFF_RP		32 bit	Transmit MAC FIFO Read Pointer */
-/*	TX_MFF_PC		32 bit	Transmit MAC FIFO Packet Cnt */
-/*	TX_MFF_LEV		32 bit	Transmit MAC FIFO Level */
-								/* Bit 31.. 6:	reserved */
-#define MFF_MSK			0x007fL	/* Bit	5.. 0:	MAC FIFO Address/Ptr Bits */
-
-/*	RX_MFF_CTRL1	16 bit	Receive MAC FIFO Control Reg 1 */
-								/* Bit 15..14:	reserved */
-#define MFF_ENA_RDY_PAT	BIT_13S		/* Enable  Ready Patch */
-#define MFF_DIS_RDY_PAT	BIT_12S		/* Disable Ready Patch */
-#define MFF_ENA_TIM_PAT	BIT_11S		/* Enable  Timing Patch */
-#define MFF_DIS_TIM_PAT	BIT_10S		/* Disable Timing Patch */
-#define MFF_ENA_ALM_FUL	BIT_9S		/* Enable  AlmostFull Sign */
-#define MFF_DIS_ALM_FUL	BIT_8S		/* Disable AlmostFull Sign */
-#define MFF_ENA_PAUSE	BIT_7S		/* Enable  Pause Signaling */
-#define MFF_DIS_PAUSE	BIT_6S		/* Disable Pause Signaling */
-#define MFF_ENA_FLUSH	BIT_5S		/* Enable  Frame Flushing */
-#define MFF_DIS_FLUSH	BIT_4S		/* Disable Frame Flushing */
-#define MFF_ENA_TIST	BIT_3S		/* Enable  Time Stamp Gener */
-#define MFF_DIS_TIST	BIT_2S		/* Disable Time Stamp Gener */
-#define MFF_CLR_INTIST	BIT_1S		/* Clear IRQ No Time Stamp */
-#define MFF_CLR_INSTAT	BIT_0S		/* Clear IRQ No Status */
-
-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
-
-/*	TX_MFF_CTRL1	16 bit	Transmit MAC FIFO Control Reg 1 */
-#define MFF_CLR_PERR	BIT_15S		/* Clear Parity Error IRQ */
-								/* Bit 14:	reserved */
-#define MFF_ENA_PKT_REC	BIT_13S		/* Enable  Packet Recovery */
-#define MFF_DIS_PKT_REC BIT_12S		/* Disable Packet Recovery */
-/*	MFF_ENA_TIM_PAT	 (see RX_MFF_CTRL1) Bit 11:	Enable  Timing Patch */
-/*	MFF_DIS_TIM_PAT	 (see RX_MFF_CTRL1) Bit 10:	Disable Timing Patch */
-/*	MFF_ENA_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 9:	Enable  Almost Full Sign */
-/*	MFF_DIS_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 8:	Disable Almost Full Sign */
-#define MFF_ENA_W4E		BIT_7S		/* Enable  Wait for Empty */
-#define MFF_DIS_W4E		BIT_6S		/* Disable Wait for Empty */
-/*	MFF_ENA_FLUSH	 (see RX_MFF_CTRL1) Bit	 5:	Enable  Frame Flushing */
-/*	MFF_DIS_FLUSH	 (see RX_MFF_CTRL1) Bit	 4:	Disable Frame Flushing */
-#define MFF_ENA_LOOPB	BIT_3S		/* Enable  Loopback */
-#define MFF_DIS_LOOPB	BIT_2S		/* Disable Loopback */
-#define MFF_CLR_MAC_RST	BIT_1S		/* Clear XMAC Reset */
-#define MFF_SET_MAC_RST	BIT_0S		/* Set   XMAC Reset */
-
-#define MFF_TX_CTRL_DEF	(MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
-
-/*	RX_MFF_TST2	 	 8 bit	Receive MAC FIFO Test Register 2 */
-/*	TX_MFF_TST2	 	 8 bit	Transmit MAC FIFO Test Register 2 */
-								/* Bit 7:	reserved */
-#define MFF_WSP_T_ON	BIT_6S	/* Tx: Write Shadow Ptr TestOn */
-#define MFF_WSP_T_OFF	BIT_5S	/* Tx: Write Shadow Ptr TstOff */
-#define MFF_WSP_INC		BIT_4S	/* Tx: Write Shadow Ptr Increment */
-#define MFF_PC_DEC		BIT_3S	/* Packet Counter Decrement */
-#define MFF_PC_T_ON		BIT_2S	/* Packet Counter Test On */
-#define MFF_PC_T_OFF	BIT_1S	/* Packet Counter Test Off */
-#define MFF_PC_INC		BIT_0S	/* Packet Counter Increment */
-
-/*	RX_MFF_TST1	 	 8 bit	Receive MAC FIFO Test Register 1 */
-/*	TX_MFF_TST1	 	 8 bit	Transmit MAC FIFO Test Register 1 */
-					/* Bit 7:	reserved */
-#define MFF_WP_T_ON		BIT_6S	/* Write Pointer Test On */
-#define MFF_WP_T_OFF	BIT_5S	/* Write Pointer Test Off */
-#define MFF_WP_INC		BIT_4S	/* Write Pointer Increm */
-							/* Bit 3:	reserved */
-#define MFF_RP_T_ON		BIT_2S	/* Read Pointer Test On */
-#define MFF_RP_T_OFF	BIT_1S	/* Read Pointer Test Off */
-#define MFF_RP_DEC		BIT_0S	/* Read Pointer Decrement */
-
-/*	RX_MFF_CTRL2	 8 bit	Receive MAC FIFO Control Reg 2 */
-/*	TX_MFF_CTRL2	 8 bit	Transmit MAC FIFO Control Reg 2 */
-								/* Bit 7..4:	reserved */
-#define MFF_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
-#define MFF_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
-#define MFF_RST_CLR		BIT_1S	/* Clear MAC FIFO Reset */
-#define MFF_RST_SET		BIT_0S	/* Set   MAC FIFO Reset */
-
-
-/*	Link LED Counter Registers (GENESIS only) */
-
-/*	RX_LED_CTRL		 8 bit	Receive LED Cnt Control Reg */
-/*	TX_LED_CTRL		 8 bit	Transmit LED Cnt Control Reg */
-/*	LNK_SYNC_CTRL	 8 bit	Link Sync Cnt Control Register */
-							/* Bit 7.. 3:	reserved */
-#define LED_START		BIT_2S	/* Start Timer */
-#define LED_STOP		BIT_1S	/* Stop Timer */
-#define LED_STATE		BIT_0S	/* Rx/Tx: LED State, 1=LED on */
-#define LED_CLR_IRQ		BIT_0S	/* Lnk: 	Clear Link IRQ */
-
-/*	RX_LED_TST		 8 bit	Receive LED Cnt Test Register */
-/*	TX_LED_TST		 8 bit	Transmit LED Cnt Test Register */
-/*	LNK_SYNC_TST	 8 bit	Link Sync Cnt Test Register */
-							/* Bit 7.. 3:	reserved */
-#define LED_T_ON		BIT_2S	/* LED Counter Test mode On */
-#define LED_T_OFF		BIT_1S	/* LED Counter Test mode Off */
-#define LED_T_STEP		BIT_0S	/* LED Counter Step */
-
-/*	LNK_LED_REG	 	 8 bit	Link LED Register */
-								/* Bit 7.. 6:	reserved */
-#define LED_BLK_ON		BIT_5S	/* Link LED Blinking On */
-#define LED_BLK_OFF		BIT_4S	/* Link LED Blinking Off */
-#define LED_SYNC_ON		BIT_3S	/* Use Sync Wire to switch LED */
-#define LED_SYNC_OFF	BIT_2S	/* Disable Sync Wire Input */
-#define LED_ON			BIT_1S	/* switch LED on */
-#define LED_OFF			BIT_0S	/* switch LED off */
-
-/*	Receive and Transmit GMAC FIFO Registers (YUKON only) */
-
-/*	RX_GMF_EA		32 bit	Rx GMAC FIFO End Address */
-/*	RX_GMF_AF_THR	32 bit	Rx GMAC FIFO Almost Full Thresh. */
-/*	RX_GMF_WP		32 bit 	Rx GMAC FIFO Write Pointer */
-/*	RX_GMF_WLEV		32 bit 	Rx GMAC FIFO Write Level */
-/*	RX_GMF_RP		32 bit 	Rx GMAC FIFO Read Pointer */
-/*	RX_GMF_RLEV		32 bit 	Rx GMAC FIFO Read Level */
-/*	TX_GMF_EA		32 bit	Tx GMAC FIFO End Address */
-/*	TX_GMF_AE_THR	32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
-/*	TX_GMF_WP		32 bit 	Tx GMAC FIFO Write Pointer */
-/*	TX_GMF_WSP		32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
-/*	TX_GMF_WLEV		32 bit 	Tx GMAC FIFO Write Level */
-/*	TX_GMF_RP		32 bit 	Tx GMAC FIFO Read Pointer */
-/*	TX_GMF_RSTP		32 bit 	Tx GMAC FIFO Restart Pointer */
-/*	TX_GMF_RLEV		32 bit 	Tx GMAC FIFO Read Level */
-
-/*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
-						/* Bits 31..15:	reserved */
-#define GMF_WP_TST_ON	BIT_14		/* Write Pointer Test On */
-#define GMF_WP_TST_OFF	BIT_13		/* Write Pointer Test Off */
-#define GMF_WP_STEP		BIT_12		/* Write Pointer Step/Increment */
-						/* Bit 11:	reserved */
-#define GMF_RP_TST_ON	BIT_10		/* Read Pointer Test On */
-#define GMF_RP_TST_OFF	BIT_9		/* Read Pointer Test Off */
-#define GMF_RP_STEP		BIT_8		/* Read Pointer Step/Increment */
-#define GMF_RX_F_FL_ON	BIT_7		/* Rx FIFO Flush Mode On */
-#define GMF_RX_F_FL_OFF	BIT_6		/* Rx FIFO Flush Mode Off */
-#define GMF_CLI_RX_FO	BIT_5		/* Clear IRQ Rx FIFO Overrun */
-#define GMF_CLI_RX_FC	BIT_4		/* Clear IRQ Rx Frame Complete */
-#define GMF_OPER_ON		BIT_3		/* Operational Mode On */
-#define GMF_OPER_OFF	BIT_2		/* Operational Mode Off */
-#define GMF_RST_CLR		BIT_1		/* Clear GMAC FIFO Reset */
-#define GMF_RST_SET		BIT_0		/* Set   GMAC FIFO Reset */
-
-/*	TX_GMF_CTRL_T	32 bit	Tx GMAC FIFO Control/Test */
-						/* Bits 31..19:	reserved */
-#define GMF_WSP_TST_ON	BIT_18		/* Write Shadow Pointer Test On */
-#define GMF_WSP_TST_OFF	BIT_17		/* Write Shadow Pointer Test Off */
-#define GMF_WSP_STEP	BIT_16		/* Write Shadow Pointer Step/Increment */
-						/* Bits 15..7: same as for RX_GMF_CTRL_T */
-#define GMF_CLI_TX_FU	BIT_6		/* Clear IRQ Tx FIFO Underrun */
-#define GMF_CLI_TX_FC	BIT_5		/* Clear IRQ Tx Frame Complete */
-#define GMF_CLI_TX_PE	BIT_4		/* Clear IRQ Tx Parity Error */
-						/* Bits 3..0: same as for RX_GMF_CTRL_T */
-
-#define GMF_RX_CTRL_DEF		(GMF_OPER_ON | GMF_RX_F_FL_ON)
-#define GMF_TX_CTRL_DEF		GMF_OPER_ON
-
-#define RX_GMF_FL_THR_DEF	0x0a	/* Rx GMAC FIFO Flush Threshold default */
-
-/*	GMAC_TI_ST_CTRL	 8 bit	Time Stamp Timer Ctrl Reg (YUKON only) */
-								/* Bit 7.. 3:	reserved */
-#define GMT_ST_START	BIT_2S		/* Start Time Stamp Timer */
-#define GMT_ST_STOP		BIT_1S		/* Stop  Time Stamp Timer */
-#define GMT_ST_CLR_IRQ	BIT_0S		/* Clear Time Stamp Timer IRQ */
-
-/*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
-						/* Bits 31.. 8:	reserved */
-#define GMC_H_BURST_ON	BIT_7		/* Half Duplex Burst Mode On */
-#define GMC_H_BURST_OFF	BIT_6		/* Half Duplex Burst Mode Off */
-#define GMC_F_LOOPB_ON	BIT_5		/* FIFO Loopback On */
-#define GMC_F_LOOPB_OFF	BIT_4		/* FIFO Loopback Off */
-#define GMC_PAUSE_ON	BIT_3		/* Pause On */
-#define GMC_PAUSE_OFF	BIT_2		/* Pause Off */
-#define GMC_RST_CLR		BIT_1		/* Clear GMAC Reset */
-#define GMC_RST_SET		BIT_0		/* Set   GMAC Reset */
-
-/*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
-						/* Bits 31..29:	reserved */
-#define GPC_SEL_BDT		BIT_28	/* Select Bi-Dir. Transfer for MDC/MDIO */
-#define GPC_INT_POL_HI	BIT_27	/* IRQ Polarity is Active HIGH */
-#define GPC_75_OHM		BIT_26	/* Use 75 Ohm Termination instead of 50 */
-#define GPC_DIS_FC		BIT_25	/* Disable Automatic Fiber/Copper Detection */
-#define GPC_DIS_SLEEP	BIT_24	/* Disable Energy Detect */
-#define GPC_HWCFG_M_3	BIT_23	/* HWCFG_MODE[3] */
-#define GPC_HWCFG_M_2	BIT_22	/* HWCFG_MODE[2] */
-#define GPC_HWCFG_M_1	BIT_21	/* HWCFG_MODE[1] */
-#define GPC_HWCFG_M_0	BIT_20	/* HWCFG_MODE[0] */
-#define GPC_ANEG_0		BIT_19	/* ANEG[0] */
-#define GPC_ENA_XC		BIT_18	/* Enable MDI crossover */
-#define GPC_DIS_125		BIT_17	/* Disable 125 MHz clock */
-#define GPC_ANEG_3		BIT_16	/* ANEG[3] */
-#define GPC_ANEG_2		BIT_15	/* ANEG[2] */
-#define GPC_ANEG_1		BIT_14	/* ANEG[1] */
-#define GPC_ENA_PAUSE	BIT_13	/* Enable Pause (SYM_OR_REM) */
-#define GPC_PHYADDR_4	BIT_12	/* Bit 4 of Phy Addr */
-#define GPC_PHYADDR_3	BIT_11	/* Bit 3 of Phy Addr */
-#define GPC_PHYADDR_2	BIT_10	/* Bit 2 of Phy Addr */
-#define GPC_PHYADDR_1	BIT_9	/* Bit 1 of Phy Addr */
-#define GPC_PHYADDR_0	BIT_8	/* Bit 0 of Phy Addr */
-						/* Bits  7..2:	reserved */
-#define GPC_RST_CLR		BIT_1	/* Clear GPHY Reset */
-#define GPC_RST_SET		BIT_0	/* Set   GPHY Reset */
-
-#define GPC_HWCFG_GMII_COP	(GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_HWCFG_GMII_FIB	(				 GPC_HWCFG_M_2 | \
-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_ANEG_ADV_ALL_M	(GPC_ANEG_3 | GPC_ANEG_2 | \
-							 GPC_ANEG_1 | GPC_ANEG_0)
-
-/* forced speed and duplex mode (don't mix with other ANEG bits) */
-#define GPC_FRC10MBIT_HALF	0
-#define GPC_FRC10MBIT_FULL	GPC_ANEG_0
-#define GPC_FRC100MBIT_HALF	GPC_ANEG_1
-#define GPC_FRC100MBIT_FULL	(GPC_ANEG_0 | GPC_ANEG_1)
-
-/* auto-negotiation with limited advertised speeds */
-/* mix only with master/slave settings (for copper) */
-#define GPC_ADV_1000_HALF	GPC_ANEG_2
-#define GPC_ADV_1000_FULL	GPC_ANEG_3
-#define GPC_ADV_ALL			(GPC_ANEG_2 | GPC_ANEG_3)
-
-/* master/slave settings */
-/* only for copper with 1000 Mbps */
-#define GPC_FORCE_MASTER	0
-#define GPC_FORCE_SLAVE		GPC_ANEG_0
-#define GPC_PREF_MASTER		GPC_ANEG_1
-#define GPC_PREF_SLAVE		(GPC_ANEG_1 | GPC_ANEG_0)
-
-/*	GMAC_IRQ_SRC	 8 bit	GMAC Interrupt Source Reg (YUKON only) */
-/*	GMAC_IRQ_MSK	 8 bit	GMAC Interrupt Mask   Reg (YUKON only) */
-#define GM_IS_TX_CO_OV	BIT_5		/* Transmit Counter Overflow IRQ */
-#define GM_IS_RX_CO_OV	BIT_4		/* Receive Counter Overflow IRQ */
-#define GM_IS_TX_FF_UR	BIT_3		/* Transmit FIFO Underrun */
-#define GM_IS_TX_COMPL	BIT_2		/* Frame Transmission Complete */
-#define GM_IS_RX_FF_OR	BIT_1		/* Receive FIFO Overrun */
-#define GM_IS_RX_COMPL	BIT_0		/* Frame Reception Complete */
-
-#define GMAC_DEF_MSK	(GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
-						GM_IS_TX_FF_UR)
-
-/*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
-						/* Bits 15.. 2:	reserved */
-#define GMLC_RST_CLR	BIT_1S		/* Clear GMAC Link Reset */
-#define GMLC_RST_SET	BIT_0S		/* Set   GMAC Link Reset */
-
-
-/*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
-#define WOL_CTL_LINK_CHG_OCC			BIT_15S
-#define WOL_CTL_MAGIC_PKT_OCC			BIT_14S
-#define WOL_CTL_PATTERN_OCC				BIT_13S
-
-#define WOL_CTL_CLEAR_RESULT			BIT_12S
-
-#define WOL_CTL_ENA_PME_ON_LINK_CHG		BIT_11S
-#define WOL_CTL_DIS_PME_ON_LINK_CHG		BIT_10S
-#define WOL_CTL_ENA_PME_ON_MAGIC_PKT	BIT_9S
-#define WOL_CTL_DIS_PME_ON_MAGIC_PKT	BIT_8S
-#define WOL_CTL_ENA_PME_ON_PATTERN		BIT_7S
-#define WOL_CTL_DIS_PME_ON_PATTERN		BIT_6S
-
-#define WOL_CTL_ENA_LINK_CHG_UNIT		BIT_5S
-#define WOL_CTL_DIS_LINK_CHG_UNIT		BIT_4S
-#define WOL_CTL_ENA_MAGIC_PKT_UNIT		BIT_3S
-#define WOL_CTL_DIS_MAGIC_PKT_UNIT		BIT_2S
-#define WOL_CTL_ENA_PATTERN_UNIT		BIT_1S
-#define WOL_CTL_DIS_PATTERN_UNIT		BIT_0S
-
-#define WOL_CTL_DEFAULT				\
-	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
-	WOL_CTL_DIS_PME_ON_PATTERN |	\
-	WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
-	WOL_CTL_DIS_LINK_CHG_UNIT |		\
-	WOL_CTL_DIS_PATTERN_UNIT |		\
-	WOL_CTL_DIS_MAGIC_PKT_UNIT)
-
-/*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
-#define WOL_CTL_PATT_ENA(x)				(BIT_0 << (x))
-
-#define SK_NUM_WOL_PATTERN		7
-#define SK_PATTERN_PER_WORD		4
-#define SK_BITMASK_PATTERN		7
-#define SK_POW_PATTERN_LENGTH	128
-
-#define WOL_LENGTH_MSK		0x7f
-#define WOL_LENGTH_SHIFT	8
-
-
-/* Receive and Transmit Descriptors ******************************************/
-
-/* Transmit Descriptor struct */
-typedef	struct s_HwTxd {
-	SK_U32 volatile	TxCtrl;	/* Transmit Buffer Control Field */
-	SK_U32	TxNext;			/* Physical Address Pointer to the next TxD */
-	SK_U32	TxAdrLo;		/* Physical Tx Buffer Address lower dword */
-	SK_U32	TxAdrHi;		/* Physical Tx Buffer Address upper dword */
-	SK_U32	TxStat;			/* Transmit Frame Status Word */
-#ifndef	SK_USE_REV_DESC
-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
-	SK_U16	TxRes1;			/* 16 bit reserved field */
-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
-#else	/* SK_USE_REV_DESC */
-	SK_U16	TxRes1;			/* 16 bit reserved field */
-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
-#endif	/* SK_USE_REV_DESC */
-	SK_U32  TxRes2;			/* 32 bit reserved field */
-} SK_HWTXD;
-
-/* Receive Descriptor struct */
-typedef	struct s_HwRxd {
-	SK_U32 volatile RxCtrl;	/* Receive Buffer Control Field */
-	SK_U32	RxNext;			/* Physical Address Pointer to the next RxD */
-	SK_U32	RxAdrLo;		/* Physical Rx Buffer Address lower dword */
-	SK_U32	RxAdrHi;		/* Physical Rx Buffer Address upper dword */
-	SK_U32	RxStat;			/* Receive Frame Status Word */
-	SK_U32	RxTiSt;			/* Receive Time Stamp (from XMAC on GENESIS) */
-#ifndef	SK_USE_REV_DESC
-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
-#else	/* SK_USE_REV_DESC */
-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
-#endif	/* SK_USE_REV_DESC */
-} SK_HWRXD;
-
-/*
- * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
- * should set the define SK_USE_REV_DESC.
- * Structures are 'normaly' not endianess dependent. But in
- * this case the SK_U16 fields are bound to bit positions inside the
- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
- * The bit positions inside a DWord are of course endianess dependent and
- * swaps if the DWord is swapped by the hardware.
- */
-
-
-/* Descriptor Bit Definition */
-/*	TxCtrl		Transmit Buffer Control Field */
-/*	RxCtrl		Receive  Buffer Control Field */
-#define BMU_OWN			BIT_31	/* OWN bit: 0=host/1=BMU */
-#define BMU_STF			BIT_30	/* Start of Frame */
-#define BMU_EOF			BIT_29	/* End of Frame */
-#define BMU_IRQ_EOB		BIT_28	/* Req "End of Buffer" IRQ */
-#define BMU_IRQ_EOF		BIT_27	/* Req "End of Frame" IRQ */
-/* TxCtrl specific bits */
-#define BMU_STFWD		BIT_26	/* (Tx)	Store & Forward Frame */
-#define BMU_NO_FCS		BIT_25	/* (Tx) Disable MAC FCS (CRC) generation */
-#define BMU_SW			BIT_24	/* (Tx)	1 bit res. for SW use */
-/* RxCtrl specific bits */
-#define BMU_DEV_0		BIT_26	/* (Rx)	Transfer data to Dev0 */
-#define BMU_STAT_VAL	BIT_25	/* (Rx)	Rx Status Valid */
-#define BMU_TIST_VAL	BIT_24	/* (Rx)	Rx TimeStamp Valid */
-								/* Bit 23..16:	BMU Check Opcodes */
-#define BMU_CHECK		(0x55L<<16)	/* Default BMU check */
-#define BMU_TCP_CHECK	(0x56L<<16)	/* Descr with TCP ext */
-#define BMU_UDP_CHECK	(0x57L<<16)	/* Descr with UDP ext (YUKON only) */
-#define BMU_BBC			0xffffL	/* Bit 15.. 0:	Buffer Byte Counter */
-
-/*	TxStat		Transmit Frame Status Word */
-/*	RxStat		Receive Frame Status Word */
-/*
- *Note: TxStat is reserved for ASIC loopback mode only
- *
- *	The Bits of the Status words are defined in xmac_ii.h
- *	(see XMR_FS bits)
- */
-
-/* macros ********************************************************************/
-
-/* Receive and Transmit Queues */
-#define Q_R1	0x0000		/* Receive Queue 1 */
-#define Q_R2	0x0080		/* Receive Queue 2 */
-#define Q_XS1	0x0200		/* Synchronous Transmit Queue 1 */
-#define Q_XA1	0x0280		/* Asynchronous Transmit Queue 1 */
-#define Q_XS2	0x0300		/* Synchronous Transmit Queue 2 */
-#define Q_XA2	0x0380		/* Asynchronous Transmit Queue 2 */
-
-/*
- *	Macro Q_ADDR()
- *
- *	Use this macro to access the Receive and Transmit Queue Registers.
- *
- * para:
- *	Queue	Queue to access.
- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- *	Offs	Queue register offset.
- *				Values: Q_D, Q_DA_L ... Q_T2, Q_T3
- *
- * usage	SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
- */
-#define Q_ADDR(Queue, Offs)	(B8_Q_REGS + (Queue) + (Offs))
-
-/*
- *	Macro RB_ADDR()
- *
- *	Use this macro to access the RAM Buffer Registers.
- *
- * para:
- *	Queue	Queue to access.
- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- *	Offs	Queue register offset.
- *				Values: RB_START, RB_END ... RB_LEV, RB_CTRL
- *
- * usage	SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
- */
-#define RB_ADDR(Queue, Offs)	(B16_RAM_REGS + (Queue) + (Offs))
-
-
-/* MAC Related Registers */
-#define MAC_1		0	/* belongs to the port near the slot */
-#define MAC_2		1	/* belongs to the port far away from the slot */
-
-/*
- *	Macro MR_ADDR()
- *
- *	Use this macro to access a MAC Related Registers inside the ASIC.
- *
- * para:
- *	Mac		MAC to access.
- *				Values: MAC_1, MAC_2
- *	Offs	MAC register offset.
- *				Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
- *						TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
- *
- * usage	SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
- */
-#define MR_ADDR(Mac, Offs)	(((Mac) << 7) + (Offs))
-
-#ifdef	SK_LITTLE_ENDIAN
-#define XM_WORD_LO	0
-#define XM_WORD_HI	1
-#else	/* !SK_LITTLE_ENDIAN */
-#define XM_WORD_LO	1
-#define XM_WORD_HI	0
-#endif	/* !SK_LITTLE_ENDIAN */
-
-
-/*
- * macros to access the XMAC (GENESIS only)
- *
- * XM_IN16(),		to read a 16 bit register (e.g. XM_MMU_CMD)
- * XM_OUT16(),		to write a 16 bit register (e.g. XM_MMU_CMD)
- * XM_IN32(),		to read a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_OUT32(),		to write a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_INADDR(),		to read a network address register (e.g. XM_SRC_CHK)
- * XM_OUTADDR(),	to write a network address register (e.g. XM_SRC_CHK)
- * XM_INHASH(),		to read the XM_HSM_CHK register
- * XM_OUTHASH()		to write the XM_HSM_CHK register
- *
- * para:
- *	Mac		XMAC to access		values: MAC_1 or MAC_2
- *	IoC		I/O context needed for SK I/O macros
- *	Reg		XMAC Register to read or write
- *	(p)Val	Value or pointer to the value which should be read or written
- *
- * usage:	XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
- */
-
-#define XMA(Mac, Reg)									\
-	((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
-
-#define XM_IN16(IoC, Mac, Reg, pVal)					\
-	SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
-
-#define XM_OUT16(IoC, Mac, Reg, Val)					\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
-
-#define XM_IN32(IoC, Mac, Reg, pVal) {					\
-	SK_IN16((IoC), XMA((Mac), (Reg)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
-}
-
-#define XM_OUT32(IoC, Mac, Reg, Val) {										\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
-
-#define XM_INADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define XM_OUTADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-}
-
-#define XM_INHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word);			\
-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define XM_OUTHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16)		\
-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
-}
-
-/*
- * macros to access the GMAC (YUKON only)
- *
- * GM_IN16(),		to read  a 16 bit register (e.g. GM_GP_STAT)
- * GM_OUT16(),		to write a 16 bit register (e.g. GM_GP_CTRL)
- * GM_IN32(),		to read  a 32 bit register (e.g. GM_)
- * GM_OUT32(),		to write a 32 bit register (e.g. GM_)
- * GM_INADDR(),		to read  a network address register (e.g. GM_SRC_ADDR_1L)
- * GM_OUTADDR(),	to write a network address register (e.g. GM_SRC_ADDR_2L)
- * GM_INHASH(),		to read  the GM_MC_ADDR_H1 register
- * GM_OUTHASH()		to write the GM_MC_ADDR_H1 register
- *
- * para:
- *	Mac		GMAC to access		values: MAC_1 or MAC_2
- *	IoC		I/O context needed for SK I/O macros
- *	Reg		GMAC Register to read or write
- *	(p)Val	Value or pointer to the value which should be read or written
- *
- * usage:	GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
- */
-
-#define GMA(Mac, Reg)									\
-	((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
-
-#define GM_IN16(IoC, Mac, Reg, pVal)					\
-	SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
-
-#define GM_OUT16(IoC, Mac, Reg, Val)					\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
-
-#define GM_IN32(IoC, Mac, Reg, pVal) {					\
-	SK_IN16((IoC), GMA((Mac), (Reg)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
-}
-
-#define GM_OUT32(IoC, Mac, Reg, Val) {										\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-#define GM_INADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define GM_OUTADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-}
-
-#define GM_INHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word);		\
-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define GM_OUTHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16)		\
-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
-}
-
-/*
- * Different MAC Types
- */
-#define SK_MAC_XMAC		0	/* Xaqti XMAC II */
-#define SK_MAC_GMAC		1	/* Marvell GMAC */
-
-/*
- * Different PHY Types
- */
-#define SK_PHY_XMAC			0	/* integrated in XMAC II */
-#define SK_PHY_BCOM			1	/* Broadcom BCM5400 */
-#define SK_PHY_LONE			2	/* Level One LXT1000 */
-#define SK_PHY_NAT			3	/* National DP83891 */
-#define SK_PHY_MARV_COPPER	4	/* Marvell 88E1011S */
-#define SK_PHY_MARV_FIBER	5	/* Marvell 88E1011S working on fiber */
-
-/*
- * PHY addresses (bits 12..8 of PHY address reg)
- */
-#define PHY_ADDR_XMAC	(0<<8)
-#define PHY_ADDR_BCOM	(1<<8)
-#define PHY_ADDR_LONE	(3<<8)
-#define PHY_ADDR_NAT	(0<<8)
-
-/* GPHY address (bits 15..11 of SMI control reg) */
-#define PHY_ADDR_MARV	0
-
-/*
- * macros to access the PHY
- *
- * PHY_READ()		read a 16 bit value from the PHY
- * PHY_WRITE()		write a 16 bit value to the PHY
- *
- * para:
- * 	IoC		I/O context needed for SK I/O macros
- * 	pPort	Pointer to port struct for PhyAddr
- * 	Mac		XMAC to access		values: MAC_1 or MAC_2
- * 	PhyReg	PHY Register to read or write
- * 	(p)Val	Value or pointer to the value which should be read or
- *			written.
- *
- * usage:	PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
- * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
- *          comes back. This is checked in DEBUG mode.
- */
-#ifndef DEBUG
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
-	SK_U16 Mmu;  														\
-																		\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
-	}  																	\
-}
-#else
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
-	SK_U16 Mmu;  														\
-	int __i = 0;														\
-																		\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-			__i++;														\
-			if (__i > 100000) {											\
-				SK_DBG_PRINTF("*****************************\n");		\
-				SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n");		\
-				SK_DBG_PRINTF("*****************************\n");		\
-				break;													\
-			}															\
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
-	}  																	\
-}
-#endif /* DEBUG */
-
-#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) {						\
-	SK_U16 Mmu;															\
-																		\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
-	}  																	\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
-	}  																	\
-}
-
-/*
- *	Macro PCI_C()
- *
- *	Use this macro to access PCI config register from the I/O space.
- *
- * para:
- *	Addr	PCI configuration register to access.
- *			Values:	PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
- *
- * usage	SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
- */
-#define PCI_C(Addr)	(B7_CFG_SPC + (Addr))	/* PCI Config Space */
-
-/*
- *	Macro SK_HW_ADDR(Base, Addr)
- *
- *	Calculates the effective HW address
- *
- * para:
- *	Base	I/O or memory base address
- *	Addr	Address offset
- *
- * usage:	May be used in SK_INxx and SK_OUTxx macros
- *		#define SK_IN8(pAC, Addr, pVal) ...\
- *			*pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
- */
-#ifdef SK_MEM_MAPPED_IO
-#define SK_HW_ADDR(Base, Addr)	((Base) + (Addr))
-#else  /* SK_MEM_MAPPED_IO */
-#define SK_HW_ADDR(Base, Addr)	\
-			((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
-#endif /* SK_MEM_MAPPED_IO */
-
-#define SZ_LONG	(sizeof(SK_U32))
-
-/*
- *	Macro SK_HWAC_LINK_LED()
- *
- *	Use this macro to set the link LED mode.
- * para:
- *	pAC		Pointer to adapter context struct
- *	IoC		I/O context needed for SK I/O macros
- *  Port	Port number
- *	Mode	Mode to set for this LED
- */
-#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
-
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKGEHW_H */
diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
deleted file mode 100644
index e6b0016..0000000
--- a/drivers/net/sk98lin/h/skgehwt.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Name:	skhwt.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/09/16 12:55:08 $
- * Purpose:	Defines for the hardware timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEHWT.H	contains all defines and types for the timer functions
- */
-
-#ifndef	_SKGEHWT_H_
-#define _SKGEHWT_H_
-
-/*
- * SK Hardware Timer
- * - needed wherever the HWT module is used
- * - use in Adapters context name pAC->Hwt
- */
-typedef	struct s_Hwt {
-	SK_U32		TStart;	/* HWT start */
-	SK_U32		TStop;	/* HWT stop */
-	int		TActive;	/* HWT: flag : active/inactive */
-} SK_HWT;
-
-extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
-extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
-extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
-#endif	/* _SKGEHWT_H_ */
diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
deleted file mode 100644
index d9b6f6d..0000000
--- a/drivers/net/sk98lin/h/skgei2c.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgei2c.h
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.25 $
- * Date:	$Date: 2003/10/20 09:06:05 $
- * Purpose:	Special defines for TWSI
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEI2C.H	contains all SK-98xx specific defines for the TWSI handling
- */
-
-#ifndef _INC_SKGEI2C_H_
-#define _INC_SKGEI2C_H_
-
-/*
- * Macros to access the B2_I2C_CTRL
- */
-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
-	SK_OUT32(IoC, B2_I2C_CTRL,\
-		(flag ? 0x80000000UL : 0x0L) | \
-		(((SK_U32)reg << 16) & I2C_ADDR) | \
-		(((SK_U32)dev << 9) & I2C_DEV_SEL) | \
-		(dev_size & I2C_DEV_SIZE) | \
-		((burst << 4) & I2C_BURST_LEN))
-
-#define SK_I2C_STOP(IoC) {				\
-	SK_U32	I2cCtrl;				\
-	SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl);		\
-	SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP);	\
-}
-
-#define SK_I2C_GET_CTL(IoC, pI2cCtrl)	SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
-
-/*
- * Macros to access the TWSI SW Registers
- */
-#define SK_I2C_SET_BIT(IoC, SetBits) {			\
-	SK_U8	OrgBits;				\
-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
-	SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits));	\
-}
-
-#define SK_I2C_CLR_BIT(IoC, ClrBits) {			\
-	SK_U8	OrgBits;				\
-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
-	SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits)));	\
-}
-
-#define SK_I2C_GET_SW(IoC, pI2cSw)	SK_IN8(IoC, B2_I2C_SW, pI2cSw)
-
-/*
- * define the possible sensor states
- */
-#define	SK_SEN_IDLE		0	/* Idle: sensor not read */
-#define	SK_SEN_VALUE	1	/* Value Read cycle */
-#define	SK_SEN_VALEXT	2	/* Extended Value Read cycle */
-
-/*
- * Conversion factor to convert read Voltage sensor to milli Volt
- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
- */
-#define	SK_LM80_VT_LSB		22	/* 22mV LSB resolution */
-#define	SK_LM80_TEMP_LSB	10	/* 1 degree LSB resolution */
-#define	SK_LM80_TEMPEXT_LSB	 5	/* 0.5 degree LSB resolution for ext. val. */
-
-/*
- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
- * assuming: 6500rpm, 4 pulses, divisor 1
- */
-#define SK_LM80_FAN_FAKTOR	((22500L*60)/(1*2))
-
-/*
- * Define sensor management data
- * Maximum is reached on Genesis copper dual port and Yukon-64
- * Board specific maximum is in pAC->I2c.MaxSens
- */
-#define	SK_MAX_SENSORS	8	/* maximal no. of installed sensors */
-#define	SK_MIN_SENSORS	5	/* minimal no. of installed sensors */
-
-/*
- * To watch the state machine (SM) use the timer in two ways
- * instead of one as hitherto
- */
-#define	SK_TIMER_WATCH_SM		0	/* Watch the SM to finish in a spec. time */
-#define	SK_TIMER_NEW_GAUGING	1	/* Start a new gauging when timer expires */
-
-/*
- * Defines for the individual thresholds
- */
-
-/* Temperature sensor */
-#define	SK_SEN_TEMP_HIGH_ERR	800	/* Temperature High Err  Threshold */
-#define	SK_SEN_TEMP_HIGH_WARN	700	/* Temperature High Warn Threshold */
-#define	SK_SEN_TEMP_LOW_WARN	100	/* Temperature Low  Warn Threshold */
-#define	SK_SEN_TEMP_LOW_ERR		  0	/* Temperature Low  Err  Threshold */
-
-/* VCC which should be 5 V */
-#define	SK_SEN_PCI_5V_HIGH_ERR		5588	/* Voltage PCI High Err  Threshold */
-#define	SK_SEN_PCI_5V_HIGH_WARN		5346	/* Voltage PCI High Warn Threshold */
-#define	SK_SEN_PCI_5V_LOW_WARN		4664	/* Voltage PCI Low  Warn Threshold */
-#define	SK_SEN_PCI_5V_LOW_ERR		4422	/* Voltage PCI Low  Err  Threshold */
-
-/*
- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
- * 1. Initialize lowest lower limit and highest higher limit.
- * 2. After the first value is read correct the upper or the lower limit to
- *    the appropriate C constant.
- *
- * Warning limits are +-5% of the exepected voltage.
- * Error limits are +-10% of the expected voltage.
- */
-
-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
-
-#define	SK_SEN_PCI_IO_5V_HIGH_ERR	5566	/* + 10% V PCI-IO High Err Threshold */
-#define	SK_SEN_PCI_IO_5V_HIGH_WARN	5324	/* +  5% V PCI-IO High Warn Threshold */
-					/*		5000	mVolt */
-#define	SK_SEN_PCI_IO_5V_LOW_WARN	4686	/* -  5% V PCI-IO Low Warn Threshold */
-#define	SK_SEN_PCI_IO_5V_LOW_ERR	4444	/* - 10% V PCI-IO Low Err Threshold */
-
-#define	SK_SEN_PCI_IO_RANGE_LIMITER	4000	/* 4000 mV range delimiter */
-
-/* correction values for the second pass */
-#define	SK_SEN_PCI_IO_3V3_HIGH_ERR	3850	/* + 15% V PCI-IO High Err Threshold */
-#define	SK_SEN_PCI_IO_3V3_HIGH_WARN	3674	/* + 10% V PCI-IO High Warn Threshold */
-					/*		3300	mVolt */
-#define	SK_SEN_PCI_IO_3V3_LOW_WARN	2926	/* - 10% V PCI-IO Low Warn Threshold */
-#define	SK_SEN_PCI_IO_3V3_LOW_ERR	2772	/* - 15% V PCI-IO Low Err  Threshold */
-
-/*
- * VDD voltage
- */
-#define	SK_SEN_VDD_HIGH_ERR		3630	/* Voltage ASIC High Err  Threshold */
-#define	SK_SEN_VDD_HIGH_WARN	3476	/* Voltage ASIC High Warn Threshold */
-#define	SK_SEN_VDD_LOW_WARN		3146	/* Voltage ASIC Low  Warn Threshold */
-#define	SK_SEN_VDD_LOW_ERR		2970	/* Voltage ASIC Low  Err  Threshold */
-
-/*
- * PHY PLL 3V3 voltage
- */
-#define	SK_SEN_PLL_3V3_HIGH_ERR		3630	/* Voltage PMA High Err  Threshold */
-#define	SK_SEN_PLL_3V3_HIGH_WARN	3476	/* Voltage PMA High Warn Threshold */
-#define	SK_SEN_PLL_3V3_LOW_WARN		3146	/* Voltage PMA Low  Warn Threshold */
-#define	SK_SEN_PLL_3V3_LOW_ERR		2970	/* Voltage PMA Low  Err  Threshold */
-
-/*
- * VAUX (YUKON only)
- */
-#define	SK_SEN_VAUX_3V3_HIGH_ERR	3630	/* Voltage VAUX High Err Threshold */
-#define	SK_SEN_VAUX_3V3_HIGH_WARN	3476	/* Voltage VAUX High Warn Threshold */
-#define	SK_SEN_VAUX_3V3_LOW_WARN	3146	/* Voltage VAUX Low Warn Threshold */
-#define	SK_SEN_VAUX_3V3_LOW_ERR		2970	/* Voltage VAUX Low Err Threshold */
-#define	SK_SEN_VAUX_0V_WARN_ERR		   0	/* if VAUX not present */
-#define	SK_SEN_VAUX_RANGE_LIMITER	1000	/* 1000 mV range delimiter */
-
-/*
- * PHY 2V5 voltage
- */
-#define	SK_SEN_PHY_2V5_HIGH_ERR		2750	/* Voltage PHY High Err Threshold */
-#define	SK_SEN_PHY_2V5_HIGH_WARN	2640	/* Voltage PHY High Warn Threshold */
-#define	SK_SEN_PHY_2V5_LOW_WARN		2376	/* Voltage PHY Low Warn Threshold */
-#define	SK_SEN_PHY_2V5_LOW_ERR		2222	/* Voltage PHY Low Err Threshold */
-
-/*
- * ASIC Core 1V5 voltage (YUKON only)
- */
-#define	SK_SEN_CORE_1V5_HIGH_ERR	1650	/* Voltage ASIC Core High Err Threshold */
-#define	SK_SEN_CORE_1V5_HIGH_WARN	1575	/* Voltage ASIC Core High Warn Threshold */
-#define	SK_SEN_CORE_1V5_LOW_WARN	1425	/* Voltage ASIC Core Low Warn Threshold */
-#define	SK_SEN_CORE_1V5_LOW_ERR 	1350	/* Voltage ASIC Core Low Err Threshold */
-
-/*
- * FAN 1 speed
- */
-/* assuming: 6500rpm +-15%, 4 pulses,
- * warning at:	80 %
- * error at:	70 %
- * no upper limit
- */
-#define	SK_SEN_FAN_HIGH_ERR		20000	/* FAN Speed High Err Threshold */
-#define	SK_SEN_FAN_HIGH_WARN	20000	/* FAN Speed High Warn Threshold */
-#define	SK_SEN_FAN_LOW_WARN		 5200	/* FAN Speed Low Warn Threshold */
-#define	SK_SEN_FAN_LOW_ERR		 4550	/* FAN Speed Low Err Threshold */
-
-/*
- * Some Voltages need dynamic thresholds
- */
-#define	SK_SEN_DYN_INIT_NONE		 0  /* No dynamic init of thresholds */
-#define	SK_SEN_DYN_INIT_PCI_IO		10  /* Init PCI-IO with new thresholds */
-#define	SK_SEN_DYN_INIT_VAUX		11  /* Init VAUX with new thresholds */
-
-extern	int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
-#endif	/* n_INC_SKGEI2C_H */
diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
deleted file mode 100644
index 143e635..0000000
--- a/drivers/net/sk98lin/h/skgeinit.h
+++ /dev/null
@@ -1,797 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgeinit.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.83 $
- * Date:	$Date: 2003/09/16 14:07:37 $
- * Purpose:	Structures and prototypes for the GE Init Module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEINIT_H_
-#define __INC_SKGEINIT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_TEST_VAL		0x11335577UL
-
-/* modifying Link LED behaviour (used with SkGeLinkLED()) */
-#define SK_LNK_OFF		LED_OFF
-#define SK_LNK_ON		(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LNK_BLINK	(LED_ON | LED_BLK_ON  | LED_SYNC_ON)
-#define SK_LNK_PERM		(LED_ON | LED_BLK_OFF | LED_SYNC_ON)
-#define SK_LNK_TST		(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
-
-/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
-#define SK_LED_OFF		LED_OFF
-#define SK_LED_ACTIVE	(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LED_STANDBY	(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
-
-/* addressing LED Registers in SkGeXmitLED() */
-#define XMIT_LED_INI	0
-#define XMIT_LED_CNT	(RX_LED_VAL - RX_LED_INI)
-#define XMIT_LED_CTRL	(RX_LED_CTRL- RX_LED_INI)
-#define XMIT_LED_TST	(RX_LED_TST - RX_LED_INI)
-
-/* parameter 'Mode' when calling SkGeXmitLED() */
-#define SK_LED_DIS	0
-#define SK_LED_ENA	1
-#define SK_LED_TST	2
-
-/* Counter and Timer constants, for a host clock of 62.5 MHz */
-#define SK_XMIT_DUR		0x002faf08UL	/*  50 ms */
-#define SK_BLK_DUR		0x01dcd650UL	/* 500 ms */
-
-#define SK_DPOLL_DEF	0x00ee6b28UL	/* 250 ms at 62.5 MHz */
-
-#define SK_DPOLL_MAX	0x00ffffffUL	/* 268 ms at 62.5 MHz */
-										/* 215 ms at 78.12 MHz */
-
-#define SK_FACT_62		100			/* is given in percent */
-#define SK_FACT_53		 85         /* on GENESIS:	53.12 MHz */
-#define SK_FACT_78		125			/* on YUKON:	78.12 MHz */
-
-/* Timeout values */
-#define SK_MAC_TO_53	72			/* MAC arbiter timeout */
-#define SK_PKT_TO_53	0x2000		/* Packet arbiter timeout */
-#define SK_PKT_TO_MAX	0xffff		/* Maximum value */
-#define SK_RI_TO_53		36			/* RAM interface timeout */
-
-#define SK_PHY_ACC_TO	600000		/* PHY access timeout */
-
-/* RAM Buffer High Pause Threshold values */
-#define SK_RB_ULPP		( 8 * 1024)	/* Upper Level in kB/8 */
-#define SK_RB_LLPP_S	(10 * 1024)	/* Lower Level for small Queues */
-#define SK_RB_LLPP_B	(16 * 1024)	/* Lower Level for big Queues */
-
-#ifndef SK_BMU_RX_WM
-#define SK_BMU_RX_WM	0x600		/* BMU Rx Watermark */
-#endif
-#ifndef SK_BMU_TX_WM
-#define SK_BMU_TX_WM	0x600		/* BMU Tx Watermark */
-#endif
-
-/* XMAC II Rx High Watermark */
-#define SK_XM_RX_HI_WM	0x05aa		/* 1450 */
-
-/* XMAC II Tx Threshold */
-#define SK_XM_THR_REDL	0x01fb		/* .. for redundant link usage */
-#define SK_XM_THR_SL	0x01fb		/* .. for single link adapters */
-#define SK_XM_THR_MULL	0x01fb		/* .. for multiple link usage */
-#define SK_XM_THR_JUMBO	0x03fc		/* .. for jumbo frame usage */
-
-/* values for GIPortUsage */
-#define SK_RED_LINK		1		/* redundant link usage */
-#define SK_MUL_LINK		2		/* multiple link usage */
-#define SK_JUMBO_LINK	3		/* driver uses jumbo frames */
-
-/* Minimum RAM Buffer Rx Queue Size */
-#define SK_MIN_RXQ_SIZE	16		/* 16 kB */
-
-/* Minimum RAM Buffer Tx Queue Size */
-#define SK_MIN_TXQ_SIZE	16		/* 16 kB */
-
-/* Queue Size units */
-#define QZ_UNITS		0x7
-#define QZ_STEP			8
-
-/* Percentage of queue size from whole memory */
-/* 80 % for receive */
-#define RAM_QUOTA_RX	80L
-/* 0% for sync transfer */
-#define	RAM_QUOTA_SYNC	0L
-/* the rest (20%) is taken for async transfer */
-
-/* Get the rounded queue size in Bytes in 8k steps */
-#define ROUND_QUEUE_SIZE(SizeInBytes)					\
-	((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) &	\
-	~(QZ_STEP-1))
-
-/* Get the rounded queue size in KBytes in 8k steps */
-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
-	ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
-
-/* Types of RAM Buffer Queues */
-#define SK_RX_SRAM_Q	1	/* small receive queue */
-#define SK_RX_BRAM_Q	2	/* big receive queue */
-#define SK_TX_RAM_Q		3	/* small or big transmit queue */
-
-/* parameter 'Dir' when calling SkGeStopPort() */
-#define SK_STOP_TX	1	/* Stops the transmit path, resets the XMAC */
-#define SK_STOP_RX	2	/* Stops the receive path */
-#define SK_STOP_ALL	3	/* Stops Rx and Tx path, resets the XMAC */
-
-/* parameter 'RstMode' when calling SkGeStopPort() */
-#define SK_SOFT_RST	1	/* perform a software reset */
-#define SK_HARD_RST	2	/* perform a hardware reset */
-
-/* Init Levels */
-#define SK_INIT_DATA	0	/* Init level 0: init data structures */
-#define SK_INIT_IO		1	/* Init level 1: init with IOs */
-#define SK_INIT_RUN		2	/* Init level 2: init for run time */
-
-/* Link Mode Parameter */
-#define SK_LMODE_HALF		1	/* Half Duplex Mode */
-#define SK_LMODE_FULL		2	/* Full Duplex Mode */
-#define SK_LMODE_AUTOHALF	3	/* AutoHalf Duplex Mode */
-#define SK_LMODE_AUTOFULL	4	/* AutoFull Duplex Mode */
-#define SK_LMODE_AUTOBOTH	5	/* AutoBoth Duplex Mode */
-#define SK_LMODE_AUTOSENSE	6	/* configured mode auto sensing */
-#define SK_LMODE_INDETERMINATED	7	/* indeterminated */
-
-/* Auto-negotiation timeout in 100ms granularity */
-#define SK_AND_MAX_TO		6	/* Wait 600 msec before link comes up */
-
-/* Auto-negotiation error codes */
-#define SK_AND_OK			0	/* no error */
-#define SK_AND_OTHER		1	/* other error than below */
-#define SK_AND_DUP_CAP		2	/* Duplex capabilities error */
-
-
-/* Link Speed Capabilities */
-#define SK_LSPEED_CAP_AUTO			(1<<0)	/* Automatic resolution */
-#define SK_LSPEED_CAP_10MBPS		(1<<1)	/* 10 Mbps */
-#define SK_LSPEED_CAP_100MBPS		(1<<2)	/* 100 Mbps */
-#define SK_LSPEED_CAP_1000MBPS		(1<<3)	/* 1000 Mbps */
-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Speed Parameter */
-#define SK_LSPEED_AUTO				1	/* Automatic resolution */
-#define SK_LSPEED_10MBPS			2	/* 10 Mbps */
-#define SK_LSPEED_100MBPS			3	/* 100 Mbps */
-#define SK_LSPEED_1000MBPS			4	/* 1000 Mbps */
-#define SK_LSPEED_INDETERMINATED	5	/* indeterminated */
-
-/* Link Speed Current State */
-#define SK_LSPEED_STAT_UNKNOWN		1
-#define SK_LSPEED_STAT_10MBPS		2
-#define SK_LSPEED_STAT_100MBPS 		3
-#define SK_LSPEED_STAT_1000MBPS		4
-#define SK_LSPEED_STAT_INDETERMINATED 5
-
-
-/* Link Capability Parameter */
-#define SK_LMODE_CAP_HALF		(1<<0)	/* Half Duplex Mode */
-#define SK_LMODE_CAP_FULL		(1<<1)	/* Full Duplex Mode */
-#define SK_LMODE_CAP_AUTOHALF	(1<<2)	/* AutoHalf Duplex Mode */
-#define SK_LMODE_CAP_AUTOFULL	(1<<3)	/* AutoFull Duplex Mode */
-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Mode Current State */
-#define SK_LMODE_STAT_UNKNOWN	1	/* Unknown Duplex Mode */
-#define SK_LMODE_STAT_HALF		2	/* Half Duplex Mode */
-#define SK_LMODE_STAT_FULL		3	/* Full Duplex Mode */
-#define SK_LMODE_STAT_AUTOHALF	4	/* Half Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_AUTOFULL	5	/* Full Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_INDETERMINATED 6	/* indeterminated */
-
-/* Flow Control Mode Parameter (and capabilities) */
-#define SK_FLOW_MODE_NONE		1	/* No Flow-Control */
-#define SK_FLOW_MODE_LOC_SEND	2	/* Local station sends PAUSE */
-#define SK_FLOW_MODE_SYMMETRIC	3	/* Both stations may send PAUSE */
-#define SK_FLOW_MODE_SYM_OR_REM	4	/* Both stations may send PAUSE or
-					 * just the remote station may send PAUSE
-					 */
-#define SK_FLOW_MODE_INDETERMINATED 5	/* indeterminated */
-
-/* Flow Control Status Parameter */
-#define SK_FLOW_STAT_NONE		1	/* No Flow Control */
-#define SK_FLOW_STAT_REM_SEND	2	/* Remote Station sends PAUSE */
-#define SK_FLOW_STAT_LOC_SEND	3	/* Local station sends PAUSE */
-#define SK_FLOW_STAT_SYMMETRIC	4	/* Both station may send PAUSE */
-#define SK_FLOW_STAT_INDETERMINATED 5	/* indeterminated */
-
-/* Master/Slave Mode Capabilities */
-#define SK_MS_CAP_AUTO		(1<<0)	/* Automatic resolution */
-#define SK_MS_CAP_MASTER	(1<<1)	/* This station is master */
-#define SK_MS_CAP_SLAVE		(1<<2)	/* This station is slave */
-#define SK_MS_CAP_INDETERMINATED (1<<3)	/* indeterminated */
-
-/* Set Master/Slave Mode Parameter (and capabilities) */
-#define SK_MS_MODE_AUTO		1	/* Automatic resolution */
-#define SK_MS_MODE_MASTER	2	/* This station is master */
-#define SK_MS_MODE_SLAVE	3	/* This station is slave */
-#define SK_MS_MODE_INDETERMINATED 4	/* indeterminated */
-
-/* Master/Slave Status Parameter */
-#define SK_MS_STAT_UNSET	1	/* The M/S status is not set */
-#define SK_MS_STAT_MASTER	2	/* This station is master */
-#define SK_MS_STAT_SLAVE	3	/* This station is slave */
-#define SK_MS_STAT_FAULT	4	/* M/S resolution failed */
-#define SK_MS_STAT_INDETERMINATED 5	/* indeterminated */
-
-/* parameter 'Mode' when calling SkXmSetRxCmd() */
-#define SK_STRIP_FCS_ON		(1<<0)	/* Enable  FCS stripping of Rx frames */
-#define SK_STRIP_FCS_OFF	(1<<1)	/* Disable FCS stripping of Rx frames */
-#define SK_STRIP_PAD_ON		(1<<2)	/* Enable  pad byte stripping of Rx fr */
-#define SK_STRIP_PAD_OFF	(1<<3)	/* Disable pad byte stripping of Rx fr */
-#define SK_LENERR_OK_ON		(1<<4)	/* Don't chk fr for in range len error */
-#define SK_LENERR_OK_OFF	(1<<5)	/* Check frames for in range len error */
-#define SK_BIG_PK_OK_ON		(1<<6)	/* Don't set Rx Error bit for big frames */
-#define SK_BIG_PK_OK_OFF	(1<<7)	/* Set Rx Error bit for big frames */
-#define SK_SELF_RX_ON		(1<<8)	/* Enable  Rx of own packets */
-#define SK_SELF_RX_OFF		(1<<9)	/* Disable Rx of own packets */
-
-/* parameter 'Para' when calling SkMacSetRxTxEn() */
-#define SK_MAC_LOOPB_ON		(1<<0)	/* Enable  MAC Loopback Mode */
-#define SK_MAC_LOOPB_OFF	(1<<1)	/* Disable MAC Loopback Mode */
-#define SK_PHY_LOOPB_ON		(1<<2)	/* Enable  PHY Loopback Mode */
-#define SK_PHY_LOOPB_OFF	(1<<3)	/* Disable PHY Loopback Mode */
-#define SK_PHY_FULLD_ON		(1<<4)	/* Enable  GMII Full Duplex */
-#define SK_PHY_FULLD_OFF	(1<<5)	/* Disable GMII Full Duplex */
-
-/* States of PState */
-#define SK_PRT_RESET	0	/* the port is reset */
-#define SK_PRT_STOP		1	/* the port is stopped (similar to SW reset) */
-#define SK_PRT_INIT		2	/* the port is initialized */
-#define SK_PRT_RUN		3	/* the port has an active link */
-
-/* PHY power down modes */
-#define PHY_PM_OPERATIONAL_MODE		0	/* PHY operational mode */
-#define PHY_PM_DEEP_SLEEP			1	/* coma mode --> minimal power */
-#define PHY_PM_IEEE_POWER_DOWN		2	/* IEEE 22.2.4.1.5 compl. power down */
-#define PHY_PM_ENERGY_DETECT		3	/* energy detect */
-#define PHY_PM_ENERGY_DETECT_PLUS	4	/* energy detect plus */
-
-/* Default receive frame limit for Workaround of XMAC Errata */
-#define SK_DEF_RX_WA_LIM	SK_CONSTU64(100)
-
-/* values for GILedBlinkCtrl (LED Blink Control) */
-#define SK_ACT_LED_BLINK	(1<<0)	/* Active LED blinking */
-#define SK_DUP_LED_NORMAL	(1<<1)	/* Duplex LED normal */
-#define SK_LED_LINK100_ON	(1<<2)	/* Link 100M LED on */
-
-/* Link Partner Status */
-#define SK_LIPA_UNKNOWN	0	/* Link partner is in unknown state */
-#define SK_LIPA_MANUAL	1	/* Link partner is in detected manual state */
-#define SK_LIPA_AUTO	2	/* Link partner is in auto-negotiation state */
-
-/* Maximum Restarts before restart is ignored (3Com WA) */
-#define SK_MAX_LRESTART	3	/* Max. 3 times the link is restarted */
-
-/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
-#define SK_MAX_ANEG_TO	10	/* Max. 10 times the sense mode is reset */
-
-/* structures *****************************************************************/
-
-/*
- * MAC specific functions
- */
-typedef struct s_GeMacFunc {
-	int  (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
-	int  (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
-							SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
-	int  (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
-	int  (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
-						   SK_U16 IStatus, SK_U64 SK_FAR *pVal);
-} SK_GEMACFUNC;
-
-/*
- * Port Structure
- */
-typedef	struct s_GePort {
-#ifndef SK_DIAG
-	SK_TIMER	PWaTimer;	/* Workaround Timer */
-	SK_TIMER	HalfDupChkTimer;
-#endif /* SK_DIAG */
-	SK_U32	PPrevShorts;	/* Previous Short Counter checking */
-	SK_U32	PPrevFcs;		/* Previous FCS Error Counter checking */
-	SK_U64	PPrevRx;		/* Previous RxOk Counter checking */
-	SK_U64	PRxLim;			/* Previous RxOk Counter checking */
-	SK_U64	LastOctets;		/* For half duplex hang check */
-	int		PLinkResCt;		/* Link Restart Counter */
-	int		PAutoNegTimeOut;/* Auto-negotiation timeout current value */
-	int		PAutoNegTOCt;	/* Auto-negotiation Timeout Counter */
-	int		PRxQSize;		/* Port Rx Queue Size in kB */
-	int		PXSQSize;		/* Port Synchronous  Transmit Queue Size in kB */
-	int		PXAQSize;		/* Port Asynchronous Transmit Queue Size in kB */
-	SK_U32	PRxQRamStart;	/* Receive Queue RAM Buffer Start Address */
-	SK_U32	PRxQRamEnd;		/* Receive Queue RAM Buffer End Address */
-	SK_U32	PXsQRamStart;	/* Sync Tx Queue RAM Buffer Start Address */
-	SK_U32	PXsQRamEnd;		/* Sync Tx Queue RAM Buffer End Address */
-	SK_U32	PXaQRamStart;	/* Async Tx Queue RAM Buffer Start Address */
-	SK_U32	PXaQRamEnd;		/* Async Tx Queue RAM Buffer End Address */
-	SK_U32	PRxOverCnt;		/* Receive Overflow Counter */
-	int		PRxQOff;		/* Rx Queue Address Offset */
-	int		PXsQOff;		/* Synchronous Tx Queue Address Offset */
-	int		PXaQOff;		/* Asynchronous Tx Queue Address Offset */
-	int		PhyType;		/* PHY used on this port */
-	int		PState;			/* Port status (reset, stop, init, run) */
-	SK_U16	PhyId1;			/* PHY Id1 on this port */
-	SK_U16	PhyAddr;		/* MDIO/MDC PHY address */
-	SK_U16	PIsave;			/* Saved Interrupt status word */
-	SK_U16	PSsave;			/* Saved PHY status word */
-	SK_U16	PGmANegAdv;		/* Saved GPhy AutoNegAdvertisment register */
-	SK_BOOL	PHWLinkUp;		/* The hardware Link is up (wiring) */
-	SK_BOOL	PLinkBroken;	/* Is Link broken ? */
-	SK_BOOL	PCheckPar;		/* Do we check for parity errors ? */
-	SK_BOOL	HalfDupTimerActive;
-	SK_U8	PLinkCap;		/* Link Capabilities */
-	SK_U8	PLinkModeConf;	/* Link Mode configured */
-	SK_U8	PLinkMode;		/* Link Mode currently used */
-	SK_U8	PLinkModeStatus;/* Link Mode Status */
-	SK_U8	PLinkSpeedCap;	/* Link Speed Capabilities(10/100/1000 Mbps) */
-	SK_U8	PLinkSpeed;		/* configured Link Speed (10/100/1000 Mbps) */
-	SK_U8	PLinkSpeedUsed;	/* current Link Speed (10/100/1000 Mbps) */
-	SK_U8	PFlowCtrlCap;	/* Flow Control Capabilities */
-	SK_U8	PFlowCtrlMode;	/* Flow Control Mode */
-	SK_U8	PFlowCtrlStatus;/* Flow Control Status */
-	SK_U8	PMSCap;			/* Master/Slave Capabilities */
-	SK_U8	PMSMode;		/* Master/Slave Mode */
-	SK_U8	PMSStatus;		/* Master/Slave Status */
-	SK_BOOL	PAutoNegFail;	/* Auto-negotiation fail flag */
-	SK_U8	PLipaAutoNeg;	/* Auto-negotiation possible with Link Partner */
-	SK_U8	PCableLen;		/* Cable Length */
-	SK_U8	PMdiPairLen[4];	/* MDI[0..3] Pair Length */
-	SK_U8	PMdiPairSts[4];	/* MDI[0..3] Pair Diagnostic Status */
-	SK_U8	PPhyPowerState;	/* PHY current power state */
-	int		PMacColThres;	/* MAC Collision Threshold */
-	int		PMacJamLen;		/* MAC Jam length */
-	int		PMacJamIpgVal;	/* MAC Jam IPG */
-	int		PMacJamIpgData;	/* MAC IPG Jam to Data */
-	int		PMacIpgData;	/* MAC Data IPG */
-	SK_BOOL PMacLimit4;		/* reset collision counter and backoff algorithm */
-} SK_GEPORT;
-
-/*
- * Gigabit Ethernet Initialization Struct
- * (has to be included in the adapter context)
- */
-typedef	struct s_GeInit {
-	int			GIChipId;		/* Chip Identification Number */
-	int			GIChipRev;		/* Chip Revision Number */
-	SK_U8		GIPciHwRev;		/* PCI HW Revision Number */
-	SK_BOOL		GIGenesis;		/* Genesis adapter ? */
-	SK_BOOL		GIYukon;		/* YUKON-A1/Bx chip */
-	SK_BOOL		GIYukonLite;	/* YUKON-Lite chip */
-	SK_BOOL		GICopperType;	/* Copper Type adapter ? */
-	SK_BOOL		GIPciSlot64;	/* 64-bit PCI Slot */
-	SK_BOOL		GIPciClock66;	/* 66 MHz PCI Clock */
-	SK_BOOL		GIVauxAvail;	/* VAUX available (YUKON) */
-	SK_BOOL		GIYukon32Bit;	/* 32-Bit YUKON adapter */
-	SK_U16		GILedBlinkCtrl;	/* LED Blink Control */
-	int			GIMacsFound;	/* Number of MACs found on this adapter */
-	int			GIMacType;		/* MAC Type used on this adapter */
-	int			GIHstClkFact;	/* Host Clock Factor (62.5 / HstClk * 100) */
-	int			GIPortUsage;	/* Driver Port Usage */
-	int			GILevel;		/* Initialization Level completed */
-	int			GIRamSize;		/* The RAM size of the adapter in kB */
-	int			GIWolOffs;		/* WOL Register Offset (HW-Bug in Rev. A) */
-	SK_U32		GIRamOffs;		/* RAM Address Offset for addr calculation */
-	SK_U32		GIPollTimerVal;	/* Descr. Poll Timer Init Val (HstClk ticks) */
-	SK_U32		GIValIrqMask;	/* Value for Interrupt Mask */
-	SK_U32		GITimeStampCnt;	/* Time Stamp High Counter (YUKON only) */
-	SK_GEPORT	GP[SK_MAX_MACS];/* Port Dependent Information */
-	SK_GEMACFUNC GIFunc;		/* MAC depedent functions */
-} SK_GEINIT;
-
-/*
- * Error numbers and messages for skxmac2.c and skgeinit.c
- */
-#define SKERR_HWI_E001		(SK_ERRBASE_HWINIT)
-#define SKERR_HWI_E001MSG	"SkXmClrExactAddr() has got illegal parameters"
-#define SKERR_HWI_E002		(SKERR_HWI_E001+1)
-#define SKERR_HWI_E002MSG	"SkGeInit(): Level 1 call missing"
-#define SKERR_HWI_E003		(SKERR_HWI_E002+1)
-#define SKERR_HWI_E003MSG	"SkGeInit() called with illegal init Level"
-#define SKERR_HWI_E004		(SKERR_HWI_E003+1)
-#define SKERR_HWI_E004MSG	"SkGeInitPort(): Queue Size illegal configured"
-#define SKERR_HWI_E005		(SKERR_HWI_E004+1)
-#define SKERR_HWI_E005MSG	"SkGeInitPort(): cannot init running ports"
-#define SKERR_HWI_E006		(SKERR_HWI_E005+1)
-#define SKERR_HWI_E006MSG	"SkGeMacInit(): PState does not match HW state"
-#define SKERR_HWI_E007		(SKERR_HWI_E006+1)
-#define SKERR_HWI_E007MSG	"SkXmInitDupMd() called with invalid Dup Mode"
-#define SKERR_HWI_E008		(SKERR_HWI_E007+1)
-#define SKERR_HWI_E008MSG	"SkXmSetRxCmd() called with invalid Mode"
-#define SKERR_HWI_E009		(SKERR_HWI_E008+1)
-#define SKERR_HWI_E009MSG	"SkGeCfgSync() called although PXSQSize zero"
-#define SKERR_HWI_E010		(SKERR_HWI_E009+1)
-#define SKERR_HWI_E010MSG	"SkGeCfgSync() called with invalid parameters"
-#define SKERR_HWI_E011		(SKERR_HWI_E010+1)
-#define SKERR_HWI_E011MSG	"SkGeInitPort(): Receive Queue Size too small"
-#define SKERR_HWI_E012		(SKERR_HWI_E011+1)
-#define SKERR_HWI_E012MSG	"SkGeInitPort(): invalid Queue Size specified"
-#define SKERR_HWI_E013		(SKERR_HWI_E012+1)
-#define SKERR_HWI_E013MSG	"SkGeInitPort(): cfg changed for running queue"
-#define SKERR_HWI_E014		(SKERR_HWI_E013+1)
-#define SKERR_HWI_E014MSG	"SkGeInitPort(): unknown GIPortUsage specified"
-#define SKERR_HWI_E015		(SKERR_HWI_E014+1)
-#define SKERR_HWI_E015MSG	"Illegal Link mode parameter"
-#define SKERR_HWI_E016		(SKERR_HWI_E015+1)
-#define SKERR_HWI_E016MSG	"Illegal Flow control mode parameter"
-#define SKERR_HWI_E017		(SKERR_HWI_E016+1)
-#define SKERR_HWI_E017MSG	"Illegal value specified for GIPollTimerVal"
-#define SKERR_HWI_E018		(SKERR_HWI_E017+1)
-#define SKERR_HWI_E018MSG	"FATAL: SkGeStopPort() does not terminate (Tx)"
-#define SKERR_HWI_E019		(SKERR_HWI_E018+1)
-#define SKERR_HWI_E019MSG	"Illegal Speed parameter"
-#define SKERR_HWI_E020		(SKERR_HWI_E019+1)
-#define SKERR_HWI_E020MSG	"Illegal Master/Slave parameter"
-#define SKERR_HWI_E021		(SKERR_HWI_E020+1)
-#define	SKERR_HWI_E021MSG	"MacUpdateStats(): cannot update statistic counter"
-#define	SKERR_HWI_E022		(SKERR_HWI_E021+1)
-#define	SKERR_HWI_E022MSG	"MacStatistic(): illegal statistic base address"
-#define SKERR_HWI_E023		(SKERR_HWI_E022+1)
-#define SKERR_HWI_E023MSG	"SkGeInitPort(): Transmit Queue Size too small"
-#define SKERR_HWI_E024		(SKERR_HWI_E023+1)
-#define SKERR_HWI_E024MSG	"FATAL: SkGeStopPort() does not terminate (Rx)"
-#define SKERR_HWI_E025		(SKERR_HWI_E024+1)
-#define SKERR_HWI_E025MSG	""
-
-/* function prototypes ********************************************************/
-
-#ifndef	SK_KR_PROTO
-
-/*
- * public functions in skgeinit.c
- */
-extern void	SkGePollTxD(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL PollTxD);
-
-extern void	SkGeYellowLED(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		State);
-
-extern int	SkGeCfgSync(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U32	IntTime,
-	SK_U32	LimCount,
-	int		SyncMode);
-
-extern void	SkGeLoadLnkSyncCnt(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U32	CntVal);
-
-extern void	SkGeStopPort(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Dir,
-	int		RstMode);
-
-extern int	SkGeInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Level);
-
-extern void	SkGeDeInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC);
-
-extern int	SkGeInitPort(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkGeXmitLED(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Led,
-	int		Mode);
-
-extern int	SkGeInitAssignRamToQueues(
-	SK_AC	*pAC,
-	int		ActivePort,
-	SK_BOOL	DualNet);
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacSoftRst(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacHardRst(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkXmInitMac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkGmInitMac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void SkMacInitPhy(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	DoLoop);
-
-extern void SkMacIrqDisable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacFlushTxFifo(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacIrq(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern int	SkMacAutoNegDone(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacAutoNegLipaPhy(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U16	IStatus);
-
-extern int  SkMacRxTxEnable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacPromiscMode(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-
-extern void	SkMacHashing(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-
-extern void	SkXmPhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	SK_FAR *pVal);
-
-extern void	SkXmPhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkGmPhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	SK_FAR *pVal);
-
-extern void	SkGmPhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkXmClrExactAddr(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		StartNum,
-	int		StopNum);
-
-extern void	SkXmAutoNegLipaXmac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U16	IStatus);
-
-extern int SkXmUpdateStats(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkGmUpdateStats(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkXmMacStatistic(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	StatAddr,
-	SK_U32	SK_FAR *pVal);
-
-extern int SkGmMacStatistic(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	StatAddr,
-	SK_U32	SK_FAR *pVal);
-
-extern int SkXmResetCounter(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkGmResetCounter(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkXmOverflowStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16  IStatus,
-	SK_U64	SK_FAR *pStatus);
-
-extern int SkGmOverflowStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	MacStatus,
-	SK_U64	SK_FAR *pStatus);
-
-extern int SkGmCableDiagStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	StartTest);
-
-#ifdef SK_DIAG
-extern void	SkGePhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	*pVal);
-
-extern void	SkGePhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkMacSetRxCmd(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Mode);
-extern void	SkMacCrcGener(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-extern void	SkMacTimeStamp(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-extern void	SkXmSendCont(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-#endif /* SK_DIAG */
-
-#else	/* SK_KR_PROTO */
-
-/*
- * public functions in skgeinit.c
- */
-extern void	SkGePollTxD();
-extern void	SkGeYellowLED();
-extern int	SkGeCfgSync();
-extern void	SkGeLoadLnkSyncCnt();
-extern void	SkGeStopPort();
-extern int	SkGeInit();
-extern void	SkGeDeInit();
-extern int	SkGeInitPort();
-extern void	SkGeXmitLED();
-extern int	SkGeInitAssignRamToQueues();
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable();
-extern void	SkMacSoftRst();
-extern void	SkMacHardRst();
-extern void SkMacInitPhy();
-extern int  SkMacRxTxEnable();
-extern void SkMacPromiscMode();
-extern void SkMacHashing();
-extern void SkMacIrqDisable();
-extern void	SkMacFlushTxFifo();
-extern void	SkMacIrq();
-extern int	SkMacAutoNegDone();
-extern void	SkMacAutoNegLipaPhy();
-extern void	SkXmInitMac();
-extern void	SkXmPhyRead();
-extern void	SkXmPhyWrite();
-extern void	SkGmInitMac();
-extern void	SkGmPhyRead();
-extern void	SkGmPhyWrite();
-extern void	SkXmClrExactAddr();
-extern void	SkXmAutoNegLipaXmac();
-extern int	SkXmUpdateStats();
-extern int	SkGmUpdateStats();
-extern int	SkXmMacStatistic();
-extern int	SkGmMacStatistic();
-extern int	SkXmResetCounter();
-extern int	SkGmResetCounter();
-extern int	SkXmOverflowStatus();
-extern int	SkGmOverflowStatus();
-extern int	SkGmCableDiagStatus();
-
-#ifdef SK_DIAG
-extern void	SkGePhyRead();
-extern void	SkGePhyWrite();
-extern void	SkMacSetRxCmd();
-extern void	SkMacCrcGener();
-extern void	SkMacTimeStamp();
-extern void	SkXmSendCont();
-#endif /* SK_DIAG */
-
-#endif	/* SK_KR_PROTO */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKGEINIT_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
deleted file mode 100644
index ddd304f..0000000
--- a/drivers/net/sk98lin/h/skgepnm2.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnm2.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.36 $
- * Date:	$Date: 2003/05/23 12:45:13 $
- * Purpose:	Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNM2_H_
-#define _SKGEPNM2_H_
-
-/*
- * General definitions
- */
-#define SK_PNMI_CHIPSET_XMAC	1	/* XMAC11800FP */
-#define SK_PNMI_CHIPSET_YUKON	2	/* YUKON */
-
-#define	SK_PNMI_BUS_PCI		1	/* PCI bus*/
-
-/*
- * Actions
- */
-#define SK_PNMI_ACT_IDLE		1
-#define SK_PNMI_ACT_RESET		2
-#define SK_PNMI_ACT_SELFTEST	3
-#define SK_PNMI_ACT_RESETCNT	4
-
-/*
- * VPD releated defines
- */
-
-#define SK_PNMI_VPD_RW		1
-#define SK_PNMI_VPD_RO		2
-
-#define SK_PNMI_VPD_OK			0
-#define SK_PNMI_VPD_NOTFOUND	1
-#define SK_PNMI_VPD_CUT			2
-#define SK_PNMI_VPD_TIMEOUT		3
-#define SK_PNMI_VPD_FULL		4
-#define SK_PNMI_VPD_NOWRITE		5
-#define SK_PNMI_VPD_FATAL		6
-
-#define SK_PNMI_VPD_IGNORE	0
-#define SK_PNMI_VPD_CREATE	1
-#define SK_PNMI_VPD_DELETE	2
-
-
-/*
- * RLMT related defines
- */
-#define SK_PNMI_DEF_RLMT_CHG_THRES	240	/* 4 changes per minute */
-
-
-/*
- * VCT internal status values
- */
-#define SK_PNMI_VCT_PENDING	32
-#define SK_PNMI_VCT_TEST_DONE	64
-#define SK_PNMI_VCT_LINK	128
-
-/*
- * Internal table definitions
- */
-#define SK_PNMI_GET		0
-#define SK_PNMI_PRESET	1
-#define SK_PNMI_SET		2
-
-#define SK_PNMI_RO		0
-#define SK_PNMI_RW		1
-#define SK_PNMI_WO		2
-
-typedef struct s_OidTabEntry {
-	SK_U32			Id;
-	SK_U32			InstanceNo;
-	unsigned int	StructSize;
-	unsigned int	Offset;
-	int				Access;
-	int				(* Func)(SK_AC *pAc, SK_IOC pIo, int action,
-							 SK_U32 Id, char* pBuf, unsigned int* pLen,
-							 SK_U32 Instance, unsigned int TableIndex,
-							 SK_U32 NetNumber);
-	SK_U16			Param;
-} SK_PNMI_TAB_ENTRY;
-
-
-/*
- * Trap lengths
- */
-#define SK_PNMI_TRAP_SIMPLE_LEN			17
-#define SK_PNMI_TRAP_SENSOR_LEN_BASE	46
-#define SK_PNMI_TRAP_RLMT_CHANGE_LEN	23
-#define SK_PNMI_TRAP_RLMT_PORT_LEN		23
-
-/*
- * Number of MAC types supported
- */
-#define SK_PNMI_MAC_TYPES	(SK_MAC_GMAC + 1)
-
-/*
- * MAC statistic data list (overall set for MAC types used)
- */
-enum SK_MACSTATS {
-	SK_PNMI_HTX				= 0,
-	SK_PNMI_HTX_OCTET,
-	SK_PNMI_HTX_OCTETHIGH 	= SK_PNMI_HTX_OCTET,
-	SK_PNMI_HTX_OCTETLOW,
-	SK_PNMI_HTX_BROADCAST,
-	SK_PNMI_HTX_MULTICAST,
-	SK_PNMI_HTX_UNICAST,
-	SK_PNMI_HTX_BURST,
-	SK_PNMI_HTX_PMACC,
-	SK_PNMI_HTX_MACC,
-	SK_PNMI_HTX_COL,
-	SK_PNMI_HTX_SINGLE_COL,
-	SK_PNMI_HTX_MULTI_COL,
-	SK_PNMI_HTX_EXCESS_COL,
-	SK_PNMI_HTX_LATE_COL,
-	SK_PNMI_HTX_DEFFERAL,
-	SK_PNMI_HTX_EXCESS_DEF,
-	SK_PNMI_HTX_UNDERRUN,
-	SK_PNMI_HTX_CARRIER,
-	SK_PNMI_HTX_UTILUNDER,
-	SK_PNMI_HTX_UTILOVER,
-	SK_PNMI_HTX_64,
-	SK_PNMI_HTX_127,
-	SK_PNMI_HTX_255,
-	SK_PNMI_HTX_511,
-	SK_PNMI_HTX_1023,
-	SK_PNMI_HTX_MAX,
-	SK_PNMI_HTX_LONGFRAMES,
-	SK_PNMI_HTX_SYNC,
-	SK_PNMI_HTX_SYNC_OCTET,
-	SK_PNMI_HTX_RESERVED,
-	
-	SK_PNMI_HRX,
-	SK_PNMI_HRX_OCTET,
-	SK_PNMI_HRX_OCTETHIGH	= SK_PNMI_HRX_OCTET,
-	SK_PNMI_HRX_OCTETLOW,
-	SK_PNMI_HRX_BADOCTET,
-	SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
-	SK_PNMI_HRX_BADOCTETLOW,
-	SK_PNMI_HRX_BROADCAST,
-	SK_PNMI_HRX_MULTICAST,
-	SK_PNMI_HRX_UNICAST,
-	SK_PNMI_HRX_PMACC,
-	SK_PNMI_HRX_MACC,
-	SK_PNMI_HRX_PMACC_ERR,
-	SK_PNMI_HRX_MACC_UNKWN,
-	SK_PNMI_HRX_BURST,
-	SK_PNMI_HRX_MISSED,
-	SK_PNMI_HRX_FRAMING,
-	SK_PNMI_HRX_UNDERSIZE,
-	SK_PNMI_HRX_OVERFLOW,
-	SK_PNMI_HRX_JABBER,
-	SK_PNMI_HRX_CARRIER,
-	SK_PNMI_HRX_IRLENGTH,
-	SK_PNMI_HRX_SYMBOL,
-	SK_PNMI_HRX_SHORTS,
-	SK_PNMI_HRX_RUNT,
-	SK_PNMI_HRX_TOO_LONG,
-	SK_PNMI_HRX_FCS,
-	SK_PNMI_HRX_CEXT,
-	SK_PNMI_HRX_UTILUNDER,
-	SK_PNMI_HRX_UTILOVER,
-	SK_PNMI_HRX_64,
-	SK_PNMI_HRX_127,
-	SK_PNMI_HRX_255,
-	SK_PNMI_HRX_511,
-	SK_PNMI_HRX_1023,
-	SK_PNMI_HRX_MAX,
-	SK_PNMI_HRX_LONGFRAMES,
-	
-	SK_PNMI_HRX_RESERVED,
-	
-	SK_PNMI_MAX_IDX		/* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
-};
-
-/*
- * MAC specific data
- */
-typedef struct s_PnmiStatAddr {
-	SK_U16		Reg;		/* MAC register containing the value */
-	SK_BOOL		GetOffset;	/* TRUE: Offset managed by PNMI (call GetStatVal())*/
-} SK_PNMI_STATADDR;
-
-
-/*
- * SK_PNMI_STRUCT_DATA copy offset evaluation macros
- */
-#define SK_PNMI_OFF(e)		((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_MAI_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_VPD_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
-#define SK_PNMI_SEN_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
-#define SK_PNMI_CHK_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
-#define SK_PNMI_STA_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
-#define SK_PNMI_CNF_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
-#define SK_PNMI_RLM_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
-#define SK_PNMI_MON_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
-#define SK_PNMI_TRP_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
-
-#define SK_PNMI_SET_STAT(b,s,o)	{SK_U32	Val32; char *pVal; \
-					Val32 = (s); \
-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
-						ReturnStatus.ErrorStatus)); \
-					SK_PNMI_STORE_U32(pVal, Val32); \
-					Val32 = (o); \
-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
-						ReturnStatus.ErrorOffset)); \
-					SK_PNMI_STORE_U32(pVal, Val32);}
-
-/*
- * Time macros
- */
-#ifndef SK_PNMI_HUNDREDS_SEC
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t)	(((t) * 100) / (SK_TICKS_PER_SEC))
-#endif /* !SK_TICKS_PER_SEC */
-#endif /* !SK_PNMI_HUNDREDS_SEC */
-
-/*
- * Macros to work around alignment problems
- */
-#ifndef SK_PNMI_STORE_U16
-#define SK_PNMI_STORE_U16(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1);}
-#endif
-
-#ifndef SK_PNMI_STORE_U32
-#define SK_PNMI_STORE_U32(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1); \
-					*((char *)(p) + 2) = \
-						*(((char *)&(v)) + 2); \
-					*((char *)(p) + 3) = \
-						*(((char *)&(v)) + 3);}
-#endif
-
-#ifndef SK_PNMI_STORE_U64
-#define SK_PNMI_STORE_U64(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1); \
-					*((char *)(p) + 2) = \
-						*(((char *)&(v)) + 2); \
-					*((char *)(p) + 3) = \
-						*(((char *)&(v)) + 3); \
-					*((char *)(p) + 4) = \
-						*(((char *)&(v)) + 4); \
-					*((char *)(p) + 5) = \
-						*(((char *)&(v)) + 5); \
-					*((char *)(p) + 6) = \
-						*(((char *)&(v)) + 6); \
-					*((char *)(p) + 7) = \
-						*(((char *)&(v)) + 7);}
-#endif
-
-#ifndef SK_PNMI_READ_U16
-#define SK_PNMI_READ_U16(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1);}
-#endif
-
-#ifndef SK_PNMI_READ_U32
-#define SK_PNMI_READ_U32(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1); \
-					*(((char *)&(v)) + 2) = \
-						*((char *)(p) + 2); \
-					*(((char *)&(v)) + 3) = \
-						*((char *)(p) + 3);}
-#endif
-
-#ifndef SK_PNMI_READ_U64
-#define SK_PNMI_READ_U64(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1); \
-					*(((char *)&(v)) + 2) = \
-						*((char *)(p) + 2); \
-					*(((char *)&(v)) + 3) = \
-						*((char *)(p) + 3); \
-					*(((char *)&(v)) + 4) = \
-						*((char *)(p) + 4); \
-					*(((char *)&(v)) + 5) = \
-						*((char *)(p) + 5); \
-					*(((char *)&(v)) + 6) = \
-						*((char *)(p) + 6); \
-					*(((char *)&(v)) + 7) = \
-						*((char *)(p) + 7);}
-#endif
-
-/*
- * Macros for Debug
- */
-#ifdef DEBUG
-
-#define SK_PNMI_CHECKFLAGS(vSt)	{if (pAC->Pnmi.MacUpdatedFlag > 0 || \
-					pAC->Pnmi.RlmtUpdatedFlag > 0 || \
-					pAC->Pnmi.SirqUpdatedFlag > 0) { \
-						SK_DBG_MSG(pAC, \
-						SK_DBGMOD_PNMI, \
-						SK_DBGCAT_CTRL,	\
-						("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
-						vSt, \
-						pAC->Pnmi.MacUpdatedFlag, \
-						pAC->Pnmi.RlmtUpdatedFlag, \
-						pAC->Pnmi.SirqUpdatedFlag))}}
-
-#else	/* !DEBUG */
-
-#define SK_PNMI_CHECKFLAGS(vSt)	/* Nothing */
-
-#endif	/* !DEBUG */
-
-#endif	/* _SKGEPNM2_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
deleted file mode 100644
index 1ed214c..0000000
--- a/drivers/net/sk98lin/h/skgepnmi.h
+++ /dev/null
@@ -1,962 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnmi.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.62 $
- * Date:	$Date: 2003/08/15 12:31:52 $
- * Purpose:	Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNMI_H_
-#define _SKGEPNMI_H_
-
-/*
- * Include dependencies
- */
-#include "h/sktypes.h"
-#include "h/skerror.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skaddr.h"
-#include "h/skrlmt.h"
-#include "h/skvpd.h"
-
-/*
- * Management Database Version
- */
-#define SK_PNMI_MDB_VERSION		0x00030001	/* 3.1 */
-
-
-/*
- * Event definitions
- */
-#define SK_PNMI_EVT_SIRQ_OVERFLOW		1	/* Counter overflow */
-#define SK_PNMI_EVT_SEN_WAR_LOW			2	/* Lower war thres exceeded */
-#define SK_PNMI_EVT_SEN_WAR_UPP			3	/* Upper war thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_LOW			4	/* Lower err thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_UPP			5	/* Upper err thres exceeded */
-#define SK_PNMI_EVT_CHG_EST_TIMER		6	/* Timer event for RLMT Chg */
-#define SK_PNMI_EVT_UTILIZATION_TIMER	7	/* Timer event for Utiliza. */
-#define SK_PNMI_EVT_CLEAR_COUNTER		8	/* Clear statistic counters */
-#define SK_PNMI_EVT_XMAC_RESET			9	/* XMAC will be reset */
-
-#define SK_PNMI_EVT_RLMT_PORT_UP		10	/* Port came logically up */
-#define SK_PNMI_EVT_RLMT_PORT_DOWN		11	/* Port went logically down */
-#define SK_PNMI_EVT_RLMT_SEGMENTATION	13	/* Two SP root bridges found */
-#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN	14	/* Port went logically down */
-#define SK_PNMI_EVT_RLMT_ACTIVE_UP		15	/* Port came logically up */
-#define SK_PNMI_EVT_RLMT_SET_NETS		16	/* 1. Parameter is number of nets
-												1 = single net; 2 = dual net */
-#define SK_PNMI_EVT_VCT_RESET		17	/* VCT port reset timer event started with SET. */
-
-
-/*
- * Return values
- */
-#define SK_PNMI_ERR_OK				0
-#define SK_PNMI_ERR_GENERAL			1
-#define SK_PNMI_ERR_TOO_SHORT		2
-#define SK_PNMI_ERR_BAD_VALUE		3
-#define SK_PNMI_ERR_READ_ONLY		4
-#define SK_PNMI_ERR_UNKNOWN_OID		5
-#define SK_PNMI_ERR_UNKNOWN_INST	6
-#define SK_PNMI_ERR_UNKNOWN_NET 	7
-#define SK_PNMI_ERR_NOT_SUPPORTED	10
-
-
-/*
- * Return values of driver reset function SK_DRIVER_RESET() and
- * driver event function SK_DRIVER_EVENT()
- */
-#define SK_PNMI_ERR_OK			0
-#define SK_PNMI_ERR_FAIL		1
-
-
-/*
- * Return values of driver test function SK_DRIVER_SELFTEST()
- */
-#define SK_PNMI_TST_UNKNOWN		(1 << 0)
-#define SK_PNMI_TST_TRANCEIVER		(1 << 1)
-#define SK_PNMI_TST_ASIC		(1 << 2)
-#define SK_PNMI_TST_SENSOR		(1 << 3)
-#define SK_PNMI_TST_POWERMGMT		(1 << 4)
-#define SK_PNMI_TST_PCI			(1 << 5)
-#define SK_PNMI_TST_MAC			(1 << 6)
-
-
-/*
- * RLMT specific definitions
- */
-#define SK_PNMI_RLMT_STATUS_STANDBY	1
-#define SK_PNMI_RLMT_STATUS_ACTIVE	2
-#define SK_PNMI_RLMT_STATUS_ERROR	3
-
-#define SK_PNMI_RLMT_LSTAT_PHY_DOWN	1
-#define SK_PNMI_RLMT_LSTAT_AUTONEG	2
-#define SK_PNMI_RLMT_LSTAT_LOG_DOWN	3
-#define SK_PNMI_RLMT_LSTAT_LOG_UP	4
-#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
-
-#define SK_PNMI_RLMT_MODE_CHK_LINK	(SK_RLMT_CHECK_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_RX	(SK_RLMT_CHECK_LOC_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_SPT	(SK_RLMT_CHECK_SEG)
-/* #define SK_PNMI_RLMT_MODE_CHK_EX */
-
-/*
- * OID definition
- */
-#ifndef _NDIS_	/* Check, whether NDIS already included OIDs */
-
-#define OID_GEN_XMIT_OK					0x00020101
-#define OID_GEN_RCV_OK					0x00020102
-#define OID_GEN_XMIT_ERROR				0x00020103
-#define OID_GEN_RCV_ERROR				0x00020104
-#define OID_GEN_RCV_NO_BUFFER			0x00020105
-
-/* #define OID_GEN_DIRECTED_BYTES_XMIT	0x00020201 */
-#define OID_GEN_DIRECTED_FRAMES_XMIT	0x00020202
-/* #define OID_GEN_MULTICAST_BYTES_XMIT	0x00020203 */
-#define OID_GEN_MULTICAST_FRAMES_XMIT	0x00020204
-/* #define OID_GEN_BROADCAST_BYTES_XMIT	0x00020205 */
-#define OID_GEN_BROADCAST_FRAMES_XMIT	0x00020206
-/* #define OID_GEN_DIRECTED_BYTES_RCV	0x00020207 */
-#define OID_GEN_DIRECTED_FRAMES_RCV		0x00020208
-/* #define OID_GEN_MULTICAST_BYTES_RCV	0x00020209 */
-#define OID_GEN_MULTICAST_FRAMES_RCV	0x0002020A
-/* #define OID_GEN_BROADCAST_BYTES_RCV	0x0002020B */
-#define OID_GEN_BROADCAST_FRAMES_RCV	0x0002020C
-#define OID_GEN_RCV_CRC_ERROR			0x0002020D
-#define OID_GEN_TRANSMIT_QUEUE_LENGTH	0x0002020E
-
-#define OID_802_3_PERMANENT_ADDRESS		0x01010101
-#define OID_802_3_CURRENT_ADDRESS		0x01010102
-/* #define OID_802_3_MULTICAST_LIST		0x01010103 */
-/* #define OID_802_3_MAXIMUM_LIST_SIZE	0x01010104 */
-/* #define OID_802_3_MAC_OPTIONS		0x01010105 */
-			
-#define OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
-#define OID_802_3_XMIT_ONE_COLLISION	0x01020102
-#define OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
-#define OID_802_3_XMIT_DEFERRED			0x01020201
-#define OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
-#define OID_802_3_RCV_OVERRUN			0x01020203
-#define OID_802_3_XMIT_UNDERRUN			0x01020204
-#define OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
-#define OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
-
-/*
- * PnP and PM OIDs
- */
-#ifdef SK_POWER_MGMT
-#define OID_PNP_CAPABILITIES			0xFD010100
-#define OID_PNP_SET_POWER				0xFD010101
-#define OID_PNP_QUERY_POWER				0xFD010102
-#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
-#define OID_PNP_REMOVE_WAKE_UP_PATTERN	0xFD010104
-#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
-#endif /* SK_POWER_MGMT */
-
-#endif /* _NDIS_ */
-
-#define OID_SKGE_MDB_VERSION			0xFF010100
-#define OID_SKGE_SUPPORTED_LIST			0xFF010101
-#define OID_SKGE_VPD_FREE_BYTES			0xFF010102
-#define OID_SKGE_VPD_ENTRIES_LIST		0xFF010103
-#define OID_SKGE_VPD_ENTRIES_NUMBER		0xFF010104
-#define OID_SKGE_VPD_KEY				0xFF010105
-#define OID_SKGE_VPD_VALUE				0xFF010106
-#define OID_SKGE_VPD_ACCESS				0xFF010107
-#define OID_SKGE_VPD_ACTION				0xFF010108
-			
-#define OID_SKGE_PORT_NUMBER			0xFF010110
-#define OID_SKGE_DEVICE_TYPE			0xFF010111
-#define OID_SKGE_DRIVER_DESCR			0xFF010112
-#define OID_SKGE_DRIVER_VERSION			0xFF010113
-#define OID_SKGE_HW_DESCR				0xFF010114
-#define OID_SKGE_HW_VERSION				0xFF010115
-#define OID_SKGE_CHIPSET				0xFF010116
-#define OID_SKGE_ACTION					0xFF010117
-#define OID_SKGE_RESULT					0xFF010118
-#define OID_SKGE_BUS_TYPE				0xFF010119
-#define OID_SKGE_BUS_SPEED				0xFF01011A
-#define OID_SKGE_BUS_WIDTH				0xFF01011B
-/* 0xFF01011C unused */
-#define OID_SKGE_DIAG_ACTION			0xFF01011D
-#define OID_SKGE_DIAG_RESULT			0xFF01011E
-#define OID_SKGE_MTU					0xFF01011F
-#define OID_SKGE_PHYS_CUR_ADDR			0xFF010120
-#define OID_SKGE_PHYS_FAC_ADDR			0xFF010121
-#define OID_SKGE_PMD					0xFF010122
-#define OID_SKGE_CONNECTOR				0xFF010123
-#define OID_SKGE_LINK_CAP				0xFF010124
-#define OID_SKGE_LINK_MODE				0xFF010125
-#define OID_SKGE_LINK_MODE_STATUS		0xFF010126
-#define OID_SKGE_LINK_STATUS			0xFF010127
-#define OID_SKGE_FLOWCTRL_CAP			0xFF010128
-#define OID_SKGE_FLOWCTRL_MODE			0xFF010129
-#define OID_SKGE_FLOWCTRL_STATUS		0xFF01012A
-#define OID_SKGE_PHY_OPERATION_CAP		0xFF01012B
-#define OID_SKGE_PHY_OPERATION_MODE		0xFF01012C
-#define OID_SKGE_PHY_OPERATION_STATUS	0xFF01012D
-#define OID_SKGE_MULTICAST_LIST			0xFF01012E
-#define OID_SKGE_CURRENT_PACKET_FILTER	0xFF01012F
-
-#define OID_SKGE_TRAP					0xFF010130
-#define OID_SKGE_TRAP_NUMBER			0xFF010131
-
-#define OID_SKGE_RLMT_MODE				0xFF010140
-#define OID_SKGE_RLMT_PORT_NUMBER		0xFF010141
-#define OID_SKGE_RLMT_PORT_ACTIVE		0xFF010142
-#define OID_SKGE_RLMT_PORT_PREFERRED	0xFF010143
-#define OID_SKGE_INTERMEDIATE_SUPPORT	0xFF010160
-
-#define OID_SKGE_SPEED_CAP				0xFF010170
-#define OID_SKGE_SPEED_MODE				0xFF010171
-#define OID_SKGE_SPEED_STATUS			0xFF010172
-
-#define OID_SKGE_BOARDLEVEL				0xFF010180
-
-#define OID_SKGE_SENSOR_NUMBER			0xFF020100			
-#define OID_SKGE_SENSOR_INDEX			0xFF020101
-#define OID_SKGE_SENSOR_DESCR			0xFF020102
-#define OID_SKGE_SENSOR_TYPE			0xFF020103
-#define OID_SKGE_SENSOR_VALUE			0xFF020104
-#define OID_SKGE_SENSOR_WAR_THRES_LOW	0xFF020105
-#define OID_SKGE_SENSOR_WAR_THRES_UPP	0xFF020106
-#define OID_SKGE_SENSOR_ERR_THRES_LOW	0xFF020107
-#define OID_SKGE_SENSOR_ERR_THRES_UPP	0xFF020108
-#define OID_SKGE_SENSOR_STATUS			0xFF020109
-#define OID_SKGE_SENSOR_WAR_CTS			0xFF02010A
-#define OID_SKGE_SENSOR_ERR_CTS			0xFF02010B
-#define OID_SKGE_SENSOR_WAR_TIME		0xFF02010C
-#define OID_SKGE_SENSOR_ERR_TIME		0xFF02010D
-
-#define OID_SKGE_CHKSM_NUMBER			0xFF020110
-#define OID_SKGE_CHKSM_RX_OK_CTS		0xFF020111
-#define OID_SKGE_CHKSM_RX_UNABLE_CTS	0xFF020112
-#define OID_SKGE_CHKSM_RX_ERR_CTS		0xFF020113
-#define OID_SKGE_CHKSM_TX_OK_CTS		0xFF020114
-#define OID_SKGE_CHKSM_TX_UNABLE_CTS	0xFF020115
-
-#define OID_SKGE_STAT_TX				0xFF020120
-#define OID_SKGE_STAT_TX_OCTETS			0xFF020121
-#define OID_SKGE_STAT_TX_BROADCAST		0xFF020122
-#define OID_SKGE_STAT_TX_MULTICAST		0xFF020123
-#define OID_SKGE_STAT_TX_UNICAST		0xFF020124
-#define OID_SKGE_STAT_TX_LONGFRAMES		0xFF020125
-#define OID_SKGE_STAT_TX_BURST			0xFF020126
-#define OID_SKGE_STAT_TX_PFLOWC			0xFF020127
-#define OID_SKGE_STAT_TX_FLOWC			0xFF020128
-#define OID_SKGE_STAT_TX_SINGLE_COL		0xFF020129
-#define OID_SKGE_STAT_TX_MULTI_COL		0xFF02012A
-#define OID_SKGE_STAT_TX_EXCESS_COL		0xFF02012B
-#define OID_SKGE_STAT_TX_LATE_COL		0xFF02012C
-#define OID_SKGE_STAT_TX_DEFFERAL		0xFF02012D
-#define OID_SKGE_STAT_TX_EXCESS_DEF		0xFF02012E
-#define OID_SKGE_STAT_TX_UNDERRUN		0xFF02012F
-#define OID_SKGE_STAT_TX_CARRIER		0xFF020130
-/* #define OID_SKGE_STAT_TX_UTIL		0xFF020131 */
-#define OID_SKGE_STAT_TX_64				0xFF020132
-#define OID_SKGE_STAT_TX_127			0xFF020133
-#define OID_SKGE_STAT_TX_255			0xFF020134
-#define OID_SKGE_STAT_TX_511			0xFF020135
-#define OID_SKGE_STAT_TX_1023			0xFF020136
-#define OID_SKGE_STAT_TX_MAX			0xFF020137
-#define OID_SKGE_STAT_TX_SYNC			0xFF020138
-#define OID_SKGE_STAT_TX_SYNC_OCTETS	0xFF020139
-#define OID_SKGE_STAT_RX				0xFF02013A
-#define OID_SKGE_STAT_RX_OCTETS			0xFF02013B
-#define OID_SKGE_STAT_RX_BROADCAST		0xFF02013C
-#define OID_SKGE_STAT_RX_MULTICAST		0xFF02013D
-#define OID_SKGE_STAT_RX_UNICAST		0xFF02013E
-#define OID_SKGE_STAT_RX_PFLOWC			0xFF02013F
-#define OID_SKGE_STAT_RX_FLOWC			0xFF020140
-#define OID_SKGE_STAT_RX_PFLOWC_ERR		0xFF020141
-#define OID_SKGE_STAT_RX_FLOWC_UNKWN	0xFF020142
-#define OID_SKGE_STAT_RX_BURST			0xFF020143
-#define OID_SKGE_STAT_RX_MISSED			0xFF020144
-#define OID_SKGE_STAT_RX_FRAMING		0xFF020145
-#define OID_SKGE_STAT_RX_OVERFLOW		0xFF020146
-#define OID_SKGE_STAT_RX_JABBER			0xFF020147
-#define OID_SKGE_STAT_RX_CARRIER		0xFF020148
-#define OID_SKGE_STAT_RX_IR_LENGTH		0xFF020149
-#define OID_SKGE_STAT_RX_SYMBOL			0xFF02014A
-#define OID_SKGE_STAT_RX_SHORTS			0xFF02014B
-#define OID_SKGE_STAT_RX_RUNT			0xFF02014C
-#define OID_SKGE_STAT_RX_CEXT			0xFF02014D
-#define OID_SKGE_STAT_RX_TOO_LONG		0xFF02014E
-#define OID_SKGE_STAT_RX_FCS			0xFF02014F
-/* #define OID_SKGE_STAT_RX_UTIL		0xFF020150 */
-#define OID_SKGE_STAT_RX_64				0xFF020151
-#define OID_SKGE_STAT_RX_127			0xFF020152
-#define OID_SKGE_STAT_RX_255			0xFF020153
-#define OID_SKGE_STAT_RX_511			0xFF020154
-#define OID_SKGE_STAT_RX_1023			0xFF020155
-#define OID_SKGE_STAT_RX_MAX			0xFF020156
-#define OID_SKGE_STAT_RX_LONGFRAMES		0xFF020157
-
-#define OID_SKGE_RLMT_CHANGE_CTS		0xFF020160
-#define OID_SKGE_RLMT_CHANGE_TIME		0xFF020161
-#define OID_SKGE_RLMT_CHANGE_ESTIM		0xFF020162
-#define OID_SKGE_RLMT_CHANGE_THRES		0xFF020163
-
-#define OID_SKGE_RLMT_PORT_INDEX		0xFF020164
-#define OID_SKGE_RLMT_STATUS			0xFF020165
-#define OID_SKGE_RLMT_TX_HELLO_CTS		0xFF020166
-#define OID_SKGE_RLMT_RX_HELLO_CTS		0xFF020167
-#define OID_SKGE_RLMT_TX_SP_REQ_CTS		0xFF020168
-#define OID_SKGE_RLMT_RX_SP_CTS			0xFF020169
-
-#define OID_SKGE_RLMT_MONITOR_NUMBER	0xFF010150
-#define OID_SKGE_RLMT_MONITOR_INDEX		0xFF010151
-#define OID_SKGE_RLMT_MONITOR_ADDR		0xFF010152
-#define OID_SKGE_RLMT_MONITOR_ERRS		0xFF010153
-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP	0xFF010154
-#define OID_SKGE_RLMT_MONITOR_ADMIN		0xFF010155
-
-#define OID_SKGE_TX_SW_QUEUE_LEN		0xFF020170
-#define OID_SKGE_TX_SW_QUEUE_MAX		0xFF020171
-#define OID_SKGE_TX_RETRY				0xFF020172
-#define OID_SKGE_RX_INTR_CTS			0xFF020173
-#define OID_SKGE_TX_INTR_CTS			0xFF020174
-#define OID_SKGE_RX_NO_BUF_CTS			0xFF020175
-#define OID_SKGE_TX_NO_BUF_CTS			0xFF020176
-#define OID_SKGE_TX_USED_DESCR_NO		0xFF020177
-#define OID_SKGE_RX_DELIVERED_CTS		0xFF020178
-#define OID_SKGE_RX_OCTETS_DELIV_CTS	0xFF020179
-#define OID_SKGE_RX_HW_ERROR_CTS		0xFF02017A
-#define OID_SKGE_TX_HW_ERROR_CTS		0xFF02017B
-#define OID_SKGE_IN_ERRORS_CTS			0xFF02017C
-#define OID_SKGE_OUT_ERROR_CTS			0xFF02017D
-#define OID_SKGE_ERR_RECOVERY_CTS		0xFF02017E
-#define OID_SKGE_SYSUPTIME				0xFF02017F
-
-#define OID_SKGE_ALL_DATA				0xFF020190
-
-/* Defines for VCT. */
-#define OID_SKGE_VCT_GET				0xFF020200
-#define OID_SKGE_VCT_SET				0xFF020201
-#define OID_SKGE_VCT_STATUS				0xFF020202
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define OID_SKGE_DIAG_MODE				0xFF020204
-#endif /* SK_DIAG_SUPPORT */
-
-/* New OIDs */
-#define OID_SKGE_DRIVER_RELDATE			0xFF020210
-#define OID_SKGE_DRIVER_FILENAME		0xFF020211
-#define OID_SKGE_CHIPID					0xFF020212
-#define OID_SKGE_RAMSIZE				0xFF020213
-#define OID_SKGE_VAUXAVAIL				0xFF020214
-#define OID_SKGE_PHY_TYPE				0xFF020215
-#define OID_SKGE_PHY_LP_MODE			0xFF020216
-
-/* VCT struct to store a backup copy of VCT data after a port reset. */
-typedef struct s_PnmiVct {
-	SK_U8			VctStatus;
-	SK_U8			PCableLen;
-	SK_U32			PMdiPairLen[4];
-	SK_U8			PMdiPairSts[4];
-} SK_PNMI_VCT;
-
-
-/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
-#define SK_PNMI_VCT_NONE		0
-#define SK_PNMI_VCT_OLD_VCT_DATA	1
-#define SK_PNMI_VCT_NEW_VCT_DATA	2
-#define SK_PNMI_VCT_OLD_DSP_DATA	4
-#define SK_PNMI_VCT_NEW_DSP_DATA	8
-#define SK_PNMI_VCT_RUNNING		16
-
-
-/* VCT cable test status. */
-#define SK_PNMI_VCT_NORMAL_CABLE		0
-#define SK_PNMI_VCT_SHORT_CABLE			1
-#define SK_PNMI_VCT_OPEN_CABLE			2
-#define SK_PNMI_VCT_TEST_FAIL			3
-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH		4
-
-#define	OID_SKGE_TRAP_SEN_WAR_LOW		500
-#define OID_SKGE_TRAP_SEN_WAR_UPP		501
-#define	OID_SKGE_TRAP_SEN_ERR_LOW		502
-#define OID_SKGE_TRAP_SEN_ERR_UPP		503
-#define OID_SKGE_TRAP_RLMT_CHANGE_THRES	520
-#define OID_SKGE_TRAP_RLMT_CHANGE_PORT	521
-#define OID_SKGE_TRAP_RLMT_PORT_DOWN	522
-#define OID_SKGE_TRAP_RLMT_PORT_UP		523
-#define OID_SKGE_TRAP_RLMT_SEGMENTATION	524
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define SK_DIAG_ATTACHED	2
-#define SK_DIAG_RUNNING		1
-#define SK_DIAG_IDLE		0
-#endif /* SK_DIAG_SUPPORT */
-
-/*
- * Generic PNMI IOCTL subcommand definitions.
- */
-#define	SK_GET_SINGLE_VAR		1
-#define	SK_SET_SINGLE_VAR		2
-#define	SK_PRESET_SINGLE_VAR	3
-#define	SK_GET_FULL_MIB			4
-#define	SK_SET_FULL_MIB			5
-#define	SK_PRESET_FULL_MIB		6
-
-
-/*
- * Define error numbers and messages for syslog
- */
-#define SK_PNMI_ERR001		(SK_ERRBASE_PNMI + 1)
-#define SK_PNMI_ERR001MSG	"SkPnmiGetStruct: Unknown OID"
-#define SK_PNMI_ERR002		(SK_ERRBASE_PNMI + 2)
-#define SK_PNMI_ERR002MSG	"SkPnmiGetStruct: Cannot read VPD keys"
-#define SK_PNMI_ERR003		(SK_ERRBASE_PNMI + 3)
-#define SK_PNMI_ERR003MSG	"OidStruct: Called with wrong OID"
-#define SK_PNMI_ERR004		(SK_ERRBASE_PNMI + 4)
-#define SK_PNMI_ERR004MSG	"OidStruct: Called with wrong action"
-#define SK_PNMI_ERR005		(SK_ERRBASE_PNMI + 5)
-#define SK_PNMI_ERR005MSG	"Perform: Cannot reset driver"
-#define SK_PNMI_ERR006		(SK_ERRBASE_PNMI + 6)
-#define SK_PNMI_ERR006MSG	"Perform: Unknown OID action command"
-#define SK_PNMI_ERR007		(SK_ERRBASE_PNMI + 7)
-#define SK_PNMI_ERR007MSG	"General: Driver description not initialized"
-#define SK_PNMI_ERR008		(SK_ERRBASE_PNMI + 8)
-#define SK_PNMI_ERR008MSG	"Addr: Tried to get unknown OID"
-#define SK_PNMI_ERR009		(SK_ERRBASE_PNMI + 9)
-#define SK_PNMI_ERR009MSG	"Addr: Unknown OID"
-#define SK_PNMI_ERR010		(SK_ERRBASE_PNMI + 10)
-#define SK_PNMI_ERR010MSG	"CsumStat: Unknown OID"
-#define SK_PNMI_ERR011		(SK_ERRBASE_PNMI + 11)
-#define SK_PNMI_ERR011MSG	"SensorStat: Sensor descr string too long"
-#define SK_PNMI_ERR012		(SK_ERRBASE_PNMI + 12)
-#define SK_PNMI_ERR012MSG	"SensorStat: Unknown OID"
-#define SK_PNMI_ERR013		(SK_ERRBASE_PNMI + 13)
-#define SK_PNMI_ERR013MSG	""
-#define SK_PNMI_ERR014		(SK_ERRBASE_PNMI + 14)
-#define SK_PNMI_ERR014MSG	"Vpd: Cannot read VPD keys"
-#define SK_PNMI_ERR015		(SK_ERRBASE_PNMI + 15)
-#define SK_PNMI_ERR015MSG	"Vpd: Internal array for VPD keys to small"
-#define SK_PNMI_ERR016		(SK_ERRBASE_PNMI + 16)
-#define SK_PNMI_ERR016MSG	"Vpd: Key string too long"
-#define SK_PNMI_ERR017		(SK_ERRBASE_PNMI + 17)
-#define SK_PNMI_ERR017MSG	"Vpd: Invalid VPD status pointer"
-#define SK_PNMI_ERR018		(SK_ERRBASE_PNMI + 18)
-#define SK_PNMI_ERR018MSG	"Vpd: VPD data not valid"
-#define SK_PNMI_ERR019		(SK_ERRBASE_PNMI + 19)
-#define SK_PNMI_ERR019MSG	"Vpd: VPD entries list string too long"
-#define SK_PNMI_ERR021		(SK_ERRBASE_PNMI + 21)
-#define SK_PNMI_ERR021MSG	"Vpd: VPD data string too long"
-#define SK_PNMI_ERR022		(SK_ERRBASE_PNMI + 22)
-#define SK_PNMI_ERR022MSG	"Vpd: VPD data string too long should be errored before"
-#define SK_PNMI_ERR023		(SK_ERRBASE_PNMI + 23)
-#define SK_PNMI_ERR023MSG	"Vpd: Unknown OID in get action"
-#define SK_PNMI_ERR024		(SK_ERRBASE_PNMI + 24)
-#define SK_PNMI_ERR024MSG	"Vpd: Unknown OID in preset/set action"
-#define SK_PNMI_ERR025		(SK_ERRBASE_PNMI + 25)
-#define SK_PNMI_ERR025MSG	"Vpd: Cannot write VPD after modify entry"
-#define SK_PNMI_ERR026		(SK_ERRBASE_PNMI + 26)
-#define SK_PNMI_ERR026MSG	"Vpd: Cannot update VPD"
-#define SK_PNMI_ERR027		(SK_ERRBASE_PNMI + 27)
-#define SK_PNMI_ERR027MSG	"Vpd: Cannot delete VPD entry"
-#define SK_PNMI_ERR028		(SK_ERRBASE_PNMI + 28)
-#define SK_PNMI_ERR028MSG	"Vpd: Cannot update VPD after delete entry"
-#define SK_PNMI_ERR029		(SK_ERRBASE_PNMI + 29)
-#define SK_PNMI_ERR029MSG	"General: Driver description string too long"
-#define SK_PNMI_ERR030		(SK_ERRBASE_PNMI + 30)
-#define SK_PNMI_ERR030MSG	"General: Driver version not initialized"
-#define SK_PNMI_ERR031		(SK_ERRBASE_PNMI + 31)
-#define SK_PNMI_ERR031MSG	"General: Driver version string too long"
-#define SK_PNMI_ERR032		(SK_ERRBASE_PNMI + 32)
-#define SK_PNMI_ERR032MSG	"General: Cannot read VPD Name for HW descr"
-#define SK_PNMI_ERR033		(SK_ERRBASE_PNMI + 33)
-#define SK_PNMI_ERR033MSG	"General: HW description string too long"
-#define SK_PNMI_ERR034		(SK_ERRBASE_PNMI + 34)
-#define SK_PNMI_ERR034MSG	"General: Unknown OID"
-#define SK_PNMI_ERR035		(SK_ERRBASE_PNMI + 35)
-#define SK_PNMI_ERR035MSG	"Rlmt: Unknown OID"
-#define SK_PNMI_ERR036		(SK_ERRBASE_PNMI + 36)
-#define SK_PNMI_ERR036MSG	""
-#define SK_PNMI_ERR037		(SK_ERRBASE_PNMI + 37)
-#define SK_PNMI_ERR037MSG	"Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
-#define SK_PNMI_ERR038		(SK_ERRBASE_PNMI + 38)
-#define SK_PNMI_ERR038MSG	"Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
-#define SK_PNMI_ERR039		(SK_ERRBASE_PNMI + 39)
-#define SK_PNMI_ERR039MSG	"RlmtStat: Unknown OID"
-#define SK_PNMI_ERR040		(SK_ERRBASE_PNMI + 40)
-#define SK_PNMI_ERR040MSG	"PowerManagement: Unknown OID"
-#define SK_PNMI_ERR041		(SK_ERRBASE_PNMI + 41)
-#define SK_PNMI_ERR041MSG	"MacPrivateConf: Unknown OID"
-#define SK_PNMI_ERR042		(SK_ERRBASE_PNMI + 42)
-#define SK_PNMI_ERR042MSG	"MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
-#define SK_PNMI_ERR043		(SK_ERRBASE_PNMI + 43)
-#define SK_PNMI_ERR043MSG	"MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
-#define SK_PNMI_ERR044		(SK_ERRBASE_PNMI + 44)
-#define SK_PNMI_ERR044MSG	"MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
-#define SK_PNMI_ERR045		(SK_ERRBASE_PNMI + 45)
-#define SK_PNMI_ERR045MSG	"MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
-#define SK_PNMI_ERR046		(SK_ERRBASE_PNMI + 46)
-#define SK_PNMI_ERR046MSG	"Monitor: Unknown OID"
-#define SK_PNMI_ERR047		(SK_ERRBASE_PNMI + 47)
-#define SK_PNMI_ERR047MSG	"SirqUpdate: Event function returns not 0"
-#define SK_PNMI_ERR048		(SK_ERRBASE_PNMI + 48)
-#define SK_PNMI_ERR048MSG	"RlmtUpdate: Event function returns not 0"
-#define SK_PNMI_ERR049		(SK_ERRBASE_PNMI + 49)
-#define SK_PNMI_ERR049MSG	"SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
-#define SK_PNMI_ERR050		(SK_ERRBASE_PNMI + 50)
-#define SK_PNMI_ERR050MSG	"SkPnmiInit: Invalid size of 'StatAddr' table!!"
-#define SK_PNMI_ERR051		(SK_ERRBASE_PNMI + 51)
-#define SK_PNMI_ERR051MSG	"SkPnmiEvent: Port switch suspicious"
-#define SK_PNMI_ERR052		(SK_ERRBASE_PNMI + 52)
-#define SK_PNMI_ERR052MSG	""
-#define SK_PNMI_ERR053		(SK_ERRBASE_PNMI + 53)
-#define SK_PNMI_ERR053MSG	"General: Driver release date not initialized"
-#define SK_PNMI_ERR054		(SK_ERRBASE_PNMI + 54)
-#define SK_PNMI_ERR054MSG	"General: Driver release date string too long"
-#define SK_PNMI_ERR055		(SK_ERRBASE_PNMI + 55)
-#define SK_PNMI_ERR055MSG	"General: Driver file name not initialized"
-#define SK_PNMI_ERR056		(SK_ERRBASE_PNMI + 56)
-#define SK_PNMI_ERR056MSG	"General: Driver file name string too long"
-
-/*
- * Management counter macros called by the driver
- */
-#define SK_PNMI_SET_DRIVER_DESCR(pAC,v)	((pAC)->Pnmi.pDriverDescription = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_VER(pAC,v)	((pAC)->Pnmi.pDriverVersion = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v)	((pAC)->Pnmi.pDriverReleaseDate = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v)	((pAC)->Pnmi.pDriverFileName = \
-	(char *)(v))
-
-#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
-	{ \
-		(pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
-		if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
-			(pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
-		} \
-	}
-#define SK_PNMI_CNT_TX_RETRY(pAC,p)	(((pAC)->Pnmi.Port[p].TxRetryCts)++)
-#define SK_PNMI_CNT_RX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].RxIntrCts)++)
-#define SK_PNMI_CNT_TX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].TxIntrCts)++)
-#define SK_PNMI_CNT_NO_RX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].RxNoBufCts)++)
-#define SK_PNMI_CNT_NO_TX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].TxNoBufCts)++)
-#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
-	((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
-#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
-	{ \
-		((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
-		(pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
-	}
-#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p)	(((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
-
-#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatSyncCts)++; \
-			(pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
-		} \
-	}
-
-/*
- * Conversion Macros
- */
-#define SK_PNMI_PORT_INST2LOG(i)	((unsigned int)(i) - 1)
-#define SK_PNMI_PORT_LOG2INST(l)	((unsigned int)(l) + 1)
-#define SK_PNMI_PORT_PHYS2LOG(p)	((unsigned int)(p) + 1)
-#define SK_PNMI_PORT_LOG2PHYS(pAC,l)	((unsigned int)(l) - 1)
-#define SK_PNMI_PORT_PHYS2INST(pAC,p)	\
-	(pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
-#define SK_PNMI_PORT_INST2PHYS(pAC,i)	((unsigned int)(i) - 2)
-
-/*
- * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
- */
-#define SK_PNMI_VPD_KEY_SIZE	5
-#define SK_PNMI_VPD_BUFSIZE		(VPD_SIZE)
-#define SK_PNMI_VPD_ENTRIES		(VPD_SIZE / 4)
-#define SK_PNMI_VPD_DATALEN		128 /*  Number of data bytes */
-
-#define SK_PNMI_MULTICAST_LISTLEN	64
-#define SK_PNMI_SENSOR_ENTRIES		(SK_MAX_SENSORS)
-#define SK_PNMI_CHECKSUM_ENTRIES	3
-#define SK_PNMI_MAC_ENTRIES			(SK_MAX_MACS + 1)
-#define SK_PNMI_MONITOR_ENTRIES		20
-#define SK_PNMI_TRAP_ENTRIES		10
-#define SK_PNMI_TRAPLEN				128
-#define SK_PNMI_STRINGLEN1			80
-#define SK_PNMI_STRINGLEN2			25
-#define SK_PNMI_TRAP_QUEUE_LEN		512
-
-typedef struct s_PnmiVpd {
-	char			VpdKey[SK_PNMI_VPD_KEY_SIZE];
-	char			VpdValue[SK_PNMI_VPD_DATALEN];
-	SK_U8			VpdAccess;
-	SK_U8			VpdAction;
-} SK_PNMI_VPD;
-
-typedef struct s_PnmiSensor {
-	SK_U8			SensorIndex;
-	char			SensorDescr[SK_PNMI_STRINGLEN2];
-	SK_U8			SensorType;
-	SK_U32			SensorValue;
-	SK_U32			SensorWarningThresholdLow;
-	SK_U32			SensorWarningThresholdHigh;
-	SK_U32			SensorErrorThresholdLow;
-	SK_U32			SensorErrorThresholdHigh;
-	SK_U8			SensorStatus;
-	SK_U64			SensorWarningCts;
-	SK_U64			SensorErrorCts;
-	SK_U64			SensorWarningTimestamp;
-	SK_U64			SensorErrorTimestamp;
-} SK_PNMI_SENSOR;
-
-typedef struct s_PnmiChecksum {
-	SK_U64			ChecksumRxOkCts;
-	SK_U64			ChecksumRxUnableCts;
-	SK_U64			ChecksumRxErrCts;
-	SK_U64			ChecksumTxOkCts;
-	SK_U64			ChecksumTxUnableCts;
-} SK_PNMI_CHECKSUM;
-
-typedef struct s_PnmiStat {
-	SK_U64			StatTxOkCts;
-	SK_U64			StatTxOctetsOkCts;
-	SK_U64			StatTxBroadcastOkCts;
-	SK_U64			StatTxMulticastOkCts;
-	SK_U64			StatTxUnicastOkCts;
-	SK_U64			StatTxLongFramesCts;
-	SK_U64			StatTxBurstCts;
-	SK_U64			StatTxPauseMacCtrlCts;
-	SK_U64			StatTxMacCtrlCts;
-	SK_U64			StatTxSingleCollisionCts;
-	SK_U64			StatTxMultipleCollisionCts;
-	SK_U64			StatTxExcessiveCollisionCts;
-	SK_U64			StatTxLateCollisionCts;
-	SK_U64			StatTxDeferralCts;
-	SK_U64			StatTxExcessiveDeferralCts;
-	SK_U64			StatTxFifoUnderrunCts;
-	SK_U64			StatTxCarrierCts;
-	SK_U64			Dummy1; /* StatTxUtilization */
-	SK_U64			StatTx64Cts;
-	SK_U64			StatTx127Cts;
-	SK_U64			StatTx255Cts;
-	SK_U64			StatTx511Cts;
-	SK_U64			StatTx1023Cts;
-	SK_U64			StatTxMaxCts;
-	SK_U64			StatTxSyncCts;
-	SK_U64			StatTxSyncOctetsCts;
-	SK_U64			StatRxOkCts;
-	SK_U64			StatRxOctetsOkCts;
-	SK_U64			StatRxBroadcastOkCts;
-	SK_U64			StatRxMulticastOkCts;
-	SK_U64			StatRxUnicastOkCts;
-	SK_U64			StatRxLongFramesCts;
-	SK_U64			StatRxPauseMacCtrlCts;
-	SK_U64			StatRxMacCtrlCts;
-	SK_U64			StatRxPauseMacCtrlErrorCts;
-	SK_U64			StatRxMacCtrlUnknownCts;
-	SK_U64			StatRxBurstCts;
-	SK_U64			StatRxMissedCts;
-	SK_U64			StatRxFramingCts;
-	SK_U64			StatRxFifoOverflowCts;
-	SK_U64			StatRxJabberCts;
-	SK_U64			StatRxCarrierCts;
-	SK_U64			StatRxIRLengthCts;
-	SK_U64			StatRxSymbolCts;
-	SK_U64			StatRxShortsCts;
-	SK_U64			StatRxRuntCts;
-	SK_U64			StatRxCextCts;
-	SK_U64			StatRxTooLongCts;
-	SK_U64			StatRxFcsCts;
-	SK_U64			Dummy2; /* StatRxUtilization */
-	SK_U64			StatRx64Cts;
-	SK_U64			StatRx127Cts;
-	SK_U64			StatRx255Cts;
-	SK_U64			StatRx511Cts;
-	SK_U64			StatRx1023Cts;
-	SK_U64			StatRxMaxCts;
-} SK_PNMI_STAT;
-
-typedef struct s_PnmiConf {
-	char			ConfMacCurrentAddr[6];
-	char			ConfMacFactoryAddr[6];
-	SK_U8			ConfPMD;
-	SK_U8			ConfConnector;
-	SK_U32			ConfPhyType;
-	SK_U32			ConfPhyMode;
-	SK_U8			ConfLinkCapability;
-	SK_U8			ConfLinkMode;
-	SK_U8			ConfLinkModeStatus;
-	SK_U8			ConfLinkStatus;
-	SK_U8			ConfFlowCtrlCapability;
-	SK_U8			ConfFlowCtrlMode;
-	SK_U8			ConfFlowCtrlStatus;
-	SK_U8			ConfPhyOperationCapability;
-	SK_U8			ConfPhyOperationMode;
-	SK_U8			ConfPhyOperationStatus;
-	SK_U8			ConfSpeedCapability;
-	SK_U8			ConfSpeedMode;
-	SK_U8			ConfSpeedStatus;
-} SK_PNMI_CONF;
-
-typedef struct s_PnmiRlmt {
-	SK_U32			RlmtIndex;
-	SK_U32			RlmtStatus;
-	SK_U64			RlmtTxHelloCts;
-	SK_U64			RlmtRxHelloCts;
-	SK_U64			RlmtTxSpHelloReqCts;
-	SK_U64			RlmtRxSpHelloCts;
-} SK_PNMI_RLMT;
-
-typedef struct s_PnmiRlmtMonitor {
-	SK_U32			RlmtMonitorIndex;
-	char			RlmtMonitorAddr[6];
-	SK_U64			RlmtMonitorErrorCts;
-	SK_U64			RlmtMonitorTimestamp;
-	SK_U8			RlmtMonitorAdmin;
-} SK_PNMI_RLMT_MONITOR;
-
-typedef struct s_PnmiRequestStatus {
-	SK_U32			ErrorStatus;
-	SK_U32			ErrorOffset;
-} SK_PNMI_REQUEST_STATUS;
-
-typedef struct s_PnmiStrucData {
-	SK_U32			MgmtDBVersion;
-	SK_PNMI_REQUEST_STATUS	ReturnStatus;
-	SK_U32			VpdFreeBytes;
-	char			VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
-	SK_U32			VpdEntriesNumber;
-	SK_PNMI_VPD		Vpd[SK_PNMI_VPD_ENTRIES];
-	SK_U32			PortNumber;
-	SK_U32			DeviceType;
-	char			DriverDescr[SK_PNMI_STRINGLEN1];
-	char			DriverVersion[SK_PNMI_STRINGLEN2];
-	char			DriverReleaseDate[SK_PNMI_STRINGLEN1];
-	char			DriverFileName[SK_PNMI_STRINGLEN1];
-	char			HwDescr[SK_PNMI_STRINGLEN1];
-	char			HwVersion[SK_PNMI_STRINGLEN2];
-	SK_U16			Chipset;
-	SK_U32			ChipId;
-	SK_U8			VauxAvail;
-	SK_U32			RamSize;
-	SK_U32			MtuSize;
-	SK_U32			Action;
-	SK_U32			TestResult;
-	SK_U8			BusType;
-	SK_U8			BusSpeed;
-	SK_U8			BusWidth;
-	SK_U8			SensorNumber;
-	SK_PNMI_SENSOR	Sensor[SK_PNMI_SENSOR_ENTRIES];
-	SK_U8			ChecksumNumber;
-	SK_PNMI_CHECKSUM	Checksum[SK_PNMI_CHECKSUM_ENTRIES];
-	SK_PNMI_STAT	Stat[SK_PNMI_MAC_ENTRIES];
-	SK_PNMI_CONF	Conf[SK_PNMI_MAC_ENTRIES];
-	SK_U8			RlmtMode;
-	SK_U32			RlmtPortNumber;
-	SK_U8			RlmtPortActive;
-	SK_U8			RlmtPortPreferred;
-	SK_U64			RlmtChangeCts;
-	SK_U64			RlmtChangeTime;
-	SK_U64			RlmtChangeEstimate;
-	SK_U64			RlmtChangeThreshold;
-	SK_PNMI_RLMT	Rlmt[SK_MAX_MACS];
-	SK_U32			RlmtMonitorNumber;
-	SK_PNMI_RLMT_MONITOR	RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
-	SK_U32			TrapNumber;
-	SK_U8			Trap[SK_PNMI_TRAP_QUEUE_LEN];
-	SK_U64			TxSwQueueLen;
-	SK_U64			TxSwQueueMax;
-	SK_U64			TxRetryCts;
-	SK_U64			RxIntrCts;
-	SK_U64			TxIntrCts;
-	SK_U64			RxNoBufCts;
-	SK_U64			TxNoBufCts;
-	SK_U64			TxUsedDescrNo;
-	SK_U64			RxDeliveredCts;
-	SK_U64			RxOctetsDeliveredCts;
-	SK_U64			RxHwErrorsCts;
-	SK_U64			TxHwErrorsCts;
-	SK_U64			InErrorsCts;
-	SK_U64			OutErrorsCts;
-	SK_U64			ErrRecoveryCts;
-	SK_U64			SysUpTime;
-} SK_PNMI_STRUCT_DATA;
-
-#define SK_PNMI_STRUCT_SIZE	(sizeof(SK_PNMI_STRUCT_DATA))
-#define SK_PNMI_MIN_STRUCT_SIZE	((unsigned int)(SK_UPTR)\
-				 &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
-														/*
-														 * ReturnStatus field
-														 * must be located
-														 * before VpdFreeBytes
-														 */
-
-/*
- * Various definitions
- */
-#define SK_PNMI_MAX_PROTOS		3
-
-#define SK_PNMI_CNT_NO			66	/* Must have the value of the enum
-									 * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
-									 * for check while init phase 1
-									 */
-
-/*
- * Estimate data structure
- */
-typedef struct s_PnmiEstimate {
-	unsigned int	EstValueIndex;
-	SK_U64			EstValue[7];
-	SK_U64			Estimate;
-	SK_TIMER		EstTimer;
-} SK_PNMI_ESTIMATE;
-
-
-/*
- * VCT timer data structure
- */
-typedef struct s_VctTimer {
-	SK_TIMER		VctTimer;
-} SK_PNMI_VCT_TIMER;
-
-
-/*
- * PNMI specific adapter context structure
- */
-typedef struct s_PnmiPort {
-	SK_U64			StatSyncCts;
-	SK_U64			StatSyncOctetsCts;
-	SK_U64			StatRxLongFrameCts;
-	SK_U64			StatRxFrameTooLongCts;
-	SK_U64			StatRxPMaccErr;
-	SK_U64			TxSwQueueLen;
-	SK_U64			TxSwQueueMax;
-	SK_U64			TxRetryCts;
-	SK_U64			RxIntrCts;
-	SK_U64			TxIntrCts;
-	SK_U64			RxNoBufCts;
-	SK_U64			TxNoBufCts;
-	SK_U64			TxUsedDescrNo;
-	SK_U64			RxDeliveredCts;
-	SK_U64			RxOctetsDeliveredCts;
-	SK_U64			RxHwErrorsCts;
-	SK_U64			TxHwErrorsCts;
-	SK_U64			InErrorsCts;
-	SK_U64			OutErrorsCts;
-	SK_U64			ErrRecoveryCts;
-	SK_U64			RxShortZeroMark;
-	SK_U64			CounterOffset[SK_PNMI_CNT_NO];
-	SK_U32			CounterHigh[SK_PNMI_CNT_NO];
-	SK_BOOL			ActiveFlag;
-	SK_U8			Align[3];
-} SK_PNMI_PORT;
-
-
-typedef struct s_PnmiData {
-	SK_PNMI_PORT	Port	[SK_MAX_MACS];
-	SK_PNMI_PORT	BufPort	[SK_MAX_MACS]; /* 2002-09-13 pweber  */
-	SK_U64			VirtualCounterOffset[SK_PNMI_CNT_NO];
-	SK_U32			TestResult;
-	char			HwVersion[10];
-	SK_U16			Align01;
-
-	char			*pDriverDescription;
-	char			*pDriverVersion;
-	char			*pDriverReleaseDate;
-	char			*pDriverFileName;
-
-	int				MacUpdatedFlag;
-	int				RlmtUpdatedFlag;
-	int				SirqUpdatedFlag;
-
-	SK_U64			RlmtChangeCts;
-	SK_U64			RlmtChangeTime;
-	SK_PNMI_ESTIMATE	RlmtChangeEstimate;
-	SK_U64			RlmtChangeThreshold;
-
-	SK_U64			StartUpTime;
-	SK_U32			DeviceType;
-	char			PciBusSpeed;
-	char			PciBusWidth;
-	char			Chipset;
-	char			PMD;
-	char			Connector;
-	SK_BOOL			DualNetActiveFlag;
-	SK_U16			Align02;
-
-	char			TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
-	unsigned int	TrapBufFree;
-	unsigned int	TrapQueueBeg;
-	unsigned int	TrapQueueEnd;
-	unsigned int	TrapBufPad;
-	unsigned int	TrapUnique;
-	SK_U8		VctStatus[SK_MAX_MACS];
-	SK_PNMI_VCT	VctBackup[SK_MAX_MACS];
-	SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
-#ifdef SK_DIAG_SUPPORT
-	SK_U32			DiagAttached;
-#endif /* SK_DIAG_SUPPORT */
-} SK_PNMI;
-
-
-/*
- * Function prototypes
- */
-extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
-extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
-	SK_EVPARA Param);
-extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
-	unsigned int * pLen, SK_U32 NetIndex);
-
-#endif
diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
deleted file mode 100644
index 3eec627..0000000
--- a/drivers/net/sk98lin/h/skgesirq.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgesirq.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.30 $
- * Date:	$Date: 2003/07/04 12:34:13 $
- * Purpose:	SK specific Gigabit Ethernet special IRQ functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKGESIRQ_H_
-#define _INC_SKGESIRQ_H_
-
-/* Define return codes of SkGePortCheckUp and CheckShort */
-#define	SK_HW_PS_NONE		0	/* No action needed */
-#define	SK_HW_PS_RESTART	1	/* Restart needed */
-#define	SK_HW_PS_LINK		2	/* Link Up actions needed */
-
-/*
- * Define the Event the special IRQ/INI module can handle
- */
-#define SK_HWEV_WATIM			1	/* Timeout for WA Errata #2 XMAC */
-#define SK_HWEV_PORT_START		2	/* Port Start Event by RLMT */
-#define SK_HWEV_PORT_STOP		3	/* Port Stop Event by RLMT */
-#define SK_HWEV_CLEAR_STAT		4	/* Clear Statistics by PNMI */
-#define SK_HWEV_UPDATE_STAT		5	/* Update Statistics by PNMI */
-#define SK_HWEV_SET_LMODE		6	/* Set Link Mode by PNMI */
-#define SK_HWEV_SET_FLOWMODE	7	/* Set Flow Control Mode by PNMI */
-#define SK_HWEV_SET_ROLE		8	/* Set Master/Slave (Role) by PNMI */
-#define SK_HWEV_SET_SPEED		9	/* Set Link Speed by PNMI */
-#define SK_HWEV_HALFDUP_CHK		10	/* Half Duplex Hangup Workaround */
-
-#define SK_WA_ACT_TIME		(5000000UL)	/* 5 sec */
-#define SK_WA_INA_TIME		(100000UL)	/* 100 msec */
-
-#define SK_HALFDUP_CHK_TIME	(10000UL)	/* 10 msec */
-
-/*
- * Define the error numbers and messages
- */
-#define SKERR_SIRQ_E001		(SK_ERRBASE_SIRQ+0)
-#define SKERR_SIRQ_E001MSG	"Unknown event"
-#define SKERR_SIRQ_E002		(SKERR_SIRQ_E001+1)
-#define SKERR_SIRQ_E002MSG	"Packet timeout RX1"
-#define SKERR_SIRQ_E003		(SKERR_SIRQ_E002+1)
-#define SKERR_SIRQ_E003MSG	"Packet timeout RX2"
-#define SKERR_SIRQ_E004		(SKERR_SIRQ_E003+1)
-#define SKERR_SIRQ_E004MSG	"MAC 1 not correctly initialized"
-#define SKERR_SIRQ_E005		(SKERR_SIRQ_E004+1)
-#define SKERR_SIRQ_E005MSG	"MAC 2 not correctly initialized"
-#define SKERR_SIRQ_E006		(SKERR_SIRQ_E005+1)
-#define SKERR_SIRQ_E006MSG	"CHECK failure R1"
-#define SKERR_SIRQ_E007		(SKERR_SIRQ_E006+1)
-#define SKERR_SIRQ_E007MSG	"CHECK failure R2"
-#define SKERR_SIRQ_E008		(SKERR_SIRQ_E007+1)
-#define SKERR_SIRQ_E008MSG	"CHECK failure XS1"
-#define SKERR_SIRQ_E009		(SKERR_SIRQ_E008+1)
-#define SKERR_SIRQ_E009MSG	"CHECK failure XA1"
-#define SKERR_SIRQ_E010		(SKERR_SIRQ_E009+1)
-#define SKERR_SIRQ_E010MSG	"CHECK failure XS2"
-#define SKERR_SIRQ_E011		(SKERR_SIRQ_E010+1)
-#define SKERR_SIRQ_E011MSG	"CHECK failure XA2"
-#define SKERR_SIRQ_E012		(SKERR_SIRQ_E011+1)
-#define SKERR_SIRQ_E012MSG	"unexpected IRQ Master error"
-#define SKERR_SIRQ_E013		(SKERR_SIRQ_E012+1)
-#define SKERR_SIRQ_E013MSG	"unexpected IRQ Status error"
-#define SKERR_SIRQ_E014		(SKERR_SIRQ_E013+1)
-#define SKERR_SIRQ_E014MSG	"Parity error on RAM (read)"
-#define SKERR_SIRQ_E015		(SKERR_SIRQ_E014+1)
-#define SKERR_SIRQ_E015MSG	"Parity error on RAM (write)"
-#define SKERR_SIRQ_E016		(SKERR_SIRQ_E015+1)
-#define SKERR_SIRQ_E016MSG	"Parity error MAC 1"
-#define SKERR_SIRQ_E017		(SKERR_SIRQ_E016+1)
-#define SKERR_SIRQ_E017MSG	"Parity error MAC 2"
-#define SKERR_SIRQ_E018		(SKERR_SIRQ_E017+1)
-#define SKERR_SIRQ_E018MSG	"Parity error RX 1"
-#define SKERR_SIRQ_E019		(SKERR_SIRQ_E018+1)
-#define SKERR_SIRQ_E019MSG	"Parity error RX 2"
-#define SKERR_SIRQ_E020		(SKERR_SIRQ_E019+1)
-#define SKERR_SIRQ_E020MSG	"MAC transmit FIFO underrun"
-#define SKERR_SIRQ_E021		(SKERR_SIRQ_E020+1)
-#define SKERR_SIRQ_E021MSG	"Spurious TWSI interrupt"
-#define SKERR_SIRQ_E022		(SKERR_SIRQ_E021+1)
-#define SKERR_SIRQ_E022MSG	"Cable pair swap error"
-#define SKERR_SIRQ_E023		(SKERR_SIRQ_E022+1)
-#define SKERR_SIRQ_E023MSG	"Auto-negotiation error"
-#define SKERR_SIRQ_E024		(SKERR_SIRQ_E023+1)
-#define SKERR_SIRQ_E024MSG	"FIFO overflow error"
-#define SKERR_SIRQ_E025		(SKERR_SIRQ_E024+1)
-#define SKERR_SIRQ_E025MSG	"2 Pair Downshift detected"
-
-extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
-extern int  SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
-
-#endif	/* _INC_SKGESIRQ_H_ */
diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
deleted file mode 100644
index 6a63f4a..0000000
--- a/drivers/net/sk98lin/h/ski2c.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/******************************************************************************
- *
- * Name:	ski2c.h
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.35 $
- * Date:	$Date: 2003/10/20 09:06:30 $
- * Purpose:	Defines to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKI2C.H	contains all I2C specific defines
- */
-
-#ifndef _SKI2C_H_
-#define _SKI2C_H_
-
-typedef struct  s_Sensor SK_SENSOR;
-
-#include "h/skgei2c.h"
-
-/*
- * Define the I2C events.
- */
-#define SK_I2CEV_IRQ	1	/* IRQ happened Event */
-#define SK_I2CEV_TIM	2	/* Timeout event */
-#define SK_I2CEV_CLEAR	3	/* Clear MIB Values */
-
-/*
- * Define READ and WRITE Constants.
- */
-#define I2C_READ	0
-#define I2C_WRITE	1
-#define I2C_BURST	1
-#define I2C_SINGLE	0
-
-#define SKERR_I2C_E001		(SK_ERRBASE_I2C+0)
-#define SKERR_I2C_E001MSG	"Sensor index unknown"
-#define SKERR_I2C_E002		(SKERR_I2C_E001+1)
-#define SKERR_I2C_E002MSG	"TWSI: transfer does not complete"
-#define SKERR_I2C_E003		(SKERR_I2C_E002+1)
-#define SKERR_I2C_E003MSG	"LM80: NAK on device send"
-#define SKERR_I2C_E004		(SKERR_I2C_E003+1)
-#define SKERR_I2C_E004MSG	"LM80: NAK on register send"
-#define SKERR_I2C_E005		(SKERR_I2C_E004+1)
-#define SKERR_I2C_E005MSG	"LM80: NAK on device (2) send"
-#define SKERR_I2C_E006		(SKERR_I2C_E005+1)
-#define SKERR_I2C_E006MSG	"Unknown event"
-#define SKERR_I2C_E007		(SKERR_I2C_E006+1)
-#define SKERR_I2C_E007MSG	"LM80 read out of state"
-#define SKERR_I2C_E008		(SKERR_I2C_E007+1)
-#define SKERR_I2C_E008MSG	"Unexpected sensor read completed"
-#define SKERR_I2C_E009		(SKERR_I2C_E008+1)
-#define SKERR_I2C_E009MSG	"WARNING: temperature sensor out of range"
-#define SKERR_I2C_E010		(SKERR_I2C_E009+1)
-#define SKERR_I2C_E010MSG	"WARNING: voltage sensor out of range"
-#define SKERR_I2C_E011		(SKERR_I2C_E010+1)
-#define SKERR_I2C_E011MSG	"ERROR: temperature sensor out of range"
-#define SKERR_I2C_E012		(SKERR_I2C_E011+1)
-#define SKERR_I2C_E012MSG	"ERROR: voltage sensor out of range"
-#define SKERR_I2C_E013		(SKERR_I2C_E012+1)
-#define SKERR_I2C_E013MSG	"ERROR: couldn't init sensor"
-#define SKERR_I2C_E014		(SKERR_I2C_E013+1)
-#define SKERR_I2C_E014MSG	"WARNING: fan sensor out of range"
-#define SKERR_I2C_E015		(SKERR_I2C_E014+1)
-#define SKERR_I2C_E015MSG	"ERROR: fan sensor out of range"
-#define SKERR_I2C_E016		(SKERR_I2C_E015+1)
-#define SKERR_I2C_E016MSG	"TWSI: active transfer does not complete"
-
-/*
- * Define Timeout values
- */
-#define SK_I2C_TIM_LONG		2000000L	/* 2 seconds */
-#define SK_I2C_TIM_SHORT	 100000L	/* 100 milliseconds */
-#define SK_I2C_TIM_WATCH	1000000L	/* 1 second */
-
-/*
- * Define trap and error log hold times
- */
-#ifndef	SK_SEN_ERR_TR_HOLD
-#define SK_SEN_ERR_TR_HOLD		(4*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_ERR_LOG_HOLD
-#define SK_SEN_ERR_LOG_HOLD		(60*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_WARN_TR_HOLD
-#define SK_SEN_WARN_TR_HOLD		(15*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_WARN_LOG_HOLD
-#define SK_SEN_WARN_LOG_HOLD	(15*60*SK_TICKS_PER_SEC)
-#endif
-
-/*
- * Defines for SenType
- */
-#define SK_SEN_UNKNOWN	0
-#define SK_SEN_TEMP		1
-#define SK_SEN_VOLT		2
-#define SK_SEN_FAN		3
-
-/*
- * Define for the SenErrorFlag
- */
-#define SK_SEN_ERR_NOT_PRESENT	0	/* Error Flag: Sensor not present */
-#define SK_SEN_ERR_OK			1	/* Error Flag: O.K. */
-#define SK_SEN_ERR_WARN			2	/* Error Flag: Warning */
-#define SK_SEN_ERR_ERR			3	/* Error Flag: Error */
-#define SK_SEN_ERR_FAULTY		4	/* Error Flag: Faulty */
-
-/*
- * Define the Sensor struct
- */
-struct	s_Sensor {
-	char	*SenDesc;			/* Description */
-	int		SenType;			/* Voltage or Temperature */
-	SK_I32	SenValue;			/* Current value of the sensor */
-	SK_I32	SenThreErrHigh;		/* High error Threshhold of this sensor */
-	SK_I32	SenThreWarnHigh;	/* High warning Threshhold of this sensor */
-	SK_I32	SenThreErrLow;		/* Lower error Threshold of the sensor */
-	SK_I32	SenThreWarnLow;		/* Lower warning Threshold of the sensor */
-	int		SenErrFlag;			/* Sensor indicated an error */
-	SK_BOOL	SenInit;			/* Is sensor initialized ? */
-	SK_U64	SenErrCts;			/* Error trap counter */
-	SK_U64	SenWarnCts;			/* Warning trap counter */
-	SK_U64	SenBegErrTS;		/* Begin error timestamp */
-	SK_U64	SenBegWarnTS;		/* Begin warning timestamp */
-	SK_U64	SenLastErrTrapTS;	/* Last error trap timestamp */
-	SK_U64	SenLastErrLogTS;	/* Last error log timestamp */
-	SK_U64	SenLastWarnTrapTS;	/* Last warning trap timestamp */
-	SK_U64	SenLastWarnLogTS;	/* Last warning log timestamp */
-	int		SenState;			/* Sensor State (see HW specific include) */
-	int		(*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
-								/* Sensors read function */
-	SK_U16	SenReg;				/* Register Address for this sensor */
-	SK_U8	SenDev;				/* Device Selection for this sensor */
-};
-
-typedef	struct	s_I2c {
-	SK_SENSOR	SenTable[SK_MAX_SENSORS];	/* Sensor Table */
-	int			CurrSens;	/* Which sensor is currently queried */
-	int			MaxSens;	/* Max. number of sensors */
-	int			TimerMode;	/* Use the timer also to watch the state machine */
-	int			InitLevel;	/* Initialized Level */
-#ifndef SK_DIAG
-	int			DummyReads;	/* Number of non-checked dummy reads */
-	SK_TIMER	SenTimer;	/* Sensors timer */
-#endif /* !SK_DIAG */
-} SK_I2C;
-
-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
-#ifdef SK_DIAG
-extern	SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
-						 int Burst);
-#else /* !SK_DIAG */
-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
-#endif /* !SK_DIAG */
-#endif /* n_SKI2C_H */
-
diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
deleted file mode 100644
index 2ec40d4..0000000
--- a/drivers/net/sk98lin/h/skqueue.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- *
- * Name:	skqueue.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.16 $
- * Date:	$Date: 2003/09/16 12:50:32 $
- * Purpose:	Defines for the Event queue
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKQUEUE.H	contains all defines and types for the event queue
- */
-
-#ifndef _SKQUEUE_H_
-#define _SKQUEUE_H_
-
-
-/*
- * define the event classes to be served
- */
-#define	SKGE_DRV	1	/* Driver Event Class */
-#define	SKGE_RLMT	2	/* RLMT Event Class */
-#define	SKGE_I2C	3	/* I2C Event Class */
-#define	SKGE_PNMI	4	/* PNMI Event Class */
-#define	SKGE_CSUM	5	/* Checksum Event Class */
-#define	SKGE_HWAC	6	/* Hardware Access Event Class */
-
-#define	SKGE_SWT	9	/* Software Timer Event Class */
-#define	SKGE_LACP	10	/* LACP Aggregation Event Class */
-#define	SKGE_RSF	11	/* RSF Aggregation Event Class */
-#define	SKGE_MARKER	12	/* MARKER Aggregation Event Class */
-#define	SKGE_FD		13	/* FD Distributor Event Class */
-
-/*
- * define event queue as circular buffer
- */
-#define SK_MAX_EVENT	64
-
-/*
- * Parameter union for the Para stuff
- */
-typedef	union u_EvPara {
-	void	*pParaPtr;	/* Parameter Pointer */
-	SK_U64	Para64;		/* Parameter 64bit version */
-	SK_U32	Para32[2];	/* Parameter Array of 32bit parameters */
-} SK_EVPARA;
-
-/*
- * Event Queue
- *	skqueue.c
- * events are class/value pairs
- *	class	is addressee, e.g. RLMT, PNMI etc.
- *	value	is command, e.g. line state change, ring op change etc.
- */
-typedef	struct s_EventElem {
-	SK_U32		Class;			/* Event class */
-	SK_U32		Event;			/* Event value */
-	SK_EVPARA	Para;			/* Event parameter */
-} SK_EVENTELEM;
-
-typedef	struct s_Queue {
-	SK_EVENTELEM	EvQueue[SK_MAX_EVENT];
-	SK_EVENTELEM	*EvPut;
-	SK_EVENTELEM	*EvGet;
-} SK_QUEUE;
-
-extern	void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern	void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
-	SK_EVPARA Para);
-extern	int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
-
-
-/* Define Error Numbers and messages */
-#define	SKERR_Q_E001	(SK_ERRBASE_QUEUE+0)
-#define	SKERR_Q_E001MSG	"Event queue overflow"
-#define	SKERR_Q_E002	(SKERR_Q_E001+1)
-#define	SKERR_Q_E002MSG	"Undefined event class"
-#endif	/* _SKQUEUE_H_ */
-
diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
deleted file mode 100644
index ca75dfd..0000000
--- a/drivers/net/sk98lin/h/skrlmt.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/******************************************************************************
- *
- * Name:	skrlmt.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/04/15 09:43:43 $
- * Purpose:	Header file for Redundant Link ManagemenT.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the header file for Redundant Link ManagemenT.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	...
- *	"sktypes.h"
- *	"skqueue.h"
- *	"skaddr.h"
- *	"skrlmt.h"
- *	...
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKRLMT_H
-#define __INC_SKRLMT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-/* defines ********************************************************************/
-
-#define	SK_RLMT_NET_DOWN_TEMP	1	/* NET_DOWN due to last port down. */
-#define	SK_RLMT_NET_DOWN_FINAL	2	/* NET_DOWN due to RLMT_STOP. */
-
-/* ----- Default queue sizes - must be multiples of 8 KB ----- */
-
-/* Less than 8 KB free in RX queue => pause frames. */
-#define SK_RLMT_STANDBY_QRXSIZE	128	/* Size of rx standby queue in KB. */
-#define SK_RLMT_STANDBY_QXASIZE	32	/* Size of async standby queue in KB. */
-#define SK_RLMT_STANDBY_QXSSIZE	0	/* Size of sync standby queue in KB. */
-
-#define SK_RLMT_MAX_TX_BUF_SIZE	60	/* Maximum RLMT transmit size. */
-
-/* ----- PORT states ----- */
-
-#define SK_RLMT_PS_INIT			0	/* Port state: Init. */
-#define SK_RLMT_PS_LINK_DOWN	1	/* Port state: Link down. */
-#define SK_RLMT_PS_DOWN			2	/* Port state: Port down. */
-#define SK_RLMT_PS_GOING_UP		3	/* Port state: Going up. */
-#define SK_RLMT_PS_UP			4	/* Port state: Up. */
-
-/* ----- RLMT states ----- */
-
-#define SK_RLMT_RS_INIT			0	/* RLMT state: Init. */
-#define SK_RLMT_RS_NET_DOWN		1	/* RLMT state: Net down. */
-#define SK_RLMT_RS_NET_UP		2	/* RLMT state: Net up. */
-
-/* ----- PORT events ----- */
-
-#define SK_RLMT_LINK_UP			1001	/* Link came up. */
-#define SK_RLMT_LINK_DOWN		1002	/* Link went down. */
-#define SK_RLMT_PORT_ADDR		1003	/* Port address changed. */
-
-/* ----- RLMT events ----- */
-
-#define SK_RLMT_START			2001	/* Start RLMT. */
-#define SK_RLMT_STOP			2002	/* Stop RLMT. */
-#define SK_RLMT_PACKET_RECEIVED	2003	/* Packet was received for RLMT. */
-#define SK_RLMT_STATS_CLEAR		2004	/* Clear statistics. */
-#define SK_RLMT_STATS_UPDATE	2005	/* Update statistics. */
-#define SK_RLMT_PREFPORT_CHANGE	2006	/* Change preferred port. */
-#define SK_RLMT_MODE_CHANGE		2007	/* New RlmtMode. */
-#define SK_RLMT_SET_NETS		2008	/* Number of Nets (1 or 2). */
-
-/* ----- RLMT mode bits ----- */
-
-/*
- * CAUTION:	These defines are private to RLMT.
- *			Please use the RLMT mode defines below.
- */
-
-#define SK_RLMT_CHECK_LINK		  1		/* Check Link. */
-#define SK_RLMT_CHECK_LOC_LINK	  2		/* Check other link on same adapter. */
-#define SK_RLMT_CHECK_SEG		  4		/* Check segmentation. */
-
-#ifndef RLMT_CHECK_REMOTE
-#define SK_RLMT_CHECK_OTHERS	SK_RLMT_CHECK_LOC_LINK
-#else	/* RLMT_CHECK_REMOTE */
-#define SK_RLMT_CHECK_REM_LINK	  8		/* Check link(s) on other adapter(s). */
-#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED	3
-#define SK_RLMT_CHECK_OTHERS	\
-		(SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-#endif	/* RLMT_CHECK_REMOTE */
-
-#ifndef SK_RLMT_ENABLE_TRANSPARENT
-#define SK_RLMT_TRANSPARENT		  0		/* RLMT transparent - inactive. */
-#else	/* SK_RLMT_ENABLE_TRANSPARENT */
-#define SK_RLMT_TRANSPARENT		128		/* RLMT transparent. */
-#endif	/* SK_RLMT_ENABLE_TRANSPARENT */
-
-/* ----- RLMT modes ----- */
-
-/* Check Link State. */
-#define SK_RLMT_MODE_CLS	(SK_RLMT_CHECK_LINK)
-
-/* Check Local Ports: check other links on the same adapter. */
-#define SK_RLMT_MODE_CLP	(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
-
-/* Check Local Ports and Segmentation Status. */
-#define SK_RLMT_MODE_CLPSS	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
-
-#ifdef RLMT_CHECK_REMOTE
-/* Check Local and Remote Ports: check links (local or remote). */
-	Name of define TBD!
-#define SK_RLMT_MODE_CRP	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-
-/* Check Local and Remote Ports and Segmentation Status. */
-	Name of define TBD!
-#define SK_RLMT_MODE_CRPSS	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
-		SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
-#endif	/* RLMT_CHECK_REMOTE */
-
-/* ----- RLMT lookahead result bits ----- */
-
-#define SK_RLMT_RX_RLMT			1	/* Give packet to RLMT. */
-#define SK_RLMT_RX_PROTOCOL		2	/* Give packet to protocol. */
-
-/* Macros */
-
-#if 0
-SK_AC		*pAC		/* adapter context */
-SK_U32		PortNum		/* receiving port */
-unsigned	PktLen		/* received packet's length */
-SK_BOOL		IsBc		/* Flag: packet is broadcast */
-unsigned	*pOffset	/* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
-unsigned	*pNumBytes	/* #Bytes to present to SK_RLMT_LOOKAHEAD */
-#endif	/* 0 */
-
-#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
-	SK_AC	*_pAC; \
-	SK_U32	_PortNum; \
-	_pAC = (pAC); \
-	_PortNum = (SK_U32)(PortNum); \
-	/* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
-	_pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
-    if (_pAC->Rlmt.RlmtOff) { \
-		*(pNumBytes) = 0; \
-    } \
-    else {\
-        if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
-    		*(pNumBytes) = 0; \
-    	} \
-    	else if (IsBc) { \
-    		if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
-    			*(pNumBytes) = 6; \
-    			*(pOffset) = 6; \
-    		} \
-    		else { \
-    			*(pNumBytes) = 0; \
-    		} \
-    	} \
-    	else { \
-    		if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
-    			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-    			*(pNumBytes) = 0; \
-    		} \
-    		else { \
-    			*(pNumBytes) = 6; \
-    			*(pOffset) = 0; \
-    		} \
-    	} \
-    } \
-}
-
-#if 0
-SK_AC		*pAC		/* adapter context */
-SK_U32		PortNum		/* receiving port */
-SK_U8		*pLaPacket,	/* received packet's data (points to pOffset) */
-SK_BOOL		IsBc		/* Flag: packet is broadcast */
-SK_BOOL		IsMc		/* Flag: packet is multicast */
-unsigned	*pForRlmt	/* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
-SK_RLMT_LOOKAHEAD() expects *pNumBytes from
-packet offset *pOffset (s.a.) at *pLaPacket.
-
-If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
-BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
-can trash unneeded parts of the if construction.
-#endif	/* 0 */
-
-#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
-	SK_AC	*_pAC; \
-	SK_U32	_PortNum; \
-	SK_U8	*_pLaPacket; \
-	_pAC = (pAC); \
-	_PortNum = (SK_U32)(PortNum); \
-	_pLaPacket = (SK_U8 *)(pLaPacket); \
-	if (IsBc) {\
-		if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
-			_PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
-			_pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
-			_pAC->Rlmt.CheckSwitch = SK_TRUE; \
-		} \
-		/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-		*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-	} \
-	else if (IsMc) { \
-		if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
-			_pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
-			if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
-				*(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
-			} \
-			else { \
-				*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-			} \
-		} \
-		else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
-		} \
-		else { \
-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-		} \
-	} \
-	else { \
-		if (SK_ADDR_EQUAL( \
-			_pLaPacket, \
-			_pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
-		} \
-		else { \
-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-		} \
-	} \
-}
-
-#ifdef SK_RLMT_FAST_LOOKAHEAD
-Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif	/* SK_RLMT_FAST_LOOKAHEAD */
-#ifdef SK_RLMT_SLOW_LOOKAHEAD
-Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif	/* SK_RLMT_SLOW_LOOKAHEAD */
-
-/* typedefs *******************************************************************/
-
-#ifdef SK_RLMT_MBUF_PRIVATE
-typedef struct s_RlmtMbuf {
-	some content
-} SK_RLMT_MBUF;
-#endif	/* SK_RLMT_MBUF_PRIVATE */
-
-
-#ifdef SK_LA_INFO
-typedef struct s_Rlmt_PacketInfo {
-	unsigned	PacketLength;			/* Length of packet. */
-	unsigned	PacketType;				/* Directed/Multicast/Broadcast. */
-} SK_RLMT_PINFO;
-#endif	/* SK_LA_INFO */
-
-
-typedef struct s_RootId {
-	SK_U8		Id[8];					/* Root Bridge Id. */
-} SK_RLMT_ROOT_ID;
-
-
-typedef struct s_port {
-	SK_MAC_ADDR	CheckAddr;
-	SK_BOOL		SuspectTx;
-} SK_PORT_CHECK;
-
-
-typedef struct s_RlmtNet SK_RLMT_NET;
-
-
-typedef struct s_RlmtPort {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U8			PortState;				/* Current state of this port. */
-
-	/* For PNMI */
-	SK_BOOL			LinkDown;
-	SK_BOOL			PortDown;
-	SK_U8			Align01;
-
-	SK_U32			PortNumber;				/* Number of port on adapter. */
-	SK_RLMT_NET *	Net;					/* Net port belongs to. */
-
-	SK_U64			TxHelloCts;
-	SK_U64			RxHelloCts;
-	SK_U64			TxSpHelloReqCts;
-	SK_U64			RxSpHelloCts;
-
-/* ----- Private part ----- */
-
-/*	SK_U64			PacketsRx; */				/* Total packets received. */
-	SK_U32			PacketsPerTimeSlot;		/* Packets rxed between TOs. */
-/*	SK_U32			DataPacketsPerTimeSlot; */	/* Data packets ... */
-	SK_U32			BpduPacketsPerTimeSlot;	/* BPDU packets rxed in TS. */
-	SK_U64			BcTimeStamp;			/* Time of last BC receive. */
-	SK_U64			GuTimeStamp;			/* Time of entering GOING_UP. */
-
-	SK_TIMER		UpTimer;				/* Timer struct Link/Port up. */
-	SK_TIMER		DownRxTimer;			/* Timer struct down rx. */
-	SK_TIMER		DownTxTimer;			/* Timer struct down tx. */
-
-	SK_U32			CheckingState;			/* Checking State. */
-
-	SK_ADDR_PORT *	AddrPort;
-
-	SK_U8			Random[4];				/* Random value. */
-	unsigned		PortsChecked;			/* #ports checked. */
-	unsigned		PortsSuspect;			/* #ports checked that are s. */
-	SK_PORT_CHECK	PortCheck[1];
-/*	SK_PORT_CHECK	PortCheck[SK_MAX_MACS - 1]; */
-
-	SK_BOOL			PortStarted;			/* Port is started. */
-	SK_BOOL			PortNoRx;				/* NoRx for >= 1 time slot. */
-	SK_BOOL			RootIdSet;
-	SK_RLMT_ROOT_ID	Root;					/* Root Bridge Id. */
-} SK_RLMT_PORT;
-
-
-struct s_RlmtNet {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U32			NetNumber;			/* Number of net. */
-
-	SK_RLMT_PORT *	Port[SK_MAX_MACS];	/* Ports that belong to this net. */
-	SK_U32			NumPorts;			/* Number of ports. */
-	SK_U32			PrefPort;			/* Preferred port. */
-
-	/* For PNMI */
-
-	SK_U32			ChgBcPrio;			/* Change Priority of last broadcast received */
-	SK_U32			RlmtMode;			/* Check ... */
-	SK_U32			ActivePort;			/* Active port. */
-	SK_U32			Preference;		/* 0xFFFFFFFF: Automatic. */
-
-	SK_U8			RlmtState;			/* Current RLMT state. */
-
-/* ----- Private part ----- */
-	SK_BOOL			RootIdSet;
-	SK_U16			Align01;
-
-	int				LinksUp;			/* #Links up. */
-	int				PortsUp;			/* #Ports up. */
-	SK_U32			TimeoutValue;		/* RLMT timeout value. */
-
-	SK_U32			CheckingState;		/* Checking State. */
-	SK_RLMT_ROOT_ID	Root;				/* Root Bridge Id. */
-
-	SK_TIMER		LocTimer;			/* Timer struct. */
-	SK_TIMER		SegTimer;			/* Timer struct. */
-};
-
-
-typedef struct s_Rlmt {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U32			NumNets;			/* Number of nets. */
-	SK_U32			NetsStarted;		/* Number of nets started. */
-	SK_RLMT_NET		Net[SK_MAX_NETS];	/* Array of available nets. */
-	SK_RLMT_PORT	Port[SK_MAX_MACS];	/* Array of available ports. */
-
-/* ----- Private part ----- */
-	SK_BOOL			CheckSwitch;
-	SK_BOOL			RlmtOff;            /* set to zero if the Mac addresses 
-                                           are equal or the second one 
-                                           is zero */
-	SK_U16			Align01;
-
-} SK_RLMT;
-
-
-extern	SK_MAC_ADDR	BridgeMcAddr;
-extern	SK_MAC_ADDR	SkRlmtMcAddr;
-
-/* function prototypes ********************************************************/
-
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkRlmt */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern	void	SkRlmtInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Level);
-
-extern	int	SkRlmtEvent(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		Event,
-	SK_EVPARA	Para);
-
-#else	/* defined(SK_KR_PROTO) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style function prototypes are not yet provided.
-
-#endif	/* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKRLMT_H */
diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
deleted file mode 100644
index 04e6d7c..0000000
--- a/drivers/net/sk98lin/h/sktimer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktimer.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/16 12:58:18 $
- * Purpose:	Defines for the timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKTIMER.H	contains all defines and types for the timer functions
- */
-
-#ifndef	_SKTIMER_H_
-#define _SKTIMER_H_
-
-#include "h/skqueue.h"
-
-/*
- * SK timer
- * - needed wherever a timer is used. Put this in your data structure
- *   wherever you want.
- */
-typedef	struct s_Timer SK_TIMER;
-
-struct s_Timer {
-	SK_TIMER	*TmNext;	/* linked list */
-	SK_U32		TmClass;	/* Timer Event class */
-	SK_U32		TmEvent;	/* Timer Event value */
-	SK_EVPARA	TmPara;		/* Timer Event parameter */
-	SK_U32		TmDelta;	/* delta time */
-	int			TmActive;	/* flag: active/inactive */
-};
-
-/*
- * Timer control struct.
- * - use in Adapters context name pAC->Tim
- */
-typedef	struct s_TimCtrl {
-	SK_TIMER	*StQueue;	/* Head of Timer queue */
-} SK_TIMCTRL;
-
-extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
-extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
-	SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
-extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
-#endif	/* _SKTIMER_H_ */
diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
deleted file mode 100644
index 40edc96..0000000
--- a/drivers/net/sk98lin/h/sktypes.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktypes.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.2 $
- * Date:	$Date: 2003/10/07 08:16:51 $
- * Purpose:	Define data types for Linux
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
- 
-/******************************************************************************
- *
- * Description:
- *
- * In this file, all data types that are needed by the common modules
- * are mapped to Linux data types.
- * 
- *
- * Include File Hierarchy:
- *
- *
- ******************************************************************************/
-
-#ifndef __INC_SKTYPES_H
-#define __INC_SKTYPES_H
-
-
-/* defines *******************************************************************/
-
-/*
- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
- */
-#define SK_I8	s8
-#define SK_U8	u8
-#define SK_I16	s16
-#define SK_U16	u16
-#define SK_I32	s32
-#define SK_U32	u32
-#define SK_I64	s64
-#define SK_U64	u64
-
-#define SK_UPTR	ulong		/* casting pointer <-> integral */
-
-/*
-* Boolean type.
-*/
-#define SK_BOOL		SK_U8
-#define SK_FALSE	0
-#define SK_TRUE		(!SK_FALSE)
-
-/* typedefs *******************************************************************/
-
-/* function prototypes ********************************************************/
-
-#endif	/* __INC_SKTYPES_H */
diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
deleted file mode 100644
index a1a7294..0000000
--- a/drivers/net/sk98lin/h/skversion.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/******************************************************************************
- *
- * Name:	version.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/10/07 08:16:51 $
- * Purpose:	SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifdef	lint
-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
-static const char SysKonnectBuildNumber[] =
-	"@(#)SK-BUILD: 6.23 PL: 01"; 
-#endif	/* !defined(lint) */
-
-#define BOOT_STRING	"sk98lin: Network Device Driver v6.23\n" \
-			"(C)Copyright 1999-2004 Marvell(R)."
-
-#define VER_STRING	"6.23"
-#define DRIVER_FILE_NAME	"sk98lin"
-#define DRIVER_REL_DATE		"Feb-13-2004"
-
-
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
deleted file mode 100644
index fdd9e48..0000000
--- a/drivers/net/sk98lin/h/skvpd.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/******************************************************************************
- *
- * Name:	skvpd.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/01/13 10:39:38 $
- * Purpose:	Defines and Macros for VPD handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2003 SysKonnect GmbH.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * skvpd.h	contains Diagnostic specific defines for VPD handling
- */
-
-#ifndef __INC_SKVPD_H_
-#define __INC_SKVPD_H_
-
-/*
- * Define Resource Type Identifiers and VPD keywords
- */
-#define	RES_ID		0x82	/* Resource Type ID String (Product Name) */
-#define RES_VPD_R	0x90	/* start of VPD read only area */
-#define RES_VPD_W	0x91	/* start of VPD read/write area */
-#define RES_END		0x78	/* Resource Type End Tag */
-
-#ifndef VPD_NAME
-#define VPD_NAME	"Name"	/* Product Name, VPD name of RES_ID */
-#endif	/* VPD_NAME */
-#define VPD_PN		"PN"	/* Adapter Part Number */
-#define	VPD_EC		"EC"	/* Adapter Engineering Level */
-#define VPD_MN		"MN"	/* Manufacture ID */
-#define VPD_SN		"SN"	/* Serial Number */
-#define VPD_CP		"CP"	/* Extended Capability */
-#define VPD_RV		"RV"	/* Checksum and Reserved */
-#define	VPD_YA		"YA"	/* Asset Tag Identifier */
-#define VPD_VL		"VL"	/* First Error Log Message (SK specific) */
-#define VPD_VF		"VF"	/* Second Error Log Message (SK specific) */
-#define VPD_RW		"RW"	/* Remaining Read / Write Area */
-
-/* 'type' values for vpd_setup_para() */
-#define VPD_RO_KEY	1	/* RO keys are "PN", "EC", "MN", "SN", "RV" */
-#define VPD_RW_KEY	2	/* RW keys are "Yx", "Vx", and "RW" */
-
-/* 'op' values for vpd_setup_para() */
-#define	ADD_KEY		1	/* add the key at the pos "RV" or "RW" */
-#define OWR_KEY		2	/* overwrite key if already exists */
-
-/*
- * Define READ and WRITE Constants.
- */
-
-#define VPD_DEV_ID_GENESIS 	0x4300
-
-#define	VPD_SIZE_YUKON		256
-#define	VPD_SIZE_GENESIS	512
-#define	VPD_SIZE			512
-#define VPD_READ	0x0000
-#define VPD_WRITE	0x8000
-
-#define VPD_STOP(pAC,IoC)	VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
-
-#define VPD_GET_RES_LEN(p)	((unsigned int) \
-					(* (SK_U8 *)&(p)[1]) |\
-					((* (SK_U8 *)&(p)[2]) << 8))
-#define VPD_GET_VPD_LEN(p)	((unsigned int)(* (SK_U8 *)&(p)[2]))
-#define VPD_GET_VAL(p)		((char *)&(p)[3])
-
-#define VPD_MAX_LEN	50
-
-/* VPD status */
-	/* bit 7..1 reserved */
-#define VPD_VALID	(1<<0)	/* VPD data buffer, vpd_free_ro, */
-							/* and vpd_free_rw valid	 */
-
-/*
- * VPD structs
- */
-typedef	struct s_vpd_status {
-	unsigned short	Align01;			/* Alignment */
-	unsigned short	vpd_status;			/* VPD status, description see above */
-	int				vpd_free_ro;		/* unused bytes in read only area */
-	int				vpd_free_rw;		/* bytes available in read/write area */
-} SK_VPD_STATUS;
-
-typedef	struct s_vpd {
-	SK_VPD_STATUS	v;					/* VPD status structure */
-	char			vpd_buf[VPD_SIZE];	/* VPD buffer */
-	int				rom_size;			/* VPD ROM Size from PCI_OUR_REG_2 */
-	int				vpd_size;			/* saved VPD-size */
-} SK_VPD;
-
-typedef	struct s_vpd_para {
-	unsigned int	p_len;	/* parameter length */
-	char			*p_val;	/* points to the value */
-} SK_VPD_PARA;
-
-/*
- * structure of Large Resource Type Identifiers
- */
-
-/* was removed because of alignment problems */
-
-/*
- * structure of VPD keywords
- */
-typedef	struct s_vpd_key {
-	char			p_key[2];	/* 2 bytes ID string */
-	unsigned char	p_len;		/* 1 byte length */
-	char			p_val;		/* start of the value string */
-} SK_VPD_KEY;
-
-
-/*
- * System specific VPD macros
- */
-#ifndef SKDIAG
-#ifndef VPD_DO_IO
-#define VPD_OUT8(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgByte(pAC,Addr,Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgWord(pAC,Addr,Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgByte(pAC,Addr,pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgWord(pAC,Addr,pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgDWord(pAC,Addr,pVal)
-#else	/* VPD_DO_IO */
-#define VPD_OUT8(pAC,IoC,Addr,Val)	SK_OUT8(IoC,PCI_C(Addr),Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val)	SK_OUT16(IoC,PCI_C(Addr),Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal)	SK_IN8(IoC,PCI_C(Addr),pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal)	SK_IN16(IoC,PCI_C(Addr),pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal)	SK_IN32(IoC,PCI_C(Addr),pVal)
-#endif	/* VPD_DO_IO */
-#else	/* SKDIAG */
-#define VPD_OUT8(pAC,Ioc,Addr,Val) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciWriteCfgByte(pAC,Addr,Val);	\
-		else									\
-			SK_OUT8(pAC,PCI_C(Addr),Val);		\
-		}
-#define VPD_OUT16(pAC,Ioc,Addr,Val) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciWriteCfgWord(pAC,Addr,Val);	\
-		else						\
-			SK_OUT16(pAC,PCI_C(Addr),Val);		\
-		}
-#define VPD_IN8(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle) 			\
-			SkPciReadCfgByte(pAC,Addr,pVal);	\
-		else						\
-			SK_IN8(pAC,PCI_C(Addr),pVal); 		\
-		}
-#define VPD_IN16(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle) 			\
-			SkPciReadCfgWord(pAC,Addr,pVal);	\
-		else						\
-			SK_IN16(pAC,PCI_C(Addr),pVal); 		\
-		}
-#define VPD_IN32(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciReadCfgDWord(pAC,Addr,pVal);	\
-		else						\
-			SK_IN32(pAC,PCI_C(Addr),pVal);		\
-		}
-#endif	/* nSKDIAG */
-
-/* function prototypes ********************************************************/
-
-#ifndef	SK_KR_PROTO
-#ifdef SKDIAG
-extern SK_U32	VpdReadDWord(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	int			addr);
-#endif	/* SKDIAG */
-
-extern SK_VPD_STATUS	*VpdStat(
-	SK_AC		*pAC,
-	SK_IOC		IoC);
-
-extern int	VpdKeys(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			*len,
-	int			*elements);
-
-extern int	VpdRead(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	const char	*key,
-	char		*buf,
-	int			*len);
-
-extern SK_BOOL	VpdMayWrite(
-	char		*key);
-
-extern int	VpdWrite(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	const char	*key,
-	const char	*buf);
-
-extern int	VpdDelete(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*key);
-
-extern int	VpdUpdate(
-	SK_AC		*pAC,
-	SK_IOC		IoC);
-
-#ifdef	SKDIAG
-extern int	VpdReadBlock(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			addr,
-	int			len);
-
-extern int	VpdWriteBlock(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			addr,
-	int			len);
-#endif	/* SKDIAG */
-#else	/* SK_KR_PROTO */
-extern SK_U32	VpdReadDWord();
-extern SK_VPD_STATUS	*VpdStat();
-extern int	VpdKeys();
-extern int	VpdRead();
-extern SK_BOOL	VpdMayWrite();
-extern int	VpdWrite();
-extern int	VpdDelete();
-extern int	VpdUpdate();
-#endif	/* SK_KR_PROTO */
-
-#endif	/* __INC_SKVPD_H_ */
diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
deleted file mode 100644
index 7f8e6d0..0000000
--- a/drivers/net/sk98lin/h/xmac_ii.h
+++ /dev/null
@@ -1,1579 +0,0 @@
-/******************************************************************************
- *
- * Name:	xmac_ii.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/10/02 16:35:50 $
- * Purpose:	Defines and Macros for Gigabit Ethernet Controller
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_XMAC_H
-#define __INC_XMAC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * XMAC II registers
- *
- * The XMAC registers are 16 or 32 bits wide.
- * The XMACs host processor interface is set to 16 bit mode,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the XMAC registers
- * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
- * XM_INHASH(), and XM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note:	NA reg	= Network Address e.g DA, SA etc.
- *
- */
-#define XM_MMU_CMD		0x0000	/* 16 bit r/w	MMU Command Register */
-	/* 0x0004:		reserved */
-#define XM_POFF			0x0008	/* 32 bit r/w	Packet Offset Register */
-#define XM_BURST		0x000c	/* 32 bit r/w	Burst Register for half duplex*/
-#define XM_1L_VLAN_TAG	0x0010	/* 16 bit r/w	One Level VLAN Tag ID */
-#define XM_2L_VLAN_TAG	0x0014	/* 16 bit r/w	Two Level VLAN Tag ID */
-	/* 0x0018 - 0x001e:	reserved */
-#define XM_TX_CMD		0x0020	/* 16 bit r/w	Transmit Command Register */
-#define XM_TX_RT_LIM	0x0024	/* 16 bit r/w	Transmit Retry Limit Register */
-#define XM_TX_STIME		0x0028	/* 16 bit r/w	Transmit Slottime Register */
-#define XM_TX_IPG		0x002c	/* 16 bit r/w	Transmit Inter Packet Gap */
-#define XM_RX_CMD		0x0030	/* 16 bit r/w	Receive Command Register */
-#define XM_PHY_ADDR		0x0034	/* 16 bit r/w	PHY Address Register */
-#define XM_PHY_DATA		0x0038	/* 16 bit r/w	PHY Data Register */
-	/* 0x003c: 		reserved */
-#define XM_GP_PORT		0x0040	/* 32 bit r/w	General Purpose Port Register */
-#define XM_IMSK			0x0044	/* 16 bit r/w	Interrupt Mask Register */
-#define XM_ISRC			0x0048	/* 16 bit r/o	Interrupt Status Register */
-#define XM_HW_CFG		0x004c	/* 16 bit r/w	Hardware Config Register */
-	/* 0x0050 - 0x005e:	reserved */
-#define XM_TX_LO_WM		0x0060	/* 16 bit r/w	Tx FIFO Low Water Mark */
-#define XM_TX_HI_WM		0x0062	/* 16 bit r/w	Tx FIFO High Water Mark */
-#define XM_TX_THR		0x0064	/* 16 bit r/w	Tx Request Threshold */
-#define XM_HT_THR		0x0066	/* 16 bit r/w	Host Request Threshold */
-#define XM_PAUSE_DA		0x0068	/* NA reg r/w	Pause Destination Address */
-	/* 0x006e: 		reserved */
-#define XM_CTL_PARA		0x0070	/* 32 bit r/w	Control Parameter Register */
-#define XM_MAC_OPCODE	0x0074	/* 16 bit r/w	Opcode for MAC control frames */
-#define XM_MAC_PTIME	0x0076	/* 16 bit r/w	Pause time for MAC ctrl frames*/
-#define XM_TX_STAT		0x0078	/* 32 bit r/o	Tx Status LIFO Register */
-
-	/* 0x0080 - 0x00fc:	16 NA reg r/w	Exact Match Address Registers */
-	/* 				use the XM_EXM() macro to address */
-#define XM_EXM_START	0x0080	/* r/w	Start Address of the EXM Regs */
-
-	/*
-	 * XM_EXM(Reg)
-	 *
-	 * returns the XMAC address offset of specified Exact Match Addr Reg
-	 *
-	 * para:	Reg	EXM register to addr	(0 .. 15)
-	 *
-	 * usage:	XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
-	 */
-#define XM_EXM(Reg)	(XM_EXM_START + ((Reg) << 3))
-
-#define XM_SRC_CHK		0x0100	/* NA reg r/w	Source Check Address Register */
-#define XM_SA			0x0108	/* NA reg r/w	Station Address Register */
-#define XM_HSM			0x0110	/* 64 bit r/w	Hash Match Address Registers */
-#define XM_RX_LO_WM		0x0118	/* 16 bit r/w	Receive Low Water Mark */
-#define XM_RX_HI_WM		0x011a	/* 16 bit r/w	Receive High Water Mark */
-#define XM_RX_THR		0x011c	/* 32 bit r/w	Receive Request Threshold */
-#define XM_DEV_ID		0x0120	/* 32 bit r/o	Device ID Register */
-#define XM_MODE			0x0124	/* 32 bit r/w	Mode Register */
-#define XM_LSA			0x0128	/* NA reg r/o	Last Source Register */
-	/* 0x012e:		reserved */
-#define XM_TS_READ		0x0130	/* 32 bit r/o	Time Stamp Read Register */
-#define XM_TS_LOAD		0x0134	/* 32 bit r/o	Time Stamp Load Value */
-	/* 0x0138 - 0x01fe:	reserved */
-#define XM_STAT_CMD	0x0200	/* 16 bit r/w	Statistics Command Register */
-#define XM_RX_CNT_EV	0x0204	/* 32 bit r/o	Rx Counter Event Register */
-#define XM_TX_CNT_EV	0x0208	/* 32 bit r/o	Tx Counter Event Register */
-#define XM_RX_EV_MSK	0x020c	/* 32 bit r/w	Rx Counter Event Mask */
-#define XM_TX_EV_MSK	0x0210	/* 32 bit r/w	Tx Counter Event Mask */
-	/* 0x0204 - 0x027e:	reserved */
-#define XM_TXF_OK		0x0280	/* 32 bit r/o	Frames Transmitted OK Conuter */
-#define XM_TXO_OK_HI	0x0284	/* 32 bit r/o	Octets Transmitted OK High Cnt*/
-#define XM_TXO_OK_LO	0x0288	/* 32 bit r/o	Octets Transmitted OK Low Cnt */
-#define XM_TXF_BC_OK	0x028c	/* 32 bit r/o	Broadcast Frames Xmitted OK */
-#define XM_TXF_MC_OK	0x0290	/* 32 bit r/o	Multicast Frames Xmitted OK */
-#define XM_TXF_UC_OK	0x0294	/* 32 bit r/o	Unicast Frames Xmitted OK */
-#define XM_TXF_LONG		0x0298	/* 32 bit r/o	Tx Long Frame Counter */
-#define XM_TXE_BURST	0x029c	/* 32 bit r/o	Tx Burst Event Counter */
-#define XM_TXF_MPAUSE	0x02a0	/* 32 bit r/o	Tx Pause MAC Ctrl Frame Cnt */
-#define XM_TXF_MCTRL	0x02a4	/* 32 bit r/o	Tx MAC Ctrl Frame Counter */
-#define XM_TXF_SNG_COL	0x02a8	/* 32 bit r/o	Tx Single Collision Counter */
-#define XM_TXF_MUL_COL	0x02ac	/* 32 bit r/o	Tx Multiple Collision Counter */
-#define XM_TXF_ABO_COL	0x02b0	/* 32 bit r/o	Tx aborted due to Exces. Col. */
-#define XM_TXF_LAT_COL	0x02b4	/* 32 bit r/o	Tx Late Collision Counter */
-#define XM_TXF_DEF		0x02b8	/* 32 bit r/o	Tx Deferred Frame Counter */
-#define XM_TXF_EX_DEF	0x02bc	/* 32 bit r/o	Tx Excessive Deferall Counter */
-#define XM_TXE_FIFO_UR	0x02c0	/* 32 bit r/o	Tx FIFO Underrun Event Cnt */
-#define XM_TXE_CS_ERR	0x02c4	/* 32 bit r/o	Tx Carrier Sense Error Cnt */
-#define XM_TXP_UTIL		0x02c8	/* 32 bit r/o	Tx Utilization in % */
-	/* 0x02cc - 0x02ce:	reserved */
-#define XM_TXF_64B		0x02d0	/* 32 bit r/o	64 Byte Tx Frame Counter */
-#define XM_TXF_127B		0x02d4	/* 32 bit r/o	65-127 Byte Tx Frame Counter */
-#define XM_TXF_255B		0x02d8	/* 32 bit r/o	128-255 Byte Tx Frame Counter */
-#define XM_TXF_511B		0x02dc	/* 32 bit r/o	256-511 Byte Tx Frame Counter */
-#define XM_TXF_1023B	0x02e0	/* 32 bit r/o	512-1023 Byte Tx Frame Counter*/
-#define XM_TXF_MAX_SZ	0x02e4	/* 32 bit r/o	1024-MaxSize Byte Tx Frame Cnt*/
-	/* 0x02e8 - 0x02fe:	reserved */
-#define XM_RXF_OK		0x0300	/* 32 bit r/o	Frames Received OK */
-#define XM_RXO_OK_HI	0x0304	/* 32 bit r/o	Octets Received OK High Cnt */
-#define XM_RXO_OK_LO	0x0308	/* 32 bit r/o	Octets Received OK Low Counter*/
-#define XM_RXF_BC_OK	0x030c	/* 32 bit r/o	Broadcast Frames Received OK */
-#define XM_RXF_MC_OK	0x0310	/* 32 bit r/o	Multicast Frames Received OK */
-#define XM_RXF_UC_OK	0x0314	/* 32 bit r/o	Unicast Frames Received OK */
-#define XM_RXF_MPAUSE	0x0318	/* 32 bit r/o	Rx Pause MAC Ctrl Frame Cnt */
-#define XM_RXF_MCTRL	0x031c	/* 32 bit r/o	Rx MAC Ctrl Frame Counter */
-#define XM_RXF_INV_MP	0x0320	/* 32 bit r/o	Rx invalid Pause Frame Cnt */
-#define XM_RXF_INV_MOC	0x0324	/* 32 bit r/o	Rx Frames with inv. MAC Opcode*/
-#define XM_RXE_BURST	0x0328	/* 32 bit r/o	Rx Burst Event Counter */
-#define XM_RXE_FMISS	0x032c	/* 32 bit r/o	Rx Missed Frames Event Cnt */
-#define XM_RXF_FRA_ERR	0x0330	/* 32 bit r/o	Rx Framing Error Counter */
-#define XM_RXE_FIFO_OV	0x0334	/* 32 bit r/o	Rx FIFO overflow Event Cnt */
-#define XM_RXF_JAB_PKT	0x0338	/* 32 bit r/o	Rx Jabber Packet Frame Cnt */
-#define XM_RXE_CAR_ERR	0x033c	/* 32 bit r/o	Rx Carrier Event Error Cnt */
-#define XM_RXF_LEN_ERR	0x0340	/* 32 bit r/o	Rx in Range Length Error */
-#define XM_RXE_SYM_ERR	0x0344	/* 32 bit r/o	Rx Symbol Error Counter */
-#define XM_RXE_SHT_ERR	0x0348	/* 32 bit r/o	Rx Short Event Error Cnt */
-#define XM_RXE_RUNT		0x034c	/* 32 bit r/o	Rx Runt Event Counter */
-#define XM_RXF_LNG_ERR	0x0350	/* 32 bit r/o	Rx Frame too Long Error Cnt */
-#define XM_RXF_FCS_ERR	0x0354	/* 32 bit r/o	Rx Frame Check Seq. Error Cnt */
-	/* 0x0358 - 0x035a:	reserved */
-#define XM_RXF_CEX_ERR	0x035c	/* 32 bit r/o	Rx Carrier Ext Error Frame Cnt*/
-#define XM_RXP_UTIL		0x0360	/* 32 bit r/o	Rx Utilization in % */
-	/* 0x0364 - 0x0366:	reserved */
-#define XM_RXF_64B		0x0368	/* 32 bit r/o	64 Byte Rx Frame Counter */
-#define XM_RXF_127B		0x036c	/* 32 bit r/o	65-127 Byte Rx Frame Counter */
-#define XM_RXF_255B		0x0370	/* 32 bit r/o	128-255 Byte Rx Frame Counter */
-#define XM_RXF_511B		0x0374	/* 32 bit r/o	256-511 Byte Rx Frame Counter */
-#define XM_RXF_1023B	0x0378	/* 32 bit r/o	512-1023 Byte Rx Frame Counter*/
-#define XM_RXF_MAX_SZ	0x037c	/* 32 bit r/o	1024-MaxSize Byte Rx Frame Cnt*/
-	/* 0x02e8 - 0x02fe:	reserved */
-
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- *	(sc)	self clearing
- *	(ro)	read only
- */
-
-/*	XM_MMU_CMD	16 bit r/w	MMU Command Register */
-								/* Bit 15..13:	reserved */
-#define XM_MMU_PHY_RDY	(1<<12)	/* Bit 12:	PHY Read Ready */
-#define XM_MMU_PHY_BUSY	(1<<11)	/* Bit 11:	PHY Busy */
-#define XM_MMU_IGN_PF	(1<<10)	/* Bit 10:	Ignore Pause Frame */
-#define XM_MMU_MAC_LB	(1<<9)	/* Bit  9:	Enable MAC Loopback */
-								/* Bit  8:	reserved */
-#define XM_MMU_FRC_COL	(1<<7)	/* Bit  7:	Force Collision */
-#define XM_MMU_SIM_COL	(1<<6)	/* Bit  6:	Simulate Collision */
-#define XM_MMU_NO_PRE	(1<<5)	/* Bit  5:	No MDIO Preamble */
-#define XM_MMU_GMII_FD	(1<<4)	/* Bit  4:	GMII uses Full Duplex */
-#define XM_MMU_RAT_CTRL	(1<<3)	/* Bit  3:	Enable Rate Control */
-#define XM_MMU_GMII_LOOP (1<<2)	/* Bit  2:	PHY is in Loopback Mode */
-#define XM_MMU_ENA_RX	(1<<1)	/* Bit  1:	Enable Receiver */
-#define XM_MMU_ENA_TX	(1<<0)	/* Bit  0:	Enable Transmitter */
-
-
-/*	XM_TX_CMD	16 bit r/w	Transmit Command Register */
-								/* Bit 15..7:	reserved */
-#define XM_TX_BK2BK		(1<<6)	/* Bit  6:	Ignor Carrier Sense (Tx Bk2Bk)*/
-#define XM_TX_ENC_BYP	(1<<5)	/* Bit  5:	Set Encoder in Bypass Mode */
-#define XM_TX_SAM_LINE	(1<<4)	/* Bit  4: (sc)	Start utilization calculation */
-#define XM_TX_NO_GIG_MD	(1<<3)	/* Bit  3:	Disable Carrier Extension */
-#define XM_TX_NO_PRE	(1<<2)	/* Bit  2:	Disable Preamble Generation */
-#define XM_TX_NO_CRC	(1<<1)	/* Bit  1:	Disable CRC Generation */
-#define XM_TX_AUTO_PAD	(1<<0)	/* Bit  0:	Enable Automatic Padding */
-
-
-/*	XM_TX_RT_LIM	16 bit r/w	Transmit Retry Limit Register */
-								/* Bit 15..5:	reserved */
-#define XM_RT_LIM_MSK	0x1f	/* Bit  4..0:	Tx Retry Limit */
-
-
-/*	XM_TX_STIME	16 bit r/w	Transmit Slottime Register */
-								/* Bit 15..7:	reserved */
-#define XM_STIME_MSK	0x7f	/* Bit  6..0:	Tx Slottime bits */
-
-
-/*	XM_TX_IPG	16 bit r/w	Transmit Inter Packet Gap */
-								/* Bit 15..8:	reserved */
-#define XM_IPG_MSK		0xff	/* Bit  7..0:	IPG value bits */
-
-
-/*	XM_RX_CMD	16 bit r/w	Receive Command Register */
-								/* Bit 15..9:	reserved */
-#define XM_RX_LENERR_OK (1<<8)	/* Bit  8	don't set Rx Err bit for */
-								/*		inrange error packets */
-#define XM_RX_BIG_PK_OK	(1<<7)	/* Bit  7	don't set Rx Err bit for */
-								/*		jumbo packets */
-#define XM_RX_IPG_CAP	(1<<6)	/* Bit  6	repl. type field with IPG */
-#define XM_RX_TP_MD		(1<<5)	/* Bit  5:	Enable transparent Mode */
-#define XM_RX_STRIP_FCS	(1<<4)	/* Bit  4:	Enable FCS Stripping */
-#define XM_RX_SELF_RX	(1<<3)	/* Bit  3: 	Enable Rx of own packets */
-#define XM_RX_SAM_LINE	(1<<2)	/* Bit  2: (sc)	Start utilization calculation */
-#define XM_RX_STRIP_PAD	(1<<1)	/* Bit  1:	Strip pad bytes of Rx frames */
-#define XM_RX_DIS_CEXT	(1<<0)	/* Bit  0:	Disable carrier ext. check */
-
-
-/*	XM_PHY_ADDR	16 bit r/w	PHY Address Register */
-								/* Bit 15..5:	reserved */
-#define XM_PHY_ADDR_SZ	0x1f	/* Bit  4..0:	PHY Address bits */
-
-
-/*	XM_GP_PORT	32 bit r/w	General Purpose Port Register */
-								/* Bit 31..7:	reserved */
-#define XM_GP_ANIP		(1L<<6)	/* Bit  6: (ro)	Auto-Neg. in progress */
-#define XM_GP_FRC_INT	(1L<<5)	/* Bit  5: (sc)	Force Interrupt */
-								/* Bit  4:	reserved */
-#define XM_GP_RES_MAC	(1L<<3)	/* Bit  3: (sc)	Reset MAC and FIFOs */
-#define XM_GP_RES_STAT	(1L<<2)	/* Bit  2: (sc)	Reset the statistics module */
-								/* Bit  1:	reserved */
-#define XM_GP_INP_ASS	(1L<<0)	/* Bit  0: (ro) GP Input Pin asserted */
-
-
-/*	XM_IMSK		16 bit r/w	Interrupt Mask Register */
-/*	XM_ISRC		16 bit r/o	Interrupt Status Register */
-								/* Bit 15:	reserved */
-#define XM_IS_LNK_AE	(1<<14) /* Bit 14:	Link Asynchronous Event */
-#define XM_IS_TX_ABORT	(1<<13) /* Bit 13:	Transmit Abort, late Col. etc */
-#define XM_IS_FRC_INT	(1<<12) /* Bit 12:	Force INT bit set in GP */
-#define XM_IS_INP_ASS	(1<<11)	/* Bit 11:	Input Asserted, GP bit 0 set */
-#define XM_IS_LIPA_RC	(1<<10)	/* Bit 10:	Link Partner requests config */
-#define XM_IS_RX_PAGE	(1<<9)	/* Bit  9:	Page Received */
-#define XM_IS_TX_PAGE	(1<<8)	/* Bit  8:	Next Page Loaded for Transmit */
-#define XM_IS_AND		(1<<7)	/* Bit  7:	Auto-Negotiation Done */
-#define XM_IS_TSC_OV	(1<<6)	/* Bit  6:	Time Stamp Counter Overflow */
-#define XM_IS_RXC_OV	(1<<5)	/* Bit  5:	Rx Counter Event Overflow */
-#define XM_IS_TXC_OV	(1<<4)	/* Bit  4:	Tx Counter Event Overflow */
-#define XM_IS_RXF_OV	(1<<3)	/* Bit  3:	Receive FIFO Overflow */
-#define XM_IS_TXF_UR	(1<<2)	/* Bit  2:	Transmit FIFO Underrun */
-#define XM_IS_TX_COMP	(1<<1)	/* Bit  1:	Frame Tx Complete */
-#define XM_IS_RX_COMP	(1<<0)	/* Bit  0:	Frame Rx Complete */
-
-#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
-			XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
-
-
-/*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
-								/* Bit 15.. 4:	reserved */
-#define XM_HW_GEN_EOP	(1<<3)	/* Bit  3:	generate End of Packet pulse */
-#define XM_HW_COM4SIG	(1<<2)	/* Bit  2:	use Comma Detect for Sig. Det.*/
-								/* Bit  1:	reserved */
-#define XM_HW_GMII_MD	(1<<0)	/* Bit  0:	GMII Interface selected */
-
-
-/*	XM_TX_LO_WM	16 bit r/w	Tx FIFO Low Water Mark */
-/*	XM_TX_HI_WM	16 bit r/w	Tx FIFO High Water Mark */
-								/* Bit 15..10	reserved */
-#define XM_TX_WM_MSK	0x01ff	/* Bit  9.. 0	Tx FIFO Watermark bits */
-
-/*	XM_TX_THR	16 bit r/w	Tx Request Threshold */
-/*	XM_HT_THR	16 bit r/w	Host Request Threshold */
-/*	XM_RX_THR	16 bit r/w	Rx Request Threshold */
-								/* Bit 15..11	reserved */
-#define XM_THR_MSK		0x03ff	/* Bit 10.. 0	Rx/Tx Request Threshold bits */
-
-
-/*	XM_TX_STAT	32 bit r/o	Tx Status LIFO Register */
-#define XM_ST_VALID		(1UL<<31)	/* Bit 31:	Status Valid */
-#define XM_ST_BYTE_CNT	(0x3fffL<<17)	/* Bit 30..17:	Tx frame Length */
-#define XM_ST_RETRY_CNT	(0x1fL<<12)	/* Bit 16..12:	Retry Count */
-#define XM_ST_EX_COL	(1L<<11)	/* Bit 11:	Excessive Collisions */
-#define XM_ST_EX_DEF	(1L<<10)	/* Bit 10:	Excessive Deferral */
-#define XM_ST_BURST		(1L<<9)		/* Bit  9:	p. xmitted in burst md*/
-#define XM_ST_DEFER		(1L<<8)		/* Bit  8:	packet was defered */
-#define XM_ST_BC		(1L<<7)		/* Bit  7:	Broadcast packet */
-#define XM_ST_MC		(1L<<6)		/* Bit  6:	Multicast packet */
-#define XM_ST_UC		(1L<<5)		/* Bit  5:	Unicast packet */
-#define XM_ST_TX_UR		(1L<<4)		/* Bit  4:	FIFO Underrun occured */
-#define XM_ST_CS_ERR	(1L<<3)		/* Bit  3:	Carrier Sense Error */
-#define XM_ST_LAT_COL	(1L<<2)		/* Bit  2:	Late Collision Error */
-#define XM_ST_MUL_COL	(1L<<1)		/* Bit  1:	Multiple Collisions */
-#define XM_ST_SGN_COL	(1L<<0)		/* Bit  0:	Single Collision */
-
-/*	XM_RX_LO_WM	16 bit r/w	Receive Low Water Mark */
-/*	XM_RX_HI_WM	16 bit r/w	Receive High Water Mark */
-									/* Bit 15..11:	reserved */
-#define XM_RX_WM_MSK	0x03ff		/* Bit 11.. 0:	Rx FIFO Watermark bits */
-
-
-/*	XM_DEV_ID	32 bit r/o	Device ID Register */
-#define XM_DEV_OUI	(0x00ffffffUL<<8)	/* Bit 31..8:	Device OUI */
-#define XM_DEV_REV	(0x07L << 5)		/* Bit  7..5:	Chip Rev Num */
-
-
-/*	XM_MODE		32 bit r/w	Mode Register */
-									/* Bit 31..27:	reserved */
-#define XM_MD_ENA_REJ	(1L<<26)	/* Bit 26:	Enable Frame Reject */
-#define XM_MD_SPOE_E	(1L<<25)	/* Bit 25:	Send Pause on Edge */
-									/* 		extern generated */
-#define XM_MD_TX_REP	(1L<<24)	/* Bit 24:	Transmit Repeater Mode */
-#define XM_MD_SPOFF_I	(1L<<23)	/* Bit 23:	Send Pause on FIFO full */
-									/*		intern generated */
-#define XM_MD_LE_STW	(1L<<22)	/* Bit 22:	Rx Stat Word in Little Endian */
-#define XM_MD_TX_CONT	(1L<<21)	/* Bit 21:	Send Continuous */
-#define XM_MD_TX_PAUSE	(1L<<20)	/* Bit 20: (sc)	Send Pause Frame */
-#define XM_MD_ATS		(1L<<19)	/* Bit 19:	Append Time Stamp */
-#define XM_MD_SPOL_I	(1L<<18)	/* Bit 18:	Send Pause on Low */
-									/*		intern generated */
-#define XM_MD_SPOH_I	(1L<<17)	/* Bit 17:	Send Pause on High */
-									/*		intern generated */
-#define XM_MD_CAP		(1L<<16)	/* Bit 16:	Check Address Pair */
-#define XM_MD_ENA_HASH	(1L<<15)	/* Bit 15:	Enable Hashing */
-#define XM_MD_CSA		(1L<<14)	/* Bit 14:	Check Station Address */
-#define XM_MD_CAA		(1L<<13)	/* Bit 13:	Check Address Array */
-#define XM_MD_RX_MCTRL	(1L<<12)	/* Bit 12:	Rx MAC Control Frame */
-#define XM_MD_RX_RUNT	(1L<<11)	/* Bit 11:	Rx Runt Frames */
-#define XM_MD_RX_IRLE	(1L<<10)	/* Bit 10:	Rx in Range Len Err Frame */
-#define XM_MD_RX_LONG	(1L<<9)		/* Bit  9:	Rx Long Frame */
-#define XM_MD_RX_CRCE	(1L<<8)		/* Bit  8:	Rx CRC Error Frame */
-#define XM_MD_RX_ERR	(1L<<7)		/* Bit  7:	Rx Error Frame */
-#define XM_MD_DIS_UC	(1L<<6)		/* Bit  6:	Disable Rx Unicast */
-#define XM_MD_DIS_MC	(1L<<5)		/* Bit  5:	Disable Rx Multicast */
-#define XM_MD_DIS_BC	(1L<<4)		/* Bit  4:	Disable Rx Broadcast */
-#define XM_MD_ENA_PROM	(1L<<3)		/* Bit  3:	Enable Promiscuous */
-#define XM_MD_ENA_BE	(1L<<2)		/* Bit  2:	Enable Big Endian */
-#define XM_MD_FTF		(1L<<1)		/* Bit  1: (sc)	Flush Tx FIFO */
-#define XM_MD_FRF		(1L<<0)		/* Bit  0: (sc)	Flush Rx FIFO */
-
-#define XM_PAUSE_MODE	(XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
-#define XM_DEF_MODE		(XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
-				XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
-
-/*	XM_STAT_CMD	16 bit r/w	Statistics Command Register */
-								/* Bit 16..6:	reserved */
-#define XM_SC_SNP_RXC	(1<<5)	/* Bit  5: (sc)	Snap Rx Counters */
-#define XM_SC_SNP_TXC	(1<<4)	/* Bit  4: (sc)	Snap Tx Counters */
-#define XM_SC_CP_RXC	(1<<3)	/* Bit  3: 	Copy Rx Counters Continuously */
-#define XM_SC_CP_TXC	(1<<2)	/* Bit  2:	Copy Tx Counters Continuously */
-#define XM_SC_CLR_RXC	(1<<1)	/* Bit  1: (sc)	Clear Rx Counters */
-#define XM_SC_CLR_TXC	(1<<0)	/* Bit  0: (sc) Clear Tx Counters */
-
-
-/*	XM_RX_CNT_EV	32 bit r/o	Rx Counter Event Register */
-/*	XM_RX_EV_MSK	32 bit r/w	Rx Counter Event Mask */
-#define XMR_MAX_SZ_OV	(1UL<<31)	/* Bit 31:	1024-MaxSize Rx Cnt Ov*/
-#define XMR_1023B_OV	(1L<<30)	/* Bit 30:	512-1023Byte Rx Cnt Ov*/
-#define XMR_511B_OV		(1L<<29)	/* Bit 29:	256-511 Byte Rx Cnt Ov*/
-#define XMR_255B_OV		(1L<<28)	/* Bit 28:	128-255 Byte Rx Cnt Ov*/
-#define XMR_127B_OV		(1L<<27)	/* Bit 27:	65-127 Byte Rx Cnt Ov */
-#define XMR_64B_OV		(1L<<26)	/* Bit 26:	64 Byte Rx Cnt Ov */
-#define XMR_UTIL_OV		(1L<<25)	/* Bit 25:	Rx Util Cnt Overflow */
-#define XMR_UTIL_UR		(1L<<24)	/* Bit 24:	Rx Util Cnt Underrun */
-#define XMR_CEX_ERR_OV	(1L<<23)	/* Bit 23:	CEXT Err Cnt Ov */
-									/* Bit 22:	reserved */
-#define XMR_FCS_ERR_OV	(1L<<21)	/* Bit 21:	Rx FCS Error Cnt Ov */
-#define XMR_LNG_ERR_OV	(1L<<20)	/* Bit 20:	Rx too Long Err Cnt Ov*/
-#define XMR_RUNT_OV		(1L<<19)	/* Bit 19:	Runt Event Cnt Ov */
-#define XMR_SHT_ERR_OV	(1L<<18)	/* Bit 18:	Rx Short Ev Err Cnt Ov*/
-#define XMR_SYM_ERR_OV	(1L<<17)	/* Bit 17:	Rx Sym Err Cnt Ov */
-									/* Bit 16:	reserved */
-#define XMR_CAR_ERR_OV	(1L<<15)	/* Bit 15:	Rx Carr Ev Err Cnt Ov */
-#define XMR_JAB_PKT_OV	(1L<<14)	/* Bit 14:	Rx Jabb Packet Cnt Ov */
-#define XMR_FIFO_OV		(1L<<13)	/* Bit 13:	Rx FIFO Ov Ev Cnt Ov */
-#define XMR_FRA_ERR_OV	(1L<<12)	/* Bit 12:	Rx Framing Err Cnt Ov */
-#define XMR_FMISS_OV	(1L<<11)	/* Bit 11:	Rx Missed Ev Cnt Ov */
-#define XMR_BURST		(1L<<10)	/* Bit 10:	Rx Burst Event Cnt Ov */
-#define XMR_INV_MOC		(1L<<9)		/* Bit  9:	Rx with inv. MAC OC Ov*/
-#define XMR_INV_MP		(1L<<8)		/* Bit  8:	Rx inv Pause Frame Ov */
-#define XMR_MCTRL_OV	(1L<<7)		/* Bit  7:	Rx MAC Ctrl-F Cnt Ov */
-#define XMR_MPAUSE_OV	(1L<<6)		/* Bit  6:	Rx Pause MAC Ctrl-F Ov*/
-#define XMR_UC_OK_OV	(1L<<5)		/* Bit  5:	Rx Unicast Frame CntOv*/
-#define XMR_MC_OK_OV	(1L<<4)		/* Bit  4:	Rx Multicast Cnt Ov */
-#define XMR_BC_OK_OV	(1L<<3)		/* Bit  3:	Rx Broadcast Cnt Ov */
-#define XMR_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Rx OK Low CntOv*/
-#define XMR_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Rx OK Hi Cnt Ov*/
-#define XMR_OK_OV		(1L<<0)		/* Bit  0:	Frames Received Ok Ov */
-
-#define XMR_DEF_MSK		(XMR_OK_LO_OV | XMR_OK_HI_OV)
-
-/*	XM_TX_CNT_EV	32 bit r/o	Tx Counter Event Register */
-/*	XM_TX_EV_MSK	32 bit r/w	Tx Counter Event Mask */
-									/* Bit 31..26:	reserved */
-#define XMT_MAX_SZ_OV	(1L<<25)	/* Bit 25:	1024-MaxSize Tx Cnt Ov*/
-#define XMT_1023B_OV	(1L<<24)	/* Bit 24:	512-1023Byte Tx Cnt Ov*/
-#define XMT_511B_OV		(1L<<23)	/* Bit 23:	256-511 Byte Tx Cnt Ov*/
-#define XMT_255B_OV		(1L<<22)	/* Bit 22:	128-255 Byte Tx Cnt Ov*/
-#define XMT_127B_OV		(1L<<21)	/* Bit 21:	65-127 Byte Tx Cnt Ov */
-#define XMT_64B_OV		(1L<<20)	/* Bit 20:	64 Byte Tx Cnt Ov */
-#define XMT_UTIL_OV		(1L<<19)	/* Bit 19:	Tx Util Cnt Overflow */
-#define XMT_UTIL_UR		(1L<<18)	/* Bit 18:	Tx Util Cnt Underrun */
-#define XMT_CS_ERR_OV	(1L<<17)	/* Bit 17:	Tx Carr Sen Err Cnt Ov*/
-#define XMT_FIFO_UR_OV	(1L<<16)	/* Bit 16:	Tx FIFO Ur Ev Cnt Ov */
-#define XMT_EX_DEF_OV	(1L<<15)	/* Bit 15:	Tx Ex Deferall Cnt Ov */
-#define XMT_DEF			(1L<<14)	/* Bit 14:	Tx Deferred Cnt Ov */
-#define XMT_LAT_COL_OV	(1L<<13)	/* Bit 13:	Tx Late Col Cnt Ov */
-#define XMT_ABO_COL_OV	(1L<<12)	/* Bit 12:	Tx abo dueto Ex Col Ov*/
-#define XMT_MUL_COL_OV	(1L<<11)	/* Bit 11:	Tx Mult Col Cnt Ov */
-#define XMT_SNG_COL		(1L<<10)	/* Bit 10:	Tx Single Col Cnt Ov */
-#define XMT_MCTRL_OV	(1L<<9)		/* Bit  9:	Tx MAC Ctrl Counter Ov*/
-#define XMT_MPAUSE		(1L<<8)		/* Bit  8:	Tx Pause MAC Ctrl-F Ov*/
-#define XMT_BURST		(1L<<7)		/* Bit  7:	Tx Burst Event Cnt Ov */
-#define XMT_LONG		(1L<<6)		/* Bit  6:	Tx Long Frame Cnt Ov */
-#define XMT_UC_OK_OV	(1L<<5)		/* Bit  5:	Tx Unicast Cnt Ov */
-#define XMT_MC_OK_OV	(1L<<4)		/* Bit  4:	Tx Multicast Cnt Ov */
-#define XMT_BC_OK_OV	(1L<<3)		/* Bit  3:	Tx Broadcast Cnt Ov */
-#define XMT_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Tx OK Low CntOv*/
-#define XMT_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Tx OK Hi Cnt Ov*/
-#define XMT_OK_OV		(1L<<0)		/* Bit  0:	Frames Tx Ok Ov */
-
-#define XMT_DEF_MSK		(XMT_OK_LO_OV | XMT_OK_HI_OV)
-
-/*
- * Receive Frame Status Encoding
- */
-#define XMR_FS_LEN	(0x3fffUL<<18)	/* Bit 31..18:	Rx Frame Length */
-#define XMR_FS_2L_VLAN	(1L<<17)	/* Bit 17:	tagged wh 2Lev VLAN ID*/
-#define XMR_FS_1L_VLAN	(1L<<16)	/* Bit 16:	tagged wh 1Lev VLAN ID*/
-#define XMR_FS_BC		(1L<<15)	/* Bit 15:	Broadcast Frame */
-#define XMR_FS_MC		(1L<<14)	/* Bit 14:	Multicast Frame */
-#define XMR_FS_UC		(1L<<13)	/* Bit 13:	Unicast Frame */
-									/* Bit 12:	reserved */
-#define XMR_FS_BURST	(1L<<11)	/* Bit 11:	Burst Mode */
-#define XMR_FS_CEX_ERR	(1L<<10)	/* Bit 10:	Carrier Ext. Error */
-#define XMR_FS_802_3	(1L<<9)		/* Bit  9:	802.3 Frame */
-#define XMR_FS_COL_ERR	(1L<<8)		/* Bit  8:	Collision Error */
-#define XMR_FS_CAR_ERR	(1L<<7)		/* Bit  7:	Carrier Event Error */
-#define XMR_FS_LEN_ERR	(1L<<6)		/* Bit  6:	In-Range Length Error */
-#define XMR_FS_FRA_ERR	(1L<<5)		/* Bit  5:	Framing Error */
-#define XMR_FS_RUNT		(1L<<4)		/* Bit  4:	Runt Frame */
-#define XMR_FS_LNG_ERR	(1L<<3)		/* Bit  3:	Giant (Jumbo) Frame */
-#define XMR_FS_FCS_ERR	(1L<<2)		/* Bit  2:	Frame Check Sequ Err */
-#define XMR_FS_ERR		(1L<<1)		/* Bit  1:	Frame Error */
-#define XMR_FS_MCTRL	(1L<<0)		/* Bit  0:	MAC Control Packet */
-
-/*
- * XMR_FS_ERR will be set if
- *	XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
- *	XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
- * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
- * XMR_FS_ERR unless the corresponding bit in the Receive Command
- * Register is set.
- */
-#define XMR_FS_ANY_ERR	XMR_FS_ERR
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC-PHY Registers, indirect addressed over the XMAC
- */
-#define PHY_XMAC_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_XMAC_STAT		0x01	/* 16 bit r/w	PHY Status Register */
-#define PHY_XMAC_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_XMAC_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_XMAC_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_XMAC_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Abi Reg */
-#define PHY_XMAC_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_XMAC_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_XMAC_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* 0x09 - 0x0e:		reserved */
-#define PHY_XMAC_EXT_STAT	0x0f	/* 16 bit r/o	Ext Status Register */
-#define PHY_XMAC_RES_ABI	0x10	/* 16 bit r/o	PHY Resolved Ability */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Broadcom-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_BCOM_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_BCOM_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_BCOM_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_BCOM_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_BCOM_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_BCOM_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_BCOM_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_BCOM_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_BCOM_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Broadcom-specific registers */
-#define PHY_BCOM_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
-#define PHY_BCOM_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b - 0x0e:		reserved */
-#define PHY_BCOM_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_BCOM_P_EXT_CTRL	0x10	/* 16 bit r/w	PHY Extended Ctrl Reg */
-#define PHY_BCOM_P_EXT_STAT	0x11	/* 16 bit r/o	PHY Extended Stat Reg */
-#define PHY_BCOM_RE_CTR		0x12	/* 16 bit r/w	Receive Error Counter */
-#define PHY_BCOM_FC_CTR		0x13	/* 16 bit r/w	False Carrier Sense Cnt */
-#define PHY_BCOM_RNO_CTR	0x14	/* 16 bit r/w	Receiver NOT_OK Cnt */
-	/* 0x15 - 0x17:		reserved */
-#define PHY_BCOM_AUX_CTRL	0x18	/* 16 bit r/w	Auxiliary Control Reg */
-#define PHY_BCOM_AUX_STAT	0x19	/* 16 bit r/o	Auxiliary Stat Summary */
-#define PHY_BCOM_INT_STAT	0x1a	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_BCOM_INT_MASK	0x1b	/* 16 bit r/w	Interrupt Mask Reg */
-	/* 0x1c:		reserved */
-	/* 0x1d - 0x1f:		test registers */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Marvel-PHY Registers, indirect addressed over GMAC
- */
-#define PHY_MARV_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_MARV_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_MARV_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_MARV_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_MARV_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_MARV_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_MARV_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_MARV_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_MARV_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Marvel-specific registers */
-#define PHY_MARV_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
-#define PHY_MARV_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b - 0x0e:		reserved */
-#define PHY_MARV_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_MARV_PHY_CTRL	0x10	/* 16 bit r/w	PHY Specific Ctrl Reg */
-#define PHY_MARV_PHY_STAT	0x11	/* 16 bit r/o	PHY Specific Stat Reg */
-#define PHY_MARV_INT_MASK	0x12	/* 16 bit r/w	Interrupt Mask Reg */
-#define PHY_MARV_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_MARV_EXT_CTRL	0x14	/* 16 bit r/w	Ext. PHY Specific Ctrl */
-#define PHY_MARV_RXE_CNT	0x15	/* 16 bit r/w	Receive Error Counter */
-#define PHY_MARV_EXT_ADR	0x16	/* 16 bit r/w	Ext. Ad. for Cable Diag. */
-	/* 0x17:		reserved */
-#define PHY_MARV_LED_CTRL	0x18	/* 16 bit r/w	LED Control Reg */
-#define PHY_MARV_LED_OVER	0x19	/* 16 bit r/w	Manual LED Override Reg */
-#define PHY_MARV_EXT_CTRL_2	0x1a	/* 16 bit r/w	Ext. PHY Specific Ctrl 2 */
-#define PHY_MARV_EXT_P_STAT	0x1b	/* 16 bit r/w	Ext. PHY Spec. Stat Reg */
-#define PHY_MARV_CABLE_DIAG	0x1c	/* 16 bit r/o	Cable Diagnostic Reg */
-	/* 0x1d - 0x1f:		reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Level One-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_LONE_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_LONE_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_LONE_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_LONE_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_LONE_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_LONE_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_LONE_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_LONE_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_LONE_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Level One-specific registers */
-#define PHY_LONE_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg*/
-#define PHY_LONE_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b -0x0e:		reserved */
-#define PHY_LONE_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_LONE_PORT_CFG	0x10	/* 16 bit r/w	Port Configuration Reg*/
-#define PHY_LONE_Q_STAT		0x11	/* 16 bit r/o	Quick Status Reg */
-#define PHY_LONE_INT_ENAB	0x12	/* 16 bit r/w	Interrupt Enable Reg */
-#define PHY_LONE_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_LONE_LED_CFG	0x14	/* 16 bit r/w	LED Configuration Reg */
-#define PHY_LONE_PORT_CTRL	0x15	/* 16 bit r/w	Port Control Reg */
-#define PHY_LONE_CIM		0x16	/* 16 bit r/o	CIM Reg */
-	/* 0x17 -0x1c:		reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * National-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_NAT_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_NAT_STAT		0x01	/* 16 bit r/w	PHY Status Register */
-#define PHY_NAT_ID0			0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_NAT_ID1			0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_NAT_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_NAT_AUNE_LP		0x05	/* 16 bit r/o	Link Partner Ability Reg */
-#define PHY_NAT_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_NAT_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_NAT_NEPG_LP		0x08	/* 16 bit r/o	Next Page Link Partner Reg */
-	/* National-specific registers */
-#define PHY_NAT_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
-#define PHY_NAT_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b -0x0e:		reserved */
-#define PHY_NAT_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Register */
-#define PHY_NAT_EXT_CTRL1	0x10	/* 16 bit r/o	Extended Control Reg1 */
-#define PHY_NAT_Q_STAT1		0x11	/* 16 bit r/o	Quick Status Reg1 */
-#define PHY_NAT_10B_OP		0x12	/* 16 bit r/o	10Base-T Operations Reg */
-#define PHY_NAT_EXT_CTRL2	0x13	/* 16 bit r/o	Extended Control Reg1 */
-#define PHY_NAT_Q_STAT2		0x14	/* 16 bit r/o	Quick Status Reg2 */
-	/* 0x15 -0x18:		reserved */
-#define PHY_NAT_PHY_ADDR	0x19	/* 16 bit r/o	PHY Address Register */
-
-
-/*----------------------------------------------------------------------------*/
-
-/*
- * PHY bit definitions
- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
- * XMAC/Broadcom/LevelOne/National/Marvell-specific.
- * All other are general.
- */
-
-/*****  PHY_XMAC_CTRL	16 bit r/w	PHY Control Register *****/
-/*****  PHY_BCOM_CTRL	16 bit r/w	PHY Control Register *****/
-/*****  PHY_MARV_CTRL	16 bit r/w	PHY Status Register *****/
-/*****  PHY_LONE_CTRL	16 bit r/w	PHY Control Register *****/
-#define PHY_CT_RESET	(1<<15)	/* Bit 15: (sc)	clear all PHY related regs */
-#define PHY_CT_LOOP		(1<<14)	/* Bit 14:	enable Loopback over PHY */
-#define PHY_CT_SPS_LSB	(1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
-#define PHY_CT_ANE		(1<<12)	/* Bit 12:	Auto-Negotiation Enabled */
-#define PHY_CT_PDOWN	(1<<11)	/* Bit 11: (BC,L1) Power Down Mode */
-#define PHY_CT_ISOL		(1<<10)	/* Bit 10: (BC,L1) Isolate Mode */
-#define PHY_CT_RE_CFG	(1<<9)	/* Bit  9: (sc) Restart Auto-Negotiation */
-#define PHY_CT_DUP_MD	(1<<8)	/* Bit  8:	Duplex Mode */
-#define PHY_CT_COL_TST	(1<<7)	/* Bit  7: (BC,L1) Collision Test enabled */
-#define PHY_CT_SPS_MSB	(1<<6)	/* Bit  6: (BC,L1) Speed select, upper bit */
-								/* Bit  5..0:	reserved */
-
-#define PHY_CT_SP1000	PHY_CT_SPS_MSB	/* enable speed of 1000 Mbps */
-#define PHY_CT_SP100	PHY_CT_SPS_LSB	/* enable speed of  100 Mbps */
-#define PHY_CT_SP10		(0)				/* enable speed of   10 Mbps */
-
-
-/*****  PHY_XMAC_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_BCOM_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_MARV_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_LONE_STAT	16 bit r/w	PHY Status Register *****/
-								/* Bit 15..9:	reserved */
-				/*	(BC/L1) 100/10 Mbps cap bits ignored*/
-#define PHY_ST_EXT_ST	(1<<8)	/* Bit  8:	Extended Status Present */
-								/* Bit  7:	reserved */
-#define PHY_ST_PRE_SUP	(1<<6)	/* Bit  6: (BC/L1) preamble suppression */
-#define PHY_ST_AN_OVER	(1<<5)	/* Bit  5:	Auto-Negotiation Over */
-#define PHY_ST_REM_FLT	(1<<4)	/* Bit  4:	Remote Fault Condition Occured */
-#define PHY_ST_AN_CAP	(1<<3)	/* Bit  3:	Auto-Negotiation Capability */
-#define PHY_ST_LSYNC	(1<<2)	/* Bit  2:	Link Synchronized */
-#define PHY_ST_JAB_DET	(1<<1)	/* Bit  1: (BC/L1) Jabber Detected */
-#define PHY_ST_EXT_REG	(1<<0)	/* Bit  0:	Extended Register available */
-
-
-/*****	PHY_XMAC_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_BCOM_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_MARV_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_LONE_ID1		16 bit r/o	PHY ID1 Register */
-#define PHY_I1_OUI_MSK	(0x3f<<10)	/* Bit 15..10:	Organization Unique ID */
-#define PHY_I1_MOD_NUM	(0x3f<<4)	/* Bit  9.. 4:	Model Number */
-#define PHY_I1_REV_MSK	0x0f		/* Bit  3.. 0:	Revision Number */
-
-/* different Broadcom PHY Ids */
-#define PHY_BCOM_ID1_A1		0x6041
-#define PHY_BCOM_ID1_B2		0x6043
-#define PHY_BCOM_ID1_C0		0x6044
-#define PHY_BCOM_ID1_C5		0x6047
-
-
-/*****  PHY_XMAC_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_XMAC_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-#define PHY_AN_NXT_PG	(1<<15)	/* Bit 15:	Request Next Page */
-#define PHY_X_AN_ACK	(1<<14)	/* Bit 14: (ro)	Acknowledge Received */
-#define PHY_X_AN_RFB	(3<<12)	/* Bit 13..12:	Remote Fault Bits */
-								/* Bit 11.. 9:	reserved */
-#define PHY_X_AN_PAUSE	(3<<7)	/* Bit  8.. 7:	Pause Bits */
-#define PHY_X_AN_HD		(1<<6)	/* Bit  6:	Half Duplex */
-#define PHY_X_AN_FD		(1<<5)	/* Bit  5:	Full Duplex */
-								/* Bit  4.. 0:	reserved */
-
-/*****  PHY_BCOM_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_BCOM_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_B_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_B_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
-#define PHY_B_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_B_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/*****  PHY_LONE_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_LONE_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_L_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_L_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
-#define PHY_L_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_L_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/*****  PHY_NAT_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_NAT_AUNE_LP		16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_N_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_N_AN_100F	(1<<11)	/* Bit 11:	100Base-T2 FD Support */
-#define PHY_N_AN_100H	(1<<10)	/* Bit 10:	100Base-T2 HD Support */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_N_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/* field type definition for PHY_x_AN_SEL */
-#define PHY_SEL_TYPE	0x01	/* 00001 = Ethernet */
-
-/*****  PHY_XMAC_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-								/* Bit 15..4:	reserved */
-#define PHY_ANE_LP_NP	(1<<3)	/* Bit  3:	Link Partner can Next Page */
-#define PHY_ANE_LOC_NP	(1<<2)	/* Bit  2:	Local PHY can Next Page */
-#define PHY_ANE_RX_PG	(1<<1)	/* Bit  1:	Page Received */
-								/* Bit  0:	reserved */
-
-/*****  PHY_BCOM_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-/*****  PHY_LONE_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-/*****  PHY_MARV_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-								/* Bit 15..5:	reserved */
-#define PHY_ANE_PAR_DF	(1<<4)	/* Bit  4:	Parallel Detection Fault */
-/*	PHY_ANE_LP_NP		(see XMAC) Bit  3:	Link Partner can Next Page */
-/*	PHY_ANE_LOC_NP		(see XMAC) Bit  2:	Local PHY can Next Page */
-/*	PHY_ANE_RX_PG		(see XMAC) Bit  1:	Page Received */
-#define PHY_ANE_LP_CAP	(1<<0)	/* Bit  0:	Link Partner Auto-Neg. Cap. */ 	
-
-/*****  PHY_XMAC_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_BCOM_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_LONE_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_XMAC_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-/*****  PHY_BCOM_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-/*****  PHY_LONE_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-#define PHY_NP_MORE		(1<<15)	/* Bit 15:	More, Next Pages to follow */
-#define PHY_NP_ACK1		(1<<14)	/* Bit 14: (ro)	Ack1, for receiving a message */
-#define PHY_NP_MSG_VAL	(1<<13)	/* Bit 13:	Message Page valid */
-#define PHY_NP_ACK2		(1<<12)	/* Bit 12:	Ack2, comply with msg content */
-#define PHY_NP_TOG		(1<<11)	/* Bit 11:	Toggle Bit, ensure sync */
-#define PHY_NP_MSG		0x07ff	/* Bit 10..0:	Message from/to Link Partner */
-
-/*
- * XMAC-Specific
- */
-/*****  PHY_XMAC_EXT_STAT	16 bit r/w	Extended Status Register *****/
-#define PHY_X_EX_FD		(1<<15)	/* Bit 15:	Device Supports Full Duplex */
-#define PHY_X_EX_HD		(1<<14)	/* Bit 14:	Device Supports Half Duplex */
-								/* Bit 13..0:	reserved */
-
-/*****  PHY_XMAC_RES_ABI	16 bit r/o	PHY Resolved Ability *****/
-								/* Bit 15..9:	reserved */
-#define PHY_X_RS_PAUSE	(3<<7)	/* Bit  8..7:	selected Pause Mode */
-#define PHY_X_RS_HD		(1<<6)	/* Bit  6:	Half Duplex Mode selected */
-#define PHY_X_RS_FD		(1<<5)	/* Bit  5:	Full Duplex Mode selected */
-#define PHY_X_RS_ABLMIS (1<<4)	/* Bit  4:	duplex or pause cap mismatch */
-#define PHY_X_RS_PAUMIS (1<<3)	/* Bit  3:	pause capability mismatch */
-								/* Bit  2..0:	reserved */
-/*
- * Remote Fault Bits (PHY_X_AN_RFB) encoding
- */
-#define X_RFB_OK		(0<<12)	/* Bit 13..12	No errors, Link OK */
-#define X_RFB_LF		(1<<12)	/* Bit 13..12	Link Failure */
-#define X_RFB_OFF		(2<<12)	/* Bit 13..12	Offline */
-#define X_RFB_AN_ERR	(3<<12)	/* Bit 13..12	Auto-Negotiation Error */
-
-/*
- * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
- */
-#define PHY_X_P_NO_PAUSE	(0<<7)	/* Bit  8..7:	no Pause Mode */
-#define PHY_X_P_SYM_MD		(1<<7)	/* Bit  8..7:	symmetric Pause Mode */
-#define PHY_X_P_ASYM_MD		(2<<7)	/* Bit  8..7:	asymmetric Pause Mode */
-#define PHY_X_P_BOTH_MD		(3<<7)	/* Bit  8..7:	both Pause Mode */
-
-
-/*
- * Broadcom-Specific
- */
-/*****  PHY_BCOM_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_B_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_B_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_B_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_B_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_B_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_B_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_BCOM_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-/*****  PHY_MARV_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_B_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_B_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_B_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_B_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
-#define PHY_B_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_B_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-									/* Bit  9..8:	reserved */
-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_BCOM_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_B_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_B_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_B_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_B_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/*****  PHY_BCOM_P_EXT_CTRL	16 bit r/w	PHY Extended Control Reg *****/
-#define PHY_B_PEC_MAC_PHY	(1<<15)	/* Bit 15:	10BIT/GMI-Interface */
-#define PHY_B_PEC_DIS_CROSS	(1<<14)	/* Bit 14:	Disable MDI Crossover */
-#define PHY_B_PEC_TX_DIS	(1<<13)	/* Bit 13:	Tx output Disabled */
-#define PHY_B_PEC_INT_DIS	(1<<12)	/* Bit 12:	Interrupts Disabled */
-#define PHY_B_PEC_F_INT		(1<<11)	/* Bit 11:	Force Interrupt */
-#define PHY_B_PEC_BY_45		(1<<10)	/* Bit 10:	Bypass 4B5B-Decoder */
-#define PHY_B_PEC_BY_SCR	(1<<9)	/* Bit  9:	Bypass Scrambler */
-#define PHY_B_PEC_BY_MLT3	(1<<8)	/* Bit  8:	Bypass MLT3 Encoder */
-#define PHY_B_PEC_BY_RXA	(1<<7)	/* Bit  7:	Bypass Rx Alignm. */
-#define PHY_B_PEC_RES_SCR	(1<<6)	/* Bit  6:	Reset Scrambler */
-#define PHY_B_PEC_EN_LTR	(1<<5)	/* Bit  5:	Ena LED Traffic Mode */
-#define PHY_B_PEC_LED_ON	(1<<4)	/* Bit  4:	Force LED's on */
-#define PHY_B_PEC_LED_OFF	(1<<3)	/* Bit  3:	Force LED's off */
-#define PHY_B_PEC_EX_IPG	(1<<2)	/* Bit  2:	Extend Tx IPG Mode */
-#define PHY_B_PEC_3_LED		(1<<1)	/* Bit  1:	Three Link LED mode */
-#define PHY_B_PEC_HIGH_LA	(1<<0)	/* Bit  0:	GMII FIFO Elasticy */
-
-/*****  PHY_BCOM_P_EXT_STAT	16 bit r/o	PHY Extended Status Reg *****/
-									/* Bit 15..14:	reserved */
-#define PHY_B_PES_CROSS_STAT	(1<<13)	/* Bit 13:	MDI Crossover Status */
-#define PHY_B_PES_INT_STAT	(1<<12)	/* Bit 12:	Interrupt Status */
-#define PHY_B_PES_RRS		(1<<11)	/* Bit 11:	Remote Receiver Stat. */
-#define PHY_B_PES_LRS		(1<<10)	/* Bit 10:	Local Receiver Stat. */
-#define PHY_B_PES_LOCKED	(1<<9)	/* Bit  9:	Locked */
-#define PHY_B_PES_LS		(1<<8)	/* Bit  8:	Link Status */
-#define PHY_B_PES_RF		(1<<7)	/* Bit  7:	Remote Fault */
-#define PHY_B_PES_CE_ER		(1<<6)	/* Bit  6:	Carrier Ext Error */
-#define PHY_B_PES_BAD_SSD	(1<<5)	/* Bit  5:	Bad SSD */
-#define PHY_B_PES_BAD_ESD	(1<<4)	/* Bit  4:	Bad ESD */
-#define PHY_B_PES_RX_ER		(1<<3)	/* Bit  3:	Receive Error */
-#define PHY_B_PES_TX_ER		(1<<2)	/* Bit  2:	Transmit Error */
-#define PHY_B_PES_LOCK_ER	(1<<1)	/* Bit  1:	Lock Error */
-#define PHY_B_PES_MLT3_ER	(1<<0)	/* Bit  0:	MLT3 code Error */
-
-/*****  PHY_BCOM_FC_CTR		16 bit r/w	False Carrier Counter *****/
-									/* Bit 15..8:	reserved */
-#define PHY_B_FC_CTR		0xff	/* Bit  7..0:	False Carrier Counter */
-
-/*****  PHY_BCOM_RNO_CTR	16 bit r/w	Receive NOT_OK Counter *****/
-#define PHY_B_RC_LOC_MSK	0xff00	/* Bit 15..8:	Local Rx NOT_OK cnt */
-#define PHY_B_RC_REM_MSK	0x00ff	/* Bit  7..0:	Remote Rx NOT_OK cnt */
-
-/*****  PHY_BCOM_AUX_CTRL	16 bit r/w	Auxiliary Control Reg *****/
-#define PHY_B_AC_L_SQE		(1<<15)	/* Bit 15:	Low Squelch */
-#define PHY_B_AC_LONG_PACK	(1<<14)	/* Bit 14:	Rx Long Packets */
-#define PHY_B_AC_ER_CTRL	(3<<12)	/* Bit 13..12:	Edgerate Control */
-									/* Bit 11:	reserved */
-#define PHY_B_AC_TX_TST		(1<<10) /* Bit 10:	Tx test bit, always 1 */
-									/* Bit  9.. 8:	reserved */
-#define PHY_B_AC_DIS_PRF	(1<<7)	/* Bit  7:	dis part resp filter */
-									/* Bit  6:	reserved */
-#define PHY_B_AC_DIS_PM		(1<<5)	/* Bit  5:	dis power management */
-									/* Bit  4:	reserved */
-#define PHY_B_AC_DIAG		(1<<3)	/* Bit  3:	Diagnostic Mode */
-									/* Bit  2.. 0:	reserved */
-
-/*****  PHY_BCOM_AUX_STAT	16 bit r/o	Auxiliary Status Reg *****/
-#define PHY_B_AS_AN_C		(1<<15)	/* Bit 15:	AutoNeg complete */
-#define PHY_B_AS_AN_CA		(1<<14)	/* Bit 14:	AN Complete Ack */
-#define PHY_B_AS_ANACK_D	(1<<13)	/* Bit 13:	AN Ack Detect */
-#define PHY_B_AS_ANAB_D		(1<<12)	/* Bit 12:	AN Ability Detect */
-#define PHY_B_AS_NPW		(1<<11)	/* Bit 11:	AN Next Page Wait */
-#define PHY_B_AS_AN_RES_MSK	(7<<8)	/* Bit 10..8:	AN HDC */
-#define PHY_B_AS_PDF		(1<<7)	/* Bit  7:	Parallel Detect. Fault */
-#define PHY_B_AS_RF			(1<<6)	/* Bit  6:	Remote Fault */
-#define PHY_B_AS_ANP_R		(1<<5)	/* Bit  5:	AN Page Received */
-#define PHY_B_AS_LP_ANAB	(1<<4)	/* Bit  4:	LP AN Ability */
-#define PHY_B_AS_LP_NPAB	(1<<3)	/* Bit  3:	LP Next Page Ability */
-#define PHY_B_AS_LS			(1<<2)	/* Bit  2:	Link Status */
-#define PHY_B_AS_PRR		(1<<1)	/* Bit  1:	Pause Resolution-Rx */
-#define PHY_B_AS_PRT		(1<<0)	/* Bit  0:	Pause Resolution-Tx */
-
-#define PHY_B_AS_PAUSE_MSK	(PHY_B_AS_PRR | PHY_B_AS_PRT)
-
-/*****  PHY_BCOM_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-/*****  PHY_BCOM_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
-									/* Bit 15:	reserved */
-#define PHY_B_IS_PSE		(1<<14)	/* Bit 14:	Pair Swap Error */
-#define PHY_B_IS_MDXI_SC	(1<<13)	/* Bit 13:	MDIX Status Change */
-#define PHY_B_IS_HCT		(1<<12)	/* Bit 12:	counter above 32k */
-#define PHY_B_IS_LCT		(1<<11)	/* Bit 11:	counter above 128 */
-#define PHY_B_IS_AN_PR		(1<<10)	/* Bit 10:	Page Received */
-#define PHY_B_IS_NO_HDCL	(1<<9)	/* Bit  9:	No HCD Link */
-#define PHY_B_IS_NO_HDC		(1<<8)	/* Bit  8:	No HCD */
-#define PHY_B_IS_NEG_USHDC	(1<<7)	/* Bit  7:	Negotiated Unsup. HCD */
-#define PHY_B_IS_SCR_S_ER	(1<<6)	/* Bit  6:	Scrambler Sync Error */
-#define PHY_B_IS_RRS_CHANGE	(1<<5)	/* Bit  5:	Remote Rx Stat Change */
-#define PHY_B_IS_LRS_CHANGE	(1<<4)	/* Bit  4:	Local Rx Stat Change */
-#define PHY_B_IS_DUP_CHANGE	(1<<3)	/* Bit  3:	Duplex Mode Change */
-#define PHY_B_IS_LSP_CHANGE	(1<<2)	/* Bit  2:	Link Speed Change */
-#define PHY_B_IS_LST_CHANGE	(1<<1)	/* Bit  1:	Link Status Changed */
-#define PHY_B_IS_CRC_ER		(1<<0)	/* Bit  0:	CRC Error */
-
-#define PHY_B_DEF_MSK	(~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
-
-/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
-#define PHY_B_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
-#define PHY_B_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
-#define PHY_B_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
-#define PHY_B_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
-
-/*
- * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
- */
-#define PHY_B_RES_1000FD	(7<<8)	/* Bit 10..8:	1000Base-T Full Dup. */
-#define PHY_B_RES_1000HD	(6<<8)	/* Bit 10..8:	1000Base-T Half Dup. */
-/* others: 100/10: invalid for us */
-
-/*
- * Level One-Specific
- */
-/*****  PHY_LONE_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_L_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_L_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_L_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_L_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_L_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_L_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_LONE_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_L_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_L_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_L_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_L_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
-#define PHY_L_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_L_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-									/* Bit  9..8:	reserved */
-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_LONE_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_L_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_L_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_L_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_L_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/*****  PHY_LONE_PORT_CFG	16 bit r/w	Port Configuration Reg *****/
-#define PHY_L_PC_REP_MODE	(1<<15)	/* Bit 15:	Repeater Mode */
-									/* Bit 14:	reserved */
-#define PHY_L_PC_TX_DIS		(1<<13)	/* Bit 13:	Tx output Disabled */
-#define PHY_L_PC_BY_SCR		(1<<12)	/* Bit 12:	Bypass Scrambler */
-#define PHY_L_PC_BY_45		(1<<11)	/* Bit 11:	Bypass 4B5B-Decoder */
-#define PHY_L_PC_JAB_DIS	(1<<10)	/* Bit 10:	Jabber Disabled */
-#define PHY_L_PC_SQE		(1<<9)	/* Bit  9:	Enable Heartbeat */
-#define PHY_L_PC_TP_LOOP	(1<<8)	/* Bit  8:	TP Loopback */
-#define PHY_L_PC_SSS		(1<<7)	/* Bit  7:	Smart Speed Selection */
-#define PHY_L_PC_FIFO_SIZE	(1<<6)	/* Bit  6:	FIFO Size */
-#define PHY_L_PC_PRE_EN		(1<<5)	/* Bit  5:	Preamble Enable */
-#define PHY_L_PC_CIM		(1<<4)	/* Bit  4:	Carrier Integrity Mon */
-#define PHY_L_PC_10_SER		(1<<3)	/* Bit  3:	Use Serial Output */
-#define PHY_L_PC_ANISOL		(1<<2)	/* Bit  2:	Unisolate Port */
-#define PHY_L_PC_TEN_BIT	(1<<1)	/* Bit  1:	10bit iface mode on */
-#define PHY_L_PC_ALTCLOCK	(1<<0)	/* Bit  0: (ro)	ALTCLOCK Mode on */
-
-/*****  PHY_LONE_Q_STAT		16 bit r/o	Quick Status Reg *****/
-#define PHY_L_QS_D_RATE		(3<<14)	/* Bit 15..14:	Data Rate */
-#define PHY_L_QS_TX_STAT	(1<<13)	/* Bit 13:	Transmitting */
-#define PHY_L_QS_RX_STAT	(1<<12)	/* Bit 12:	Receiving */
-#define PHY_L_QS_COL_STAT	(1<<11)	/* Bit 11:	Collision */
-#define PHY_L_QS_L_STAT		(1<<10)	/* Bit 10:	Link is up */
-#define PHY_L_QS_DUP_MOD	(1<<9)	/* Bit  9:	Full/Half Duplex */
-#define PHY_L_QS_AN			(1<<8)	/* Bit  8:	AutoNeg is On */
-#define PHY_L_QS_AN_C		(1<<7)	/* Bit  7:	AN is Complete */
-#define PHY_L_QS_LLE		(7<<4)	/* Bit  6:	Line Length Estim. */
-#define PHY_L_QS_PAUSE		(1<<3)	/* Bit  3:	LP advertised Pause */
-#define PHY_L_QS_AS_PAUSE	(1<<2)	/* Bit  2:	LP adv. asym. Pause */
-#define PHY_L_QS_ISOLATE	(1<<1)	/* Bit  1:	CIM Isolated */
-#define PHY_L_QS_EVENT		(1<<0)	/* Bit  0:	Event has occurred */
-
-/*****  PHY_LONE_INT_ENAB	16 bit r/w	Interrupt Enable Reg *****/
-/*****  PHY_LONE_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-									/* Bit 15..14:	reserved */
-#define PHY_L_IS_AN_F		(1<<13)	/* Bit 13:	Auto-Negotiation fault */
-									/* Bit 12:	not described */
-#define PHY_L_IS_CROSS		(1<<11)	/* Bit 11:	Crossover used */
-#define PHY_L_IS_POL		(1<<10)	/* Bit 10:	Polarity correct. used */
-#define PHY_L_IS_SS			(1<<9)	/* Bit  9:	Smart Speed Downgrade */
-#define PHY_L_IS_CFULL		(1<<8)	/* Bit  8:	Counter Full */
-#define PHY_L_IS_AN_C		(1<<7)	/* Bit  7:	AutoNeg Complete */
-#define PHY_L_IS_SPEED		(1<<6)	/* Bit  6:	Speed Changed */
-#define PHY_L_IS_DUP		(1<<5)	/* Bit  5:	Duplex Changed */
-#define PHY_L_IS_LS			(1<<4)	/* Bit  4:	Link Status Changed */
-#define PHY_L_IS_ISOL		(1<<3)	/* Bit  3:	Isolate Occured */
-#define PHY_L_IS_MDINT		(1<<2)	/* Bit  2: (ro)	STAT: MII Int Pending */
-#define PHY_L_IS_INTEN		(1<<1)	/* Bit  1:	ENAB: Enable IRQs */
-#define PHY_L_IS_FORCE		(1<<0)	/* Bit  0:	ENAB: Force Interrupt */
-
-/* int. mask */
-#define PHY_L_DEF_MSK		(PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
-
-/*****  PHY_LONE_LED_CFG	16 bit r/w	LED Configuration Reg *****/
-#define PHY_L_LC_LEDC		(3<<14)	/* Bit 15..14:	Col/Blink/On/Off */
-#define PHY_L_LC_LEDR		(3<<12)	/* Bit 13..12:	Rx/Blink/On/Off */
-#define PHY_L_LC_LEDT		(3<<10)	/* Bit 11..10:	Tx/Blink/On/Off */
-#define PHY_L_LC_LEDG		(3<<8)	/* Bit  9..8:	Giga/Blink/On/Off */
-#define PHY_L_LC_LEDS		(3<<6)	/* Bit  7..6:	10-100/Blink/On/Off */
-#define PHY_L_LC_LEDL		(3<<4)	/* Bit  5..4:	Link/Blink/On/Off */
-#define PHY_L_LC_LEDF		(3<<2)	/* Bit  3..2:	Duplex/Blink/On/Off */
-#define PHY_L_LC_PSTRECH	(1<<1)	/* Bit  1:	Strech LED Pulses */
-#define PHY_L_LC_FREQ		(1<<0)	/* Bit  0:	30/100 ms */
-
-/*****  PHY_LONE_PORT_CTRL	16 bit r/w	Port Control Reg *****/
-#define PHY_L_PC_TX_TCLK	(1<<15)	/* Bit 15:	Enable TX_TCLK */
-									/* Bit 14:	reserved */
-#define PHY_L_PC_ALT_NP		(1<<13)	/* Bit 14:	Alternate Next Page */
-#define PHY_L_PC_GMII_ALT	(1<<12)	/* Bit 13:	Alternate GMII driver */
-									/* Bit 11:	reserved */
-#define PHY_L_PC_TEN_CRS	(1<<10)	/* Bit 10:	Extend CRS*/
-									/* Bit  9..0:	not described */
-
-/*****  PHY_LONE_CIM		16 bit r/o	CIM Reg *****/
-#define PHY_L_CIM_ISOL		(255<<8)/* Bit 15..8:	Isolate Count */
-#define PHY_L_CIM_FALSE_CAR	(255<<0)/* Bit  7..0:	False Carrier Count */
-
-
-/*
- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
- */
-#define PHY_L_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
-#define PHY_L_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
-#define PHY_L_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
-#define PHY_L_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
-
-
-/*
- * National-Specific
- */
-/*****  PHY_NAT_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_N_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_N_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_N_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_N_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_N_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_N_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-#define PHY_N_1000C_APC		(1<<7)	/* Bit  7:	Asymmetric Pause Cap. */
-									/* Bit  6..0:	reserved */
-
-/*****  PHY_NAT_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_N_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_N_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_N_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_N_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status*/
-#define PHY_N_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_N_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-#define PHY_N_1000C_LP_APC	(1<<9)	/* Bit  9:	LP Asym. Pause Cap. */
-									/* Bit  8:	reserved */
-#define PHY_N_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_NAT_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_N_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_N_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_N_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_N_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/* todo: those are still missing */
-/*****  PHY_NAT_EXT_CTRL1	16 bit r/o	Extended Control Reg1 *****/
-/*****  PHY_NAT_Q_STAT1		16 bit r/o	Quick Status Reg1 *****/
-/*****  PHY_NAT_10B_OP		16 bit r/o	10Base-T Operations Reg *****/
-/*****  PHY_NAT_EXT_CTRL2	16 bit r/o	Extended Control Reg1 *****/
-/*****  PHY_NAT_Q_STAT2		16 bit r/o	Quick Status Reg2 *****/
-/*****  PHY_NAT_PHY_ADDR	16 bit r/o	PHY Address Register *****/
-
-/*
- * Marvell-Specific
- */
-/*****  PHY_MARV_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_MARV_AUNE_LP	16 bit r/w	Link Part Ability Reg *****/
-#define PHY_M_AN_NXT_PG		BIT_15	/* Request Next Page */
-#define PHY_M_AN_ACK		BIT_14	/* (ro)	Acknowledge Received */
-#define PHY_M_AN_RF			BIT_13	/* Remote Fault */
-									/* Bit 12:	reserved */
-#define PHY_M_AN_ASP		BIT_11	/* Asymmetric Pause */
-#define PHY_M_AN_PC			BIT_10	/* MAC Pause implemented */
-#define PHY_M_AN_100_FD		BIT_8	/* Advertise 100Base-TX Full Duplex */
-#define PHY_M_AN_100_HD		BIT_7	/* Advertise 100Base-TX Half Duplex */
-#define PHY_M_AN_10_FD		BIT_6	/* Advertise 10Base-TX Full Duplex */
-#define PHY_M_AN_10_HD		BIT_5	/* Advertise 10Base-TX Half Duplex */
-
-/* special defines for FIBER (88E1011S only) */
-#define PHY_M_AN_ASP_X		BIT_8	/* Asymmetric Pause */
-#define PHY_M_AN_PC_X		BIT_7	/* MAC Pause implemented */
-#define PHY_M_AN_1000X_AHD	BIT_6	/* Advertise 10000Base-X Half Duplex */
-#define PHY_M_AN_1000X_AFD	BIT_5	/* Advertise 10000Base-X Full Duplex */
-
-/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
-#define PHY_M_P_NO_PAUSE_X	(0<<7)	/* Bit  8.. 7:	no Pause Mode */
-#define PHY_M_P_SYM_MD_X	(1<<7)	/* Bit  8.. 7:	symmetric Pause Mode */
-#define PHY_M_P_ASYM_MD_X	(2<<7)	/* Bit  8.. 7:	asymmetric Pause Mode */
-#define PHY_M_P_BOTH_MD_X	(3<<7)	/* Bit  8.. 7:	both Pause Mode */
-
-/*****  PHY_MARV_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_M_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_M_1000C_MSE		(1<<12)	/* Bit 12:	Manual Master/Slave Enable */
-#define PHY_M_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration (1=Master) */
-#define PHY_M_1000C_MPD		(1<<10)	/* Bit 10:	Multi-Port Device */
-#define PHY_M_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_M_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_MARV_PHY_CTRL	16 bit r/w	PHY Specific Ctrl Reg *****/
-#define PHY_M_PC_TX_FFD_MSK	(3<<14)	/* Bit 15..14:	Tx FIFO Depth Mask */
-#define PHY_M_PC_RX_FFD_MSK	(3<<12)	/* Bit 13..12:	Rx FIFO Depth Mask */
-#define PHY_M_PC_ASS_CRS_TX	(1<<11)	/* Bit 11:	Assert CRS on Transmit */
-#define PHY_M_PC_FL_GOOD	(1<<10)	/* Bit 10:	Force Link Good */
-#define PHY_M_PC_EN_DET_MSK	(3<<8)	/* Bit  9.. 8:	Energy Detect Mask */
-#define PHY_M_PC_ENA_EXT_D	(1<<7)	/* Bit  7:	Enable Ext. Distance (10BT) */
-#define PHY_M_PC_MDIX_MSK	(3<<5)	/* Bit  6.. 5:	MDI/MDIX Config. Mask */
-#define PHY_M_PC_DIS_125CLK	(1<<4)	/* Bit  4:	Disable 125 CLK */
-#define PHY_M_PC_MAC_POW_UP	(1<<3)	/* Bit  3:	MAC Power up */
-#define PHY_M_PC_SQE_T_ENA	(1<<2)	/* Bit  2:	SQE Test Enabled */
-#define PHY_M_PC_POL_R_DIS	(1<<1)	/* Bit  1:	Polarity Reversal Disabled */
-#define PHY_M_PC_DIS_JABBER	(1<<0)	/* Bit  0:	Disable Jabber */
-
-#define PHY_M_PC_EN_DET			SHIFT8(2)	/* Energy Detect (Mode 1) */
-#define PHY_M_PC_EN_DET_PLUS	SHIFT8(3)	/* Energy Detect Plus (Mode 2) */
-
-#define PHY_M_PC_MDI_XMODE(x)	SHIFT5(x)	
-#define PHY_M_PC_MAN_MDI	0    	/* 00 = Manual MDI configuration */
-#define PHY_M_PC_MAN_MDIX	1		/* 01 = Manual MDIX configuration */
-#define PHY_M_PC_ENA_AUTO	3		/* 11 = Enable Automatic Crossover */
-
-/*****  PHY_MARV_PHY_STAT	16 bit r/o	PHY Specific Status Reg *****/
-#define PHY_M_PS_SPEED_MSK	(3<<14)	/* Bit 15..14:	Speed Mask */
-#define PHY_M_PS_SPEED_1000	(1<<15)	/*       10 = 1000 Mbps */
-#define PHY_M_PS_SPEED_100	(1<<14)	/*       01 =  100 Mbps */
-#define PHY_M_PS_SPEED_10	0		/*       00 =   10 Mbps */
-#define PHY_M_PS_FULL_DUP	(1<<13)	/* Bit 13:	Full Duplex */
-#define PHY_M_PS_PAGE_REC	(1<<12)	/* Bit 12:	Page Received */
-#define PHY_M_PS_SPDUP_RES	(1<<11)	/* Bit 11:	Speed & Duplex Resolved */
-#define PHY_M_PS_LINK_UP	(1<<10)	/* Bit 10:	Link Up */
-#define PHY_M_PS_CABLE_MSK	(3<<7)	/* Bit  9.. 7:	Cable Length Mask */
-#define PHY_M_PS_MDI_X_STAT	(1<<6)	/* Bit  6:	MDI Crossover Stat (1=MDIX) */
-#define PHY_M_PS_DOWNS_STAT	(1<<5)	/* Bit  5:	Downshift Status (1=downsh.) */
-#define PHY_M_PS_ENDET_STAT	(1<<4)	/* Bit  4:	Energy Detect Status (1=act) */
-#define PHY_M_PS_TX_P_EN	(1<<3)	/* Bit  3:	Tx Pause Enabled */
-#define PHY_M_PS_RX_P_EN	(1<<2)	/* Bit  2:	Rx Pause Enabled */
-#define PHY_M_PS_POL_REV	(1<<1)	/* Bit  1:	Polarity Reversed */
-#define PHY_M_PC_JABBER		(1<<0)	/* Bit  0:	Jabber */
-
-#define PHY_M_PS_PAUSE_MSK	(PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
-
-/*****  PHY_MARV_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
-/*****  PHY_MARV_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-#define PHY_M_IS_AN_ERROR	(1<<15)	/* Bit 15:	Auto-Negotiation Error */
-#define PHY_M_IS_LSP_CHANGE	(1<<14)	/* Bit 14:	Link Speed Changed */
-#define PHY_M_IS_DUP_CHANGE	(1<<13)	/* Bit 13:	Duplex Mode Changed */
-#define PHY_M_IS_AN_PR		(1<<12)	/* Bit 12:	Page Received */
-#define PHY_M_IS_AN_COMPL	(1<<11)	/* Bit 11:	Auto-Negotiation Completed */
-#define PHY_M_IS_LST_CHANGE	(1<<10)	/* Bit 10:	Link Status Changed */
-#define PHY_M_IS_SYMB_ERROR	(1<<9)	/* Bit  9:	Symbol Error */
-#define PHY_M_IS_FALSE_CARR	(1<<8)	/* Bit  8:	False Carrier */
-#define PHY_M_IS_FIFO_ERROR	(1<<7)	/* Bit  7:	FIFO Overflow/Underrun Error */
-#define PHY_M_IS_MDI_CHANGE	(1<<6)	/* Bit  6:	MDI Crossover Changed */
-#define PHY_M_IS_DOWNSH_DET	(1<<5)	/* Bit  5:	Downshift Detected */
-#define PHY_M_IS_END_CHANGE	(1<<4)	/* Bit  4:	Energy Detect Changed */
-									/* Bit  3..2:	reserved */
-#define PHY_M_IS_POL_CHANGE	(1<<1)	/* Bit  1:	Polarity Changed */
-#define PHY_M_IS_JABBER		(1<<0)	/* Bit  0:	Jabber */
-
-#define PHY_M_DEF_MSK		(PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
-							PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
-
-/*****  PHY_MARV_EXT_CTRL	16 bit r/w	Ext. PHY Specific Ctrl *****/
-#define PHY_M_EC_M_DSC_MSK	(3<<10)	/* Bit 11..10:	Master downshift counter */
-#define PHY_M_EC_S_DSC_MSK	(3<<8)	/* Bit  9.. 8:	Slave  downshift counter */
-#define PHY_M_EC_MAC_S_MSK	(7<<4)	/* Bit  6.. 4:	Def. MAC interface speed */
-#define PHY_M_EC_FIB_AN_ENA	(1<<3)	/* Bit  3:	Fiber Auto-Neg. Enable */
-
-#define PHY_M_EC_M_DSC(x)		SHIFT10(x)	/* 00=1x; 01=2x; 10=3x; 11=4x */
-#define PHY_M_EC_S_DSC(x)		SHIFT8(x)	/* 00=dis; 01=1x; 10=2x; 11=3x */
-#define PHY_M_EC_MAC_S(x)		SHIFT4(x)	/* 01X=0; 110=2.5; 111=25 (MHz) */
-
-#define MAC_TX_CLK_0_MHZ	2
-#define MAC_TX_CLK_2_5_MHZ	6
-#define MAC_TX_CLK_25_MHZ	7
-
-/*****  PHY_MARV_LED_CTRL	16 bit r/w	LED Control Reg *****/
-#define PHY_M_LEDC_DIS_LED	(1<<15)	/* Bit 15:	Disable LED */
-#define PHY_M_LEDC_PULS_MSK	(7<<12)	/* Bit 14..12:  Pulse Stretch Mask */
-#define PHY_M_LEDC_F_INT	(1<<11)	/* Bit 11:	Force Interrupt */
-#define PHY_M_LEDC_BL_R_MSK	(7<<8)	/* Bit 10.. 8:  Blink Rate Mask */
-									/* Bit  7.. 5:	reserved */
-#define PHY_M_LEDC_LINK_MSK	(3<<3)	/* Bit  4.. 3:	Link Control Mask */
-#define PHY_M_LEDC_DP_CTRL	(1<<2)	/* Bit  2:	Duplex Control */
-#define PHY_M_LEDC_RX_CTRL	(1<<1)	/* Bit  1:	Rx activity / Link */
-#define PHY_M_LEDC_TX_CTRL	(1<<0)	/* Bit  0:	Tx activity / Link */
-
-#define PHY_M_LED_PULS_DUR(x)	SHIFT12(x)	/* Pulse Stretch Duration */
-
-#define	PULS_NO_STR		0		/* no pulse stretching */
-#define	PULS_21MS		1		/* 21 ms to 42 ms */
-#define PULS_42MS		2		/* 42 ms to 84 ms */
-#define PULS_84MS		3		/* 84 ms to 170 ms */
-#define PULS_170MS		4		/* 170 ms to 340 ms */
-#define PULS_340MS		5		/* 340 ms to 670 ms */
-#define PULS_670MS		6		/* 670 ms to 1.3 s */
-#define PULS_1300MS		7		/* 1.3 s to 2.7 s */
-
-#define PHY_M_LED_BLINK_RT(x)	SHIFT8(x)	/* Blink Rate */
-
-#define BLINK_42MS		0		/* 42 ms */
-#define BLINK_84MS		1		/* 84 ms */
-#define BLINK_170MS		2		/* 170 ms */
-#define BLINK_340MS		3		/* 340 ms */
-#define BLINK_670MS		4		/* 670 ms */
-								/* values 5 - 7: reserved */
-
-/*****  PHY_MARV_LED_OVER	16 bit r/w	Manual LED Override Reg *****/
-#define PHY_M_LED_MO_DUP(x)		SHIFT10(x)	/* Bit 11..10:  Duplex */
-#define PHY_M_LED_MO_10(x)		SHIFT8(x)	/* Bit  9.. 8:  Link 10 */
-#define PHY_M_LED_MO_100(x)		SHIFT6(x)	/* Bit  7.. 6:  Link 100 */
-#define PHY_M_LED_MO_1000(x)	SHIFT4(x)	/* Bit  5.. 4:  Link 1000 */
-#define PHY_M_LED_MO_RX(x)		SHIFT2(x)	/* Bit  3.. 2:  Rx */
-#define PHY_M_LED_MO_TX(x)		SHIFT0(x)	/* Bit  1.. 0:  Tx */
-
-#define MO_LED_NORM			0
-#define MO_LED_BLINK		1
-#define MO_LED_OFF			2
-#define MO_LED_ON			3
-
-/*****  PHY_MARV_EXT_CTRL_2	16 bit r/w	Ext. PHY Specific Ctrl 2 *****/
-									/* Bit 15.. 7:	reserved */
-#define PHY_M_EC2_FI_IMPED	(1<<6)	/* Bit  6:	Fiber Input  Impedance */
-#define PHY_M_EC2_FO_IMPED	(1<<5)	/* Bit  5:	Fiber Output Impedance */
-#define PHY_M_EC2_FO_M_CLK	(1<<4)	/* Bit  4:	Fiber Mode Clock Enable */
-#define PHY_M_EC2_FO_BOOST	(1<<3)	/* Bit  3:	Fiber Output Boost */
-#define PHY_M_EC2_FO_AM_MSK	7		/* Bit  2.. 0:	Fiber Output Amplitude */
-
-/*****	PHY_MARV_EXT_P_STAT 16 bit r/w	Ext. PHY Specific Status *****/
-#define PHY_M_FC_AUTO_SEL	(1<<15)	/* Bit 15:	Fiber/Copper Auto Sel. dis. */
-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14:	Fiber/Copper Autoneg. reg acc */
-#define PHY_M_FC_RESULUTION (1<<13)	/* Bit 13:	Fiber/Copper Resulution */
-#define PHY_M_SER_IF_AN_BP  (1<<12) /* Bit 12:	Ser IF autoneg. bypass enable */
-#define PHY_M_SER_IF_BP_ST	(1<<11) /* Bit 11:	Ser IF autoneg. bypass status */
-#define PHY_M_IRQ_POLARITY	(1<<10) /* Bit 10:	IRQ polarity */
-									/* Bit 9..4: reserved */
-#define PHY_M_UNDOC1		(1<< 7) /* undocumented bit !! */
-#define PHY_M_MODE_MASK		(0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
-
-
-/*****  PHY_MARV_CABLE_DIAG	16 bit r/o	Cable Diagnostic Reg *****/
-#define PHY_M_CABD_ENA_TEST	(1<<15)	/* Bit 15:	Enable Test */
-#define PHY_M_CABD_STAT_MSK	(3<<13)	/* Bit 14..13:	Status */
-									/* Bit 12.. 8:	reserved */
-#define PHY_M_CABD_DIST_MSK	0xff	/* Bit  7.. 0:	Distance */
-
-/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
-#define CABD_STAT_NORMAL	0
-#define CABD_STAT_SHORT		1
-#define CABD_STAT_OPEN		2
-#define CABD_STAT_FAIL		3
-
-
-/*
- * GMAC registers
- *
- * The GMAC registers are 16 or 32 bits wide.
- * The GMACs host processor interface is 16 bits wide,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the GMAC registers
- * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
- * GM_INHASH(), and GM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note:	NA reg	= Network Address e.g DA, SA etc.
- *
- */
-
-/* Port Registers */
-#define GM_GP_STAT		0x0000		/* 16 bit r/o	General Purpose Status */
-#define GM_GP_CTRL		0x0004		/* 16 bit r/w	General Purpose Control */
-#define GM_TX_CTRL		0x0008		/* 16 bit r/w	Transmit Control Reg. */
-#define GM_RX_CTRL		0x000c		/* 16 bit r/w	Receive Control Reg. */
-#define GM_TX_FLOW_CTRL	0x0010		/* 16 bit r/w	Transmit Flow-Control */
-#define GM_TX_PARAM		0x0014		/* 16 bit r/w	Transmit Parameter Reg. */
-#define GM_SERIAL_MODE	0x0018		/* 16 bit r/w	Serial Mode Register */
-
-/* Source Address Registers */
-#define GM_SRC_ADDR_1L	0x001c		/* 16 bit r/w	Source Address 1 (low) */
-#define GM_SRC_ADDR_1M	0x0020		/* 16 bit r/w	Source Address 1 (middle) */
-#define GM_SRC_ADDR_1H	0x0024		/* 16 bit r/w	Source Address 1 (high) */
-#define GM_SRC_ADDR_2L	0x0028		/* 16 bit r/w	Source Address 2 (low) */
-#define GM_SRC_ADDR_2M	0x002c		/* 16 bit r/w	Source Address 2 (middle) */
-#define GM_SRC_ADDR_2H	0x0030		/* 16 bit r/w	Source Address 2 (high) */
-
-/* Multicast Address Hash Registers */
-#define GM_MC_ADDR_H1	0x0034		/* 16 bit r/w	Multicast Address Hash 1 */
-#define GM_MC_ADDR_H2	0x0038		/* 16 bit r/w	Multicast Address Hash 2 */
-#define GM_MC_ADDR_H3	0x003c		/* 16 bit r/w	Multicast Address Hash 3 */
-#define GM_MC_ADDR_H4	0x0040		/* 16 bit r/w	Multicast Address Hash 4 */
-
-/* Interrupt Source Registers */
-#define GM_TX_IRQ_SRC	0x0044		/* 16 bit r/o	Tx Overflow IRQ Source */
-#define GM_RX_IRQ_SRC	0x0048		/* 16 bit r/o	Rx Overflow IRQ Source */
-#define GM_TR_IRQ_SRC	0x004c		/* 16 bit r/o	Tx/Rx Over. IRQ Source */
-
-/* Interrupt Mask Registers */
-#define GM_TX_IRQ_MSK	0x0050		/* 16 bit r/w	Tx Overflow IRQ Mask */
-#define GM_RX_IRQ_MSK	0x0054		/* 16 bit r/w	Rx Overflow IRQ Mask */
-#define GM_TR_IRQ_MSK	0x0058		/* 16 bit r/w	Tx/Rx Over. IRQ Mask */
-
-/* Serial Management Interface (SMI) Registers */
-#define GM_SMI_CTRL		0x0080		/* 16 bit r/w	SMI Control Register */
-#define GM_SMI_DATA		0x0084		/* 16 bit r/w	SMI Data Register */
-#define GM_PHY_ADDR		0x0088		/* 16 bit r/w	GPHY Address Register */
-
-/* MIB Counters */
-#define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
-#define GM_MIB_CNT_SIZE	44			/* Number of MIB Counters */
-
-/*
- * MIB Counters base address definitions (low word) -
- * use offset 4 for access to high word	(32 bit r/o)
- */
-#define GM_RXF_UC_OK \
-			(GM_MIB_CNT_BASE + 0)	/* Unicast Frames Received OK */
-#define GM_RXF_BC_OK \
-			(GM_MIB_CNT_BASE + 8)	/* Broadcast Frames Received OK */
-#define GM_RXF_MPAUSE \
-			(GM_MIB_CNT_BASE + 16)	/* Pause MAC Ctrl Frames Received */
-#define GM_RXF_MC_OK \
-			(GM_MIB_CNT_BASE + 24)	/* Multicast Frames Received OK */
-#define GM_RXF_FCS_ERR \
-			(GM_MIB_CNT_BASE + 32)	/* Rx Frame Check Seq. Error */
-	/* GM_MIB_CNT_BASE + 40:	reserved */
-#define GM_RXO_OK_LO \
-			(GM_MIB_CNT_BASE + 48)	/* Octets Received OK Low */
-#define GM_RXO_OK_HI \
-			(GM_MIB_CNT_BASE + 56)	/* Octets Received OK High */
-#define GM_RXO_ERR_LO \
-			(GM_MIB_CNT_BASE + 64)	/* Octets Received Invalid Low */
-#define GM_RXO_ERR_HI \
-			(GM_MIB_CNT_BASE + 72)	/* Octets Received Invalid High */
-#define GM_RXF_SHT \
-			(GM_MIB_CNT_BASE + 80)	/* Frames <64 Byte Received OK */
-#define GM_RXE_FRAG \
-			(GM_MIB_CNT_BASE + 88)	/* Frames <64 Byte Received with FCS Err */
-#define GM_RXF_64B \
-			(GM_MIB_CNT_BASE + 96)	/* 64 Byte Rx Frame */
-#define GM_RXF_127B \
-			(GM_MIB_CNT_BASE + 104)	/* 65-127 Byte Rx Frame */
-#define GM_RXF_255B \
-			(GM_MIB_CNT_BASE + 112)	/* 128-255 Byte Rx Frame */
-#define GM_RXF_511B \
-			(GM_MIB_CNT_BASE + 120)	/* 256-511 Byte Rx Frame */
-#define GM_RXF_1023B \
-			(GM_MIB_CNT_BASE + 128)	/* 512-1023 Byte Rx Frame */
-#define GM_RXF_1518B \
-			(GM_MIB_CNT_BASE + 136)	/* 1024-1518 Byte Rx Frame */
-#define GM_RXF_MAX_SZ \
-			(GM_MIB_CNT_BASE + 144)	/* 1519-MaxSize Byte Rx Frame */
-#define GM_RXF_LNG_ERR \
-			(GM_MIB_CNT_BASE + 152)	/* Rx Frame too Long Error */
-#define GM_RXF_JAB_PKT \
-			(GM_MIB_CNT_BASE + 160)	/* Rx Jabber Packet Frame */
-	/* GM_MIB_CNT_BASE + 168:	reserved */
-#define GM_RXE_FIFO_OV \
-			(GM_MIB_CNT_BASE + 176)	/* Rx FIFO overflow Event */
-	/* GM_MIB_CNT_BASE + 184:	reserved */
-#define GM_TXF_UC_OK \
-			(GM_MIB_CNT_BASE + 192)	/* Unicast Frames Xmitted OK */
-#define GM_TXF_BC_OK \
-			(GM_MIB_CNT_BASE + 200)	/* Broadcast Frames Xmitted OK */
-#define GM_TXF_MPAUSE \
-			(GM_MIB_CNT_BASE + 208)	/* Pause MAC Ctrl Frames Xmitted */
-#define GM_TXF_MC_OK \
-			(GM_MIB_CNT_BASE + 216)	/* Multicast Frames Xmitted OK */
-#define GM_TXO_OK_LO \
-			(GM_MIB_CNT_BASE + 224)	/* Octets Transmitted OK Low */
-#define GM_TXO_OK_HI \
-			(GM_MIB_CNT_BASE + 232)	/* Octets Transmitted OK High */
-#define GM_TXF_64B \
-			(GM_MIB_CNT_BASE + 240)	/* 64 Byte Tx Frame */
-#define GM_TXF_127B \
-			(GM_MIB_CNT_BASE + 248)	/* 65-127 Byte Tx Frame */
-#define GM_TXF_255B \
-			(GM_MIB_CNT_BASE + 256)	/* 128-255 Byte Tx Frame */
-#define GM_TXF_511B \
-			(GM_MIB_CNT_BASE + 264)	/* 256-511 Byte Tx Frame */
-#define GM_TXF_1023B \
-			(GM_MIB_CNT_BASE + 272)	/* 512-1023 Byte Tx Frame */
-#define GM_TXF_1518B \
-			(GM_MIB_CNT_BASE + 280)	/* 1024-1518 Byte Tx Frame */
-#define GM_TXF_MAX_SZ \
-			(GM_MIB_CNT_BASE + 288)	/* 1519-MaxSize Byte Tx Frame */
-	/* GM_MIB_CNT_BASE + 296:	reserved */
-#define GM_TXF_COL \
-			(GM_MIB_CNT_BASE + 304)	/* Tx Collision */
-#define GM_TXF_LAT_COL \
-			(GM_MIB_CNT_BASE + 312)	/* Tx Late Collision */
-#define GM_TXF_ABO_COL \
-			(GM_MIB_CNT_BASE + 320)	/* Tx aborted due to Exces. Col. */
-#define GM_TXF_MUL_COL \
-			(GM_MIB_CNT_BASE + 328)	/* Tx Multiple Collision */
-#define GM_TXF_SNG_COL \
-			(GM_MIB_CNT_BASE + 336)	/* Tx Single Collision */
-#define GM_TXE_FIFO_UR \
-			(GM_MIB_CNT_BASE + 344)	/* Tx FIFO Underrun Event */
-
-/*----------------------------------------------------------------------------*/
-/*
- * GMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- *	(sc)	self clearing
- *	(r/o)	read only
- */
-
-/*	GM_GP_STAT	16 bit r/o	General Purpose Status Register */
-#define GM_GPSR_SPEED		(1<<15) /* Bit 15:	Port Speed (1 = 100 Mbps) */
-#define GM_GPSR_DUPLEX		(1<<14) /* Bit 14:	Duplex Mode (1 = Full) */
-#define GM_GPSR_FC_TX_DIS	(1<<13) /* Bit 13:	Tx Flow-Control Mode Disabled */
-#define GM_GPSR_LINK_UP		(1<<12)	/* Bit 12:	Link Up Status */
-#define GM_GPSR_PAUSE		(1<<11)	/* Bit 11:	Pause State */
-#define GM_GPSR_TX_ACTIVE	(1<<10)	/* Bit 10:	Tx in Progress */
-#define GM_GPSR_EXC_COL		(1<<9)	/* Bit  9:	Excessive Collisions Occured */
-#define GM_GPSR_LAT_COL		(1<<8)	/* Bit  8:	Late Collisions Occured */
-								/* Bit  7..6:	reserved */
-#define GM_GPSR_PHY_ST_CH	(1<<5)	/* Bit  5:	PHY Status Change */
-#define GM_GPSR_GIG_SPEED	(1<<4)	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
-#define GM_GPSR_PART_MODE	(1<<3)	/* Bit  3:	Partition mode */
-#define GM_GPSR_FC_RX_DIS	(1<<2)	/* Bit  2:	Rx Flow-Control Mode Disabled */
-#define GM_GPSR_PROM_EN		(1<<1)	/* Bit  1:	Promiscuous Mode Enabled */
-								/* Bit  0:	reserved */
-	
-/*	GM_GP_CTRL	16 bit r/w	General Purpose Control Register */
-								/* Bit 15:	reserved */
-#define GM_GPCR_PROM_ENA	(1<<14)	/* Bit 14:	Enable Promiscuous Mode */
-#define GM_GPCR_FC_TX_DIS	(1<<13) /* Bit 13:	Disable Tx Flow-Control Mode */
-#define GM_GPCR_TX_ENA		(1<<12) /* Bit 12:	Enable Transmit */
-#define GM_GPCR_RX_ENA		(1<<11) /* Bit 11:	Enable Receive */
-#define GM_GPCR_BURST_ENA	(1<<10)	/* Bit 10:	Enable Burst Mode */
-#define GM_GPCR_LOOP_ENA	(1<<9)	/* Bit  9:	Enable MAC Loopback Mode */
-#define GM_GPCR_PART_ENA	(1<<8)	/* Bit  8:	Enable Partition Mode */
-#define GM_GPCR_GIGS_ENA	(1<<7)	/* Bit  7:	Gigabit Speed (1000 Mbps) */
-#define GM_GPCR_FL_PASS		(1<<6)	/* Bit  6:	Force Link Pass */
-#define GM_GPCR_DUP_FULL	(1<<5)	/* Bit  5:	Full Duplex Mode */
-#define GM_GPCR_FC_RX_DIS	(1<<4)	/* Bit  4:	Disable Rx Flow-Control Mode */
-#define GM_GPCR_SPEED_100	(1<<3)  /* Bit  3:	Port Speed 100 Mbps */
-#define GM_GPCR_AU_DUP_DIS	(1<<2)	/* Bit  2:	Disable Auto-Update Duplex */
-#define GM_GPCR_AU_FCT_DIS	(1<<1)	/* Bit  1:	Disable Auto-Update Flow-C. */
-#define GM_GPCR_AU_SPD_DIS	(1<<0)	/* Bit  0:	Disable Auto-Update Speed */
-
-#define GM_GPCR_SPEED_1000	(GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
-#define GM_GPCR_AU_ALL_DIS	(GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
-							 GM_GPCR_AU_SPD_DIS)
-	
-/*	GM_TX_CTRL				16 bit r/w	Transmit Control Register */
-#define GM_TXCR_FORCE_JAM	(1<<15)	/* Bit 15:	Force Jam / Flow-Control */
-#define GM_TXCR_CRC_DIS		(1<<14)	/* Bit 14:	Disable insertion of CRC */
-#define GM_TXCR_PAD_DIS		(1<<13)	/* Bit 13:	Disable padding of packets */
-#define GM_TXCR_COL_THR_MSK	(7<<10)	/* Bit 12..10:	Collision Threshold */
-
-#define TX_COL_THR(x)		(SHIFT10(x) & GM_TXCR_COL_THR_MSK)
-
-#define TX_COL_DEF			0x04
-	
-/*	GM_RX_CTRL				16 bit r/w	Receive Control Register */
-#define GM_RXCR_UCF_ENA		(1<<15)	/* Bit 15:	Enable Unicast filtering */
-#define GM_RXCR_MCF_ENA		(1<<14)	/* Bit 14:	Enable Multicast filtering */
-#define GM_RXCR_CRC_DIS		(1<<13)	/* Bit 13:	Remove 4-byte CRC */
-#define GM_RXCR_PASS_FC		(1<<12)	/* Bit 12:	Pass FC packets to FIFO */
-	
-/*	GM_TX_PARAM				16 bit r/w	Transmit Parameter Register */
-#define GM_TXPA_JAMLEN_MSK	(0x03<<14)	/* Bit 15..14:	Jam Length */
-#define GM_TXPA_JAMIPG_MSK	(0x1f<<9)	/* Bit 13..9:	Jam IPG */
-#define GM_TXPA_JAMDAT_MSK	(0x1f<<4)	/* Bit  8..4:	IPG Jam to Data */
-								/* Bit  3..0:	reserved */
-
-#define TX_JAM_LEN_VAL(x)	(SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
-#define TX_JAM_IPG_VAL(x)	(SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
-#define TX_IPG_JAM_DATA(x)	(SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
-
-#define TX_JAM_LEN_DEF		0x03
-#define TX_JAM_IPG_DEF		0x0b
-#define TX_IPG_JAM_DEF		0x1c
-
-/*	GM_SERIAL_MODE			16 bit r/w	Serial Mode Register */
-#define GM_SMOD_DATABL_MSK	(0x1f<<11)	/* Bit 15..11:	Data Blinder (r/o) */
-#define GM_SMOD_LIMIT_4		(1<<10)	/* Bit 10:	4 consecutive Tx trials */
-#define GM_SMOD_VLAN_ENA	(1<<9)	/* Bit  9:	Enable VLAN  (Max. Frame Len) */
-#define GM_SMOD_JUMBO_ENA	(1<<8)	/* Bit  8:	Enable Jumbo (Max. Frame Len) */
-								/* Bit  7..5:	reserved */
-#define GM_SMOD_IPG_MSK		0x1f	/* Bit 4..0:	Inter-Packet Gap (IPG) */
-	
-#define DATA_BLIND_VAL(x)	(SHIFT11(x) & GM_SMOD_DATABL_MSK)
-#define DATA_BLIND_DEF		0x04
-
-#define IPG_DATA_VAL(x)		(x & GM_SMOD_IPG_MSK)
-#define IPG_DATA_DEF		0x1e
-
-/*	GM_SMI_CTRL				16 bit r/w	SMI Control Register */
-#define GM_SMI_CT_PHY_A_MSK	(0x1f<<11)	/* Bit 15..11:	PHY Device Address */
-#define GM_SMI_CT_REG_A_MSK	(0x1f<<6)	/* Bit 10.. 6:	PHY Register Address */
-#define GM_SMI_CT_OP_RD		(1<<5)	/* Bit  5:	OpCode Read (0=Write)*/
-#define GM_SMI_CT_RD_VAL	(1<<4)	/* Bit  4:	Read Valid (Read completed) */
-#define GM_SMI_CT_BUSY		(1<<3)	/* Bit  3:	Busy (Operation in progress) */
-								/* Bit   2..0:	reserved */
-	
-#define GM_SMI_CT_PHY_AD(x)	(SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
-#define GM_SMI_CT_REG_AD(x)	(SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
-
-	/*	GM_PHY_ADDR				16 bit r/w	GPHY Address Register */
-								/* Bit  15..6:	reserved */
-#define GM_PAR_MIB_CLR		(1<<5)	/* Bit  5:	Set MIB Clear Counter Mode */
-#define GM_PAR_MIB_TST		(1<<4)	/* Bit  4:	MIB Load Counter (Test Mode) */
-								/* Bit   3..0:	reserved */
-	
-/* Receive Frame Status Encoding */
-#define GMR_FS_LEN	(0xffffUL<<16)	/* Bit 31..16:	Rx Frame Length */
-								/* Bit  15..14:	reserved */
-#define GMR_FS_VLAN		(1L<<13)	/* Bit 13:	VLAN Packet */
-#define GMR_FS_JABBER	(1L<<12)	/* Bit 12:	Jabber Packet */
-#define GMR_FS_UN_SIZE	(1L<<11)	/* Bit 11:	Undersize Packet */
-#define GMR_FS_MC		(1L<<10)	/* Bit 10:	Multicast Packet */
-#define GMR_FS_BC		(1L<<9)		/* Bit  9:	Broadcast Packet */
-#define GMR_FS_RX_OK	(1L<<8)		/* Bit  8:	Receive OK (Good Packet) */
-#define GMR_FS_GOOD_FC	(1L<<7)		/* Bit  7:	Good Flow-Control Packet */
-#define GMR_FS_BAD_FC	(1L<<6)		/* Bit  6:	Bad  Flow-Control Packet */
-#define GMR_FS_MII_ERR	(1L<<5)		/* Bit  5:	MII Error */
-#define GMR_FS_LONG_ERR	(1L<<4)		/* Bit  4:	Too Long Packet */
-#define GMR_FS_FRAGMENT	(1L<<3)		/* Bit  3:	Fragment */
-								/* Bit  2:	reserved */
-#define GMR_FS_CRC_ERR	(1L<<1)		/* Bit  1:	CRC Error */
-#define GMR_FS_RX_FF_OV	(1L<<0)		/* Bit  0:	Rx FIFO Overflow */
-
-/*
- * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
- */
-#define GMR_FS_ANY_ERR	(GMR_FS_CRC_ERR | \
-			GMR_FS_LONG_ERR | \
-			GMR_FS_MII_ERR | \
-			GMR_FS_BAD_FC | \
-			GMR_FS_GOOD_FC | \
-			GMR_FS_JABBER)
-
-/* Rx GMAC FIFO Flush Mask (default) */
-#define RX_FF_FL_DEF_MSK	(GMR_FS_CRC_ERR | \
-			GMR_FS_RX_FF_OV | \
-			GMR_FS_MII_ERR | \
-			GMR_FS_BAD_FC | \
-			GMR_FS_GOOD_FC | \
-			GMR_FS_UN_SIZE | \
-			GMR_FS_JABBER)
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_XMAC_H */
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
deleted file mode 100644
index 6e6c56a..0000000
--- a/drivers/net/sk98lin/skaddr.c
+++ /dev/null
@@ -1,1788 +0,0 @@
-/******************************************************************************
- *
- * Name:	skaddr.c
- * Project:	Gigabit Ethernet Adapters, ADDR-Module
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/06/02 13:46:15 $
- * Purpose:	Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses, address override,
- * and promiscuous mode on GEnesis and Yukon adapters.
- *
- * Address Layout:
- *	port address:		physical MAC address
- *	1st exact match:	logical MAC address (GEnesis only)
- *	2nd exact match:	RLMT multicast (GEnesis only)
- *	exact match 3-13:	OS-specific multicasts (GEnesis only)
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
-#endif /* DEBUG ||!LINT || !SK_SLIM */
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-
-#define XMAC_POLY	0xEDB88320UL	/* CRC32-Poly - XMAC: Little Endian */
-#define GMAC_POLY	0x04C11DB7L	/* CRC16-Poly - GMAC: Little Endian */
-#define HASH_BITS	6				/* #bits in hash */
-#define	SK_MC_BIT	0x01
-
-/* Error numbers and messages. */
-
-#define SKERR_ADDR_E001		(SK_ERRBASE_ADDR + 0)
-#define SKERR_ADDR_E001MSG	"Bad Flags."
-#define SKERR_ADDR_E002		(SKERR_ADDR_E001 + 1)
-#define SKERR_ADDR_E002MSG	"New Error."
-
-/* typedefs *******************************************************************/
-
-/* None. */
-
-/* global variables ***********************************************************/
-
-/* 64-bit hash values with all bits set. */
-
-static const SK_U16	OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
-
-/* local variables ************************************************************/
-
-#ifdef DEBUG
-static int	Next0[SK_MAX_MACS] = {0};
-#endif	/* DEBUG */
-
-static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			   SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			     int Flags);
-static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
-				       SK_U32 PortNumber, int NewPromMode);
-static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			   SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			     int Flags);
-static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
-				       SK_U32 PortNumber, int NewPromMode);
-
-/* functions ******************************************************************/
-
-/******************************************************************************
- *
- *	SkAddrInit - initialize data, set state to init
- *
- * Description:
- *
- *	SK_INIT_DATA
- *	============
- *
- *	This routine clears the multicast tables and resets promiscuous mode.
- *	Some entries are reserved for the "logical MAC address", the
- *	SK-RLMT multicast address, and the BPDU multicast address.
- *
- *
- *	SK_INIT_IO
- *	==========
- *
- *	All permanent MAC addresses are read from EPROM.
- *	If the current MAC addresses are not already set in software,
- *	they are set to the values of the permanent addresses.
- *	The current addresses are written to the corresponding MAC.
- *
- *
- *	SK_INIT_RUN
- *	===========
- *
- *	Nothing.
- *
- * Context:
- *	init, pageable
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- */
-int	SkAddrInit(
-SK_AC	*pAC,	/* the adapter context */
-SK_IOC	IoC,	/* I/O context */
-int		Level)	/* initialization level */
-{
-	int			j;
-	SK_U32		i;
-	SK_U8		*InAddr;
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
-            (SK_U16) sizeof(SK_ADDR));
-
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			pAPort = &pAC->Addr.Port[i];
-			pAPort->PromMode = SK_PROM_MODE_NONE;
-			
-			pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-			pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-			pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-			pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-		}
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 4;
-			}
-		}
-#endif	/* DEBUG */
-		/* pAC->Addr.InitDone = SK_INIT_DATA; */
-		break;
-
-    case SK_INIT_IO:
-#ifndef SK_NO_RLMT
-		for (i = 0; i < SK_MAX_NETS; i++) {
-			pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
-		}
-#endif /* !SK_NO_RLMT */
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 8;
-			}
-		}
-#endif	/* DEBUG */
-		
-		/* Read permanent logical MAC address from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
-			SK_IN8(IoC, B2_MAC_1 + j, InAddr);
-		}
-
-		if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
-			/* Set the current logical MAC address to the permanent one. */
-			pAC->Addr.Net[0].CurrentMacAddress =
-				pAC->Addr.Net[0].PermanentMacAddress;
-			pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
-		}
-
-		/* Set the current logical MAC address. */
-		pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
-			pAC->Addr.Net[0].CurrentMacAddress;
-#if SK_MAX_NETS > 1
-		/* Set logical MAC address for net 2 to (log | 3). */
-		if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
-			pAC->Addr.Net[1].PermanentMacAddress =
-				pAC->Addr.Net[0].PermanentMacAddress;
-			pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
-			/* Set the current logical MAC address to the permanent one. */
-			pAC->Addr.Net[1].CurrentMacAddress =
-				pAC->Addr.Net[1].PermanentMacAddress;
-			pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
-		}
-#endif	/* SK_MAX_NETS > 1 */
-
-#ifdef DEBUG
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
-					i,
-					pAC->Addr.Net[i].PermanentMacAddress.a[0],
-					pAC->Addr.Net[i].PermanentMacAddress.a[1],
-					pAC->Addr.Net[i].PermanentMacAddress.a[2],
-					pAC->Addr.Net[i].PermanentMacAddress.a[3],
-					pAC->Addr.Net[i].PermanentMacAddress.a[4],
-					pAC->Addr.Net[i].PermanentMacAddress.a[5]))
-			
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
-					i,
-					pAC->Addr.Net[i].CurrentMacAddress.a[0],
-					pAC->Addr.Net[i].CurrentMacAddress.a[1],
-					pAC->Addr.Net[i].CurrentMacAddress.a[2],
-					pAC->Addr.Net[i].CurrentMacAddress.a[3],
-					pAC->Addr.Net[i].CurrentMacAddress.a[4],
-					pAC->Addr.Net[i].CurrentMacAddress.a[5]))
-		}
-#endif	/* DEBUG */
-
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			pAPort = &pAC->Addr.Port[i];
-
-			/* Read permanent port addresses from Control Register File. */
-			for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-				InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
-				SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
-			}
-
-			if (!pAPort->CurrentMacAddressSet) {
-				/*
-				 * Set the current and previous physical MAC address
-				 * of this port to its permanent MAC address.
-				 */
-				pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
-				pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
-				pAPort->CurrentMacAddressSet = SK_TRUE;
-			}
-
-			/* Set port's current physical MAC address. */
-			OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-#ifdef GENESIS
-			if (pAC->GIni.GIGenesis) {
-				XM_OUTADDR(IoC, i, XM_SA, OutAddr);
-			}
-#endif /* GENESIS */
-#ifdef YUKON
-			if (!pAC->GIni.GIGenesis) {
-				GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
-			}
-#endif /* YUKON */
-#ifdef DEBUG
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-					pAPort->PermanentMacAddress.a[0],
-					pAPort->PermanentMacAddress.a[1],
-					pAPort->PermanentMacAddress.a[2],
-					pAPort->PermanentMacAddress.a[3],
-					pAPort->PermanentMacAddress.a[4],
-					pAPort->PermanentMacAddress.a[5]))
-			
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-					pAPort->CurrentMacAddress.a[0],
-					pAPort->CurrentMacAddress.a[1],
-					pAPort->CurrentMacAddress.a[2],
-					pAPort->CurrentMacAddress.a[3],
-					pAPort->CurrentMacAddress.a[4],
-					pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-		}
-		/* pAC->Addr.InitDone = SK_INIT_IO; */
-		break;
-
-	case SK_INIT_RUN:
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 16;
-			}
-		}
-#endif	/* DEBUG */
-
-		/* pAC->Addr.InitDone = SK_INIT_RUN; */
-		break;
-
-	default:	/* error */
-		break;
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrInit */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast table.
- *
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- *	It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
- *	to the adapter in use. The real work is done there.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int ReturnCode;
-	
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-	
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
-	}
-	else {
-		ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
-	}
-
-	return (ReturnCode);
-
-}	/* SkAddrMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrXmacMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast table
- *	(either entry 2 or entries 3-16 and InexactFilter) of the given port.
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int i;
-
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-
-		/* Clear RLMT multicast addresses. */
-		pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-	}
-	else {	/* not permanent => DRV */
-
-		/* Clear InexactFilter */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-		}
-
-		/* Clear DRV multicast addresses. */
-
-		pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-	}
-
-	if (!(Flags & SK_MC_SW_ONLY)) {
-		(void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrXmacMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrGmacMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast hashing table (InexactFilter)
- *	(either the RLMT or the driver bits) of the given port.
- *
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int i;
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif	/* DEBUG */
-
-	/* Clear InexactFilter */
-	for (i = 0; i < 8; i++) {
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-	}
-	
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-		
-		/* Copy DRV bits to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-			
-			/* Clear InexactRlmtFilter. */
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
-
-		}		
-	}
-	else {	/* not permanent => DRV */
-		
-		/* Copy RLMT bits to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-			
-			/* Clear InexactDrvFilter. */
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
-		}
-	}
-	
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif	/* DEBUG */
-	
-	if (!(Flags & SK_MC_SW_ONLY)) {
-		(void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
-	}
-	
-	return (SK_ADDR_SUCCESS);
-
-}	/* SkAddrGmacMcClear */
-
-#ifndef SK_ADDR_CHEAT
-
-/******************************************************************************
- *
- *	SkXmacMcHash - hash multicast address
- *
- * Description:
- *	This routine computes the hash value for a multicast address.
- *	A CRC32 algorithm is used.
- *
- * Notes:
- *	The code was adapted from the XaQti data sheet.
- *
- * Context:
- *	runtime, pageable
- *
- * Returns:
- *	Hash value of multicast address.
- */
-static SK_U32 SkXmacMcHash(
-unsigned char *pMc)	/* Multicast address */
-{
-	SK_U32 Idx;
-	SK_U32 Bit;
-	SK_U32 Data;
-	SK_U32 Crc;
-
-	Crc = 0xFFFFFFFFUL;
-	for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
-		Data = *pMc++;
-		for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
-			Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
-		}
-	}
-
-	return (Crc & ((1 << HASH_BITS) - 1));
-
-}	/* SkXmacMcHash */
-
-
-/******************************************************************************
- *
- *	SkGmacMcHash - hash multicast address
- *
- * Description:
- *	This routine computes the hash value for a multicast address.
- *	A CRC16 algorithm is used.
- *
- * Notes:
- *
- *
- * Context:
- *	runtime, pageable
- *
- * Returns:
- *	Hash value of multicast address.
- */
-static SK_U32 SkGmacMcHash(
-unsigned char *pMc)	/* Multicast address */
-{
-	SK_U32 Data;
-	SK_U32 TmpData;
-	SK_U32 Crc;
-	int Byte;
-	int Bit;
-
-	Crc = 0xFFFFFFFFUL;
-	for (Byte = 0; Byte < 6; Byte++) {
-		/* Get next byte. */
-		Data = (SK_U32) pMc[Byte];
-		
-		/* Change bit order in byte. */
-		TmpData = Data;
-		for (Bit = 0; Bit < 8; Bit++) {
-			if (TmpData & 1L) {
-				Data |=  1L << (7 - Bit);
-			}
-			else {
-				Data &= ~(1L << (7 - Bit));
-			}
-			TmpData >>= 1;
-		}
-		
-		Crc ^= (Data << 24);
-		for (Bit = 0; Bit < 8; Bit++) {
-			if (Crc & 0x80000000) {
-				Crc = (Crc << 1) ^ GMAC_POLY;
-			}
-			else {
-				Crc <<= 1;
-			}
-		}
-	}
-	
-	return (Crc & ((1 << HASH_BITS) - 1));
-
-}	/* SkGmacMcHash */
-
-#endif	/* !SK_ADDR_CHEAT */
-
-/******************************************************************************
- *
- *	SkAddrMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- *	It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
- *	adapter in use. The real work is done there.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- *	SK_MC_ILLEGAL_PORT
- *	SK_MC_RLMT_OVERFLOW
- */
-int	SkAddrMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int			Flags)		/* permanent/non-permanent */
-{
-	int ReturnCode;
-	
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-	
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
-	}
-	else {
-		ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
-	}
-
-	return (ReturnCode);
-
-}	/* SkAddrMcAdd */
-
-
-/******************************************************************************
- *
- *	SkAddrXmacMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- *	The multicast bit is only checked if there are no free exact match
- *	entries.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- *	SK_MC_RLMT_OVERFLOW
- */
-static int	SkAddrXmacMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int		Flags)		/* permanent/non-permanent */
-{
-	int	i;
-	SK_U8	Inexact;
-#ifndef SK_ADDR_CHEAT
-	SK_U32 HashBit;
-#endif	/* !defined(SK_ADDR_CHEAT) */
-
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-#ifdef xDEBUG
-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
-			SK_ADDR_FIRST_MATCH_RLMT) {
-			Next0[PortNumber] |= 1;
-			return (SK_MC_RLMT_OVERFLOW);
-		}
-#endif	/* DEBUG */
-		
-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
-			SK_ADDR_LAST_MATCH_RLMT) {
-			return (SK_MC_RLMT_OVERFLOW);
-		}
-
-		/* Set a RLMT multicast address. */
-
-		pAC->Addr.Port[PortNumber].Exact[
-			pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
-
-		return (SK_MC_FILTERING_EXACT);
-	}
-
-#ifdef xDEBUG
-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
-		SK_ADDR_FIRST_MATCH_DRV) {
-			Next0[PortNumber] |= 2;
-		return (SK_MC_RLMT_OVERFLOW);
-	}
-#endif	/* DEBUG */
-	
-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-
-		/* Set exact match entry. */
-		pAC->Addr.Port[PortNumber].Exact[
-			pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
-
-		/* Clear InexactFilter */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-		}
-	}
-	else {
-		if (!(pMc->a[0] & SK_MC_BIT)) {
-			/* Hashing only possible with multicast addresses */
-			return (SK_MC_ILLEGAL_ADDRESS);
-		}
-#ifndef SK_ADDR_CHEAT
-		/* Compute hash value of address. */
-		HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
-
-		/* Add bit to InexactFilter. */
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-#else	/* SK_ADDR_CHEAT */
-		/* Set all bits in InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
-		}
-#endif	/* SK_ADDR_CHEAT */
-	}
-
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-	}
-
-	if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-
-}	/* SkAddrXmacMcAdd */
-
-
-/******************************************************************************
- *
- *	SkAddrGmacMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- */
-static int	SkAddrGmacMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int		Flags)		/* permanent/non-permanent */
-{
-	int	i;
-#ifndef SK_ADDR_CHEAT
-	SK_U32 HashBit;
-#endif	/* !defined(SK_ADDR_CHEAT) */
-		
-	if (!(pMc->a[0] & SK_MC_BIT)) {
-		/* Hashing only possible with multicast addresses */
-		return (SK_MC_ILLEGAL_ADDRESS);
-	}
-	
-#ifndef SK_ADDR_CHEAT
-	
-	/* Compute hash value of address. */
-	HashBit = SkGmacMcHash(&pMc->a[0]);
-	
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-		
-		/* Add bit to InexactRlmtFilter. */
-		pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-		
-		/* Copy bit to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-		}
-#ifdef DEBUG
-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
-#endif	/* DEBUG */
-	}
-	else {	/* not permanent => DRV */
-		
-		/* Add bit to InexactDrvFilter. */
-		pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-		
-		/* Copy bit to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-		}
-#ifdef DEBUG
-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
-#endif	/* DEBUG */
-	}
-	
-#else	/* SK_ADDR_CHEAT */
-	
-	/* Set all bits in InexactFilter. */
-	for (i = 0; i < 8; i++) {
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
-	}
-#endif	/* SK_ADDR_CHEAT */
-		
-	return (SK_MC_FILTERING_INEXACT);
-	
-}	/* SkAddrGmacMcAdd */
-
-#endif /* !SK_SLIM */
-
-/******************************************************************************
- *
- *	SkAddrMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- *	It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
- *	to the adapter in use. The real work is done there.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-	int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
-	}
-#endif /* GENESIS */
-#ifdef YUKON
-	if (!pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
-	}
-#endif /* YUKON */
-	return (ReturnCode);
-
-}	/* SkAddrMcUpdate */
-
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- *	SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-	SK_U32		i;
-	SK_U8		Inexact;
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
-	
-	pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-
-	/* Start with 0 to also program the logical MAC address. */
-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
-		/* Set exact match address i on XMAC */
-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
-	}
-
-	/* Clear other permanent exact match addresses on XMAC */
-	if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
-		
-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
-			SK_ADDR_LAST_MATCH_RLMT);
-	}
-
-	for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
-	}
-
-	/* Clear other non-permanent exact match addresses on XMAC */
-	if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-		
-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
-			SK_ADDR_LAST_MATCH_DRV);
-	}
-
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAPort->InexactFilter.Bytes[i];
-	}
-
-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
-		
-		/* Set all bits in 64-bit hash register. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if (Inexact != 0) {
-		
-		/* Set 64-bit hash register to InexactFilter. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else {
-		/* Disable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-
-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
-		(void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	}
-
-	/* Set port's current physical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-	
-	XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-
-#ifdef xDEBUG
-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
-		SK_U8		InAddr8[6];
-		SK_U16		*InAddr;
-
-		/* Get exact match address i from port PortNumber. */
-		InAddr = (SK_U16 *) &InAddr8[0];
-		
-		XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
-		
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
-			 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
-				i,
-				PortNumber,
-				InAddr8[0],
-				InAddr8[1],
-				InAddr8[2],
-				InAddr8[3],
-				InAddr8[4],
-				InAddr8[5],
-				pAPort->Exact[i].a[0],
-				pAPort->Exact[i].a[1],
-				pAPort->Exact[i].a[2],
-				pAPort->Exact[i].a[3],
-				pAPort->Exact[i].a[4],
-				pAPort->Exact[i].a[5]))
-	}
-#endif /* DEBUG */
-
-	/* Determine return value. */
-	if (Inexact == 0 && pAPort->PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-	
-}	/* SkAddrXmacMcUpdate */
-
-#endif  /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- *	SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-#ifndef SK_SLIM
-	SK_U32		i;
-	SK_U8		Inexact;
-#endif	/* not SK_SLIM */
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
-	
-	pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-	
-#ifndef SK_SLIM
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAPort->InexactFilter.Bytes[i];
-	}
-	
-	/* Set 64-bit hash register to InexactFilter. */
-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
-		&pAPort->InexactFilter.Bytes[0]);
-	
-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {				
-		
-		/* Set all bits in 64-bit hash register. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else {	
-		/* Enable Hashing. */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	
-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
-		(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	}
-#else /* SK_SLIM */
-
-	/* Set all bits in 64-bit hash register. */
-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
-	/* Enable Hashing */
-	SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	
-	(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	
-#endif /* SK_SLIM */
-	
-	/* Set port's current physical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-	
-	/* Set port's current logical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
-	
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-			pAPort->Exact[0].a[0],
-			pAPort->Exact[0].a[1],
-			pAPort->Exact[0].a[2],
-			pAPort->Exact[0].a[3],
-			pAPort->Exact[0].a[4],
-			pAPort->Exact[0].a[5]))
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-			pAPort->CurrentMacAddress.a[0],
-			pAPort->CurrentMacAddress.a[1],
-			pAPort->CurrentMacAddress.a[2],
-			pAPort->CurrentMacAddress.a[3],
-			pAPort->CurrentMacAddress.a[4],
-			pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-	
-#ifndef SK_SLIM
-	/* Determine return value. */
-	if (Inexact == 0 && pAPort->PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-#else /* SK_SLIM */
-	return (SK_MC_FILTERING_INEXACT);
-#endif /* SK_SLIM */
-	
-}	/* SkAddrGmacMcUpdate */
-
-#endif /* YUKON */
-
-#ifndef SK_NO_MAO
-
-/******************************************************************************
- *
- *	SkAddrOverride - override a port's MAC address
- *
- * Description:
- *	This routine overrides the MAC address of one port.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS if successful.
- *	SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
- *	SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
- *	SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
- */
-int	SkAddrOverride(
-SK_AC		*pAC,				/* adapter context */
-SK_IOC		IoC,				/* I/O context */
-SK_U32		PortNumber,			/* Port Number */
-SK_MAC_ADDR	SK_FAR *pNewAddr,	/* new MAC address */
-int			Flags)				/* logical/physical MAC address */
-{
-#ifndef SK_NO_RLMT
-	SK_EVPARA	Para;
-#endif /* !SK_NO_RLMT */
-	SK_U32		NetNumber;
-	SK_U32		i;
-	SK_U16		SK_FAR *OutAddr;
-
-#ifndef SK_NO_RLMT
-	NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
-#else
-	NetNumber = 0;
-#endif /* SK_NO_RLMT */
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-	if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
-		return (SK_ADDR_MULTICAST_ADDRESS);
-	}
-
-	if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
-		return (SK_ADDR_TOO_EARLY);
-	}
-
-	if (Flags & SK_ADDR_SET_LOGICAL) {	/* Activate logical MAC address. */
-		/* Parameter *pNewAddr is ignored. */
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-		}
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		pAC->Addr.Port[PortNumber].Exact[0] =
-			pAC->Addr.Net[NetNumber].CurrentMacAddress;
-
-		/* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-	else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
-		/* Deactivate logical MAC address. */
-		/* Parameter *pNewAddr is ignored. */
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-		}
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
-			pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
-		}
-
-		/* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-	else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) {	/* Physical MAC address. */
-		if (SK_ADDR_EQUAL(pNewAddr->a,
-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
-			return (SK_ADDR_DUPLICATE_ADDRESS);
-		}
-
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-
-			if (SK_ADDR_EQUAL(pNewAddr->a,
-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
-				if (i == PortNumber) {
-					return (SK_ADDR_SUCCESS);
-				}
-				else {
-					return (SK_ADDR_DUPLICATE_ADDRESS);
-				}
-			}
-		}
-
-		pAC->Addr.Port[PortNumber].PreviousMacAddress =
-			pAC->Addr.Port[PortNumber].CurrentMacAddress;
-		pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-
-		/* Change port's physical MAC address. */
-		OutAddr = (SK_U16 SK_FAR *) pNewAddr;
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-		}
-#endif /* GENESIS */
-#ifdef YUKON
-		if (!pAC->GIni.GIGenesis) {
-			GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-		}
-#endif /* YUKON */
-
-#ifndef SK_NO_RLMT
-		/* Report address change to RLMT. */
-		Para.Para32[0] = PortNumber;
-		Para.Para32[0] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
-	}
-	else {	/* Logical MAC address. */
-		if (SK_ADDR_EQUAL(pNewAddr->a,
-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
-			return (SK_ADDR_SUCCESS);
-		}
-		
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-
-			if (SK_ADDR_EQUAL(pNewAddr->a,
-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
-				return (SK_ADDR_DUPLICATE_ADDRESS);
-			}
-		}
-		
-		/*
-		 * In case that the physical and the logical MAC addresses are equal
-		 * we must also change the physical MAC address here.
-		 * In this case we have an adapter which initially was programmed with
-		 * two identical MAC addresses.
-		 */
-		if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
-				pAC->Addr.Port[PortNumber].Exact[0].a)) {
-			
-			pAC->Addr.Port[PortNumber].PreviousMacAddress =
-				pAC->Addr.Port[PortNumber].CurrentMacAddress;
-			pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-			
-#ifndef SK_NO_RLMT
-			/* Report address change to RLMT. */
-			Para.Para32[0] = PortNumber;
-			Para.Para32[0] = -1;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
-		}
-		
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
-		pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
-#ifdef DEBUG
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
-		
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-
-        /* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrOverride */
-
-
-#endif /* SK_NO_MAO */
-
-/******************************************************************************
- *
- *	SkAddrPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- *	It calls either SkAddrXmacPromiscuousChange or
- *	SkAddrGmacPromiscuousChange, according to the adapter in use.
- *	The real work is done there.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode =
-			SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
-	}
-#endif /* GENESIS */
-#ifdef YUKON
-	if (!pAC->GIni.GIGenesis) {
-		ReturnCode =
-			SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
-	}
-#endif /* YUKON */
-
-	return (ReturnCode);
-
-}	/* SkAddrPromiscuousChange */
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- *	SkAddrXmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	int			i;
-	SK_BOOL		InexactModeBit;
-	SK_U8		Inexact;
-	SK_U8		HwInexact;
-	SK_FILTER64	HwInexactFilter;
-	SK_U16		LoMode;		/* Lower 16 bits of XMAC Mode Register. */
-	int			CurPromMode = SK_PROM_MODE_NONE;
-
-	/* Read CurPromMode from Hardware. */
-	XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
-	if ((LoMode & XM_MD_ENA_PROM) != 0) {
-		/* Promiscuous mode! */
-		CurPromMode |= SK_PROM_MODE_LLC;
-	}
-	
-	for (Inexact = 0xFF, i = 0; i < 8; i++) {
-		Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-	}
-	if (Inexact == 0xFF) {
-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
-	}
-	else {
-		/* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
-		XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-		
-		InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
-
-		/* Read 64-bit hash register from XMAC */
-		XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
-
-		for (HwInexact = 0xFF, i = 0; i < 8; i++) {
-			HwInexact &= HwInexactFilter.Bytes[i];
-		}
-
-		if (InexactModeBit && (HwInexact == 0xFF)) {
-			CurPromMode |= SK_PROM_MODE_ALL_MC;
-		}
-	}
-
-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
-	if (NewPromMode == CurPromMode) {
-		return (SK_ADDR_SUCCESS);
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC. */
-		
-		/* Set all bits in 64-bit hash register. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm MC. */
-		for (Inexact = 0, i = 0; i < 8; i++) {
-			Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-		}
-		if (Inexact == 0) {
-			/* Disable Hashing */
-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
-		}
-		else {
-			/* Set 64-bit hash register to InexactFilter. */
-			XM_OUTHASH(IoC, PortNumber, XM_HSM,
-				&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
-			/* Enable Hashing */
-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-		}
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
-		/* Set the MAC in Promiscuous Mode */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC. */
-		/* Clear Promiscuous Mode */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-	
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrXmacPromiscuousChange */
-
-#endif /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- *	SkAddrGmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	SK_U16		ReceiveControl;	/* GMAC Receive Control Register */
-	int		CurPromMode = SK_PROM_MODE_NONE;
-
-	/* Read CurPromMode from Hardware. */
-	GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
-
-	if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
-		/* Promiscuous mode! */
-		CurPromMode |= SK_PROM_MODE_LLC;
-	}
-
-	if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
-		/* All Multicast mode! */
-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
-	}
-
-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
-	if (NewPromMode == CurPromMode) {
-		return (SK_ADDR_SUCCESS);
-	}
-	
-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC */
-		
-		/* Set all bits in 64-bit hash register. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	
-	if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm. MC */
-
-		/* Set 64-bit hash register to InexactFilter. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
-			&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
-		/* Enable Hashing. */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
-		
-		/* Set the MAC to Promiscuous Mode. */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC */
-		
-		/* Clear Promiscuous Mode. */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrGmacPromiscuousChange */
-
-#endif /* YUKON */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrSwap - swap address info
- *
- * Description:
- *	This routine swaps address info of two ports.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrSwap(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	FromPortNumber,		/* Port1 Index */
-SK_U32	ToPortNumber)		/* Port2 Index */
-{
-	int			i;
-	SK_U8		Byte;
-	SK_MAC_ADDR	MacAddr;
-	SK_U32		DWord;
-
-	if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	/*
-	 * Swap:
-	 * - Exact Match Entries (GEnesis and Yukon)
-	 *   Yukon uses first entry for the logical MAC
-	 *   address (stored in the second GMAC register).
-	 * - FirstExactMatchRlmt (GEnesis only)
-	 * - NextExactMatchRlmt (GEnesis only)
-	 * - FirstExactMatchDrv (GEnesis only)
-	 * - NextExactMatchDrv (GEnesis only)
-	 * - 64-bit filter (InexactFilter)
-	 * - Promiscuous Mode
-	 * of ports.
-	 */
-
-	for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
-		MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
-		pAC->Addr.Port[FromPortNumber].Exact[i] =
-			pAC->Addr.Port[ToPortNumber].Exact[i];
-		pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
-	}
-
-	for (i = 0; i < 8; i++) {
-		Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
-		pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
-			pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
-		pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
-	}
-	
-	i = pAC->Addr.Port[FromPortNumber].PromMode;
-	pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
-	pAC->Addr.Port[ToPortNumber].PromMode = i;
-	
-	if (pAC->GIni.GIGenesis) {
-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
-		pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
-			pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
-		pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
-		pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
-			pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
-		pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
-		pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
-			pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
-		pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
-		pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
-			pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
-		pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
-	}
-	
-	/* CAUTION: Solution works if only ports of one adapter are in use. */
-	for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
-		Net->NetNumber].NumPorts; i++) {
-		if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
-			Port[i]->PortNumber == ToPortNumber) {
-			pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
-				ActivePort = i;
-			/* 20001207 RA: Was "ToPortNumber;". */
-		}
-	}
-	
-	(void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
-	(void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrSwap */
-
-#endif /* !SK_SLIM */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
deleted file mode 100644
index 37ce03f..0000000
--- a/drivers/net/sk98lin/skdim.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdim.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/11/28 12:55:40 $
- * Purpose:	All functions to maintain interrupt moderation
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage the dynamic interrupt moderation on both   
- * GEnesis and Yukon adapters.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef	lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
-#endif
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-#error C++ is not yet supported.
-extern "C" {
-#endif
-
-/*******************************************************************************
-**
-** Includes
-**
-*******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#include "h/skdrv1st.h"
-#endif
-
-#ifndef __INC_SKDRV2ND_H
-#include "h/skdrv2nd.h"
-#endif
-
-#include	<linux/kernel_stat.h>
-
-/*******************************************************************************
-**
-** Defines
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Typedefs
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local function prototypes 
-**
-*******************************************************************************/
-
-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
-static SK_U64       GetIsrCalls(SK_AC *pAC);
-static SK_BOOL      IsIntModEnabled(SK_AC *pAC);
-static void         SetCurrIntCtr(SK_AC *pAC);
-static void         EnableIntMod(SK_AC *pAC); 
-static void         DisableIntMod(SK_AC *pAC);
-static void         ResizeDimTimerDuration(SK_AC *pAC);
-static void         DisplaySelectedModerationType(SK_AC *pAC);
-static void         DisplaySelectedModerationMask(SK_AC *pAC);
-static void         DisplayDescrRatio(SK_AC *pAC);
-
-/*******************************************************************************
-**
-** Global variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Global functions 
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function     : SkDimModerate
-** Description  : Called in every ISR to check if moderation is to be applied
-**                or not for the current number of interrupts
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimModerate(SK_AC *pAC) {
-    unsigned int CurrSysLoad    = 0;  /* expressed in percent */
-    unsigned int LoadIncrease   = 0;  /* expressed in percent */
-    SK_U64       ThresholdInts  = 0;
-    SK_U64       IsrCallsPerSec = 0;
-
-#define M_DIMINFO pAC->DynIrqModInfo
-
-    if (!IsIntModEnabled(pAC)) {
-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-            CurrSysLoad = GetCurrentSystemLoad(pAC);
-            if (CurrSysLoad > 75) {
-                    /* 
-                    ** More than 75% total system load! Enable the moderation 
-                    ** to shield the system against too many interrupts.
-                    */
-                    EnableIntMod(pAC);
-            } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
-                LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
-                if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
-                                         C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
-                    if (CurrSysLoad > 10) {
-                        /* 
-                        ** More than 50% increase with respect to the 
-                        ** previous load of the system. Most likely this 
-                        ** is due to our ISR-proc...
-                        */
-                        EnableIntMod(pAC);
-                    }
-                }
-            } else {
-                /*
-                ** Neither too much system load at all nor too much increase
-                ** with respect to the previous system load. Hence, we can leave
-                ** the ISR-handling like it is without enabling moderation.
-                */
-            }
-            M_DIMINFO.PrevSysLoad = CurrSysLoad;
-        }   
-    } else {
-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-            ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
-                                   C_INT_MOD_DISABLE_PERCENTAGE) / 100);
-            IsrCallsPerSec = GetIsrCalls(pAC);
-            if (IsrCallsPerSec <= ThresholdInts) {
-                /* 
-                ** The number of interrupts within the last second is 
-                ** lower than the disable_percentage of the desried 
-                ** maxrate. Therefore we can disable the moderation.
-                */
-                DisableIntMod(pAC);
-                M_DIMINFO.MaxModIntsPerSec = 
-                   (M_DIMINFO.MaxModIntsPerSecUpperLimit +
-                    M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
-            } else {
-                /*
-                ** The number of interrupts per sec is the same as expected.
-                ** Evalulate the descriptor-ratio. If it has changed, a resize 
-                ** in the moderation timer might be useful
-                */
-                if (M_DIMINFO.AutoSizing) {
-                    ResizeDimTimerDuration(pAC);
-                }
-            }
-        }
-    }
-
-    /*
-    ** Some information to the log...
-    */
-    if (M_DIMINFO.DisplayStats) {
-        DisplaySelectedModerationType(pAC);
-        DisplaySelectedModerationMask(pAC);
-        DisplayDescrRatio(pAC);
-    }
-
-    M_DIMINFO.NbrProcessedDescr = 0; 
-    SetCurrIntCtr(pAC);
-}
-
-/*******************************************************************************
-** Function     : SkDimStartModerationTimer
-** Description  : Starts the audit-timer for the dynamic interrupt moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimStartModerationTimer(SK_AC *pAC) {
-    SK_EVPARA    EventParam;   /* Event struct for timer event */
- 
-    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
-    EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
-    SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
-                 SK_DRV_MODERATION_TIMER_LENGTH,
-                 SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*******************************************************************************
-** Function     : SkDimEnableModerationIfNeeded
-** Description  : Either enables or disables moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : This function is called when a particular adapter is opened
-**                There is no Disable function, because when all interrupts 
-**                might be disable, the moderation timer has no meaning at all
-******************************************************************************/
-
-void
-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
-
-    if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
-        EnableIntMod(pAC);   /* notification print in this function */
-    } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-        SkDimStartModerationTimer(pAC);
-        if (M_DIMINFO.DisplayStats) {
-            printk("Dynamic moderation has been enabled\n");
-        }
-    } else {
-        if (M_DIMINFO.DisplayStats) {
-            printk("No moderation has been enabled\n");
-        }
-    }
-}
-
-/*******************************************************************************
-** Function     : SkDimDisplayModerationSettings
-** Description  : Displays the current settings regarding interrupt moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimDisplayModerationSettings(SK_AC *pAC) {
-    DisplaySelectedModerationType(pAC);
-    DisplaySelectedModerationMask(pAC);
-}
-
-/*******************************************************************************
-**
-** Local functions 
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function     : GetCurrentSystemLoad
-** Description  : Retrieves the current system load of the system. This load
-**                is evaluated for all processors within the system.
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : unsigned int: load expressed in percentage
-** Notes        : The possible range being returned is from 0 up to 100.
-**                Whereas 0 means 'no load at all' and 100 'system fully loaded'
-**                It is impossible to determine what actually causes the system
-**                to be in 100%, but maybe that is due to too much interrupts.
-*******************************************************************************/
-
-static unsigned int
-GetCurrentSystemLoad(SK_AC *pAC) {
-	unsigned long jif         = jiffies;
-	unsigned int  UserTime    = 0;
-	unsigned int  SystemTime  = 0;
-	unsigned int  NiceTime    = 0;
-	unsigned int  IdleTime    = 0;
-	unsigned int  TotalTime   = 0;
-	unsigned int  UsedTime    = 0;
-	unsigned int  SystemLoad  = 0;
-
-	/* unsigned int  NbrCpu      = 0; */
-
-	/*
-	** The following lines have been commented out, because
-	** from kernel 2.5.44 onwards, the kernel-owned structure
-	**
-	**      struct kernel_stat kstat
-	**
-	** is not marked as an exported symbol in the file
-	**
-	**      kernel/ksyms.c 
-	**
-	** As a consequence, using this driver as KLM is not possible
-	** and any access of the structure kernel_stat via the 
-	** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
-	**
-	** The kstat-information might be added again in future 
-	** versions of the 2.5.xx kernel, but for the time being, 
-	** number of interrupts will serve as indication how much 
-	** load we currently have... 
-	**
-	** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
-	**	UserTime   = UserTime   + kstat_cpu(NbrCpu).cpustat.user;
-	**	NiceTime   = NiceTime   + kstat_cpu(NbrCpu).cpustat.nice;
-	**	SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
-	** }
-	*/
-	SK_U64 ThresholdInts  = 0;
-	SK_U64 IsrCallsPerSec = 0;
-
-	ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
-			   C_INT_MOD_ENABLE_PERCENTAGE) + 100);
-	IsrCallsPerSec = GetIsrCalls(pAC);
-	if (IsrCallsPerSec >= ThresholdInts) {
-	    /*
-	    ** We do not know how much the real CPU-load is!
-	    ** Return 80% as a default in order to activate DIM
-	    */
-	    SystemLoad = 80;
-	    return (SystemLoad);  
-	} 
-
-	UsedTime  = UserTime + NiceTime + SystemTime;
-
-	IdleTime  = jif * num_online_cpus() - UsedTime;
-	TotalTime = UsedTime + IdleTime;
-
-	SystemLoad = ( 100 * (UsedTime  - M_DIMINFO.PrevUsedTime) ) /
-						(TotalTime - M_DIMINFO.PrevTotalTime);
-
-	if (M_DIMINFO.DisplayStats) {
-		printk("Current system load is: %u\n", SystemLoad);
-	}
-
-	M_DIMINFO.PrevTotalTime = TotalTime;
-	M_DIMINFO.PrevUsedTime  = UsedTime;
-
-	return (SystemLoad);
-}
-
-/*******************************************************************************
-** Function     : GetIsrCalls
-** Description  : Depending on the selected moderation mask, this function will
-**                return the number of interrupts handled in the previous time-
-**                frame. This evaluated number is based on the current number 
-**                of interrupts stored in PNMI-context and the previous stored 
-**                interrupts.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : int:   the number of interrupts being executed in the last
-**                       timeframe
-** Notes        : It makes only sense to call this function, when dynamic 
-**                interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetIsrCalls(SK_AC *pAC) {
-    SK_U64   RxPort0IntDiff = 0;
-    SK_U64   RxPort1IntDiff = 0;
-    SK_U64   TxPort0IntDiff = 0;
-    SK_U64   TxPort1IntDiff = 0;
-
-    if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
-        if (pAC->GIni.GIMacsFound == 2) {
-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
-        }
-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
-    } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
-        if (pAC->GIni.GIMacsFound == 2) {
-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-        }
-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-    } else {
-        if (pAC->GIni.GIMacsFound == 2) {
-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
-        } 
-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
-    }
-
-    return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function     : GetRxCalls
-** Description  : This function will return the number of times a receive inter-
-**                rupt was processed. This is needed to evaluate any resizing 
-**                factor.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : SK_U64: the number of RX-ints being processed
-** Notes        : It makes only sense to call this function, when dynamic 
-**                interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetRxCalls(SK_AC *pAC) {
-    SK_U64   RxPort0IntDiff = 0;
-    SK_U64   RxPort1IntDiff = 0;
-
-    if (pAC->GIni.GIMacsFound == 2) {
-        RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-    }
-    RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                     pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-
-    return (RxPort0IntDiff + RxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function     : SetCurrIntCtr
-** Description  : Will store the current number orf occured interrupts in the 
-**                adapter context. This is needed to evaluated the number of 
-**                interrupts within a current timeframe.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-static void
-SetCurrIntCtr(SK_AC *pAC) {
-    if (pAC->GIni.GIMacsFound == 2) {
-        pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
-        pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
-    } 
-    pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
-    pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
-}
-
-/*******************************************************************************
-** Function     : IsIntModEnabled()
-** Description  : Retrieves the current value of the interrupts moderation
-**                command register. Its content determines whether any 
-**                moderation is running or not.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : SK_TRUE  : if mod timer running
-**                SK_FALSE : if no moderation is being performed
-** Notes        : -
-*******************************************************************************/
-
-static SK_BOOL
-IsIntModEnabled(SK_AC *pAC) {
-    unsigned long CtrCmd;
-
-    SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
-    if ((CtrCmd & TIM_START) == TIM_START) {
-       return SK_TRUE;
-    } else {
-       return SK_FALSE;
-    }
-}
-
-/*******************************************************************************
-** Function     : EnableIntMod()
-** Description  : Enables the interrupt moderation using the values stored in
-**                in the pAC->DynIntMod data structure
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : -
-** Notes        : -
-*******************************************************************************/
-
-static void
-EnableIntMod(SK_AC *pAC) {
-    unsigned long ModBase;
-
-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-       ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    } else {
-       ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    }
-
-    SK_OUT32(pAC->IoBase, B2_IRQM_INI,  ModBase);
-    SK_OUT32(pAC->IoBase, B2_IRQM_MSK,  pAC->DynIrqModInfo.MaskIrqModeration);
-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
-    if (M_DIMINFO.DisplayStats) {
-        printk("Enabled interrupt moderation (%i ints/sec)\n",
-               M_DIMINFO.MaxModIntsPerSec);
-    }
-}
-
-/*******************************************************************************
-** Function     : DisableIntMod()
-** Description  : Disables the interrupt moderation independent of what inter-
-**                rupts are running or not
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : -
-** Notes        : -
-*******************************************************************************/
-
-static void 
-DisableIntMod(SK_AC *pAC) {
-
-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
-    if (M_DIMINFO.DisplayStats) {
-        printk("Disabled interrupt moderation\n");
-    }
-} 
-
-/*******************************************************************************
-** Function     : ResizeDimTimerDuration();
-** Description  : Checks the current used descriptor ratio and resizes the 
-**                duration timer (longer/smaller) if possible. 
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : -
-** Notes        : There are both maximum and minimum timer duration value. 
-**                This function assumes that interrupt moderation is already
-**                enabled!
-*******************************************************************************/
-
-static void 
-ResizeDimTimerDuration(SK_AC *pAC) {
-    SK_BOOL IncreaseTimerDuration;
-    int     TotalMaxNbrDescr;
-    int     UsedDescrRatio;
-    int     RatioDiffAbs;
-    int     RatioDiffRel;
-    int     NewMaxModIntsPerSec;
-    int     ModAdjValue;
-    long    ModBase;
-
-    /*
-    ** Check first if we are allowed to perform any modification
-    */
-    if (IsIntModEnabled(pAC)) { 
-        if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
-            return; 
-        } else {
-            if (M_DIMINFO.ModJustEnabled) {
-                M_DIMINFO.ModJustEnabled = SK_FALSE;
-                return;
-            }
-        }
-    }
-
-    /*
-    ** If we got until here, we have to evaluate the amount of the
-    ** descriptor ratio change...
-    */
-    TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
-    UsedDescrRatio   = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
-
-    if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
-        RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_FALSE;  /* in other words: DECREASE */
-    } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
-    } else {
-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
-    }
-
-    /*
-    ** Now we can determine the change in percent
-    */
-    if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    }
-
-    if (IncreaseTimerDuration) {
-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec +
-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
-    } else {
-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec -
-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
-    }
-
-    /* 
-    ** Check if we exceed boundaries...
-    */
-    if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
-         (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
-        if (M_DIMINFO.DisplayStats) {
-            printk("Cannot change ModTim from %i to %i ints/sec\n",
-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
-        }
-        return;
-    } else {
-        if (M_DIMINFO.DisplayStats) {
-            printk("Resized ModTim from %i to %i ints/sec\n",
-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
-        }
-    }
-
-    M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
-
-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-        ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    } else {
-        ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    }
-
-    /* 
-    ** We do not need to touch any other registers
-    */
-    SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
-} 
-
-/*******************************************************************************
-** Function     : DisplaySelectedModerationType()
-** Description  : Displays what type of moderation we have
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationType(SK_AC *pAC) {
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
-             printk("Static int moderation runs with %i INTS/sec\n",
-                    pAC->DynIrqModInfo.MaxModIntsPerSec);
-        } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-             if (IsIntModEnabled(pAC)) {
-                printk("Dynamic int moderation runs with %i INTS/sec\n",
-                       pAC->DynIrqModInfo.MaxModIntsPerSec);
-             } else {
-                printk("Dynamic int moderation currently not applied\n");
-             }
-        } else {
-             printk("No interrupt moderation selected!\n");
-        }
-    }
-}
-
-/*******************************************************************************
-** Function     : DisplaySelectedModerationMask()
-** Description  : Displays what interrupts are moderated
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationMask(SK_AC *pAC) {
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
-            switch (pAC->DynIrqModInfo.MaskIrqModeration) {
-                case IRQ_MASK_TX_ONLY: 
-                   printk("Only Tx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_RX_ONLY: 
-                   printk("Only Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_ONLY: 
-                   printk("Only special-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_TX_RX: 
-                   printk("Tx- and Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_RX: 
-                   printk("Special- and Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_TX: 
-                   printk("Special- and Tx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_RX_TX_SP:
-                   printk("All Rx-, Tx and special-interrupts are moderated\n");
-                   break;
-                default:
-                   printk("Don't know what is moderated\n");
-                   break;
-            }
-        } else {
-            printk("No specific interrupts masked for moderation\n");
-        }
-    } 
-}
-
-/*******************************************************************************
-** Function     : DisplayDescrRatio
-** Description  : Like the name states...
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplayDescrRatio(SK_AC *pAC) {
-    int TotalMaxNbrDescr = 0;
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
-        printk("Ratio descriptors: %i/%i\n",
-               M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
-    }
-}
-
-/*******************************************************************************
-**
-** End of file
-**
-*******************************************************************************/
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
deleted file mode 100644
index 5a6da89..0000000
--- a/drivers/net/sk98lin/skethtool.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/******************************************************************************
- *
- * Name:        skethtool.c
- * Project:     GEnesis, PCI Gigabit Ethernet Adapter
- * Version:     $Revision: 1.7 $
- * Date:        $Date: 2004/09/29 13:32:07 $
- * Purpose:     All functions regarding ethtool handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2004 Marvell.
- *
- *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
- *      Server Adapters.
- *
- *	Author: Ralph Roesler (rroesler@syskonnect.de)
- *	        Mirko Lindner (mlindner@syskonnect.de)
- *
- *	Address all question to: linux@syskonnect.de
- *
- *	The technical manual for the adapters is available from SysKonnect's
- *	web pages: www.syskonnect.com
- *	
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- *****************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-#include "h/skversion.h"
-
-#include <linux/ethtool.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-
-/******************************************************************************
- *
- * Defines
- *
- *****************************************************************************/
-
-#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half  | SUPPORTED_10baseT_Full  | \
-                         SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-                         SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
-                         SUPPORTED_TP)
-
-#define ADV_COPPER_ALL  (ADVERTISED_10baseT_Half  | ADVERTISED_10baseT_Full  | \
-                         ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-                         ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
-                         ADVERTISED_TP)
-
-#define SUPP_FIBRE_ALL  (SUPPORTED_1000baseT_Full | \
-                         SUPPORTED_FIBRE          | \
-                         SUPPORTED_Autoneg)
-
-#define ADV_FIBRE_ALL   (ADVERTISED_1000baseT_Full | \
-                         ADVERTISED_FIBRE          | \
-                         ADVERTISED_Autoneg)
-
-
-/******************************************************************************
- *
- * Local Functions
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * 	getSettings - retrieves the current settings of the selected adapter
- *
- * Description:
- *	The current configuration of the selected adapter is returned.
- *	This configuration involves a)speed, b)duplex and c)autoneg plus
- *	a number of other variables.
- *
- * Returns:    always 0
- *
- */
-static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	const DEV_NET *pNet = netdev_priv(dev);
-	int port = pNet->PortNr;
-	const SK_AC *pAC = pNet->pAC;
-	const SK_GEPORT *pPort = &pAC->GIni.GP[port];
-
-	static int DuplexAutoNegConfMap[9][3]= {
-		{ -1                     , -1         , -1              },
-		{ 0                      , -1         , -1              },
-		{ SK_LMODE_HALF          , DUPLEX_HALF, AUTONEG_DISABLE },
-		{ SK_LMODE_FULL          , DUPLEX_FULL, AUTONEG_DISABLE },
-		{ SK_LMODE_AUTOHALF      , DUPLEX_HALF, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOFULL      , DUPLEX_FULL, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOBOTH      , DUPLEX_FULL, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOSENSE     , -1         , -1              },
-		{ SK_LMODE_INDETERMINATED, -1         , -1              }
-	};
-	static int SpeedConfMap[6][2] = {
-		{ 0                       , -1         },
-		{ SK_LSPEED_AUTO          , -1         },
-		{ SK_LSPEED_10MBPS        , SPEED_10   },
-		{ SK_LSPEED_100MBPS       , SPEED_100  },
-		{ SK_LSPEED_1000MBPS      , SPEED_1000 },
-		{ SK_LSPEED_INDETERMINATED, -1         }
-	};
-	static int AdvSpeedMap[6][2] = {
-		{ 0                       , -1         },
-		{ SK_LSPEED_AUTO          , -1         },
-		{ SK_LSPEED_10MBPS        , ADVERTISED_10baseT_Half   | ADVERTISED_10baseT_Full },
-		{ SK_LSPEED_100MBPS       , ADVERTISED_100baseT_Half  | ADVERTISED_100baseT_Full },
-		{ SK_LSPEED_1000MBPS      , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
-		{ SK_LSPEED_INDETERMINATED, -1         }
-	};
-
-	ecmd->phy_address = port;
-	ecmd->speed       = SpeedConfMap[pPort->PLinkSpeedUsed][1];
-	ecmd->duplex      = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
-	ecmd->autoneg     = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (pAC->GIni.GICopperType) {
-		ecmd->port        = PORT_TP;
-		ecmd->supported   = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
-		if (pAC->GIni.GIGenesis) {
-			ecmd->supported &= ~(SUPPORTED_10baseT_Half);
-			ecmd->supported &= ~(SUPPORTED_10baseT_Full);
-			ecmd->supported &= ~(SUPPORTED_100baseT_Half);
-			ecmd->supported &= ~(SUPPORTED_100baseT_Full);
-		} else {
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
-			} 
-#ifdef CHIP_ID_YUKON_FE
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
-			}
-#endif
-		}
-		if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
-			ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-				ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
-			} 
-		} else {
-			ecmd->advertising = ecmd->supported;
-		}
-
-		if (ecmd->autoneg == AUTONEG_ENABLE) 
-			ecmd->advertising |= ADVERTISED_Autoneg;
-	} else {
-		ecmd->port        = PORT_FIBRE;
-		ecmd->supported   = SUPP_FIBRE_ALL;
-		ecmd->advertising = ADV_FIBRE_ALL;
-	}
-	return 0;
-}
-
-/*
- * MIB infrastructure uses instance value starting at 1
- * based on board and port.
- */
-static inline u32 pnmiInstance(const DEV_NET *pNet)
-{
-	return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
-}
-
-/*****************************************************************************
- *
- *	setSettings - configures the settings of a selected adapter
- *
- * Description:
- *	Possible settings that may be altered are a)speed, b)duplex or 
- *	c)autonegotiation.
- *
- * Returns:
- *	0:	everything fine, no error
- *	<0:	the return value is the error code of the failure 
- */
-static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	u32 instance;
-	char buf[4];
-	int len = 1;
-
-	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100 
-	    && ecmd->speed != SPEED_1000)
-		return -EINVAL;
-
-	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
-		return -EINVAL;
-
-	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
-		return -EINVAL;
-
-	if (ecmd->autoneg == AUTONEG_DISABLE)
-		*buf = (ecmd->duplex == DUPLEX_FULL) 
-			? SK_LMODE_FULL : SK_LMODE_HALF;
-	else
-		*buf = (ecmd->duplex == DUPLEX_FULL) 
-			? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
-	
-	instance = pnmiInstance(pNet);
-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, 
-			   &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
-		return -EINVAL;
-
-	switch(ecmd->speed) {
-	case SPEED_1000:
-		*buf = SK_LSPEED_1000MBPS;
-		break;
-	case SPEED_100:
-		*buf = SK_LSPEED_100MBPS;
-		break;
-	case SPEED_10:
-		*buf = SK_LSPEED_10MBPS;
-	}
-
-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
-			 &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
-		return -EINVAL;
-
-	return 0;
-}
-
-/*****************************************************************************
- *
- * 	getDriverInfo - returns generic driver and adapter information
- *
- * Description:
- *	Generic driver information is returned via this function, such as
- *	the name of the driver, its version and and firmware version.
- *	In addition to this, the location of the selected adapter is 
- *	returned as a bus info string (e.g. '01:05.0').
- *	
- * Returns:	N/A
- *
- */
-static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	const DEV_NET	*pNet = netdev_priv(dev);
-	const SK_AC *pAC = pNet->pAC;
-	char vers[32];
-
-	snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
-		(pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
-
-	strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
-	strcpy(info->version, vers);
-	strcpy(info->fw_version, "N/A");
-	strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
-}
-
-/*
- * Ethtool statistics support.
- */
-static const char StringsStats[][ETH_GSTRING_LEN] = {
-	"rx_packets",	"tx_packets",
-	"rx_bytes",	"tx_bytes",
-	"rx_errors",	"tx_errors",	
-	"rx_dropped",	"tx_dropped",
-	"multicasts",	"collisions",	
-	"rx_length_errors",		"rx_buffer_overflow_errors",
-	"rx_crc_errors",		"rx_frame_errors",
-	"rx_too_short_errors",		"rx_too_long_errors",
-	"rx_carrier_extension_errors",	"rx_symbol_errors",
-	"rx_llc_mac_size_errors",	"rx_carrier_errors",	
-	"rx_jabber_errors",		"rx_missed_errors",
-	"tx_abort_collision_errors",	"tx_carrier_errors",
-	"tx_buffer_underrun_errors",	"tx_heartbeat_errors",
-	"tx_window_errors",
-};
-
-static int getStatsCount(struct net_device *dev)
-{
-	return ARRAY_SIZE(StringsStats);
-}
-
-static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	switch(stringset) {
-	case ETH_SS_STATS:
-		memcpy(data, *StringsStats, sizeof(StringsStats));
-		break;
-	}
-}
-
-static void getEthtoolStats(struct net_device *dev,
-			    struct ethtool_stats *stats, u64 *data)
-{
-	const DEV_NET	*pNet = netdev_priv(dev);
-	const SK_AC *pAC = pNet->pAC;
-	const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
-
-	*data++ = pPnmiStruct->Stat[0].StatRxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
-	*data++ = pPnmiStruct->InErrorsCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->RxNoBufCts;
-	*data++ = pPnmiStruct->TxNoBufCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCextCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
-	*data++ = pAC->stats.tx_aborted_errors;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pAC->stats.tx_window_errors;
-}
-
-
-/*****************************************************************************
- *
- * 	toggleLeds - Changes the LED state of an adapter
- *
- * Description:
- *	This function changes the current state of all LEDs of an adapter so
- *	that it can be located by a user. 
- *
- * Returns:	N/A
- *
- */
-static void toggleLeds(DEV_NET *pNet, int on)
-{
-	SK_AC *pAC = pNet->pAC;
-	int port = pNet->PortNr;
-	void __iomem *io = pAC->IoBase;
-
-	if (pAC->GIni.GIGenesis) {
-		SK_OUT8(io, MR_ADDR(port,LNK_LED_REG), 
-			on ? SK_LNK_ON : SK_LNK_OFF);
-		SkGeYellowLED(pAC, io, 
-			      on ? (LED_ON >> 1) : (LED_OFF >> 1));
-		SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
-			    on ? SK_LED_TST : SK_LED_DIS);
-
-		if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
-			SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL, 
-				     on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
-		else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
-			SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
-				     on ? 0x0800 : PHY_L_LC_LEDT);
-		else
-			SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
-				    on ? SK_LED_TST : SK_LED_DIS);
-	} else {
-		const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON)  |
-				      PHY_M_LED_MO_10(MO_LED_ON)   |
-				      PHY_M_LED_MO_100(MO_LED_ON)  |
-				      PHY_M_LED_MO_1000(MO_LED_ON) | 
-				      PHY_M_LED_MO_RX(MO_LED_ON));
-		const u16  YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF)  |
-					PHY_M_LED_MO_10(MO_LED_OFF)   |
-					PHY_M_LED_MO_100(MO_LED_OFF)  |
-					PHY_M_LED_MO_1000(MO_LED_OFF) | 
-					PHY_M_LED_MO_RX(MO_LED_OFF));
-	
-
-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER, 
-			     on ? YukLedOn : YukLedOff);
-	}
-}
-
-/*****************************************************************************
- *
- * 	skGeBlinkTimer - Changes the LED state of an adapter
- *
- * Description:
- *	This function changes the current state of all LEDs of an adapter so
- *	that it can be located by a user. If the requested time interval for
- *	this test has elapsed, this function cleans up everything that was 
- *	temporarily setup during the locate NIC test. This involves of course
- *	also closing or opening any adapter so that the initial board state 
- *	is recovered.
- *
- * Returns:	N/A
- *
- */
-void SkGeBlinkTimer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *) data;
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	toggleLeds(pNet, pAC->LedsOn);
-
-	pAC->LedsOn = !pAC->LedsOn;
-	mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
-}
-
-/*****************************************************************************
- *
- * 	locateDevice - start the locate NIC feature of the elected adapter 
- *
- * Description:
- *	This function is used if the user want to locate a particular NIC.
- *	All LEDs are regularly switched on and off, so the NIC can easily
- *	be identified.
- *
- * Returns:	
- *	==0:	everything fine, no error, locateNIC test was started
- *	!=0:	one locateNIC test runs already
- *
- */
-static int locateDevice(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
-		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
-	/* start blinking */
-	pAC->LedsOn = 0;
-	mod_timer(&pAC->BlinkTimer, jiffies);
-	msleep_interruptible(data * 1000);
-	del_timer_sync(&pAC->BlinkTimer);
-	toggleLeds(pNet, 0);
-
-	return 0;
-}
-
-/*****************************************************************************
- *
- * 	getPauseParams - retrieves the pause parameters
- *
- * Description:
- *	All current pause parameters of a selected adapter are placed 
- *	in the passed ethtool_pauseparam structure and are returned.
- *
- * Returns:	N/A
- *
- */
-static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause) 
-{
-	DEV_NET	*pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-
-	epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
-		  (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
-
-	epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
-	epause->autoneg = epause->rx_pause || epause->tx_pause;
-}
-
-/*****************************************************************************
- *
- *	setPauseParams - configures the pause parameters of an adapter
- *
- * Description:
- *	This function sets the Rx or Tx pause parameters 
- *
- * Returns:
- *	==0:	everything fine, no error
- *	!=0:	the return value is the error code of the failure 
- */
-static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
-{
-	DEV_NET	*pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-	u32	instance = pnmiInstance(pNet);
-	struct ethtool_pauseparam old;
-	u8	oldspeed = pPort->PLinkSpeedUsed;
-	char	buf[4];
-	int	len = 1;
-	int ret;
-
-	/*
-	** we have to determine the current settings to see if 
-	** the operator requested any modification of the flow 
-	** control parameters...
-	*/
-	getPauseParams(dev, &old);
-
-	/*
-	** perform modifications regarding the changes 
-	** requested by the operator
-	*/
-	if (epause->autoneg != old.autoneg) 
-		*buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
-	else {
-		if (epause->rx_pause && epause->tx_pause) 
-			*buf = SK_FLOW_MODE_SYMMETRIC;
-		else if (epause->rx_pause && !epause->tx_pause)
-			*buf =  SK_FLOW_MODE_SYM_OR_REM;
-		else if (!epause->rx_pause && epause->tx_pause)
-			*buf =  SK_FLOW_MODE_LOC_SEND;
-		else
-			*buf = SK_FLOW_MODE_NONE;
-	}
-
-	ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
-			 &buf, &len, instance, pNet->NetNr);
-
-	if (ret != SK_PNMI_ERR_OK) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
-			   ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
-		goto err;
-	}
-
-	/*
-	** It may be that autoneg has been disabled! Therefore
-	** set the speed to the previously used value...
-	*/
-	if (!epause->autoneg) {
-		len = 1;
-		ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
-				   &oldspeed, &len, instance, pNet->NetNr);
-		if (ret != SK_PNMI_ERR_OK) 
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
-				   ("ethtool (sk98lin): error setting speed (%i)\n", ret));
-	}
- err:
-        return ret ? -EIO : 0;
-}
-
-/* Only Yukon supports checksum offload. */
-static int setScatterGather(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-	return ethtool_op_set_sg(dev, data);
-}
-
-static int setTxCsum(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-
-	return ethtool_op_set_tx_csum(dev, data);
-}
-
-static u32 getRxCsum(struct net_device *dev)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	return pAC->RxPort[pNet->PortNr].RxCsum;
-}
-
-static int setRxCsum(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-
-	pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
-	return 0;
-}
-
-static int getRegsLen(struct net_device *dev)
-{
-	return 0x4000;
-}
-
-/*
- * Returns copy of whole control register region
- * Note: skip RAM address register because accessing it will
- * 	 cause bus hangs!
- */
-static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
-			  void *p)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	const void __iomem *io = pNet->pAC->IoBase;
-
-	regs->version = 1;
-	memset(p, 0, regs->len);
-	memcpy_fromio(p, io, B3_RAM_ADDR);
-
-	memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-		      regs->len - B3_RI_WTO_R1);
-}
-
-const struct ethtool_ops SkGeEthtoolOps = {
-	.get_settings		= getSettings,
-	.set_settings		= setSettings,
-	.get_drvinfo		= getDriverInfo,
-	.get_strings		= getStrings,
-	.get_stats_count	= getStatsCount,
-	.get_ethtool_stats	= getEthtoolStats,
-	.phys_id		= locateDevice,
-	.get_pauseparam		= getPauseParams,
-	.set_pauseparam		= setPauseParams,
-	.get_link		= ethtool_op_get_link,
-	.get_sg			= ethtool_op_get_sg,
-	.set_sg			= setScatterGather,
-	.get_tx_csum		= ethtool_op_get_tx_csum,
-	.set_tx_csum		= setTxCsum,
-	.get_rx_csum		= getRxCsum,
-	.set_rx_csum		= setRxCsum,
-	.get_regs		= getRegs,
-	.get_regs_len		= getRegsLen,
-};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
deleted file mode 100644
index 20890e4..0000000
--- a/drivers/net/sk98lin/skge.c
+++ /dev/null
@@ -1,5218 +0,0 @@
-/******************************************************************************
- *
- * Name:	skge.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.45 $
- * Date:       	$Date: 2004/02/12 14:41:02 $
- * Purpose:	The main driver source module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet 
- *      Server Adapters.
- *
- *	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)
- *
- *	Address all question to: linux@syskonnect.de
- *
- *	The technical manual for the adapters is available from SysKonnect's
- *	web pages: www.syskonnect.com
- *	Goto "Support" and search Knowledge Base for "manual".
- *	
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Possible compiler options (#define xxx / -Dxxx):
- *
- *	debugging can be enable by changing SK_DEBUG_CHKMOD and
- *	SK_DEBUG_CHKCAT in makefile (described there).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- *	This is the main module of the Linux GE driver.
- *	
- *	All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
- *	are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
- *	Those are used for drivers on multiple OS', so some thing may seem
- *	unnecessary complicated on Linux. Please do not try to 'clean up'
- *	them without VERY good reasons, because this will make it more
- *	difficult to keep the Linux driver in synchronisation with the
- *	other versions.
- *
- * Include file hierarchy:
- *
- *	<linux/module.h>
- *
- *	"h/skdrv1st.h"
- *		<linux/types.h>
- *		<linux/kernel.h>
- *		<linux/string.h>
- *		<linux/errno.h>
- *		<linux/ioport.h>
- *		<linux/slab.h>
- *		<linux/interrupt.h>
- *		<linux/pci.h>
- *		<linux/bitops.h>
- *		<asm/byteorder.h>
- *		<asm/io.h>
- *		<linux/netdevice.h>
- *		<linux/etherdevice.h>
- *		<linux/skbuff.h>
- *	    those three depending on kernel version used:
- *		<linux/bios32.h>
- *		<linux/init.h>
- *		<asm/uaccess.h>
- *		<net/checksum.h>
- *
- *		"h/skerror.h"
- *		"h/skdebug.h"
- *		"h/sktypes.h"
- *		"h/lm80.h"
- *		"h/xmac_ii.h"
- *
- *      "h/skdrv2nd.h"
- *		"h/skqueue.h"
- *		"h/skgehwt.h"
- *		"h/sktimer.h"
- *		"h/ski2c.h"
- *		"h/skgepnmi.h"
- *		"h/skvpd.h"
- *		"h/skgehw.h"
- *		"h/skgeinit.h"
- *		"h/skaddr.h"
- *		"h/skgesirq.h"
- *		"h/skrlmt.h"
- *
- ******************************************************************************/
-
-#include	"h/skversion.h"
-
-#include	<linux/in.h>
-#include	<linux/module.h>
-#include	<linux/moduleparam.h>
-#include	<linux/init.h>
-#include	<linux/dma-mapping.h>
-#include	<linux/ip.h>
-#include	<linux/mii.h>
-#include	<linux/mm.h>
-
-#include	"h/skdrv1st.h"
-#include	"h/skdrv2nd.h"
-
-/*******************************************************************************
- *
- * 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
-
-/*
- * threshold for copying small receive frames
- * set to 0 to avoid copying, set to 9001 to copy all frames
- */
-#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
- * 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 DUP_CAP_B	{"Both", }
-// #define FLOW_CTRL_A	{"SymOrRem", }
-// #define FLOW_CTRL_B	{"SymOrRem", }
-// #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)
-
-
-/* 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 SkIsrRetVar	SkGeIsr(int irq, void *dev_id);
-static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id);
-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 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*, 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 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 int	SkGeInitPCI(SK_AC *pAC);
-static void	StartDrvCleanupTimer(SK_AC *pAC);
-static void	StopDrvCleanupTimer(SK_AC *pAC);
-static int	XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
-
-#ifdef SK_DIAG_SUPPORT
-static SK_U32   ParseDeviceNbrFromSlotName(const char *SlotName);
-static int      SkDrvInitAdapter(SK_AC *pAC, int devNbr);
-static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
-#endif
-
-/*******************************************************************************
- *
- * Extern Function Prototypes
- *
- ******************************************************************************/
-extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);	
-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
-extern void SkDimStartModerationTimer(SK_AC *pAC);
-extern void SkDimModerate(SK_AC *pAC);
-extern void SkGeBlinkTimer(unsigned long data);
-
-#ifdef DEBUG
-static void	DumpMsg(struct sk_buff*, char*);
-static void	DumpData(char*, int);
-static void	DumpLong(char*, int);
-#endif
-
-/* global variables *********************************************************/
-static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
-extern const struct ethtool_ops SkGeEthtoolOps;
-
-/* local variables **********************************************************/
-static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
-static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- *	This routine writes a 32 bit value to the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-static inline int SkPciWriteCfgDWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U32 Val)		/* pointer to store the read value */
-{
-	pci_write_config_dword(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgDWord */
-
-/*****************************************************************************
- *
- * 	SkGeInitPCI - Init the PCI resources
- *
- * Description:
- *	This function initialize the PCI resources and IO
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-static __devinit int SkGeInitPCI(SK_AC *pAC)
-{
-	struct SK_NET_DEVICE *dev = pAC->dev[0];
-	struct pci_dev *pdev = pAC->PciDev;
-	int retval;
-
-	dev->mem_start = pci_resource_start (pdev, 0);
-	pci_set_master(pdev);
-
-	retval = pci_request_regions(pdev, "sk98lin");
-	if (retval)
-		goto out;
-
-#ifdef SK_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
-
-	/*
-	 * Remap the regs into kernel space.
-	 */
-	pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
-	if (!pAC->IoBase) {
-		retval = -EIO;
-		goto out_release;
-	}
-
-	return 0;
-
- out_release:
-	pci_release_regions(pdev);
- out:
-	return retval;
-}
-
-
-/*****************************************************************************
- *
- * 	FreeResources - release resources allocated for adapter
- *
- * Description:
- *	This function releases the IRQ, unmaps the IO and
- *	frees the desriptor ring.
- *
- * Returns: N/A
- *	
- */
-static void FreeResources(struct SK_NET_DEVICE *dev)
-{
-SK_U32 AllocFlag;
-DEV_NET		*pNet;
-SK_AC		*pAC;
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	AllocFlag = pAC->AllocFlag;
-	if (pAC->PciDev) {
-		pci_release_regions(pAC->PciDev);
-	}
-	if (AllocFlag & SK_ALLOC_IRQ) {
-		free_irq(dev->irq, dev);
-	}
-	if (pAC->IoBase) {
-		iounmap(pAC->IoBase);
-	}
-	if (pAC->pDescrMem) {
-		BoardFreeMem(pAC);
-	}
-	
-} /* FreeResources */
-
-MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
-MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
-MODULE_LICENSE("GPL");
-
-#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;
-#else
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_A
-static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
-#else
-static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_A
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
-#else
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_A
-static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
-#else
-static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_B
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
-#else
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_B
-static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
-#else
-static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_B
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
-#else
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_B
-static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
-#else
-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
-static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef RLMT_MODE
-static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
-#else
-static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-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];
-
-module_param_array(Speed_A, charp, NULL, 0);
-module_param_array(Speed_B, charp, NULL, 0);
-module_param_array(AutoNeg_A, charp, NULL, 0);
-module_param_array(AutoNeg_B, charp, NULL, 0);
-module_param_array(DupCap_A, charp, NULL, 0);
-module_param_array(DupCap_B, charp, NULL, 0);
-module_param_array(FlowCtrl_A, charp, NULL, 0);
-module_param_array(FlowCtrl_B, charp, NULL, 0);
-module_param_array(Role_A, charp, NULL, 0);
-module_param_array(Role_B, charp, NULL, 0);
-module_param_array(ConType, charp, NULL, 0);
-module_param_array(PrefPort, charp, NULL, 0);
-module_param_array(RlmtMode, charp, NULL, 0);
-/* used for interrupt moderation */
-module_param_array(IntsPerSec, int, NULL, 0);
-module_param_array(Moderation, charp, NULL, 0);
-module_param_array(Stats, charp, NULL, 0);
-module_param_array(ModerationMask, charp, NULL, 0);
-module_param_array(AutoSizing, charp, NULL, 0);
-
-/*****************************************************************************
- *
- * 	SkGeBoardInit - do level 0 and 1 initialization
- *
- * Description:
- *	This function prepares the board hardware for running. The desriptor
- *	ring is set up, the IRQ is allocated and the configuration settings
- *	are examined.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int __devinit 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));
-	for (i=0; i<SK_MAX_MACS; i++) {
-		pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
-		pAC->TxPort[i][0].PortIndex = i;
-		pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
-		pAC->RxPort[i].PortIndex = i;
-	}
-
-	/* 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);
-	}
-	spin_lock_init(&pAC->SlowPathLock);
-
-	/* setup phy_id blink timer */
-	pAC->BlinkTimer.function = SkGeBlinkTimer;
-	pAC->BlinkTimer.data = (unsigned long) dev;
-	init_timer(&pAC->BlinkTimer);
-
-	/* level 0 init common modules here */
-	
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	/* Does a RESET on board ...*/
-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
-		printk("HWInit (0) failed.\n");
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		return -EIO;
-	}
-	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 = SK_INIT_DATA;
-	pAC->RxBufSize  = ETH_BUF_SIZE;
-
-	SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
-	SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
-
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	/* level 1 init common modules here (HW init) */
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
-		printk("sk98lin: HWInit (1) failed.\n");
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		return -EIO;
-	}
-	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);
-
-	/* Set chipset type support */
-	pAC->ChipsetType = 0;
-	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
-		(pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
-		pAC->ChipsetType = 1;
-	}
-
-	GetConfiguration(pAC);
-	if (pAC->RlmtNets == 2) {
-		pAC->GIni.GIPortUsage = SK_MUL_LINK;
-	}
-
-	pAC->BoardLevel = SK_INIT_IO;
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	if (pAC->GIni.GIMacsFound == 2) {
-		 Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
-	} else if (pAC->GIni.GIMacsFound == 1) {
-		Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED,
-			"sk98lin", dev);
-	} else {
-		printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
-		       pAC->GIni.GIMacsFound);
-		return -EIO;
-	}
-
-	if (Ret) {
-		printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
-		       dev->irq);
-		return Ret;
-	}
-	pAC->AllocFlag |= SK_ALLOC_IRQ;
-
-	/* Alloc memory for this board (Mem for RxD/TxD) : */
-	if(!BoardAllocMem(pAC)) {
-		printk("No memory for descriptor rings.\n");
-		return -ENOMEM;
-	}
-
-	BoardInitMem(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("sk98lin: SkGeInitAssignRamToQueues failed.\n");
-		return -EIO;
-	}
-
-	return (0);
-} /* SkGeBoardInit */
-
-
-/*****************************************************************************
- *
- * 	BoardAllocMem - allocate the memory for the descriptor rings
- *
- * Description:
- *	This function allocates the memory for all descriptor rings.
- *	Each ring is aligned for the desriptor alignment and no ring
- *	has a 4 GByte boundary in it (because the upper 32 bit must
- *	be constant for all descriptiors in one rings).
- *
- * Returns:
- *	SK_TRUE, if all memory could be allocated
- *	SK_FALSE, if not
- */
-static __devinit SK_BOOL BoardAllocMem(SK_AC	*pAC)
-{
-caddr_t		pDescrMem;	/* pointer to descriptor memory area */
-size_t		AllocLength;	/* length of complete descriptor area */
-int		i;		/* loop counter */
-unsigned long	BusAddr;
-
-	
-	/* rings plus one for alignment (do not cross 4 GB boundary) */
-	/* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
-#if (BITS_PER_LONG == 32)
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
-		+ RX_RING_SIZE + 8;
-#endif
-
-	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.
-	 */
-	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",
-			i, (unsigned long) pDescrMem,
-			BusAddr));
-		pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
-		pAC->TxPort[i][0].VTxDescrRing = BusAddr;
-		pDescrMem += TX_RING_SIZE;
-		BusAddr += TX_RING_SIZE;
-	
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-			("RX%d: pDescrMem: %lX,   PhysDescrMem: %lX\n",
-			i, (unsigned long) pDescrMem,
-			(unsigned long)BusAddr));
-		pAC->RxPort[i].pRxDescrRing = pDescrMem;
-		pAC->RxPort[i].VRxDescrRing = BusAddr;
-		pDescrMem += RX_RING_SIZE;
-		BusAddr += RX_RING_SIZE;
-	} /* for */
-	
-	return (SK_TRUE);
-} /* BoardAllocMem */
-
-
-/****************************************************************************
- *
- *	BoardFreeMem - reverse of BoardAllocMem
- *
- * Description:
- *	Free all memory allocated in BoardAllocMem: adapter context,
- *	descriptor rings, locks.
- *
- * Returns:	N/A
- */
-static void BoardFreeMem(
-SK_AC		*pAC)
-{
-size_t		AllocLength;	/* length of complete descriptor area */
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("BoardFreeMem\n"));
-#if (BITS_PER_LONG == 32)
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
-		+ RX_RING_SIZE + 8;
-#endif
-
-	pci_free_consistent(pAC->PciDev, AllocLength,
-			    pAC->pDescrMem, pAC->pDescrMemDMA);
-	pAC->pDescrMem = NULL;
-} /* BoardFreeMem */
-
-
-/*****************************************************************************
- *
- * 	BoardInitMem - initiate the descriptor rings
- *
- * Description:
- *	This function sets the descriptor rings up in memory.
- *	The adapter is initialized with the descriptor start addresses.
- *
- * Returns:	N/A
- */
-static __devinit void BoardInitMem(SK_AC *pAC)
-{
-int	i;		/* loop counter */
-int	RxDescrSize;	/* the size of a rx descriptor rounded up to alignment*/
-int	TxDescrSize;	/* the size of a tx descriptor rounded up to alignment*/
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("BoardInitMem\n"));
-
-	RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
-	pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
-	TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
-	pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
-	
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		SetupRing(
-			pAC,
-			pAC->TxPort[i][0].pTxDescrRing,
-			pAC->TxPort[i][0].VTxDescrRing,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingHead,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingTail,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
-			&pAC->TxPort[i][0].TxdRingFree,
-			SK_TRUE);
-		SetupRing(
-			pAC,
-			pAC->RxPort[i].pRxDescrRing,
-			pAC->RxPort[i].VRxDescrRing,
-			&pAC->RxPort[i].pRxdRingHead,
-			&pAC->RxPort[i].pRxdRingTail,
-			&pAC->RxPort[i].pRxdRingPrev,
-			&pAC->RxPort[i].RxdRingFree,
-			SK_FALSE);
-	}
-} /* BoardInitMem */
-
-
-/*****************************************************************************
- *
- * 	SetupRing - create one descriptor ring
- *
- * Description:
- *	This function creates one descriptor ring in the given memory area.
- *	The head, tail and number of free descriptors in the ring are set.
- *
- * Returns:
- *	none
- */
-static void SetupRing(
-SK_AC		*pAC,
-void		*pMemArea,	/* a pointer to the memory area for the ring */
-uintptr_t	VMemArea,	/* the virtual bus address of the memory area */
-RXD		**ppRingHead,	/* address where the head should be written */
-RXD		**ppRingTail,	/* address where the tail should be written */
-RXD		**ppRingPrev,	/* address where the tail should be written */
-int		*pRingFree,	/* address where the # of free descr. goes */
-SK_BOOL		IsTx)		/* flag: is this a tx ring */
-{
-int	i;		/* loop counter */
-int	DescrSize;	/* the size of a descriptor rounded up to alignment*/
-int	DescrNum;	/* number of descriptors per ring */
-RXD	*pDescr;	/* pointer to a descriptor (receive or transmit) */
-RXD	*pNextDescr;	/* pointer to the next descriptor */
-RXD	*pPrevDescr;	/* pointer to the previous descriptor */
-uintptr_t VNextDescr;	/* the virtual bus address of the next descriptor */
-
-	if (IsTx == SK_TRUE) {
-		DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
-			DESCR_ALIGN;
-		DescrNum = TX_RING_SIZE / DescrSize;
-	} else {
-		DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
-			DESCR_ALIGN;
-		DescrNum = RX_RING_SIZE / DescrSize;
-	}
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-		("Descriptor size: %d   Descriptor Number: %d\n",
-		DescrSize,DescrNum));
-	
-	pDescr = (RXD*) pMemArea;
-	pPrevDescr = NULL;
-	pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
-	VNextDescr = VMemArea + DescrSize;
-	for(i=0; i<DescrNum; i++) {
-		/* set the pointers right */
-		pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
-		pDescr->pNextRxd = pNextDescr;
-		if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
-
-		/* advance one step */
-		pPrevDescr = pDescr;
-		pDescr = pNextDescr;
-		pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
-		VNextDescr += DescrSize;
-	}
-	pPrevDescr->pNextRxd = (RXD*) pMemArea;
-	pPrevDescr->VNextRxd = VMemArea;
-	pDescr = (RXD*) pMemArea;
-	*ppRingHead = (RXD*) pMemArea;
-	*ppRingTail = *ppRingHead;
-	*ppRingPrev = pPrevDescr;
-	*pRingFree = DescrNum;
-} /* SetupRing */
-
-
-/*****************************************************************************
- *
- * 	PortReInitBmu - re-initiate the descriptor rings for one port
- *
- * Description:
- *	This function reinitializes the descriptor rings of one port
- *	in memory. The port must be stopped before.
- *	The HW is initialized with the descriptor start addresses.
- *
- * Returns:
- *	none
- */
-static void PortReInitBmu(
-SK_AC	*pAC,		/* pointer to adapter context */
-int	PortIndex)	/* index of the port for which to re-init */
-{
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("PortReInitBmu "));
-
-	/* set address of first descriptor of ring in BMU */
-	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]+ 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]+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]+Q_DA_H,
-		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
-		pAC->RxPort[PortIndex].pRxDescrRing +
-		pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
-} /* PortReInitBmu */
-
-
-/****************************************************************************
- *
- *	SkGeIsr - handle adapter interrupts
- *
- * Description:
- *	The interrupt routine is called when the network adapter
- *	generates an interrupt. It may also be called if another device
- *	shares this interrupt vector with the driver.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsr(int irq, void *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 */	
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	/*
-	 * Check and process if its our interrupt
-	 */
-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
-	if (IntSrc == 0) {
-		return SkIsrRetNone;
-	}
-
-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
-		if (IntSrc & IS_IRQ_SW) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("Software IRQ\n"));
-		}
-#endif
-		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_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 0);
-		}
-		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_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 1);
-		}
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		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);
-			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 & 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);
-			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 & 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);
-			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 & 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);
-			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
-#endif
-
-		/* do all IO at once */
-		if (IntSrc & IS_R1_F)
-			ClearAndStartRx(pAC, 0);
-		if (IntSrc & IS_R2_F)
-			ClearAndStartRx(pAC, 1);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F)
-			ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-		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 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
-	 * 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);
-	 */
-
-	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, pAC->GIni.GIValIrqMask);
-
-		return SkIsrRetHandled;
-} /* SkGeIsr */
-
-
-/****************************************************************************
- *
- *	SkGeIsrOnePort - handle adapter interrupts for single port adapter
- *
- * Description:
- *	The interrupt routine is called when the network adapter
- *	generates an interrupt. It may also be called if another device
- *	shares this interrupt vector with the driver.
- *	This is the same as above, but handles only one port.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *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 */	
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	/*
-	 * Check and process if its our interrupt
-	 */
-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
-	if (IntSrc == 0) {
-		return SkIsrRetNone;
-	}
-	
-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
-		if (IntSrc & IS_IRQ_SW) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("Software IRQ\n"));
-		}
-#endif
-		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_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 0);
-		}
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		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);
-			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 & 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);
-			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
-#endif
-
-		/* do all IO at once */
-		if (IntSrc & IS_R1_F)
-			ClearAndStartRx(pAC, 0);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		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 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
-	 * 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);
-	 */
-
-	/* IRQ is processed - Enable IRQs again*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
-		return SkIsrRetHandled;
-} /* SkGeIsrOnePort */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/****************************************************************************
- *
- * 	SkGePollController - polling receive, for netconsole
- *
- * Description:
- *	Polling receive - used by netconsole and other diagnostic tools
- *	to allow network i/o with interrupts disabled.
- *
- * Returns: N/A
- */
-static void SkGePollController(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	SkGeIsr(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-/****************************************************************************
- *
- *	SkGeOpen - handle start of initialized adapter
- *
- * Description:
- *	This function starts the initialized adapter.
- *	The board level variable is set and the adapter is
- *	brought to full functionality.
- *	The device flags are set for operation.
- *	Do all necessary level 2 initialization, enable interrupts and
- *	give start command to RLMT.
- *
- * Returns:
- *	0 on success
- *	!= 0 on error
- */
-static int SkGeOpen(
-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 */
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-			return (-1);   /* still in use by diag; deny actions */
-		} 
-	}
-#endif
-
-	/* Set blink mode */
-	if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
-		pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
-
-	if (pAC->BoardLevel == SK_INIT_DATA) {
-		/* level 1 init common modules here */
-		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, 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;
-	}
-
-	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);
-
-	StartDrvCleanupTimer(pAC);
-	SkDimEnableModerationIfNeeded(pAC);	
-	SkDimDisplayModerationSettings(pAC);
-
-	pAC->GIni.GIValIrqMask &= IRQ_MASK;
-
-	/* enable Interrupts */
-	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);
-
-	if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
-		EvPara.Para32[0] = pAC->RlmtNets;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
-			EvPara);
-		EvPara.Para32[0] = pAC->RlmtMode;
-		EvPara.Para32[1] = 0;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
-			EvPara);
-	}
-
-	EvPara.Para32[0] = pNet->NetNr;
-	EvPara.Para32[1] = -1;
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	SkEventDispatcher(pAC, pAC->IoBase);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	pAC->MaxPorts++;
-
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeOpen suceeded\n"));
-
-	return (0);
-} /* SkGeOpen */
-
-
-/****************************************************************************
- *
- *	SkGeClose - Stop initialized adapter
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkGeClose(
-struct SK_NET_DEVICE	*dev)
-{
-	DEV_NET		*pNet;
-	DEV_NET		*newPtrNet;
-	SK_AC		*pAC;
-
-	unsigned long	Flags;		/* for spin lock */
-	int		i;
-	int		PortIdx;
-	SK_EVPARA	EvPara;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->DiagFlowCtrl == SK_FALSE) {
-			/* 
-			** notify that the interface which has been closed
-			** by operator interaction must not be started up 
-			** again when the DIAG has finished. 
-			*/
-			newPtrNet = netdev_priv(pAC->dev[0]);
-			if (newPtrNet == pNet) {
-				pAC->WasIfUp[0] = SK_FALSE;
-			} else {
-				pAC->WasIfUp[1] = SK_FALSE;
-			}
-			return 0; /* return to system everything is fine... */
-		} else {
-			pAC->DiagFlowCtrl = SK_FALSE;
-		}
-	}
-#endif
-
-	netif_stop_queue(dev);
-
-	if (pAC->RlmtNets == 1)
-		PortIdx = pAC->ActivePort;
-	else
-		PortIdx = pNet->NetNr;
-
-        StopDrvCleanupTimer(pAC);
-
-	/*
-	 * Clear multicast table, promiscuous mode ....
-	 */
-	SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-	SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-		SK_PROM_MODE_NONE);
-
-	if (pAC->MaxPorts == 1) {
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		EvPara.Para32[0] = pNet->NetNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		/* stop the hardware */
-		SkGeDeInit(pAC, pAC->IoBase);
-		pAC->BoardLevel = SK_INIT_DATA;
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	} else {
-
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		EvPara.Para32[0] = pNet->NetNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		
-		/* Stop port */
-		spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
-			[TX_PRIO_LOW].TxDesRingLock, Flags);
-		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], 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], SK_TRUE);
-		ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
-		ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
-	}
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeClose: done "));
-
-	SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
-	SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-
-	pAC->MaxPorts--;
-
-	return (0);
-} /* SkGeClose */
-
-
-/*****************************************************************************
- *
- * 	SkGeXmit - Linux frame transmit function
- *
- * Description:
- *	The system calls this function to send frames onto the wire.
- *	It puts the frame in the tx descriptor ring. If the ring is
- *	full then, the 'tbusy' flag is set.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- * WARNING: returning 1 in 'tbusy' case caused system crashes (double
- *	allocated skb's) !!!
- */
-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 = netdev_priv(dev);
-	pAC = pNet->pAC;
-
-	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) {
-		netif_stop_queue(dev);
-	}
-
-	/* If not taken, give buffer ownership back to the
-	 * queueing layer.
-	 */
-	if (Rc < 0)
-		return (1);
-
-	dev->trans_start = jiffies;
-	return (0);
-} /* SkGeXmit */
-
-
-/*****************************************************************************
- *
- * 	XmitFrame - fill one socket buffer into the transmit ring
- *
- * Description:
- *	This function puts a message into the transmit descriptor ring
- *	if there is a descriptors left.
- *	Linux skb's consist of only one continuous buffer.
- *	The first step locks the ring. It is held locked
- *	all time to avoid problems with SWITCH_../PORT_RESET.
- *	Then the descriptoris allocated.
- *	The second part is linking the buffer to the descriptor.
- *	At the very last, the Control field of the descriptor
- *	is made valid for the BMU and a start TX command is given
- *	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)
- */
-static int XmitFrame(
-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;		/* the rxd to fill */
-	TXD		*pOldTxd;
-	unsigned long	 Flags;
-	SK_U64		 PhysAddr;
-	int		 BytesSend = pMessage->len;
-
-	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.
-		** Maybe free'ing some old one help?
-		*/
-		FreeTxDescriptors(pAC, pTxPort);
-		if (pTxPort->TxdRingFree == 0) {
-			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,
-				("XmitFrame failed\n"));
-			/* 
-			** 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);
-		}
-	}
-
-	/*
-	** 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) {
-		if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-			return 0;
-		}
-		pMessage->len = C_LEN_ETHERNET_MINSIZE;
-	}
-
-	/* 
-	** 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--;
-
-#ifdef SK_DUMP_TX
-	DumpMsg(pMessage, "XmitFrame");
-#endif
-
-	/* 
-	** 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;
-
-	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
-		u16 hdrlen = skb_transport_offset(pMessage);
-		u16 offset = hdrlen + pMessage->csum_offset;
-
-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
-			(pAC->GIni.GIChipRev == 0) &&
-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-			pTxd->TBControl = BMU_TCP_CHECK;
-		} else {
-			pTxd->TBControl = BMU_UDP_CHECK;
-		}
-
-		pTxd->TcpSumOfs = 0;
-		pTxd->TcpSumSt  = hdrlen;
-		pTxd->TcpSumWr  = offset;
-
-		pTxd->TBControl |= BMU_OWN | BMU_STF | 
-				   BMU_SW  | BMU_EOF |
-#ifdef USE_TX_COMPLETE
-				   BMU_IRQ_EOF |
-#endif
-				   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;
-	}
-
-	/* 
-	** 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) {
-		return (BytesSend);
-	} 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;
-	skb_frag_t	*sk_frag;
-	SK_U64		 PhysAddr;
-	unsigned long	 Flags;
-	SK_U32		 Control;
-
-	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;
-
-	/* 
-	** 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_PARTIAL) {
-		u16 hdrlen = skb_transport_offset(pMessage);
-		u16 offset = hdrlen + pMessage->csum_offset;
-
-		Control = BMU_STFWD;
-
-		/* 
-		** We have to use the opcode for tcp here,  because the
-		** opcode for udp is not working in the hardware yet 
-		** (Revision 2.0)
-		*/
-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
-			(pAC->GIni.GIChipRev == 0) &&
-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-			Control |= BMU_TCP_CHECK;
-		} else {
-			Control |= BMU_UDP_CHECK;
-		}
-
-		pTxd->TcpSumOfs = 0;
-		pTxd->TcpSumSt  = hdrlen;
-		pTxd->TcpSumWr  = offset;
-	} else
-		Control = BMU_CHECK | BMU_SW;
-
-	pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
-
-	pTxd = pTxd->pNextTxd;
-	pTxPort->TxdRingFree--;
-	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;
-		
-		pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
-
-		/* 
-		** Do we have the last fragment? 
-		*/
-		if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags )  {
-#ifdef USE_TX_COMPLETE
-			pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
-#else
-			pTxd->TBControl |= BMU_EOF;
-#endif
-			pTxdFst->TBControl |= BMU_OWN | BMU_SW;
-		}
-		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);
-	}
-}
-
-/*****************************************************************************
- *
- * 	FreeTxDescriptors - release descriptors from the descriptor ring
- *
- * Description:
- *	This function releases descriptors from a transmit ring if they
- *	have been sent by the BMU.
- *	If a descriptors is sent, it can be freed and the message can
- *	be freed, too.
- *	The SOFTWARE controllable bit is used to prevent running around a
- *	completely free ring for ever. If this bit is no set in the
- *	frame (by XmitFrame), this frame has never been sent or is
- *	already freed.
- *	The Tx descriptor ring lock must be held while calling this function !!!
- *
- * Returns:
- *	none
- */
-static void FreeTxDescriptors(
-SK_AC	*pAC,		/* pointer to the adapter context */
-TX_PORT	*pTxPort)	/* pointer to destination port structure */
-{
-TXD	*pTxd;		/* pointer to the checked descriptor */
-TXD	*pNewTail;	/* pointer to 'end' of the ring */
-SK_U32	Control;	/* TBControl field of descriptor */
-SK_U64	PhysAddr;	/* address of DMA mapping */
-
-	pNewTail = pTxPort->pTxdRingTail;
-	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 & 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_wake_queue(pAC->dev[pTxPort->PortIndex]);
-			return;
-		}
-		if (Control & BMU_OWN) {
-			pTxPort->pTxdRingTail = pTxd;
-			if (pTxPort->TxdRingFree > 0) {
-				netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
-			}
-			return;
-		}
-		
-		/* 
-		** 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);
-
-		if (Control & BMU_EOF)
-			DEV_KFREE_SKB_ANY(pTxd->pMBuf);	/* free message */
-
-		pTxPort->TxdRingFree++;
-		pTxd->TBControl &= ~BMU_SW;
-		pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
-	} /* while(forever) */
-} /* FreeTxDescriptors */
-
-/*****************************************************************************
- *
- * 	FillRxRing - fill the receive ring with valid descriptors
- *
- * Description:
- *	This function fills the receive ring descriptors with data
- *	segments and makes them valid for the BMU.
- *	The active ring is filled completely, if possible.
- *	The non-active ring is filled only partial to save memory.
- *
- * Description of rx ring structure:
- *	head - points to the descriptor which will be used next by the BMU
- *	tail - points to the next descriptor to give to the BMU
- *	
- * Returns:	N/A
- */
-static void FillRxRing(
-SK_AC		*pAC,		/* pointer to the adapter context */
-RX_PORT		*pRxPort)	/* ptr to port struct for which the ring
-				   should be filled */
-{
-unsigned long	Flags;
-
-	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
-	while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
-		if(!FillRxDescriptor(pAC, pRxPort))
-			break;
-	}
-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* FillRxRing */
-
-
-/*****************************************************************************
- *
- * 	FillRxDescriptor - fill one buffer into the receive ring
- *
- * Description:
- *	The function allocates a new receive buffer and
- *	puts it into the next descriptor.
- *
- * Returns:
- *	SK_TRUE - a buffer was added to the ring
- *	SK_FALSE - a buffer could not be added
- */
-static SK_BOOL FillRxDescriptor(
-SK_AC		*pAC,		/* pointer to the adapter context struct */
-RX_PORT		*pRxPort)	/* ptr to port struct of ring to fill */
-{
-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
-RXD		*pRxd;		/* the rxd to fill */
-SK_U16		Length;		/* data fragment length */
-SK_U64		PhysAddr;	/* physical address of a rx buffer */
-
-	pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
-	if (pMsgBlock == NULL) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-			SK_DBGCAT_DRV_ENTRY,
-			("%s: Allocation of rx buffer failed !\n",
-			pAC->dev[pRxPort->PortIndex]->name));
-		SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
-		return(SK_FALSE);
-	}
-	skb_reserve(pMsgBlock, 2); /* to align IP frames */
-	/* skb allocated ok, so add buffer */
-	pRxd = pRxPort->pRxdRingTail;
-	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);
-	pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-	pRxd->pMBuf     = pMsgBlock;
-	pRxd->RBControl = BMU_OWN       | 
-			  BMU_STF       | 
-			  BMU_IRQ_EOF   | 
-			  BMU_TCP_CHECK | 
-			  Length;
-	return (SK_TRUE);
-
-} /* FillRxDescriptor */
-
-
-/*****************************************************************************
- *
- * 	ReQueueRxBuffer - fill one buffer back into the receive ring
- *
- * Description:
- *	Fill a given buffer back into the rx ring. The buffer
- *	has been previously allocated and aligned, and its phys.
- *	address calculated, so this is no more necessary.
- *
- * Returns: N/A
- */
-static void ReQueueRxBuffer(
-SK_AC		*pAC,		/* pointer to the adapter context struct */
-RX_PORT		*pRxPort,	/* ptr to port struct of ring to fill */
-struct sk_buff	*pMsg,		/* pointer to the buffer */
-SK_U32		PhysHigh,	/* phys address high dword */
-SK_U32		PhysLow)	/* phys address low dword */
-{
-RXD		*pRxd;		/* the rxd to fill */
-SK_U16		Length;		/* data fragment length */
-
-	pRxd = pRxPort->pRxdRingTail;
-	pRxPort->pRxdRingTail = pRxd->pNextRxd;
-	pRxPort->RxdRingFree--;
-	Length = pAC->RxBufSize;
-
-	pRxd->VDataLow  = PhysLow;
-	pRxd->VDataHigh = PhysHigh;
-	pRxd->pMBuf     = pMsg;
-	pRxd->RBControl = BMU_OWN       | 
-			  BMU_STF       |
-			  BMU_IRQ_EOF   | 
-			  BMU_TCP_CHECK | 
-			  Length;
-	return;
-} /* ReQueueRxBuffer */
-
-/*****************************************************************************
- *
- * 	ReceiveIrq - handle a receive IRQ
- *
- * Description:
- *	This function is called when a receive IRQ is set.
- *	It walks the receive descriptor ring and sends up all
- *	frames that are complete.
- *
- * Returns:	N/A
- */
-static void ReceiveIrq(
-	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 */	
-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_BOOL  IsBadFrame; 			/* Bad frame */
-
-SK_U32			FrameStat;
-SK_U64			PhysAddr;
-
-rx_start:	
-	/* do forever; exit if BMU_OWN found */
-	for ( pRxd = pRxPort->pRxdRingHead ;
-		  pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
-		  pRxd = pRxd->pNextRxd,
-		  pRxPort->pRxdRingHead = pRxd,
-		  pRxPort->RxdRingFree ++) {
-
-		/*
-		 * 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.
-		 * On entry of this loop pRxd is a pointer to the Rxd that needs
-		 * to be checked next.
-		 */
-
-		Control = pRxd->RBControl;
-	
-		/* check if this descriptor is ready */
-		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 & BMU_BBC;
-		if (FrameLength > pAC->RxBufSize) {
-			goto rx_failed;
-		}
-
-		/* check for STF and 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 & 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));
-
-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
-				pRxd->VDataHigh, pRxd->VDataLow);
-
-			continue;
-		}
-
-		/*
-		 * if short frame then copy data to reduce memory waste
-		 */
-		if ((FrameLength < SK_COPY_THRESHOLD) &&
-			((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
-			/*
-			 * Short frame detected and allocation successfull
-			 */
-			/* use new skb and copy data */
-			skb_reserve(pNewMsg, 2);
-			skb_put(pNewMsg, FrameLength);
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-
-			pci_dma_sync_single_for_cpu(pAC->PciDev,
-						    (dma_addr_t) PhysAddr,
-						    FrameLength,
-						    PCI_DMA_FROMDEVICE);
-			skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength);
-
-			pci_dma_sync_single_for_device(pAC->PciDev,
-						       (dma_addr_t) PhysAddr,
-						       FrameLength,
-						       PCI_DMA_FROMDEVICE);
-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
-				pRxd->VDataHigh, pRxd->VDataLow);
-
-			pMsg = pNewMsg;
-
-		}
-		else {
-			/*
-			 * if large frame, or SKB allocation failed, pass
-			 * the SKB directly to the networking
-			 */
-
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-
-			/* release the DMA mapping */
-			pci_unmap_single(pAC->PciDev,
-					 PhysAddr,
-					 pAC->RxBufSize - 2,
-					 PCI_DMA_FROMDEVICE);
-
-			/* set length in message */
-			skb_put(pMsg, FrameLength);
-		} /* frame > SK_COPY_TRESHOLD */
-
-#ifdef USE_SK_RX_CHECKSUM
-		pMsg->csum = pRxd->TcpSums & 0xffff;
-		pMsg->ip_summed = CHECKSUM_COMPLETE;
-#else
-		pMsg->ip_summed = CHECKSUM_NONE;
-#endif
-
-		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;
-#endif
-			SK_RLMT_LOOKAHEAD(pAC, PortIndex,
-				&pMsg->data[Offset],
-				IsBc, IsMc, &ForRlmt);
-		}
-		if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
-					SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("W"));
-			/* send up only frames from active port */
-			if ((PortIndex == pAC->ActivePort) ||
-				(pAC->RlmtNets == 2)) {
-				/* frame for upper layer */
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
-#ifdef xDEBUG
-				DumpMsg(pMsg, "Rx");
-#endif
-				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
-					FrameLength, pRxPort->PortIndex);
-
-				pMsg->protocol = eth_type_trans(pMsg,
-					pAC->dev[pRxPort->PortIndex]);
-				netif_rx(pMsg);
-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
-			}
-			else {
-				/* drop frame */
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("D"));
-				DEV_KFREE_SKB(pMsg);
-			}
-			
-		} /* if not for rlmt */
-		else {
-			/* packet for rlmt */
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
-			pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
-				pAC->IoBase, FrameLength);
-			if (pRlmtMbuf != NULL) {
-				pRlmtMbuf->pNext = NULL;
-				pRlmtMbuf->Length = FrameLength;
-				pRlmtMbuf->PortIdx = PortIndex;
-				EvPara.pParaPtr = pRlmtMbuf;
-				memcpy((char*)(pRlmtMbuf->pData),
-					   (char*)(pMsg->data),
-					   FrameLength);
-
-				/* 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 &
-				(IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
-				(ForRlmt & SK_RLMT_RX_PROTOCOL) ==
-				SK_RLMT_RX_PROTOCOL) {
-				pMsg->protocol = eth_type_trans(pMsg,
-					pAC->dev[pRxPort->PortIndex]);
-				netif_rx(pMsg);
-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
-			}
-			else {
-				DEV_KFREE_SKB(pMsg);
-			}
-
-		} /* if packet for rlmt */
-	} /* for ... scanning the RXD ring */
-
-	/* RXD ring is empty -> fill and restart */
-	FillRxRing(pAC, pRxPort);
-	/* do not start if called from Close */
-	if (pAC->BoardLevel > SK_INIT_DATA) {
-		ClearAndStartRx(pAC, PortIndex);
-	}
-	return;
-
-rx_failed:
-	/* remove error frame */
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
-		("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);
-	DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
-	pRxd->pMBuf = NULL;
-	pRxPort->RxdRingFree++;
-	pRxPort->pRxdRingHead = pRxd->pNextRxd;
-	goto rx_start;
-
-} /* ReceiveIrq */
-
-
-/*****************************************************************************
- *
- * 	ClearAndStartRx - give a start receive command to BMU, clear IRQ
- *
- * Description:
- *	This function sends a start command and a clear interrupt
- *	command for one receive queue to the BMU.
- *
- * Returns: N/A
- *	none
- */
-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]+Q_CSR,
-		CSR_START | CSR_IRQ_CL_F);
-} /* ClearAndStartRx */
-
-
-/*****************************************************************************
- *
- * 	ClearTxIrq - give a clear transmit IRQ command to BMU
- *
- * Description:
- *	This function sends a clear tx IRQ command for one
- *	transmit queue to the BMU.
- *
- * Returns: N/A
- */
-static void ClearTxIrq(
-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]+Q_CSR,
-		CSR_IRQ_CL_F);
-} /* ClearTxIrq */
-
-
-/*****************************************************************************
- *
- * 	ClearRxRing - remove all buffers from the receive ring
- *
- * Description:
- *	This function removes all receive buffers from the ring.
- *	The receive BMU must be stopped before calling this function.
- *
- * Returns: N/A
- */
-static void ClearRxRing(
-SK_AC	*pAC,		/* pointer to adapter context */
-RX_PORT	*pRxPort)	/* pointer to rx port struct */
-{
-RXD		*pRxd;	/* pointer to the current descriptor */
-unsigned long	Flags;
-SK_U64		PhysAddr;
-
-	if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
-		return;
-	}
-	spin_lock_irqsave(&pRxPort->RxDesRingLock, 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);
-			DEV_KFREE_SKB(pRxd->pMBuf);
-			pRxd->pMBuf = NULL;
-		}
-		pRxd->RBControl &= BMU_OWN;
-		pRxd = pRxd->pNextRxd;
-		pRxPort->RxdRingFree++;
-	} while (pRxd != pRxPort->pRxdRingTail);
-	pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* ClearRxRing */
-
-/*****************************************************************************
- *
- *	ClearTxRing - remove all buffers from the transmit ring
- *
- * Description:
- *	This function removes all transmit buffers from the ring.
- *	The transmit BMU must be stopped before calling this function
- *	and transmitting at the upper level must be disabled.
- *	The BMU own bit of all descriptors is cleared, the rest is
- *	done by calling FreeTxDescriptors.
- *
- * Returns: N/A
- */
-static void ClearTxRing(
-SK_AC	*pAC,		/* pointer to adapter context */
-TX_PORT	*pTxPort)	/* pointer to tx prt struct */
-{
-TXD		*pTxd;		/* pointer to the current descriptor */
-int		i;
-unsigned long	Flags;
-
-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-	pTxd = pTxPort->pTxdRingHead;
-	for (i=0; i<pAC->TxDescrPerRing; i++) {
-		pTxd->TBControl &= ~BMU_OWN;
-		pTxd = pTxd->pNextTxd;
-	}
-	FreeTxDescriptors(pAC, pTxPort);
-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-} /* ClearTxRing */
-
-/*****************************************************************************
- *
- * 	SkGeSetMacAddr - Set the hardware MAC address
- *
- * Description:
- *	This function sets the MAC address used by the adapter.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
-{
-
-DEV_NET *pNet = netdev_priv(dev);
-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))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
-	
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	if (pAC->RlmtNets == 2)
-		SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-	else
-		SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-
-	
-	
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	return 0;
-} /* SkGeSetMacAddr */
-
-
-/*****************************************************************************
- *
- * 	SkGeSetRxMode - set receive mode
- *
- * Description:
- *	This function sets the receive mode of an adapter. The adapter
- *	supports promiscuous mode, allmulticast mode and a number of
- *	multicast addresses. If more multicast addresses the available
- *	are selected, a hash function in the hardware is used.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
-{
-
-DEV_NET		*pNet;
-SK_AC		*pAC;
-
-struct dev_mc_list	*pMcList;
-int			i;
-int			PortIdx;
-unsigned long		Flags;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeSetRxMode starts now... "));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	if (pAC->RlmtNets == 1)
-		PortIdx = pAC->ActivePort;
-	else
-		PortIdx = pNet->NetNr;
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	if (dev->flags & IFF_PROMISC) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("PROMISCUOUS mode\n"));
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_LLC);
-	} else if (dev->flags & IFF_ALLMULTI) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("ALLMULTI mode\n"));
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_ALL_MC);
-	} else {
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_NONE);
-		SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("Number of MC entries: %d ", dev->mc_count));
-		
-		pMcList = dev->mc_list;
-		for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
-			SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
-				(SK_MAC_ADDR*)pMcList->dmi_addr, 0);
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
-				("%02x:%02x:%02x:%02x:%02x:%02x\n",
-				pMcList->dmi_addr[0],
-				pMcList->dmi_addr[1],
-				pMcList->dmi_addr[2],
-				pMcList->dmi_addr[3],
-				pMcList->dmi_addr[4],
-				pMcList->dmi_addr[5]));
-		}
-		SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
-	}
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	
-	return;
-} /* SkGeSetRxMode */
-
-
-/*****************************************************************************
- *
- * 	SkGeChangeMtu - set the MTU to another value
- *
- * Description:
- *	This function sets is called whenever the MTU size is changed
- *	(ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
- *	ethernet MTU size, long frame support is activated.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
-{
-DEV_NET		*pNet;
-struct net_device *pOtherDev;
-SK_AC		*pAC;
-unsigned long	Flags;
-int		i;
-SK_EVPARA 	EvPara;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeChangeMtu starts now...\n"));
-
-	pNet = netdev_priv(dev);
-	pAC  = pNet->pAC;
-
-	if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
-		return -EINVAL;
-	}
-
-	if(pAC->BoardLevel != SK_INIT_RUN) {
-		return -EINVAL;
-	}
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->DiagFlowCtrl == SK_FALSE) {
-			return -1; /* still in use, deny any actions of MTU */
-		} else {
-			pAC->DiagFlowCtrl = SK_FALSE;
-		}
-	}
-#endif
-
-	pOtherDev = pAC->dev[1 - pNet->NetNr];
-
-	if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
-	     && (NewMtu <= 1500))
-		return 0;
-
-	pAC->RxBufSize = NewMtu + 32;
-	dev->mtu = NewMtu;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("New MTU: %d\n", NewMtu));
-
-	/* 
-	** Prevent any reconfiguration while changing the MTU 
-	** by disabling any interrupts 
-	*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	/* 
-	** 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(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
-		netif_stop_queue(pAC->dev[i]);
-
-	}
-
-	/*
-	** 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++) {
-		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 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);
-
-	/*
-	** enable/disable hardware support for long frames
-	*/
-	if (NewMtu > 1500) {
-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
-		pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
-	} 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, 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);
-	
-	/*
-	** 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
-	*/
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
-		ClearRxRing(pAC, &pAC->RxPort[i]);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-
-		/* 
-		** Enable transmit descriptor polling
-		*/
-		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-	};
-
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-	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 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);
-
-	/* 
-	** 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);
-			
-		if (netif_running(pOtherDev)) {
-			DEV_NET *pOtherNet = netdev_priv(pOtherDev);
-			EvPara.Para32[0] = pOtherNet->PortNr;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-		}
-	} else {
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	}
-
-	SkEventDispatcher(pAC, pAC->IoBase);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	
-	/*
-	** 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 */
-
-
-/*****************************************************************************
- *
- * 	SkGeStats - return ethernet device statistics
- *
- * Description:
- *	This function return statistic data about the ethernet device
- *	to the operating system.
- *
- * Returns:
- *	pointer to the statistic structure.
- */
-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
-{
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC	*pAC = pNet->pAC;
-SK_PNMI_STRUCT_DATA *pPnmiStruct;       /* structure for all Pnmi-Data */
-SK_PNMI_STAT    *pPnmiStat;             /* pointer to virtual XMAC stat. data */
-SK_PNMI_CONF    *pPnmiConf;             /* pointer to virtual link config. */
-unsigned int    Size;                   /* size of pnmi struct */
-unsigned long	Flags;			/* for spin lock */
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeStats starts now...\n"));
-	pPnmiStruct = &pAC->PnmiStruct;
-
-#ifdef SK_DIAG_SUPPORT
-        if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
-                (pAC->BoardLevel == SK_INIT_RUN)) {
-#endif
-        SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
-        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-        Size = SK_PNMI_STRUCT_SIZE;
-		SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-#ifdef SK_DIAG_SUPPORT
-	}
-#endif
-
-        pPnmiStat = &pPnmiStruct->Stat[0];
-        pPnmiConf = &pPnmiStruct->Conf[0];
-
-	pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
-	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;
-	
-        if (dev->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;
-	pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF;
-	pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
-
-	/* detailed rx_errors: */
-	pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF;
-	pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
-	pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF;
-	pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF;
-	pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
-	pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF;
-
-	/* detailed tx_errors */
-	pAC->stats.tx_aborted_errors = (SK_U32) 0;
-	pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
-	pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF;
-	pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
-	pAC->stats.tx_window_errors = (SK_U32) 0;
-
-	return(&pAC->stats);
-} /* SkGeStats */
-
-/*
- * Basic MII register access
- */
-static int SkGeMiiIoctl(struct net_device *dev,
-			struct mii_ioctl_data *data, int cmd)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_IOC IoC = pAC->IoBase;
-	int Port = pNet->PortNr;
-	SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
-	unsigned long Flags;
-	int err = 0;
-	int reg = data->reg_num & 0x1f;
-	SK_U16 val = data->val_in;
-
-	if (!netif_running(dev))
-		return -ENODEV;	/* Phy still in reset */
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	switch(cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = pPrt->PhyAddr;
-
-		/* fallthru */
-	case SIOCGMIIREG:
-		if (pAC->GIni.GIGenesis)
-			SkXmPhyRead(pAC, IoC, Port, reg, &val);
-		else
-			SkGmPhyRead(pAC, IoC, Port, reg, &val);
-
-		data->val_out = val;
-		break;
-
-	case SIOCSMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			err = -EPERM;
-
-		else if (pAC->GIni.GIGenesis)
-			SkXmPhyWrite(pAC, IoC, Port, reg, val);
-		else
-			SkGmPhyWrite(pAC, IoC, Port, reg, val);
-		break;
-	default:
-		err = -EOPNOTSUPP;
-	}
-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	return err;
-}
-
-
-/*****************************************************************************
- *
- * 	SkGeIoctl - IO-control function
- *
- * Description:
- *	This function is called if an ioctl is issued on the device.
- *	There are three subfunction for reading, writing and test-writing
- *	the private MIB data structure (useful for SysKonnect-internal tools).
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
-{
-DEV_NET		*pNet;
-SK_AC		*pAC;
-void		*pMemBuf;
-struct pci_dev  *pdev = NULL;
-SK_GE_IOCTL	Ioctl;
-unsigned int	Err = 0;
-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"));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
-	    return SkGeMiiIoctl(dev, if_mii(rq), cmd);
-
-	if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
-		return -EFAULT;
-	}
-
-	switch(cmd) {
-	case SK_IOCTL_SETMIB:
-	case SK_IOCTL_PRESETMIB:
-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
- 	case SK_IOCTL_GETMIB:
-		if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
-			Ioctl.Len<sizeof(pAC->PnmiStruct)?
-			Ioctl.Len : sizeof(pAC->PnmiStruct))) {
-			return -EFAULT;
-		}
-		Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
-		if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
-			Ioctl.Len<Size? Ioctl.Len : Size)) {
-			return -EFAULT;
-		}
-		Ioctl.Len = Size;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			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 -ENOMEM;
-		}
-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		Ioctl.Len = Length;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-fault_gen:
-		kfree(pMemBuf); /* cleanup everything */
-		break;
-#ifdef SK_DIAG_SUPPORT
-       case SK_IOCTL_DIAG:
-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
-		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
-			Length = Ioctl.Len;
-		} else {
-			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
-		}
-		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
-			return -ENOMEM;
-		}
-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-		pdev = pAC->PciDev;
-		Length = 3 * sizeof(SK_U32);  /* Error, Bus and Device */
-		/* 
-		** While coding this new IOCTL interface, only a few lines of code
-		** are to to be added. Therefore no dedicated function has been 
-		** added. If more functionality is added, a separate function 
-		** should be used...
-		*/
-		* ((SK_U32 *)pMemBuf) = 0;
-		* ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
-		* ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-		Ioctl.Len = Length;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-fault_diag:
-		kfree(pMemBuf); /* cleanup everything */
-		break;
-#endif
-	default:
-		Err = -EOPNOTSUPP;
-	}
-
-	return(Err);
-
-} /* SkGeIoctl */
-
-
-/*****************************************************************************
- *
- * 	SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
- *
- * Description:
- *	This function reads/writes the MIB data using PNMI (Private Network
- *	Management Interface).
- *	The destination for the data must be provided with the
- *	ioctl call and is given to the driver in the form of
- *	a user space address.
- *	Copying from the user-provided data area into kernel messages
- *	and back is done by copy_from_user and copy_to_user calls in
- *	SkGeIoctl.
- *
- * Returns:
- *	returned size from PNMI call
- */
-static int SkGeIocMib(
-DEV_NET		*pNet,	/* pointer to the adapter context */
-unsigned int	Size,	/* length of ioctl data */
-int		mode)	/* flag for set/preset */
-{
-unsigned long	Flags;	/* for spin lock */
-SK_AC		*pAC;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeIocMib starts now...\n"));
-	pAC = pNet->pAC;
-	/* access MIB */
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	switch(mode) {
-	case SK_IOCTL_GETMIB:
-		SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	case SK_IOCTL_PRESETMIB:
-		SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	case SK_IOCTL_SETMIB:
-		SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	default:
-		break;
-	}
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("MIB data access succeeded\n"));
-	return (Size);
-} /* SkGeIocMib */
-
-
-/*****************************************************************************
- *
- * 	GetConfiguration - read configuration information
- *
- * Description:
- *	This function reads per-adapter configuration information from
- *	the options provided on the command line.
- *
- * Returns:
- *	none
- */
-static void GetConfiguration(
-SK_AC	*pAC)	/* pointer to the adapter context structure */
-{
-SK_I32	Port;		/* preferred port */
-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:
- *	DuplexCap ->	|	both	|	full	|	half	|
- *	AutoNeg		|		|		|		|
- *	-----------------------------------------------------------------
- *	Off		|    illegal	|	Full	|	Half	|
- *	-----------------------------------------------------------------
- *	On		|   AutoBoth	|   AutoFull	|   AutoHalf	|
- *	-----------------------------------------------------------------
- *	Sense		|   AutoSense	|   AutoSense	|   AutoSense	|
- */
-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]
-
-
-	/*
-	** 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) ) {
-
-			/* Check chipset family */
-			if ((!pAC->ChipsetType) && 
-				(strcmp(ConType[pAC->Index],"Auto")!=0) &&
-				(strcmp(ConType[pAC->Index],"")!=0)) {
-				/* Set the speed parameter back */
-					printk("sk98lin: Illegal value \"%s\" " 
-							"for ConType."
-							" Using Auto.\n", 
-							ConType[pAC->Index]);
-
-					sprintf(ConType[pAC->Index], "Auto");	
-			}
-
-				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("sk98lin: Illegal value \"%s\" for ConType\n", 
-			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("sk98lin: Illegal value \"%s\" for Speed_A\n",
-			Speed_A[pAC->Index]);
-		    IsLinkSpeedDefined = SK_FALSE;
-		}
-	} else {
-	    IsLinkSpeedDefined = SK_FALSE;
-	}
-
-	/* 
-	** Check speed parameter: 
-	**    Only copper type adapter and GE V2 cards 
-	*/
-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
-		((LinkSpeed != SK_LSPEED_AUTO) &&
-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
-		printk("sk98lin: Illegal value for Speed_A. "
-			"Not a copper card or GE V2 card\n    Using "
-			"speed 1000\n");
-		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;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
-			AutoNeg_A[pAC->Index]);
-		}
-	}
-
-	DuplexCap = DC_BOTH;
-	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;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
-			DupCap_A[pAC->Index]);
-		}
-	}
-
-	/* 
-	** Check for illegal combinations 
-	*/
-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
-		(pAC->ChipsetType)) {
-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
-					"    Using Full Duplex.\n");
-				DuplexCap = DC_FULL;
-	}
-
-	if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
-		printk("sk98lin, Port A: DuplexCapabilities"
-			" ignored using Sense mode\n");
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
-		printk("sk98lin: Port A: Illegal combination"
-			" of values AutoNeg. and DuplexCap.\n    Using "
-			"Full Duplex\n");
-		DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
-		DuplexCap = DC_FULL;
-	}
-	
-	if (!AutoSet && DupSet) {
-		printk("sk98lin: Port A: Duplex setting not"
-			" possible in\n    default AutoNegotiation mode"
-			" (Sense).\n    Using AutoNegotiation On\n");
-		AutoNeg = AN_ON;
-	}
-	
-	/* 
-	** set the desired mode 
-	*/
-	if (AutoSet || DupSet) {
-	    pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
-	}
-	
-	/* 
-	** 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("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
-                        FlowCtrl_A[pAC->Index]);
-		    IsFlowCtrlDefined = SK_FALSE;
-		}
-	} else {
-	   IsFlowCtrlDefined = SK_FALSE;
-	}
-
-	if (IsFlowCtrlDefined) {
-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
-		printk("sk98lin: Port A: FlowControl"
-			" impossible without AutoNegotiation,"
-			" disabled\n");
-		FlowCtrl = SK_FLOW_MODE_NONE;
-	    }
-	    pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
-	}
-
-	/*
-	** 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("sk98lin: Illegal value \"%s\" for Role_A\n",
-			Role_A[pAC->Index]);
-		    IsRoleDefined = SK_FALSE;
-		}
-	} else {
-	   IsRoleDefined = SK_FALSE;
-	}
-
-	if (IsRoleDefined == SK_TRUE) {
-	    pAC->GIni.GP[0].PMSMode = MSMode;
-	}
-	
-
-	
-	/* 
-	** 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("sk98lin: Illegal value \"%s\" for Speed_B\n",
-			Speed_B[pAC->Index]);
-		    IsLinkSpeedDefined = SK_FALSE;
-		}
-	} else {
-	    IsLinkSpeedDefined = SK_FALSE;
-	}
-
-	/* 
-	** Check speed parameter:
-	**    Only copper type adapter and GE V2 cards 
-	*/
-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
-		((LinkSpeed != SK_LSPEED_AUTO) &&
-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
-		printk("sk98lin: Illegal value for Speed_B. "
-			"Not a copper card or GE V2 card\n    Using "
-			"speed 1000\n");
-		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;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
-			AutoNeg_B[pAC->Index]);
-		}
-	}
-
-	DuplexCap = DC_BOTH;
-	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;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
-			DupCap_B[pAC->Index]);
-		}
-	}
-
-	
-	/* 
-	** Check for illegal combinations 
-	*/
-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
-		(pAC->ChipsetType)) {
-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
-					"    Using Full Duplex.\n");
-				DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_SENS && DupSet) {
-		printk("sk98lin, Port B: DuplexCapabilities"
-			" ignored using Sense mode\n");
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
-		printk("sk98lin: Port B: Illegal combination"
-			" of values AutoNeg. and DuplexCap.\n    Using "
-			"Full Duplex\n");
-		DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
-		DuplexCap = DC_FULL;
-	}
-	
-	if (!AutoSet && DupSet) {
-		printk("sk98lin: Port B: Duplex setting not"
-			" possible in\n    default AutoNegotiation mode"
-			" (Sense).\n    Using AutoNegotiation On\n");
-		AutoNeg = AN_ON;
-	}
-
-	/* 
-	** set the desired mode 
-	*/
-	if (AutoSet || DupSet) {
-	    pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
-	}
-
-	/*
-	** 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("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
-			FlowCtrl_B[pAC->Index]);
-		    IsFlowCtrlDefined = SK_FALSE;
-		}
-	} else {
-		IsFlowCtrlDefined = SK_FALSE;
-	}
-
-	if (IsFlowCtrlDefined) {
-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
-		printk("sk98lin: Port B: FlowControl"
-			" impossible without AutoNegotiation,"
-			" disabled\n");
-		FlowCtrl = SK_FLOW_MODE_NONE;
-	    }
-	    pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
-	}
-
-	/*
-	** 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("sk98lin: Illegal value \"%s\" for Role_B\n",
-			Role_B[pAC->Index]);
-		    IsRoleDefined = SK_FALSE;
-		}
-	} else {
-	    IsRoleDefined = SK_FALSE;
-	}
-
-	if (IsRoleDefined) {
-	    pAC->GIni.GP[1].PMSMode = MSMode;
-	}
-	
-	/*
-	** 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.
-			*/
-			if (pAC->GIni.GIMacsFound == 1) {
-				printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
-					"      Port B not available on single port adapters.\n");
-
-				pAC->ActivePort             =  0;
-				pAC->Rlmt.Net[0].Preference = -1; /* auto */
-				pAC->Rlmt.Net[0].PrefPort   =  0;
-			} else {
-				Port                        = 1;
-				pAC->Rlmt.Net[0].Preference = Port;
-				pAC->Rlmt.Net[0].PrefPort   = Port;
-			}
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
-			PrefPort[pAC->Index]);
-		}
-	}
-
-	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) {
-			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) {
-			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("sk98lin: Illegal value \"%s\" for"
-			" RlmtMode, using default\n", 
-			RlmtMode[pAC->Index]);
-			pAC->RlmtMode = 0;
-		}
-	} else {
-		pAC->RlmtMode = 0;
-	}
-	
-	/*
-	** Check the interrupt moderation parameters
-	*/
-	if (Moderation[pAC->Index] != NULL) {
-		if (strcmp(Moderation[pAC->Index], "") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		} else 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 if (strcmp(Moderation[pAC->Index], "None") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		} else {
-	   		printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
-				"      Disable interrupt moderation.\n",
-				Moderation[pAC->Index]);
-			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]< C_INT_MOD_IPS_LOWER_RANGE) || 
-			(IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
-	   		printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
-				"      Using default value of %i.\n", 
-				IntsPerSec[pAC->Index],
-				C_INT_MOD_IPS_LOWER_RANGE,
-				C_INT_MOD_IPS_UPPER_RANGE,
-				C_INTS_PER_SEC_DEFAULT);
-			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 */
-
-
-/*****************************************************************************
- *
- * 	ProductStr - return a adapter identification string from vpd
- *
- * Description:
- *	This function reads the product name string from the vpd area
- *	and puts it the field pAC->DeviceString.
- *
- * Returns: N/A
- */
-static inline int ProductStr(
-	SK_AC	*pAC,		/* pointer to adapter context */
-	char    *DeviceStr,	/* result string */
-	int      StrLen		/* length of the string */
-)
-{
-char	Keyword[] = VPD_NAME;	/* vpd productname identifier */
-int	ReturnCode;		/* return code from vpd_read */
-unsigned long Flags;
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	return ReturnCode;
-} /* 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 *********************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- *	SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
- *
- * Description:
- *	This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
- *	is embedded into a socket buff data area.
- *
- * Context:
- *	runtime
- *
- * Returns:
- *	NULL or pointer to Mbuf.
- */
-SK_MBUF *SkDrvAllocRlmtMbuf(
-SK_AC		*pAC,		/* pointer to adapter context */
-SK_IOC		IoC,		/* the IO-context */
-unsigned	BufferSize)	/* size of the requested buffer */
-{
-SK_MBUF		*pRlmtMbuf;	/* pointer to a new rlmt-mbuf structure */
-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
-
-	pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
-	if (pMsgBlock == NULL) {
-		return (NULL);
-	}
-	pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
-	skb_reserve(pMsgBlock, sizeof(SK_MBUF));
-	pRlmtMbuf->pNext = NULL;
-	pRlmtMbuf->pOs = pMsgBlock;
-	pRlmtMbuf->pData = pMsgBlock->data;	/* Data buffer. */
-	pRlmtMbuf->Size = BufferSize;		/* Data buffer size. */
-	pRlmtMbuf->Length = 0;		/* Length of packet (<= Size). */
-	return (pRlmtMbuf);
-
-} /* SkDrvAllocRlmtMbuf */
-
-
-/*****************************************************************************
- *
- *	SkDrvFreeRlmtMbuf - free an RLMT mbuf
- *
- * Description:
- *	This routine frees one or more RLMT mbuf(s).
- *
- * Context:
- *	runtime
- *
- * Returns:
- *	Nothing
- */
-void  SkDrvFreeRlmtMbuf(
-SK_AC		*pAC,		/* pointer to adapter context */
-SK_IOC		IoC,		/* the IO-context */
-SK_MBUF		*pMbuf)		/* size of the requested buffer */
-{
-SK_MBUF		*pFreeMbuf;
-SK_MBUF		*pNextMbuf;
-
-	pFreeMbuf = pMbuf;
-	do {
-		pNextMbuf = pFreeMbuf->pNext;
-		DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
-		pFreeMbuf = pNextMbuf;
-	} while ( pFreeMbuf != NULL );
-} /* SkDrvFreeRlmtMbuf */
-
-
-/*****************************************************************************
- *
- *	SkOsGetTime - provide a time value
- *
- * Description:
- *	This routine provides a time value. The unit is 1/HZ (defined by Linux).
- *	It is not used for absolute time, but only for time differences.
- *
- *
- * Returns:
- *	Time value
- */
-SK_U64 SkOsGetTime(SK_AC *pAC)
-{
-	SK_U64	PrivateJiffies;
-	SkOsGetTimeCurrent(pAC, &PrivateJiffies);
-	return PrivateJiffies;
-} /* SkOsGetTime */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgDWord - read a 32 bit value from pci config space
- *
- * Description:
- *	This routine reads a 32 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgDWord(
-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);
-	return(0);
-} /* SkPciReadCfgDWord */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgWord - read a 16 bit value from pci config space
- *
- * Description:
- *	This routine reads a 16 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgWord(
-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);
-	return(0);
-} /* SkPciReadCfgWord */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgByte - read a 8 bit value from pci config space
- *
- * Description:
- *	This routine reads a 8 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgByte(
-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);
-	return(0);
-} /* SkPciReadCfgByte */
-
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgWord - write a 16 bit value to pci config space
- *
- * Description:
- *	This routine writes a 16 bit value to the pci configuration
- *	space. The flag PciConfigUp indicates whether the config space
- *	is accesible or must be set up first.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciWriteCfgWord(
-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);
-	return(0);
-} /* SkPciWriteCfgWord */
-
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgWord - write a 8 bit value to pci config space
- *
- * Description:
- *	This routine writes a 8 bit value to the pci configuration
- *	space. The flag PciConfigUp indicates whether the config space
- *	is accesible or must be set up first.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciWriteCfgByte(
-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);
-	return(0);
-} /* SkPciWriteCfgByte */
-
-
-/*****************************************************************************
- *
- *	SkDrvEvent - handle driver events
- *
- * Description:
- *	This function handles events from all modules directed to the driver
- *
- * Context:
- *	Is called under protection of slow path lock.
- *
- * Returns:
- *	0 if everything ok
- *	< 0  on error
- *	
- */
-int SkDrvEvent(
-SK_AC *pAC,		/* pointer to adapter context */
-SK_IOC IoC,		/* io-context */
-SK_U32 Event,		/* event-id */
-SK_EVPARA Param)	/* event-parameter */
-{
-SK_MBUF		*pRlmtMbuf;	/* pointer to a rlmt-mbuf structure */
-struct sk_buff	*pMsg;		/* pointer to a message block */
-int		FromPort;	/* the port from which we switch away */
-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:
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("ADAPTER FAIL EVENT\n"));
-		printk("%s: Adapter failed.\n", pAC->dev[0]->name);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		/* cgoos */
-		break;
-	case SK_DRV_PORT_FAIL:
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT FAIL EVENT, Port: %d\n", FromPort));
-		if (FromPort == 0) {
-			printk("%s: Port A failed.\n", pAC->dev[0]->name);
-		} else {
-			printk("%s: Port B failed.\n", pAC->dev[1]->name);
-		}
-		/* cgoos */
-		break;
-	case SK_DRV_PORT_RESET:	 /* SK_U32 PortIdx */
-		/* action list 4 */
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT RESET EVENT, Port: %d ", FromPort));
-		NewPara.Para64 = FromPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-
-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
-		netif_carrier_off(pAC->dev[Param.Para32[0]]);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		
-		/* clear rx ring from received frames */
-		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);
-		
-		/* 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);
-		ClearAndStartRx(pAC, FromPort);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		break;
-	case SK_DRV_NET_UP:	 /* SK_U32 PortIdx */
-	{	struct net_device *dev = pAC->dev[Param.Para32[0]];
-		/* action list 5 */
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("NET UP EVENT, Port: %d ", Param.Para32[0]));
-		/* Mac update */
-		SkAddrMcUpdate(pAC,IoC, FromPort);
-
-		if (DoPrintInterfaceChange) {
-		printk("%s: network connection up using"
-			" port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
-
-		/* 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");
-		}
-
-
-		Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
-			Stat == SK_LMODE_STAT_AUTOFULL) {
-			printk("    autonegotiation: yes\n");
-		}
-		else {
-			printk("    autonegotiation: no\n");
-		}
-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
-			Stat == SK_LMODE_STAT_HALF) {
-			printk("    duplex mode:     half\n");
-		}
-		else {
-			printk("    duplex mode:     full\n");
-		}
-		Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
-		if (Stat == SK_FLOW_STAT_REM_SEND ) {
-			printk("    flowctrl:        remote send\n");
-		}
-		else if (Stat == SK_FLOW_STAT_LOC_SEND ){
-			printk("    flowctrl:        local send\n");
-		}
-		else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
-			printk("    flowctrl:        symmetric\n");
-		}
-		else {
-			printk("    flowctrl:        none\n");
-		}
-		
-		/* 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");
-			}
-			else if (Stat == SK_MS_STAT_SLAVE ) {
-				printk("    role:            slave\n");
-			}
-			else {
-				printk("    role:            ???\n");
-			}
-		}
-
-		/* 
-		   Display dim (dynamic interrupt moderation) 
-		   informations
-		 */
-		if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
-			printk("    irq moderation:  static (%d ints/sec)\n",
-					pAC->DynIrqModInfo.MaxModIntsPerSec);
-		else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
-			printk("    irq moderation:  dynamic (%d ints/sec)\n",
-					pAC->DynIrqModInfo.MaxModIntsPerSec);
-		else
-			printk("    irq moderation:  disabled\n");
-
-
-		printk("    scatter-gather:  %s\n",
-		       (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
-		printk("    tx-checksum:     %s\n",
-		       (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
-		printk("    rx-checksum:     %s\n",
-		       pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
-
-		} else {
-                        DoPrintInterfaceChange = SK_TRUE;
-                }
-	
-		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. */
-		netif_carrier_on(dev);
-		break;
-	}
-	case SK_DRV_NET_DOWN:	 /* SK_U32 Reason */
-		/* action list 7 */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("NET DOWN EVENT "));
-		if (DoPrintInterfaceChange) {
-			printk("%s: network connection down\n", 
-				pAC->dev[Param.Para32[1]]->name);
-		} else {
-			DoPrintInterfaceChange = SK_TRUE;
-		}
-		netif_carrier_off(pAC->dev[Param.Para32[1]]);
-		break;
-	case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT SWITCH HARD "));
-	case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-	/* action list 6 */
-		printk("%s: switching to port %c\n", pAC->dev[0]->name,
-			'A'+Param.Para32[1]);
-	case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-		FromPort = Param.Para32[0];
-		ToPort = Param.Para32[1];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT SWITCH EVENT, From: %d  To: %d (Pref %d) ",
-			FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
-		NewPara.Para64 = FromPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		NewPara.Para64 = ToPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
-		SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-
-		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,
-			Flags);
-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		pAC->ActivePort = ToPort;
-#if 0
-		SetQueueSizes(pAC);
-#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(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-			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) {
-			SkMacRxTxEnable(pAC, IoC, FromPort);
-		}
-		SkMacRxTxEnable(pAC, IoC, ToPort);
-		SkAddrSwap(pAC, IoC, FromPort, ToPort);
-		SkAddrMcUpdate(pAC, IoC, FromPort);
-		SkAddrMcUpdate(pAC, IoC, ToPort);
-		PortReInitBmu(pAC, FromPort);
-		PortReInitBmu(pAC, ToPort);
-		SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
-		SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
-		ClearAndStartRx(pAC, FromPort);
-		ClearAndStartRx(pAC, ToPort);
-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		break;
-	case SK_DRV_RLMT_SEND:	 /* SK_MBUF *pMb */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("RLS "));
-		pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
-		pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
-		skb_put(pMsg, pRlmtMbuf->Length);
-		if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
-			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;
-	}
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-		("END EVENT "));
-	
-	return (0);
-} /* SkDrvEvent */
-
-
-/*****************************************************************************
- *
- *	SkErrorLog - log errors
- *
- * Description:
- *	This function logs errors to the system buffer and to the console
- *
- * Returns:
- *	0 if everything ok
- *	< 0  on error
- *	
- */
-void SkErrorLog(
-SK_AC	*pAC,
-int	ErrClass,
-int	ErrNum,
-char	*pErrorMsg)
-{
-char	ClassStr[80];
-
-	switch (ErrClass) {
-	case SK_ERRCL_OTHER:
-		strcpy(ClassStr, "Other error");
-		break;
-	case SK_ERRCL_CONFIG:
-		strcpy(ClassStr, "Configuration error");
-		break;
-	case SK_ERRCL_INIT:
-		strcpy(ClassStr, "Initialization error");
-		break;
-	case SK_ERRCL_NORES:
-		strcpy(ClassStr, "Out of resources error");
-		break;
-	case SK_ERRCL_SW:
-		strcpy(ClassStr, "internal Software error");
-		break;
-	case SK_ERRCL_HW:
-		strcpy(ClassStr, "Hardware failure");
-		break;
-	case SK_ERRCL_COMM:
-		strcpy(ClassStr, "Communication error");
-		break;
-	}
-	printk(KERN_INFO "%s: -- ERROR --\n        Class:  %s\n"
-		"        Nr:  0x%x\n        Msg:  %s\n", pAC->dev[0]->name,
-		ClassStr, ErrNum, pErrorMsg);
-
-} /* SkErrorLog */
-
-#ifdef SK_DIAG_SUPPORT
-
-/*****************************************************************************
- *
- *	SkDrvEnterDiagMode - handles DIAG attach request
- *
- * Description:
- *	Notify the kernel to NOT access the card any longer due to DIAG
- *	Deinitialize the Card
- *
- * Returns:
- *	int
- */
-int SkDrvEnterDiagMode(
-SK_AC   *pAc)   /* pointer to adapter context */
-{
-	DEV_NET *pNet = netdev_priv(pAc->dev[0]);
-	SK_AC   *pAC  = pNet->pAC;
-
-	SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-
-	pAC->DiagModeActive = DIAG_ACTIVE;
-	if (pAC->BoardLevel > SK_INIT_DATA) {
-		if (netif_running(pAC->dev[0])) {
-			pAC->WasIfUp[0] = SK_TRUE;
-			pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose      */
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
-		} else {
-			pAC->WasIfUp[0] = SK_FALSE;
-		}
-		if (pNet != netdev_priv(pAC->dev[1])) {
-			pNet = netdev_priv(pAC->dev[1]);
-			if (netif_running(pAC->dev[1])) {
-				pAC->WasIfUp[1] = SK_TRUE;
-				pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-				DoPrintInterfaceChange = SK_FALSE;
-				SkDrvDeInitAdapter(pAC, 1);  /* do SkGeClose  */
-			} else {
-				pAC->WasIfUp[1] = SK_FALSE;
-			}
-		}
-		pAC->BoardLevel = SK_INIT_DATA;
-	}
-	return(0);
-}
-
-/*****************************************************************************
- *
- *	SkDrvLeaveDiagMode - handles DIAG detach request
- *
- * Description:
- *	Notify the kernel to may access the card again after use by DIAG
- *	Initialize the Card
- *
- * Returns:
- * 	int
- */
-int SkDrvLeaveDiagMode(
-SK_AC   *pAc)   /* pointer to adapter control context */
-{ 
-	SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-	pAc->DiagModeActive    = DIAG_NOTACTIVE;
-	pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
-        if (pAc->WasIfUp[0] == SK_TRUE) {
-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-		DoPrintInterfaceChange = SK_FALSE;
-                SkDrvInitAdapter(pAc, 0);    /* first device  */
-        }
-        if (pAc->WasIfUp[1] == SK_TRUE) {
-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-		DoPrintInterfaceChange = SK_FALSE;
-                SkDrvInitAdapter(pAc, 1);    /* second device */
-        }
-	return(0);
-}
-
-/*****************************************************************************
- *
- *	ParseDeviceNbrFromSlotName - Evaluate PCI device number
- *
- * Description:
- * 	This function parses the PCI slot name information string and will
- *	retrieve the devcie number out of it. The slot_name maintianed by
- *	linux is in the form of '02:0a.0', whereas the first two characters 
- *	represent the bus number in hex (in the sample above this is 
- *	pci bus 0x02) and the next two characters the device number (0x0a).
- *
- * Returns:
- *	SK_U32: The device number from the PCI slot name
- */ 
-
-static SK_U32 ParseDeviceNbrFromSlotName(
-const char *SlotName)   /* pointer to pci slot name eg. '02:0a.0' */
-{
-	char	*CurrCharPos	= (char *) SlotName;
-	int	FirstNibble	= -1;
-	int	SecondNibble	= -1;
-	SK_U32	Result		=  0;
-
-	while (*CurrCharPos != '\0') {
-		if (*CurrCharPos == ':') { 
-			while (*CurrCharPos != '.') {
-				CurrCharPos++;  
-				if (	(*CurrCharPos >= '0') && 
-					(*CurrCharPos <= '9')) {
-					if (FirstNibble == -1) {
-						/* dec. value for '0' */
-						FirstNibble = *CurrCharPos - 48;
-					} else {
-						SecondNibble = *CurrCharPos - 48;
-					}  
-				} else if (	(*CurrCharPos >= 'a') && 
-						(*CurrCharPos <= 'f')  ) {
-					if (FirstNibble == -1) {
-						FirstNibble = *CurrCharPos - 87; 
-					} else {
-						SecondNibble = *CurrCharPos - 87; 
-					}
-				} else {
-					Result = 0;
-				}
-			}
-
-			Result = FirstNibble;
-			Result = Result << 4; /* first nibble is higher one */
-			Result = Result | SecondNibble;
-		}
-		CurrCharPos++;   /* next character */
-	}
-	return (Result);
-}
-
-/****************************************************************************
- *
- *	SkDrvDeInitAdapter - deinitialize adapter (this function is only 
- *				called if Diag attaches to that card)
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkDrvDeInitAdapter(
-SK_AC   *pAC,		/* pointer to adapter context   */
-int      devNbr)	/* what device is to be handled */
-{
-	struct SK_NET_DEVICE *dev;
-
-	dev = pAC->dev[devNbr];
-
-	/* On Linux 2.6 the network driver does NOT mess with reference
-	** counts.  The driver MUST be able to be unloaded at any time
-	** due to the possibility of hotplug.
-	*/
-	if (SkGeClose(dev) != 0) {
-		return (-1);
-	}
-	return (0);
-
-} /* SkDrvDeInitAdapter() */
-
-/****************************************************************************
- *
- *	SkDrvInitAdapter - Initialize adapter (this function is only 
- *				called if Diag deattaches from that card)
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkDrvInitAdapter(
-SK_AC   *pAC,		/* pointer to adapter context   */
-int      devNbr)	/* what device is to be handled */
-{
-	struct SK_NET_DEVICE *dev;
-
-	dev = pAC->dev[devNbr];
-
-	if (SkGeOpen(dev) != 0) {
-		return (-1);
-	}
-
-	/*
-	** Use correct MTU size and indicate to kernel TX queue can be started
-	*/ 
-	if (SkGeChangeMtu(dev, dev->mtu) != 0) {
-		return (-1);
-	} 
-	return (0);
-
-} /* SkDrvInitAdapter */
-
-#endif
-
-#ifdef DEBUG
-/****************************************************************************/
-/* "debug only" section *****************************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- *	DumpMsg - print a frame
- *
- * Description:
- *	This function prints frames to the system logfile/to the console.
- *
- * Returns: N/A
- *	
- */
-static void DumpMsg(struct sk_buff *skb, char *str)
-{
-	int	msglen;
-
-	if (skb == NULL) {
-		printk("DumpMsg(): NULL-Message\n");
-		return;
-	}
-
-	if (skb->data == NULL) {
-		printk("DumpMsg(): Message empty\n");
-		return;
-	}
-
-	msglen = skb->len;
-	if (msglen > 64)
-		msglen = 64;
-
-	printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
-
-	DumpData((char *)skb->data, msglen);
-
-	printk("------- End of message ---------\n");
-} /* DumpMsg */
-
-
-
-/*****************************************************************************
- *
- *	DumpData - print a data area
- *
- * Description:
- *	This function prints a area of data to the system logfile/to the
- *	console.
- *
- * Returns: N/A
- *	
- */
-static void DumpData(char *p, int size)
-{
-register int    i;
-int	haddr, addr;
-char	hex_buffer[180];
-char	asc_buffer[180];
-char	HEXCHAR[] = "0123456789ABCDEF";
-
-	addr = 0;
-	haddr = 0;
-	hex_buffer[0] = 0;
-	asc_buffer[0] = 0;
-	for (i=0; i < size; ) {
-		if (*p >= '0' && *p <='z')
-			asc_buffer[addr] = *p;
-		else
-			asc_buffer[addr] = '.';
-		addr++;
-		asc_buffer[addr] = 0;
-		hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
-		haddr++;
-		hex_buffer[haddr] = ' ';
-		haddr++;
-		hex_buffer[haddr] = 0;
-		p++;
-		i++;
-		if (i%16 == 0) {
-			printk("%s  %s\n", hex_buffer, asc_buffer);
-			addr = 0;
-			haddr = 0;
-		}
-	}
-} /* DumpData */
-
-
-/*****************************************************************************
- *
- *	DumpLong - print a data area as long values
- *
- * Description:
- *	This function prints a area of data to the system logfile/to the
- *	console.
- *
- * Returns: N/A
- *	
- */
-static void DumpLong(char *pc, int size)
-{
-register int    i;
-int	haddr, addr;
-char	hex_buffer[180];
-char	asc_buffer[180];
-char	HEXCHAR[] = "0123456789ABCDEF";
-long	*p;
-int	l;
-
-	addr = 0;
-	haddr = 0;
-	hex_buffer[0] = 0;
-	asc_buffer[0] = 0;
-	p = (long*) pc;
-	for (i=0; i < size; ) {
-		l = (long) *p;
-		hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[l & 0x0f];
-		haddr++;
-		hex_buffer[haddr] = ' ';
-		haddr++;
-		hex_buffer[haddr] = 0;
-		p++;
-		i++;
-		if (i%8 == 0) {
-			printk("%4x %s\n", (i-8)*4, hex_buffer);
-			haddr = 0;
-		}
-	}
-	printk("------------------------\n");
-} /* DumpLong */
-
-#endif
-
-static int __devinit skge_probe_one(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	SK_AC			*pAC;
-	DEV_NET			*pNet = NULL;
-	struct net_device	*dev = NULL;
-	static int boards_found = 0;
-	int error = -ENODEV;
-	int using_dac = 0;
-	char DeviceStr[80];
-
-	if (pci_enable_device(pdev))
-		goto out;
- 
-	/* Configure DMA attributes. */
-	if (sizeof(dma_addr_t) > sizeof(u32) &&
-	    !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
-		using_dac = 1;
-		error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-		if (error < 0) {
-			printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
-			       "for consistent allocations\n", pci_name(pdev));
-			goto out_disable_device;
-		}
-	} else {
-		error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-		if (error) {
-			printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
-			       pci_name(pdev));
-			goto out_disable_device;
-		}
-	}
-
- 	error = -ENOMEM;
- 	dev = alloc_etherdev(sizeof(DEV_NET));
- 	if (!dev) {
-		printk(KERN_ERR "sk98lin: unable to allocate etherdev "
-		       "structure!\n");
-		goto out_disable_device;
-	}
-
-	pNet = netdev_priv(dev);
-	pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
-	if (!pNet->pAC) {
-		printk(KERN_ERR "sk98lin: unable to allocate adapter "
-		       "structure!\n");
-		goto out_free_netdev;
-	}
-
-	pAC = pNet->pAC;
-	pAC->PciDev = pdev;
-
-	pAC->dev[0] = dev;
-	pAC->dev[1] = dev;
-	pAC->CheckQueue = SK_FALSE;
-
-	dev->irq = pdev->irq;
-
-	error = SkGeInitPCI(pAC);
-	if (error) {
-		printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
-		goto out_free_netdev;
-	}
-
-	dev->open =		&SkGeOpen;
-	dev->stop =		&SkGeClose;
-	dev->hard_start_xmit =	&SkGeXmit;
-	dev->get_stats =	&SkGeStats;
-	dev->set_multicast_list = &SkGeSetRxMode;
-	dev->set_mac_address =	&SkGeSetMacAddr;
-	dev->do_ioctl =		&SkGeIoctl;
-	dev->change_mtu =	&SkGeChangeMtu;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller =	&SkGePollController;
-#endif
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
-	/* Use only if yukon hardware */
-	if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
-		dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
-		dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
-		pAC->RxPort[0].RxCsum = 1;
-#endif
-	}
-
-	if (using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	pAC->Index = boards_found++;
-
-	error = SkGeBoardInit(dev, pAC);
-	if (error)
-		goto out_free_netdev;
-
-	/* Read Adapter name from VPD */
-	if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
-		error = -EIO;
-		printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
-		goto out_free_resources;
-	}
-
-	/* Register net device */
-	error = register_netdev(dev);
-	if (error) {
-		printk(KERN_ERR "sk98lin: Could not register device.\n");
-		goto out_free_resources;
-	}
-
-	/* Print adapter specific string from vpd */
-	printk("%s: %s\n", dev->name, DeviceStr);
-
-	/* Print configuration settings */
-	printk("      PrefPort:%c  RlmtMode:%s\n",
-		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
-		(pAC->RlmtMode==0)  ? "Check Link State" :
-		((pAC->RlmtMode==1) ? "Check Link State" :
-		((pAC->RlmtMode==3) ? "Check Local Port" :
-		((pAC->RlmtMode==7) ? "Check Segmentation" :
-		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-	memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-	pNet->PortNr = 0;
-	pNet->NetNr  = 0;
-
-	boards_found++;
-
-	pci_set_drvdata(pdev, dev);
-
-	/* More then one port found */
-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		dev = alloc_etherdev(sizeof(DEV_NET));
-		if (!dev) {
-			printk(KERN_ERR "sk98lin: unable to allocate etherdev "
-				"structure!\n");
-			goto single_port;
-		}
-
-		pNet          = netdev_priv(dev);
-		pNet->PortNr  = 1;
-		pNet->NetNr   = 1;
-		pNet->pAC     = pAC;
-
-		dev->open               = &SkGeOpen;
-		dev->stop               = &SkGeClose;
-		dev->hard_start_xmit    = &SkGeXmit;
-		dev->get_stats          = &SkGeStats;
-		dev->set_multicast_list = &SkGeSetRxMode;
-		dev->set_mac_address    = &SkGeSetMacAddr;
-		dev->do_ioctl           = &SkGeIoctl;
-		dev->change_mtu         = &SkGeChangeMtu;
-		SET_NETDEV_DEV(dev, &pdev->dev);
-		SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
-		if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
-			dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
-			dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
-			pAC->RxPort[1].RxCsum = 1;
-#endif
-		}
-
-		if (using_dac)
-			dev->features |= NETIF_F_HIGHDMA;
-
-		error = register_netdev(dev);
-		if (error) {
-			printk(KERN_ERR "sk98lin: Could not register device"
-			       " for second port. (%d)\n", error);
-			free_netdev(dev);
-			goto single_port;
-		}
-
-		pAC->dev[1]   = dev;
-		memcpy(&dev->dev_addr,
-		       &pAC->Addr.Net[1].CurrentMacAddress, 6);
-		memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-		printk("%s: %s\n", dev->name, DeviceStr);
-		printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
-	}
-
-single_port:
-
-	/* Save the hardware revision */
-	pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
-		(pAC->GIni.GIPciHwRev & 0x0F);
-
-	/* Set driver globals */
-	pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
-	pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
-	memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
-	memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
-
-	return 0;
-
- out_free_resources:
-	FreeResources(dev);
- out_free_netdev:
-	free_netdev(dev);
- out_disable_device:
-	pci_disable_device(pdev);
- out:
-	return error;
-}
-
-static void __devexit skge_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-
-	unregister_netdev(dev);
-
-	SkGeYellowLED(pAC, pAC->IoBase, 0);
-
-	if (pAC->BoardLevel == SK_INIT_RUN) {
-		SK_EVPARA EvPara;
-		unsigned long Flags;
-
-		/* board is still alive */
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		EvPara.Para32[0] = 0;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		EvPara.Para32[0] = 1;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		SkGeDeInit(pAC, pAC->IoBase);
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		pAC->BoardLevel = SK_INIT_DATA;
-		/* We do NOT check here, if IRQ was pending, of course*/
-	}
-
-	if (pAC->BoardLevel == SK_INIT_IO) {
-		/* board is still alive */
-		SkGeDeInit(pAC, pAC->IoBase);
-		pAC->BoardLevel = SK_INIT_DATA;
-	}
-
-	FreeResources(dev);
-	free_netdev(dev);
-	if (otherdev != dev)
-		free_netdev(otherdev);
-	kfree(pAC);
-}
-
-#ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-
-	if (netif_running(dev)) {
-		netif_carrier_off(dev);
-		DoPrintInterfaceChange = SK_FALSE;
-		SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
-		netif_device_detach(dev);
-	}
-	if (otherdev != dev) {
-		if (netif_running(otherdev)) {
-			netif_carrier_off(otherdev);
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvDeInitAdapter(pAC, 1);  /* performs SkGeClose */
-			netif_device_detach(otherdev);
-		}
-	}
-
-	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-	if (pAC->AllocFlag & SK_ALLOC_IRQ) {
-		free_irq(dev->irq, dev);
-	}
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-static int skge_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-	int ret;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		printk(KERN_WARNING "sk98lin: unable to enable device %s "
-				"in resume\n", dev->name);
-		goto err_out;
-	}
-	pci_set_master(pdev);
-	if (pAC->GIni.GIMacsFound == 2)
-		ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
-	else
-		ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev);
-	if (ret) {
-		printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
-		ret = -EBUSY;
-		goto err_out_disable_pdev;
-	}
-
-	netif_device_attach(dev);
-	if (netif_running(dev)) {
-		DoPrintInterfaceChange = SK_FALSE;
-		SkDrvInitAdapter(pAC, 0);    /* first device  */
-	}
-	if (otherdev != dev) {
-		netif_device_attach(otherdev);
-		if (netif_running(otherdev)) {
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvInitAdapter(pAC, 1);    /* second device  */
-		}
-	}
-
-	return 0;
-
-err_out_disable_pdev:
-	pci_disable_device(pdev);
-err_out:
-	pAC->AllocFlag &= ~SK_ALLOC_IRQ;
-	dev->irq = 0;
-	return ret;
-}
-#else
-#define skge_suspend NULL
-#define skge_resume NULL
-#endif
-
-static struct pci_device_id skge_pci_tbl[] = {
-#ifdef SK98LIN_ALL_DEVICES
-	{ PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
-#ifdef GENESIS
-	/* Generic SysKonnect SK-98xx Gigabit Ethernet Server Adapter */	
-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
-	/* Generic SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter */	
-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#ifdef SK98LIN_ALL_DEVICES
-/* DLink card does not have valid VPD so this driver gags
- *	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- */
-	{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
-static struct pci_driver skge_driver = {
-	.name		= "sk98lin",
-	.id_table	= skge_pci_tbl,
-	.probe		= skge_probe_one,
-	.remove		= __devexit_p(skge_remove_one),
-	.suspend	= skge_suspend,
-	.resume		= skge_resume,
-};
-
-static int __init skge_init(void)
-{
-	printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
-	       " and is scheduled for removal\n");
-
-	return pci_register_driver(&skge_driver);
-}
-
-static void __exit skge_exit(void)
-{
-	pci_unregister_driver(&skge_driver);
-}
-
-module_init(skge_init);
-module_exit(skge_exit);
diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
deleted file mode 100644
index db67099..0000000
--- a/drivers/net/sk98lin/skgehwt.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgehwt.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/09/16 13:41:23 $
- * Purpose:	Hardware Timer
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- *   Hardware Timer function queue management.
- */
-intro()
-{}
-#endif
-
-/*
- * Prototypes of local functions.
- */
-#define	SK_HWT_MAX	(65000)
-
-/* correction factor */
-#define	SK_HWT_FAC	(1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
-
-/*
- * Initialize hardware timer.
- *
- * Must be called during init level 1.
- */
-void	SkHwtInit(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	pAC->Hwt.TStart = 0 ;
-	pAC->Hwt.TStop	= 0 ;
-	pAC->Hwt.TActive = SK_FALSE;
-
-	SkHwtStop(pAC, Ioc);
-}
-
-/*
- *
- * Start hardware timer (clock ticks are 16us).
- *
- */
-void	SkHwtStart(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc,	/* IoContext */
-SK_U32	Time)	/* Time in units of 16us to load the timer with. */
-{
-	SK_U32	Cnt;
-
-	if (Time > SK_HWT_MAX)
-		Time = SK_HWT_MAX;
-
-	pAC->Hwt.TStart = Time;
-	pAC->Hwt.TStop = 0L;
-
-	Cnt = Time;
-
-	/*
-	 * if time < 16 us
-	 *	time = 16 us
-	 */
-	if (!Cnt) {
-		Cnt++;
-	}
-
-	SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
-	
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_START);	/* Start timer. */
-
-	pAC->Hwt.TActive = SK_TRUE;
-}
-
-/*
- * Stop hardware timer.
- * and clear the timer IRQ
- */
-void	SkHwtStop(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
-	
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
-
-	pAC->Hwt.TActive = SK_FALSE;
-}
-
-
-/*
- *	Stop hardware timer and read time elapsed since last start.
- *
- * returns
- *	The elapsed time since last start in units of 16us.
- *
- */
-SK_U32	SkHwtRead(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SK_U32	TRead;
-	SK_U32	IStatus;
-
-	if (pAC->Hwt.TActive) {
-		
-		SkHwtStop(pAC, Ioc);
-
-		SK_IN32(Ioc, B2_TI_VAL, &TRead);
-		TRead /= SK_HWT_FAC;
-
-		SK_IN32(Ioc, B0_ISRC, &IStatus);
-
-		/* Check if timer expired (or wraped around) */
-		if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
-			
-			SkHwtStop(pAC, Ioc);
-			
-			pAC->Hwt.TStop = pAC->Hwt.TStart;
-		}
-		else {
-			
-			pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
-		}
-	}
-	return(pAC->Hwt.TStop);
-}
-
-/*
- * interrupt source= timer
- */
-void	SkHwtIsr(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SkHwtStop(pAC, Ioc);
-	
-	pAC->Hwt.TStop = pAC->Hwt.TStart;
-	
-	SkTimerDone(pAC, Ioc);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
deleted file mode 100644
index 67f1d6a..0000000
--- a/drivers/net/sk98lin/skgeinit.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgeinit.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.97 $
- * Date:	$Date: 2003/10/02 16:45:31 $
- * Purpose:	Contains functions to initialize the adapter
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* global variables ***********************************************************/
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
-#endif
-
-struct s_QOffTab {
-	int	RxQOff;		/* Receive Queue Address Offset */
-	int	XsQOff;		/* Sync Tx Queue Address Offset */
-	int	XaQOff;		/* Async Tx Queue Address Offset */
-};
-static struct s_QOffTab QOffTab[] = {
-	{Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
-};
-
-struct s_Config {
-	char	ScanString[8];
-	SK_U32	Value;
-};
-
-static struct s_Config OemConfig = {
-	{'O','E','M','_','C','o','n','f'},
-#ifdef SK_OEM_CONFIG
-	OEM_CONFIG_VALUE,
-#else
-	0,
-#endif
-};
-
-/******************************************************************************
- *
- *	SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
- *
- * Description:
- *	Enable or disable the descriptor polling of the transmit descriptor
- *	ring(s) (TxD) for port 'Port'.
- *	The new configuration is *not* saved over any SkGeStopPort() and
- *	SkGeInitPort() calls.
- *
- * Returns:
- *	nothing
- */
-void SkGePollTxD(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL PollTxD)	/* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
-{
-	SK_GEPORT *pPrt;
-	SK_U32	DWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
-
-	if (pPrt->PXSQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
-	}
-	
-	if (pPrt->PXAQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
-	}
-}	/* SkGePollTxD */
-
-
-/******************************************************************************
- *
- *	SkGeYellowLED() - Switch the yellow LED on or off.
- *
- * Description:
- *	Switch the yellow LED on or off.
- *
- * Note:
- *	This function may be called any time after SkGeInit(Level 1).
- *
- * Returns:
- *	nothing
- */
-void SkGeYellowLED(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		State)		/* yellow LED state, 0 = OFF, 0 != ON */
-{
-	if (State == 0) {
-		/* Switch yellow LED OFF */
-		SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
-	}
-	else {
-		/* Switch yellow LED ON */
-		SK_OUT8(IoC, B0_LED, LED_STAT_ON);
-	}
-}	/* SkGeYellowLED */
-
-
-#if (!defined(SK_SLIM) || defined(GENESIS))
-/******************************************************************************
- *
- *	SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
- *
- * Description:
- *	The Rx or Tx LED which is specified by 'Led' will be
- *	enabled, disabled or switched on in test mode.
- *
- * Note:
- *	'Led' must contain the address offset of the LEDs INI register.
- *
- * Usage:
- *	SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
- *
- * Returns:
- *	nothing
- */
-void SkGeXmitLED(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Led,		/* offset to the LED Init Value register */
-int		Mode)		/* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
-{
-	SK_U32	LedIni;
-
-	switch (Mode) {
-	case SK_LED_ENA:
-		LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-		SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
-		break;
-	case SK_LED_TST:
-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
-		break;
-	case SK_LED_DIS:
-	default:
-		/*
-		 * Do NOT stop the LED Timer here. The LED might be
-		 * in on state. But it needs to go off.
-		 */
-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
-		break;
-	}
-			
-	/*
-	 * 1000BT: The Transmit LED is driven by the PHY.
-	 * But the default LED configuration is used for
-	 * Level One and Broadcom PHYs.
-	 * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
-	 * (In this case it has to be added here. But we will see. XXX)
-	 */
-}	/* SkGeXmitLED */
-#endif	/* !SK_SLIM || GENESIS */
-
-
-/******************************************************************************
- *
- *	DoCalcAddr() - Calculates the start and the end address of a queue.
- *
- * Description:
- *	This function calculates the start and the end address of a queue.
- *  Afterwards the 'StartVal' is incremented to the next start position.
- *	If the port is already initialized the calculated values
- *	will be checked against the configured values and an
- *	error will be returned, if they are not equal.
- *	If the port is not initialized the values will be written to
- *	*StartAdr and *EndAddr.
- *
- * Returns:
- *	0:	success
- *	1:	configuration error
- */
-static int DoCalcAddr(
-SK_AC		*pAC, 				/* adapter context */
-SK_GEPORT	SK_FAR *pPrt,		/* port index */
-int			QuSize,				/* size of the queue to configure in kB */
-SK_U32		SK_FAR *StartVal,	/* start value for address calculation */
-SK_U32		SK_FAR *QuStartAddr,/* start addr to calculate */
-SK_U32		SK_FAR *QuEndAddr)	/* end address to calculate */
-{
-	SK_U32	EndVal;
-	SK_U32	NextStart;
-	int		Rtv;
-
-	Rtv = 0;
-	if (QuSize == 0) {
-		EndVal = *StartVal;
-		NextStart = EndVal;
-	}
-	else {
-		EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
-		NextStart = EndVal + 1;
-	}
-
-	if (pPrt->PState >= SK_PRT_INIT) {
-		if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
-			Rtv = 1;
-		}
-	}
-	else {
-		*QuStartAddr = *StartVal;
-		*QuEndAddr = EndVal;
-	}
-
-	*StartVal = NextStart;
-	return(Rtv);
-}	/* DoCalcAddr */
-
-/******************************************************************************
- *
- *	SkGeInitAssignRamToQueues() - allocate default queue sizes
- *
- * Description:
- *	This function assigns the memory to the different queues and ports.
- *	When DualNet is set to SK_TRUE all ports get the same amount of memory.
- *  Otherwise the first port gets most of the memory and all the
- *	other ports just the required minimum.
- *	This function can only be called when pAC->GIni.GIRamSize and
- *	pAC->GIni.GIMacsFound have been initialized, usually this happens
- *	at init level 1
- *
- * Returns:
- *	0 - ok
- *	1 - invalid input values
- *	2 - not enough memory
- */
-
-int SkGeInitAssignRamToQueues(
-SK_AC	*pAC,			/* Adapter context */
-int		ActivePort,		/* Active Port in RLMT mode */
-SK_BOOL	DualNet)		/* adapter context */
-{
-	int	i;
-	int	UsedKilobytes;			/* memory already assigned */
-	int	ActivePortKilobytes;	/* memory available for active port */
-	SK_GEPORT *pGePort;
-
-	UsedKilobytes = 0;
-
-	if (ActivePort >= pAC->GIni.GIMacsFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
-			ActivePort));
-		return(1);
-	}
-	if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
-		((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
-			 pAC->GIni.GIRamSize));
-		return(2);
-	}
-
-	if (DualNet) {
-		/* every port gets the same amount of memory */
-		ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-			pGePort = &pAC->GIni.GP[i];
-			
-			/* take away the minimum memory for active queues */
-			ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-
-			/* receive queue gets the minimum + 80% of the rest */
-			pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
-				ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
-				+ SK_MIN_RXQ_SIZE;
-
-			ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
-			/* synchronous transmit queue */
-			pGePort->PXSQSize = 0;
-
-			/* asynchronous transmit queue */
-			pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
-				SK_MIN_TXQ_SIZE);
-		}
-	}
-	else {	
-		/* Rlmt Mode or single link adapter */
-
-		/* Set standby queue size defaults for all standby ports */
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-			if (i != ActivePort) {
-				pGePort = &pAC->GIni.GP[i];
-
-				pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
-				pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
-				pGePort->PXSQSize = 0;
-
-				/* Count used RAM */
-				UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
-			}
-		}
-		/* what's left? */
-		ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
-
-		/* assign it to the active port */
-		/* first take away the minimum memory */
-		ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-		pGePort = &pAC->GIni.GP[ActivePort];
-
-		/* receive queue get's the minimum + 80% of the rest */
-		pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
-			(unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
-
-		ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
-		/* synchronous transmit queue */
-		pGePort->PXSQSize = 0;
-
-		/* asynchronous transmit queue */
-		pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
-			SK_MIN_TXQ_SIZE;
-	}
-#ifdef VCPU
-	VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
-		pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
-#endif /* VCPU */
-
-	return(0);
-}	/* SkGeInitAssignRamToQueues */
-
-/******************************************************************************
- *
- *	SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
- *
- * Description:
- *	This function verifies the Queue Size Configuration specified
- *	in the variables PRxQSize, PXSQSize, and PXAQSize of all
- *	used ports.
- *	This requirements must be fullfilled to have a valid configuration:
- *		- The size of all queues must not exceed GIRamSize.
- *		- The queue sizes must be specified in units of 8 kB.
- *		- The size of Rx queues of available ports must not be
- *		  smaller than 16 kB.
- *		- The size of at least one Tx queue (synch. or asynch.)
- *        of available ports must not be smaller than 16 kB
- *        when Jumbo Frames are used.
- *		- The RAM start and end addresses must not be changed
- *		  for ports which are already initialized.
- *	Furthermore SkGeCheckQSize() defines the Start and End Addresses
- *  of all ports and stores them into the HWAC port	structure.
- *
- * Returns:
- *	0:	Queue Size Configuration valid
- *	1:	Queue Size Configuration invalid
- */
-static int SkGeCheckQSize(
-SK_AC	 *pAC,		/* adapter context */
-int		 Port)		/* port index */
-{
-	SK_GEPORT *pPrt;
-	int	i;
-	int	Rtv;
-	int	Rtv2;
-	SK_U32	StartAddr;
-#ifndef SK_SLIM
-	int	UsedMem;	/* total memory used (max. found ports) */
-#endif	
-
-	Rtv = 0;
-	
-#ifndef SK_SLIM
-
-	UsedMem = 0;
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
-			(pPrt->PXSQSize & QZ_UNITS) != 0 ||
-			(pPrt->PXAQSize & QZ_UNITS) != 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
-			return(1);
-		}
-
-		if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
-			return(1);
-		}
-		
-		/*
-		 * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
-		 * if Jumbo Frames are used, this size has to be >= 16 kB.
-		 */
-		if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
-			(pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
-            ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
-			 (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
-				return(1);
-		}
-		
-		UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
-	}
-	
-	if (UsedMem > pAC->GIni.GIRamSize) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
-		return(1);
-	}
-#endif	/* !SK_SLIM */
-
-	/* Now start address calculation */
-	StartAddr = pAC->GIni.GIRamOffs;
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		/* Calculate/Check values for the receive queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
-			&pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
-		Rtv |= Rtv2;
-
-		/* Calculate/Check values for the synchronous Tx queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
-			&pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
-		Rtv |= Rtv2;
-
-		/* Calculate/Check values for the asynchronous Tx queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
-			&pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
-		Rtv |= Rtv2;
-
-		if (Rtv) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
-			return(1);
-		}
-	}
-
-	return(0);
-}	/* SkGeCheckQSize */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkGeInitMacArb() - Initialize the MAC Arbiter
- *
- * Description:
- *	This function initializes the MAC Arbiter.
- *	It must not be called if there is still an
- *	initialized or active port.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitMacArb(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
-
-	SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
-
-	/* recovery values are needed for XMAC II Rev. B2 only */
-	/* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
-
-	/*
-	 * There is no start or enable button to push, therefore
-	 * the MAC arbiter is configured and enabled now.
-	 */
-}	/* SkGeInitMacArb */
-
-
-/******************************************************************************
- *
- *	SkGeInitPktArb() - Initialize the Packet Arbiter
- *
- * Description:
- *	This function initializes the Packet Arbiter.
- *	It must not be called if there is still an
- *	initialized or active port.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitPktArb(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
-
-	/*
-	 * enable timeout timers if jumbo frames not used
-	 * NOTE: the packet arbiter timeout interrupt is needed for
-	 * half duplex hangup workaround
-	 */
-	if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
-		if (pAC->GIni.GIMacsFound == 1) {
-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
-		}
-		else {
-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
-		}
-	}
-}	/* SkGeInitPktArb */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkGeInitMacFifo() - Initialize the MAC FIFOs
- *
- * Description:
- *	Initialize all MAC FIFOs of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitMacFifo(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Word;
-#ifdef VCPU
-	SK_U32	DWord;
-#endif /* VCPU */
-	/*
-	 * For each FIFO:
-	 *	- release local reset
-	 *	- use default value for MAC FIFO size
-	 *	- setup defaults for the control register
-	 *	- enable the FIFO
-	 */
-	
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* Configure Rx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
-	
-		/* Configure Tx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
-	
-		/* Enable frame flushing if jumbo frames used */
-		if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-			SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* set Rx GMAC FIFO Flush Mask */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
-		
-		Word = (SK_U16)GMF_RX_CTRL_DEF;
-
-		/* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
-		if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-
-			Word &= ~GMF_RX_F_FL_ON;
-		}
-		
-		/* Configure Rx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
-		
-		/* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
-		
-		/* Configure Tx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
-		
-#ifdef VCPU
-		SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
-		SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
-#endif /* VCPU */
-		
-		/* set Tx GMAC FIFO Almost Empty Threshold */
-/*		SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
-	}
-#endif /* YUKON */
-
-}	/* SkGeInitMacFifo */
-
-#ifdef	SK_LNK_SYNC_CNT
-/******************************************************************************
- *
- *	SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
- *
- * Description:
- *	This function starts the Link Sync Counter of the specified
- *	port and enables the generation of an Link Sync IRQ.
- *	The Link Sync Counter may be used to detect an active link,
- *	if autonegotiation is not used.
- *
- * Note:
- *	o To ensure receiving the Link Sync Event the LinkSyncCounter
- *	  should be initialized BEFORE clearing the XMAC's reset!
- *	o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
- *	  function.
- *
- * Returns:
- *	nothing
- */
-void SkGeLoadLnkSyncCnt(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U32	CntVal)		/* Counter value */
-{
-	SK_U32	OrgIMsk;
-	SK_U32	NewIMsk;
-	SK_U32	ISrc;
-	SK_BOOL	IrqPend;
-
-	/* stop counter */
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
-
-	/*
-	 * ASIC problem:
-	 * Each time starting the Link Sync Counter an IRQ is generated
-	 * by the adapter. See problem report entry from 21.07.98
-	 *
-	 * Workaround:	Disable Link Sync IRQ and clear the unexpeced IRQ
-	 *		if no IRQ is already pending.
-	 */
-	IrqPend = SK_FALSE;
-	SK_IN32(IoC, B0_ISRC, &ISrc);
-	SK_IN32(IoC, B0_IMSK, &OrgIMsk);
-	if (Port == MAC_1) {
-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
-		if ((ISrc & IS_LNK_SYNC_M1) != 0) {
-			IrqPend = SK_TRUE;
-		}
-	}
-	else {
-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
-		if ((ISrc & IS_LNK_SYNC_M2) != 0) {
-			IrqPend = SK_TRUE;
-		}
-	}
-	if (!IrqPend) {
-		SK_OUT32(IoC, B0_IMSK, NewIMsk);
-	}
-
-	/* load counter */
-	SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
-
-	/* start counter */
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
-
-	if (!IrqPend) {
-		/* clear the unexpected IRQ, and restore the interrupt mask */
-		SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
-		SK_OUT32(IoC, B0_IMSK, OrgIMsk);
-	}
-}	/* SkGeLoadLnkSyncCnt*/
-#endif	/* SK_LNK_SYNC_CNT */
-
-#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
-/******************************************************************************
- *
- *	SkGeCfgSync() - Configure synchronous bandwidth for this port.
- *
- * Description:
- *	This function may be used to configure synchronous bandwidth
- *	to the specified port. This may be done any time after
- *	initializing the port. The configuration values are NOT saved
- *	in the HWAC port structure and will be overwritten any
- *	time when stopping and starting the port.
- *	Any values for the synchronous configuration will be ignored
- *	if the size of the synchronous queue is zero!
- *
- *	The default configuration for the synchronous service is
- *	TXA_ENA_FSYNC. This means if the size of
- *	the synchronous queue is unequal zero but no specific
- *	synchronous bandwidth is configured, the synchronous queue
- *	will always have the 'unlimited' transmit priority!
- *
- *	This mode will be restored if the synchronous bandwidth is
- *	deallocated ('IntTime' = 0 and 'LimCount' = 0).
- *
- * Returns:
- *	0:	success
- *	1:	parameter configuration error
- *	2:	try to configure quality of service although no
- *		synchronous queue is configured
- */
-int SkGeCfgSync(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U32	IntTime,	/* Interval Timer Value in units of 8ns */
-SK_U32	LimCount,	/* Number of bytes to transfer during IntTime */
-int		SyncMode)	/* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
-{
-	int Rtv;
-
-	Rtv = 0;
-
-	/* check the parameters */
-	if (LimCount > IntTime ||
-		(LimCount == 0 && IntTime != 0) ||
-		(LimCount != 0 && IntTime == 0)) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
-		return(1);
-	}
-	
-	if (pAC->GIni.GP[Port].PXSQSize == 0) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
-		return(2);
-	}
-	
-	/* calculate register values */
-	IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
-	LimCount = LimCount / 8;
-	
-	if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
-		return(1);
-	}
-
-	/*
-	 * - Enable 'Force Sync' to ensure the synchronous queue
-	 *   has the priority while configuring the new values.
-	 * - Also 'disable alloc' to ensure the settings complies
-	 *   to the SyncMode parameter.
-	 * - Disable 'Rate Control' to configure the new values.
-	 * - write IntTime and LimCount
-	 * - start 'Rate Control' and disable 'Force Sync'
-	 *   if Interval Timer or Limit Counter not zero.
-	 */
-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-		TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-	
-	SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
-	SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
-	
-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-		(SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
-	
-	if (IntTime != 0 || LimCount != 0) {
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
-	}
-
-	return(0);
-}	/* SkGeCfgSync */
-#endif /* SK_DIAG || SK_CFG_SYNC*/
-
-
-/******************************************************************************
- *
- *	DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
- *
- * Desccription:
- *	If the queue is used, enable and initialize it.
- *	Make sure the queue is still reset, if it is not used.
- *
- * Returns:
- *	nothing
- */
-static void DoInitRamQueue(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-int		QuIoOffs,		/* Queue IO Address Offset */
-SK_U32	QuStartAddr,	/* Queue Start Address */
-SK_U32	QuEndAddr,		/* Queue End Address */
-int		QuType)			/* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
-{
-	SK_U32	RxUpThresVal;
-	SK_U32	RxLoThresVal;
-
-	if (QuStartAddr != QuEndAddr) {
-		/* calculate thresholds, assume we have a big Rx queue */
-		RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
-		RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
-
-		/* build HW address format */
-		QuStartAddr = QuStartAddr / 8;
-		QuEndAddr = QuEndAddr / 8;
-
-		/* release local reset */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
-
-		/* configure addresses */
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
-
-		switch (QuType) {
-		case SK_RX_SRAM_Q:
-			/* configure threshold for small Rx Queue */
-			RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
-
-			/* continue with SK_RX_BRAM_Q */
-		case SK_RX_BRAM_Q:
-			/* write threshold for Rx Queue */
-
-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
-
-			/* the high priority threshold not used */
-			break;
-		case SK_TX_RAM_Q:
-			/*
-			 * Do NOT use Store & Forward under normal operation due to
-			 * performance optimization (GENESIS only).
-			 * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
-			 * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
-			 * we NEED Store & Forward of the RAM buffer.
-			 */
-			if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
-				pAC->GIni.GIYukon) {
-				/* enable Store & Forward Mode for the Tx Side */
-				SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
-			}
-			break;
-		}
-
-		/* set queue operational */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
-	}
-	else {
-		/* ensure the queue is still disabled */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
-	}
-}	/* DoInitRamQueue */
-
-
-/******************************************************************************
- *
- *	SkGeInitRamBufs() - Initialize the RAM Buffer Queues
- *
- * Description:
- *	Initialize all RAM Buffer Queues of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitRamBufs(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT *pPrt;
-	int RxQType;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
-		RxQType = SK_RX_SRAM_Q; 	/* small Rx Queue */
-	}
-	else {
-		RxQType = SK_RX_BRAM_Q;		/* big Rx Queue */
-	}
-
-	DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
-		pPrt->PRxQRamEnd, RxQType);
-	
-	DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
-		pPrt->PXsQRamEnd, SK_TX_RAM_Q);
-	
-	DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
-		pPrt->PXaQRamEnd, SK_TX_RAM_Q);
-
-}	/* SkGeInitRamBufs */
-
-
-/******************************************************************************
- *
- *	SkGeInitRamIface() - Initialize the RAM Interface
- *
- * Description:
- *	This function initializes the Adapters RAM Interface.
- *
- * Note:
- *	This function is used in the diagnostics.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitRamIface(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
-
-}	/* SkGeInitRamIface */
-
-
-/******************************************************************************
- *
- *	SkGeInitBmu() - Initialize the BMU state machines
- *
- * Description:
- *	Initialize all BMU state machines of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitBmu(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U32		RxWm;
-	SK_U32		TxWm;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	RxWm = SK_BMU_RX_WM;
-	TxWm = SK_BMU_TX_WM;
-	
-	if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
-		/* for better performance */
-		RxWm /= 2;
-		TxWm /= 2;
-	}
-
-	/* Rx Queue: Release all local resets and set the watermark */
-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
-
-	/*
-	 * Tx Queue: Release all local resets if the queue is used !
-	 * 		set watermark
-	 */
-	if (pPrt->PXSQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
-	}
-	
-	if (pPrt->PXAQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
-	}
-	/*
-	 * Do NOT enable the descriptor poll timers here, because
-	 * the descriptor addresses are not specified yet.
-	 */
-}	/* SkGeInitBmu */
-
-
-/******************************************************************************
- *
- *	TestStopBit() -	Test the stop bit of the queue
- *
- * Description:
- *	Stopping a queue is not as simple as it seems to be.
- *	If descriptor polling is enabled, it may happen
- *	that RX/TX stop is done and SV idle is NOT set.
- *	In this case we have to issue another stop command.
- *
- * Returns:
- *	The queues control status register
- */
-static SK_U32 TestStopBit(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		QuIoOffs)	/* Queue IO Address Offset */
-{
-	SK_U32	QuCsr;	/* CSR contents */
-
-	SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-	
-	if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
-		/* Stop Descriptor overridden by start command */
-		SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
-
-		SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-	}
-	
-	return(QuCsr);
-}	/* TestStopBit */
-
-
-/******************************************************************************
- *
- *	SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
- *
- * Description:
- *	After calling this function the descriptor rings and Rx and Tx
- *	queues of this port may be reconfigured.
- *
- *	It is possible to stop the receive and transmit path separate or
- *	both together.
- *
- *	Dir =	SK_STOP_TX 	Stops the transmit path only and resets the MAC.
- *				The receive queue is still active and
- *				the pending Rx frames may be still transferred
- *				into the RxD.
- *		SK_STOP_RX	Stop the receive path. The tansmit path
- *				has to be stopped once before.
- *		SK_STOP_ALL	SK_STOP_TX + SK_STOP_RX
- *
- *	RstMode = SK_SOFT_RST	Resets the MAC. The PHY is still alive.
- *			SK_HARD_RST	Resets the MAC and the PHY.
- *
- * Example:
- *	1) A Link Down event was signaled for a port. Therefore the activity
- *	of this port should be stopped and a hardware reset should be issued
- *	to enable the workaround of XMAC Errata #2. But the received frames
- *	should not be discarded.
- *		...
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
- *		(transfer all pending Rx frames)
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
- *		...
- *
- *	2) An event was issued which request the driver to switch
- *	the 'virtual active' link to an other already active port
- *	as soon as possible. The frames in the receive queue of this
- *	port may be lost. But the PHY must not be reset during this
- *	event.
- *		...
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
- *		...
- *
- * Extended Description:
- *	If SK_STOP_TX is set,
- *		o disable the MAC's receive and transmitter to prevent
- *		  from sending incomplete frames
- *		o stop the port's transmit queues before terminating the
- *		  BMUs to prevent from performing incomplete PCI cycles
- *		  on the PCI bus
- *		- The network Rx and Tx activity and PCI Tx transfer is
- *		  disabled now.
- *		o reset the MAC depending on the RstMode
- *		o Stop Interval Timer and Limit Counter of Tx Arbiter,
- *		  also disable Force Sync bit and Enable Alloc bit.
- *		o perform a local reset of the port's Tx path
- *			- reset the PCI FIFO of the async Tx queue
- *			- reset the PCI FIFO of the sync Tx queue
- *			- reset the RAM Buffer async Tx queue
- *			- reset the RAM Buffer sync Tx queue
- *			- reset the MAC Tx FIFO
- *		o switch Link and Tx LED off, stop the LED counters
- *
- *	If SK_STOP_RX is set,
- *		o stop the port's receive queue
- *		- The path data transfer activity is fully stopped now.
- *		o perform a local reset of the port's Rx path
- *			- reset the PCI FIFO of the Rx queue
- *			- reset the RAM Buffer receive queue
- *			- reset the MAC Rx FIFO
- *		o switch Rx LED off, stop the LED counter
- *
- *	If all ports are stopped,
- *		o reset the RAM Interface.
- *
- * Notes:
- *	o This function may be called during the driver states RESET_PORT and
- *	  SWITCH_PORT.
- */
-void SkGeStopPort(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* I/O context */
-int		Port,	/* port to stop (MAC_1 + n) */
-int		Dir,	/* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
-int		RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
-{
-#ifndef SK_DIAG
-	SK_EVPARA Para;
-#endif /* !SK_DIAG */
-	SK_GEPORT *pPrt;
-	SK_U32	DWord;
-	SK_U32	XsCsr;
-	SK_U32	XaCsr;
-	SK_U64	ToutStart;
-	int		i;
-	int		ToutCnt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((Dir & SK_STOP_TX) != 0) {
-		/* disable receiver and transmitter */
-		SkMacRxTxDisable(pAC, IoC, Port);
-		
-		/* stop both transmit queues */
-		/*
-		 * If the BMU is in the reset state CSR_STOP will terminate
-		 * immediately.
-		 */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
-
-		ToutStart = SkOsGetTime(pAC);
-		ToutCnt = 0;
-		do {
-			/*
-			 * Clear packet arbiter timeout to make sure
-			 * this loop will terminate.
-			 */
-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
-				PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
-
-			/*
-			 * If the transfer stucks at the MAC the STOP command will not
-			 * terminate if we don't flush the XMAC's transmit FIFO !
-			 */
-			SkMacFlushTxFifo(pAC, IoC, Port);
-
-			XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
-			XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
-
-			if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
-				/*
-				 * Timeout of 1/18 second reached.
-				 * This needs to be checked at 1/18 sec only.
-				 */
-				ToutCnt++;
-				if (ToutCnt > 1) {
-					/* Might be a problem when the driver event handler
-					 * calls StopPort again. XXX.
-					 */
-
-					/* Fatal Error, Loop aborted */
-					SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
-						SKERR_HWI_E018MSG);
-#ifndef SK_DIAG
-					Para.Para64 = Port;
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-#endif /* !SK_DIAG */
-					return;
-				}
-				/*
-				 * Cache incoherency workaround: Assume a start command
-				 * has been lost while sending the frame.
-				 */
-				ToutStart = SkOsGetTime(pAC);
-
-				if ((XsCsr & CSR_STOP) != 0) {
-					SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
-				}
-				if ((XaCsr & CSR_STOP) != 0) {
-					SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
-				}
-			}
-
-			/*
-			 * Because of the ASIC problem report entry from 21.08.1998 it is
-			 * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
-			 */
-		} while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
-				 (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
-		/* Reset the MAC depending on the RstMode */
-		if (RstMode == SK_SOFT_RST) {
-			SkMacSoftRst(pAC, IoC, Port);
-		}
-		else {
-			SkMacHardRst(pAC, IoC, Port);
-		}
- 		
-		/* Disable Force Sync bit and Enable Alloc bit */
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-			TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-		
-		/* Stop Interval Timer and Limit Counter of Tx Arbiter */
-		SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
-		SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
-
-		/* Perform a local reset of the port's Tx path */
-
-		/* Reset the PCI FIFO of the async Tx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the PCI FIFO of the sync Tx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the RAM Buffer async Tx queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
-		/* Reset the RAM Buffer sync Tx queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
-		
-		/* Reset Tx MAC FIFO */
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/* Note: MFF_RST_SET does NOT reset the XMAC ! */
-			SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
-
-			/* switch Link and Tx LED off, stop the LED counters */
-			/* Link LED is switched off by the RLMT and the Diag itself */
-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			/* Reset TX MAC FIFO */
-			SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
-		}
-#endif /* YUKON */
-	}
-
-	if ((Dir & SK_STOP_RX) != 0) {
-		/*
-		 * The RX Stop Command will not terminate if no buffers
-		 * are queued in the RxD ring. But it will always reach
-		 * the Idle state. Therefore we can use this feature to
-		 * stop the transfer of received packets.
-		 */
-		/* stop the port's receive queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
-		
-		i = 100;
-		do {
-			/*
-			 * Clear packet arbiter timeout to make sure
-			 * this loop will terminate
-			 */
-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
-				PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
-
-			DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
-
-			/* timeout if i==0 (bug fix for #10748) */
-			if (--i == 0) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
-					SKERR_HWI_E024MSG);
-				break;
-			}
-			/*
-			 * because of the ASIC problem report entry from 21.08.98
-			 * it is required to wait until CSR_STOP is reset and
-			 * CSR_SV_IDLE is set.
-			 */
-		} while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
-		/* The path data transfer activity is fully stopped now */
-
-		/* Perform a local reset of the port's Rx path */
-
-		 /*	Reset the PCI FIFO of the Rx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the RAM Buffer receive queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
-
-		/* Reset Rx MAC FIFO */
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			
-			SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
-
-			/* switch Rx LED off, stop the LED counter */
-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			/* Reset Rx MAC FIFO */
-			SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
-		}
-#endif /* YUKON */
-	}
-}	/* SkGeStopPort */
-
-
-/******************************************************************************
- *
- *	SkGeInit0() - Level 0 Initialization
- *
- * Description:
- *	- Initialize the BMU address offsets
- *
- * Returns:
- *	nothing
- */
-static void SkGeInit0(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	int i;
-	SK_GEPORT *pPrt;
-
-	for (i = 0; i < SK_MAX_MACS; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		pPrt->PState = SK_PRT_RESET;
-		pPrt->PRxQOff = QOffTab[i].RxQOff;
-		pPrt->PXsQOff = QOffTab[i].XsQOff;
-		pPrt->PXaQOff = QOffTab[i].XaQOff;
-		pPrt->PCheckPar = SK_FALSE;
-		pPrt->PIsave = 0;
-		pPrt->PPrevShorts = 0;
-		pPrt->PLinkResCt = 0;
-		pPrt->PAutoNegTOCt = 0;
-		pPrt->PPrevRx = 0;
-		pPrt->PPrevFcs = 0;
-		pPrt->PRxLim = SK_DEF_RX_WA_LIM;
-		pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-		pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
-		pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
-		pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
-		pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
-		pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
-			SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-		pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
-		pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-		pPrt->PMSCap = 0;
-		pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
-		pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
-		pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
-		pPrt->PAutoNegFail = SK_FALSE;
-		pPrt->PHWLinkUp = SK_FALSE;
-		pPrt->PLinkBroken = SK_TRUE; /* See WA code */
-		pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
-		pPrt->PMacColThres = TX_COL_DEF;
-		pPrt->PMacJamLen = TX_JAM_LEN_DEF;
-		pPrt->PMacJamIpgVal	= TX_JAM_IPG_DEF;
-		pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
-		pPrt->PMacIpgData = IPG_DATA_DEF;
-		pPrt->PMacLimit4 = SK_FALSE;
-	}
-
-	pAC->GIni.GIPortUsage = SK_RED_LINK;
-	pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
-	pAC->GIni.GIValIrqMask = IS_ALL_MSK;
-
-}	/* SkGeInit0*/
-
-
-/******************************************************************************
- *
- *	SkGeInit1() - Level 1 Initialization
- *
- * Description:
- *	o Do a software reset.
- *	o Clear all reset bits.
- *	o Verify that the detected hardware is present.
- *	  Return an error if not.
- *	o Get the hardware configuration
- *		+ Read the number of MACs/Ports.
- *		+ Read the RAM size.
- *		+ Read the PCI Revision Id.
- *		+ Find out the adapters host clock speed
- *		+ Read and check the PHY type
- *
- * Returns:
- *	0:	success
- *	5:	Unexpected PHY type detected
- *	6:	HW self test failed
- */
-static int SkGeInit1(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	SK_U8	Byte;
-	SK_U16	Word;
-	SK_U16	CtrlStat;
-	SK_U32	DWord;
-	int	RetVal;
-	int	i;
-
-	RetVal = 0;
-
-	/* save CLK_RUN bits (YUKON-Lite) */
-	SK_IN16(IoC, B0_CTST, &CtrlStat);
-
-	/* do the SW-reset */
-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-
-	/* release the SW-reset */
-	SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
-
-	/* reset all error bits in the PCI STATUS register */
-	/*
-	 * Note: PCI Cfg cycles cannot be used, because they are not
-	 *		 available on some platforms after 'boot time'.
-	 */
-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-	
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-	/* release Master Reset */
-	SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
-
-#ifdef CLK_RUN
-	CtrlStat |= CS_CLK_RUN_ENA;
-#endif /* CLK_RUN */
-
-	/* restore CLK_RUN bits */
-	SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
-		(CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
-
-	/* read Chip Identification Number */
-	SK_IN8(IoC, B2_CHIP_ID, &Byte);
-	pAC->GIni.GIChipId = Byte;
-	
-	/* read number of MACs */
-	SK_IN8(IoC, B2_MAC_CFG, &Byte);
-	pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
-	
-	/* get Chip Revision Number */
-	pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
-
-	/* get diff. PCI parameters */
-	SK_IN16(IoC, B0_CTST, &CtrlStat);
-	
-	/* read the adapters RAM size */
-	SK_IN8(IoC, B2_E_0, &Byte);
-	
-	pAC->GIni.GIGenesis = SK_FALSE;
-	pAC->GIni.GIYukon = SK_FALSE;
-	pAC->GIni.GIYukonLite = SK_FALSE;
-
-#ifdef GENESIS
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-
-		pAC->GIni.GIGenesis = SK_TRUE;
-
-		if (Byte == (SK_U8)3) {						
-			/* special case: 4 x 64k x 36, offset = 0x80000 */
-			pAC->GIni.GIRamSize = 1024;
-			pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
-		}
-		else {
-			pAC->GIni.GIRamSize = (int)Byte * 512;
-			pAC->GIni.GIRamOffs = 0;
-		}
-		/* all GE adapters work with 53.125 MHz host clock */
-		pAC->GIni.GIHstClkFact = SK_FACT_53;
-		
-		/* set Descr. Poll Timer Init Value to 250 ms */
-		pAC->GIni.GIPollTimerVal =
-			SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
-		
-		pAC->GIni.GIYukon = SK_TRUE;
-		
-		pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
-		
-		pAC->GIni.GIRamOffs = 0;
-		
-		/* WA for chip Rev. A */
-		pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
-			pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
-		
-		/* get PM Capabilities of PCI config space */
-		SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
-
-		/* check if VAUX is available */
-		if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
-			/* check also if PME from D3cold is set */
-			((Word & PCI_PME_D3C_SUP) != 0)) {
-			/* set entry in GE init struct */
-			pAC->GIni.GIVauxAvail = SK_TRUE;
-		}
-		
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
-			/* this is Rev. A1 */
-			pAC->GIni.GIYukonLite = SK_TRUE;
-		}
-		else {
-			/* save Flash-Address Register */
-			SK_IN32(IoC, B2_FAR, &DWord);
-
-			/* test Flash-Address Register */
-			SK_OUT8(IoC, B2_FAR + 3, 0xff);
-			SK_IN8(IoC, B2_FAR + 3, &Byte);
-
-			if (Byte != 0) {
-				/* this is Rev. A0 */
-				pAC->GIni.GIYukonLite = SK_TRUE;
-
-				/* restore Flash-Address Register */
-				SK_OUT32(IoC, B2_FAR, DWord);
-			}
-		}
-
-		/* switch power to VCC (WA for VAUX problem) */
-		SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
-			PC_VAUX_OFF | PC_VCC_ON));
-
-		/* read the Interrupt source */
-		SK_IN32(IoC, B0_ISRC, &DWord);
-		
-		if ((DWord & IS_HW_ERR) != 0) {
-			/* read the HW Error Interrupt source */
-			SK_IN32(IoC, B0_HWE_ISRC, &DWord);
-			
-			if ((DWord & IS_IRQ_SENSOR) != 0) {
-				/* disable HW Error IRQ */
-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
-			}
-		}
-		
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-			/* set GMAC Link Control reset */
-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
-
-			/* clear GMAC Link Control reset */
-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
-		}
-		/* all YU chips work with 78.125 MHz host clock */
-		pAC->GIni.GIHstClkFact = SK_FACT_78;
-		
-		pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;	/* 215 ms */
-	}
-#endif /* YUKON */
-
-	/* check if 64-bit PCI Slot is present */
-	pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
-	
-	/* check if 66 MHz PCI Clock is active */
-	pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
-
-	/* read PCI HW Revision Id. */
-	SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
-	pAC->GIni.GIPciHwRev = Byte;
-
-	/* read the PMD type */
-	SK_IN8(IoC, B2_PMD_TYP, &Byte);
-	pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
-
-	/* read the PHY type */
-	SK_IN8(IoC, B2_E_1, &Byte);
-
-	Byte &= 0x0f;	/* the PHY type is stored in the lower nibble */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			switch (Byte) {
-			case SK_PHY_XMAC:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
-				break;
-			case SK_PHY_BCOM:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
-				break;
-#ifdef OTHER_PHY
-			case SK_PHY_LONE:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
-				break;
-			case SK_PHY_NAT:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
-				break;
-#endif /* OTHER_PHY */
-			default:
-				/* ERROR: unexpected PHY type detected */
-				RetVal = 5;
-				break;
-			}
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			
-			if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
-				/* if this field is not initialized */
-				Byte = (SK_U8)SK_PHY_MARV_COPPER;
-				
-				pAC->GIni.GICopperType = SK_TRUE;
-			}
-			
-			pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
-			
-			if (pAC->GIni.GICopperType) {
-
-				pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
-					SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
-					SK_LSPEED_CAP_1000MBPS);
-				
-				pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
-				
-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
-			}
-			else {
-				Byte = (SK_U8)SK_PHY_MARV_FIBER;
-			}
-		}
-#endif /* YUKON */
-		
-		pAC->GIni.GP[i].PhyType = (int)Byte;
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("PHY type: %d  PHY addr: %04x\n", Byte,
-			pAC->GIni.GP[i].PhyAddr));
-	}
-	
-	/* get MAC Type & set function pointers dependent on */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		pAC->GIni.GIMacType = SK_MAC_XMAC;
-
-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkXmUpdateStats;
-		pAC->GIni.GIFunc.pFnMacStatistic	= SkXmMacStatistic;
-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkXmResetCounter;
-		pAC->GIni.GIFunc.pFnMacOverflow		= SkXmOverflowStatus;
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		pAC->GIni.GIMacType = SK_MAC_GMAC;
-
-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkGmUpdateStats;
-		pAC->GIni.GIFunc.pFnMacStatistic	= SkGmMacStatistic;
-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkGmResetCounter;
-		pAC->GIni.GIFunc.pFnMacOverflow		= SkGmOverflowStatus;
-
-#ifdef SPECIAL_HANDLING
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-			/* check HW self test result */
-			SK_IN8(IoC, B2_E_3, &Byte);
-			if (Byte & B2_E3_RES_MASK) {
-				RetVal = 6;
-			}
-		}
-#endif
-	}
-#endif /* YUKON */
-	
-	return(RetVal);
-}	/* SkGeInit1 */
-
-
-/******************************************************************************
- *
- *	SkGeInit2() - Level 2 Initialization
- *
- * Description:
- *	- start the Blink Source Counter
- *	- start the Descriptor Poll Timer
- *	- configure the MAC-Arbiter
- *	- configure the Packet-Arbiter
- *	- enable the Tx Arbiters
- *	- enable the RAM Interface Arbiter
- *
- * Returns:
- *	nothing
- */
-static void SkGeInit2(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-#ifdef GENESIS
-	SK_U32	DWord;
-#endif /* GENESIS */
-	int		i;
-
-	/* start the Descriptor Poll Timer */
-	if (pAC->GIni.GIPollTimerVal != 0) {
-		if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
-			pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
-		}
-		SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
-		SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* start the Blink Source Counter */
-		DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-
-		SK_OUT32(IoC, B2_BSC_INI, DWord);
-		SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
-
-		/*
-		 * Configure the MAC Arbiter and the Packet Arbiter.
-		 * They will be started once and never be stopped.
-		 */
-		SkGeInitMacArb(pAC, IoC);
-
-		SkGeInitPktArb(pAC, IoC);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* start Time Stamp Timer */
-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
-	}
-#endif /* YUKON */
-
-	/* enable the Tx Arbiters */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
-	}
-
-	/* enable the RAM Interface Arbiter */
-	SkGeInitRamIface(pAC, IoC);
-
-}	/* SkGeInit2 */
-
-/******************************************************************************
- *
- *	SkGeInit() - Initialize the GE Adapter with the specified level.
- *
- * Description:
- *	Level	0:	Initialize the Module structures.
- *	Level	1:	Generic Hardware Initialization. The IOP/MemBase pointer has
- *				to be set before calling this level.
- *
- *			o Do a software reset.
- *			o Clear all reset bits.
- *			o Verify that the detected hardware is present.
- *			  Return an error if not.
- *			o Get the hardware configuration
- *				+ Set GIMacsFound with the number of MACs.
- *				+ Store the RAM size in GIRamSize.
- *				+ Save the PCI Revision ID in GIPciHwRev.
- *			o return an error
- *				if Number of MACs > SK_MAX_MACS
- *
- *			After returning from Level 0 the adapter
- *			may be accessed with IO operations.
- *
- *	Level	2:	start the Blink Source Counter
- *
- * Returns:
- *	0:	success
- *	1:	Number of MACs exceeds SK_MAX_MACS	(after level 1)
- *	2:	Adapter not present or not accessible
- *	3:	Illegal initialization level
- *	4:	Initialization Level 1 Call missing
- *	5:	Unexpected PHY type detected
- *	6:	HW self test failed
- */
-int	SkGeInit(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Level)		/* initialization level */
-{
-	int		RetVal;		/* return value */
-	SK_U32	DWord;
-
-	RetVal = 0;
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-		("SkGeInit(Level %d)\n", Level));
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		/* Initialization Level 0 */
-		SkGeInit0(pAC, IoC);
-		pAC->GIni.GILevel = SK_INIT_DATA;
-		break;
-	
-	case SK_INIT_IO:
-		/* Initialization Level 1 */
-		RetVal = SkGeInit1(pAC, IoC);
-		if (RetVal != 0) {
-			break;
-		}
-
-		/* check if the adapter seems to be accessible */
-		SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
-		SK_IN32(IoC, B2_IRQM_INI, &DWord);
-		SK_OUT32(IoC, B2_IRQM_INI, 0L);
-		
-		if (DWord != SK_TEST_VAL) {
-			RetVal = 2;
-			break;
-		}
-
-		/* check if the number of GIMacsFound matches SK_MAX_MACS */
-		if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
-			RetVal = 1;
-			break;
-		}
-
-		/* Level 1 successfully passed */
-		pAC->GIni.GILevel = SK_INIT_IO;
-		break;
-	
-	case SK_INIT_RUN:
-		/* Initialization Level 2 */
-		if (pAC->GIni.GILevel != SK_INIT_IO) {
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
-#endif /* !SK_DIAG */
-			RetVal = 4;
-			break;
-		}
-		SkGeInit2(pAC, IoC);
-
-		/* Level 2 successfully passed */
-		pAC->GIni.GILevel = SK_INIT_RUN;
-		break;
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
-		RetVal = 3;
-		break;
-	}
-
-	return(RetVal);
-}	/* SkGeInit */
-
-
-/******************************************************************************
- *
- *	SkGeDeInit() - Deinitialize the adapter
- *
- * Description:
- *	All ports of the adapter will be stopped if not already done.
- *	Do a software reset and switch off all LEDs.
- *
- * Returns:
- *	nothing
- */
-void SkGeDeInit(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	int	i;
-	SK_U16	Word;
-
-#if (!defined(SK_SLIM) && !defined(VCPU))
-	/* ensure I2C is ready */
-	SkI2cWaitIrq(pAC, IoC);
-#endif	
-
-	/* stop all current transfer activity */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
-			pAC->GIni.GP[i].PState != SK_PRT_RESET) {
-
-			SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
-		}
-	}
-
-	/* Reset all bits in the PCI STATUS register */
-	/*
-	 * Note: PCI Cfg cycles cannot be used, because they are not
-	 *	 available on some platforms after 'boot time'.
-	 */
-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-	
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-	/* do the reset, all LEDs are switched off now */
-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-	
-	pAC->GIni.GILevel = SK_INIT_DATA;
-}	/* SkGeDeInit */
-
-
-/******************************************************************************
- *
- *	SkGeInitPort()	Initialize the specified port.
- *
- * Description:
- *	PRxQSize, PXSQSize, and PXAQSize has to be
- *	configured for the specified port before calling this function.
- *  The descriptor rings has to be initialized too.
- *
- *	o (Re)configure queues of the specified port.
- *	o configure the MAC of the specified port.
- *	o put ASIC and MAC(s) in operational mode.
- *	o initialize Rx/Tx and Sync LED
- *	o initialize RAM Buffers and MAC FIFOs
- *
- *	The port is ready to connect when returning.
- *
- * Note:
- *	The MAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	0:	success
- *	1:	Queue size initialization error. The configured values
- *		for PRxQSize, PXSQSize, or PXAQSize are invalid for one
- *		or more queues. The specified port was NOT initialized.
- *		An error log entry was generated.
- *	2:	The port has to be stopped before it can be initialized again.
- */
-int SkGeInitPort(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port to configure */
-{
-	SK_GEPORT *pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (SkGeCheckQSize(pAC, Port) != 0) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
-		return(1);
-	}
-	
-	if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
-		return(2);
-	}
-
-	/* configuration ok, initialize the Port now */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* initialize Rx, Tx and Link LED */
-		/*
-		 * If 1000BT Phy needs LED initialization than swap
-		 * LED and XMAC initialization order
-		 */
-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
-		/* The Link LED is initialized by RLMT or Diagnostics itself */
-		
-		SkXmInitMac(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-
-		SkGmInitMac(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-	
-	/* do NOT initialize the Link Sync Counter */
-
-	SkGeInitMacFifo(pAC, IoC, Port);
-	
-	SkGeInitRamBufs(pAC, IoC, Port);
-	
-	if (pPrt->PXSQSize != 0) {
-		/* enable Force Sync bit if synchronous queue available */
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
-	}
-	
-	SkGeInitBmu(pAC, IoC, Port);
-
-	/* mark port as initialized */
-	pPrt->PState = SK_PRT_INIT;
-
-	return(0);
-}	/* SkGeInitPort */
diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
deleted file mode 100644
index fde45083..0000000
--- a/drivers/net/sk98lin/skgemib.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgemib.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/15 13:38:12 $
- * Purpose:	Private Network Management Interface Management Database
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * PRIVATE OID handler function prototypes
- */
-PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int* pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-
-#ifdef SK_POWER_MGMT
-PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_DIAG_SUPPORT */
-
-
-/* defines *******************************************************************/
-#define ID_TABLE_SIZE	ARRAY_SIZE(IdTable)
-
-
-/* global variables **********************************************************/
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
-	{OID_GEN_XMIT_OK,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
-	{OID_GEN_RCV_OK,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
-	{OID_GEN_XMIT_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_RCV_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_RCV_NO_BUFFER,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_DIRECTED_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
-	{OID_GEN_MULTICAST_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
-	{OID_GEN_BROADCAST_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
-	{OID_GEN_DIRECTED_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
-	{OID_GEN_MULTICAST_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
-	{OID_GEN_BROADCAST_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
-	{OID_GEN_RCV_CRC_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
-	{OID_GEN_TRANSMIT_QUEUE_LENGTH,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_802_3_PERMANENT_ADDRESS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, 0},
-	{OID_802_3_CURRENT_ADDRESS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, 0},
-	{OID_802_3_RCV_ERROR_ALIGNMENT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
-	{OID_802_3_XMIT_ONE_COLLISION,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
-	{OID_802_3_XMIT_MORE_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
-	{OID_802_3_XMIT_DEFERRED,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
-	{OID_802_3_XMIT_MAX_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
-	{OID_802_3_RCV_OVERRUN,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
-	{OID_802_3_XMIT_UNDERRUN,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
-	{OID_802_3_XMIT_TIMES_CRS_LOST,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
-	{OID_802_3_XMIT_LATE_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
-#ifdef SK_POWER_MGMT
-	{OID_PNP_CAPABILITIES,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, PowerManagement, 0},
-	{OID_PNP_SET_POWER,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_QUERY_POWER,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, PowerManagement, 0},
-	{OID_PNP_ADD_WAKE_UP_PATTERN,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_REMOVE_WAKE_UP_PATTERN,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_ENABLE_WAKE_UP,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, PowerManagement, 0},
-#endif /* SK_POWER_MGMT */
-#ifdef SK_DIAG_SUPPORT
-	{OID_SKGE_DIAG_MODE,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, DiagActions, 0},
-#endif /* SK_DIAG_SUPPORT */
-	{OID_SKGE_MDB_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(MgmtDBVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SUPPORTED_LIST,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ALL_DATA,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, OidStruct, 0},
-	{OID_SKGE_VPD_FREE_BYTES,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdFreeBytes),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ENTRIES_LIST,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdEntriesList),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ENTRIES_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdEntriesNumber),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_KEY,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_VALUE,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ACCESS,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ACTION,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
-		SK_PNMI_RW, Vpd, 0},
-	{OID_SKGE_PORT_NUMBER,		
-		1,
-		0,
-		SK_PNMI_MAI_OFF(PortNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DEVICE_TYPE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DeviceType),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_DESCR,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverDescr),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_RELDATE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverReleaseDate),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_FILENAME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverFileName),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_HW_DESCR,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(HwDescr),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_HW_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(HwVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHIPSET,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Chipset),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHIPID,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ChipId),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RAMSIZE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RamSize),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_VAUXAVAIL,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VauxAvail),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ACTION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Action),
-		SK_PNMI_RW, Perform, 0},
-	{OID_SKGE_RESULT,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TestResult),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_TYPE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusType),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_SPEED,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusSpeed),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_WIDTH,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusWidth),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_SW_QUEUE_LEN,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxSwQueueLen),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_SW_QUEUE_MAX,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxSwQueueMax),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_RETRY,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxRetryCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_INTR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxIntrCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_INTR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxIntrCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_NO_BUF_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxNoBufCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_NO_BUF_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxNoBufCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_USED_DESCR_NO,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxUsedDescrNo),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_DELIVERED_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxDeliveredCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_OCTETS_DELIV_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_HW_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxHwErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_HW_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxHwErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_IN_ERRORS_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(InErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_OUT_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(OutErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ERR_RECOVERY_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ErrRecoveryCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SYSUPTIME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(SysUpTime),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SENSOR_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(SensorNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SENSOR_INDEX,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_DESCR,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_TYPE,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_VALUE,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_THRES_LOW,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_THRES_UPP,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_THRES_LOW,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_THRES_UPP,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_STATUS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_CTS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_CTS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_TIME,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_TIME,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_CHKSM_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ChecksumNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHKSM_RX_OK_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_RX_UNABLE_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_RX_ERR_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_TX_OK_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_TX_UNABLE_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_STAT_TX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
-	{OID_SKGE_STAT_TX_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
-	{OID_SKGE_STAT_TX_BROADCAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
-	{OID_SKGE_STAT_TX_MULTICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
-	{OID_SKGE_STAT_TX_UNICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
-	{OID_SKGE_STAT_TX_LONGFRAMES,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
-	{OID_SKGE_STAT_TX_BURST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
-	{OID_SKGE_STAT_TX_PFLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
-	{OID_SKGE_STAT_TX_FLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
-	{OID_SKGE_STAT_TX_SINGLE_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
-	{OID_SKGE_STAT_TX_MULTI_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
-	{OID_SKGE_STAT_TX_EXCESS_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
-	{OID_SKGE_STAT_TX_LATE_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
-	{OID_SKGE_STAT_TX_DEFFERAL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
-	{OID_SKGE_STAT_TX_EXCESS_DEF,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
-	{OID_SKGE_STAT_TX_UNDERRUN,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
-	{OID_SKGE_STAT_TX_CARRIER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
-/*	{OID_SKGE_STAT_TX_UTIL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
-	{OID_SKGE_STAT_TX_64,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
-	{OID_SKGE_STAT_TX_127,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
-	{OID_SKGE_STAT_TX_255,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
-	{OID_SKGE_STAT_TX_511,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
-	{OID_SKGE_STAT_TX_1023,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
-	{OID_SKGE_STAT_TX_MAX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
-	{OID_SKGE_STAT_TX_SYNC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
-	{OID_SKGE_STAT_TX_SYNC_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
-	{OID_SKGE_STAT_RX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
-	{OID_SKGE_STAT_RX_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
-	{OID_SKGE_STAT_RX_BROADCAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
-	{OID_SKGE_STAT_RX_MULTICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
-	{OID_SKGE_STAT_RX_UNICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
-	{OID_SKGE_STAT_RX_LONGFRAMES,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
-	{OID_SKGE_STAT_RX_PFLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
-	{OID_SKGE_STAT_RX_FLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
-	{OID_SKGE_STAT_RX_PFLOWC_ERR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
-	{OID_SKGE_STAT_RX_FLOWC_UNKWN,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
-	{OID_SKGE_STAT_RX_BURST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
-	{OID_SKGE_STAT_RX_MISSED,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
-	{OID_SKGE_STAT_RX_FRAMING,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
-	{OID_SKGE_STAT_RX_OVERFLOW,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
-	{OID_SKGE_STAT_RX_JABBER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
-	{OID_SKGE_STAT_RX_CARRIER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
-	{OID_SKGE_STAT_RX_IR_LENGTH,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
-	{OID_SKGE_STAT_RX_SYMBOL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
-	{OID_SKGE_STAT_RX_SHORTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
-	{OID_SKGE_STAT_RX_RUNT,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
-	{OID_SKGE_STAT_RX_CEXT,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
-	{OID_SKGE_STAT_RX_TOO_LONG,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
-	{OID_SKGE_STAT_RX_FCS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
-/*	{OID_SKGE_STAT_RX_UTIL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
-	{OID_SKGE_STAT_RX_64,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
-	{OID_SKGE_STAT_RX_127,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
-	{OID_SKGE_STAT_RX_255,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
-	{OID_SKGE_STAT_RX_511,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
-	{OID_SKGE_STAT_RX_1023,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
-	{OID_SKGE_STAT_RX_MAX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
-	{OID_SKGE_PHYS_CUR_ADDR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
-		SK_PNMI_RW, Addr, 0},
-	{OID_SKGE_PHYS_FAC_ADDR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
-		SK_PNMI_RO, Addr, 0},
-	{OID_SKGE_PMD,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_CONNECTOR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_TYPE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_LINK_MODE_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_TRAP,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Trap),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TRAP_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TrapNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RLMT_MODE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtMode),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortNumber),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_ACTIVE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortActive),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_PREFERRED,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortPreferred),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeCts),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_TIME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeTime),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_ESTIM,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeEstimate),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_THRES,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeThreshold),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_INDEX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_TX_HELLO_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_RX_HELLO_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_TX_SP_REQ_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_RX_SP_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_MONITOR_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtMonitorNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RLMT_MONITOR_INDEX,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ADDR,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ERRS,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_TIMESTAMP,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ADMIN,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
-		SK_PNMI_RW, Monitor, 0},
-	{OID_SKGE_MTU,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(MtuSize),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_VCT_GET,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Vct, 0},
-	{OID_SKGE_VCT_SET,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, Vct, 0},
-	{OID_SKGE_VCT_STATUS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Vct, 0},
-	{OID_SKGE_BOARDLEVEL,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-};
-
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
deleted file mode 100644
index 876bb21..0000000
--- a/drivers/net/sk98lin/skgepnmi.c
+++ /dev/null
@@ -1,8198 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnmi.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.111 $
- * Date:	$Date: 2003/09/15 13:35:35 $
- * Purpose:	Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-#ifndef _lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
-#endif /* !_lint */
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/xmac_ii.h"
-#include "h/skdebug.h"
-#include "h/skqueue.h"
-#include "h/skgepnmi.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skdrv2nd.h"
-#include "h/skgepnm2.h"
-#ifdef SK_POWER_MGMT
-#include "h/skgepmgt.h"
-#endif
-/* defines *******************************************************************/
-
-#ifndef DEBUG
-#define PNMI_STATIC	static
-#else	/* DEBUG */
-#define PNMI_STATIC
-#endif /* DEBUG */
-
-/*
- * Public Function prototypes
- */
-int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
-int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
-int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
-	unsigned int * pLen, SK_U32 NetIndex);
-
-
-/*
- * Private Function prototypes
- */
-
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
-	PhysPortIndex);
-PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
-	PhysPortIndex);
-PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
-PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
-PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
-	unsigned int PhysPortIndex, unsigned int StatIndex);
-PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
-	unsigned int StatIndex, SK_U32 NetIndex);
-PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
-PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
-	unsigned int *pEntries);
-PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
-	unsigned int KeyArrLen, unsigned int *pKeyNo);
-PNMI_STATIC int LookupId(SK_U32 Id);
-PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
-	unsigned int LastMac);
-PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
-PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
-	unsigned int PortIndex);
-PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
-	unsigned int SensorIndex);
-PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
-PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
-PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
-	unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-#include "skgemib.c"
-
-/* global variables **********************************************************/
-
-/*
- * Overflow status register bit table and corresponding counter
- * dependent on MAC type - the number relates to the size of overflow
- * mask returned by the pFnMacOverflow function
- */
-PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
-/* Bit0  */	{ SK_PNMI_HTX, 				SK_PNMI_HTX_UNICAST},
-/* Bit1  */	{ SK_PNMI_HTX_OCTETHIGH, 	SK_PNMI_HTX_BROADCAST},
-/* Bit2  */	{ SK_PNMI_HTX_OCTETLOW, 	SK_PNMI_HTX_PMACC},
-/* Bit3  */	{ SK_PNMI_HTX_BROADCAST, 	SK_PNMI_HTX_MULTICAST},
-/* Bit4  */	{ SK_PNMI_HTX_MULTICAST, 	SK_PNMI_HTX_OCTETLOW},
-/* Bit5  */	{ SK_PNMI_HTX_UNICAST, 		SK_PNMI_HTX_OCTETHIGH},
-/* Bit6  */	{ SK_PNMI_HTX_LONGFRAMES, 	SK_PNMI_HTX_64},
-/* Bit7  */	{ SK_PNMI_HTX_BURST, 		SK_PNMI_HTX_127},
-/* Bit8  */	{ SK_PNMI_HTX_PMACC, 		SK_PNMI_HTX_255},
-/* Bit9  */	{ SK_PNMI_HTX_MACC, 		SK_PNMI_HTX_511},
-/* Bit10 */	{ SK_PNMI_HTX_SINGLE_COL, 	SK_PNMI_HTX_1023},
-/* Bit11 */	{ SK_PNMI_HTX_MULTI_COL, 	SK_PNMI_HTX_MAX},
-/* Bit12 */	{ SK_PNMI_HTX_EXCESS_COL, 	SK_PNMI_HTX_LONGFRAMES},
-/* Bit13 */	{ SK_PNMI_HTX_LATE_COL, 	SK_PNMI_HTX_RESERVED},
-/* Bit14 */	{ SK_PNMI_HTX_DEFFERAL, 	SK_PNMI_HTX_COL},
-/* Bit15 */	{ SK_PNMI_HTX_EXCESS_DEF, 	SK_PNMI_HTX_LATE_COL},
-/* Bit16 */	{ SK_PNMI_HTX_UNDERRUN, 	SK_PNMI_HTX_EXCESS_COL},
-/* Bit17 */	{ SK_PNMI_HTX_CARRIER, 		SK_PNMI_HTX_MULTI_COL},
-/* Bit18 */	{ SK_PNMI_HTX_UTILUNDER, 	SK_PNMI_HTX_SINGLE_COL},
-/* Bit19 */	{ SK_PNMI_HTX_UTILOVER, 	SK_PNMI_HTX_UNDERRUN},
-/* Bit20 */	{ SK_PNMI_HTX_64, 			SK_PNMI_HTX_RESERVED},
-/* Bit21 */	{ SK_PNMI_HTX_127, 			SK_PNMI_HTX_RESERVED},
-/* Bit22 */	{ SK_PNMI_HTX_255, 			SK_PNMI_HTX_RESERVED},
-/* Bit23 */	{ SK_PNMI_HTX_511, 			SK_PNMI_HTX_RESERVED},
-/* Bit24 */	{ SK_PNMI_HTX_1023, 		SK_PNMI_HTX_RESERVED},
-/* Bit25 */	{ SK_PNMI_HTX_MAX, 			SK_PNMI_HTX_RESERVED},
-/* Bit26 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit27 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit28 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit29 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit30 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit31 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit32 */	{ SK_PNMI_HRX, 				SK_PNMI_HRX_UNICAST},
-/* Bit33 */	{ SK_PNMI_HRX_OCTETHIGH, 	SK_PNMI_HRX_BROADCAST},
-/* Bit34 */	{ SK_PNMI_HRX_OCTETLOW, 	SK_PNMI_HRX_PMACC},
-/* Bit35 */	{ SK_PNMI_HRX_BROADCAST, 	SK_PNMI_HRX_MULTICAST},
-/* Bit36 */	{ SK_PNMI_HRX_MULTICAST, 	SK_PNMI_HRX_FCS},
-/* Bit37 */	{ SK_PNMI_HRX_UNICAST, 		SK_PNMI_HRX_RESERVED},
-/* Bit38 */	{ SK_PNMI_HRX_PMACC, 		SK_PNMI_HRX_OCTETLOW},
-/* Bit39 */	{ SK_PNMI_HRX_MACC, 		SK_PNMI_HRX_OCTETHIGH},
-/* Bit40 */	{ SK_PNMI_HRX_PMACC_ERR, 	SK_PNMI_HRX_BADOCTETLOW},
-/* Bit41 */	{ SK_PNMI_HRX_MACC_UNKWN,	SK_PNMI_HRX_BADOCTETHIGH},
-/* Bit42 */	{ SK_PNMI_HRX_BURST, 		SK_PNMI_HRX_UNDERSIZE},
-/* Bit43 */	{ SK_PNMI_HRX_MISSED, 		SK_PNMI_HRX_RUNT},
-/* Bit44 */	{ SK_PNMI_HRX_FRAMING, 		SK_PNMI_HRX_64},
-/* Bit45 */	{ SK_PNMI_HRX_OVERFLOW, 	SK_PNMI_HRX_127},
-/* Bit46 */	{ SK_PNMI_HRX_JABBER, 		SK_PNMI_HRX_255},
-/* Bit47 */	{ SK_PNMI_HRX_CARRIER, 		SK_PNMI_HRX_511},
-/* Bit48 */	{ SK_PNMI_HRX_IRLENGTH, 	SK_PNMI_HRX_1023},
-/* Bit49 */	{ SK_PNMI_HRX_SYMBOL, 		SK_PNMI_HRX_MAX},
-/* Bit50 */	{ SK_PNMI_HRX_SHORTS, 		SK_PNMI_HRX_LONGFRAMES},
-/* Bit51 */	{ SK_PNMI_HRX_RUNT, 		SK_PNMI_HRX_TOO_LONG},
-/* Bit52 */	{ SK_PNMI_HRX_TOO_LONG, 	SK_PNMI_HRX_JABBER},
-/* Bit53 */	{ SK_PNMI_HRX_FCS, 			SK_PNMI_HRX_RESERVED},
-/* Bit54 */	{ SK_PNMI_HRX_RESERVED, 	SK_PNMI_HRX_OVERFLOW},
-/* Bit55 */	{ SK_PNMI_HRX_CEXT, 		SK_PNMI_HRX_RESERVED},
-/* Bit56 */	{ SK_PNMI_HRX_UTILUNDER, 	SK_PNMI_HRX_RESERVED},
-/* Bit57 */	{ SK_PNMI_HRX_UTILOVER, 	SK_PNMI_HRX_RESERVED},
-/* Bit58 */	{ SK_PNMI_HRX_64, 			SK_PNMI_HRX_RESERVED},
-/* Bit59 */	{ SK_PNMI_HRX_127, 			SK_PNMI_HRX_RESERVED},
-/* Bit60 */	{ SK_PNMI_HRX_255, 			SK_PNMI_HRX_RESERVED},
-/* Bit61 */	{ SK_PNMI_HRX_511, 			SK_PNMI_HRX_RESERVED},
-/* Bit62 */	{ SK_PNMI_HRX_1023, 		SK_PNMI_HRX_RESERVED},
-/* Bit63 */	{ SK_PNMI_HRX_MAX, 			SK_PNMI_HRX_RESERVED}
-};
-
-/*
- * Table for hardware register saving on resets and port switches
- */
-PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
-	/* SK_PNMI_HTX */
-	{{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_OCTETHIGH */
-	{{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
-	/* SK_PNMI_HTX_OCTETLOW */
-	{{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
-	/* SK_PNMI_HTX_BROADCAST */
-	{{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_MULTICAST */
-	{{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_UNICAST */
-	{{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_BURST */
-	{{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_PMACC */
-	{{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
-	/* SK_PNMI_HTX_MACC */
-	{{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_COL */
-	{{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_SINGLE_COL */
-	{{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_MULTI_COL */
-	{{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_EXCESS_COL */
-	{{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_LATE_COL */
-	{{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_DEFFERAL */
-	{{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_EXCESS_DEF */
-	{{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UNDERRUN */
-	{{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
-	/* SK_PNMI_HTX_CARRIER */
-	{{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UTILUNDER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UTILOVER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_64 */
-	{{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
-	/* SK_PNMI_HTX_127 */
-	{{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
-	/* SK_PNMI_HTX_255 */
-	{{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
-	/* SK_PNMI_HTX_511 */
-	{{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
-	/* SK_PNMI_HTX_1023 */
-	{{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
-	/* SK_PNMI_HTX_MAX */
-	{{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
-	/* SK_PNMI_HTX_LONGFRAMES  */
-	{{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
-	/* SK_PNMI_HTX_SYNC */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_SYNC_OCTET */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_RESERVED */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX */
-	{{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_OCTETHIGH */
-	{{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
-	/* SK_PNMI_HRX_OCTETLOW */
-	{{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
-	/* SK_PNMI_HRX_BADOCTETHIGH */
-	{{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
-	/* SK_PNMI_HRX_BADOCTETLOW */
-	{{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
-	/* SK_PNMI_HRX_BROADCAST */
-	{{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_MULTICAST */
-	{{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_UNICAST */
-	{{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_PMACC */
-	{{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
-	/* SK_PNMI_HRX_MACC */
-	{{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_PMACC_ERR */
-	{{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_MACC_UNKWN */
-	{{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_BURST */
-	{{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_MISSED */
-	{{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_FRAMING */
-	{{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UNDERSIZE */
-	{{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
-	/* SK_PNMI_HRX_OVERFLOW */
-	{{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
-	/* SK_PNMI_HRX_JABBER */
-	{{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
-	/* SK_PNMI_HRX_CARRIER */
-	{{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_IRLENGTH */
-	{{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_SYMBOL */
-	{{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_SHORTS */
-	{{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_RUNT */
-	{{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
-	/* SK_PNMI_HRX_TOO_LONG */
-	{{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
-	/* SK_PNMI_HRX_FCS */
-	{{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
-	/* SK_PNMI_HRX_CEXT */
-	{{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UTILUNDER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UTILOVER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_64 */
-	{{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
-	/* SK_PNMI_HRX_127 */
-	{{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
-	/* SK_PNMI_HRX_255 */
-	{{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
-	/* SK_PNMI_HRX_511 */
-	{{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
-	/* SK_PNMI_HRX_1023 */
-	{{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
-	/* SK_PNMI_HRX_MAX */
-	{{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
-	/* SK_PNMI_HRX_LONGFRAMES */
-	{{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
-	/* SK_PNMI_HRX_RESERVED */
-	{{0, SK_FALSE}, {0, SK_FALSE}}
-};
-
-
-/*****************************************************************************
- *
- * Public functions
- *
- */
-
-/*****************************************************************************
- *
- * SkPnmiInit - Init function of PNMI
- *
- * Description:
- *	SK_INIT_DATA: Initialises the data structures
- *	SK_INIT_IO:   Resets the XMAC statistics, determines the device and
- *	              connector type.
- *	SK_INIT_RUN:  Starts a timer event for port switch per hour
- *	              calculation.
- *
- * Returns:
- *	Always 0
- */
-int SkPnmiInit(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Level)		/* Initialization level */
-{
-	unsigned int	PortMax;	/* Number of ports */
-	unsigned int	PortIndex;	/* Current port index in loop */
-	SK_U16		Val16;		/* Multiple purpose 16 bit variable */
-	SK_U8		Val8;		/* Mulitple purpose 8 bit variable */
-	SK_EVPARA	EventParam;	/* Event struct for timer event */
-	SK_PNMI_VCT	*pVctBackupData;
-
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiInit: Called, level=%d\n", Level));
-
-	switch (Level) {
-
-	case SK_INIT_DATA:
-		SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
-		pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
-		pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-		pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
-		for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
-
-			pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
-			pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
-		}
-
-#ifdef SK_PNMI_CHECK
-		if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
-			
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
-					   ("CounterOffset struct size (%d) differs from "
-						"SK_PNMI_MAX_IDX (%d)\n",
-						SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
-		}
-
-#endif /* SK_PNMI_CHECK */
-		break;
-
-	case SK_INIT_IO:
-		/*
-		 * Reset MAC counters
-		 */
-		PortMax = pAC->GIni.GIMacsFound;
-
-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-
-			pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
-		}
-		
-		/* Initialize DSP variables for Vct() to 0xff => Never written! */		
-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-			pAC->GIni.GP[PortIndex].PCableLen = 0xff;
-			pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
-			pVctBackupData->PCableLen = 0xff;
-		}
-		
-		/*
-		 * Get pci bus speed
-		 */
-		SK_IN16(IoC, B0_CTST, &Val16);
-		if ((Val16 & CS_BUS_CLOCK) == 0) {
-
-			pAC->Pnmi.PciBusSpeed = 33;
-		}
-		else {
-			pAC->Pnmi.PciBusSpeed = 66;
-		}
-
-		/*
-		 * Get pci bus width
-		 */
-		SK_IN16(IoC, B0_CTST, &Val16);
-		if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
-
-			pAC->Pnmi.PciBusWidth = 32;
-		}
-		else {
-			pAC->Pnmi.PciBusWidth = 64;
-		}
-
-		/*
-		 * Get chipset
-		 */
-		switch (pAC->GIni.GIChipId) {
-		case CHIP_ID_GENESIS:
-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
-			break;
-
-		case CHIP_ID_YUKON:
-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
-			break;
-
-		default:
-			break;
-		}
-
-		/*
-		 * Get PMD and DeviceType
-		 */
-		SK_IN8(IoC, B2_PMD_TYP, &Val8);
-		switch (Val8) {
-		case 'S':
-			pAC->Pnmi.PMD = 3;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020002;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020001;
-			}
-			break;
-
-		case 'L':
-			pAC->Pnmi.PMD = 2;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020004;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020003;
-			}
-			break;
-
-		case 'C':
-			pAC->Pnmi.PMD = 4;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020006;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020005;
-			}
-			break;
-
-		case 'T':
-			pAC->Pnmi.PMD = 5;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020008;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020007;
-			}
-			break;
-
-		default :
-			pAC->Pnmi.PMD = 1;
-			pAC->Pnmi.DeviceType = 0;
-			break;
-		}
-
-		/*
-		 * Get connector
-		 */
-		SK_IN8(IoC, B2_CONN_TYP, &Val8);
-		switch (Val8) {
-		case 'C':
-			pAC->Pnmi.Connector = 2;
-			break;
-
-		case 'D':
-			pAC->Pnmi.Connector = 3;
-			break;
-
-		case 'F':
-			pAC->Pnmi.Connector = 4;
-			break;
-
-		case 'J':
-			pAC->Pnmi.Connector = 5;
-			break;
-
-		case 'V':
-			pAC->Pnmi.Connector = 6;
-			break;
-
-		default:
-			pAC->Pnmi.Connector = 1;
-			break;
-		}
-		break;
-
-	case SK_INIT_RUN:
-		/*
-		 * Start timer for RLMT change counter
-		 */
-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
-			EventParam);
-		break;
-
-	default:
-		break; /* Nothing todo */
-	}
-
-	return (0);
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetVar - Retrieves the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. If the instance
- *	-1 is passed, the values of all instances are returned in an
- *	array of values.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-static int SkPnmiGetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetVar - Presets the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	If the instance -1 is passed, an array of values is supposed and
- *	all instances of the OID will be set.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-static int SkPnmiPreSetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* Total length of management data */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetVar - Sets the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	If the instance -1 is passed, an array of values is supposed and
- *	all instances of the OID will be set.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-int SkPnmiSetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* Total length of management data */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Runs through the IdTable, queries the single OIDs and stores the
- *	returned data into the management database structure
- *	SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
- *	is stored in the IdTable. The return value of the function will also
- *	be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-int SkPnmiGetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer to which the management data will be copied. */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	TableIndex;
-	unsigned int	DstOffset;
-	unsigned int	InstanceNo;
-	unsigned int	InstanceCnt;
-	SK_U32		Instance;
-	unsigned int	TmpLen;
-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
-				(SK_U32)(-1));
-		}
-
-		*pLen = SK_PNMI_STRUCT_SIZE;
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-    /*
-     * Check NetIndex
-     */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-
-	/* Update statistic */
-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
-
-	if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
-		SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	/*
-	 * Increment semaphores to indicate that an update was
-	 * already done
-	 */
-	pAC->Pnmi.MacUpdatedFlag ++;
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-	pAC->Pnmi.SirqUpdatedFlag ++;
-
-	/* Get vpd keys for instance calculation */
-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
-	if (Ret != SK_PNMI_ERR_OK) {
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		pAC->Pnmi.RlmtUpdatedFlag --;
-		pAC->Pnmi.SirqUpdatedFlag --;
-
-		SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/* Retrieve values */
-	SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
-		InstanceNo = IdTable[TableIndex].InstanceNo;
-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
-			InstanceCnt ++) {
-
-			DstOffset = IdTable[TableIndex].Offset +
-				(InstanceCnt - 1) *
-				IdTable[TableIndex].StructSize;
-
-			/*
-			 * For the VPD the instance is not an index number
-			 * but the key itself. Determin with the instance
-			 * counter the VPD key to be used.
-			 */
-			if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
-
-				SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
-			}
-			else {
-				Instance = (SK_U32)InstanceCnt;
-			}
-
-			TmpLen = *pLen - DstOffset;
-			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
-				IdTable[TableIndex].Id, (char *)pBuf +
-				DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
-
-			/*
-			 * An unknown instance error means that we reached
-			 * the last instance of that variable. Proceed with
-			 * the next OID in the table and ignore the return
-			 * code.
-			 */
-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
-                break;
-			}
-
-			if (Ret != SK_PNMI_ERR_OK) {
-
-				pAC->Pnmi.MacUpdatedFlag --;
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-				SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (Ret);
-			}
-		}
-	}
-
-	pAC->Pnmi.MacUpdatedFlag --;
-	pAC->Pnmi.RlmtUpdatedFlag --;
-	pAC->Pnmi.SirqUpdatedFlag --;
-
-	*pLen = SK_PNMI_STRUCT_SIZE;
-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Calls a general sub-function for all this set stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	The sub-function runs through the IdTable, checks which OIDs are able
- *	to set, and calls the handler function of the OID to perform the
- *	preset. The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- */
-int SkPnmiPreSetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer which contains the data to be set */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
-    					pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Calls a general sub-function for all this set stuff. The return value
- *	of the function will also be stored in SK_PNMI_STRUCT_DATA if the
- *	passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *	The sub-function runs through the IdTable, checks which OIDs are able
- *	to set, and calls the handler function of the OID to perform the
- *	set. The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- */
-int SkPnmiSetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer which contains the data to be set */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
-    					pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiEvent - Event handler
- *
- * Description:
- *	Handles the following events:
- *	SK_PNMI_EVT_SIRQ_OVERFLOW     When a hardware counter overflows an
- *	                              interrupt will be generated which is
- *	                              first handled by SIRQ which generates a
- *	                              this event. The event increments the
- *	                              upper 32 bit of the 64 bit counter.
- *	SK_PNMI_EVT_SEN_XXX           The event is generated by the I2C module
- *	                              when a sensor reports a warning or
- *	                              error. The event will store a trap
- *	                              message in the trap buffer.
- *	SK_PNMI_EVT_CHG_EST_TIMER     The timer event was initiated by this
- *	                              module and is used to calculate the
- *	                              port switches per hour.
- *	SK_PNMI_EVT_CLEAR_COUNTER     The event clears all counters and
- *	                              timestamps.
- *	SK_PNMI_EVT_XMAC_RESET        The event is generated by the driver
- *	                              before a hard reset of the XMAC is
- *	                              performed. All counters will be saved
- *	                              and added to the hardware counter
- *	                              values after reset to grant continuous
- *	                              counter values.
- *	SK_PNMI_EVT_RLMT_PORT_UP      Generated by RLMT to notify that a port
- *	                              went logically up. A trap message will
- *	                              be stored to the trap buffer.
- *	SK_PNMI_EVT_RLMT_PORT_DOWN    Generated by RLMT to notify that a port
- *	                              went logically down. A trap message will
- *	                              be stored to the trap buffer.
- *	SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
- *	                              spanning tree root bridges were
- *	                              detected. A trap message will be stored
- *	                              to the trap buffer.
- *	SK_PNMI_EVT_RLMT_ACTIVE_DOWN  Notifies PNMI that an active port went
- *	                              down. PNMI will not further add the
- *	                              statistic values to the virtual port.
- *	SK_PNMI_EVT_RLMT_ACTIVE_UP    Notifies PNMI that a port went up and
- *	                              is now an active port. PNMI will now
- *	                              add the statistic data of this port to
- *	                              the virtual port.
- *	SK_PNMI_EVT_RLMT_SET_NETS     Notifies PNMI about the net mode. The first parameter
- *	                              contains the number of nets. 1 means single net, 2 means
- *	                              dual net. The second parameter is -1
- *
- * Returns:
- *	Always 0
- */
-int SkPnmiEvent(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Event,		/* Event-Id */
-SK_EVPARA Param)	/* Event dependent parameter */
-{
-	unsigned int	PhysPortIndex;
-    unsigned int	MaxNetNumber;
-	int			CounterIndex;
-	int			Ret;
-	SK_U16		MacStatus;
-	SK_U64		OverflowStatus;
-	SK_U64		Mask;
-	int			MacType;
-	SK_U64		Value;
-	SK_U32		Val32;
-	SK_U16		Register;
-	SK_EVPARA	EventParam;
-	SK_U64		NewestValue;
-	SK_U64		OldestValue;
-	SK_U64		Delta;
-	SK_PNMI_ESTIMATE *pEst;
-	SK_U32		NetIndex;
-	SK_GEPORT	*pPrt;
-	SK_PNMI_VCT	*pVctBackupData;
-	SK_U32		RetCode;
-	int		i;
-	SK_U32		CableLength;
-
-
-#ifdef DEBUG
-	if (Event != SK_PNMI_EVT_XMAC_RESET) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-			("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
-			(unsigned int)Event, (unsigned int)Param.Para64));
-	}
-#endif /* DEBUG */
-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
-
-	MacType = pAC->GIni.GIMacType;
-	
-	switch (Event) {
-
-	case SK_PNMI_EVT_SIRQ_OVERFLOW:
-		PhysPortIndex = (int)Param.Para32[0];
-		MacStatus = (SK_U16)Param.Para32[1];
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
-				 " wrong, PhysPortIndex=0x%x\n",
-				PhysPortIndex));
-			return (0);
-		}
-#endif /* DEBUG */
-		OverflowStatus = 0;
-
-		/*
-		 * Check which source caused an overflow interrupt.
-		 */
-		if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
-				MacStatus, &OverflowStatus) != 0) ||
-			(OverflowStatus == 0)) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-
-		/*
-		 * Check the overflow status register and increment
-		 * the upper dword of corresponding counter.
-		 */
-		for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
-			CounterIndex ++) {
-
-			Mask = (SK_U64)1 << CounterIndex;
-			if ((OverflowStatus & Mask) == 0) {
-
-				continue;
-			}
-
-			switch (StatOvrflwBit[CounterIndex][MacType]) {
-
-			case SK_PNMI_HTX_UTILUNDER:
-			case SK_PNMI_HTX_UTILOVER:
-				if (MacType == SK_MAC_XMAC) {
-					XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
-					Register |= XM_TX_SAM_LINE;
-					XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
-				}
-				break;
-
-			case SK_PNMI_HRX_UTILUNDER:
-			case SK_PNMI_HRX_UTILOVER:
-				if (MacType == SK_MAC_XMAC) {
-					XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
-					Register |= XM_RX_SAM_LINE;
-					XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
-				}
-				break;
-
-			case SK_PNMI_HTX_OCTETHIGH:
-			case SK_PNMI_HTX_OCTETLOW:
-			case SK_PNMI_HTX_RESERVED:
-			case SK_PNMI_HRX_OCTETHIGH:
-			case SK_PNMI_HRX_OCTETLOW:
-			case SK_PNMI_HRX_IRLENGTH:
-			case SK_PNMI_HRX_RESERVED:
-			
-			/*
-			 * the following counters aren't be handled (id > 63)
-			 */
-			case SK_PNMI_HTX_SYNC:
-			case SK_PNMI_HTX_SYNC_OCTET:
-				break;
-
-			case SK_PNMI_HRX_LONGFRAMES:
-				if (MacType == SK_MAC_GMAC) {
-					pAC->Pnmi.Port[PhysPortIndex].
-						CounterHigh[CounterIndex] ++;
-				}
-				break;
-
-			default:
-				pAC->Pnmi.Port[PhysPortIndex].
-					CounterHigh[CounterIndex] ++;
-			}
-		}
-		break;
-
-	case SK_PNMI_EVT_SEN_WAR_LOW:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_SEN_WAR_UPP:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_SEN_ERR_LOW:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-	
-	case SK_PNMI_EVT_SEN_ERR_UPP:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_CHG_EST_TIMER:
-		/*
-		 * Calculate port switch average on a per hour basis
-		 *   Time interval for check       : 28125 ms
-		 *   Number of values for average  : 8
-		 *
-		 * Be careful in changing these values, on change check
-		 *   - typedef of SK_PNMI_ESTIMATE (Size of EstValue
-		 *     array one less than value number)
-		 *   - Timer initialization SkTimerStart() in SkPnmiInit
-		 *   - Delta value below must be multiplicated with
-		 *     power of 2
-		 *
-		 */
-		pEst = &pAC->Pnmi.RlmtChangeEstimate;
-		CounterIndex = pEst->EstValueIndex + 1;
-		if (CounterIndex == 7) {
-
-			CounterIndex = 0;
-		}
-		pEst->EstValueIndex = CounterIndex;
-
-		NewestValue = pAC->Pnmi.RlmtChangeCts;
-		OldestValue = pEst->EstValue[CounterIndex];
-		pEst->EstValue[CounterIndex] = NewestValue;
-
-		/*
-		 * Calculate average. Delta stores the number of
-		 * port switches per 28125 * 8 = 225000 ms
-		 */
-		if (NewestValue >= OldestValue) {
-
-			Delta = NewestValue - OldestValue;
-		}
-		else {
-			/* Overflow situation */
-			Delta = (SK_U64)(0 - OldestValue) + NewestValue;
-		}
-
-		/*
-		 * Extrapolate delta to port switches per hour.
-		 *     Estimate = Delta * (3600000 / 225000)
-		 *              = Delta * 16
-		 *              = Delta << 4
-		 */
-		pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
-
-		/*
-		 * Check if threshold is exceeded. If the threshold is
-		 * permanently exceeded every 28125 ms an event will be
-		 * generated to remind the user of this condition.
-		 */
-		if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
-			(pAC->Pnmi.RlmtChangeEstimate.Estimate >=
-			pAC->Pnmi.RlmtChangeThreshold)) {
-
-			QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
-			(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		}
-
-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
-			EventParam);
-		break;
-
-	case SK_PNMI_EVT_CLEAR_COUNTER:
-		/*
-		 *  Param.Para32[0] contains the NetIndex (0 ..1).
-		 *  Param.Para32[1] is reserved, contains -1.
-		 */
-		NetIndex = (SK_U32)Param.Para32[0];
-
-#ifdef DEBUG
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
-				NetIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Set all counters and timestamps to zero.
-		 * The according NetIndex is required as a
-		 * parameter of the event.
-		 */
-		ResetCounter(pAC, IoC, NetIndex);
-		break;
-
-	case SK_PNMI_EVT_XMAC_RESET:
-		/*
-		 * To grant continuous counter values store the current
-		 * XMAC statistic values to the entries 1..n of the
-		 * CounterOffset array. XMAC Errata #2
-		 */
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif
-		PhysPortIndex = (unsigned int)Param.Para64;
-
-		/*
-		 * Update XMAC statistic to get fresh values
-		 */
-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-		if (Ret != SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		/*
-		 * Increment semaphore to indicate that an update was
-		 * already done
-		 */
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
-				GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-			
-			pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
-		}
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_PORT_UP:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/* Bugfix for XMAC errata (#10620)*/
-		if (MacType == SK_MAC_XMAC) {
-			/* Add incremental difference to offset (#10620)*/
-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
-				XM_RXE_SHT_ERR, &Val32);
-			
-			Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
-				Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
-		}
-		
-		/* Tell VctStatus() that a link was up meanwhile. */
-		pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;		
-		break;
-
-    case SK_PNMI_EVT_RLMT_PORT_DOWN:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/* Bugfix #10620 - get zero level for incremental difference */
-		if (MacType == SK_MAC_XMAC) {
-
-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
-				XM_RXE_SHT_ERR, &Val32);
-			
-			pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
-				(((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
-		}
-		break;
-
-	case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-		NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
-				PhysPortIndex));
-		}
-
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
-				NetIndex));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * For now, ignore event if NetIndex != 0.
-		 */
-		if (Param.Para32[1] != 0) {
-
-			return (0);
-		}
-
-		/*
-		 * Nothing to do if port is already inactive
-		 */
-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			return (0);
-		}
-
-		/*
-		 * Update statistic counters to calculate new offset for the virtual
-		 * port and increment semaphore to indicate that an update was already
-		 * done.
-		 */
-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
-			SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Calculate new counter offset for virtual port to grant continous
-		 * counting on port switches. The virtual port consists of all currently
-		 * active ports. The port down event indicates that a port is removed
-		 * from the virtual port. Therefore add the counter value of the removed
-		 * port to the CounterOffset for the virtual port to grant the same
-		 * counter value.
-		 */
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
-		}
-
-		/*
-		 * Set port to inactive
-		 */
-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_ACTIVE_UP:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-		NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
-				PhysPortIndex));
-		}
-
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
-				NetIndex));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * For now, ignore event if NetIndex != 0.
-		 */
-		if (Param.Para32[1] != 0) {
-
-			return (0);
-		}
-
-		/*
-		 * Nothing to do if port is already active
-		 */
-		if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			return (0);
-		}
-
-		/*
-		 * Statistic maintenance
-		 */
-		pAC->Pnmi.RlmtChangeCts ++;
-		pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtNewMacTrap(pAC, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/*
-		 * Update statistic counters to calculate new offset for the virtual
-		 * port and increment semaphore to indicate that an update was
-		 * already done.
-		 */
-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
-			SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Calculate new counter offset for virtual port to grant continous
-		 * counting on port switches. A new port is added to the virtual port.
-		 * Therefore substract the counter value of the new port from the
-		 * CounterOffset for the virtual port to grant the same value.
-		 */
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
-		}
-
-		/* Set port to active */
-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_SEGMENTATION:
-		/*
-		 * Para.Para32[0] contains the NetIndex.
-		 */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-    case SK_PNMI_EVT_RLMT_SET_NETS:
-		/*
-		 *  Param.Para32[0] contains the number of Nets.
-		 *  Param.Para32[1] is reserved, contains -1.
-		 */
-	    /*
-    	 * Check number of nets
-		 */
-		MaxNetNumber = pAC->GIni.GIMacsFound;
-		if (((unsigned int)Param.Para32[0] < 1)
-			|| ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
-			return (SK_PNMI_ERR_UNKNOWN_NET);
-		}
-
-        if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
-        	pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
-        }
-        else { /* dual net mode */
-        	pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
-        }
-        break;
-
-    case SK_PNMI_EVT_VCT_RESET:
-		PhysPortIndex = Param.Para32[0];
-		pPrt = &pAC->GIni.GP[PhysPortIndex];
-		pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-		
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
-			RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
-			if (RetCode == 2) {
-				/*
-				 * VCT test is still running.
-				 * Start VCT timer counter again.
-				 */
-				SK_MEMSET((char *) &Param, 0, sizeof(Param));
-				Param.Para32[0] = PhysPortIndex;
-				Param.Para32[1] = -1;
-				SkTimerStart(pAC, IoC,
-					&pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
-				4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
-				break;
-			}
-			pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
-			pAC->Pnmi.VctStatus[PhysPortIndex] |=
-				(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-			
-			/* Copy results for later use to PNMI struct. */
-			for (i = 0; i < 4; i++)  {
-				if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
-					if ((pPrt->PMdiPairLen[i] > 35) &&
-						(pPrt->PMdiPairLen[i] < 0xff)) {
-						pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
-					}
-				}
-				if ((pPrt->PMdiPairLen[i] > 35) &&
-					(pPrt->PMdiPairLen[i] != 0xff)) {
-					CableLength = 1000 *
-						(((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
-				}
-				else {
-					CableLength = 0;
-				}
-				pVctBackupData->PMdiPairLen[i] = CableLength;
-				pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
-			}
-			
-			Param.Para32[0] = PhysPortIndex;
-			Param.Para32[1] = -1;
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
-			SkEventDispatcher(pAC, IoC);
-		}
-		
-		break;
-
-	default:
-		break;
-	}
-
-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-	return (0);
-}
-
-
-/******************************************************************************
- *
- * Private functions
- *
- */
-
-/*****************************************************************************
- *
- * PnmiVar - Gets, presets, and sets single OIDs
- *
- * Description:
- *	Looks up the requested OID, calls the corresponding handler
- *	function, and passes the parameters with the get, preset, or
- *	set command. The function is called by SkGePnmiGetVar,
- *	SkGePnmiPreSetVar, or SkGePnmiSetVar.
- *
- * Returns:
- *	SK_PNMI_ERR_XXX. For details have a look at the description of the
- *	calling functions.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* Total length of pBuf management data  */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	TableIndex;
-	int		Ret;
-
-
-	if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_OID);
-	}
-	
-    /* Check NetIndex */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-
-	SK_PNMI_CHECKFLAGS("PnmiVar: On call");
-
-	Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
-		Instance, TableIndex, NetIndex);
-
-	SK_PNMI_CHECKFLAGS("PnmiVar: On return");
-
-	return (Ret);
-}
-
-/*****************************************************************************
- *
- * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
- *	checks which OIDs are able to set, and calls the handler function of
- *	the OID to perform the set. The return value of the function will
- *	also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
- *	by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
- *
- * Returns:
- *	SK_PNMI_ERR_XXX. The codes are described in the calling functions.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int  Action,	/* PRESET/SET action to be performed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* Length of pBuf management data buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	TableIndex;
-	unsigned int	DstOffset;
-	unsigned int	Len;
-	unsigned int	InstanceNo;
-	unsigned int	InstanceCnt;
-	SK_U32		Instance;
-	SK_U32		Id;
-
-
-	/* Check if the passed buffer has the right size */
-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
-		/* Check if we can return the error within the buffer */
-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
-				(SK_U32)(-1));
-		}
-
-		*pLen = SK_PNMI_STRUCT_SIZE;
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-	
-    /* Check NetIndex */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-	
-	SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
-
-	/*
-	 * Update the values of RLMT and SIRQ and increment semaphores to
-	 * indicate that an update was already done.
-	 */
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-	pAC->Pnmi.SirqUpdatedFlag ++;
-
-	/* Preset/Set values */
-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
-		if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
-			(IdTable[TableIndex].Access != SK_PNMI_WO)) {
-
-			continue;
-		}
-
-		InstanceNo = IdTable[TableIndex].InstanceNo;
-		Id = IdTable[TableIndex].Id;
-
-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
-			InstanceCnt ++) {
-
-			DstOffset = IdTable[TableIndex].Offset +
-				(InstanceCnt - 1) *
-				IdTable[TableIndex].StructSize;
-
-			/*
-			 * Because VPD multiple instance variables are
-			 * not setable we do not need to evaluate VPD
-			 * instances. Have a look to VPD instance
-			 * calculation in SkPnmiGetStruct().
-			 */
-			Instance = (SK_U32)InstanceCnt;
-
-			/*
-			 * Evaluate needed buffer length
-			 */
-			Len = 0;
-			Ret = IdTable[TableIndex].Func(pAC, IoC,
-				SK_PNMI_GET, IdTable[TableIndex].Id,
-				NULL, &Len, Instance, TableIndex, NetIndex);
-
-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
-				break;
-			}
-			if (Ret != SK_PNMI_ERR_TOO_SHORT) {
-
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-				SK_PNMI_SET_STAT(pBuf,
-					SK_PNMI_ERR_GENERAL, DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			if (Id == OID_SKGE_VPD_ACTION) {
-
-				switch (*(pBuf + DstOffset)) {
-
-				case SK_PNMI_VPD_CREATE:
-					Len = 3 + *(pBuf + DstOffset + 3);
-					break;
-
-				case SK_PNMI_VPD_DELETE:
-					Len = 3;
-					break;
-
-				default:
-					Len = 1;
-					break;
-				}
-			}
-
-			/* Call the OID handler function */
-			Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
-				IdTable[TableIndex].Id, pBuf + DstOffset,
-				&Len, Instance, TableIndex, NetIndex);
-
-			if (Ret != SK_PNMI_ERR_OK) {
-
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-				SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
-					DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-		}
-	}
-
-	pAC->Pnmi.RlmtUpdatedFlag --;
-	pAC->Pnmi.SirqUpdatedFlag --;
-
-	SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * LookupId - Lookup an OID in the IdTable
- *
- * Description:
- *	Scans the IdTable to find the table entry of an OID.
- *
- * Returns:
- *	The table index or -1 if not found.
- */
-PNMI_STATIC int LookupId(
-SK_U32 Id)		/* Object identifier to be searched */
-{
-	int i;
-
-	for (i = 0; i < ID_TABLE_SIZE; i++) {
-
-		if (IdTable[i].Id == Id) {
-
-			return i;
-		}
-	}
-
-	return (-1);
-}
-
-/*****************************************************************************
- *
- * OidStruct - Handler of OID_SKGE_ALL_DATA
- *
- * Description:
- *	This OID performs a Get/Preset/SetStruct call and returns all data
- *	in a SK_PNMI_STRUCT_DATA structure.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int OidStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	if (Id != OID_SKGE_ALL_DATA) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
-			SK_PNMI_ERR003MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	switch (Action) {
-
-	case SK_PNMI_GET:
-		return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
-	case SK_PNMI_PRESET:
-		return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
-	case SK_PNMI_SET:
-		return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-	}
-
-	SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
-
-	*pLen = 0;
-	return (SK_PNMI_ERR_GENERAL);
-}
-
-/*****************************************************************************
- *
- * Perform - OID handler of OID_SKGE_ACTION
- *
- * Description:
- *	None.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Perform(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int	Ret;
-	SK_U32	ActionOp;
-
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	if (*pLen < sizeof(SK_U32)) {
-
-		*pLen = sizeof(SK_U32);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/* Check if a get should be performed */
-	if (Action == SK_PNMI_GET) {
-
-		/* A get is easy. We always return the same value */
-		ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
-		SK_PNMI_STORE_U32(pBuf, ActionOp);
-		*pLen = sizeof(SK_U32);
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Continue with PRESET/SET action */
-	if (*pLen > sizeof(SK_U32)) {
-
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	/* Check if the command is a known one */
-	SK_PNMI_READ_U32(pBuf, ActionOp);
-	if (*pLen > sizeof(SK_U32) ||
-		(ActionOp != SK_PNMI_ACT_IDLE &&
-		ActionOp != SK_PNMI_ACT_RESET &&
-		ActionOp != SK_PNMI_ACT_SELFTEST &&
-		ActionOp != SK_PNMI_ACT_RESETCNT)) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	/* A preset ends here */
-	if (Action == SK_PNMI_PRESET) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	switch (ActionOp) {
-
-	case SK_PNMI_ACT_IDLE:
-		/* Nothing to do */
-		break;
-
-	case SK_PNMI_ACT_RESET:
-		/*
-		 * Perform a driver reset or something that comes near
-		 * to this.
-		 */
-		Ret = SK_DRIVER_RESET(pAC, IoC);
-		if (Ret != 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
-				SK_PNMI_ERR005MSG);
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		break;
-
-	case SK_PNMI_ACT_SELFTEST:
-		/*
-		 * Perform a driver selftest or something similar to this.
-		 * Currently this feature is not used and will probably
-		 * implemented in another way.
-		 */
-		Ret = SK_DRIVER_SELFTEST(pAC, IoC);
-		pAC->Pnmi.TestResult = Ret;
-		break;
-
-	case SK_PNMI_ACT_RESETCNT:
-		/* Set all counters and timestamps to zero */
-		ResetCounter(pAC, IoC, NetIndex);
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
-			SK_PNMI_ERR006MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
- *
- * Description:
- *	Retrieves the statistic values of the virtual port (logical
- *	index 0). Only special OIDs of NDIS are handled which consist
- *	of a 32 bit instead of a 64 bit value. The OIDs are public
- *	because perhaps some other platform can use them too.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Mac8023Stat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex,	/* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int     Ret;
-	SK_U64  StatVal;
-	SK_U32  StatVal32;
-	SK_BOOL Is64BitReq = SK_FALSE;
-
-	/*
-	 * Only the active Mac is returned
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check action type
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	switch (Id) {
-
-	case OID_802_3_PERMANENT_ADDRESS:
-	case OID_802_3_CURRENT_ADDRESS:
-		if (*pLen < sizeof(SK_MAC_ADDR)) {
-
-			*pLen = sizeof(SK_MAC_ADDR);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-#ifndef SK_NDIS_64BIT_CTR
-		if (*pLen < sizeof(SK_U32)) {
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-#else /* SK_NDIS_64BIT_CTR */
-
-		/* for compatibility, at least 32bit are required for OID */
-		if (*pLen < sizeof(SK_U32)) {
-			/*
-			* but indicate handling for 64bit values,
-			* if insufficient space is provided
-			*/
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
-		break;
-	}
-
-	/*
-	 * Update all statistics, because we retrieve virtual MAC, which
-	 * consists of multiple physical statistics and increment semaphore
-	 * to indicate that an update was already done.
-	 */
-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-	if ( Ret != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.MacUpdatedFlag ++;
-
-	/*
-	 * Get value (MAC Index 0 identifies the virtual MAC)
-	 */
-	switch (Id) {
-
-	case OID_802_3_PERMANENT_ADDRESS:
-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
-		*pLen = sizeof(SK_MAC_ADDR);
-		break;
-
-	case OID_802_3_CURRENT_ADDRESS:
-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
-		*pLen = sizeof(SK_MAC_ADDR);
-		break;
-
-	default:
-		StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
-
-		/* by default 32bit values are evaluated */
-		if (!Is64BitReq) {
-			StatVal32 = (SK_U32)StatVal;
-			SK_PNMI_STORE_U32(pBuf, StatVal32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, StatVal);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-	}
-
-	pAC->Pnmi.MacUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
- *
- * Description:
- *	Retrieves the MAC statistic data.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int MacPrivateStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	LogPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	PhysPortMax;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	int				MacType;
-	int				Ret;
-	SK_U64			StatVal;
-	
-	
-
-	/* Calculate instance if wished. MAC index 0 is the virtual MAC */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-	
-	MacType = pAC->GIni.GIMacType;
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/* Check action */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
-
-		*pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/*
-	 * Update MAC statistic and increment semaphore to indicate that
-	 * an update was already done.
-	 */
-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-	if (Ret != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.MacUpdatedFlag ++;
-
-	/* Get value */
-	Offset = 0;
-	for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-		switch (Id) {
-
-/* XXX not yet implemented due to XMAC problems
-		case OID_SKGE_STAT_TX_UTIL:
-			return (SK_PNMI_ERR_GENERAL);
-*/
-/* XXX not yet implemented due to XMAC problems
-		case OID_SKGE_STAT_RX_UTIL:
-			return (SK_PNMI_ERR_GENERAL);
-*/
-		case OID_SKGE_STAT_RX:
-			if (MacType == SK_MAC_GMAC) {
-				StatVal =
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_BROADCAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_MULTICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_UNICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_UNDERSIZE, NetIndex);
-			}
-			else {
-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-					IdTable[TableIndex].Param, NetIndex);
-			}
-			break;
-
-		case OID_SKGE_STAT_TX:
-			if (MacType == SK_MAC_GMAC) {
-				StatVal =
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_BROADCAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_MULTICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_UNICAST, NetIndex);
-			}
-			else {
-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-					IdTable[TableIndex].Param, NetIndex);
-			}
-			break;
-
-		default:
-			StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-				IdTable[TableIndex].Param, NetIndex);
-		}
-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-
-		Offset += sizeof(SK_U64);
-	}
-	*pLen = Offset;
-
-	pAC->Pnmi.MacUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
- *
- * Description:
- *	Get/Presets/Sets the current and factory MAC address. The MAC
- *	address of the virtual port, which is reported to the OS, may
- *	not be changed, but the physical ones. A set to the virtual port
- *	will be ignored. No error should be reported because otherwise
- *	a multiple instance set (-1) would always fail.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Addr(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	LogPortMax;
-	unsigned int	PhysPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	PhysPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset = 0;
-
-	/*
-	 * Calculate instance if wished. MAC index 0 is the virtual
-	 * MAC.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/*
-	 * Perform Action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/* Check length */
-		if (*pLen < (Limit - LogPortIndex) * 6) {
-
-			*pLen = (Limit - LogPortIndex) * 6;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		/*
-		 * Get value
-		 */
-		for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-			switch (Id) {
-
-			case OID_SKGE_PHYS_CUR_ADDR:
-				if (LogPortIndex == 0) {
-					CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
-				}
-				else {
-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
-				}
-				Offset += 6;
-				break;
-
-			case OID_SKGE_PHYS_FAC_ADDR:
-				if (LogPortIndex == 0) {
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Net[NetIndex].PermanentMacAddress);
-				}
-				else {
-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-						pAC, LogPortIndex);
-
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
-				}
-				Offset += 6;
-				break;
-
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
-					SK_PNMI_ERR008MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-
-		*pLen = Offset;
-	}
-	else {
-		/*
-		 * The logical MAC address may not be changed only
-		 * the physical ones
-		 */
-		if (Id == OID_SKGE_PHYS_FAC_ADDR) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-
-		/*
-		 * Only the current address may be changed
-		 */
-		if (Id != OID_SKGE_PHYS_CUR_ADDR) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
-				SK_PNMI_ERR009MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/* Check length */
-		if (*pLen < (Limit - LogPortIndex) * 6) {
-
-			*pLen = (Limit - LogPortIndex) * 6;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen > (Limit - LogPortIndex) * 6) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-
-		/*
-		 * Check Action
-		 */
-		if (Action == SK_PNMI_PRESET) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_OK);
-		}
-
-		/*
-		 * Set OID_SKGE_MAC_CUR_ADDR
-		 */
-		for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
-
-			/*
-			 * A set to virtual port and set of broadcast
-			 * address will be ignored
-			 */
-			if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
-				"\xff\xff\xff\xff\xff\xff", 6) == 0) {
-
-				continue;
-			}
-
-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
-				LogPortIndex);
-
-			Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
-				(SK_MAC_ADDR *)(pBuf + Offset),
-				(LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
-				SK_ADDR_PHYSICAL_ADDRESS));
-			if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
-
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
- *
- * Description:
- *	Retrieves the statistic values of the CSUM module. The CSUM data
- *	structure must be available in the SK_AC even if the CSUM module
- *	is not included, because PNMI reads the statistic data from the
- *	CSUM part of SK_AC directly.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int CsumStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset = 0;
-	SK_U64		StatVal;
-
-
-	/*
-	 * Calculate instance if wished
-	 */
-	if (Instance != (SK_U32)(-1)) {
-
-		if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		Index = (unsigned int)Instance - 1;
-		Limit = Index + 1;
-	}
-	else {
-		Index = 0;
-		Limit = SKCS_NUM_PROTOCOLS;
-	}
-
-	/*
-	 * Check action
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
-		*pLen = (Limit - Index) * sizeof(SK_U64);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/*
-	 * Get value
-	 */
-	for (; Index < Limit; Index ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_CHKSM_RX_OK_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
-			break;
-
-		case OID_SKGE_CHKSM_RX_UNABLE_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
-			break;
-
-		case OID_SKGE_CHKSM_RX_ERR_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
-			break;
-
-		case OID_SKGE_CHKSM_TX_OK_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
-			break;
-
-		case OID_SKGE_CHKSM_TX_UNABLE_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
-				SK_PNMI_ERR010MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-		Offset += sizeof(SK_U64);
-	}
-
-	/*
-	 * Store used buffer space
-	 */
-	*pLen = Offset;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
- *
- * Description:
- *	Retrieves the statistic values of the I2C module, which handles
- *	the temperature and voltage sensors.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int SensorStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	i;
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	unsigned int	Len;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-
-	/*
-	 * Calculate instance if wished
-	 */
-	if ((Instance != (SK_U32)(-1))) {
-
-		if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		Index = (unsigned int)Instance -1;
-		Limit = (unsigned int)Instance;
-	}
-	else {
-		Index = 0;
-		Limit = (unsigned int) pAC->I2c.MaxSens;
-	}
-
-	/*
-	 * Check action
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	switch (Id) {
-
-	case OID_SKGE_SENSOR_VALUE:
-	case OID_SKGE_SENSOR_WAR_THRES_LOW:
-	case OID_SKGE_SENSOR_WAR_THRES_UPP:
-	case OID_SKGE_SENSOR_ERR_THRES_LOW:
-	case OID_SKGE_SENSOR_ERR_THRES_UPP:
-		if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
-
-			*pLen = (Limit - Index) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_DESCR:
-		for (Offset = 0, i = Index; i < Limit; i ++) {
-
-			Len = (unsigned int)
-				SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
-			if (Len >= SK_PNMI_STRINGLEN2) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
-					SK_PNMI_ERR011MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			Offset += Len;
-		}
-		if (*pLen < Offset) {
-
-			*pLen = Offset;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_INDEX:
-	case OID_SKGE_SENSOR_TYPE:
-	case OID_SKGE_SENSOR_STATUS:
-		if (*pLen < Limit - Index) {
-
-			*pLen = Limit - Index;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_WAR_CTS:
-	case OID_SKGE_SENSOR_WAR_TIME:
-	case OID_SKGE_SENSOR_ERR_CTS:
-	case OID_SKGE_SENSOR_ERR_TIME:
-		if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
-			*pLen = (Limit - Index) * sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
-			SK_PNMI_ERR012MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-
-	}
-
-	/*
-	 * Get value
-	 */
-	for (Offset = 0; Index < Limit; Index ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_SENSOR_INDEX:
-			*(pBuf + Offset) = (char)Index;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_DESCR:
-			Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
-			SK_MEMCPY(pBuf + Offset + 1,
-				pAC->I2c.SenTable[Index].SenDesc, Len);
-			*(pBuf + Offset) = (char)Len;
-			Offset += Len + 1;
-			break;
-
-		case OID_SKGE_SENSOR_TYPE:
-			*(pBuf + Offset) =
-				(char)pAC->I2c.SenTable[Index].SenType;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_VALUE:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_THRES_LOW:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreWarnLow;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_THRES_UPP:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreWarnHigh;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_THRES_LOW:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreErrLow;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_THRES_UPP:
-			Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_STATUS:
-			*(pBuf + Offset) =
-				(char)pAC->I2c.SenTable[Index].SenErrFlag;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_CTS:
-			Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_CTS:
-			Val64 = pAC->I2c.SenTable[Index].SenErrCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_TIME:
-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
-				SenBegWarnTS);
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_TIME:
-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
-				SenBegErrTS);
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("SensorStat: Unknown OID should be handled before"));
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	/*
-	 * Store used buffer space
-	 */
-	*pLen = Offset;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Vpd - OID handler function of OID_SKGE_VPD_XXX
- *
- * Description:
- *	Get/preset/set of VPD data. As instance the name of a VPD key
- *	can be passed. The Instance parameter is a SK_U32 and can be
- *	used as a string buffer for the VPD key, because their maximum
- *	length is 4 byte.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Vpd(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_VPD_STATUS	*pVpdStatus;
-	unsigned int	BufLen;
-	char		Buf[256];
-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-	char		KeyStr[SK_PNMI_VPD_KEY_SIZE];
-	unsigned int	KeyNo;
-	unsigned int	Offset;
-	unsigned int	Index;
-	unsigned int	FirstIndex;
-	unsigned int	LastIndex;
-	unsigned int	Len;
-	int		Ret;
-	SK_U32		Val32;
-
-	/*
-	 * Get array of all currently stored VPD keys
-	 */
-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
-	if (Ret != SK_PNMI_ERR_OK) {
-		*pLen = 0;
-		return (Ret);
-	}
-
-	/*
-	 * If instance is not -1, try to find the requested VPD key for
-	 * the multiple instance variables. The other OIDs as for example
-	 * OID VPD_ACTION are single instance variables and must be
-	 * handled separatly.
-	 */
-	FirstIndex = 0;
-	LastIndex = KeyNo;
-
-	if ((Instance != (SK_U32)(-1))) {
-
-		if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
-			Id == OID_SKGE_VPD_ACCESS) {
-
-			SK_STRNCPY(KeyStr, (char *)&Instance, 4);
-			KeyStr[4] = 0;
-
-			for (Index = 0; Index < KeyNo; Index ++) {
-
-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-					FirstIndex = Index;
-					LastIndex = Index+1;
-					break;
-				}
-			}
-			if (Index == KeyNo) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_UNKNOWN_INST);
-			}
-		}
-		else if (Instance != 1) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-	}
-
-	/*
-	 * Get value, if a query should be performed
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		switch (Id) {
-
-		case OID_SKGE_VPD_FREE_BYTES:
-			/* Check length of buffer */
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Get number of free bytes */
-			pVpdStatus = VpdStat(pAC, IoC);
-			if (pVpdStatus == NULL) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
-					SK_PNMI_ERR017MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
-					SK_PNMI_ERR018MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			
-			Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_VPD_ENTRIES_LIST:
-			/* Check length */
-			for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
-
-				Len += SK_STRLEN(KeyArr[Index]) + 1;
-			}
-			if (*pLen < Len) {
-
-				*pLen = Len;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/* Get value */
-			*(pBuf) = (char)Len - 1;
-			for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
-
-				Len = SK_STRLEN(KeyArr[Index]);
-				SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
-
-				Offset += Len;
-
-				if (Index < KeyNo - 1) {
-
-					*(pBuf + Offset) = ' ';
-					Offset ++;
-				}
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ENTRIES_NUMBER:
-			/* Check length */
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			Val32 = (SK_U32)KeyNo;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_VPD_KEY:
-			/* Check buffer length, if it is large enough */
-			for (Len = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				Len += SK_STRLEN(KeyArr[Index]) + 1;
-			}
-			if (*pLen < Len) {
-
-				*pLen = Len;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/*
-			 * Get the key to an intermediate buffer, because
-			 * we have to prepend a length byte.
-			 */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				Len = SK_STRLEN(KeyArr[Index]);
-
-				*(pBuf + Offset) = (char)Len;
-				SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
-					Len);
-				Offset += Len + 1;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_VALUE:
-			/* Check the buffer length if it is large enough */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				BufLen = 256;
-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
-					(int *)&BufLen) > 0 ||
-					BufLen >= SK_PNMI_VPD_DATALEN) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR021,
-						SK_PNMI_ERR021MSG);
-
-					return (SK_PNMI_ERR_GENERAL);
-				}
-				Offset += BufLen + 1;
-			}
-			if (*pLen < Offset) {
-
-				*pLen = Offset;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/*
-			 * Get the value to an intermediate buffer, because
-			 * we have to prepend a length byte.
-			 */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				BufLen = 256;
-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
-					(int *)&BufLen) > 0 ||
-					BufLen >= SK_PNMI_VPD_DATALEN) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR022,
-						SK_PNMI_ERR022MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-
-				*(pBuf + Offset) = (char)BufLen;
-				SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
-				Offset += BufLen + 1;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ACCESS:
-			if (*pLen < LastIndex - FirstIndex) {
-
-				*pLen = LastIndex - FirstIndex;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				if (VpdMayWrite(KeyArr[Index])) {
-
-					*(pBuf + Offset) = SK_PNMI_VPD_RW;
-				}
-				else {
-					*(pBuf + Offset) = SK_PNMI_VPD_RO;
-				}
-				Offset ++;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ACTION:
-			Offset = LastIndex - FirstIndex;
-			if (*pLen < Offset) {
-
-				*pLen = Offset;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			SK_MEMSET(pBuf, 0, Offset);
-			*pLen = Offset;
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
-				SK_PNMI_ERR023MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-	else {
-		/* The only OID which can be set is VPD_ACTION */
-		if (Id != OID_SKGE_VPD_ACTION) {
-
-			if (Id == OID_SKGE_VPD_FREE_BYTES ||
-				Id == OID_SKGE_VPD_ENTRIES_LIST ||
-				Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
-				Id == OID_SKGE_VPD_KEY ||
-				Id == OID_SKGE_VPD_VALUE ||
-				Id == OID_SKGE_VPD_ACCESS) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_READ_ONLY);
-			}
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
-				SK_PNMI_ERR024MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * From this point we handle VPD_ACTION. Check the buffer
-		 * length. It should at least have the size of one byte.
-		 */
-		if (*pLen < 1) {
-
-			*pLen = 1;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		/*
-		 * The first byte contains the VPD action type we should
-		 * perform.
-		 */
-		switch (*pBuf) {
-
-		case SK_PNMI_VPD_IGNORE:
-			/* Nothing to do */
-			break;
-
-		case SK_PNMI_VPD_CREATE:
-			/*
-			 * We have to create a new VPD entry or we modify
-			 * an existing one. Check first the buffer length.
-			 */
-			if (*pLen < 4) {
-
-				*pLen = 4;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			KeyStr[0] = pBuf[1];
-			KeyStr[1] = pBuf[2];
-			KeyStr[2] = 0;
-
-			/*
-			 * Is the entry writable or does it belong to the
-			 * read-only area?
-			 */
-			if (!VpdMayWrite(KeyStr)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			Offset = (int)pBuf[3] & 0xFF;
-
-			SK_MEMCPY(Buf, pBuf + 4, Offset);
-			Buf[Offset] = 0;
-
-			/* A preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/* Write the new entry or modify an existing one */
-			Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
-			if (Ret == SK_PNMI_VPD_NOWRITE ) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			else if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
-					SK_PNMI_ERR025MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			/*
-			 * Perform an update of the VPD data. This is
-			 * not mandantory, but just to be sure.
-			 */
-			Ret = VpdUpdate(pAC, IoC);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
-					SK_PNMI_ERR026MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case SK_PNMI_VPD_DELETE:
-			/* Check if the buffer size is plausible */
-			if (*pLen < 3) {
-
-				*pLen = 3;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			if (*pLen > 3) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			KeyStr[0] = pBuf[1];
-			KeyStr[1] = pBuf[2];
-			KeyStr[2] = 0;
-
-			/* Find the passed key in the array */
-			for (Index = 0; Index < KeyNo; Index ++) {
-
-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-
-					break;
-				}
-			}
-			/*
-			 * If we cannot find the key it is wrong, so we
-			 * return an appropriate error value.
-			 */
-			if (Index == KeyNo) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/* Ok, you wanted it and you will get it */
-			Ret = VpdDelete(pAC, IoC, KeyStr);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
-					SK_PNMI_ERR027MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			/*
-			 * Perform an update of the VPD data. This is
-			 * not mandantory, but just to be sure.
-			 */
-			Ret = VpdUpdate(pAC, IoC);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
-					SK_PNMI_ERR028MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * General - OID handler function of various single instance OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int General(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	Index;
-	unsigned int	Len;
-	unsigned int	Offset;
-	unsigned int	Val;
-	SK_U8		Val8;
-	SK_U16		Val16;
-	SK_U32		Val32;
-	SK_U64		Val64;
-	SK_U64		Val64RxHwErrs = 0;
-	SK_U64		Val64TxHwErrs = 0;
-	SK_BOOL		Is64BitReq = SK_FALSE;
-	char		Buf[256];
-	int			MacType;
-
-	/*
-	 * Check instance. We only handle single instance variables.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check action. We only allow get requests.
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-	
-	MacType = pAC->GIni.GIMacType;
-	
-	/*
-	 * Check length for the various supported OIDs
-	 */
-	switch (Id) {
-
-	case OID_GEN_XMIT_ERROR:
-	case OID_GEN_RCV_ERROR:
-	case OID_GEN_RCV_NO_BUFFER:
-#ifndef SK_NDIS_64BIT_CTR
-		if (*pLen < sizeof(SK_U32)) {
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-#else /* SK_NDIS_64BIT_CTR */
-
-		/*
-		 * for compatibility, at least 32bit are required for oid
-		 */
-		if (*pLen < sizeof(SK_U32)) {
-			/*
-			* but indicate handling for 64bit values,
-			* if insufficient space is provided
-			*/
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
-		break;
-
-	case OID_SKGE_PORT_NUMBER:
-	case OID_SKGE_DEVICE_TYPE:
-	case OID_SKGE_RESULT:
-	case OID_SKGE_RLMT_MONITOR_NUMBER:
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-	case OID_SKGE_TRAP_NUMBER:
-	case OID_SKGE_MDB_VERSION:
-	case OID_SKGE_BOARDLEVEL:
-	case OID_SKGE_CHIPID:
-	case OID_SKGE_RAMSIZE:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_CHIPSET:
-		if (*pLen < sizeof(SK_U16)) {
-
-			*pLen = sizeof(SK_U16);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_BUS_TYPE:
-	case OID_SKGE_BUS_SPEED:
-	case OID_SKGE_BUS_WIDTH:
-	case OID_SKGE_SENSOR_NUMBER:
-	case OID_SKGE_CHKSM_NUMBER:
-	case OID_SKGE_VAUXAVAIL:
-		if (*pLen < sizeof(SK_U8)) {
-
-			*pLen = sizeof(SK_U8);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_TX_SW_QUEUE_LEN:
-	case OID_SKGE_TX_SW_QUEUE_MAX:
-	case OID_SKGE_TX_RETRY:
-	case OID_SKGE_RX_INTR_CTS:
-	case OID_SKGE_TX_INTR_CTS:
-	case OID_SKGE_RX_NO_BUF_CTS:
-	case OID_SKGE_TX_NO_BUF_CTS:
-	case OID_SKGE_TX_USED_DESCR_NO:
-	case OID_SKGE_RX_DELIVERED_CTS:
-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
-	case OID_SKGE_RX_HW_ERROR_CTS:
-	case OID_SKGE_TX_HW_ERROR_CTS:
-	case OID_SKGE_IN_ERRORS_CTS:
-	case OID_SKGE_OUT_ERROR_CTS:
-	case OID_SKGE_ERR_RECOVERY_CTS:
-	case OID_SKGE_SYSUPTIME:
-		if (*pLen < sizeof(SK_U64)) {
-
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		/* Checked later */
-		break;
-	}
-
-	/* Update statistic */
-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
-		Id == OID_SKGE_IN_ERRORS_CTS ||
-		Id == OID_SKGE_OUT_ERROR_CTS ||
-		Id == OID_GEN_XMIT_ERROR ||
-		Id == OID_GEN_RCV_ERROR) {
-
-		/* Force the XMAC to update its statistic counters and
-		 * Increment semaphore to indicate that an update was
-		 * already done.
-		 */
-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-		if (Ret != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Some OIDs consist of multiple hardware counters. Those
-		 * values which are contained in all of them will be added
-		 * now.
-		 */
-		switch (Id) {
-
-		case OID_SKGE_RX_HW_ERROR_CTS:
-		case OID_SKGE_IN_ERRORS_CTS:
-		case OID_GEN_RCV_ERROR:
-			Val64RxHwErrs =
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
-	        break;
-
-		case OID_SKGE_TX_HW_ERROR_CTS:
-		case OID_SKGE_OUT_ERROR_CTS:
-		case OID_GEN_XMIT_ERROR:
-			Val64TxHwErrs =
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
-			break;
-		}
-	}
-
-	/*
-	 * Retrieve value
-	 */
-	switch (Id) {
-
-	case OID_SKGE_SUPPORTED_LIST:
-		Len = ID_TABLE_SIZE * sizeof(SK_U32);
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		for (Offset = 0, Index = 0; Offset < Len;
-			Offset += sizeof(SK_U32), Index ++) {
-
-			Val32 = (SK_U32)IdTable[Index].Id;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-		}
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_BOARDLEVEL:
-		Val32 = (SK_U32)pAC->GIni.GILevel;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_PORT_NUMBER:
-		Val32 = (SK_U32)pAC->GIni.GIMacsFound;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_DEVICE_TYPE:
-		Val32 = (SK_U32)pAC->Pnmi.DeviceType;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_DRIVER_DESCR:
-		if (pAC->Pnmi.pDriverDescription == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
-				SK_PNMI_ERR007MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
-				SK_PNMI_ERR029MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_VERSION:
-		if (pAC->Pnmi.pDriverVersion == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR030MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR031MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_RELDATE:
-		if (pAC->Pnmi.pDriverReleaseDate == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR053MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR054MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_FILENAME:
-		if (pAC->Pnmi.pDriverFileName == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR055MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR056MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_HW_DESCR:
-		/*
-		 * The hardware description is located in the VPD. This
-		 * query may move to the initialisation routine. But
-		 * the VPD data is cached and therefore a call here
-		 * will not make much difference.
-		 */
-		Len = 256;
-		if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
-				SK_PNMI_ERR032MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		Len ++;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
-				SK_PNMI_ERR033MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, Buf, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_HW_VERSION:
-		/* Oh, I love to do some string manipulation */
-		if (*pLen < 5) {
-
-			*pLen = 5;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
-		pBuf[0] = 4;
-		pBuf[1] = 'v';
-		pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
-		pBuf[3] = '.';
-		pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
-		*pLen = 5;
-		break;
-
-	case OID_SKGE_CHIPSET:
-		Val16 = pAC->Pnmi.Chipset;
-		SK_PNMI_STORE_U16(pBuf, Val16);
-		*pLen = sizeof(SK_U16);
-		break;
-
-	case OID_SKGE_CHIPID:
-		Val32 = pAC->GIni.GIChipId;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_RAMSIZE:
-		Val32 = pAC->GIni.GIRamSize;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_VAUXAVAIL:
-		*pBuf = (char) pAC->GIni.GIVauxAvail;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_TYPE:
-		*pBuf = (char) SK_PNMI_BUS_PCI;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_SPEED:
-		*pBuf = pAC->Pnmi.PciBusSpeed;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_WIDTH:
-		*pBuf = pAC->Pnmi.PciBusWidth;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_RESULT:
-		Val32 = pAC->Pnmi.TestResult;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_SENSOR_NUMBER:
-		*pBuf = (char)pAC->I2c.MaxSens;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_CHKSM_NUMBER:
-		*pBuf = SKCS_NUM_PROTOCOLS;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_TRAP_NUMBER:
-		GetTrapQueueLen(pAC, &Len, &Val);
-		Val32 = (SK_U32)Val;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_TRAP:
-		GetTrapQueueLen(pAC, &Len, &Val);
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		CopyTrapQueue(pAC, pBuf);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_RLMT_MONITOR_NUMBER:
-/* XXX Not yet implemented by RLMT therefore we return zero elements */
-		Val32 = 0;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_TX_SW_QUEUE_LEN:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
-					pAC->Pnmi.BufPort[1].TxSwQueueLen;
-			}			
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
-					pAC->Pnmi.Port[1].TxSwQueueLen;
-			}			
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-
-	case OID_SKGE_TX_SW_QUEUE_MAX:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
-					pAC->Pnmi.BufPort[1].TxSwQueueMax;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
-					pAC->Pnmi.Port[1].TxSwQueueMax;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_RETRY:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
-					pAC->Pnmi.BufPort[1].TxRetryCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxRetryCts +
-					pAC->Pnmi.Port[1].TxRetryCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_INTR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
-					pAC->Pnmi.BufPort[1].RxIntrCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxIntrCts +
-					pAC->Pnmi.Port[1].RxIntrCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_INTR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
-					pAC->Pnmi.BufPort[1].TxIntrCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxIntrCts +
-					pAC->Pnmi.Port[1].TxIntrCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_NO_BUF_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
-					pAC->Pnmi.BufPort[1].RxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
-					pAC->Pnmi.Port[1].RxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_NO_BUF_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
-					pAC->Pnmi.BufPort[1].TxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
-					pAC->Pnmi.Port[1].TxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_USED_DESCR_NO:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
-					pAC->Pnmi.BufPort[1].TxUsedDescrNo;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
-					pAC->Pnmi.Port[1].TxUsedDescrNo;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_DELIVERED_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
-					pAC->Pnmi.BufPort[1].RxDeliveredCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
-					pAC->Pnmi.Port[1].RxDeliveredCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
-					pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
-					pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_HW_ERROR_CTS:
-		SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_HW_ERROR_CTS:
-		SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_IN_ERRORS_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64RxHwErrs +
-					pAC->Pnmi.BufPort[0].RxNoBufCts +
-					pAC->Pnmi.BufPort[1].RxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64RxHwErrs +
-					pAC->Pnmi.Port[0].RxNoBufCts +
-					pAC->Pnmi.Port[1].RxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_OUT_ERROR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64TxHwErrs +
-					pAC->Pnmi.BufPort[0].TxNoBufCts +
-					pAC->Pnmi.BufPort[1].TxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64TxHwErrs +
-					pAC->Pnmi.Port[0].TxNoBufCts +
-					pAC->Pnmi.Port[1].TxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_ERR_RECOVERY_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
-					pAC->Pnmi.BufPort[1].ErrRecoveryCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
-					pAC->Pnmi.Port[1].ErrRecoveryCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_SYSUPTIME:
-		Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-		Val64 -= pAC->Pnmi.StartUpTime;
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_MDB_VERSION:
-		Val32 = SK_PNMI_MDB_VERSION;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_GEN_RCV_ERROR:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-		}
-		else {
-			Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_XMIT_ERROR:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-		}
-		else {
-			Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_RCV_NO_BUFFER:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-		}
-		else {
-			Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-		Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
-			SK_PNMI_ERR034MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
-		Id == OID_SKGE_IN_ERRORS_CTS ||
-		Id == OID_SKGE_OUT_ERROR_CTS ||
-		Id == OID_GEN_XMIT_ERROR ||
-		Id == OID_GEN_RCV_ERROR) {
-
-		pAC->Pnmi.MacUpdatedFlag --;
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
- *
- * Description:
- *	Get/Presets/Sets the RLMT OIDs.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Rlmt(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	PhysPortIndex;
-	unsigned int	PhysPortMax;
-	SK_EVPARA	EventParam;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-
-	/*
-	 * Check instance. Only single instance OIDs are allowed here.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Perform the requested action.
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/*
-		 * Check if the buffer length is large enough.
-		 */
-
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-		case OID_SKGE_RLMT_PORT_ACTIVE:
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			if (*pLen < sizeof(SK_U8)) {
-
-				*pLen = sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		case OID_SKGE_RLMT_PORT_NUMBER:
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_CTS:
-		case OID_SKGE_RLMT_CHANGE_TIME:
-		case OID_SKGE_RLMT_CHANGE_ESTIM:
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			if (*pLen < sizeof(SK_U64)) {
-
-				*pLen = sizeof(SK_U64);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
-				SK_PNMI_ERR035MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * Update RLMT statistic and increment semaphores to indicate
-		 * that an update was already done. Maybe RLMT will hold its
-		 * statistic always up to date some time. Then we can
-		 * remove this type of call.
-		 */
-		if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.RlmtUpdatedFlag ++;
-
-		/*
-		 * Retrieve Value
-		*/
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-			*pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_PORT_NUMBER:
-			Val32 = (SK_U32)pAC->GIni.GIMacsFound;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_PORT_ACTIVE:
-			*pBuf = 0;
-			/*
-			 * If multiple ports may become active this OID
-			 * doesn't make sense any more. A new variable in
-			 * the port structure should be created. However,
-			 * for this variable the first active port is
-			 * returned.
-			 */
-			PhysPortMax = pAC->GIni.GIMacsFound;
-
-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-				PhysPortIndex ++) {
-
-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-					*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
-					break;
-				}
-			}
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_CTS:
-			Val64 = pAC->Pnmi.RlmtChangeCts;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_TIME:
-			Val64 = pAC->Pnmi.RlmtChangeTime;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_ESTIM:
-			Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			Val64 = pAC->Pnmi.RlmtChangeThreshold;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("Rlmt: Unknown OID should be handled before"));
-
-			pAC->Pnmi.RlmtUpdatedFlag --;
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		pAC->Pnmi.RlmtUpdatedFlag --;
-	}
-	else {
-		/* Perform a preset or set */
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(char)) {
-
-				*pLen = sizeof(char);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Check if the value range is correct */
-			if (*pLen != sizeof(char) ||
-				(*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
-				*(SK_U8 *)pBuf > 15) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-			/* Send an event to RLMT to change the mode */
-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-			EventParam.Para32[0] |= (SK_U32)(*pBuf);
-			EventParam.Para32[1] = 0;
-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
-				EventParam) > 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
-					SK_PNMI_ERR037MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(char)) {
-
-				*pLen = sizeof(char);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Check if the value range is correct */
-			if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
-				(SK_U8)pAC->GIni.GIMacsFound) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/*
-			 * Send an event to RLMT change the preferred port.
-			 * A param of -1 means automatic mode. RLMT will
-			 * make the decision which is the preferred port.
-			 */
-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-			EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
-			EventParam.Para32[1] = NetIndex;
-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
-				EventParam) > 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
-					SK_PNMI_ERR038MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(SK_U64)) {
-
-				*pLen = sizeof(SK_U64);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/*
-			 * There are not many restrictions to the
-			 * value range.
-			 */
-			if (*pLen != sizeof(SK_U64)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* A preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-			/*
-			 * Store the new threshold, which will be taken
-			 * on the next timer event.
-			 */
-			SK_PNMI_READ_U64(pBuf, Val64);
-			pAC->Pnmi.RlmtChangeThreshold = Val64;
-			break;
-
-		default:
-			/* The other OIDs are not be able for set */
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
- *
- * Description:
- *	Performs get requests on multiple instance variables.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int RlmtStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	int		Ret;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-	/*
-	 * Calculate the port indexes from the instance.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-
-	if ((Instance != (SK_U32)(-1))) {
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > PhysPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		/* Single net mode */
-		PhysPortIndex = Instance - 1;
-
-		/* Dual net mode */
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-		}
-
-		/* Both net modes */
-		Limit = PhysPortIndex + 1;
-	}
-	else {
-		/* Single net mode */
-		PhysPortIndex = 0;
-		Limit = PhysPortMax;
-
-		/* Dual net mode */
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-			Limit = PhysPortIndex + 1;
-		}
-	}
-
-	/*
-	 * Currently only get requests are allowed.
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/*
-	 * Check if the buffer length is large enough.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_RLMT_PORT_INDEX:
-	case OID_SKGE_RLMT_STATUS:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_RLMT_TX_HELLO_CTS:
-	case OID_SKGE_RLMT_RX_HELLO_CTS:
-	case OID_SKGE_RLMT_TX_SP_REQ_CTS:
-	case OID_SKGE_RLMT_RX_SP_CTS:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
-
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
-			SK_PNMI_ERR039MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-
-	}
-
-	/*
-	 * Update statistic and increment semaphores to indicate that
-	 * an update was already done.
-	 */
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-
-	/*
-	 * Get value
-	 */
-	Offset = 0;
-	for (; PhysPortIndex < Limit; PhysPortIndex ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_RLMT_PORT_INDEX:
-			Val32 = PhysPortIndex;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_STATUS:
-			if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
-				SK_RLMT_PS_INIT ||
-				pAC->Rlmt.Port[PhysPortIndex].PortState ==
-				SK_RLMT_PS_DOWN) {
-
-				Val32 = SK_PNMI_RLMT_STATUS_ERROR;
-			}
-			else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-				Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
-			}
-			else {
-				Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
-			}
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_TX_HELLO_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_RX_HELLO_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_TX_SP_REQ_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_RX_SP_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("RlmtStat: Unknown OID should be errored before"));
-
-			pAC->Pnmi.RlmtUpdatedFlag --;
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-	*pLen = Offset;
-
-	pAC->Pnmi.RlmtUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateConf - OID handler function of OIDs concerning the configuration
- *
- * Description:
- *	Get/Presets/Sets the OIDs concerning the configuration.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int MacPrivateConf(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	unsigned int	LogPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	char		Val8;
-	char 		*pBufPtr;
-	int			Ret;
-	SK_EVPARA	EventParam;
-	SK_U32		Val32;
-
-	/*
-	 * Calculate instance if wished. MAC index 0 is the virtual MAC.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/*
-	 * Perform action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/* Check length */
-		switch (Id) {
-
-		case OID_SKGE_PMD:
-		case OID_SKGE_CONNECTOR:
-		case OID_SKGE_LINK_CAP:
-		case OID_SKGE_LINK_MODE:
-		case OID_SKGE_LINK_MODE_STATUS:
-		case OID_SKGE_LINK_STATUS:
-		case OID_SKGE_FLOWCTRL_CAP:
-		case OID_SKGE_FLOWCTRL_MODE:
-		case OID_SKGE_FLOWCTRL_STATUS:
-		case OID_SKGE_PHY_OPERATION_CAP:
-		case OID_SKGE_PHY_OPERATION_MODE:
-		case OID_SKGE_PHY_OPERATION_STATUS:
-		case OID_SKGE_SPEED_CAP:
-		case OID_SKGE_SPEED_MODE:
-		case OID_SKGE_SPEED_STATUS:
-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
-
-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-        case OID_SKGE_MTU:
-        case OID_SKGE_PHY_TYPE:
-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
-
-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
-				SK_PNMI_ERR041MSG);
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * Update statistic and increment semaphore to indicate
-		 * that an update was already done.
-		 */
-		if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.SirqUpdatedFlag ++;
-
-		/*
-		 * Get value
-		 */
-		Offset = 0;
-		for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-			pBufPtr = pBuf + Offset;
-			
-			switch (Id) {
-
-			case OID_SKGE_PMD:
-				*pBufPtr = pAC->Pnmi.PMD;
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_CONNECTOR:
-				*pBufPtr = pAC->Pnmi.Connector;
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_TYPE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						continue;
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-						Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
-						SK_PNMI_STORE_U32(pBufPtr, Val32);
-					}
-				}
-				else { /* DualNetMode */
-					
-					Val32 = pAC->GIni.GP[NetIndex].PhyType;
-					SK_PNMI_STORE_U32(pBufPtr, Val32);
-				}
-				Offset += sizeof(SK_U32);
-				break;
-
-			case OID_SKGE_LINK_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
-					}
-				}
-				else { /* DualNetMode */
-					
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_MODE_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr =
-							CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-					}
-				}
-				else { /* DualNetMode */
-					
-					*pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
-					}
-				}
-				else {
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
-				}
-				Offset += sizeof(char);
-				break;
-			
-			case OID_SKGE_MTU:
-				Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
-				SK_PNMI_STORE_U32(pBufPtr, Val32);
-				Offset += sizeof(SK_U32);
-				break;
-
-			default:
-				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-					("MacPrivateConf: Unknown OID should be handled before"));
-
-				pAC->Pnmi.SirqUpdatedFlag --;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-		pAC->Pnmi.SirqUpdatedFlag --;
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/*
-	 * From here SET or PRESET action. Check if the passed
-	 * buffer length is plausible.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_LINK_MODE:
-	case OID_SKGE_FLOWCTRL_MODE:
-	case OID_SKGE_PHY_OPERATION_MODE:
-	case OID_SKGE_SPEED_MODE:
-		if (*pLen < Limit - LogPortIndex) {
-
-			*pLen = Limit - LogPortIndex;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen != Limit - LogPortIndex) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-		break;
-
-	case OID_SKGE_MTU:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen != sizeof(SK_U32)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-		break;
-
-    default:
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/*
-	 * Perform preset or set
-	 */
-	Offset = 0;
-	for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_LINK_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_LMODE_HALF ||
-				(LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
-				(LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new link mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_LMODE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR043,
-							SK_PNMI_ERR043MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new link mode to
-				 * the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
-					EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR043,
-						SK_PNMI_ERR043MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_FLOWCTRL_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_FLOW_MODE_NONE ||
-				(LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
-				(LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new flow control mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_FLOWMODE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR044,
-							SK_PNMI_ERR044MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new flow control
-				 * mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_FLOWMODE, EventParam)
-					> 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR044,
-						SK_PNMI_ERR044MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE :
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-				/* mode of this port remains unchanged */
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_MS_MODE_AUTO ||
-				(LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
-				(LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with new master/slave (role) mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_ROLE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR042,
-							SK_PNMI_ERR042MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new master/slave
-				 * (role) mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_ROLE, EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR042,
-						SK_PNMI_ERR042MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SPEED_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < (SK_LSPEED_AUTO) ||
-				(LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
-				(LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new flow control mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_SPEED,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR045,
-							SK_PNMI_ERR045MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new flow control
-				 * mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_SPEED,
-					EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR045,
-						SK_PNMI_ERR045MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_MTU :
-			/* Check the value range */
-			Val32 = *(SK_U32*)(pBuf + Offset);
-			if (Val32 == 0) {
-				/* mtu of this port remains unchanged */
-				Offset += sizeof(SK_U32);
-				break;
-			}
-			if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			Offset += sizeof(SK_U32);
-			break;
-		
-		default:
-            SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-                ("MacPrivateConf: Unknown OID should be handled before set"));
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Monitor - OID handler function for RLMT_MONITOR_XXX
- *
- * Description:
- *	Because RLMT currently does not support the monitoring of
- *	remote adapter cards, we return always an empty table.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Monitor(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	unsigned int	Entries;
-
-	
-	/*
-	 * Calculate instance if wished.
-	 */
-	/* XXX Not yet implemented. Return always an empty table. */
-	Entries = 0;
-
-	if ((Instance != (SK_U32)(-1))) {
-
-		if ((Instance < 1) || (Instance > Entries)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		Index = (unsigned int)Instance - 1;
-		Limit = (unsigned int)Instance;
-	}
-	else {
-		Index = 0;
-		Limit = Entries;
-	}
-
-	/*
-	 * Get/Set value
-	*/
-	if (Action == SK_PNMI_GET) {
-
-		for (Offset=0; Index < Limit; Index ++) {
-
-			switch (Id) {
-
-			case OID_SKGE_RLMT_MONITOR_INDEX:
-			case OID_SKGE_RLMT_MONITOR_ADDR:
-			case OID_SKGE_RLMT_MONITOR_ERRS:
-			case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
-			case OID_SKGE_RLMT_MONITOR_ADMIN:
-				break;
-
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
-					SK_PNMI_ERR046MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-	}
-	else {
-		/* Only MONITOR_ADMIN can be set */
-		if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-
-		/* Check if the length is plausible */
-		if (*pLen < (Limit - Index)) {
-
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		/* Okay, we have a wide value range */
-		if (*pLen != (Limit - Index)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-/*
-		for (Offset=0; Index < Limit; Index ++) {
-		}
-*/
-/*
- * XXX Not yet implemented. Return always BAD_VALUE, because the table
- * is empty.
- */
-		*pLen = 0;
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * VirtualConf - Calculates the values of configuration OIDs for virtual port
- *
- * Description:
- *	We handle here the get of the configuration group OIDs, which are
- *	a little bit complicated. The virtual port consists of all currently
- *	active physical ports. If multiple ports are active and configured
- *	differently we get in some trouble to return a single value. So we
- *	get the value of the first active port and compare it with that of
- *	the other active ports. If they are not the same, we return a value
- *	that indicates that the state is indeterminated.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void VirtualConf(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf)		/* Buffer used for the management data transfer */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	SK_U8		Val8;
-	SK_U32		Val32;
-	SK_BOOL		PortActiveFlag;
-	SK_GEPORT	*pPrt;
-
-	*pBuf = 0;
-	PortActiveFlag = SK_FALSE;
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	
-	for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-		PhysPortIndex ++) {
-
-		pPrt = &pAC->GIni.GP[PhysPortIndex];
-
-		/* Check if the physical port is active */
-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			continue;
-		}
-
-		PortActiveFlag = SK_TRUE;
-
-		switch (Id) {
-
-		case OID_SKGE_PHY_TYPE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-				Val32 = pPrt->PhyType;
-				SK_PNMI_STORE_U32(pBuf, Val32);
-				continue;
-			}
-
-		case OID_SKGE_LINK_CAP:
-
-			/*
-			 * Different capabilities should not happen, but
-			 * in the case of the cases OR them all together.
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PLinkCap;
-			break;
-
-		case OID_SKGE_LINK_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkModeConf;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * mode than the first one we return a value that
-			 * indicates that the link mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkModeConf) {
-
-				*pBuf = SK_LMODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_LINK_MODE_STATUS:
-			/* Get the link mode of the physical port */
-			Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = Val8;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * mode status than the first one we return a value
-			 * that indicates that the link mode status is
-			 * indeterminated.
-			 */
-			if (*pBuf != Val8) {
-
-				*pBuf = SK_LMODE_STAT_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_LINK_STATUS:
-			/* Get the link status of the physical port */
-			Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = Val8;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * status than the first one, we return a value
-			 * that indicates that the link status is
-			 * indeterminated.
-			 */
-			if (*pBuf != Val8) {
-
-				*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_FLOWCTRL_CAP:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlCap;
-				continue;
-			}
-
-			/*
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PFlowCtrlCap;
-			break;
-
-		case OID_SKGE_FLOWCTRL_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlMode;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PFlowCtrlMode) {
-
-				*pBuf = SK_FLOW_MODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_FLOWCTRL_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlStatus;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PFlowCtrlStatus) {
-
-				*pBuf = SK_FLOW_STAT_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_PHY_OPERATION_CAP:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSCap;
-				continue;
-			}
-
-			/*
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PMSCap;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSMode;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different master/
-			 * slave mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PMSMode) {
-
-				*pBuf = SK_MS_MODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_PHY_OPERATION_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSStatus;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different master/
-			 * slave status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PMSStatus) {
-
-				*pBuf = SK_MS_STAT_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_SPEED_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkSpeed;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkSpeed) {
-
-				*pBuf = SK_LSPEED_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_SPEED_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkSpeedUsed;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkSpeedUsed) {
-
-				*pBuf = SK_LSPEED_STAT_INDETERMINATED;
-			}
-			break;
-		}
-	}
-
-	/*
-	 * If no port is active return an indeterminated answer
-	 */
-	if (!PortActiveFlag) {
-
-		switch (Id) {
-
-		case OID_SKGE_LINK_CAP:
-			*pBuf = SK_LMODE_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_MODE:
-			*pBuf = SK_LMODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_MODE_STATUS:
-			*pBuf = SK_LMODE_STAT_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_STATUS:
-			*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
-			break;
-
-		case OID_SKGE_FLOWCTRL_CAP:
-		case OID_SKGE_FLOWCTRL_MODE:
-			*pBuf = SK_FLOW_MODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_FLOWCTRL_STATUS:
-			*pBuf = SK_FLOW_STAT_INDETERMINATED;
-			break;
-			
-		case OID_SKGE_PHY_OPERATION_CAP:
-			*pBuf = SK_MS_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE:
-			*pBuf = SK_MS_MODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_STATUS:
-			*pBuf = SK_MS_STAT_INDETERMINATED;
-			break;
-		case OID_SKGE_SPEED_CAP:
-			*pBuf = SK_LSPEED_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_SPEED_MODE:
-			*pBuf = SK_LSPEED_INDETERMINATED;
-			break;
-
-		case OID_SKGE_SPEED_STATUS:
-			*pBuf = SK_LSPEED_STAT_INDETERMINATED;
-			break;
-		}
-	}
-}
-
-/*****************************************************************************
- *
- * CalculateLinkStatus - Determins the link status of a physical port
- *
- * Description:
- *	Determins the link status the following way:
- *	  LSTAT_PHY_DOWN:  Link is down
- *	  LSTAT_AUTONEG:   Auto-negotiation failed
- *	  LSTAT_LOG_DOWN:  Link is up but RLMT did not yet put the port
- *	                   logically up.
- *	  LSTAT_LOG_UP:    RLMT marked the port as up
- *
- * Returns:
- *	Link status of physical port
- */
-PNMI_STATIC SK_U8 CalculateLinkStatus(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_IOC IoC,			/* IO context handle */
-unsigned int PhysPortIndex)	/* Physical port index */
-{
-	SK_U8	Result;
-
-	if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
-
-		Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
-	}
-	else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
-
-		Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
-				}
-	else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
-
-		Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
-	}
-	else {
-		Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
-	}
-
-	return (Result);
-}
-
-/*****************************************************************************
- *
- * CalculateLinkModeStatus - Determins the link mode status of a phys. port
- *
- * Description:
- *	The COMMON module only tells us if the mode is half or full duplex.
- *	But in the decade of auto sensing it is useful for the user to
- *	know if the mode was negotiated or forced. Therefore we have a
- *	look to the mode, which was last used by the negotiation process.
- *
- * Returns:
- *	The link mode status
- */
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_IOC IoC,			/* IO context handle */
-unsigned int PhysPortIndex)	/* Physical port index */
-{
-	SK_U8	Result;
-
-	/* Get the current mode, which can be full or half duplex */
-	Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
-
-	/* Check if no valid mode could be found (link is down) */
-	if (Result < SK_LMODE_STAT_HALF) {
-
-		Result = SK_LMODE_STAT_UNKNOWN;
-	}
-	else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
-
-		/*
-		 * Auto-negotiation was used to bring up the link. Change
-		 * the already found duplex status that it indicates
-		 * auto-negotiation was involved.
-		 */
-		if (Result == SK_LMODE_STAT_HALF) {
-
-			Result = SK_LMODE_STAT_AUTOHALF;
-		}
-		else if (Result == SK_LMODE_STAT_FULL) {
-
-			Result = SK_LMODE_STAT_AUTOFULL;
-		}
-	}
-
-	return (Result);
-}
-
-/*****************************************************************************
- *
- * GetVpdKeyArr - Obtain an array of VPD keys
- *
- * Description:
- *	Read the VPD keys and build an array of VPD keys, which are
- *	easy to access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int GetVpdKeyArr(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-char *pKeyArr,		/* Ptr KeyArray */
-unsigned int KeyArrLen,	/* Length of array in bytes */
-unsigned int *pKeyNo)	/* Number of keys */
-{
-	unsigned int		BufKeysLen = SK_PNMI_VPD_BUFSIZE;
-	char			BufKeys[SK_PNMI_VPD_BUFSIZE];
-	unsigned int		StartOffset;
-	unsigned int		Offset;
-	int			Index;
-	int			Ret;
-
-
-	SK_MEMSET(pKeyArr, 0, KeyArrLen);
-
-	/*
-	 * Get VPD key list
-	 */
-	Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
-		(int *)pKeyNo);
-	if (Ret > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
-			SK_PNMI_ERR014MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	/* If no keys are available return now */
-	if (*pKeyNo == 0 || BufKeysLen == 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-	/*
-	 * If the key list is too long for us trunc it and give a
-	 * errorlog notification. This case should not happen because
-	 * the maximum number of keys is limited due to RAM limitations
-	 */
-	if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
-			SK_PNMI_ERR015MSG);
-
-		*pKeyNo = SK_PNMI_VPD_ENTRIES;
-	}
-
-	/*
-	 * Now build an array of fixed string length size and copy
-	 * the keys together.
-	 */
-	for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
-		Offset ++) {
-
-		if (BufKeys[Offset] != 0) {
-
-			continue;
-		}
-
-		if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
-				SK_PNMI_ERR016MSG);
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-
-		Index ++;
-		StartOffset = Offset + 1;
-	}
-
-	/* Last key not zero terminated? Get it anyway */
-	if (StartOffset < Offset) {
-
-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SirqUpdate - Let the SIRQ update its internal values
- *
- * Description:
- *	Just to be sure that the SIRQ module holds its internal data
- *	structures up to date, we send an update event before we make
- *	any access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int SirqUpdate(
-SK_AC *pAC,	/* Pointer to adapter context */
-SK_IOC IoC)	/* IO context handle */
-{
-	SK_EVPARA	EventParam;
-
-
-	/* Was the module already updated during the current PNMI call? */
-	if (pAC->Pnmi.SirqUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an synchronuous update event to the module */
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-	if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
-			SK_PNMI_ERR047MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtUpdate - Let the RLMT update its internal values
- *
- * Description:
- *	Just to be sure that the RLMT module holds its internal data
- *	structures up to date, we send an update event before we make
- *	any access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int RlmtUpdate(
-SK_AC *pAC,	/* Pointer to adapter context */
-SK_IOC IoC,	/* IO context handle */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	SK_EVPARA	EventParam;
-
-
-	/* Was the module already updated during the current PNMI call? */
-	if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an synchronuous update event to the module */
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
-			SK_PNMI_ERR048MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacUpdate - Force the XMAC to output the current statistic
- *
- * Description:
- *	The XMAC holds its statistic internally. To obtain the current
- *	values we must send a command so that the statistic data will
- *	be written to a predefined memory area on the adapter.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int MacUpdate(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-unsigned int FirstMac,	/* Index of the first Mac to be updated */
-unsigned int LastMac)	/* Index of the last Mac to be updated */
-{
-	unsigned int	MacIndex;
-
-	/*
-	 * Were the statistics already updated during the
-	 * current PNMI call?
-	 */
-	if (pAC->Pnmi.MacUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an update command to all MACs specified */
-	for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
-
-		/*
-		 * 2002-09-13 pweber:	Freeze the current SW counters.
-		 *                      (That should be done as close as
-		 *                      possible to the update of the
-		 *                      HW counters)
-		 */
-		if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
-			pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
-		}
-			
-		/* 2002-09-13 pweber:  Update the HW counter  */
-		if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * GetStatVal - Retrieve an XMAC statistic counter
- *
- * Description:
- *	Retrieves the statistic counter of a virtual or physical port. The
- *	virtual port is identified by the index 0. It consists of all
- *	currently active ports. To obtain the counter value for this port
- *	we must add the statistic counter of all active ports. To grant
- *	continuous counter values for the virtual port even when port
- *	switches occur we must additionally add a delta value, which was
- *	calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
- *
- * Returns:
- *	Requested statistic value
- */
-PNMI_STATIC SK_U64 GetStatVal(
-SK_AC *pAC,					/* Pointer to adapter context */
-SK_IOC IoC,					/* IO context handle */
-unsigned int LogPortIndex,	/* Index of the logical Port to be processed */
-unsigned int StatIndex,		/* Index to statistic value */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	unsigned int	PhysPortIndex;
-	unsigned int	PhysPortMax;
-	SK_U64			Val = 0;
-
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {	/* Dual net mode */
-
-		PhysPortIndex = NetIndex;
-		
-		Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-	}
-	else {	/* Single Net mode */
-
-		if (LogPortIndex == 0) {
-
-			PhysPortMax = pAC->GIni.GIMacsFound;
-
-			/* Add counter of all active ports */
-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-				PhysPortIndex ++) {
-
-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-					Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-				}
-			}
-
-			/* Correct value because of port switches */
-			Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
-		}
-		else {
-			/* Get counter value of physical port */
-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-			
-			Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-		}
-	}
-	return (Val);
-}
-
-/*****************************************************************************
- *
- * GetPhysStatVal - Get counter value for physical port
- *
- * Description:
- *	Builds a 64bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	in software by monitoring counter overflow interrupts in the
- *	event handler. To grant continous counter values during XMAC
- *	resets (caused by a workaround) we must add a delta value.
- *	The delta was calculated in the event handler when a
- *	SK_PNMI_EVT_XMAC_RESET was received.
- *
- * Returns:
- *	Counter value
- */
-PNMI_STATIC SK_U64 GetPhysStatVal(
-SK_AC *pAC,					/* Pointer to adapter context */
-SK_IOC IoC,					/* IO context handle */
-unsigned int PhysPortIndex,	/* Index of the logical Port to be processed */
-unsigned int StatIndex)		/* Index to statistic value */
-{
-	SK_U64	Val = 0;
-	SK_U32	LowVal = 0;
-	SK_U32	HighVal = 0;
-	SK_U16	Word;
-	int		MacType;
-	unsigned int HelpIndex;
-	SK_GEPORT	*pPrt;
-	
-	SK_PNMI_PORT	*pPnmiPrt;
-	SK_GEMACFUNC	*pFnMac;
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	
-	MacType = pAC->GIni.GIMacType;
-	
-	/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-	if (MacType == SK_MAC_XMAC) {
-		pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
-	}
-	else {
-		pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
-	}
-	
-	pFnMac   = &pAC->GIni.GIFunc;
-
-	switch (StatIndex) {
-	case SK_PNMI_HTX:
-		if (MacType == SK_MAC_GMAC) {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
-							&LowVal);
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-		}
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-	
-	case SK_PNMI_HRX:
-		if (MacType == SK_MAC_GMAC) {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
-							&LowVal);
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-		}
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_OCTET:
-	case SK_PNMI_HRX_OCTET:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &HighVal);
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex + 1][MacType].Reg,
-									  &LowVal);
-		break;
-
-	case SK_PNMI_HTX_BURST:
-	case SK_PNMI_HTX_EXCESS_DEF:
-	case SK_PNMI_HTX_CARRIER:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_MACC:
-		/* GMAC only supports PAUSE MAC control frames */
-		if (MacType == SK_MAC_GMAC) {
-			HelpIndex = SK_PNMI_HTX_PMACC;
-		}
-		else {
-			HelpIndex = StatIndex;
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-								StatAddr[HelpIndex][MacType].Reg,
-								&LowVal);
-
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_COL:
-	case SK_PNMI_HRX_UNDERSIZE:
-		/* Not supported by XMAC */
-		if (MacType == SK_MAC_XMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_DEFFERAL:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-		
-		/*
-		 * XMAC counts frames with deferred transmission
-		 * even in full-duplex mode.
-		 *
-		 * In full-duplex mode the counter remains constant!
-		 */
-		if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
-
-			LowVal = 0;
-			HighVal = 0;
-		}
-		else {
-			/* Otherwise get contents of hardware register */
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		break;
-
-	case SK_PNMI_HRX_BADOCTET:
-		/* Not supported by XMAC */
-		if (MacType == SK_MAC_XMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &HighVal);
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex + 1][MacType].Reg,
-                                      &LowVal);
-		break;
-
-	case SK_PNMI_HTX_OCTETLOW:
-	case SK_PNMI_HRX_OCTETLOW:
-	case SK_PNMI_HRX_BADOCTETLOW:
-		return (Val);
-
-	case SK_PNMI_HRX_LONGFRAMES:
-		/* For XMAC the SW counter is managed by PNMI */
-		if (MacType == SK_MAC_XMAC) {
-			return (pPnmiPrt->StatRxLongFrameCts);
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-		
-	case SK_PNMI_HRX_TOO_LONG:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-								StatAddr[StatIndex][MacType].Reg,
-								&LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		
-		Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
-		if (MacType == SK_MAC_GMAC) {
-			/* For GMAC the SW counter is additionally managed by PNMI */
-			Val += pPnmiPrt->StatRxFrameTooLongCts;
-		}
-		else {
-			/*
-			 * Frames longer than IEEE 802.3 frame max size are counted
-			 * by XMAC in frame_too_long counter even reception of long
-			 * frames was enabled and the frame was correct.
-			 * So correct the value by subtracting RxLongFrame counter.
-			 */
-			Val -= pPnmiPrt->StatRxLongFrameCts;
-		}
-
-		LowVal = (SK_U32)Val;
-		HighVal = (SK_U32)(Val >> 32);
-		break;
-		
-	case SK_PNMI_HRX_SHORTS:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			/* GM_RXE_FRAG?? */
-			return (Val);
-		}
-		
-		/*
-		 * XMAC counts short frame errors even if link down (#10620)
-		 *
-		 * If link-down the counter remains constant
-		 */
-		if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
-
-			/* Otherwise get incremental difference */
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-
-			Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-			Val -= pPnmiPrt->RxShortZeroMark;
-
-			LowVal = (SK_U32)Val;
-			HighVal = (SK_U32)(Val >> 32);
-		}
-		break;
-
-	case SK_PNMI_HRX_MACC:
-	case SK_PNMI_HRX_MACC_UNKWN:
-	case SK_PNMI_HRX_BURST:
-	case SK_PNMI_HRX_MISSED:
-	case SK_PNMI_HRX_FRAMING:
-	case SK_PNMI_HRX_CARRIER:
-	case SK_PNMI_HRX_IRLENGTH:
-	case SK_PNMI_HRX_SYMBOL:
-	case SK_PNMI_HRX_CEXT:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HRX_PMACC_ERR:
-		/* For GMAC the SW counter is managed by PNMI */
-		if (MacType == SK_MAC_GMAC) {
-			return (pPnmiPrt->StatRxPMaccErr);
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	/* SW counter managed by PNMI */
-	case SK_PNMI_HTX_SYNC:
-		LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
-		HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
-		break;
-
-	/* SW counter managed by PNMI */
-	case SK_PNMI_HTX_SYNC_OCTET:
-		LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
-		HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
-		break;
-
-	case SK_PNMI_HRX_FCS:
-		/*
-		 * Broadcom filters FCS errors and counts it in
-		 * Receive Error Counter register
-		 */
-		if (pPrt->PhyType == SK_PHY_BCOM) {
-			/* do not read while not initialized (PHY_READ hangs!)*/
-			if (pPrt->PState != SK_PRT_RESET) {
-				SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
-				
-				LowVal = Word;
-			}
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		break;
-
-	default:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-	}
-
-	Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
-	/* Correct value because of possible XMAC reset. XMAC Errata #2 */
-	Val += pPnmiPrt->CounterOffset[StatIndex];
-
-	return (Val);
-}
-
-/*****************************************************************************
- *
- * ResetCounter - Set all counters and timestamps to zero
- *
- * Description:
- *	Notifies other common modules which store statistic data to
- *	reset their counters and finally reset our own counters.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void ResetCounter(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 NetIndex)
-{
-	unsigned int	PhysPortIndex;
-	SK_EVPARA	EventParam;
-
-
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-
-	/* Notify sensor module */
-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
-
-	/* Notify RLMT module */
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
-	EventParam.Para32[1] = 0;
-
-	/* Notify SIRQ module */
-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
-
-	/* Notify CSUM module */
-#ifdef SK_USE_CSUM
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
-		EventParam);
-#endif /* SK_USE_CSUM */
-	
-	/* Clear XMAC statistic */
-	for (PhysPortIndex = 0; PhysPortIndex <
-		(unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
-
-		(void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
-
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			CounterOffset, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].CounterOffset));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatSyncOctetsCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxLongFrameCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-				  StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxFrameTooLongCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-				  StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxPMaccErr));
-	}
-
-	/*
-	 * Clear local statistics
-	 */
-	SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
-		  sizeof(pAC->Pnmi.VirtualCounterOffset));
-	pAC->Pnmi.RlmtChangeCts = 0;
-	pAC->Pnmi.RlmtChangeTime = 0;
-	SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
-		sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
-	pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
-	pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
-	pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
-	pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
-	pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
-	pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
-}
-
-/*****************************************************************************
- *
- * GetTrapEntry - Get an entry in the trap buffer
- *
- * Description:
- *	The trap buffer stores various events. A user application somehow
- *	gets notified that an event occured and retrieves the trap buffer
- *	contens (or simply polls the buffer). The buffer is organized as
- *	a ring which stores the newest traps at the beginning. The oldest
- *	traps are overwritten by the newest ones. Each trap entry has a
- *	unique number, so that applications may detect new trap entries.
- *
- * Returns:
- *	A pointer to the trap entry
- */
-PNMI_STATIC char* GetTrapEntry(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId,		/* SNMP ID of the trap */
-unsigned int Size)	/* Space needed for trap entry */
-{
-	unsigned int		BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int		BufFree = pAC->Pnmi.TrapBufFree;
-	unsigned int		Beg = pAC->Pnmi.TrapQueueBeg;
-	unsigned int		End = pAC->Pnmi.TrapQueueEnd;
-	char			*pBuf = &pAC->Pnmi.TrapBuf[0];
-	int			Wrap;
-	unsigned int		NeededSpace;
-	unsigned int		EntrySize;
-	SK_U32			Val32;
-	SK_U64			Val64;
-
-
-	/* Last byte of entry will get a copy of the entry length */
-	Size ++;
-
-	/*
-	 * Calculate needed buffer space */
-	if (Beg >= Size) {
-
-		NeededSpace = Size;
-		Wrap = SK_FALSE;
-	}
-	else {
-		NeededSpace = Beg + Size;
-		Wrap = SK_TRUE;
-	}
-
-	/*
-	 * Check if enough buffer space is provided. Otherwise
-	 * free some entries. Leave one byte space between begin
-	 * and end of buffer to make it possible to detect whether
-	 * the buffer is full or empty
-	 */
-	while (BufFree < NeededSpace + 1) {
-
-		if (End == 0) {
-
-			End = SK_PNMI_TRAP_QUEUE_LEN;
-		}
-
-		EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
-		BufFree += EntrySize;
-		End -= EntrySize;
-#ifdef DEBUG
-		SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
-#endif /* DEBUG */
-		if (End == BufPad) {
-#ifdef DEBUG
-			SK_MEMSET(pBuf, (char)(-1), End);
-#endif /* DEBUG */
-			BufFree += End;
-			End = 0;
-			BufPad = 0;
-		}
-	}
-
-	/*
-	 * Insert new entry as first entry. Newest entries are
-	 * stored at the beginning of the queue.
-	 */
-	if (Wrap) {
-
-		BufPad = Beg;
-		Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
-	}
-	else {
-		Beg = Beg - Size;
-	}
-	BufFree -= NeededSpace;
-
-	/* Save the current offsets */
-	pAC->Pnmi.TrapQueueBeg = Beg;
-	pAC->Pnmi.TrapQueueEnd = End;
-	pAC->Pnmi.TrapBufPad = BufPad;
-	pAC->Pnmi.TrapBufFree = BufFree;
-
-	/* Initialize the trap entry */
-	*(pBuf + Beg + Size - 1) = (char)Size;
-	*(pBuf + Beg) = (char)Size;
-	Val32 = (pAC->Pnmi.TrapUnique) ++;
-	SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
-	SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
-	Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-	SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
-
-	return (pBuf + Beg);
-}
-
-/*****************************************************************************
- *
- * CopyTrapQueue - Copies the trap buffer for the TRAP OID
- *
- * Description:
- *	On a query of the TRAP OID the trap buffer contents will be
- *	copied continuously to the request buffer, which must be large
- *	enough. No length check is performed.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void CopyTrapQueue(
-SK_AC *pAC,		/* Pointer to adapter context */
-char *pDstBuf)		/* Buffer to which the queued traps will be copied */
-{
-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
-	unsigned int	Len;
-	unsigned int	DstOff = 0;
-
-
-	while (Trap != End) {
-
-		Len = (unsigned int)*(pBuf + Trap);
-
-		/*
-		 * Last byte containing a copy of the length will
-		 * not be copied.
-		 */
-		*(pDstBuf + DstOff) = (char)(Len - 1);
-		SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
-		DstOff += Len - 1;
-
-		Trap += Len;
-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
-			Trap = BufPad;
-		}
-	}
-}
-
-/*****************************************************************************
- *
- * GetTrapQueueLen - Get the length of the trap buffer
- *
- * Description:
- *	Evaluates the number of currently stored traps and the needed
- *	buffer size to retrieve them.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void GetTrapQueueLen(
-SK_AC *pAC,		/* Pointer to adapter context */
-unsigned int *pLen,	/* Length in Bytes of all queued traps */
-unsigned int *pEntries)	/* Returns number of trapes stored in queue */
-{
-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
-	unsigned int	Len;
-	unsigned int	Entries = 0;
-	unsigned int	TotalLen = 0;
-
-
-	while (Trap != End) {
-
-		Len = (unsigned int)*(pBuf + Trap);
-		TotalLen += Len - 1;
-		Entries ++;
-
-		Trap += Len;
-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
-			Trap = BufPad;
-		}
-	}
-
-	*pEntries = Entries;
-	*pLen = TotalLen;
-}
-
-/*****************************************************************************
- *
- * QueueSimpleTrap - Store a simple trap to the trap buffer
- *
- * Description:
- *	A simple trap is a trap with now additional data. It consists
- *	simply of a trap code.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueSimpleTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId)		/* Type of sensor trap */
-{
-	GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
-}
-
-/*****************************************************************************
- *
- * QueueSensorTrap - Stores a sensor trap in the trap buffer
- *
- * Description:
- *	Gets an entry in the trap buffer and fills it with sensor related
- *	data.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueSensorTrap(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_U32 TrapId,			/* Type of sensor trap */
-unsigned int SensorIndex)	/* Index of sensor which caused the trap */
-{
-	char		*pBuf;
-	unsigned int	Offset;
-	unsigned int	DescrLen;
-	SK_U32		Val32;
-
-
-	/* Get trap buffer entry */
-	DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
-	pBuf = GetTrapEntry(pAC, TrapId,
-		SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
-	Offset = SK_PNMI_TRAP_SIMPLE_LEN;
-
-	/* Store additionally sensor trap related data */
-	Val32 = OID_SKGE_SENSOR_INDEX;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 4;
-	Val32 = (SK_U32)SensorIndex;
-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-	Offset += 9;
-	
-	Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = (char)DescrLen;
-	SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
-		DescrLen);
-	Offset += DescrLen + 5;
-
-	Val32 = OID_SKGE_SENSOR_TYPE;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 1;
-	*(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
-	Offset += 6;
-
-	Val32 = OID_SKGE_SENSOR_VALUE;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 4;
-	Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-}
-
-/*****************************************************************************
- *
- * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueRlmtNewMacTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-unsigned int ActiveMac)	/* Index (0..n) of the currently active port */
-{
-	char	*pBuf;
-	SK_U32	Val32;
-
-
-	pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
-		SK_PNMI_TRAP_RLMT_CHANGE_LEN);
-
-	Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
-}
-
-/*****************************************************************************
- *
- * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueRlmtPortTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId,		/* Type of RLMT port trap */
-unsigned int PortIndex)	/* Index of the port, which changed its state */
-{
-	char	*pBuf;
-	SK_U32	Val32;
-
-
-	pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
-
-	Val32 = OID_SKGE_RLMT_PORT_INDEX;
-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
-}
-
-/*****************************************************************************
- *
- * CopyMac - Copies a MAC address
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void CopyMac(
-char *pDst,		/* Pointer to destination buffer */
-SK_MAC_ADDR *pMac)	/* Pointer of Source */
-{
-	int	i;
-
-
-	for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
-
-		*(pDst + i) = pMac->a[i];
-	}
-}
-
-#ifdef SK_POWER_MGMT
-/*****************************************************************************
- *
- * PowerManagement - OID handler function of PowerManagement OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                               exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-
-PNMI_STATIC int PowerManagement(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* Get/PreSet/Set action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	
-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-	
-    
-    /* Check length */
-    switch (Id) {
-
-    case OID_PNP_CAPABILITIES:
-        if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
-
-            *pLen = sizeof(SK_PNP_CAPABILITIES);
-            return (SK_PNMI_ERR_TOO_SHORT);
-        }
-        break;
-
-	case OID_PNP_SET_POWER:
-    case OID_PNP_QUERY_POWER:
-    	if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
-    	{
-    		*pLen = sizeof(SK_DEVICE_POWER_STATE);
-    		return (SK_PNMI_ERR_TOO_SHORT);
-    	}
-        break;
-
-    case OID_PNP_ADD_WAKE_UP_PATTERN:
-    case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-		if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
-
-			*pLen = sizeof(SK_PM_PACKET_PATTERN);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-    case OID_PNP_ENABLE_WAKE_UP:
-        if (*pLen < sizeof(SK_U32)) {
-
-            *pLen = sizeof(SK_U32);
-            return (SK_PNMI_ERR_TOO_SHORT);
-        }
-        break;
-    }
-	
-    /*
-	 * Perform action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/*
-		 * Get value
-		 */
-		switch (Id) {
-
-		case OID_PNP_CAPABILITIES:
-			RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
-			break;
-
-		case OID_PNP_QUERY_POWER:
-			/* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
-			 the miniport to indicate whether it can transition its NIC
-			 to the low-power state.
-			 A miniport driver must always return NDIS_STATUS_SUCCESS
-			 to a query of OID_PNP_QUERY_POWER. */
-			*pLen = sizeof(SK_DEVICE_POWER_STATE);
-            RetCode = SK_PNMI_ERR_OK;
-			break;
-
-			/* NDIS handles these OIDs as write-only.
-			 * So in case of get action the buffer with written length = 0
-			 * is returned
-			 */
-		case OID_PNP_SET_POWER:
-		case OID_PNP_ADD_WAKE_UP_PATTERN:
-		case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-			*pLen = 0;	
-            RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
-			break;
-
-		case OID_PNP_ENABLE_WAKE_UP:
-			RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
-			break;
-
-		default:
-			RetCode = SK_PNMI_ERR_GENERAL;
-			break;
-		}
-
-		return (RetCode);
-	}
-	
-
-	/*
-	 * Perform preset or set
-	 */
-	
-	/* POWER module does not support PRESET action */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK);
-	}
-
-	switch (Id) {
-	case OID_PNP_SET_POWER:
-		RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);	
-		break;
-
-	case OID_PNP_ADD_WAKE_UP_PATTERN:
-		RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);	
-		break;
-		
-	case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-		RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);	
-		break;
-		
-	case OID_PNP_ENABLE_WAKE_UP:
-		RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
-		break;
-		
-	default:
-		RetCode = SK_PNMI_ERR_READ_ONLY;
-	}
-	
-	return (RetCode);
-}
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-/*****************************************************************************
- *
- * DiagActions - OID handler function of Diagnostic driver 
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-
-PNMI_STATIC int DiagActions(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-
-	SK_U32	DiagStatus;
-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
-
-	/*
-	 * Check instance. We only handle single instance variables.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check length.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_DIAG_MODE:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/* Perform action. */
-
-	/* GET value. */
-	if (Action == SK_PNMI_GET) {
-
-		switch (Id) {
-
-		case OID_SKGE_DIAG_MODE:
-			DiagStatus = pAC->Pnmi.DiagAttached;
-			SK_PNMI_STORE_U32(pBuf, DiagStatus);
-			*pLen = sizeof(SK_U32);	
-			RetCode = SK_PNMI_ERR_OK;
-			break;
-
-		default:
-			*pLen = 0;	
-			RetCode = SK_PNMI_ERR_GENERAL;
-			break;
-		}
-		return (RetCode); 
-	}
-
-	/* From here SET or PRESET value. */
-	
-	/* PRESET value is not supported. */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK); 
-	}
-
-	/* SET value. */
-	switch (Id) {
-		case OID_SKGE_DIAG_MODE:
-
-			/* Handle the SET. */
-			switch (*pBuf) {
-
-				/* Attach the DIAG to this adapter. */
-				case SK_DIAG_ATTACHED:
-					/* Check if we come from running */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
-						RetCode = SkDrvLeaveDiagMode(pAC);
-
-					}
-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
-
-						RetCode = SK_PNMI_ERR_OK;
-					}	
-					
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-
-					}
-					
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
-					}
-					break;
-
-				/* Enter the DIAG mode in the driver. */
-				case SK_DIAG_RUNNING:
-					RetCode = SK_PNMI_ERR_OK;
-					
-					/*
-					 * If DiagAttached is set, we can tell the driver
-					 * to enter the DIAG mode.
-					 */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-						/* If DiagMode is not active, we can enter it. */
-						if (!pAC->DiagModeActive) {
-
-							RetCode = SkDrvEnterDiagMode(pAC); 
-						}
-						else {
-
-							RetCode = SK_PNMI_ERR_GENERAL;
-						}
-					}
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-					}
-					
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
-					}
-					break;
-
-				case SK_DIAG_IDLE:
-					/* Check if we come from running */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
-						RetCode = SkDrvLeaveDiagMode(pAC);
-
-					}
-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-
-						RetCode = SK_PNMI_ERR_OK;
-					}	
-					
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-
-					}
-
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
-					}
-					break;
-
-				default:
-					RetCode = SK_PNMI_ERR_BAD_VALUE;
-					break;
-			}
-			break;
-
-		default:
-			RetCode = SK_PNMI_ERR_GENERAL;
-	}
-
-	if (RetCode == SK_PNMI_ERR_OK) {
-		*pLen = sizeof(SK_U32);
-	}
-	else {
-
-		*pLen = 0;
-	}
-	return (RetCode);
-}
-#endif /* SK_DIAG_SUPPORT */
-
-/*****************************************************************************
- *
- * Vct - OID handler function of  OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was performed successfully.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter).
- *	SK_PNMI_ERR_READ_ONLY	 Only the Get action is allowed.
- *
- */
-
-PNMI_STATIC int Vct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (-1,2..n) that is to be queried */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_GEPORT	*pPrt;
-	SK_PNMI_VCT	*pVctBackupData;
-	SK_U32		LogPortMax;
-	SK_U32		PhysPortMax;
-	SK_U32		PhysPortIndex;
-	SK_U32		Limit;
-	SK_U32		Offset;
-	SK_BOOL		Link;
-	SK_U32		RetCode = SK_PNMI_ERR_GENERAL;
-	int		i;
-	SK_EVPARA	Para;
-	SK_U32		CableLength;
-	
-	/*
-	 * Calculate the port indexes from the instance.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-	
-	/* Dual net mode? */
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-		LogPortMax--;
-	}
-	
-	if ((Instance != (SK_U32) (-1))) {
-		/* Check instance range. */
-		if ((Instance < 2) || (Instance > LogPortMax)) {
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-		}
-		else {
-			PhysPortIndex = Instance - 2;
-		}
-		Limit = PhysPortIndex + 1;
-	}
-	else {
-		/*
-		 * Instance == (SK_U32) (-1), get all Instances of that OID.
-		 *
-		 * Not implemented yet. May be used in future releases.
-		 */
-		PhysPortIndex = 0;
-		Limit = PhysPortMax;
-	}
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	if (pPrt->PHWLinkUp) {
-		Link = SK_TRUE;
-	}
-	else {
-		Link = SK_FALSE;
-	}
-	
-	/* Check MAC type */
-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	
-	/* Initialize backup data pointer. */
-	pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-	
-	/* Check action type */
-	if (Action == SK_PNMI_GET) {
-		/* Check length */
-		switch (Id) {
-		
-		case OID_SKGE_VCT_GET:
-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-		
-		case OID_SKGE_VCT_STATUS:
-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-		
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}	
-		
-		/* Get value */
-		Offset = 0;
-		for (; PhysPortIndex < Limit; PhysPortIndex++) {
-			switch (Id) {
-			
-			case OID_SKGE_VCT_GET:
-				if ((Link == SK_FALSE) &&
-					(pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
-					RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
-					if (RetCode == 0) {
-						pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
-						pAC->Pnmi.VctStatus[PhysPortIndex] |=
-							(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-						
-						/* Copy results for later use to PNMI struct. */
-						for (i = 0; i < 4; i++)  {
-							if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
-								if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
-									pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
-								}
-							}
-							if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
-								CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
-							}
-							else {
-								CableLength = 0;
-							}
-							pVctBackupData->PMdiPairLen[i] = CableLength;
-							pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
-						}
-
-						Para.Para32[0] = PhysPortIndex;
-						Para.Para32[1] = -1;
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-						SkEventDispatcher(pAC, IoC);
-					}
-					else {
-						; /* VCT test is running. */
-					}
-				}
-				
-				/* Get all results. */
-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
-				Offset += sizeof(SK_U8);
-				*(pBuf + Offset) = pPrt->PCableLen;
-				Offset += sizeof(SK_U8);
-				for (i = 0; i < 4; i++)  {
-					SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
-					Offset += sizeof(SK_U32);
-				}
-				for (i = 0; i < 4; i++)  {
-					*(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
-					Offset += sizeof(SK_U8);
-				}
-				
-				RetCode = SK_PNMI_ERR_OK;
-				break;
-		
-			case OID_SKGE_VCT_STATUS:
-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
-				Offset += sizeof(SK_U8);
-				RetCode = SK_PNMI_ERR_OK;
-				break;
-			
-			default:
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		} /* for */
-		*pLen = Offset;
-		return (RetCode);
-	
-	} /* if SK_PNMI_GET */
-	
-	/*
-	 * From here SET or PRESET action. Check if the passed
-	 * buffer length is plausible.
-	 */
-	
-	/* Check length */
-	switch (Id) {
-	case OID_SKGE_VCT_SET:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-	
-	default:
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	
-	/*
-	 * Perform preset or set.
-	 */
-	
-	/* VCT does not support PRESET action. */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK);
-	}
-	
-	Offset = 0;
-	for (; PhysPortIndex < Limit; PhysPortIndex++) {
-		switch (Id) {
-		case OID_SKGE_VCT_SET: /* Start VCT test. */
-			if (Link == SK_FALSE) {
-				SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
-				
-				RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
-				if (RetCode == 0) { /* RetCode: 0 => Start! */
-					pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
-					
-					/*
-					 * Start VCT timer counter.
-					 */
-					SK_MEMSET((char *) &Para, 0, sizeof(Para));
-					Para.Para32[0] = PhysPortIndex;
-					Para.Para32[1] = -1;
-					SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
-						4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-					RetCode = SK_PNMI_ERR_OK;
-				}
-				else { /* RetCode: 2 => Running! */
-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-					RetCode = SK_PNMI_ERR_OK;
-				}
-			}
-			else { /* RetCode: 4 => Link! */
-				RetCode = 4;
-				SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-				RetCode = SK_PNMI_ERR_OK;
-			}
-			Offset += sizeof(SK_U32);
-			break;
-	
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	} /* for */
-	*pLen = Offset;
-	return (RetCode);
-
-} /* Vct */
-
-
-PNMI_STATIC void CheckVctStatus(
-SK_AC		*pAC,
-SK_IOC		IoC,
-char		*pBuf,
-SK_U32		Offset,
-SK_U32		PhysPortIndex)
-{
-	SK_GEPORT 	*pPrt;
-	SK_PNMI_VCT	*pVctData;
-	SK_U32		RetCode;
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	
-	pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
-	pVctData->VctStatus = SK_PNMI_VCT_NONE;
-	
-	if (!pPrt->PHWLinkUp) {
-		
-		/* Was a VCT test ever made before? */
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
-			if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
-				pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
-			}
-			else {
-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
-			}
-		}
-		
-		/* Check VCT test status. */
-		RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
-		if (RetCode == 2) { /* VCT test is running. */
-			pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
-		}
-		else { /* VCT data was copied to pAC here. Check PENDING state. */
-			if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
-			}
-		}
-		
-		if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
-		}
-	}
-	else {
-		
-		/* Was a VCT test ever made before? */
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
-			pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
-		}
-		
-		/* DSP only valid in 100/1000 modes. */
-		if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
-			SK_LSPEED_STAT_10MBPS) {	
-			pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
-		}
-	}
-} /* CheckVctStatus */
-
-
-/*****************************************************************************
- *
- *      SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
- *                       PNMI function depending on the subcommand and
- *                       returns all data belonging to the complete database
- *                       or OID request.
- *
- * Description:
- *	Looks up the requested subcommand, calls the corresponding handler
- *	function and passes all required parameters to it.
- *	The function is called by the driver. It is needed to handle the new
- *  generic PNMI IOCTL. This IOCTL is given to the driver and contains both
- *  the OID and a subcommand to decide what kind of request has to be done.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-int SkPnmiGenIoctl(
-SK_AC		*pAC,		/* Pointer to adapter context struct */
-SK_IOC		IoC,		/* I/O context */
-void		*pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,		/* Length of buffer */
-SK_U32		NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-SK_I32	Mode;			/* Store value of subcommand. */
-SK_U32	Oid;			/* Store value of OID. */
-int		ReturnCode;		/* Store return value to show status of PNMI action. */
-int 	HeaderLength;	/* Length of desired action plus OID. */
-
-	ReturnCode = SK_PNMI_ERR_GENERAL;
-	
-	SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
-	SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
-	HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
-	*pLen = *pLen - HeaderLength;
-	SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
-	
-	switch(Mode) {
-	case SK_GET_SINGLE_VAR:
-		ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_PRESET_SINGLE_VAR:
-		ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_SET_SINGLE_VAR:
-		ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_GET_FULL_MIB:
-		ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	case SK_PRESET_FULL_MIB:
-		ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	case SK_SET_FULL_MIB:
-		ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	default:
-		break;
-	}
-	
-	return (ReturnCode);
-
-} /* SkGeIocGen */
diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
deleted file mode 100644
index e5ee6d6..0000000
--- a/drivers/net/sk98lin/skgesirq.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgesirq.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.92 $
- * Date:	$Date: 2003/09/16 14:37:07 $
- * Purpose:	Special IRQ module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	Special Interrupt handler
- *
- *	The following abstract should show how this module is included
- *	in the driver path:
- *
- *	In the ISR of the driver the bits for frame transmission complete and
- *	for receive complete are checked and handled by the driver itself.
- *	The bits of the slow path mask are checked after that and then the
- *	entry into the so-called "slow path" is prepared. It is an implementors
- *	decision whether this is executed directly or just scheduled by
- *	disabling the mask. In the interrupt service routine some events may be
- *	generated, so it would be a good idea to call the EventDispatcher
- *	right after this ISR.
- *
- *	The Interrupt source register of the adapter is NOT read by this module.
- *  SO if the drivers implementor needs a while loop around the
- *	slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
- *	each loop entered.
- *
- *	However, the MAC Interrupt status registers are read in a while loop.
- *
- */
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#ifndef SK_SLIM
-#include "h/skgepnmi.h"		/* PNMI Definitions */
-#include "h/skrlmt.h"		/* RLMT Definitions */
-#endif
-#include "h/skdrv2nd.h"		/* Adapter Control and Driver specific Def. */
-
-/* local function prototypes */
-#ifdef GENESIS
-static int	SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* GENESIS */
-#ifdef YUKON
-static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static int	SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* OTHER_PHY */
-
-#ifdef GENESIS
-/*
- * array of Rx counter from XMAC which are checked
- * in AutoSense mode to check whether a link is not able to auto-negotiate.
- */
-static const SK_U16 SkGeRxRegs[]= {
-	XM_RXF_64B,
-	XM_RXF_127B,
-	XM_RXF_255B,
-	XM_RXF_511B,
-	XM_RXF_1023B,
-	XM_RXF_MAX_SZ
-} ;
-#endif /* GENESIS */
-
-#ifdef __C2MAN__
-/*
- *	Special IRQ function
- *
- *	General Description:
- *
- */
-intro()
-{}
-#endif
-
-/******************************************************************************
- *
- *	SkHWInitDefSense() - Default Autosensing mode initialization
- *
- * Description: sets the PLinkMode for HWInit
- *
- * Returns: N/A
- */
-static void SkHWInitDefSense(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-	if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
-		pPrt->PLinkMode = pPrt->PLinkModeConf;
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("AutoSensing: First mode %d on Port %d\n",
-		(int)SK_LMODE_AUTOFULL, Port));
-
-	pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-
-	return;
-}	/* SkHWInitDefSense */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkHWSenseGetNext() - Get Next Autosensing Mode
- *
- * Description: gets the appropriate next mode
- *
- * Note:
- *
- */
-static SK_U8 SkHWSenseGetNext(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
-		/* Leave all as configured */
-		return(pPrt->PLinkModeConf);
-	}
-
-    if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
-		/* Return next mode AUTOBOTH */
-        return ((SK_U8)SK_LMODE_AUTOBOTH);
-	}
-
-	/* Return default autofull */
-    return ((SK_U8)SK_LMODE_AUTOFULL);
-}	/* SkHWSenseGetNext */
-
-
-/******************************************************************************
- *
- *	SkHWSenseSetNext() - Autosensing Set next mode
- *
- * Description:	sets the appropriate next mode
- *
- * Returns: N/A
- */
-static void SkHWSenseSetNext(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U8	NewMode)	/* New Mode to be written in sense mode */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("AutoSensing: next mode %d on Port %d\n",
-		(int)NewMode, Port));
-
-	pPrt->PLinkMode = NewMode;
-
-	return;
-}	/* SkHWSenseSetNext */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkHWLinkDown() - Link Down handling
- *
- * Description: handles the hardware link down signal
- *
- * Returns: N/A
- */
-void SkHWLinkDown(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Disable all MAC interrupts */
-	SkMacIrqDisable(pAC, IoC, Port);
-
-	/* Disable Receiver and Transmitter */
-	SkMacRxTxDisable(pAC, IoC, Port);
-	
-	/* Init default sense mode */
-	SkHWInitDefSense(pAC, IoC, Port);
-
-	if (pPrt->PHWLinkUp == SK_FALSE) {
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("Link down Port %d\n", Port));
-
-	/* Set Link to DOWN */
-	pPrt->PHWLinkUp = SK_FALSE;
-
-	/* Reset Port stati */
-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-    pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
-
-	/* Re-init Phy especially when the AutoSense default is set now */
-	SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-	/* GP0: used for workaround of Rev. C Errata 2 */
-
-	/* Do NOT signal to RLMT */
-
-	/* Do NOT start the timer here */
-}	/* SkHWLinkDown */
-
-
-/******************************************************************************
- *
- *	SkHWLinkUp() - Link Up handling
- *
- * Description: handles the hardware link up signal
- *
- * Returns: N/A
- */
-static void SkHWLinkUp(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		/* We do NOT need to proceed on active link */
-		return;
-	}
-
-	pPrt->PHWLinkUp = SK_TRUE;
-	pPrt->PAutoNegFail = SK_FALSE;
-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-
-    if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
-		/* Link is up and no Auto-negotiation should be done */
-
-		/* Link speed should be the configured one */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-			/* default is 1000 Mbps */
-		case SK_LSPEED_1000MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-			break;
-		case SK_LSPEED_100MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
-			break;
-		case SK_LSPEED_10MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
-			break;
-		}
-
-		/* Set Link Mode Status */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
-		}
-		else {
-            pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
-		}
-
-		/* No flow control without auto-negotiation */
-        pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-
-		/* enable Rx/Tx */
-        (void)SkMacRxTxEnable(pAC, IoC, Port);
-	}
-}	/* SkHWLinkUp */
-
-
-/******************************************************************************
- *
- *	SkMacParity() - MAC parity workaround
- *
- * Description: handles MAC parity errors correctly
- *
- * Returns: N/A
- */
-static void SkMacParity(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index of the port failed */
-{
-	SK_EVPARA	Para;
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U32		TxMax;		/* Tx Max Size Counter */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Clear IRQ Tx Parity Error */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
-			(SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
-			pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
-	}
-#endif /* YUKON */
-	
-	if (pPrt->PCheckPar) {
-
-		if (Port == MAC_1) {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
-		}
-		Para.Para64 = Port;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = Port;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		return;
-	}
-
-	/* Check whether frames with a size of 1k were sent */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* Snap statistic counters */
-		(void)SkXmUpdateStats(pAC, IoC, Port);
-		
-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-
-		(void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
-	}
-#endif /* YUKON */
-	
-	if (TxMax > 0) {
-		/* From now on check the parity */
-		pPrt->PCheckPar = SK_TRUE;
-	}
-}	/* SkMacParity */
-
-
-/******************************************************************************
- *
- *	SkGeHwErr() - Hardware Error service routine
- *
- * Description: handles all HW Error interrupts
- *
- * Returns: N/A
- */
-static void SkGeHwErr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-SK_U32	HwStatus)	/* Interrupt status word */
-{
-	SK_EVPARA	Para;
-	SK_U16		Word;
-
-	if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
-		/* PCI Errors occured */
-		if ((HwStatus & IS_IRQ_STAT) != 0) {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
-		}
-
-		/* Reset all bits in the PCI STATUS register */
-		SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-		
-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-        SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		if ((HwStatus & IS_NO_STAT_M1) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
-		}
-
-		if ((HwStatus & IS_NO_STAT_M2) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
-		}
-
-		if ((HwStatus & IS_NO_TIST_M1) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
-		}
-
-		if ((HwStatus & IS_NO_TIST_M2) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* This is necessary only for Rx timing measurements */
-		if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
-			/* increment Time Stamp Timer counter (high) */
-			pAC->GIni.GITimeStampCnt++;
-
-			/* Clear Time Stamp Timer IRQ */
-			SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
-		}
-
-		if ((HwStatus & IS_IRQ_SENSOR) != 0) {
-			/* no sensors on 32-bit Yukon */
-			if (pAC->GIni.GIYukon32Bit) {
-				/* disable HW Error IRQ */
-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
-			}
-		}
-	}
-#endif /* YUKON */
-
-	if ((HwStatus & IS_RAM_RD_PAR) != 0) {
-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-	if ((HwStatus & IS_RAM_WR_PAR) != 0) {
-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-	if ((HwStatus & IS_M1_PAR_ERR) != 0) {
-		SkMacParity(pAC, IoC, MAC_1);
-	}
-
-	if ((HwStatus & IS_M2_PAR_ERR) != 0) {
-		SkMacParity(pAC, IoC, MAC_2);
-	}
-
-	if ((HwStatus & IS_R1_PAR_ERR) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
-
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((HwStatus & IS_R2_PAR_ERR) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
-
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-}	/* SkGeHwErr */
-
-
-/******************************************************************************
- *
- *	SkGeSirqIsr() - Special Interrupt Service Routine
- *
- * Description: handles all non data transfer specific interrupts (slow path)
- *
- * Returns: N/A
- */
-void SkGeSirqIsr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-SK_U32	Istatus)	/* Interrupt status word */
-{
-	SK_EVPARA	Para;
-	SK_U32		RegVal32;	/* Read register value */
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U16 		PhyInt;
-	int			i;
-
-	if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
-		/* read the HW Error Interrupt source */
-		SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-		
-		SkGeHwErr(pAC, IoC, RegVal32);
-	}
-
-	/*
-	 * Packet Timeout interrupts
-	 */
-	/* Check whether MACs are correctly initialized */
-	if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
-		pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
-		/* MAC 1 was not initialized but Packet timeout occured */
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
-			SKERR_SIRQ_E004MSG);
-	}
-
-	if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
-	    pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
-		/* MAC 2 was not initialized but Packet timeout occured */
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
-			SKERR_SIRQ_E005MSG);
-	}
-
-	if ((Istatus & IS_PA_TO_RX1) != 0) {
-		/* Means network is filling us up */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
-			SKERR_SIRQ_E002MSG);
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
-	}
-
-	if ((Istatus & IS_PA_TO_RX2) != 0) {
-		/* Means network is filling us up */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
-			SKERR_SIRQ_E003MSG);
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
-	}
-
-	if ((Istatus & IS_PA_TO_TX1) != 0) {
-		
-		pPrt = &pAC->GIni.GP[0];
-
-		/* May be a normal situation in a server with a slow network */
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
-
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/*
-			 * workaround: if in half duplex mode, check for Tx hangup.
-			 * Read number of TX'ed bytes, wait for 10 ms, then compare
-			 * the number with current value. If nothing changed, we assume
-			 * that Tx is hanging and do a FIFO flush (see event routine).
-			 */
-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
-				!pPrt->HalfDupTimerActive) {
-				/*
-				 * many more pack. arb. timeouts may come in between,
-				 * we ignore those
-				 */
-				pPrt->HalfDupTimerActive = SK_TRUE;
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, 0);
-
-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
-
-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
-
-				pPrt->LastOctets += RegVal32;
-				
-				Para.Para32[0] = 0;
-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
-			}
-		}
-#endif /* GENESIS */
-	}
-
-	if ((Istatus & IS_PA_TO_TX2) != 0) {
-		
-		pPrt = &pAC->GIni.GP[1];
-
-		/* May be a normal situation in a server with a slow network */
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
-
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/* workaround: see above */
-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
-				!pPrt->HalfDupTimerActive) {
-				pPrt->HalfDupTimerActive = SK_TRUE;
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, 1);
-
-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
-
-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
-
-				pPrt->LastOctets += RegVal32;
-				
-				Para.Para32[0] = 1;
-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
-			}
-		}
-#endif /* GENESIS */
-	}
-
-	/* Check interrupts of the particular queues */
-	if ((Istatus & IS_R1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
-			SKERR_SIRQ_E006MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_R2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
-			SKERR_SIRQ_E007MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XS1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
-			SKERR_SIRQ_E008MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XA1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
-			SKERR_SIRQ_E009MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XS2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
-			SKERR_SIRQ_E010MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XA2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
-			SKERR_SIRQ_E011MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	/* External reg interrupt */
-	if ((Istatus & IS_EXT_REG) != 0) {
-		/* Test IRQs from PHY */
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-			
-			pPrt = &pAC->GIni.GP[i];
-			
-			if (pPrt->PState == SK_PRT_RESET) {
-				continue;
-			}
-			
-#ifdef GENESIS
-			if (pAC->GIni.GIGenesis) {
-				
-				switch (pPrt->PhyType) {
-				
-				case SK_PHY_XMAC:
-					break;
-				
-				case SK_PHY_BCOM:
-					SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
-	
-					if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-							("Port %d Bcom Int: 0x%04X\n",
-							i, PhyInt));
-						SkPhyIsrBcom(pAC, IoC, i, PhyInt);
-					}
-					break;
-#ifdef OTHER_PHY
-				case SK_PHY_LONE:
-					SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
-					
-					if ((PhyInt & PHY_L_DEF_MSK) != 0) {
-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-							("Port %d Lone Int: %x\n",
-							i, PhyInt));
-						SkPhyIsrLone(pAC, IoC, i, PhyInt);
-					}
-					break;
-#endif /* OTHER_PHY */
-				}
-			}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-			if (pAC->GIni.GIYukon) {
-				/* Read PHY Interrupt Status */
-				SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
-
-				if ((PhyInt & PHY_M_DEF_MSK) != 0) {
-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-						("Port %d Marv Int: 0x%04X\n",
-						i, PhyInt));
-					SkPhyIsrGmac(pAC, IoC, i, PhyInt);
-				}
-			}
-#endif /* YUKON */
-		}
-	}
-
-	/* I2C Ready interrupt */
-	if ((Istatus & IS_I2C_READY) != 0) {
-#ifdef SK_SLIM
-        SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-#else		
-		SkI2cIsr(pAC, IoC);
-#endif		
-	}
-
-	/* SW forced interrupt */
-	if ((Istatus & IS_IRQ_SW) != 0) {
-		/* clear the software IRQ */
-		SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
-	}
-
-	if ((Istatus & IS_LNK_SYNC_M1) != 0) {
-		/*
-		 * We do NOT need the Link Sync interrupt, because it shows
-		 * us only a link going down.
-		 */
-		/* clear interrupt */
-		SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
-	}
-
-	/* Check MAC after link sync counter */
-	if ((Istatus & IS_MAC1) != 0) {
-		/* IRQ from MAC 1 */
-		SkMacIrq(pAC, IoC, MAC_1);
-	}
-
-	if ((Istatus & IS_LNK_SYNC_M2) != 0) {
-		/*
-		 * We do NOT need the Link Sync interrupt, because it shows
-		 * us only a link going down.
-		 */
-		/* clear interrupt */
-		SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
-	}
-
-	/* Check MAC after link sync counter */
-	if ((Istatus & IS_MAC2) != 0) {
-		/* IRQ from MAC 2 */
-		SkMacIrq(pAC, IoC, MAC_2);
-	}
-
-	/* Timer interrupt (served last) */
-	if ((Istatus & IS_TIMINT) != 0) {
-		/* check for HW Errors */
-		if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
-			/* read the HW Error Interrupt source */
-			SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-
-			SkGeHwErr(pAC, IoC, RegVal32);
-		}
-
-		SkHwtIsr(pAC, IoC);
-	}
-
-}	/* SkGeSirqIsr */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- */
-static int SkGePortCheckShorts(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port)		/* Which port should be checked */
-{
-	SK_U32		Shorts;			/* Short Event Counter */
-	SK_U32		CheckShorts;	/* Check value for Short Event Counter */
-	SK_U64		RxCts;			/* Rx Counter (packets on network) */
-	SK_U32		RxTmp;			/* Rx temp. Counter */
-	SK_U32		FcsErrCts;		/* FCS Error Counter */
-	SK_GEPORT	*pPrt;			/* GIni Port struct pointer */
-	int			Rtv;			/* Return value */
-	int			i;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Default: no action */
-	Rtv = SK_HW_PS_NONE;
-
-	(void)SkXmUpdateStats(pAC, IoC, Port);
-
-	/* Extra precaution: check for short Event counter */
-	(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-
-	/*
-	 * Read Rx counters (packets seen on the network and not necessarily
-	 * really received.
-	 */
-	RxCts = 0;
-
-	for (i = 0; i < ARRAY_SIZE(SkGeRxRegs); i++) {
-		
-		(void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
-		
-		RxCts += (SK_U64)RxTmp;
-	}
-
-	/* On default: check shorts against zero */
-	CheckShorts = 0;
-
-	/* Extra precaution on active links */
-	if (pPrt->PHWLinkUp) {
-		/* Reset Link Restart counter */
-		pPrt->PLinkResCt = 0;
-		pPrt->PAutoNegTOCt = 0;
-
-		/* If link is up check for 2 */
-		CheckShorts = 2;
-
-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
-		
-		if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-		    pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
-		    (pPrt->PLinkMode == SK_LMODE_HALF ||
-			 pPrt->PLinkMode == SK_LMODE_FULL)) {
-			/*
-			 * This is autosensing and we are in the fallback
-			 * manual full/half duplex mode.
-			 */
-			if (RxCts == pPrt->PPrevRx) {
-				/* Nothing received, restart link */
-				pPrt->PPrevFcs = FcsErrCts;
-				pPrt->PPrevShorts = Shorts;
-				
-				return(SK_HW_PS_RESTART);
-			}
-			else {
-				pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
-			}
-		}
-
-		if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
-		    (!(FcsErrCts - pPrt->PPrevFcs))) {
-			/*
-			 * Note: The compare with zero above has to be done the way shown,
-			 * otherwise the Linux driver will have a problem.
-			 */
-			/*
-			 * We received a bunch of frames or no CRC error occured on the
-			 * network -> ok.
-			 */
-			pPrt->PPrevRx = RxCts;
-			pPrt->PPrevFcs = FcsErrCts;
-			pPrt->PPrevShorts = Shorts;
-
-			return(SK_HW_PS_NONE);
-		}
-
-		pPrt->PPrevFcs = FcsErrCts;
-	}
-
-
-	if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Short Event Count Restart Port %d \n", Port));
-		Rtv = SK_HW_PS_RESTART;
-	}
-
-	pPrt->PPrevShorts = Shorts;
-	pPrt->PPrevRx = RxCts;
-
-	return(Rtv);
-}	/* SkGePortCheckShorts */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUp() - Check if the link is up
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUp(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port)		/* Which port should be checked */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_BOOL		AutoNeg;	/* Is Auto-negotiation used ? */
-	int			Rtv;		/* Return value */
-
-	Rtv = SK_HW_PS_NONE;
-	
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		AutoNeg = SK_FALSE;
-	}
-	else {
-		AutoNeg = SK_TRUE;
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		switch (pPrt->PhyType) {
-		
-		case SK_PHY_XMAC:
-			Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
-			break;
-		case SK_PHY_BCOM:
-			Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
-			break;
-		case SK_PHY_NAT:
-			Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
-			break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
-	}
-#endif /* YUKON */
-
-	return(Rtv);	
-}	/* SkGePortCheckUp */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpXmac(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_U32		Shorts;		/* Short Event Counter */
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U32		GpReg;		/* General Purpose register value */
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		IsrcSum;	/* Interrupt source register sum */
-	SK_U16		LpAb;		/* Link Partner Ability */
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		ExtStat;	/* Extended Status Register */
-	SK_U8		NextMode;	/* Next AutoSensing Mode */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			return(SK_HW_PS_NONE);
-		}
-		else {
-			return(SkGePortCheckShorts(pAC, IoC, Port));
-		}
-	}
-
-	IsrcSum = pPrt->PIsave;
-	pPrt->PIsave = 0;
-
-	/* Now wait for each port's link */
-	if (pPrt->PLinkBroken) {
-		/* Link was broken */
-		XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-
-		if ((GpReg & XM_GP_INP_ASS) == 0) {
-			/* The Link is in sync */
-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-			IsrcSum |= Isrc;
-			SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-			
-			if ((Isrc & XM_IS_INP_ASS) == 0) {
-				/* It has been in sync since last time */
-				/* Restart the PORT */
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Link in sync Restart Port %d\n", Port));
-
-				(void)SkXmUpdateStats(pAC, IoC, Port);
-
-				/* We now need to reinitialize the PrevShorts counter */
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-				pPrt->PPrevShorts = Shorts;
-
-				pPrt->PLinkBroken = SK_FALSE;
-
-				/*
-				 * Link Restart Workaround:
-				 *  it may be possible that the other Link side
-				 *  restarts its link as well an we detect
-				 *  another LinkBroken. To prevent this
-				 *  happening we check for a maximum number
-				 *  of consecutive restart. If those happens,
-				 *  we do NOT restart the active link and
-				 *  check whether the link is now o.k.
-				 */
-				pPrt->PLinkResCt++;
-				
-				pPrt->PAutoNegTimeOut = 0;
-
-				if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
-					return(SK_HW_PS_RESTART);
-				}
-
-				pPrt->PLinkResCt = 0;
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
-			}
-			else {
-				pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
-
-				/* Do nothing more if link is broken */
-				return(SK_HW_PS_NONE);
-			}
-		}
-		else {
-			/* Do nothing more if link is broken */
-			return(SK_HW_PS_NONE);
-		}
-
-	}
-	else {
-		/* Link was not broken, check if it is */
-		XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-		IsrcSum |= Isrc;
-		if ((Isrc & XM_IS_INP_ASS) != 0) {
-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-			IsrcSum |= Isrc;
-			if ((Isrc & XM_IS_INP_ASS) != 0) {
-				XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-				IsrcSum |= Isrc;
-				if ((Isrc & XM_IS_INP_ASS) != 0) {
-					pPrt->PLinkBroken = SK_TRUE;
-					/* Re-Init Link partner Autoneg flag */
-					pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-						("Link broken Port %d\n", Port));
-
-					/* Cable removed-> reinit sense mode */
-					SkHWInitDefSense(pAC, IoC, Port);
-
-					return(SK_HW_PS_RESTART);
-				}
-			}
-		}
-		else {
-			SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
-			
-			if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
-				return(SK_HW_PS_RESTART);
-			}
-		}
-	}
-
-	/*
-	 * here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-	XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-	XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-	IsrcSum |= Isrc;
-
-	SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-	
-	if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
-		if ((GpReg & XM_GP_INP_ASS) == 0) {
-			/* Save Auto-negotiation Done interrupt only if link is in sync */
-			pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-		}
-#ifdef DEBUG
-		if ((pPrt->PIsave & XM_IS_AND) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("AutoNeg done rescheduled Port %d\n", Port));
-		}
-#endif /* DEBUG */
-		return(SK_HW_PS_NONE);
-	}
-
-	if (AutoNeg) {
-		if ((IsrcSum & XM_IS_AND) != 0) {
-			SkHWLinkUp(pAC, IoC, Port);
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			if (Done != SK_AND_OK) {
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
-					 Port, LpAb, ResAb));
-					
-				/* Try next possible mode */
-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
-				SkHWLinkDown(pAC, IoC, Port);
-				if (Done == SK_AND_DUP_CAP) {
-					/* GoTo next mode */
-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
-				}
-
-				return(SK_HW_PS_RESTART);
-			}
-			/*
-			 * Dummy Read extended status to prevent extra link down/ups
-			 * (clear Page Received bit if set)
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
-			
-			return(SK_HW_PS_LINK);
-		}
-		
-		/* AutoNeg not done, but HW link is up. Check for timeouts */
-		pPrt->PAutoNegTimeOut++;
-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
-			/* Increase the Timeout counter */
-			pPrt->PAutoNegTOCt++;
-
-			/* Timeout occured */
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-				("AutoNeg timeout Port %d\n", Port));
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
-				/* Set Link manually up */
-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Set manual full duplex Port %d\n", Port));
-			}
-
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
-				pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
-				/*
-				 * This is rather complicated.
-				 * we need to check here whether the LIPA_AUTO
-				 * we saw before is false alert. We saw at one
-				 * switch ( SR8800) that on boot time it sends
-				 * just one auto-neg packet and does no further
-				 * auto-negotiation.
-				 * Solution: we restart the autosensing after
-				 * a few timeouts.
-				 */
-				pPrt->PAutoNegTOCt = 0;
-				pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
-				SkHWInitDefSense(pAC, IoC, Port);
-			}
-
-			/* Do the restart */
-			return(SK_HW_PS_RESTART);
-		}
-	}
-	else {
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		/*
-		 * Link sync (GP) and so assume a good connection. But if not received
-		 * a bunch of frames received in a time slot (maybe broken tx cable)
-		 * the port is restart.
-		 */
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpXmac */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpBcom(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		PhyStat;	/* Phy Status Register */
-	SK_U16		ResAb;		/* Master/Slave resolution */
-	SK_U16		Ctrl;		/* Broadcom control flags */
-#ifdef DEBUG
-	SK_U16		LpAb;
-	SK_U16		ExtStat;
-#endif /* DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Check for No HCD Link events (#10523) */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
-
-#ifdef xDEBUG
-	if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
-		(PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
-
-		SK_U32	Stat1, Stat2, Stat3;
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"CheckUp1 - Stat: %x, Mask: %x",
-			(void *)Isrc,
-			(void *)Stat1);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"Ctrl/Stat: %x, AN Adv/LP: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-	}
-#endif /* DEBUG */
-
-	if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
-		/*
-		 * Workaround BCom Errata:
-		 *	enable and disable loopback mode if "NO HCD" occurs.
-		 */
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
-			(SK_U16)(Ctrl | PHY_CT_LOOP));
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
-			(SK_U16)(Ctrl & ~PHY_CT_LOOP));
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("No HCD Link event, Port %d\n", Port));
-#ifdef xDEBUG
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"No HCD link event, port %d.",
-			(void *)Port,
-			(void *)NULL);
-#endif /* DEBUG */
-	}
-
-	/* Not obsolete: link status bit is latched to 0 and autoclearing! */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-#ifdef xDEBUG
-	{
-		SK_U32	Stat1, Stat2, Stat3;
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"CheckUp1a - Stat: %x, Mask: %x",
-			(void *)Isrc,
-			(void *)Stat1);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-		Stat1 = Stat1 << 16 | PhyStat;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"Ctrl/Stat: %x, AN Adv/LP: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-		Stat2 = Stat2 << 16 | ResAb;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-	}
-#endif /* DEBUG */
-
-	/*
-	 * Here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
-		
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		
-		return(SK_HW_PS_RESTART);
-	}
-
-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
-		return(SK_HW_PS_NONE);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Port %d, ResAb: 0x%04X\n", Port, ResAb));
-
-	if (AutoNeg) {
-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-			
-			SkHWLinkUp(pAC, IoC, Port);
-			
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			
-			if (Done != SK_AND_OK) {
-#ifdef DEBUG
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
-					Port, LpAb, ExtStat));
-#endif /* DEBUG */
-				return(SK_HW_PS_RESTART);
-			}
-			else {
-#ifdef xDEBUG
-				/* Dummy read ISR to prevent extra link downs/ups */
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
-				if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
-					CMSMPrintString(
-						pAC->pConfigTable,
-						MSG_TYPE_RUNTIME_INFO,
-						"CheckUp2 - Stat: %x",
-						(void *)ExtStat,
-						(void *)NULL);
-				}
-#endif /* DEBUG */
-				return(SK_HW_PS_LINK);
-			}
-		}
-	}
-	else {	/* !AutoNeg */
-		/* Link is up and we don't need more. */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-#ifdef xDEBUG
-		/* Dummy read ISR to prevent extra link downs/ups */
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
-		if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
-			CMSMPrintString(
-				pAC->pConfigTable,
-				MSG_TYPE_RUNTIME_INFO,
-				"CheckUp3 - Stat: %x",
-				(void *)ExtStat,
-				(void *)NULL);
-		}
-#endif /* DEBUG */
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpGmac(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		PhyIsrc;	/* PHY Interrupt source */
-	SK_U16		PhyStat;	/* PPY Status */
-	SK_U16		PhySpecStat;/* PHY Specific Status */
-	SK_U16		ResAb;		/* Master/Slave resolution */
-	SK_EVPARA	Para;
-#ifdef DEBUG
-	SK_U16		Word;		/* I/O helper */
-#endif /* DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-	/* Read PHY Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
-	/* Read PHY Interrupt Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
-
-	if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
-		
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		
-		return(SK_HW_PS_RESTART);
-	}
-
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
-
-#ifdef DEBUG
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
-
-	if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
-		(PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  {
-		/* Read PHY Next Page Link Partner */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Page Received, NextPage: 0x%04X\n", Word));
-	}
-#endif /* DEBUG */
-
-	if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
-		return(SK_HW_PS_NONE);
-	}
-	
-	if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
-		(PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
-		/* Downshift detected */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
-		
-		Para.Para64 = Port;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-	
-	pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
-	
-	if (AutoNeg) {
-		/* Auto-Negotiation Over ? */
-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-			
-			SkHWLinkUp(pAC, IoC, Port);
-			
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			
-			if (Done != SK_AND_OK) {
-				return(SK_HW_PS_RESTART);
-			}
-			
-			return(SK_HW_PS_LINK);
-		}
-	}
-	else {	/* !AutoNeg */
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync, Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpLone(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		LpAb;		/* Link Partner Ability */
-	SK_U16		ExtStat;	/* Extended Status Register */
-	SK_U16		PhyStat;	/* Phy Status Register */
-	SK_U16		StatSum;
-	SK_U8		NextMode;	/* Next AutoSensing Mode */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-	StatSum = pPrt->PIsave;
-	pPrt->PIsave = 0;
-
-	/*
-	 * here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
-	StatSum |= PhyStat;
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
-		/* Save Auto-negotiation Done bit */
-		pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
-#ifdef DEBUG
-		if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("AutoNeg done rescheduled Port %d\n", Port));
-		}
-#endif /* DEBUG */
-		return(SK_HW_PS_NONE);
-	}
-
-	if (AutoNeg) {
-		if ((StatSum & PHY_ST_AN_OVER) != 0) {
-			SkHWLinkUp(pAC, IoC, Port);
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			if (Done != SK_AND_OK) {
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
-					 Port, LpAb, ExtStat));
-					
-				/* Try next possible mode */
-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
-				SkHWLinkDown(pAC, IoC, Port);
-				if (Done == SK_AND_DUP_CAP) {
-					/* GoTo next mode */
-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
-				}
-
-				return(SK_HW_PS_RESTART);
-
-			}
-			else {
-				/*
-				 * Dummy Read interrupt status to prevent
-				 * extra link down/ups
-				 */
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-				return(SK_HW_PS_LINK);
-			}
-		}
-		
-		/* AutoNeg not done, but HW link is up. Check for timeouts */
-		pPrt->PAutoNegTimeOut++;
-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
-			/* Timeout occured */
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-				("AutoNeg timeout Port %d\n", Port));
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
-				/* Set Link manually up */
-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Set manual full duplex Port %d\n", Port));
-			}
-
-			/* Do the restart */
-			return(SK_HW_PS_RESTART);
-		}
-	}
-	else {
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Dummy Read interrupt status to prevent
-		 * extra link down/ups
-		 */
-		SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpLone */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpNat() - Check if the link is up on National PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpNat(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	/* todo: National */
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkGeSirqEvent() - Event Service Routine
- *
- * Description:
- *
- * Notes:
- */
-int	SkGeSirqEvent(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-SK_U32		Event,		/* Module specific Event */
-SK_EVPARA	Para)		/* Event specific Parameter */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U32		Port;
-	SK_U32		Val32;
-	int			PortStat;
-	SK_U8		Val8;
-#ifdef GENESIS
-	SK_U64		Octets;
-#endif /* GENESIS */
-
-	Port = Para.Para32[0];
-	pPrt = &pAC->GIni.GP[Port];
-
-	switch (Event) {
-	case SK_HWEV_WATIM:
-		if (pPrt->PState == SK_PRT_RESET) {
-		
-			PortStat = SK_HW_PS_NONE;
-		}
-		else {
-			/* Check whether port came up */
-			PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
-		}
-
-		switch (PortStat) {
-		case SK_HW_PS_RESTART:
-			if (pPrt->PHWLinkUp) {
-				/* Set Link to down */
-				SkHWLinkDown(pAC, IoC, (int)Port);
-
-				/*
-				 * Signal directly to RLMT to ensure correct
-				 * sequence of SWITCH and RESET event.
-				 */
-				SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-			}
-
-			/* Restart needed */
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-			break;
-
-		case SK_HW_PS_LINK:
-			/* Signal to RLMT */
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
-			break;
-		}
-		
-		/* Start again the check Timer */
-		if (pPrt->PHWLinkUp) {
-			Val32 = SK_WA_ACT_TIME;
-		}
-		else {
-			Val32 = SK_WA_INA_TIME;
-		}
-
-		/* Todo: still needed for non-XMAC PHYs??? */
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-		break;
-
-	case SK_HWEV_PORT_START:
-		if (pPrt->PHWLinkUp) {
-			/*
-			 * Signal directly to RLMT to ensure correct
-			 * sequence of SWITCH and RESET event.
-			 */
-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-		}
-
-		SkHWLinkDown(pAC, IoC, (int)Port);
-
-		/* Schedule Port RESET */
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-		break;
-
-	case SK_HWEV_PORT_STOP:
-		if (pPrt->PHWLinkUp) {
-			/*
-			 * Signal directly to RLMT to ensure correct
-			 * sequence of SWITCH and RESET event.
-			 */
-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-		}
-
-		/* Stop Workaround Timer */
-		SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
-
-		SkHWLinkDown(pAC, IoC, (int)Port);
-		break;
-
-	case SK_HWEV_UPDATE_STAT:
-		/* We do NOT need to update any statistics */
-		break;
-
-	case SK_HWEV_CLEAR_STAT:
-		/* We do NOT need to clear any statistics */
-		for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
-			pPrt->PPrevRx = 0;
-			pPrt->PPrevFcs = 0;
-			pPrt->PPrevShorts = 0;
-		}
-		break;
-
-	case SK_HWEV_SET_LMODE:
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PLinkModeConf != Val8) {
-			/* Set New link mode */
-			pPrt->PLinkModeConf = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_FLOWMODE:
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PFlowCtrlMode != Val8) {
-			/* Set New Flow Control mode */
-			pPrt->PFlowCtrlMode = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_ROLE:
-		/* not possible for fiber */
-		if (!pAC->GIni.GICopperType) {
-			break;
-		}
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PMSMode != Val8) {
-			/* Set New Role (Master/Slave) mode */
-			pPrt->PMSMode = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_SPEED:
-		if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-			break;
-		}
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PLinkSpeed != Val8) {
-			/* Set New Speed parameter */
-			pPrt->PLinkSpeed = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-#ifdef GENESIS
-	case SK_HWEV_HALFDUP_CHK:
-		if (pAC->GIni.GIGenesis) {
-			/*
-			 * half duplex hangup workaround.
-			 * See packet arbiter timeout interrupt for description
-			 */
-			pPrt->HalfDupTimerActive = SK_FALSE;
-			if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, Port);
-
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
-
-				Octets = (SK_U64)Val32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
-
-				Octets += Val32;
-				
-				if (pPrt->LastOctets == Octets) {
-					/* Tx hanging, a FIFO flush restarts it */
-					SkMacFlushTxFifo(pAC, IoC, Port);
-				}
-			}
-		}
-		break;
-#endif /* GENESIS */
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
-		break;
-	}
-
-	return(0);
-}	/* SkGeSirqEvent */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkPhyIsrBcom() - PHY interrupt service routine
- *
- * Description: handles all interrupts from BCom PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrBcom(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-int			Port,		/* Port Num = PHY Num */
-SK_U16		IStatus)	/* Interrupt Status */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_EVPARA	Para;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((IStatus & PHY_B_IS_PSE) != 0) {
-		/* Incorrectable pair swap error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
-			SKERR_SIRQ_E022MSG);
-	}
-	
-	if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
-
-		SkHWLinkDown(pAC, IoC, Port);
-
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-	}
-
-}	/* SkPhyIsrBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkPhyIsrGmac() - PHY interrupt service routine
- *
- * Description: handles all interrupts from Marvell PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrGmac(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-int			Port,		/* Port Num = PHY Num */
-SK_U16		IStatus)	/* Interrupt Status */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_EVPARA	Para;
-	SK_U16		Word;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
-
-		SkHWLinkDown(pAC, IoC, Port);
-
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNeg.Adv: 0x%04X\n", Word));
-		
-		/* Set Auto-negotiation advertisement */
-		if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
-			/* restore Asymmetric Pause bit */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
-				(SK_U16)(Word | PHY_M_AN_ASP));
-		}
-		
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-	
-	if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
-		/* Auto-Negotiation Error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
-	}
-	
-	if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
-		/* FIFO Overflow/Underrun Error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
-	}
-	
-}	/* SkPhyIsrGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkPhyIsrLone() - PHY interrupt service routine
- *
- * Description: handles all interrupts from LONE PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrLone(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* Io Context */
-int		Port,		/* Port Num = PHY Num */
-SK_U16	IStatus)	/* Interrupt Status */
-{
-	SK_EVPARA	Para;
-
-	if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
-		
-		SkHWLinkDown(pAC, IoC, Port);
-
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-}	/* SkPhyIsrLone */
-#endif /* OTHER_PHY */
-
-/* End of File */
diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
deleted file mode 100644
index 79bf57c..0000000
--- a/drivers/net/sk98lin/ski2c.c
+++ /dev/null
@@ -1,1296 +0,0 @@
-/******************************************************************************
- *
- * Name:	ski2c.c
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.59 $
- * Date:	$Date: 2003/10/20 09:07:25 $
- * Purpose:	Functions to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	I2C Protocol
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	I2C protocol implementation.
-
-	General Description:
-
-	The I2C protocol is used for the temperature sensors and for
-	the serial EEPROM which hold the configuration.
-
-	This file covers functions that allow to read write and do
-	some bulk requests a specified I2C address.
-
-	The Genesis has 2 I2C buses. One for the EEPROM which holds
-	the VPD Data and one for temperature and voltage sensor.
-	The following picture shows the I2C buses, I2C devices and
-	their control registers.
-
-	Note: The VPD functions are in skvpd.c
-.
-.	PCI Config I2C Bus for VPD Data:
-.
-.		      +------------+
-.		      | VPD EEPROM |
-.		      +------------+
-.			     |
-.			     | <-- I2C
-.			     |
-.		 +-----------+-----------+
-.		 |			 |
-.	+-----------------+	+-----------------+
-.	| PCI_VPD_ADR_REG |	| PCI_VPD_DAT_REG |
-.	+-----------------+	+-----------------+
-.
-.
-.	I2C Bus for LM80 sensor:
-.
-.			+-----------------+
-.			| Temperature and |
-.			| Voltage Sensor  |
-.			| 	LM80	  |
-.			+-----------------+
-.				|
-.				|
-.			I2C --> |
-.				|
-.			     +----+
-.	     +-------------->| OR |<--+
-.	     |		     +----+   |
-.     +------+------+		      |
-.     |		    |		      |
-. +--------+	+--------+	+----------+
-. | B2_I2C |	| B2_I2C |	|  B2_I2C  |
-. | _CTRL  |	| _DATA  |	|   _SW    |
-. +--------+	+--------+	+----------+
-.
-	The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
-	and B2_I2C_DATA registers.
-	For driver software it is recommended to use the I2C control and
-	data register, because I2C bus timing is done by the ASIC and
-	an interrupt may be received when the I2C request is completed.
-
-	Clock Rate Timing:			MIN	MAX	generated by
-		VPD EEPROM:			50 kHz	100 kHz		HW
-		LM80 over I2C Ctrl/Data reg.	50 kHz	100 kHz		HW
-		LM80 over B2_I2C_SW register	0	400 kHz		SW
-
-	Note:	The clock generated by the hardware is dependend on the
-		PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
-		clock is 50 kHz.
- */
-intro()
-{}
-#endif
-
-#ifdef SK_DIAG
-/*
- * I2C Fast Mode timing values used by the LM80.
- * If new devices are added to the I2C bus the timing values have to be checked.
- */
-#ifndef I2C_SLOW_TIMING
-#define	T_CLK_LOW			1300L	/* clock low time in ns */
-#define	T_CLK_HIGH		 	 600L	/* clock high time in ns */
-#define T_DATA_IN_SETUP		 100L	/* data in Set-up Time */
-#define T_START_HOLD		 600L	/* start condition hold time */
-#define T_START_SETUP		 600L	/* start condition Set-up time */
-#define	T_STOP_SETUP		 600L	/* stop condition Set-up time */
-#define T_BUS_IDLE			1300L	/* time the bus must free after Tx */
-#define	T_CLK_2_DATA_OUT	 900L	/* max. clock low to data output valid */
-#else	/* I2C_SLOW_TIMING */
-/* I2C Standard Mode Timing */
-#define	T_CLK_LOW			4700L	/* clock low time in ns */
-#define	T_CLK_HIGH			4000L	/* clock high time in ns */
-#define T_DATA_IN_SETUP		 250L	/* data in Set-up Time */
-#define T_START_HOLD		4000L	/* start condition hold time */
-#define T_START_SETUP		4700L	/* start condition Set-up time */
-#define	T_STOP_SETUP		4000L	/* stop condition Set-up time */
-#define T_BUS_IDLE			4700L	/* time the bus must free after Tx */
-#endif	/* !I2C_SLOW_TIMING */
-
-#define NS2BCLK(x)	(((x)*125)/10000)
-
-/*
- * I2C Wire Operations
- *
- * About I2C_CLK_LOW():
- *
- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
- * clock to low, to prevent the ASIC and the I2C data client from driving the
- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
- */
-#define I2C_DATA_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA)
-#define	I2C_DATA_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA)
-#define	I2C_DATA_OUT(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
-#define	I2C_DATA_IN(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
-#define	I2C_CLK_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_CLK)
-#define	I2C_CLK_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
-#define	I2C_START_COND(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK)
-
-#define NS2CLKT(x)	((x*125L)/10000)
-
-/*--------------- I2C Interface Register Functions --------------- */
-
-/*
- * sending one bit
- */
-void SkI2cSndBit(
-SK_IOC	IoC,	/* I/O Context */
-SK_U8	Bit)	/* Bit to send */
-{
-	I2C_DATA_OUT(IoC);
-	if (Bit) {
-		I2C_DATA_HIGH(IoC);
-	}
-	else {
-		I2C_DATA_LOW(IoC);
-	}
-	SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
-	I2C_CLK_HIGH(IoC);
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-	I2C_CLK_LOW(IoC);
-}	/* SkI2cSndBit*/
-
-
-/*
- * Signal a start to the I2C Bus.
- *
- * A start is signaled when data goes to low in a high clock cycle.
- *
- * Ends with Clock Low.
- *
- * Status: not tested
- */
-void SkI2cStart(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/* Init data and Clock to output lines */
-	/* Set Data high */
-	I2C_DATA_OUT(IoC);
-	I2C_DATA_HIGH(IoC);
-	/* Set Clock high */
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
-
-	/* Set Data Low */
-	I2C_DATA_LOW(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
-
-	/* Clock low without Data to Input */
-	I2C_START_COND(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
-}	/* SkI2cStart */
-
-
-void SkI2cStop(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/* Init data and Clock to output lines */
-	/* Set Data low */
-	I2C_DATA_OUT(IoC);
-	I2C_DATA_LOW(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
-	/* Set Clock high */
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
-
-	/*
-	 * Set Data High:	Do it by setting the Data Line to Input.
-	 *			Because of a pull up resistor the Data Line
-	 *			floods to high.
-	 */
-	I2C_DATA_IN(IoC);
-
-	/*
-	 *	When I2C activity is stopped
-	 *	 o	DATA should be set to input and
-	 *	 o	CLOCK should be set to high!
-	 */
-	SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
-}	/* SkI2cStop */
-
-
-/*
- * Receive just one bit via the I2C bus.
- *
- * Note:	Clock must be set to LOW before calling this function.
- *
- * Returns The received bit.
- */
-int SkI2cRcvBit(
-SK_IOC	IoC)	/* I/O Context */
-{
-	int	Bit;
-	SK_U8	I2cSwCtrl;
-
-	/* Init data as input line */
-	I2C_DATA_IN(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-
-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-	
-	Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
-
-	I2C_CLK_LOW(IoC);
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
-
-	return(Bit);
-}	/* SkI2cRcvBit */
-
-
-/*
- * Receive an ACK.
- *
- * returns	0 If acknowledged
- *		1 in case of an error
- */
-int SkI2cRcvAck(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	return(SkI2cRcvBit(IoC) != 0);
-}	/* SkI2cRcvAck */
-
-
-/*
- * Send an NACK.
- */
-void SkI2cSndNAck(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	SkI2cSndBit(IoC, 1);
-}	/* SkI2cSndNAck */
-
-
-/*
- * Send an ACK.
- */
-void SkI2cSndAck(
-SK_IOC IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	SkI2cSndBit(IoC, 0);
-}	/* SkI2cSndAck */
-
-
-/*
- * Send one byte to the I2C device and wait for ACK.
- *
- * Return acknowleged status.
- */
-int SkI2cSndByte(
-SK_IOC	IoC,	/* I/O Context */
-int		Byte)	/* byte to send */
-{
-	int	i;
-
-	for (i = 0; i < 8; i++) {
-		if (Byte & (1<<(7-i))) {
-			SkI2cSndBit(IoC, 1);
-		}
-		else {
-			SkI2cSndBit(IoC, 0);
-		}
-	}
-
-	return(SkI2cRcvAck(IoC));
-}	/* SkI2cSndByte */
-
-
-/*
- * Receive one byte and ack it.
- *
- * Return byte.
- */
-int SkI2cRcvByte(
-SK_IOC	IoC,	/* I/O Context */
-int		Last)	/* Last Byte Flag */
-{
-	int	i;
-	int	Byte = 0;
-
-	for (i = 0; i < 8; i++) {
-		Byte <<= 1;
-		Byte |= SkI2cRcvBit(IoC);
-	}
-
-	if (Last) {
-		SkI2cSndNAck(IoC);
-	}
-	else {
-		SkI2cSndAck(IoC);
-	}
-
-	return(Byte);
-}	/* SkI2cRcvByte */
-
-
-/*
- * Start dialog and send device address
- *
- * Return 0 if acknowleged, 1 in case of an error
- */
-int	SkI2cSndDev(
-SK_IOC	IoC,	/* I/O Context */
-int		Addr,	/* Device Address */
-int		Rw)		/* Read / Write Flag */
-{
-	SkI2cStart(IoC);
-	Rw = ~Rw;
-	Rw &= I2C_WRITE;
-	return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
-}	/* SkI2cSndDev */
-
-#endif /* SK_DIAG */
-
-/*----------------- I2C CTRL Register Functions ----------*/
-
-/*
- * waits for a completion of an I2C transfer
- *
- * returns	0:	success, transfer completes
- *			1:	error,	 transfer does not complete, I2C transfer
- *						 killed, wait loop terminated.
- */
-static int	SkI2cWait(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-int		Event)	/* complete event to wait for (I2C_READ or I2C_WRITE) */
-{
-	SK_U64	StartTime;
-	SK_U64	CurrentTime;
-	SK_U32	I2cCtrl;
-
-	StartTime = SkOsGetTime(pAC);
-	
-	do {
-		CurrentTime = SkOsGetTime(pAC);
-
-		if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
-			
-			SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
-#endif /* !SK_DIAG */
-			return(1);
-		}
-		
-		SK_I2C_GET_CTL(IoC, &I2cCtrl);
-
-#ifdef xYUKON_DBG
-		printf("StartTime=%lu, CurrentTime=%lu\n",
-			StartTime, CurrentTime);
-		if (kbhit()) {
-			return(1);
-		}
-#endif /* YUKON_DBG */
-	
-	} while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
-
-	return(0);
-}	/* SkI2cWait */
-
-
-/*
- * waits for a completion of an I2C transfer
- *
- * Returns
- *	Nothing
- */
-void SkI2cWaitIrq(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	SK_SENSOR	*pSen;
-	SK_U64		StartTime;
-	SK_U32		IrqSrc;
-
-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-
-	if (pSen->SenState == SK_SEN_IDLE) {
-		return;
-	}
-
-	StartTime = SkOsGetTime(pAC);
-	
-	do {
-		if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
-			
-			SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
-#endif /* !SK_DIAG */
-			return;
-		}
-		
-		SK_IN32(IoC, B0_ISRC, &IrqSrc);
-
-	} while ((IrqSrc & IS_I2C_READY) == 0);
-
-	pSen->SenState = SK_SEN_IDLE;
-	return;
-}	/* SkI2cWaitIrq */
-
-/*
- * writes a single byte or 4 bytes into the I2C device
- *
- * returns	0:	success
- *			1:	error
- */
-static int SkI2cWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	I2cData,	/* I2C Data to write */
-int		I2cDev,		/* I2C Device Address */
-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int		I2cReg,		/* I2C Device Register Address */
-int		I2cBurst)	/* I2C Burst Flag */
-{
-	SK_OUT32(IoC, B2_I2C_DATA, I2cData);
-	
-	SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-	
-	return(SkI2cWait(pAC, IoC, I2C_WRITE));
-}	/* SkI2cWrite*/
-
-
-#ifdef	SK_DIAG
-/*
- * reads a single byte or 4 bytes from the I2C device
- *
- * returns	the word read
- */
-SK_U32 SkI2cRead(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		I2cDev,		/* I2C Device Address */
-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int		I2cReg,		/* I2C Device Register Address */
-int		I2cBurst)	/* I2C Burst Flag */
-{
-	SK_U32	Data;
-
-	SK_OUT32(IoC, B2_I2C_DATA, 0);
-	SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-	
-	if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
-		w_print("%s\n", SKERR_I2C_E002MSG);
-	}
-	
-	SK_IN32(IoC, B2_I2C_DATA, &Data);
-	
-	return(Data);
-}	/* SkI2cRead */
-#endif /* SK_DIAG */
-
-
-/*
- * read a sensor's value
- *
- * This function reads a sensor's value from the I2C sensor chip. The sensor
- * is defined by its index into the sensors database in the struct pAC points
- * to.
- * Returns
- *		1 if the read is completed
- *		0 if the read must be continued (I2C Bus still allocated)
- */
-static int	SkI2cReadSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_SENSOR	*pSen)	/* Sensor to be read */
-{
-    if (pSen->SenRead != NULL) {
-        return((*pSen->SenRead)(pAC, IoC, pSen));
-    }
-	else {
-        return(0); /* no success */
-	}
-}	/* SkI2cReadSensor */
-
-/*
- * Do the Init state 0 initialization
- */
-static int SkI2cInit0(
-SK_AC	*pAC)	/* Adapter Context */
-{
-	int	i;
-
-	/* Begin with first sensor */
-	pAC->I2c.CurrSens = 0;
-	
-	/* Begin with timeout control for state machine */
-	pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-	
-	/* Set sensor number to zero */
-	pAC->I2c.MaxSens = 0;
-
-#ifndef SK_DIAG
-	/* Initialize Number of Dummy Reads */
-	pAC->I2c.DummyReads = SK_MAX_SENSORS;
-#endif
-
-	for (i = 0; i < SK_MAX_SENSORS; i++) {
-		pAC->I2c.SenTable[i].SenDesc = "unknown";
-		pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
-		pAC->I2c.SenTable[i].SenThreErrHigh = 0;
-		pAC->I2c.SenTable[i].SenThreErrLow = 0;
-		pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
-		pAC->I2c.SenTable[i].SenThreWarnLow = 0;
-		pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
-		pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
-		pAC->I2c.SenTable[i].SenValue = 0;
-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
-		pAC->I2c.SenTable[i].SenErrCts = 0;
-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
-		pAC->I2c.SenTable[i].SenRead = NULL;
-		pAC->I2c.SenTable[i].SenDev = 0;
-	}
-
-	/* Now we are "INIT data"ed */
-	pAC->I2c.InitLevel = SK_INIT_DATA;
-	return(0);
-}	/* SkI2cInit0*/
-
-
-/*
- * Do the init state 1 initialization
- *
- * initialize the following register of the LM80:
- * Configuration register:
- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
- *
- * Interrupt Mask Register 1:
- * - all interrupts are Disabled (0xff)
- *
- * Interrupt Mask Register 2:
- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
- *
- * Fan Divisor/RST_OUT register:
- * - Divisors set to 1 (bits 00), all others 0s.
- *
- * OS# Configuration/Temperature resolution Register:
- * - all 0s
- *
- */
-static int SkI2cInit1(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-    int i;
-    SK_U8 I2cSwCtrl;
-	SK_GEPORT *pPrt;	/* GIni Port struct pointer */
-
-	if (pAC->I2c.InitLevel != SK_INIT_DATA) {
-		/* ReInit not needed in I2C module */
-		return(0);
-	}
-
-    /* Set the Direction of I2C-Data Pin to IN */
-    SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
-    /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-
-	if ((I2cSwCtrl & I2C_DATA) == 0) {
-		/* this is a 32-Bit board */
-		pAC->GIni.GIYukon32Bit = SK_TRUE;
-        return(0);
-    }
-
-	/* Check for 64 Bit Yukon without sensors */
-	if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
-        return(0);
-    }
-
-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
-		LM80_CFG, 0);
-	
-	/*
-	 * MaxSens has to be updated here, because PhyType is not
-	 * set when performing Init Level 0
-	 */
-    pAC->I2c.MaxSens = 5;
-	
-	pPrt = &pAC->GIni.GP[0];
-	
-	if (pAC->GIni.GIGenesis) {
-		if (pPrt->PhyType == SK_PHY_BCOM) {
-			if (pAC->GIni.GIMacsFound == 1) {
-				pAC->I2c.MaxSens += 1;
-			}
-			else {
-				pAC->I2c.MaxSens += 3;
-			}
-		}
-	}
-	else {
-		pAC->I2c.MaxSens += 3;
-	}
-	
-	for (i = 0; i < pAC->I2c.MaxSens; i++) {
-		switch (i) {
-		case 0:
-			pAC->I2c.SenTable[i].SenDesc = "Temperature";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
-			break;
-		case 1:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
-			break;
-		case 2:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
-			pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
-			break;
-		case 3:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
-			break;
-		case 4:
-			if (pAC->GIni.GIGenesis) {
-				if (pPrt->PhyType == SK_PHY_BCOM) {
-					pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-				}
-				else {
-					pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-				}
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
-				if (pAC->GIni.GIVauxAvail) {
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
-				}
-				else {
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
-				}
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
-			break;
-		case 5:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
-			break;
-		case 6:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
-			break;
-		case 7:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
-				pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
-				pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
-				pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
-				pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
-			}
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
-				SKERR_I2C_E001, SKERR_I2C_E001MSG);
-			break;
-		}
-
-		pAC->I2c.SenTable[i].SenValue = 0;
-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
-		pAC->I2c.SenTable[i].SenErrCts = 0;
-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
-		pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
-		pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
-	}
-
-#ifndef SK_DIAG
-	pAC->I2c.DummyReads = pAC->I2c.MaxSens;
-#endif /* !SK_DIAG */
-	
-	/* Clear I2C IRQ */
-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-	
-	/* Now we are I/O initialized */
-	pAC->I2c.InitLevel = SK_INIT_IO;
-	return(0);
-}	/* SkI2cInit1 */
-
-
-/*
- * Init level 2: Start first sensor read.
- */
-static int SkI2cInit2(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	int		ReadComplete;
-	SK_SENSOR	*pSen;
-
-	if (pAC->I2c.InitLevel != SK_INIT_IO) {
-		/* ReInit not needed in I2C module */
-		/* Init0 and Init2 not permitted */
-		return(0);
-	}
-
-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-	ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-	if (ReadComplete) {
-		SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
-	}
-
-	/* Now we are correctly initialized */
-	pAC->I2c.InitLevel = SK_INIT_RUN;
-
-	return(0);
-}	/* SkI2cInit2*/
-
-
-/*
- * Initialize I2C devices
- *
- * Get the first voltage value and discard it.
- * Go into temperature read mode. A default pointer is not set.
- *
- * The things to be done depend on the init level in the parameter list:
- * Level 0:
- *	Initialize only the data structures. Do NOT access hardware.
- * Level 1:
- *	Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
- * Level 2:
- *	Everything is possible. Interrupts may be used from now on.
- *
- * return:
- *	0 = success
- *	other = error.
- */
-int	SkI2cInit(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context needed in levels 1 and 2 */
-int		Level)	/* Init Level */
-{
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		return(SkI2cInit0(pAC));
-	case SK_INIT_IO:
-		return(SkI2cInit1(pAC, IoC));
-	case SK_INIT_RUN:
-		return(SkI2cInit2(pAC, IoC));
-	default:
-		break;
-	}
-
-	return(0);
-}	/* SkI2cInit */
-
-
-#ifndef SK_DIAG
-
-/*
- * Interrupt service function for the I2C Interface
- *
- * Clears the Interrupt source
- *
- * Reads the register and check it for sending a trap.
- *
- * Starts the timer if necessary.
- */
-void SkI2cIsr(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	SK_EVPARA	Para;
-
-	/* Clear I2C IRQ */
-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-
-	Para.Para64 = 0;
-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
-}	/* SkI2cIsr */
-
-
-/*
- * Check this sensors Value against the threshold and send events.
- */
-static void SkI2cCheckSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_SENSOR	*pSen)
-{
-	SK_EVPARA	ParaLocal;
-	SK_BOOL		TooHigh;	/* Is sensor too high? */
-	SK_BOOL		TooLow;		/* Is sensor too low? */
-	SK_U64		CurrTime;	/* Current Time */
-	SK_BOOL		DoTrapSend;	/* We need to send a trap */
-	SK_BOOL		DoErrLog;	/* We need to log the error */
-	SK_BOOL		IsError;	/* We need to log the error */
-
-	/* Check Dummy Reads first */
-	if (pAC->I2c.DummyReads > 0) {
-		pAC->I2c.DummyReads--;
-		return;
-	}
-
-	/* Get the current time */
-	CurrTime = SkOsGetTime(pAC);
-
-	/* Set para to the most useful setting: The current sensor. */
-	ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
-
-	/* Check the Value against the thresholds. First: Error Thresholds */
-	TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
-	TooLow = (pSen->SenValue < pSen->SenThreErrLow);
-		
-	IsError = SK_FALSE;
-	if (TooHigh || TooLow) {
-		/* Error condition is satisfied */
-		DoTrapSend = SK_TRUE;
-		DoErrLog = SK_TRUE;
-
-		/* Now error condition is satisfied */
-		IsError = SK_TRUE;
-
-		if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
-			/* This state is the former one */
-
-			/* So check first whether we have to send a trap */
-			if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
-			    CurrTime) {
-				/*
-				 * Do NOT send the Trap. The hold back time
-				 * has to run out first.
-				 */
-				DoTrapSend = SK_FALSE;
-			}
-
-			/* Check now whether we have to log an Error */
-			if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
-			    CurrTime) {
-				/*
-				 * Do NOT log the error. The hold back time
-				 * has to run out first.
-				 */
-				DoErrLog = SK_FALSE;
-			}
-		}
-		else {
-			/* We came from a different state -> Set Begin Time Stamp */
-			pSen->SenBegErrTS = CurrTime;
-			pSen->SenErrFlag = SK_SEN_ERR_ERR;
-		}
-
-		if (DoTrapSend) {
-			/* Set current Time */
-			pSen->SenLastErrTrapTS = CurrTime;
-			pSen->SenErrCts++;
-
-			/* Queue PNMI Event */
-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
-				SK_PNMI_EVT_SEN_ERR_UPP :
-				SK_PNMI_EVT_SEN_ERR_LOW),
-				ParaLocal);
-		}
-
-		if (DoErrLog) {
-			/* Set current Time */
-			pSen->SenLastErrLogTS = CurrTime;
-
-			if (pSen->SenType == SK_SEN_TEMP) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
-			}
-			else if (pSen->SenType == SK_SEN_VOLT) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
-			}
-			else {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
-			}
-		}
-	}
-
-	/* Check the Value against the thresholds */
-	/* 2nd: Warning thresholds */
-	TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
-	TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
-		
-	if (!IsError && (TooHigh || TooLow)) {
-		/* Error condition is satisfied */
-		DoTrapSend = SK_TRUE;
-		DoErrLog = SK_TRUE;
-
-		if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
-			/* This state is the former one */
-
-			/* So check first whether we have to send a trap */
-			if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
-				/*
-				 * Do NOT send the Trap. The hold back time
-				 * has to run out first.
-				 */
-				DoTrapSend = SK_FALSE;
-			}
-
-			/* Check now whether we have to log an Error */
-			if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
-				/*
-				 * Do NOT log the error. The hold back time
-				 * has to run out first.
-				 */
-				DoErrLog = SK_FALSE;
-			}
-		}
-		else {
-			/* We came from a different state -> Set Begin Time Stamp */
-			pSen->SenBegWarnTS = CurrTime;
-			pSen->SenErrFlag = SK_SEN_ERR_WARN;
-		}
-
-		if (DoTrapSend) {
-			/* Set current Time */
-			pSen->SenLastWarnTrapTS = CurrTime;
-			pSen->SenWarnCts++;
-
-			/* Queue PNMI Event */
-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
-				SK_PNMI_EVT_SEN_WAR_UPP :
-				SK_PNMI_EVT_SEN_WAR_LOW),
-				ParaLocal);
-		}
-
-		if (DoErrLog) {
-			/* Set current Time */
-			pSen->SenLastWarnLogTS = CurrTime;
-
-			if (pSen->SenType == SK_SEN_TEMP) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
-			}
-			else if (pSen->SenType == SK_SEN_VOLT) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
-			}
-			else {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
-			}
-		}
-	}
-
-	/* Check for NO error at all */
-	if (!IsError && !TooHigh && !TooLow) {
-		/* Set o.k. Status if no error and no warning condition */
-		pSen->SenErrFlag = SK_SEN_ERR_OK;
-	}
-
-	/* End of check against the thresholds */
-
-	/* Bug fix AF: 16.Aug.2001: Correct the init base
-	 * of LM80 sensor.
-	 */
-	if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
-
-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
-		if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
-			/* 5V PCI-IO Voltage */
-			pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
-			pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
-		}
-		else {
-			/* 3.3V PCI-IO Voltage */
-			pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
-			pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
-		}
-	}
-	
-#ifdef TEST_ONLY
-    /* Dynamic thresholds also for VAUX of LM80 sensor */
-	if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
-
-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
-		/* 3.3V VAUX Voltage */
-		if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
-			pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
-			pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
-		}
-		/* 0V VAUX Voltage */
-		else {
-			pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
-			pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
-		}
-	}
-
-	/*
-	 * Check initialization state:
-	 * The VIO Thresholds need adaption
-	 */
-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
-	     pSen->SenValue > SK_SEN_WARNLOW2C &&
-	     pSen->SenValue < SK_SEN_WARNHIGH2) {
-		pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
-		pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
-		pSen->SenInit = SK_TRUE;
-	}
-
-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
-	     pSen->SenValue > SK_SEN_WARNLOW2 &&
-	     pSen->SenValue < SK_SEN_WARNHIGH2C) {
-		pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
-		pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
-		pSen->SenInit = SK_TRUE;
-	}
-#endif
-
-	if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
-	}
-}	/* SkI2cCheckSensor */
-
-
-/*
- * The only Event to be served is the timeout event
- *
- */
-int	SkI2cEvent(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Module specific Event */
-SK_EVPARA	Para)	/* Event specific Parameter */
-{
-	int			ReadComplete;
-	SK_SENSOR	*pSen;
-	SK_U32		Time;
-	SK_EVPARA	ParaLocal;
-	int			i;
-
-	/* New case: no sensors */
-	if (pAC->I2c.MaxSens == 0) {
-		return(0);
-	}
-
-	switch (Event) {
-	case SK_I2CEV_IRQ:
-		pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-		ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-		if (ReadComplete) {
-			/* Check sensor against defined thresholds */
-			SkI2cCheckSensor(pAC, pSen);
-
-			/* Increment Current sensor and set appropriate Timeout */
-			pAC->I2c.CurrSens++;
-			if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
-				pAC->I2c.CurrSens = 0;
-				Time = SK_I2C_TIM_LONG;
-			}
-			else {
-				Time = SK_I2C_TIM_SHORT;
-			}
-
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-			
-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-        else {
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-
-            SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-		break;
-	case SK_I2CEV_TIM:
-		if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
-
-			ParaLocal.Para64 = (SK_U64)0;
-			SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
-
-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-			ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-			if (ReadComplete) {
-				/* Check sensor against defined thresholds */
-				SkI2cCheckSensor(pAC, pSen);
-
-				/* Increment Current sensor and set appropriate Timeout */
-				pAC->I2c.CurrSens++;
-				if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
-					pAC->I2c.CurrSens = 0;
-					Time = SK_I2C_TIM_LONG;
-				}
-				else {
-					Time = SK_I2C_TIM_SHORT;
-				}
-
-				/* Start Timer */
-				ParaLocal.Para64 = (SK_U64)0;
-
-				pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
-				SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-					SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-			}
-		}
-		else {
-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-			pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
-			SK_I2C_STOP(IoC);
-
-			/* Increment Current sensor and set appropriate Timeout */
-			pAC->I2c.CurrSens++;
-			if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
-				pAC->I2c.CurrSens = 0;
-				Time = SK_I2C_TIM_LONG;
-			}
-			else {
-				Time = SK_I2C_TIM_SHORT;
-			}
-
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-		break;
-	case SK_I2CEV_CLEAR:
-		for (i = 0; i < SK_MAX_SENSORS; i++) {
-			pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
-			pAC->I2c.SenTable[i].SenErrCts = 0;
-			pAC->I2c.SenTable[i].SenWarnCts = 0;
-			pAC->I2c.SenTable[i].SenBegErrTS = 0;
-			pAC->I2c.SenTable[i].SenBegWarnTS = 0;
-			pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
-		}
-		break;
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
-	}
-
-	return(0);
-}	/* SkI2cEvent*/
-
-#endif /* !SK_DIAG */
diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
deleted file mode 100644
index a204f5b..0000000
--- a/drivers/net/sk98lin/sklm80.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Name:	sklm80.c
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.22 $
- * Date:	$Date: 2003/10/20 09:08:21 $
- * Purpose:	Functions to access Voltage and Temperature Sensor (LM80)
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-	LM80 functions
-*/
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#define	BREAK_OR_WAIT(pAC,IoC,Event)	break
-
-/*
- * read a sensors value (LM80 specific)
- *
- * This function reads a sensors value from the I2C sensor chip LM80.
- * The sensor is defined by its index into the sensors database in the struct
- * pAC points to.
- *
- * Returns	1 if the read is completed
- *		0 if the read must be continued (I2C Bus still allocated)
- */
-int SkLm80ReadSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context needed in level 1 and 2 */
-SK_SENSOR	*pSen)	/* Sensor to be read */
-{
-	SK_I32		Value;
-
-	switch (pSen->SenState) {
-	case SK_SEN_IDLE:
-		/* Send address to ADDR register */
-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
-
-		pSen->SenState = SK_SEN_VALUE ;
-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-	
-	case SK_SEN_VALUE:
-		/* Read value from data register */
-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-		
-		Value &= 0xff; /* only least significant byte is valid */
-
-		/* Do NOT check the Value against the thresholds */
-		/* Checking is done in the calling instance */
-
-		if (pSen->SenType == SK_SEN_VOLT) {
-			/* Voltage sensor */
-			pSen->SenValue = Value * SK_LM80_VT_LSB;
-			pSen->SenState = SK_SEN_IDLE ;
-			return(1);
-		}
-
-		if (pSen->SenType == SK_SEN_FAN) {
-			if (Value != 0 && Value != 0xff) {
-				/* Fan speed counter */
-				pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
-			}
-			else {
-				/* Indicate Fan error */
-				pSen->SenValue = 0;
-			}
-			pSen->SenState = SK_SEN_IDLE ;
-			return(1);
-		}
-
-		/* First: correct the value: it might be negative */
-		if ((Value & 0x80) != 0) {
-			/* Value is negative */
-			Value = Value - 256;
-		}
-
-		/* We have a temperature sensor and need to get the signed extension.
-		 * For now we get the extension from the last reading, so in the normal
-		 * case we won't see flickering temperatures.
-		 */
-		pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
-			(pSen->SenValue % SK_LM80_TEMP_LSB);
-
-		/* Send address to ADDR register */
-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-
-		pSen->SenState = SK_SEN_VALEXT ;
-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-	
-	case SK_SEN_VALEXT:
-		/* Read value from data register */
-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-		Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
-
-		/* cut the LSB bit */
-		pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
-			SK_LM80_TEMP_LSB);
-
-		if (pSen->SenValue < 0) {
-			/* Value negative: The bit value must be subtracted */
-			pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
-		}
-		else {
-			/* Value positive: The bit value must be added */
-			pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
-		}
-
-		pSen->SenState = SK_SEN_IDLE ;
-		return(1);
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
-		return(1);
-	}
-
-	/* Not completed */
-	return(0);
-}
-
diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
deleted file mode 100644
index 0275b4f..0000000
--- a/drivers/net/sk98lin/skqueue.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name:	skqueue.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.20 $
- * Date:	$Date: 2003/09/16 13:44:00 $
- * Purpose:	Management of an event queue.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skqueue.h"		/* Queue Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	Event queue management.
-
-	General Description:
-
- */
-intro()
-{}
-#endif
-
-#define PRINTF(a,b,c)
-
-/*
- * init event queue management
- *
- * Must be called during init level 0.
- */
-void	SkEventInit(
-SK_AC	*pAC,	/* Adapter context */
-SK_IOC	Ioc,	/* IO context */
-int		Level)	/* Init level */
-{
-	switch (Level) {
-	case SK_INIT_DATA:
-		pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- * add event to queue
- */
-void	SkEventQueue(
-SK_AC		*pAC,	/* Adapters context */
-SK_U32		Class,	/* Event Class */
-SK_U32		Event,	/* Event to be queued */
-SK_EVPARA	Para)	/* Event parameter */
-{
-	pAC->Event.EvPut->Class = Class;
-	pAC->Event.EvPut->Event = Event;
-	pAC->Event.EvPut->Para = Para;
-	
-	if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
-		pAC->Event.EvPut = pAC->Event.EvQueue;
-
-	if (pAC->Event.EvPut == pAC->Event.EvGet) {
-		SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
-	}
-}
-
-/*
- * event dispatcher
- *	while event queue is not empty
- *		get event from queue
- *		send command to state machine
- *	end
- *	return error reported by individual Event function
- *		0 if no error occured.
- */
-int	SkEventDispatcher(
-SK_AC	*pAC,	/* Adapters Context */
-SK_IOC	Ioc)	/* Io context */
-{
-	SK_EVENTELEM	*pEv;	/* pointer into queue */
-	SK_U32			Class;
-	int			Rtv;
-
-	pEv = pAC->Event.EvGet;
-	
-	PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
-	
-	while (pEv != pAC->Event.EvPut) {
-		PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
-
-		switch (Class = pEv->Class) {
-#ifndef SK_USE_LAC_EV
-#ifndef SK_SLIM
-		case SKGE_RLMT:		/* RLMT Event */
-			Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_I2C:		/* I2C Event */
-			Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_PNMI:		/* PNMI Event */
-			Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif	/* not SK_SLIM */
-#endif	/* not SK_USE_LAC_EV */
-		case SKGE_DRV:		/* Driver Event */
-			Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#ifndef SK_USE_SW_TIMER
-		case SKGE_HWAC:
-			Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#else /* !SK_USE_SW_TIMER */
-        case SKGE_SWT :
-			Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif /* !SK_USE_SW_TIMER */
-#ifdef SK_USE_LAC_EV
-		case SKGE_LACP :
-			Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_RSF :
-			Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_MARKER :
-			Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_FD :
-			Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif /* SK_USE_LAC_EV */
-#ifdef	SK_USE_CSUM
-		case SKGE_CSUM :
-			Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif	/* SK_USE_CSUM */
-		default :
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
-			Rtv = 0;
-		}
-
-		if (Rtv != 0) {
-			return(Rtv);
-		}
-
-		if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
-			pEv = pAC->Event.EvQueue;
-
-		/* Renew get: it is used in queue_events to detect overruns */
-		pAC->Event.EvGet = pEv;
-	}
-
-	return(0);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
deleted file mode 100644
index be8d1cc..0000000
--- a/drivers/net/sk98lin/skrlmt.c
+++ /dev/null
@@ -1,3257 +0,0 @@
-/******************************************************************************
- *
- * Name:	skrlmt.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.69 $
- * Date:	$Date: 2003/04/15 09:39:22 $
- * Purpose:	Manage links on SK-NET Adapters, esp. redundant ones.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
- * It is mainly intended for adapters with more than one link.
- * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef	lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
-#endif	/* !defined(lint) */
-
-#define __SKRLMT_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-#ifndef SK_HWAC_LINK_LED
-#define SK_HWAC_LINK_LED(a,b,c,d)
-#endif	/* !defined(SK_HWAC_LINK_LED) */
-
-#ifndef DEBUG
-#define RLMT_STATIC	static
-#else	/* DEBUG */
-#define RLMT_STATIC
-
-#ifndef SK_LITTLE_ENDIAN
-/* First 32 bits */
-#define OFFS_LO32	1
-
-/* Second 32 bits */
-#define OFFS_HI32	0
-#else	/* SK_LITTLE_ENDIAN */
-/* First 32 bits */
-#define OFFS_LO32	0
-
-/* Second 32 bits */
-#define OFFS_HI32	1
-#endif	/* SK_LITTLE_ENDIAN */
-
-#endif	/* DEBUG */
-
-/* ----- Private timeout values ----- */
-
-#define SK_RLMT_MIN_TO_VAL			   125000	/* 1/8 sec. */
-#define SK_RLMT_DEF_TO_VAL			  1000000	/* 1 sec. */
-#define SK_RLMT_PORTDOWN_TIM_VAL	   900000	/* another 0.9 sec. */
-#define SK_RLMT_PORTSTART_TIM_VAL	   100000	/* 0.1 sec. */
-#define SK_RLMT_PORTUP_TIM_VAL		  2500000	/* 2.5 sec. */
-#define SK_RLMT_SEG_TO_VAL			900000000	/* 15 min. */
-
-/* Assume tick counter increment is 1 - may be set OS-dependent. */
-#ifndef SK_TICK_INCR
-#define SK_TICK_INCR	SK_CONSTU64(1)
-#endif	/* !defined(SK_TICK_INCR) */
-
-/*
- * Amount that a time stamp must be later to be recognized as "substantially
- * later". This is about 1/128 sec, but above 1 tick counter increment.
- */
-#define SK_RLMT_BC_DELTA		(1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
-									(SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
-
-/* ----- Private RLMT defaults ----- */
-
-#define SK_RLMT_DEF_PREF_PORT	0					/* "Lower" port. */
-#define SK_RLMT_DEF_MODE 		SK_RLMT_CHECK_LINK	/* Default RLMT Mode. */
-
-/* ----- Private RLMT checking states ----- */
-
-#define SK_RLMT_RCS_SEG			1		/* RLMT Check State: check seg. */
-#define SK_RLMT_RCS_START_SEG	2		/* RLMT Check State: start check seg. */
-#define SK_RLMT_RCS_SEND_SEG	4		/* RLMT Check State: send BPDU packet */
-#define SK_RLMT_RCS_REPORT_SEG	8		/* RLMT Check State: report seg. */
-
-/* ----- Private PORT checking states ----- */
-
-#define SK_RLMT_PCS_TX			1		/* Port Check State: check tx. */
-#define SK_RLMT_PCS_RX			2		/* Port Check State: check rx. */
-
-/* ----- Private PORT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_PORTSTART_TIM	1100	/* Port start timeout. */
-#define SK_RLMT_PORTUP_TIM		1101	/* Port can now go up. */
-#define SK_RLMT_PORTDOWN_RX_TIM	1102	/* Port did not receive once ... */
-#define SK_RLMT_PORTDOWN		1103	/* Port went down. */
-#define SK_RLMT_PORTDOWN_TX_TIM	1104	/* Partner did not receive ... */
-
-/* ----- Private RLMT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_TIM				2100	/* RLMT timeout. */
-#define SK_RLMT_SEG_TIM			2101	/* RLMT segmentation check timeout. */
-
-#define TO_SHORTEN(tim)	((tim) / 2)
-
-/* Error numbers and messages. */
-#define SKERR_RLMT_E001		(SK_ERRBASE_RLMT + 0)
-#define SKERR_RLMT_E001_MSG	"No Packet."
-#define SKERR_RLMT_E002		(SKERR_RLMT_E001 + 1)
-#define SKERR_RLMT_E002_MSG	"Short Packet."
-#define SKERR_RLMT_E003		(SKERR_RLMT_E002 + 1)
-#define SKERR_RLMT_E003_MSG	"Unknown RLMT event."
-#define SKERR_RLMT_E004		(SKERR_RLMT_E003 + 1)
-#define SKERR_RLMT_E004_MSG	"PortsUp incorrect."
-#define SKERR_RLMT_E005		(SKERR_RLMT_E004 + 1)
-#define SKERR_RLMT_E005_MSG	\
- "Net seems to be segmented (different root bridges are reported on the ports)."
-#define SKERR_RLMT_E006		(SKERR_RLMT_E005 + 1)
-#define SKERR_RLMT_E006_MSG	"Duplicate MAC Address detected."
-#define SKERR_RLMT_E007		(SKERR_RLMT_E006 + 1)
-#define SKERR_RLMT_E007_MSG	"LinksUp incorrect."
-#define SKERR_RLMT_E008		(SKERR_RLMT_E007 + 1)
-#define SKERR_RLMT_E008_MSG	"Port not started but link came up."
-#define SKERR_RLMT_E009		(SKERR_RLMT_E008 + 1)
-#define SKERR_RLMT_E009_MSG	"Corrected illegal setting of Preferred Port."
-#define SKERR_RLMT_E010		(SKERR_RLMT_E009 + 1)
-#define SKERR_RLMT_E010_MSG	"Ignored illegal Preferred Port."
-
-/* LLC field values. */
-#define LLC_COMMAND_RESPONSE_BIT		1
-#define LLC_TEST_COMMAND				0xE3
-#define LLC_UI							0x03
-
-/* RLMT Packet fields. */
-#define	SK_RLMT_DSAP					0
-#define	SK_RLMT_SSAP					0
-#define SK_RLMT_CTRL					(LLC_TEST_COMMAND)
-#define SK_RLMT_INDICATOR0				0x53	/* S */
-#define SK_RLMT_INDICATOR1				0x4B	/* K */
-#define SK_RLMT_INDICATOR2				0x2D	/* - */
-#define SK_RLMT_INDICATOR3				0x52	/* R */
-#define SK_RLMT_INDICATOR4				0x4C	/* L */
-#define SK_RLMT_INDICATOR5				0x4D	/* M */
-#define SK_RLMT_INDICATOR6				0x54	/* T */
-#define SK_RLMT_PACKET_VERSION			0
-
-/* RLMT SPT Flag values. */
-#define	SK_RLMT_SPT_FLAG_CHANGE			0x01
-#define	SK_RLMT_SPT_FLAG_CHANGE_ACK		0x80
-
-/* RLMT SPT Packet fields. */
-#define	SK_RLMT_SPT_DSAP				0x42
-#define	SK_RLMT_SPT_SSAP				0x42
-#define SK_RLMT_SPT_CTRL				(LLC_UI)
-#define	SK_RLMT_SPT_PROTOCOL_ID0		0x00
-#define	SK_RLMT_SPT_PROTOCOL_ID1		0x00
-#define	SK_RLMT_SPT_PROTOCOL_VERSION_ID	0x00
-#define	SK_RLMT_SPT_BPDU_TYPE			0x00
-#define	SK_RLMT_SPT_FLAGS				0x00	/* ?? */
-#define	SK_RLMT_SPT_ROOT_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_ROOT_ID1			0xFF	/* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define	SK_RLMT_SPT_ROOT_PATH_COST0		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST1		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST2		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST3		0x00
-#define	SK_RLMT_SPT_BRIDGE_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_BRIDGE_ID1			0xFF	/* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define	SK_RLMT_SPT_PORT_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_PORT_ID1			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_MSG_AGE0			0x00
-#define	SK_RLMT_SPT_MSG_AGE1			0x00
-#define	SK_RLMT_SPT_MAX_AGE0			0x00
-#define	SK_RLMT_SPT_MAX_AGE1			0xFF
-#define	SK_RLMT_SPT_HELLO_TIME0			0x00
-#define	SK_RLMT_SPT_HELLO_TIME1			0xFF
-#define	SK_RLMT_SPT_FWD_DELAY0			0x00
-#define	SK_RLMT_SPT_FWD_DELAY1			0x40
-
-/* Size defines. */
-#define SK_RLMT_MIN_PACKET_SIZE			34
-#define SK_RLMT_MAX_PACKET_SIZE			(SK_RLMT_MAX_TX_BUF_SIZE)
-#define SK_PACKET_DATA_LEN				(SK_RLMT_MAX_PACKET_SIZE - \
-										SK_RLMT_MIN_PACKET_SIZE)
-
-/* ----- RLMT packet types ----- */
-#define SK_PACKET_ANNOUNCE				1	/* Port announcement. */
-#define SK_PACKET_ALIVE					2	/* Alive packet to port. */
-#define SK_PACKET_ADDR_CHANGED			3	/* Port address changed. */
-#define SK_PACKET_CHECK_TX				4	/* Check your tx line. */
-
-#ifdef SK_LITTLE_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
-	SK_U8	*_Addr = (SK_U8*)(Addr); \
-	SK_U16	_Val = (SK_U16)(Val); \
-	*_Addr++ = (SK_U8)(_Val >> 8); \
-	*_Addr = (SK_U8)(_Val & 0xFF); \
-}
-#endif	/* SK_LITTLE_ENDIAN */
-
-#ifdef SK_BIG_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
-#endif	/* SK_BIG_ENDIAN */
-
-#define AUTONEG_FAILED	SK_FALSE
-#define AUTONEG_SUCCESS	SK_TRUE
-
-
-/* typedefs *******************************************************************/
-
-/* RLMT packet.  Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
-typedef struct s_RlmtPacket {
-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
-	SK_U8	TypeLen[2];
-	SK_U8	DSap;
-	SK_U8	SSap;
-	SK_U8	Ctrl;
-	SK_U8	Indicator[7];
-	SK_U8	RlmtPacketType[2];
-	SK_U8	Align1[2];
-	SK_U8	Random[4];				/* Random value of requesting(!) station. */
-	SK_U8	RlmtPacketVersion[2];	/* RLMT Packet version. */
-	SK_U8	Data[SK_PACKET_DATA_LEN];
-} SK_RLMT_PACKET;
-
-typedef struct s_SpTreeRlmtPacket {
-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
-	SK_U8	TypeLen[2];
-	SK_U8	DSap;
-	SK_U8	SSap;
-	SK_U8	Ctrl;
-	SK_U8	ProtocolId[2];
-	SK_U8	ProtocolVersionId;
-	SK_U8	BpduType;
-	SK_U8	Flags;
-	SK_U8	RootId[8];
-	SK_U8	RootPathCost[4];
-	SK_U8	BridgeId[8];
-	SK_U8	PortId[2];
-	SK_U8	MessageAge[2];
-	SK_U8	MaxAge[2];
-	SK_U8	HelloTime[2];
-	SK_U8	ForwardDelay[2];
-} SK_SPTREE_PACKET;
-
-/* global variables ***********************************************************/
-
-SK_MAC_ADDR	SkRlmtMcAddr =	{{0x01,  0x00,  0x5A,  0x52,  0x4C,  0x4D}};
-SK_MAC_ADDR	BridgeMcAddr =	{{0x01,  0x80,  0xC2,  0x00,  0x00,  0x00}};
-
-/* local variables ************************************************************/
-
-/* None. */
-
-/* functions ******************************************************************/
-
-RLMT_STATIC void	SkRlmtCheckSwitch(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	NetIdx);
-RLMT_STATIC void	SkRlmtCheckSeg(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	NetIdx);
-RLMT_STATIC void	SkRlmtEvtSetNets(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_EVPARA	Para);
-
-/******************************************************************************
- *
- *	SkRlmtInit - initialize data, set state to init
- *
- * Description:
- *
- *	SK_INIT_DATA
- *	============
- *
- *	This routine initializes all RLMT-related variables to a known state.
- *	The initial state is SK_RLMT_RS_INIT.
- *	All ports are initialized to SK_RLMT_PS_INIT.
- *
- *
- *	SK_INIT_IO
- *	==========
- *
- *	Nothing.
- *
- *
- *	SK_INIT_RUN
- *	===========
- *
- *	Determine the adapter's random value.
- *	Set the hw registers, the "logical MAC address", the
- *	RLMT multicast address, and eventually the BPDU multicast address.
- *
- * Context:
- *	init, pageable
- *
- * Returns:
- *	Nothing.
- */
-void	SkRlmtInit(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-int		Level)	/* Initialization Level */
-{
-	SK_U32		i, j;
-	SK_U64		Random;
-	SK_EVPARA	Para;
-    SK_MAC_ADDR		VirtualMacAddress;
-    SK_MAC_ADDR		PhysicalAMacAddress;
-    SK_BOOL		VirtualMacAddressSet;
-    SK_BOOL		PhysicalAMacAddressSet;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
-		("RLMT Init level %d.\n", Level))
-
-	switch (Level) {
-	case SK_INIT_DATA:	/* Initialize data structures. */
-		SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
-
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
-			pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
-			pAC->Rlmt.Port[i].PortDown = SK_TRUE;
-			pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
-			pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
-			pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Port[i].PortNumber = i;
-			pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
-			pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
-		}
-
-		pAC->Rlmt.NumNets = 1;
-		for (i = 0; i < SK_MAX_NETS; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* Automatic. */
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
-		pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
-#if SK_MAX_NETS > 1
-		pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
-#endif	/* SK_MAX_NETS > 1 */
-		break;
-
-	case SK_INIT_IO:	/* GIMacsFound first available here. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
-			("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
-
-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
-		/* Initialize HW registers? */
-		if (pAC->GIni.GIMacsFound == 1) {
-			Para.Para32[0] = SK_RLMT_MODE_CLS;
-			Para.Para32[1] = 0;
-			(void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
-		}
-		break;
-
-	case SK_INIT_RUN:
-		/* Ensure RLMT is set to one net. */
-		if (pAC->Rlmt.NumNets > 1) {
-			Para.Para32[0] = 1;
-			Para.Para32[1] = -1;
-			SkRlmtEvtSetNets(pAC, IoC, Para);
-		}
-
-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-			Random = SkOsGetTime(pAC);
-			*(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
-
-			for (j = 0; j < 4; j++) {
-				pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
-					CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
-			}
-
-			(void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-			
-			/* Add RLMT MC address. */
-			(void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
-			if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
-				/* Add BPDU MC address. */
-				(void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
-			}
-
-			(void)SkAddrMcUpdate(pAC, IoC, i);
-		}
-
-    	VirtualMacAddressSet = SK_FALSE;
-		/* Read virtual MAC address from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			
-            SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
-            VirtualMacAddressSet |= VirtualMacAddress.a[j];
-		}
-    	
-        PhysicalAMacAddressSet = SK_FALSE;
-		/* Read physical MAC address for MAC A from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			
-            SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
-            PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
-		}
-
-        /* check if the two mac addresses contain reasonable values */
-        if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
-
-            pAC->Rlmt.RlmtOff = SK_TRUE;
-        }
-
-        /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
-           and the RLMT_LOOKAHEAD macros */
-        else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
-
-            pAC->Rlmt.RlmtOff = SK_TRUE;
-        }
-		else {
-			pAC->Rlmt.RlmtOff = SK_FALSE;
-		}
-		break;
-
-	default:	/* error */
-		break;
-	}
-	return;
-}	/* SkRlmtInit */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildCheckChain - build the check chain
- *
- * Description:
- *	This routine builds the local check chain:
- *	- Each port that is up checks the next port.
- *	- The last port that is up checks the first port that is up.
- *
- * Notes:
- *	- Currently only local ports are considered when building the chain.
- *	- Currently the SuspectState is just reset;
- *	  it would be better to save it ...
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtBuildCheckChain(
-SK_AC	*pAC,	/* Adapter Context */
-SK_U32	NetIdx)	/* Net Number */
-{
-	SK_U32			i;
-	SK_U32			NumMacsUp;
-	SK_RLMT_PORT *	FirstMacUp;
-	SK_RLMT_PORT *	PrevMacUp;
-
-	FirstMacUp	= NULL;
-	PrevMacUp	= NULL;
-	
-	if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
-		for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
-			pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
-		}
-		return;	/* Done. */
-	}
-			
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SkRlmtBuildCheckChain.\n"))
-
-	NumMacsUp = 0;
-
-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
-		pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
-			~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
-
-		/*
-		 * If more than two links are detected we should consider
-		 * checking at least two other ports:
-		 * 1. the next port that is not LinkDown and
-		 * 2. the next port that is not PortDown.
-		 */
-		if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
-			if (NumMacsUp == 0) {
-				FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
-			}
-			else {
-				PrevMacUp->PortCheck[
-					pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
-					pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
-				PrevMacUp->PortCheck[
-					PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
-				PrevMacUp->PortsChecked++;
-			}
-			PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
-			NumMacsUp++;
-		}
-	}
-
-	if (NumMacsUp > 1) {
-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
-			FirstMacUp->AddrPort->CurrentMacAddress;
-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
-			SK_FALSE;
-		PrevMacUp->PortsChecked++;
-	}
-
-#ifdef DEBUG
-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Port %d checks %d other ports: %2X.\n", i,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
-	}
-#endif	/* DEBUG */
-
-	return;
-}	/* SkRlmtBuildCheckChain */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildPacket - build an RLMT packet
- *
- * Description:
- *	This routine sets up an RLMT packet.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF	*SkRlmtBuildPacket(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* I/O Context */
-SK_U32		PortNumber,	/* Sending port */
-SK_U16		PacketType,	/* RLMT packet type */
-SK_MAC_ADDR	*SrcAddr,	/* Source address */
-SK_MAC_ADDR	*DestAddr)	/* Destination address */
-{
-	int		i;
-	SK_U16		Length;
-	SK_MBUF		*pMb;
-	SK_RLMT_PACKET	*pPacket;
-
-#ifdef DEBUG
-	SK_U8	CheckSrc  = 0;
-	SK_U8	CheckDest = 0;
-	
-	for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
-		CheckSrc  |= SrcAddr->a[i];
-		CheckDest |= DestAddr->a[i];
-	}
-
-	if ((CheckSrc == 0) || (CheckDest == 0)) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
-			("SkRlmtBuildPacket: Invalid %s%saddr.\n",
-			 (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
-	}
-#endif
-
-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
-		pPacket = (SK_RLMT_PACKET*)pMb->pData;
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pPacket->DstAddr[i] = DestAddr->a[i];
-			pPacket->SrcAddr[i] = SrcAddr->a[i];
-		}
-		pPacket->DSap = SK_RLMT_DSAP;
-		pPacket->SSap = SK_RLMT_SSAP;
-		pPacket->Ctrl = SK_RLMT_CTRL;
-		pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
-		pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
-		pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
-		pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
-		pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
-		pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
-		pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
-
-		SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
-
-		for (i = 0; i < 4; i++) {
-			pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
-		}
-		
-		SK_U16_TO_NETWORK_ORDER(
-			SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
-
-		for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
-			pPacket->Data[i] = 0x00;
-		}
-
-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
-		pMb->Length = Length;
-		pMb->PortIdx = PortNumber;
-		Length -= 14;
-		SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
-
-		if (PacketType == SK_PACKET_ALIVE) {
-			pAC->Rlmt.Port[PortNumber].TxHelloCts++;
-		}
-	}
-
-	return (pMb);
-}	/* SkRlmtBuildPacket */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildSpanningTreePacket - build spanning tree check packet
- *
- * Description:
- *	This routine sets up a BPDU packet for spanning tree check.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF	*SkRlmtBuildSpanningTreePacket(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Sending port */
-{
-	unsigned			i;
-	SK_U16				Length;
-	SK_MBUF				*pMb;
-	SK_SPTREE_PACKET	*pSPacket;
-
-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
-		NULL) {
-		pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
-			pSPacket->SrcAddr[i] =
-				pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
-		}
-		pSPacket->DSap = SK_RLMT_SPT_DSAP;
-		pSPacket->SSap = SK_RLMT_SPT_SSAP;
-		pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
-
-		pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
-		pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
-		pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
-		pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
-		pSPacket->Flags = SK_RLMT_SPT_FLAGS;
-		pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
-		pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
-		pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
-		pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
-		pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
-		pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
-		pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
-		pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
-
-		/*
-		 * Use logical MAC address as bridge ID and filter these packets
-		 * on receive.
-		 */
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
-				pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
-					CurrentMacAddress.a[i];
-		}
-		pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
-		pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
-		pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
-		pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
-		pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
-		pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
-		pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
-		pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
-		pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
-		pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
-
-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
-		pMb->Length = Length;
-		pMb->PortIdx = PortNumber;
-		Length -= 14;
-		SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
-
-		pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
-	}
-
-	return (pMb);
-}	/* SkRlmtBuildSpanningTreePacket */
-
-
-/******************************************************************************
- *
- *	SkRlmtSend - build and send check packets
- *
- * Description:
- *	Depending on the RLMT state and the checking state, several packets
- *	are sent through the indicated port.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtSend(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Sending port */
-{
-	unsigned	j;
-	SK_EVPARA	Para;
-	SK_RLMT_PORT	*pRPort;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-	if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
-		if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
-			/* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-				&SkRlmtMcAddr)) != NULL) {
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-		}
-		else {
-			/*
-			 * Send a directed RLMT packet to all ports that are
-			 * checked by the indicated port.
-			 */
-			for (j = 0; j < pRPort->PortsChecked; j++) {
-				if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-					SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-					&pRPort->PortCheck[j].CheckAddr)) != NULL) {
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-				}
-			}
-		}
-	}
-
-	if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
-		(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
-		/*
-		 * Send a BPDU packet to make a connected switch tell us
-		 * the correct root bridge.
-		 */
-		if ((Para.pParaPtr =
-			SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
-			pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
-			pRPort->RootIdSet = SK_FALSE;
-
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
-				("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
-		}
-	}
-	return;
-}	/* SkRlmtSend */
-
-
-/******************************************************************************
- *
- *	SkRlmtPortReceives - check if port is (going) down and bring it up
- *
- * Description:
- *	This routine checks if a port who received a non-BPDU packet
- *	needs to go up or needs to be stopped going down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtPortReceives(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	PortNumber)		/* Port to check */
-{
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-	pRPort->PortNoRx = SK_FALSE;
-
-	if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
-		!(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
-		/*
-		 * Port is marked down (rx), but received a non-BPDU packet.
-		 * Bring it up.
-		 */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Received on PortDown.\n"))
-
-		pRPort->PortState = SK_RLMT_PS_GOING_UP;
-		pRPort->GuTimeStamp = SkOsGetTime(pAC);
-		Para.Para32[0] = PortNumber;
-		Para.Para32[1] = (SK_U32)-1;
-		SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
-			SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-	}	/* PortDown && !SuspectTx */
-	else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Stop bringing port down.\n"))
-		SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-	}	/* PortGoingDown */
-
-	return;
-}	/* SkRlmtPortReceives */
-
-
-/******************************************************************************
- *
- *	SkRlmtPacketReceive - receive a packet for closer examination
- *
- * Description:
- *	This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtPacketReceive(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_MBUF	*pMb)	/* Received packet */
-{
-#ifdef xDEBUG
-	extern	void DumpData(char *p, int size);
-#endif	/* DEBUG */
-	int					i;
-	unsigned			j;
-	SK_U16				PacketType;
-	SK_U32				PortNumber;
-	SK_ADDR_PORT		*pAPort;
-	SK_RLMT_PORT		*pRPort;
-	SK_RLMT_PACKET		*pRPacket;
-	SK_SPTREE_PACKET	*pSPacket;
-	SK_EVPARA			Para;
-
-	PortNumber	= pMb->PortIdx;
-	pAPort = &pAC->Addr.Port[PortNumber];
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-		("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
-
-	pRPacket = (SK_RLMT_PACKET*)pMb->pData;
-	pSPacket = (SK_SPTREE_PACKET*)pRPacket;
-
-#ifdef xDEBUG
-	DumpData((char *)pRPacket, 32);
-#endif	/* DEBUG */
-
-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
-		SkRlmtPortReceives(pAC, IoC, PortNumber);
-	}
-	
-	/* Check destination address. */
-
-	if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
-		!SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
-		!SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
-
-		/* Not sent to current MAC or registered MC address => Trash it. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Not for me.\n"))
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		return;
-	}
-	else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
-
-		/*
-		 * Was sent by same port (may happen during port switching
-		 * or in case of duplicate MAC addresses).
-		 */
-
-		/*
-		 * Check for duplicate address here:
-		 * If Packet.Random != My.Random => DupAddr.
-		 */
-		for (i = 3; i >= 0; i--) {
-			if (pRPort->Random[i] != pRPacket->Random[i]) {
-				break;
-			}
-		}
-
-		/*
-		 * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
-		 * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
-		 * pRPacket->SSap).
-		 */
-		if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
-			pRPacket->Ctrl == SK_RLMT_CTRL &&
-			pRPacket->SSap == SK_RLMT_SSAP &&
-			pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
-			pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
-			pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
-			pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
-			pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
-			pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
-			pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
-
-			/* Error Log entry. */
-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
-		}
-		else {
-			/* Simply trash it. */
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Sent by me.\n"))
-		}
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		return;
-	}
-
-	/* Check SuspectTx entries. */
-	if (pRPort->PortsSuspect > 0) {
-		for (j = 0; j < pRPort->PortsChecked; j++) {
-			if (pRPort->PortCheck[j].SuspectTx &&
-				SK_ADDR_EQUAL(
-					pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
-				pRPort->PortCheck[j].SuspectTx = SK_FALSE;
-				pRPort->PortsSuspect--;
-				break;
-			}
-		}
-	}
-
-	/* Determine type of packet. */
-	if (pRPacket->DSap == SK_RLMT_DSAP &&
-		pRPacket->Ctrl == SK_RLMT_CTRL &&
-		(pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
-		pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
-		pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
-		pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
-		pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
-		pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
-		pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
-		pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-
-		/* It's an RLMT packet. */
-		PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
-			pRPacket->RlmtPacketType[1]);
-
-		switch (PacketType) {
-		case SK_PACKET_ANNOUNCE:	/* Not yet used. */
-#if 0
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC);
-#endif	/* 0 */
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Announce.\n"))
-
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			break;
-
-		case SK_PACKET_ALIVE:
-			if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-					("SkRlmtPacketReceive: Alive Reply.\n"))
-
-				if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
-					SK_ADDR_EQUAL(
-						pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
-					/* Obviously we could send something. */
-					if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
-						pRPort->CheckingState &=  ~SK_RLMT_PCS_TX;
-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-					}
-
-					if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
-						!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
-						pRPort->PortState = SK_RLMT_PS_GOING_UP;
-						pRPort->GuTimeStamp = SkOsGetTime(pAC);
-
-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-						Para.Para32[0] = PortNumber;
-						Para.Para32[1] = (SK_U32)-1;
-						SkTimerStart(pAC, IoC, &pRPort->UpTimer,
-							SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
-							SK_RLMT_PORTUP_TIM, Para);
-					}
-				}
-
-				/* Mark sending port as alive? */
-				SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			}
-			else {	/* Alive Request Packet. */
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-					("SkRlmtPacketReceive: Alive Request.\n"))
-
-				pRPort->RxHelloCts++;
-
-				/* Answer. */
-				for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-					pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
-					pRPacket->SrcAddr[i] =
-						pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
-				}
-				pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
-
-				Para.pParaPtr = pMb;
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-			break;
-
-		case SK_PACKET_CHECK_TX:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Check your tx line.\n"))
-
-			/* A port checking us requests us to check our tx line. */
-			pRPort->CheckingState |= SK_RLMT_PCS_TX;
-
-			/* Start PortDownTx timer. */
-			Para.Para32[0] = PortNumber;
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
-				SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
-				SK_RLMT_PORTDOWN_TX_TIM, Para);
-
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-
-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-				&SkRlmtMcAddr)) != NULL) {
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-			break;
-
-		case SK_PACKET_ADDR_CHANGED:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Address Change.\n"))
-
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
-
-			/* RA;:;: ??? */
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		}
-	}
-	else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
-		pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
-		(pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: BPDU Packet.\n"))
-
-		/* Spanning Tree packet. */
-		pRPort->RxSpHelloCts++;
-
-		if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
-			Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
-			/*
-			 * Check segmentation if a new root bridge is set and
-			 * the segmentation check is not currently running.
-			 */
-			if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
-				(pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
-				(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
-				!= 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
-				SK_RLMT_RCS_SEG) == 0) {
-				pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
-					SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
-			}
-
-			/* Store tree view of this port. */
-			for (i = 0; i < 8; i++) {
-				pRPort->Root.Id[i] = pSPacket->RootId[i];
-			}
-			pRPort->RootIdSet = SK_TRUE;
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
-				("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-					PortNumber,
-					pRPort->Root.Id[0], pRPort->Root.Id[1],
-					pRPort->Root.Id[2], pRPort->Root.Id[3],
-					pRPort->Root.Id[4], pRPort->Root.Id[5],
-					pRPort->Root.Id[6], pRPort->Root.Id[7]))
-		}
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
-			SK_RLMT_RCS_REPORT_SEG) != 0) {
-			SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
-		}
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Unknown Packet Type.\n"))
-
-		/* Unknown packet. */
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-	}
-	return;
-}	/* SkRlmtPacketReceive */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckPort - check if a port works
- *
- * Description:
- *	This routine checks if a port whose link is up received something
- *	and if it seems to transmit successfully.
- *
- *	# PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
- *	# PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
- *	# RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
- *
- *	if (Rx - RxBpdu == 0) {	# No rx.
- *		if (state == PsUp) {
- *			PortCheckingState |= ChkRx
- *		}
- *		if (ModeCheckSeg && (Timeout ==
- *			TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
- *			RlmtCheckingState |= ChkSeg)
- *			PortCheckingState |= ChkSeg
- *		}
- *		NewTimeout = TO_SHORTEN(Timeout)
- *		if (NewTimeout < RLMT_MIN_TIMEOUT) {
- *			NewTimeout = RLMT_MIN_TIMEOUT
- *			PortState = PsDown
- *			...
- *		}
- *	}
- *	else {	# something was received
- *		# Set counter to 0 at LinkDown?
- *		#   No - rx may be reported after LinkDown ???
- *		PortCheckingState &= ~ChkRx
- *		NewTimeout = RLMT_DEFAULT_TIMEOUT
- *		if (RxAck == 0) {
- *			possible reasons:
- *			is my tx line bad? --
- *				send RLMT multicast and report
- *				back internally? (only possible
- *				between ports on same adapter)
- *		}
- *		if (RxChk == 0) {
- *			possible reasons:
- *			- tx line of port set to check me
- *			  maybe bad
- *			- no other port/adapter available or set
- *			  to check me
- *			- adapter checking me has a longer
- *			  timeout
- *			??? anything that can be done here?
- *		}
- *	}
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	New timeout value.
- */
-RLMT_STATIC SK_U32	SkRlmtCheckPort(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Port to check */
-{
-	unsigned		i;
-	SK_U32			NewTimeout;
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-
-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
-				PortNumber, pRPort->PacketsPerTimeSlot))
-
-		/*
-		 * Check segmentation if there was no receive at least twice
-		 * in a row (PortNoRx is already set) and the segmentation
-		 * check is not currently running.
-		 */
-
-		if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
-			(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
-			!(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
-			pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
-				SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
-		}
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
-				pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
-
-		if (pRPort->PortState != SK_RLMT_PS_DOWN) {
-			NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
-			if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
-				NewTimeout = SK_RLMT_MIN_TO_VAL;
-			}
-
-			if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
-				Para.Para32[0] = PortNumber;
-				pRPort->CheckingState |= SK_RLMT_PCS_RX;
-
-				/*
-				 * What shall we do if the port checked by this one receives
-				 * our request frames?  What's bad - our rx line or his tx line?
-				 */
-				Para.Para32[1] = (SK_U32)-1;
-				SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
-					SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
-					SK_RLMT_PORTDOWN_RX_TIM, Para);
-
-				for (i = 0; i < pRPort->PortsChecked; i++) {
-					if (pRPort->PortCheck[i].SuspectTx) {
-						continue;
-					}
-					pRPort->PortCheck[i].SuspectTx = SK_TRUE;
-					pRPort->PortsSuspect++;
-					if ((Para.pParaPtr =
-						SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
-							&pAC->Addr.Port[PortNumber].CurrentMacAddress,
-							&pRPort->PortCheck[i].CheckAddr)) != NULL) {
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-					}
-				}
-			}
-		}
-		else {	/* PortDown -- or all partners suspect. */
-			NewTimeout = SK_RLMT_DEF_TO_VAL;
-		}
-		pRPort->PortNoRx = SK_TRUE;
-	}
-	else {	/* A non-BPDU packet was received. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
-				PortNumber,
-				pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
-				pRPort->PacketsPerTimeSlot))
-		
-		SkRlmtPortReceives(pAC, IoC, PortNumber);
-		if (pAC->Rlmt.CheckSwitch) {
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-
-		NewTimeout = SK_RLMT_DEF_TO_VAL;
-	}
-
-	return (NewTimeout);
-}	/* SkRlmtCheckPort */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
- *
- * Description:
- *	This routine selects the port that received a broadcast frame
- *	substantially later than all other ports.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectBcRx(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	Active,		/* Active port */
-SK_U32	PrefPort,	/* Preferred port */
-SK_U32	*pSelect)	/* New active port */
-{
-	SK_U64		BcTimeStamp;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	BcTimeStamp = 0;	/* Not totally necessary, but feeling better. */
-	PortFound = SK_FALSE;
-	
-	/* Select port with the latest TimeStamp. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
-				i,
-   				pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
-
-		if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
-			if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
-				BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
-				*pSelect = i;
-				PortFound = SK_TRUE;
-			}
-		}
-	}
-
-	if (PortFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Port %d received the last broadcast.\n", *pSelect))
-
-		/* Look if another port's time stamp is similar. */
-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-			if (i == *pSelect) {
-				continue;
-			}
-			if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
-				(pAC->Rlmt.Port[i].BcTimeStamp >
-				 BcTimeStamp - SK_RLMT_BC_DELTA ||
-				pAC->Rlmt.Port[i].BcTimeStamp +
-				 SK_RLMT_BC_DELTA > BcTimeStamp)) {
-				PortFound = SK_FALSE;
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-					("Port %d received a broadcast at a similar time.\n", i))
-				break;
-			}
-		}
-	}
-
-#ifdef DEBUG
-	if (PortFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
-			 "latest broadcast (%u).\n",
-				*pSelect,
-				BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
-	}
-#endif	/* DEBUG */
-
-	return (PortFound);
-}	/* SkRlmtSelectBcRx */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
- *
- * Description:
- *	This routine selects a good port (it is PortUp && !SuspectRx).
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectNotSuspect(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	Active,		/* Active port */
-SK_U32	PrefPort,	/* Preferred port */
-SK_U32	*pSelect)	/* New active port */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortUp && !SuspectRx. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (!pAC->Rlmt.Port[i].PortDown &&
-			!(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
-			*pSelect = i;
-			if (!pAC->Rlmt.Port[Active].PortDown &&
-				!(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
-				*pSelect = Active;
-			}
-			if (!pAC->Rlmt.Port[PrefPort].PortDown &&
-				!(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
-					*pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectNotSuspect */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
- *
- * Description:
- *	This routine selects a port that is up.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectUp(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortUp. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			*pSelect = i;
-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
-				*pSelect = Active;
-			}
-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
- *
- * Description:
- *	This routine selects the port that is going up for the longest time.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectGoingUp(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U64		GuTimeStamp;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	GuTimeStamp = 0;
-	PortFound = SK_FALSE;
-
-	/* Select port that is PortGoingUp for the longest time. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
-			*pSelect = i;
-			PortFound = SK_TRUE;
-			break;
-		}
-	}
-
-	if (!PortFound) {
-		return (SK_FALSE);
-	}
-
-	for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
-			pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
-			*pSelect = i;
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
-	return (SK_TRUE);
-}	/* SkRlmtSelectGoingUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
- *
- * Description:
- *	This routine selects a port that is down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectDown(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortDown. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			*pSelect = i;
-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
-				*pSelect = Active;
-			}
-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectDown */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckSwitch - select new active port and switch to it
- *
- * Description:
- *	This routine decides which port should be the active one and queues
- *	port switching if necessary.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtCheckSwitch(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_U32	NetIdx)	/* Net index */
-{
-	SK_EVPARA	Para;
-	SK_U32		Active;
-	SK_U32		PrefPort;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	Active = pAC->Rlmt.Net[NetIdx].ActivePort;	/* Index of active port. */
-	PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort;	/* Index of preferred port. */
-	PortFound = SK_FALSE;
-	pAC->Rlmt.CheckSwitch = SK_FALSE;
-
-#if 0	/* RW 2001/10/18 - active port becomes always prefered one */
-	if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
-		/* disable auto-fail back */
-		PrefPort = Active;
-	}
-#endif
-
-	if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
-		/* Last link went down - shut down the net. */
-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
-		Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
-		Para.Para32[1] = NetIdx;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
-
-		Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-			Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
-		Para.Para32[1] = NetIdx;
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
-		return;
-	}	/* pAC->Rlmt.LinksUp == 0 */
-	else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
-		pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
-		/* First link came up - get the net up. */
-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
-
-		/*
-		 * If pAC->Rlmt.ActivePort != Para.Para32[0],
-		 * the DRV switches to the port that came up.
-		 */
-		for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-			if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
-				if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
-					i = Active;
-				}
-				if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
-					i = PrefPort;
-				}
-				PortFound = SK_TRUE;
-				break;
-			}
-		}
-
-		if (PortFound) {
-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
-			Para.Para32[1] = NetIdx;
-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-
-			pAC->Rlmt.Net[NetIdx].ActivePort = i;
-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
-			Para.Para32[1] = NetIdx;
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
-
-			if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-				(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
-				SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
-				CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
-				/*
-				 * Send announce packet to RLMT multicast address to force
-				 * switches to learn the new location of the logical MAC address.
-				 */
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
-		}
-
-		return;
-	}	/* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
-	else {	/* Cannot be reached in dual-net mode. */
-		Para.Para32[0] = Active;
-
-		/*
-		 * Preselection:
-		 *	If RLMT Mode != CheckLinkState
-		 *		select port that received a broadcast frame substantially later
-		 *		than all other ports
-		 *	else select first port that is not SuspectRx
-		 *	else select first port that is PortUp
-		 *	else select port that is PortGoingUp for the longest time
-		 *	else select first port that is PortDown
-		 *	else stop.
-		 *
-		 * For the preselected port:
-		 *	If ActivePort is equal in quality, select ActivePort.
-		 *
-		 *	If PrefPort is equal in quality, select PrefPort.
-		 *
-		 *	If ActivePort != SelectedPort,
-		 *		If old ActivePort is LinkDown,
-		 *			SwitchHard
-		 *		else
-		 *			SwitchSoft
-		 */
-		/* check of ChgBcPrio flag added */
-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
-			(!pAC->Rlmt.Net[0].ChgBcPrio)) {
-			
-			if (!PortFound) {
-				PortFound = SkRlmtSelectBcRx(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectNotSuspect(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		/* with changed priority for last broadcast received */
-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
-			(pAC->Rlmt.Net[0].ChgBcPrio)) {
-			if (!PortFound) {
-				PortFound = SkRlmtSelectNotSuspect(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectBcRx(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectGoingUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectGoingUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-		}
-
-		if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
-			if (!PortFound) {
-				PortFound = SkRlmtSelectDown(pAC, IoC,
-					Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectDown(pAC, IoC,
-					Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		if (PortFound) {
-
-			if (Para.Para32[1] != Active) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-					("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
-				pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-					Port[Para.Para32[0]]->PortNumber;
-				Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
-					Port[Para.Para32[1]]->PortNumber;
-				SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
-				if (pAC->Rlmt.Port[Active].LinkDown) {
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
-				}
-				else {
-					SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
-				}
-				Para.Para32[1] = NetIdx;
-				Para.Para32[0] =
-					pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-					Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-				if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-					(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
-					SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
-					&SkRlmtMcAddr)) != NULL) {
-					/*
-					 * Send announce packet to RLMT multicast address to force
-					 * switches to learn the new location of the logical
-					 * MAC address.
-					 */
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-				}	/* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
-			}	/* Para.Para32[1] != Active */
-		}	/* PortFound */
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
-		}
-	}	/* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
-	return;
-}	/* SkRlmtCheckSwitch */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckSeg - Report if segmentation is detected
- *
- * Description:
- *	This routine checks if the ports see different root bridges and reports
- *	segmentation in such a case.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtCheckSeg(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_U32	NetIdx)	/* Net number */
-{
-	SK_EVPARA	Para;
-	SK_RLMT_NET	*pNet;
-	SK_U32		i, j;
-	SK_BOOL		Equal;
-
-	pNet = &pAC->Rlmt.Net[NetIdx];
-	pNet->RootIdSet = SK_FALSE;
-	Equal = SK_TRUE;
-
-	for (i = 0; i < pNet->NumPorts; i++) {
-		if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
-			continue;
-		}
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
-			("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
-				pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
-				pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
-				pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
-				pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
-
-		if (!pNet->RootIdSet) {
-			pNet->Root = pNet->Port[i]->Root;
-			pNet->RootIdSet = SK_TRUE;
-			continue;
-		}
-
-		for (j = 0; j < 8; j ++) {
-			Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
-			if (!Equal) {
-				break;
-			}
-		}
-		
-		if (!Equal) {
-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
-			Para.Para32[0] = NetIdx;
-			Para.Para32[1] = (SK_U32)-1;
-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
-
-			pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
-
-			/* 2000-03-06 RA: New. */
-			Para.Para32[0] = NetIdx;
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
-				SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-			break;
-		}
-	}	/* for (i = 0; i < pNet->NumPorts; i++) */
-
-	/* 2000-03-06 RA: Moved here. */
-	/* Segmentation check not running anymore. */
-	pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
-
-}	/* SkRlmtCheckSeg */
-
-
-/******************************************************************************
- *
- *	SkRlmtPortStart - initialize port variables and start port
- *
- * Description:
- *	This routine initializes a port's variables and issues a PORT_START
- *	to the HWAC module.  This handles retries if the start fails or the
- *	link eventually goes down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtPortStart(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Port number */
-{
-	SK_EVPARA	Para;
-
-	pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
-	pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].CheckingState = 0;
-	pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
-	Para.Para32[0] = PortNumber;
-	Para.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-}	/* SkRlmtPortStart */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortStartTim - PORT_START_TIM
- *
- * Description:
- *	This routine handles PORT_START_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortStartTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_U32			i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
-
-		if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
-		return;
-	}
-
-	/*
-	 * Used to start non-preferred ports if the preferred one
-	 * does not come up.
-	 * This timeout needs only be set when starting the first
-	 * (preferred) port.
-	 */
-	if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
-		/* PORT_START failed. */
-		for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
-			if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
-				SkRlmtPortStart(pAC, IoC,
-					pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
-			}
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
-}	/* SkRlmtEvtPortStartTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtLinkUp - LINK_UP
- *
- * Description:
- *	This routine handles LLINK_UP events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtLinkUp(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
-{
-	SK_U32			i;
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (!pRPort->PortStarted) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_LINK_UP Event EMPTY.\n"))
-		return;
-	}
-
-	if (!pRPort->LinkDown) {
-		/* RA;:;: Any better solution? */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_LINK_UP Event EMPTY.\n"))
-		return;
-	}
-
-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-	/* Do something if timer already fired? */
-
-	pRPort->LinkDown = SK_FALSE;
-	pRPort->PortState = SK_RLMT_PS_GOING_UP;
-	pRPort->GuTimeStamp = SkOsGetTime(pAC);
-	pRPort->BcTimeStamp = 0;
-	pRPort->Net->LinksUp++;
-	if (pRPort->Net->LinksUp == 1) {
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
-	}
-	else {
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
-	}
-
-	for (i = 0; i < pRPort->Net->NumPorts; i++) {
-		if (!pRPort->Net->Port[i]->PortStarted) {
-			SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
-		}
-	}
-
-	SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-
-	if (pRPort->Net->LinksUp >= 2) {
-		if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-		}
-	}
-
-	/* If the first link comes up, start the periodical RLMT timeout. */
-	if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
-		Para2.Para32[0] = pRPort->Net->NetNumber;
-		Para2.Para32[1] = (SK_U32)-1;
-		SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
-			pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
-	}
-
-	Para2 = Para;
-	Para2.Para32[1] = (SK_U32)-1;
-	SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
-		SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
-	
-	/* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
-	if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
-		(Para2.pParaPtr =
-			SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
-			&pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
-		) != NULL) {
-		/* Send "new" packet to RLMT multicast address. */
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-	}
-
-	if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
-		if ((Para2.pParaPtr =
-			SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
-			pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
-			pRPort->Net->CheckingState |=
-				SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_UP Event END.\n"))
-}	/* SkRlmtEvtLinkUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortUpTim - PORT_UP_TIM
- *
- * Description:
- *	This routine handles PORT_UP_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortUpTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
-		return;
-	}
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
-		return;
-	}
-
-	pRPort->PortDown = SK_FALSE;
-	pRPort->PortState = SK_RLMT_PS_UP;
-	pRPort->Net->PortsUp++;
-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
-		if (pAC->Rlmt.NumNets <= 1) {
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTUP_TIM Event END.\n"))
-}	/* SkRlmtEvtPortUpTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortDownTim - PORT_DOWN_*
- *
- * Description:
- *	This routine handles PORT_DOWN_* events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortDownX(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Event code */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
-			Para.Para32[0], Event))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
-		return;
-	}
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
-		!(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
-		return;
-	}
-	
-	/* Stop port's timers. */
-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-	if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
-		pRPort->PortState = SK_RLMT_PS_DOWN;
-	}
-
-	if (!pRPort->PortDown) {
-		pRPort->Net->PortsUp--;
-		pRPort->PortDown = SK_TRUE;
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
-	}
-
-	pRPort->PacketsPerTimeSlot = 0;
-	/* pRPort->DataPacketsPerTimeSlot = 0; */
-	pRPort->BpduPacketsPerTimeSlot = 0;
-	pRPort->BcTimeStamp = 0;
-
-	/*
-	 * RA;:;: To be checked:
-	 * - actions at RLMT_STOP: We should not switch anymore.
-	 */
-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
-		if (Para.Para32[0] ==
-			pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
-			/* Active Port went down. */
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
-}	/* SkRlmtEvtPortDownX */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtLinkDown - LINK_DOWN
- *
- * Description:
- *	This routine handles LINK_DOWN events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtLinkDown(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
-		pRPort->Net->LinksUp--;
-		pRPort->LinkDown = SK_TRUE;
-		pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
-
-		if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-		}
-
-		/* Ensure that port is marked down. */
-		Para.Para32[1] = -1;
-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_DOWN Event END.\n"))
-}	/* SkRlmtEvtLinkDown */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortAddr - PORT_ADDR
- *
- * Description:
- *	This routine handles PORT_ADDR events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortAddr(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_U32			i, j;
-	SK_RLMT_PORT	*pRPort;
-	SK_MAC_ADDR		*pOldMacAddr;
-	SK_MAC_ADDR		*pNewMacAddr;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
-		return;
-	}
-
-	/* Port's physical MAC address changed. */
-	pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
-	pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
-
-	/*
-	 * NOTE: This is not scalable for solutions where ports are
-	 *	 checked remotely.  There, we need to send an RLMT
-	 *	 address change packet - and how do we ensure delivery?
-	 */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		pRPort = &pAC->Rlmt.Port[i];
-		for (j = 0; j < pRPort->PortsChecked; j++) {
-			if (SK_ADDR_EQUAL(
-				pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
-				pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
-			}
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORT_ADDR Event END.\n"))
-}	/* SkRlmtEvtPortAddr */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStart - START
- *
- * Description:
- *	This routine handles START events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStart(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_EVPARA	Para2;
-	SK_U32		PortIdx;
-	SK_U32		PortNumber;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("All nets should have been started.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
-		pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
-
-		/* Change PrefPort to internal default. */
-		Para2.Para32[0] = 0xFFFFFFFF;
-		Para2.Para32[1] = Para.Para32[0];
-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
-	}
-
-	PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
-	PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
-
-	pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
-
-	/* Start preferred port. */
-	SkRlmtPortStart(pAC, IoC, PortNumber);
-
-	/* Start Timer (for first port only). */
-	Para2.Para32[0] = PortNumber;
-	Para2.Para32[1] = (SK_U32)-1;
-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
-		SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
-
-	pAC->Rlmt.NetsStarted++;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event END.\n"))
-}	/* SkRlmtEvtStart */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStop - STOP
- *
- * Description:
- *	This routine handles STOP events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStop(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_EVPARA	Para2;
-	SK_U32		PortNumber;
-	SK_U32		i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.NetsStarted == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("All nets are stopped.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	/* Stop RLMT timers. */
-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
-
-	/* Stop net. */
-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
-	pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
-	Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
-	Para2.Para32[1] = Para.Para32[0];			/* Net# */
-	SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
-
-	/* Stop ports. */
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
-		if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
-
-			pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
-			pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
-			Para2.Para32[0] = PortNumber;
-			Para2.Para32[1] = (SK_U32)-1;
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
-		}
-	}
-
-	pAC->Rlmt.NetsStarted--;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STOP Event END.\n"))
-}	/* SkRlmtEvtStop */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtTim - TIM
- *
- * Description:
- *	This routine handles TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-	SK_U32			Timeout;
-	SK_U32			NewTimeout;
-	SK_U32			PortNumber;
-	SK_U32			i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_TIM Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_TIM Event EMPTY.\n"))
-		return;
-	}
-
-	if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
-		pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
-		/* Mode changed or all links down: No more link checking. */
-		return;
-	}
-
-#if 0
-	pAC->Rlmt.SwitchCheckCounter--;
-	if (pAC->Rlmt.SwitchCheckCounter == 0) {
-		pAC->Rlmt.SwitchCheckCounter;
-	}
-#endif	/* 0 */
-
-	NewTimeout = SK_RLMT_DEF_TO_VAL;
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
-		pRPort = &pAC->Rlmt.Port[PortNumber];
-		if (!pRPort->LinkDown) {
-			Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
-			if (Timeout < NewTimeout) {
-				NewTimeout = Timeout;
-			}
-
-			/*
-			 * These counters should be set to 0 for all ports before the
-			 * first frame is sent in the next loop.
-			 */
-			pRPort->PacketsPerTimeSlot = 0;
-			/* pRPort->DataPacketsPerTimeSlot = 0; */
-			pRPort->BpduPacketsPerTimeSlot = 0;
-		}
-	}
-	pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
-		/*
-		 * If checking remote ports, also send packets if
-		 *   (LinksUp == 1) &&
-		 *   this port checks at least one (remote) port.
-		 */
-
-		/*
-		 * Must be new loop, as SkRlmtCheckPort can request to
-		 * check segmentation when e.g. checking the last port.
-		 */
-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-			if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
-				SkRlmtSend(pAC, IoC,
-					pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
-			}
-		}
-	}
-
-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
-		pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
-		Para);
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
-		(pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
-		(pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
-		SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
-			SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
-			SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_TIM Event END.\n"))
-}	/* SkRlmtEvtTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtSegTim - SEG_TIM
- *
- * Description:
- *	This routine handles SEG_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtSegTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-#ifdef xDEBUG
-	int j;
-#endif	/* DEBUG */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SEG_TIM Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SEG_TIM Event EMPTY.\n"))
-		return;
-	}
-
-#ifdef xDEBUG
-	for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
-		SK_ADDR_PORT	*pAPort;
-		SK_U32			k;
-		SK_U16			*InAddr;
-		SK_U8			InAddr8[6];
-
-		InAddr = (SK_U16 *)&InAddr8[0];
-		pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
-		for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
-			/* Get exact match address k from port j. */
-			XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
-				XM_EXM(k), InAddr);
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x --  %02x %02x %02x %02x %02x %02x.\n",
-					k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
-					InAddr8[0], InAddr8[1], InAddr8[2],
-					InAddr8[3], InAddr8[4], InAddr8[5],
-					pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
-					pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
-					pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
-		}
-	}
-#endif	/* xDEBUG */
-				
-	SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SEG_TIM Event END.\n"))
-}	/* SkRlmtEvtSegTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPacketRx - PACKET_RECEIVED
- *
- * Description:
- *	This routine handles PACKET_RECEIVED events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPacketRx(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_MBUF *pMb */
-{
-	SK_MBUF	*pMb;
-	SK_MBUF	*pNextMb;
-	SK_U32	NetNumber;
-
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
-
-	/* Should we ignore frames during port switching? */
-
-#ifdef DEBUG
-	pMb = Para.pParaPtr;
-	if (pMb == NULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
-	}
-	else if (pMb->pNext != NULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("More than one mbuf or pMb->pNext not set.\n"))
-	}
-#endif	/* DEBUG */
-
-	for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
-		pNextMb = pMb->pNext;
-		pMb->pNext = NULL;
-
-		NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
-		if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		}
-		else {
-			SkRlmtPacketReceive(pAC, IoC, pMb);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PACKET_RECEIVED Event END.\n"))
-}	/* SkRlmtEvtPacketRx */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStatsClear - STATS_CLEAR
- *
- * Description:
- *	This routine handles STATS_CLEAR events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStatsClear(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_U32			i;
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
-		return;
-	}
-
-	/* Clear statistics for logical and physical ports. */
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		pRPort =
-			&pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
-		pRPort->TxHelloCts = 0;
-		pRPort->RxHelloCts = 0;
-		pRPort->TxSpHelloReqCts = 0;
-		pRPort->RxSpHelloCts = 0;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_CLEAR Event END.\n"))
-}	/* SkRlmtEvtStatsClear */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStatsUpdate - STATS_UPDATE
- *
- * Description:
- *	This routine handles STATS_UPDATE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStatsUpdate(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
-		return;
-	}
-
-	/* Update statistics - currently always up-to-date. */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_UPDATE Event END.\n"))
-}	/* SkRlmtEvtStatsUpdate */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPrefportChange - PREFPORT_CHANGE
- *
- * Description:
- *	This routine handles PREFPORT_CHANGE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPrefportChange(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortIndex; SK_U32 NetNumber */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[1]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	/* 0xFFFFFFFF == auto-mode. */
-	if (Para.Para32[0] == 0xFFFFFFFF) {
-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
-	}
-	else {
-		if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
-			return;
-		}
-
-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
-	}
-
-	pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
-
-	if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
-		SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
-}	/* SkRlmtEvtPrefportChange */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtSetNets - SET_NETS
- *
- * Description:
- *	This routine handles SET_NETS events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtSetNets(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NumNets; SK_U32 -1 */
-{
-	int i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SET_NETS Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
-		Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad number of nets: %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == pAC->Rlmt.NumNets) {	/* No change. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	/* Entering and leaving dual mode only allowed while nets are stopped. */
-	if (pAC->Rlmt.NetsStarted > 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Changing dual mode only allowed while all nets are stopped.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == 1) {
-		if (pAC->Rlmt.NumNets > 1) {
-			/* Clear logical MAC addr from second net's active port. */
-			(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
-				Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
-			pAC->Rlmt.Net[1].NumPorts = 0;
-		}
-
-		pAC->Rlmt.NumNets = Para.Para32[0];
-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("RLMT: Changed to one net with two ports.\n"))
-	}
-	else if (Para.Para32[0] == 2) {
-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
-		pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
-		pAC->Rlmt.Net[0].NumPorts =
-			pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
-		
-		pAC->Rlmt.NumNets = Para.Para32[0];
-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		/* Set logical MAC addr on second net's active port. */
-		(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
-			Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
-
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("RLMT: Changed to two nets with one port each.\n"))
-	}
-	else {
-		/* Not implemented for more than two nets. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SetNets not implemented for more than two nets.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SET_NETS Event END.\n"))
-}	/* SkRlmtSetNets */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtModeChange - MODE_CHANGE
- *
- * Description:
- *	This routine handles MODE_CHANGE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtModeChange(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NewMode; SK_U32 NetNumber */
-{
-	SK_EVPARA	Para2;
-	SK_U32		i;
-	SK_U32		PrevRlmtMode;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
-
-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[1]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	Para.Para32[0] |= SK_RLMT_CHECK_LINK;
-
-	if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
-		Para.Para32[0] != SK_RLMT_MODE_CLS) {
-		pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Forced RLMT mode to CLS on single port net.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	/* Update RLMT mode. */
-	PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
-	pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
-
-	if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
-		/* SK_RLMT_CHECK_LOC_LINK bit changed. */
-		if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
-			pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
-			pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
-			/* 20001207 RA: Was "PortsUp == 1". */
-			Para2.Para32[0] = Para.Para32[1];
-			Para2.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
-				pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
-				SKGE_RLMT, SK_RLMT_TIM, Para2);
-		}
-	}
-
-	if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
-		/* SK_RLMT_CHECK_SEG bit changed. */
-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
-			(void)SkAddrMcClear(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-				SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-
-			/* Add RLMT MC address. */
-			(void)SkAddrMcAdd(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-				&SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
-			if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
-				SK_RLMT_CHECK_SEG) != 0) {
-				/* Add BPDU MC address. */
-				(void)SkAddrMcAdd(pAC, IoC,
-					pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-					&BridgeMcAddr, SK_ADDR_PERMANENT);
-
-				if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
-					if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
-						(Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
-						pAC, IoC, i)) != NULL) {
-						pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
-							SK_FALSE;
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-					}
-				}
-			}
-			(void)SkAddrMcUpdate(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
-		}	/* for ... */
-
-		if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
-			Para2.Para32[0] = Para.Para32[1];
-			Para2.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
-		}
-	}	/* SK_RLMT_CHECK_SEG bit changed. */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event END.\n"))
-}	/* SkRlmtEvtModeChange */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvent - a PORT- or an RLMT-specific event happened
- *
- * Description:
- *	This routine calls subroutines to handle PORT- and RLMT-specific events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	0
- */
-int	SkRlmtEvent(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Event code */
-SK_EVPARA	Para)	/* Event-specific parameter */
-{
-	switch (Event) {
-	
-	/* ----- PORT events ----- */
-
-	case SK_RLMT_PORTSTART_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortStartTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_LINK_UP:		/* From SIRQ. */
-		SkRlmtEvtLinkUp(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORTUP_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortUpTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORTDOWN:			/* From RLMT. */
-	case SK_RLMT_PORTDOWN_RX_TIM:	/* From RLMT via TIME. */
-	case SK_RLMT_PORTDOWN_TX_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
-		break;
-	case SK_RLMT_LINK_DOWN:		/* From SIRQ. */
-		SkRlmtEvtLinkDown(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORT_ADDR:		/* From ADDR. */
-		SkRlmtEvtPortAddr(pAC, IoC, Para);
-		break;
-
-	/* ----- RLMT events ----- */
-
-	case SK_RLMT_START:		/* From DRV. */
-		SkRlmtEvtStart(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STOP:		/* From DRV. */
-		SkRlmtEvtStop(pAC, IoC, Para);
-		break;
-	case SK_RLMT_TIM:		/* From RLMT via TIME. */
-		SkRlmtEvtTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_SEG_TIM:
-		SkRlmtEvtSegTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PACKET_RECEIVED:	/* From DRV. */
-		SkRlmtEvtPacketRx(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STATS_CLEAR:	/* From PNMI. */
-		SkRlmtEvtStatsClear(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STATS_UPDATE:	/* From PNMI. */
-		SkRlmtEvtStatsUpdate(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PREFPORT_CHANGE:	/* From PNMI. */
-		SkRlmtEvtPrefportChange(pAC, IoC, Para);
-		break;
-	case SK_RLMT_MODE_CHANGE:	/* From PNMI. */
-		SkRlmtEvtModeChange(pAC, IoC, Para);
-		break;
-	case SK_RLMT_SET_NETS:	/* From DRV. */
-		SkRlmtEvtSetNets(pAC, IoC, Para);
-		break;
-
-	/* ----- Unknown events ----- */
-
-	default:	/* Create error log entry. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Unknown RLMT Event %d.\n", Event))
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
-		break;
-	}	/* switch() */
-
-	return (0);
-}	/* SkRlmtEvent */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
deleted file mode 100644
index 4e46295..0000000
--- a/drivers/net/sk98lin/sktimer.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktimer.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/09/16 13:46:51 $
- * Purpose:	High level timer functions.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	Event queue management.
-
-	General Description:
-
- */
-intro()
-{}
-#endif
-
-
-/* Forward declaration */
-static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
-
-
-/*
- * Inits the software timer
- *
- * needs to be called during Init level 1.
- */
-void	SkTimerInit(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc,		/* IoContext */
-int		Level)		/* Init Level */
-{
-	switch (Level) {
-	case SK_INIT_DATA:
-		pAC->Tim.StQueue = NULL;
-		break;
-	case SK_INIT_IO:
-		SkHwtInit(pAC, Ioc);
-		SkTimerDone(pAC, Ioc);
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- * Stops a high level timer
- * - If a timer is not in the queue the function returns normally, too.
- */
-void	SkTimerStop(
-SK_AC		*pAC,		/* Adapters context */
-SK_IOC		Ioc,		/* IoContext */
-SK_TIMER	*pTimer)	/* Timer Pointer to be started */
-{
-	SK_TIMER	**ppTimPrev;
-	SK_TIMER	*pTm;
-
-	/*
-	 * remove timer from queue
-	 */
-	pTimer->TmActive = SK_FALSE;
-	
-	if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
-		SkHwtStop(pAC, Ioc);
-	}
-	
-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
-		ppTimPrev = &pTm->TmNext ) {
-		
-		if (pTm == pTimer) {
-			/*
-			 * Timer found in queue
-			 * - dequeue it and
-			 * - correct delta of the next timer
-			 */
-			*ppTimPrev = pTm->TmNext;
-
-			if (pTm->TmNext) {
-				/* correct delta of next timer in queue */
-				pTm->TmNext->TmDelta += pTm->TmDelta;
-			}
-			return;
-		}
-	}
-}
-
-/*
- * Start a high level software timer
- */
-void	SkTimerStart(
-SK_AC		*pAC,		/* Adapters context */
-SK_IOC		Ioc,		/* IoContext */
-SK_TIMER	*pTimer,	/* Timer Pointer to be started */
-SK_U32		Time,		/* Time value */
-SK_U32		Class,		/* Event Class for this timer */
-SK_U32		Event,		/* Event Value for this timer */
-SK_EVPARA	Para)		/* Event Parameter for this timer */
-{
-	SK_TIMER	**ppTimPrev;
-	SK_TIMER	*pTm;
-	SK_U32		Delta;
-
-	Time /= 16;		/* input is uS, clock ticks are 16uS */
-	
-	if (!Time)
-		Time = 1;
-
-	SkTimerStop(pAC, Ioc, pTimer);
-
-	pTimer->TmClass = Class;
-	pTimer->TmEvent = Event;
-	pTimer->TmPara = Para;
-	pTimer->TmActive = SK_TRUE;
-
-	if (!pAC->Tim.StQueue) {
-		/* First Timer to be started */
-		pAC->Tim.StQueue = pTimer;
-		pTimer->TmNext = NULL;
-		pTimer->TmDelta = Time;
-		
-		SkHwtStart(pAC, Ioc, Time);
-		
-		return;
-	}
-
-	/*
-	 * timer correction
-	 */
-	timer_done(pAC, Ioc, 0);
-
-	/*
-	 * find position in queue
-	 */
-	Delta = 0;
-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
-		ppTimPrev = &pTm->TmNext ) {
-		
-		if (Delta + pTm->TmDelta > Time) {
-			/* Position found */
-			/* Here the timer needs to be inserted. */
-			break;
-		}
-		Delta += pTm->TmDelta;
-	}
-
-	/* insert in queue */
-	*ppTimPrev = pTimer;
-	pTimer->TmNext = pTm;
-	pTimer->TmDelta = Time - Delta;
-
-	if (pTm) {
-		/* There is a next timer
-		 * -> correct its Delta value.
-		 */
-		pTm->TmDelta -= pTimer->TmDelta;
-	}
-
-	/* restart with first */
-	SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-}
-
-
-void	SkTimerDone(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc)		/* IoContext */
-{
-	timer_done(pAC, Ioc, 1);
-}
-
-
-static void	timer_done(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc,		/* IoContext */
-int		Restart)	/* Do we need to restart the Hardware timer ? */
-{
-	SK_U32		Delta;
-	SK_TIMER	*pTm;
-	SK_TIMER	*pTComp;	/* Timer completed now now */
-	SK_TIMER	**ppLast;	/* Next field of Last timer to be deq */
-	int		Done = 0;
-
-	Delta = SkHwtRead(pAC, Ioc);
-	
-	ppLast = &pAC->Tim.StQueue;
-	pTm = pAC->Tim.StQueue;
-	while (pTm && !Done) {
-		if (Delta >= pTm->TmDelta) {
-			/* Timer ran out */
-			pTm->TmActive = SK_FALSE;
-			Delta -= pTm->TmDelta;
-			ppLast = &pTm->TmNext;
-			pTm = pTm->TmNext;
-		}
-		else {
-			/* We found the first timer that did not run out */
-			pTm->TmDelta -= Delta;
-			Delta = 0;
-			Done = 1;
-		}
-	}
-	*ppLast = NULL;
-	/*
-	 * pTm points to the first Timer that did not run out.
-	 * StQueue points to the first Timer that run out.
-	 */
-
-	for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
-		SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
-	}
-
-	/* Set head of timer queue to the first timer that did not run out */
-	pAC->Tim.StQueue = pTm;
-
-	if (Restart && pAC->Tim.StQueue) {
-		/* Restart HW timer */
-		SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-	}
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
deleted file mode 100644
index 1e662aa..0000000
--- a/drivers/net/sk98lin/skvpd.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/******************************************************************************
- *
- * Name:	skvpd.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/01/13 10:42:45 $
- * Purpose:	Shared software to read and write VPD data
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2003 SysKonnect GmbH.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-	Please refer skvpd.txt for information how to include this module
- */
-static const char SysKonnectFileId[] =
-	"@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/skdebug.h"
-#include "h/skdrv2nd.h"
-
-/*
- * Static functions
- */
-#ifndef SK_KR_PROTO
-static SK_VPD_PARA	*vpd_find_para(
-	SK_AC	*pAC,
-	const char	*key,
-	SK_VPD_PARA *p);
-#else	/* SK_KR_PROTO */
-static SK_VPD_PARA	*vpd_find_para();
-#endif	/* SK_KR_PROTO */
-
-/*
- * waits for a completion of a VPD transfer
- * The VPD transfer must complete within SK_TICKS_PER_SEC/16
- *
- * returns	0:	success, transfer completes
- *		error	exit(9) with a error message
- */
-static int VpdWait(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-int		event)	/* event to wait for (VPD_READ / VPD_write) completion*/
-{
-	SK_U64	start_time;
-	SK_U16	state;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD wait for %s\n", event?"Write":"Read"));
-	start_time = SkOsGetTime(pAC);
-	do {
-		if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
-
-			/* Bug fix AF: Thu Mar 28 2002
-			 * Do not call: VPD_STOP(pAC, IoC);
-			 * A pending VPD read cycle can not be aborted by writing
-			 * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
-			 * Although the write threshold in the OUR-register protects
-			 * VPD read only space from being overwritten this does not
-			 * protect a VPD read from being `converted` into a VPD write
-			 * operation (on the fly). As a consequence the VPD_STOP would
-			 * delete VPD read only data. In case of any problems with the
-			 * I2C bus we exit the loop here. The I2C read operation can
-			 * not be aborted except by a reset (->LR).
-			 */
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
-				("ERROR:VPD wait timeout\n"));
-			return(1);
-		}
-		
-		VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("state = %x, event %x\n",state,event));
-	} while((int)(state & PCI_VPD_FLAG) == event);
-
-	return(0);
-}
-
-#ifdef SKDIAG
-
-/*
- * Read the dword at address 'addr' from the VPD EEPROM.
- *
- * Needed Time:	MIN 1,3 ms	MAX 2,6 ms
- *
- * Note: The DWord is returned in the endianess of the machine the routine
- *       is running on.
- *
- * Returns the data read.
- */
-SK_U32 VpdReadDWord(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-int		addr)	/* VPD address */
-{
-	SK_U32	Rtv;
-
-	/* start VPD read */
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD read dword at 0x%x\n",addr));
-	addr &= ~VPD_WRITE;		/* ensure the R/W bit is set to read */
-
-	VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
-
-	/* ignore return code here */
-	(void)VpdWait(pAC, IoC, VPD_READ);
-
-	/* Don't swap here, it's a data stream of bytes */
-	Rtv = 0;
-
-	VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD read dword data = 0x%x\n",Rtv));
-	return(Rtv);
-}
-
-#endif	/* SKDIAG */
-
-/*
- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdWriteStream(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		Addr,	/* VPD start address */
-int		Len)	/* number of bytes to read / to write */
-{
-	int		i;
-	int		j;
-	SK_U16	AdrReg;
-	int		Rtv;
-	SK_U8	* pComp;	/* Compare pointer */
-	SK_U8	Data;		/* Input Data for Compare */
-
-	/* Init Compare Pointer */
-	pComp = (SK_U8 *) buf;
-
-	for (i = 0; i < Len; i++, buf++) {
-		if ((i%sizeof(SK_U32)) == 0) {
-			/*
-			 * At the begin of each cycle read the Data Reg
-			 * So it is initialized even if only a few bytes
-			 * are written.
-			 */
-			AdrReg = (SK_U16) Addr;
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				return(i);
-			}
-		}
-
-		/* Write current Byte */
-		VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
-				*(SK_U8*)buf);
-
-		if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
-			/* New Address needs to be written to VPD_ADDR reg */
-			AdrReg = (SK_U16) Addr;
-			Addr += sizeof(SK_U32);
-			AdrReg |= VPD_WRITE;	/* WRITE operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_WRITE);
-			if (Rtv != 0) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-					("Write Timed Out\n"));
-				return(i - (i%sizeof(SK_U32)));
-			}
-
-			/*
-			 * Now re-read to verify
-			 */
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-					("Verify Timed Out\n"));
-				return(i - (i%sizeof(SK_U32)));
-			}
-
-			for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
-				
-				VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
-				
-				if (Data != *pComp) {
-					/* Verify Error */
-					SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-						("WriteStream Verify Error\n"));
-					return(i - (i%sizeof(SK_U32)) + j);
-				}
-			}
-		}
-	}
-
-	return(Len);
-}
-	
-
-/*
- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdReadStream(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		Addr,	/* VPD start address */
-int		Len)	/* number of bytes to read / to write */
-{
-	int		i;
-	SK_U16	AdrReg;
-	int		Rtv;
-
-	for (i = 0; i < Len; i++, buf++) {
-		if ((i%sizeof(SK_U32)) == 0) {
-			/* New Address needs to be written to VPD_ADDR reg */
-			AdrReg = (SK_U16) Addr;
-			Addr += sizeof(SK_U32);
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				return(i);
-			}
-		}
-		VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
-			(SK_U8 *)buf);
-	}
-
-	return(Len);
-}
-
-/*
- *	Read ore writes 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdTransferBlock(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		addr,	/* VPD start address */
-int		len,	/* number of bytes to read / to write */
-int		dir)	/* transfer direction may be VPD_READ or VPD_WRITE */
-{
-	int		Rtv;	/* Return value */
-	int		vpd_rom_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD %s block, addr = 0x%x, len = %d\n",
-		dir ? "write" : "read", addr, len));
-
-	if (len == 0)
-		return(0);
-
-	vpd_rom_size = pAC->vpd.rom_size;
-	
-	if (addr > vpd_rom_size - 4) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Address error: 0x%x, exp. < 0x%x\n",
-			addr, vpd_rom_size - 4));
-		return(0);
-	}
-	
-	if (addr + len > vpd_rom_size) {
-		len = vpd_rom_size - addr;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("Warning: len was cut to %d\n", len));
-	}
-
-	if (dir == VPD_READ) {
-		Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
-	}
-	else {
-		Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
-	}
-
-	return(Rtv);
-}
-
-#ifdef SKDIAG
-
-/*
- *	Read 'len' bytes of VPD data, starting at 'addr'.
- *
- * Returns number of bytes read.
- */
-int VpdReadBlock(
-SK_AC	*pAC,	/* pAC pointer */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* buffer were the data should be stored */
-int		addr,	/* start reading at the VPD address */
-int		len)	/* number of bytes to read */
-{
-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
-}
-
-/*
- *	Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
- *
- * Returns number of bytes writes.
- */
-int VpdWriteBlock(
-SK_AC	*pAC,	/* pAC pointer */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* buffer, holds the data to write */
-int		addr,	/* start writing at the VPD address */
-int		len)	/* number of bytes to write */
-{
-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
-}
-#endif	/* SKDIAG */
-
-/*
- * (re)initialize the VPD buffer
- *
- * Reads the VPD data from the EEPROM into the VPD buffer.
- * Get the remaining read only and read / write space.
- *
- * return	0:	success
- *		1:	fatal VPD error
- */
-static int VpdInit(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	SK_VPD_PARA *r, rp;	/* RW or RV */
-	int		i;
-	unsigned char	x;
-	int		vpd_size;
-	SK_U16	dev_id;
-	SK_U32	our_reg2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
-	
-	VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
-	
-	VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
-	
-	pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
-	
-	/*
-	 * this function might get used before the hardware is initialized
-	 * therefore we cannot always trust in GIChipId
-	 */
-	if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
-		dev_id != VPD_DEV_ID_GENESIS) ||
-		((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
-		!pAC->GIni.GIGenesis)) {
-
-		/* for Yukon the VPD size is always 256 */
-		vpd_size = VPD_SIZE_YUKON;
-	}
-	else {
-		/* Genesis uses the maximum ROM size up to 512 for VPD */
-		if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
-			vpd_size = VPD_SIZE_GENESIS;
-		}
-		else {
-			vpd_size = pAC->vpd.rom_size;
-		}
-	}
-
-	/* read the VPD data into the VPD buffer */
-	if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
-		!= vpd_size) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("Block Read Error\n"));
-		return(1);
-	}
-	
-	pAC->vpd.vpd_size = vpd_size;
-
-	/* Asus K8V Se Deluxe bugfix. Correct VPD content */
-	/* MBo April 2004 */
-	if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
-	    ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
-	    ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
-		printk("sk98lin: Asus mainboard with buggy VPD? "
-				"Correcting data.\n");
-		pAC->vpd.vpd_buf[0x40] = 0x38;
-	}
-
-
-	/* find the end tag of the RO area */
-	if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: RV Tag not found\n"));
-		return(1);
-	}
-	
-	if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: Invalid VPD struct size\n"));
-		return(1);
-	}
-	pAC->vpd.v.vpd_free_ro = r->p_len - 1;
-
-	/* test the checksum */
-	for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
-		x += pAC->vpd.vpd_buf[i];
-	}
-	
-	if (x != 0) {
-		/* checksum error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("VPD Checksum Error\n"));
-		return(1);
-	}
-
-	/* find and check the end tag of the RW area */
-	if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: RV Tag not found\n"));
-		return(1);
-	}
-	
-	if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: Invalid VPD struct size\n"));
-		return(1);
-	}
-	pAC->vpd.v.vpd_free_rw = r->p_len;
-
-	/* everything seems to be ok */
-	if (pAC->GIni.GIChipId != 0) {
-		pAC->vpd.v.vpd_status |= VPD_VALID;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
-		("done. Free RO = %d, Free RW = %d\n",
-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
-	return(0);
-}
-
-/*
- *	find the Keyword 'key' in the VPD buffer and fills the
- *	parameter struct 'p' with it's values
- *
- * returns	*p	success
- *		0:	parameter was not found or VPD encoding error
- */
-static SK_VPD_PARA *vpd_find_para(
-SK_AC		*pAC,	/* common data base */
-const char	*key,	/* keyword to find (e.g. "MN") */
-SK_VPD_PARA *p)		/* parameter description struct */
-{
-	char *v	;	/* points to VPD buffer */
-	int max;	/* Maximum Number of Iterations */
-
-	v = pAC->vpd.vpd_buf;
-	max = 128;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD find para %s .. ",key));
-
-	/* check mandatory resource type ID string (Product Name) */
-	if (*v != (char)RES_ID) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Error: 0x%x missing\n", RES_ID));
-		return NULL;
-	}
-
-	if (strcmp(key, VPD_NAME) == 0) {
-		p->p_len = VPD_GET_RES_LEN(v);
-		p->p_val = VPD_GET_VAL(v);
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("found, len = %d\n", p->p_len));
-		return(p);
-	}
-
-	v += 3 + VPD_GET_RES_LEN(v) + 3;
-	for (;; ) {
-		if (SK_MEMCMP(key,v,2) == 0) {
-			p->p_len = VPD_GET_VPD_LEN(v);
-			p->p_val = VPD_GET_VAL(v);
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("found, len = %d\n",p->p_len));
-			return(p);
-		}
-
-		/* exit when reaching the "RW" Tag or the maximum of itera. */
-		max--;
-		if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
-			break;
-		}
-
-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
-		}
-		else {
-			v += 3 + VPD_GET_VPD_LEN(v);
-		}
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
-	}
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
-	if (max == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Key/Len Encoding error\n"));
-	}
-#endif /* DEBUG */
-	return NULL;
-}
-
-/*
- *	Move 'n' bytes. Begin with the last byte if 'n' is > 0,
- *	Start with the last byte if n is < 0.
- *
- * returns nothing
- */
-static void vpd_move_para(
-char	*start,		/* start of memory block */
-char	*end,		/* end of memory block to move */
-int		n)			/* number of bytes the memory block has to be moved */
-{
-	char *p;
-	int i;		/* number of byte copied */
-
-	if (n == 0)
-		return;
-
-	i = (int) (end - start + 1);
-	if (n < 0) {
-		p = start + n;
-		while (i != 0) {
-			*p++ = *start++;
-			i--;
-		}
-	}
-	else {
-		p = end + n;
-		while (i != 0) {
-			*p-- = *end--;
-			i--;
-		}
-	}
-}
-
-/*
- *	setup the VPD keyword 'key' at 'ip'.
- *
- * returns nothing
- */
-static void vpd_insert_key(
-const char	*key,	/* keyword to insert */
-const char	*buf,	/* buffer with the keyword value */
-int		len,		/* length of the value string */
-char	*ip)		/* inseration point */
-{
-	SK_VPD_KEY *p;
-
-	p = (SK_VPD_KEY *) ip;
-	p->p_key[0] = key[0];
-	p->p_key[1] = key[1];
-	p->p_len = (unsigned char) len;
-	SK_MEMCPY(&p->p_val,buf,len);
-}
-
-/*
- *	Setup the VPD end tag "RV" / "RW".
- *	Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
- *
- * returns	0:	success
- *		1:	encoding error
- */
-static int vpd_mod_endtag(
-SK_AC	*pAC,		/* common data base */
-char	*etp)		/* end pointer input position */
-{
-	SK_VPD_KEY *p;
-	unsigned char	x;
-	int	i;
-	int	vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	p = (SK_VPD_KEY *) etp;
-
-	if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
-		/* something wrong here, encoding error */
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: invalid end tag\n"));
-		return(1);
-	}
-	if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
-		/* create "RW" tag */
-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
-		pAC->vpd.v.vpd_free_rw = (int) p->p_len;
-		i = pAC->vpd.v.vpd_free_rw;
-		etp += 3;
-	}
-	else {
-		/* create "RV" tag */
-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
-		pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
-
-		/* setup checksum */
-		for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
-			x += pAC->vpd.vpd_buf[i];
-		}
-		p->p_val = (char) 0 - x;
-		i = pAC->vpd.v.vpd_free_ro;
-		etp += 4;
-	}
-	while (i) {
-		*etp++ = 0x00;
-		i--;
-	}
-
-	return(0);
-}
-
-/*
- *	Insert a VPD keyword into the VPD buffer.
- *
- *	The keyword 'key' is inserted at the position 'ip' in the
- *	VPD buffer.
- *	The keywords behind the input position will
- *	be moved. The VPD end tag "RV" or "RW" is generated again.
- *
- * returns	0:	success
- *		2:	value string was cut
- *		4:	VPD full, keyword was not written
- *		6:	fatal VPD error
- *
- */
-static int	VpdSetupPara(
-SK_AC	*pAC,		/* common data base */
-const char	*key,	/* keyword to insert */
-const char	*buf,	/* buffer with the keyword value */
-int		len,		/* length of the keyword value */
-int		type,		/* VPD_RO_KEY or VPD_RW_KEY */
-int		op)			/* operation to do: ADD_KEY or OWR_KEY */
-{
-	SK_VPD_PARA vp;
-	char	*etp;		/* end tag position */
-	int	free;		/* remaining space in selected area */
-	char	*ip;		/* input position inside the VPD buffer */
-	int	rtv;		/* return code */
-	int	head;		/* additional haeder bytes to move */
-	int	found;		/* additinoal bytes if the keyword was found */
-	int vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD setup para key = %s, val = %s\n",key,buf));
-	
-	vpd_size = pAC->vpd.vpd_size;
-
-	rtv = 0;
-	ip = NULL;
-	if (type == VPD_RW_KEY) {
-		/* end tag is "RW" */
-		free = pAC->vpd.v.vpd_free_rw;
-		etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
-	}
-	else {
-		/* end tag is "RV" */
-		free = pAC->vpd.v.vpd_free_ro;
-		etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
-	}
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("Free RO = %d, Free RW = %d\n",
-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
-	head = 0;
-	found = 0;
-	if (op == OWR_KEY) {
-		if (vpd_find_para(pAC, key, &vp)) {
-			found = 3;
-			ip = vp.p_val - 3;
-			free += vp.p_len + 3;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("Overwrite Key\n"));
-		}
-		else {
-			op = ADD_KEY;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("Add Key\n"));
-		}
-	}
-	if (op == ADD_KEY) {
-		ip = etp;
-		vp.p_len = 0;
-		head = 3;
-	}
-
-	if (len + 3 > free) {
-		if (free < 7) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD Buffer Overflow, keyword not written\n"));
-			return(4);
-		}
-		/* cut it again */
-		len = free - 3;
-		rtv = 2;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD Buffer Full, Keyword was cut\n"));
-	}
-
-	vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
-	vpd_insert_key(key, buf, len, ip);
-	if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
-		pAC->vpd.v.vpd_status &= ~VPD_VALID;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD Encoding Error\n"));
-		return(6);
-	}
-
-	return(rtv);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done.
- *
- * return:	A pointer to the vpd_status structure. The structure contains
- *		this fields.
- */
-SK_VPD_STATUS *VpdStat(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		(void)VpdInit(pAC, IoC);
-	}
-	return(&pAC->vpd.v);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the VPD
- *	buffer if not already done.
- *	Scan the VPD buffer for VPD keywords and create the VPD
- *	keyword list by copying the keywords to 'buf', all after
- *	each other and terminated with a '\0'.
- *
- * Exceptions:	o The Resource Type ID String (product name) is called "Name"
- *		o The VPD end tags 'RV' and 'RW' are not listed
- *
- *	The number of copied keywords is counted in 'elements'.
- *
- * returns	0:	success
- *		2:	buffer overfull, one or more keywords are missing
- *		6:	fatal VPD error
- *
- *	example values after returning:
- *
- *		buf =	"Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
- *		*len =		30
- *		*elements =	 9
- */
-int VpdKeys(
-SK_AC	*pAC,		/* common data base */
-SK_IOC	IoC,		/* IO Context */
-char	*buf,		/* buffer where to copy the keywords */
-int		*len,		/* buffer length */
-int		*elements)	/* number of keywords returned */
-{
-	char *v;
-	int n;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
-	*elements = 0;
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			*len = 0;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD Init Error, terminated\n"));
-			return(6);
-		}
-	}
-
-	if ((signed)strlen(VPD_NAME) + 1 <= *len) {
-		v = pAC->vpd.vpd_buf;
-		strcpy(buf,VPD_NAME);
-		n = strlen(VPD_NAME) + 1;
-		buf += n;
-		*elements = 1;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-			("'%c%c' ",v[0],v[1]));
-	}
-	else {
-		*len = 0;
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
-			("buffer overflow\n"));
-		return(2);
-	}
-
-	v += 3 + VPD_GET_RES_LEN(v) + 3;
-	for (;; ) {
-		/* exit when reaching the "RW" Tag */
-		if (SK_MEMCMP(VPD_RW,v,2) == 0) {
-			break;
-		}
-
-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
-			continue;
-		}
-
-		if (n+3 <= *len) {
-			SK_MEMCPY(buf,v,2);
-			buf += 2;
-			*buf++ = '\0';
-			n += 3;
-			v += 3 + VPD_GET_VPD_LEN(v);
-			*elements += 1;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-				("'%c%c' ",v[0],v[1]));
-		}
-		else {
-			*len = n;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("buffer overflow\n"));
-			return(2);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
-	*len = n;
-	return(0);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done. Search for the VPD keyword
- *	'key' and copy its value to 'buf'. Add a terminating '\0'.
- *	If the value does not fit into the buffer cut it after
- *	'len' - 1 bytes.
- *
- * returns	0:	success
- *		1:	keyword not found
- *		2:	value string was cut
- *		3:	VPD transfer timeout
- *		6:	fatal VPD error
- */
-int VpdRead(
-SK_AC		*pAC,	/* common data base */
-SK_IOC		IoC,	/* IO Context */
-const char	*key,	/* keyword to read (e.g. "MN") */
-char		*buf,	/* buffer where to copy the keyword value */
-int			*len)	/* buffer length */
-{
-	SK_VPD_PARA *p, vp;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			*len = 0;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
-		if (p->p_len > (*(unsigned *)len)-1) {
-			p->p_len = *len - 1;
-		}
-		SK_MEMCPY(buf, p->p_val, p->p_len);
-		buf[p->p_len] = '\0';
-		*len = p->p_len;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-			("%c%c%c%c.., len = %d\n",
-			buf[0],buf[1],buf[2],buf[3],*len));
-	}
-	else {
-		*len = 0;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
-		return(1);
-	}
-	return(0);
-}
-
-
-/*
- *	Check whether a given key may be written
- *
- * returns
- *	SK_TRUE		Yes it may be written
- *	SK_FALSE	No it may be written
- */
-SK_BOOL VpdMayWrite(
-char	*key)	/* keyword to write (allowed values "Yx", "Vx") */
-{
-	if ((*key != 'Y' && *key != 'V') ||
-		key[1] < '0' || key[1] > 'Z' ||
-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
-		return(SK_FALSE);
-	}
-	return(SK_TRUE);
-}
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the VPD
- *	buffer if not already done. Insert/overwrite the keyword 'key'
- *	in the VPD buffer. Cut the keyword value if it does not fit
- *	into the VPD read / write area.
- *
- * returns	0:	success
- *		2:	value string was cut
- *		3:	VPD transfer timeout
- *		4:	VPD full, keyword was not written
- *		5:	keyword cannot be written
- *		6:	fatal VPD error
- */
-int VpdWrite(
-SK_AC		*pAC,	/* common data base */
-SK_IOC		IoC,	/* IO Context */
-const char	*key,	/* keyword to write (allowed values "Yx", "Vx") */
-const char	*buf)	/* buffer where the keyword value can be read from */
-{
-	int len;		/* length of the keyword to write */
-	int rtv;		/* return code */
-	int rtv2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
-		("VPD write %s = %s\n",key,buf));
-
-	if ((*key != 'Y' && *key != 'V') ||
-		key[1] < '0' || key[1] > 'Z' ||
-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("illegal key tag, keyword not written\n"));
-		return(5);
-	}
-
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	rtv = 0;
-	len = strlen(buf);
-	if (len > VPD_MAX_LEN) {
-		/* cut it */
-		len = VPD_MAX_LEN;
-		rtv = 2;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
-	}
-	if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD write error\n"));
-		return(rtv2);
-	}
-
-	return(rtv);
-}
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done. Remove the VPD keyword
- *	'key' from the VPD buffer.
- *	Only the keywords in the read/write area can be deleted.
- *	Keywords in the read only area cannot be deleted.
- *
- * returns	0:	success, keyword was removed
- *		1:	keyword not found
- *		5:	keyword cannot be deleted
- *		6:	fatal VPD error
- */
-int VpdDelete(
-SK_AC	*pAC,	/* common data base */
-SK_IOC	IoC,	/* IO Context */
-char	*key)	/* keyword to read (e.g. "MN") */
-{
-	SK_VPD_PARA *p, vp;
-	char *etp;
-	int	vpd_size;
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
-		if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
-			/* try to delete read only keyword */
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("cannot delete RO keyword\n"));
-			return(5);
-		}
-
-		etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
-
-		vpd_move_para(vp.p_val+vp.p_len, etp+2,
-			- ((int)(vp.p_len + 3)));
-		if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
-			pAC->vpd.v.vpd_status &= ~VPD_VALID;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD encoding error\n"));
-			return(6);
-		}
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("keyword not found\n"));
-		return(1);
-	}
-
-	return(0);
-}
-
-/*
- *	If the VPD buffer contains valid data write the VPD
- *	read/write area back to the VPD EEPROM.
- *
- * returns	0:	success
- *		3:	VPD transfer timeout
- */
-int VpdUpdate(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	int vpd_size;
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
-		if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
-			vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("transfer timed out\n"));
-			return(3);
-		}
-	}
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
-	return(0);
-}
-
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
deleted file mode 100644
index b4e7502..0000000
--- a/drivers/net/sk98lin/skxmac2.c
+++ /dev/null
@@ -1,4160 +0,0 @@
-/******************************************************************************
- *
- * Name:	skxmac2.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.102 $
- * Date:	$Date: 2003/10/02 16:53:58 $
- * Purpose:	Contains functions to initialize the MACs and PHYs
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* typedefs *******************************************************************/
-
-/* BCOM PHY magic pattern list */
-typedef struct s_PhyHack {
-	int		PhyReg;		/* Phy register */
-	SK_U16	PhyVal;		/* Value to write */
-} BCOM_HACK;
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#ifdef GENESIS
-static BCOM_HACK BcomRegA1Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
- { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
- { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-static BCOM_HACK BcomRegC0Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
- { 0x15, 0x0A04 }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-#endif
-
-/* function prototypes ********************************************************/
-#ifdef GENESIS
-static void	SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
-static int	SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
-#endif /* GENESIS */
-#ifdef YUKON
-static void	SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static void	SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
-static int	SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
-#endif /* OTHER_PHY */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmPhyRead() - Read from XMAC PHY register
- *
- * Description:	reads a 16-bit word from XMAC PHY or ext. PHY
- *
- * Returns:
- *	nothing
- */
-void SkXmPhyRead(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-int		Port,			/* Port Index (MAC_1 + n) */
-int		PhyReg,			/* Register Address (Offset) */
-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
-{
-	SK_U16		Mmu;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* write the PHY register's address */
-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-	
-	/* get the PHY register's value */
-	XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Ready' is set */
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);
-
-		/* get the PHY register's value */
-		XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-	}
-}	/* SkXmPhyRead */
-
-
-/******************************************************************************
- *
- *	SkXmPhyWrite() - Write to XMAC PHY register
- *
- * Description:	writes a 16-bit word to XMAC PHY or ext. PHY
- *
- * Returns:
- *	nothing
- */
-void SkXmPhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	SK_U16		Mmu;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Busy' is cleared */
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
-	}
-	
-	/* write the PHY register's address */
-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-	
-	/* write the PHY register's value */
-	XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Busy' is cleared */
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
-	}
-}	/* SkXmPhyWrite */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmPhyRead() - Read from GPHY register
- *
- * Description:	reads a 16-bit word from GPHY through MDIO
- *
- * Returns:
- *	nothing
- */
-void SkGmPhyRead(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-int		Port,			/* Port Index (MAC_1 + n) */
-int		PhyReg,			/* Register Address (Offset) */
-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
-{
-	SK_U16	Ctrl;
-	SK_GEPORT	*pPrt;
-#ifdef VCPU
-	u_long SimCyle;
-	u_long SimLowTime;
-	
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
-		PhyReg, SimCyle, SimLowTime);
-#endif /* VCPU */
-	
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* set PHY-Register offset and 'Read' OpCode (= 1) */
-	*pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
-		GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
-
-	GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
-
-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-	
-	/* additional check for MDC/MDIO activity */
-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
-		*pVal = 0;
-		return;
-	}
-
-	*pVal |= GM_SMI_CT_BUSY;
-	
-	do {
-#ifdef VCPU
-		VCPUwaitTime(1000);
-#endif /* VCPU */
-
-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
-	/* wait until 'ReadValid' is set */
-	} while (Ctrl == *pVal);
-	
-	/* get the PHY register's value */
-	GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
-
-#ifdef VCPU
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
-		SimCyle, SimLowTime);
-#endif /* VCPU */
-
-}	/* SkGmPhyRead */
-
-
-/******************************************************************************
- *
- *	SkGmPhyWrite() - Write to GPHY register
- *
- * Description:	writes a 16-bit word to GPHY through MDIO
- *
- * Returns:
- *	nothing
- */
-void SkGmPhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	SK_U16	Ctrl;
-	SK_GEPORT	*pPrt;
-#ifdef VCPU
-	SK_U32	DWord;
-	u_long	SimCyle;
-	u_long	SimLowTime;
-	
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
-		PhyReg, Val, SimCyle, SimLowTime);
-#endif /* VCPU */
-	
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* write the PHY register's value */
-	GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
-	
-	/* set PHY-Register offset and 'Write' OpCode (= 0) */
-	Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
-
-	GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
-
-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-	
-	/* additional check for MDC/MDIO activity */
-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
-		return;
-	}
-	
-	Val |= GM_SMI_CT_BUSY;
-
-	do {
-#ifdef VCPU
-		/* read Timer value */
-		SK_IN32(IoC, B2_TI_VAL, &DWord);
-
-		VCPUwaitTime(1000);
-#endif /* VCPU */
-
-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
-	/* wait until 'Busy' is cleared */
-	} while (Ctrl == Val);
-	
-#ifdef VCPU
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
-		SimCyle, SimLowTime);
-#endif /* VCPU */
-
-}	/* SkGmPhyWrite */
-#endif /* YUKON */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkGePhyRead() - Read from PHY register
- *
- * Description:	calls a read PHY routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkGePhyRead(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	*pVal)		/* Pointer to Value */
-{
-	void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
-
-	if (pAC->GIni.GIGenesis) {
-		r_func = SkXmPhyRead;
-	}
-	else {
-		r_func = SkGmPhyRead;
-	}
-	
-	r_func(pAC, IoC, Port, PhyReg, pVal);
-}	/* SkGePhyRead */
-
-
-/******************************************************************************
- *
- *	SkGePhyWrite() - Write to PHY register
- *
- * Description:	calls a write PHY routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkGePhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
-
-	if (pAC->GIni.GIGenesis) {
-		w_func = SkXmPhyWrite;
-	}
-	else {
-		w_func = SkGmPhyWrite;
-	}
-	
-	w_func(pAC, IoC, Port, PhyReg, Val);
-}	/* SkGePhyWrite */
-#endif /* SK_DIAG */
-
-
-/******************************************************************************
- *
- *	SkMacPromiscMode() - Enable / Disable Promiscuous Mode
- *
- * Description:
- *   enables / disables promiscuous mode by setting Mode Register (XMAC) or
- *   Receive Control Register (GMAC) dep. on board type   	
- *
- * Returns:
- *	nothing
- */
-void SkMacPromiscMode(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-#ifdef YUKON
-	SK_U16	RcReg;
-#endif
-#ifdef GENESIS
-	SK_U32	MdReg;
-#endif	
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-		/* enable or disable promiscuous mode */
-		if (Enable) {
-			MdReg |= XM_MD_ENA_PROM;
-		}
-		else {
-			MdReg &= ~XM_MD_ENA_PROM;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-		
-		/* enable or disable unicast and multicast filtering */
-		if (Enable) {
-			RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
-		}
-		else {
-			RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
-		}
-		/* setup Receive Control Register */
-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
-	}
-#endif /* YUKON */
-
-}	/* SkMacPromiscMode*/
-
-
-/******************************************************************************
- *
- *	SkMacHashing() - Enable / Disable Hashing
- *
- * Description:
- *   enables / disables hashing by setting Mode Register (XMAC) or
- *   Receive Control Register (GMAC) dep. on board type		
- *
- * Returns:
- *	nothing
- */
-void SkMacHashing(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-#ifdef YUKON
-	SK_U16	RcReg;
-#endif	
-#ifdef GENESIS
-	SK_U32	MdReg;
-#endif
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-		/* enable or disable hashing */
-		if (Enable) {
-			MdReg |= XM_MD_ENA_HASH;
-		}
-		else {
-			MdReg &= ~XM_MD_ENA_HASH;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-		
-		/* enable or disable multicast filtering */
-		if (Enable) {
-			RcReg |= GM_RXCR_MCF_ENA;
-		}
-		else {
-			RcReg &= ~GM_RXCR_MCF_ENA;
-		}
-		/* setup Receive Control Register */
-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
-	}
-#endif /* YUKON */
-
-}	/* SkMacHashing*/
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
- *
- * Description:
- *	The features
- *	 - FCS stripping,					SK_STRIP_FCS_ON/OFF
- *	 - pad byte stripping,				SK_STRIP_PAD_ON/OFF
- *	 - don't set XMR_FS_ERR in status	SK_LENERR_OK_ON/OFF
- *	   for inrange length error frames
- *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
- *	   for frames > 1514 bytes
- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
- *
- *	for incoming packets may be enabled/disabled by this function.
- *	Additional modes may be added later.
- *	Multiple modes can be enabled/disabled at the same time.
- *	The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- *	nothing
- */
-static void SkXmSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
-	SK_U16	OldRxCmd;
-	SK_U16	RxCmd;
-
-	XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
-
-	RxCmd = OldRxCmd;
-	
-	switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
-	case SK_STRIP_FCS_ON:
-		RxCmd |= XM_RX_STRIP_FCS;
-		break;
-	case SK_STRIP_FCS_OFF:
-		RxCmd &= ~XM_RX_STRIP_FCS;
-		break;
-	}
-
-	switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
-	case SK_STRIP_PAD_ON:
-		RxCmd |= XM_RX_STRIP_PAD;
-		break;
-	case SK_STRIP_PAD_OFF:
-		RxCmd &= ~XM_RX_STRIP_PAD;
-		break;
-	}
-
-	switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
-	case SK_LENERR_OK_ON:
-		RxCmd |= XM_RX_LENERR_OK;
-		break;
-	case SK_LENERR_OK_OFF:
-		RxCmd &= ~XM_RX_LENERR_OK;
-		break;
-	}
-
-	switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
-	case SK_BIG_PK_OK_ON:
-		RxCmd |= XM_RX_BIG_PK_OK;
-		break;
-	case SK_BIG_PK_OK_OFF:
-		RxCmd &= ~XM_RX_BIG_PK_OK;
-		break;
-	}
-
-	switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
-	case SK_SELF_RX_ON:
-		RxCmd |= XM_RX_SELF_RX;
-		break;
-	case SK_SELF_RX_OFF:
-		RxCmd &= ~XM_RX_SELF_RX;
-		break;
-	}
-
-	/* Write the new mode to the Rx command register if required */
-	if (OldRxCmd != RxCmd) {
-		XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
-	}
-}	/* SkXmSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
- *
- * Description:
- *	The features
- *	 - FCS (CRC) stripping,				SK_STRIP_FCS_ON/OFF
- *	 - don't set GMR_FS_LONG_ERR		SK_BIG_PK_OK_ON/OFF
- *	   for frames > 1514 bytes
- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
- *
- *	for incoming packets may be enabled/disabled by this function.
- *	Additional modes may be added later.
- *	Multiple modes can be enabled/disabled at the same time.
- *	The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- *	nothing
- */
-static void SkGmSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
-	SK_U16	OldRxCmd;
-	SK_U16	RxCmd;
-
-	if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
-
-		RxCmd = OldRxCmd;
-
-		if ((Mode & SK_STRIP_FCS_ON) != 0) {
-			RxCmd |= GM_RXCR_CRC_DIS;
-		}
-		else {
-			RxCmd &= ~GM_RXCR_CRC_DIS;
-		}
-		/* Write the new mode to the Rx control register if required */
-		if (OldRxCmd != RxCmd) {
-			GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
-		}
-	}
-
-	if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
-		
-		GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
-
-		RxCmd = OldRxCmd;
-
-		if ((Mode & SK_BIG_PK_OK_ON) != 0) {
-			RxCmd |= GM_SMOD_JUMBO_ENA;
-		}
-		else {
-			RxCmd &= ~GM_SMOD_JUMBO_ENA;
-		}
-		/* Write the new mode to the Rx control register if required */
-		if (OldRxCmd != RxCmd) {
-			GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
-		}
-	}
-}	/* SkGmSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
- *
- * Description:	modifies the MAC's Rx Control reg. dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Rx Mode */
-{
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmSetRxCmd(pAC, IoC, Port, Mode);
-	}
-	else {
-		
-		SkGmSetRxCmd(pAC, IoC, Port, Mode);
-	}
-
-}	/* SkMacSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkMacCrcGener() - Enable / Disable CRC Generation
- *
- * Description:	enables / disables CRC generation dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacCrcGener(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U16	Word;
-
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN16(IoC, Port, XM_TX_CMD, &Word);
-
-		if (Enable) {
-			Word &= ~XM_TX_NO_CRC;
-		}
-		else {
-			Word |= XM_TX_NO_CRC;
-		}
-		/* setup Tx Command Register */
-		XM_OUT16(IoC, Port, XM_TX_CMD, Word);
-	}
-	else {
-		
-		GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
-		
-		if (Enable) {
-			Word &= ~GM_TXCR_CRC_DIS;
-		}
-		else {
-			Word |= GM_TXCR_CRC_DIS;
-		}
-		/* setup Tx Control Register */
-		GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
-	}
-
-}	/* SkMacCrcGener*/
-
-#endif /* SK_DIAG */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmClrExactAddr() - Clear Exact Match Address Registers
- *
- * Description:
- *	All Exact Match Address registers of the XMAC 'Port' will be
- *	cleared starting with 'StartNum' up to (and including) the
- *	Exact Match address number of 'StopNum'.
- *
- * Returns:
- *	nothing
- */
-void SkXmClrExactAddr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		StartNum,	/* Begin with this Address Register Index (0..15) */
-int		StopNum)	/* Stop after finished with this Register Idx (0..15) */
-{
-	int		i;
-	SK_U16	ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
-
-	if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
-		StartNum > StopNum) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
-		return;
-	}
-
-	for (i = StartNum; i <= StopNum; i++) {
-		XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
-	}
-}	/* SkXmClrExactAddr */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
- *
- * Description:
- *	Flush the transmit FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- *	nothing
- */
-void SkMacFlushTxFifo(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	SK_U32	MdReg;
-
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* no way to flush the FIFO we have to issue a reset */
-		/* TBD */
-	}
-#endif /* YUKON */
-
-}	/* SkMacFlushTxFifo */
-
-
-/******************************************************************************
- *
- *	SkMacFlushRxFifo() - Flush the MAC's receive FIFO
- *
- * Description:
- *	Flush the receive FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- *	nothing
- */
-static void SkMacFlushRxFifo(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	SK_U32	MdReg;
-
-	if (pAC->GIni.GIGenesis) {
-
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* no way to flush the FIFO we have to issue a reset */
-		/* TBD */
-	}
-#endif /* YUKON */
-
-}	/* SkMacFlushRxFifo */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmSoftRst() - Do a XMAC software reset
- *
- * Description:
- *	The PHY registers should not be destroyed during this
- *	kind of software reset. Therefore the XMAC Software Reset
- *	(XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
- *
- *	The software reset is done by
- *		- disabling the Rx and Tx state machine,
- *		- resetting the statistics module,
- *		- clear all other significant XMAC Mode,
- *		  Command, and Control Registers
- *		- clearing the Hash Register and the
- *		  Exact Match Address registers, and
- *		- flushing the XMAC's Rx and Tx FIFOs.
- *
- * Note:
- *	Another requirement when stopping the XMAC is to
- *	avoid sending corrupted frames on the network.
- *	Disabling the Tx state machine will NOT interrupt
- *	the currently transmitted frame. But we must take care
- *	that the Tx FIFO is cleared AFTER the current frame
- *	is complete sent to the network.
- *
- *	It takes about 12ns to send a frame with 1538 bytes.
- *	One PCI clock goes at least 15ns (66MHz). Therefore
- *	after reading XM_GP_PORT back, we are sure that the
- *	transmitter is disabled AND idle. And this means
- *	we may flush the transmit FIFO now.
- *
- * Returns:
- *	nothing
- */
-static void SkXmSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-	
-	/* reset the statistics module */
-	XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
-
-	/* disable all XMAC IRQs */
-	XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
-	
-	XM_OUT32(IoC, Port, XM_MODE, 0);		/* clear Mode Reg */
-	
-	XM_OUT16(IoC, Port, XM_TX_CMD, 0);		/* reset TX CMD Reg */
-	XM_OUT16(IoC, Port, XM_RX_CMD, 0);		/* reset RX CMD Reg */
-	
-	/* disable all PHY IRQs */
-	switch (pAC->GIni.GP[Port].PhyType) {
-	case SK_PHY_BCOM:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
-			break;
-		case SK_PHY_NAT:
-			/* todo: National
-			 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
-			break;
-#endif /* OTHER_PHY */
-	}
-
-	/* clear the Hash Register */
-	XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
-
-	/* clear the Exact Match Address registers */
-	SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
-	
-	/* clear the Source Check Address registers */
-	XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
-
-}	/* SkXmSoftRst */
-
-
-/******************************************************************************
- *
- *	SkXmHardRst() - Do a XMAC hardware reset
- *
- * Description:
- *	The XMAC of the specified 'Port' and all connected devices
- *	(PHY and SERDES) will receive a reset signal on its *Reset pins.
- *	External PHYs must be reset by clearing a bit in the GPIO register
- *  (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
- *
- * ATTENTION:
- * 	It is absolutely necessary to reset the SW_RST Bit first
- *	before calling this function.
- *
- * Returns:
- *	nothing
- */
-static void SkXmHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	Reg;
-	int		i;
-	int		TOut;
-	SK_U16	Word;
-
-	for (i = 0; i < 4; i++) {
-		/* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
-		TOut = 0;
-		do {
-			if (TOut++ > 10000) {
-				/*
-				 * Adapter seems to be in RESET state.
-				 * Registers cannot be written.
-				 */
-				return;
-			}
-
-			SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
-			
-			SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
-		
-		} while ((Word & MFF_SET_MAC_RST) == 0);
-	}
-
-	/* For external PHYs there must be special handling */
-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-		
-		SK_IN32(IoC, B2_GP_IO, &Reg);
-		
-		if (Port == 0) {
-			Reg |= GP_DIR_0; 	/* set to output */
-			Reg &= ~GP_IO_0;	/* set PHY reset (active low) */
-		}
-		else {
-			Reg |= GP_DIR_2;	/* set to output */
-			Reg &= ~GP_IO_2;	/* set PHY reset (active low) */
-		}
-		/* reset external PHY */
-		SK_OUT32(IoC, B2_GP_IO, Reg);
-
-		/* short delay */
-		SK_IN32(IoC, B2_GP_IO, &Reg);
-	}
-}	/* SkXmHardRst */
-
-
-/******************************************************************************
- *
- *	SkXmClearRst() - Release the PHY & XMAC reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkXmClearRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-	/* clear HW reset */
-	SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		if (Port == 0) {
-			DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
-		}
-		else {
-			DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
-		}
-		/* Clear PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-
-		/* Enable GMII interface */
-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
-	}
-}	/* SkXmClearRst */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmSoftRst() - Do a GMAC software reset
- *
- * Description:
- *	The GPHY registers should not be destroyed during this
- *	kind of software reset.
- *
- * Returns:
- *	nothing
- */
-static void SkGmSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-	SK_U16  RxCtrl;
-
-	/* reset the statistics module */
-
-	/* disable all GMAC IRQs */
-	SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-	
-	/* disable all PHY IRQs */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-	
-	/* clear the Hash Register */
-	GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
-
-	/* Enable Unicast and Multicast filtering */
-	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
-	
-	GM_OUT16(IoC, Port, GM_RX_CTRL,
-		(SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
-
-}	/* SkGmSoftRst */
-
-
-/******************************************************************************
- *
- *	SkGmHardRst() - Do a GMAC hardware reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkGmHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-	/* WA code for COMA mode */
-	if (pAC->GIni.GIYukonLite &&
-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-		
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		DWord |= (GP_DIR_9 | GP_IO_9);
-
-		/* set PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-	}
-
-	/* set GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
-
-	/* set GMAC Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-
-}	/* SkGmHardRst */
-
-
-/******************************************************************************
- *
- *	SkGmClearRst() - Release the GPHY & GMAC reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkGmClearRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-#ifdef XXX
-		/* clear GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
-
-		/* set GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-#endif /* XXX */
-
-	/* WA code for COMA mode */
-	if (pAC->GIni.GIYukonLite &&
-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-		
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		DWord |= GP_DIR_9;		/* set to output */
-		DWord &= ~GP_IO_9;		/* clear PHY reset (active high) */
-
-		/* clear PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-	}
-
-	/* set HWCFG_MODE */
-	DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
-		GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
-		(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
-		GPC_HWCFG_GMII_FIB);
-
-	/* set GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
-
-	/* release GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
-
-#ifdef VCPU
-	VCpuWait(9000);
-#endif /* VCPU */
-
-	/* clear GMAC Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
-
-#ifdef VCPU
-	VCpuWait(2000);
-	
-	SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
-			
-	SK_IN32(IoC, B0_ISRC, &DWord);
-#endif /* VCPU */
-
-}	/* SkGmClearRst */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- *	SkMacSoftRst() - Do a MAC software reset
- *
- * Description:	calls a MAC software reset routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* disable receiver and transmitter */
-	SkMacRxTxDisable(pAC, IoC, Port);
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmSoftRst(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmSoftRst(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-	/* flush the MAC's Rx and Tx FIFOs */
-	SkMacFlushTxFifo(pAC, IoC, Port);
-	
-	SkMacFlushRxFifo(pAC, IoC, Port);
-
-	pPrt->PState = SK_PRT_STOP;
-
-}	/* SkMacSoftRst */
-
-
-/******************************************************************************
- *
- *	SkMacHardRst() - Do a MAC hardware reset
- *
- * Description:	calls a MAC hardware reset routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmHardRst(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmHardRst(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
-
-}	/* SkMacHardRst */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmInitMac() - Initialize the XMAC II
- *
- * Description:
- *	Initialize the XMAC of the specified port.
- *	The XMAC must be reset or stopped before calling this function.
- *
- * Note:
- *	The XMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	nothing
- */
-void SkXmInitMac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int			i;
-	SK_U16		SWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PState == SK_PRT_STOP) {
-		/* Port State: SK_PRT_STOP */
-		/* Verify that the reset bit is cleared */
-		SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
-
-		if ((SWord & MFF_SET_MAC_RST) != 0) {
-			/* PState does not match HW state */
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
-			/* Correct it */
-			pPrt->PState = SK_PRT_RESET;
-		}
-	}
-
-	if (pPrt->PState == SK_PRT_RESET) {
-
-		SkXmClearRst(pAC, IoC, Port);
-
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			/* read Id from external PHY (all have the same address) */
-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
-
-			/*
-			 * Optimize MDIO transfer by suppressing preamble.
-			 * Must be done AFTER first access to BCOM chip.
-			 */
-			XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
-			
-			XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
-
-			if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
-				/*
-				 * Workaround BCOM Errata for the C0 type.
-				 * Write magic patterns to reserved registers.
-				 */
-				i = 0;
-				while (BcomRegC0Hack[i].PhyReg != 0) {
-					SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
-						BcomRegC0Hack[i].PhyVal);
-					i++;
-				}
-			}
-			else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
-				/*
-				 * Workaround BCOM Errata for the A1 type.
-				 * Write magic patterns to reserved registers.
-				 */
-				i = 0;
-				while (BcomRegA1Hack[i].PhyReg != 0) {
-					SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
-						BcomRegA1Hack[i].PhyVal);
-					i++;
-				}
-			}
-
-			/*
-			 * Workaround BCOM Errata (#10523) for all BCom PHYs.
-			 * Disable Power Management after reset.
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-			
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-				(SK_U16)(SWord | PHY_B_AC_DIS_PM));
-
-			/* PHY LED initialization is done in SkGeXmitLED() */
-		}
-
-		/* Dummy read the Interrupt source register */
-		XM_IN16(IoC, Port, XM_ISRC, &SWord);
-		
-		/*
-		 * The auto-negotiation process starts immediately after
-		 * clearing the reset. The auto-negotiation process should be
-		 * started by the SIRQ, therefore stop it here immediately.
-		 */
-		SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-#ifdef TEST_ONLY
-		/* temp. code: enable signal detect */
-		/* WARNING: do not override GMII setting above */
-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
-#endif
-	}
-
-	/*
-	 * configure the XMACs Station Address
-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
-	 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
-	 */
-	for (i = 0; i < 3; i++) {
-		/*
-		 * The following 2 statements are together endianess
-		 * independent. Remember this when changing.
-		 */
-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-		
-		XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
-	}
-
-	/* Tx Inter Packet Gap (XM_TX_IPG):	use default */
-	/* Tx High Water Mark (XM_TX_HI_WM):	use default */
-	/* Tx Low Water Mark (XM_TX_LO_WM):	use default */
-	/* Host Request Threshold (XM_HT_THR):	use default */
-	/* Rx Request Threshold (XM_RX_THR):	use default */
-	/* Rx Low Water Mark (XM_RX_LO_WM):	use default */
-
-	/* configure Rx High Water Mark (XM_RX_HI_WM) */
-	XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
-
-	/* Configure Tx Request Threshold */
-	SWord = SK_XM_THR_SL;				/* for single port */
-
-	if (pAC->GIni.GIMacsFound > 1) {
-		switch (pAC->GIni.GIPortUsage) {
-		case SK_RED_LINK:
-			SWord = SK_XM_THR_REDL;		/* redundant link */
-			break;
-		case SK_MUL_LINK:
-			SWord = SK_XM_THR_MULL;		/* load balancing */
-			break;
-		case SK_JUMBO_LINK:
-			SWord = SK_XM_THR_JUMBO;	/* jumbo frames */
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
-			break;
-		}
-	}
-	XM_OUT16(IoC, Port, XM_TX_THR, SWord);
-
-	/* setup register defaults for the Tx Command Register */
-	XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
-
-	/* setup register defaults for the Rx Command Register */
-	SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		SWord |= XM_RX_BIG_PK_OK;
-	}
-
-	if (pPrt->PLinkMode == SK_LMODE_HALF) {
-		/*
-		 * If in manual half duplex mode the other side might be in
-		 * full duplex mode, so ignore if a carrier extension is not seen
-		 * on frames received
-		 */
-		SWord |= XM_RX_DIS_CEXT;
-	}
-	
-	XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
-
-	/*
-	 * setup register defaults for the Mode Register
-	 *	- Don't strip error frames to avoid Store & Forward
-	 *	  on the Rx side.
-	 *	- Enable 'Check Station Address' bit
-	 *	- Enable 'Check Address Array' bit
-	 */
-	XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
-
-	/*
-	 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
-	 *	- Enable all bits excepting 'Octets Rx OK Low CntOv'
-	 *	  and 'Octets Rx OK Hi Cnt Ov'.
-	 */
-	XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
-
-	/*
-	 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
-	 *	- Enable all bits excepting 'Octets Tx OK Low CntOv'
-	 *	  and 'Octets Tx OK Hi Cnt Ov'.
-	 */
-	XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
-
-	/*
-	 * Do NOT init XMAC interrupt mask here.
-	 * All interrupts remain disable until link comes up!
-	 */
-
-	/*
-	 * Any additional configuration changes may be done now.
-	 * The last action is to enable the Rx and Tx state machine.
-	 * This should be done after the auto-negotiation process
-	 * has been completed successfully.
-	 */
-}	/* SkXmInitMac */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmInitMac() - Initialize the GMAC
- *
- * Description:
- *	Initialize the GMAC of the specified port.
- *	The GMAC must be reset or stopped before calling this function.
- *
- * Note:
- *	The GMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	nothing
- */
-void SkGmInitMac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int			i;
-	SK_U16		SWord;
-	SK_U32		DWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PState == SK_PRT_STOP) {
-		/* Port State: SK_PRT_STOP */
-		/* Verify that the reset bit is cleared */
-		SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
-		
-		if ((DWord & GMC_RST_SET) != 0) {
-			/* PState does not match HW state */
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
-			/* Correct it */
-			pPrt->PState = SK_PRT_RESET;
-		}
-	}
-
-	if (pPrt->PState == SK_PRT_RESET) {
-		
-		SkGmHardRst(pAC, IoC, Port);
-
-		SkGmClearRst(pAC, IoC, Port);
-		
-		/* Auto-negotiation ? */
-		if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-			/* Auto-negotiation disabled */
-
-			/* get General Purpose Control */
-			GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
-
-			/* disable auto-update for speed, duplex and flow-control */
-			SWord |= GM_GPCR_AU_ALL_DIS;
-			
-			/* setup General Purpose Control Register */
-			GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-			
-			SWord = GM_GPCR_AU_ALL_DIS;
-		}
-		else {
-			SWord = 0;
-		}
-
-		/* speed settings */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-		case SK_LSPEED_1000MBPS:
-			SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
-			break;
-		case SK_LSPEED_100MBPS:
-			SWord |= GM_GPCR_SPEED_100;
-			break;
-		case SK_LSPEED_10MBPS:
-			break;
-		}
-
-		/* duplex settings */
-		if (pPrt->PLinkMode != SK_LMODE_HALF) {
-			/* set full duplex */
-			SWord |= GM_GPCR_DUP_FULL;
-		}
-
-		/* flow-control settings */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			/* set Pause Off */
-			SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
-			/* disable Tx & Rx flow-control */
-			SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			/* disable Rx flow-control */
-			SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-		case SK_FLOW_MODE_SYM_OR_REM:
-			/* enable Tx & Rx flow-control */
-			break;
-		}
-
-		/* setup General Purpose Control Register */
-		GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-
-		/* dummy read the Interrupt Source Register */
-		SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
-		
-#ifndef VCPU
-		/* read Id from PHY */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
-		
-		SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
-#endif /* VCPU */
-	}
-
-	(void)SkGmResetCounter(pAC, IoC, Port);
-
-	/* setup Transmit Control Register */
-	GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
-
-	/* setup Receive Control Register */
-	GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
-		GM_RXCR_CRC_DIS);
-
-	/* setup Transmit Flow Control Register */
-	GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
-
-	/* setup Transmit Parameter Register */
-#ifdef VCPU
-	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
-#endif /* VCPU */
-
-    SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
-			TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
-			TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
-	
-	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
-
-	/* configure the Serial Mode Register */
-#ifdef VCPU
-	GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
-#endif /* VCPU */
-	
-	SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
-
-	if (pPrt->PMacLimit4) {
-		/* reset of collision counter after 4 consecutive collisions */
-		SWord |= GM_SMOD_LIMIT_4;
-	}
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		/* enable jumbo mode (Max. Frame Length = 9018) */
-		SWord |= GM_SMOD_JUMBO_ENA;
-	}
-	
-	GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
-	
-	/*
-	 * configure the GMACs Station Addresses
-	 * in PROM you can find our addresses at:
-	 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
-	 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
-	 */
-
-	for (i = 0; i < 3; i++) {
-		/*
-		 * The following 2 statements are together endianess
-		 * independent. Remember this when changing.
-		 */
-		/* physical address: will be used for pause frames */
-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-
-#ifdef WA_DEV_16
-		/* WA for deviation #16 */
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
-			/* swap the address bytes */
-			SWord = ((SWord & 0xff00) >> 8)	| ((SWord & 0x00ff) << 8);
-
-			/* write to register in reversed order */
-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
-		}
-		else {
-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-		}
-#else		
-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-#endif /* WA_DEV_16 */
-		
-		/* virtual address: will be used for data */
-		SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
-
-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
-		
-		/* reset Multicast filtering Hash registers 1-3 */
-		GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
-	}
-
-	/* reset Multicast filtering Hash register 4 */
-	GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
-
-	/* enable interrupt mask for counter overflows */
-	GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
-	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
-	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
-
-#if defined(SK_DIAG) || defined(DEBUG)
-	/* read General Purpose Status */
-	GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("MAC Stat Reg.=0x%04X\n", SWord));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
-	c_print("MAC Stat Reg=0x%04X\n", SWord);
-#endif /* SK_DIAG */
-
-}	/* SkGmInitMac */
-#endif /* YUKON */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmInitDupMd() - Initialize the XMACs Duplex Mode
- *
- * Description:
- *	This function initializes the XMACs Duplex Mode.
- *	It should be called after successfully finishing
- *	the Auto-negotiation Process
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitDupMd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	switch (pAC->GIni.GP[Port].PLinkModeStatus) {
-	case SK_LMODE_STAT_AUTOHALF:
-	case SK_LMODE_STAT_HALF:
-		/* Configuration Actions for Half Duplex Mode */
-		/*
-		 * XM_BURST = default value. We are probable not quick
-		 * 	enough at the 'XMAC' bus to burst 8kB.
-		 *	The XMAC stops bursting if no transmit frames
-		 *	are available or the burst limit is exceeded.
-		 */
-		/* XM_TX_RT_LIM = default value (15) */
-		/* XM_TX_STIME = default value (0xff = 4096 bit times) */
-		break;
-	case SK_LMODE_STAT_AUTOFULL:
-	case SK_LMODE_STAT_FULL:
-		/* Configuration Actions for Full Duplex Mode */
-		/*
-		 * The duplex mode is configured by the PHY,
-		 * therefore it seems to be that there is nothing
-		 * to do here.
-		 */
-		break;
-	case SK_LMODE_STAT_UNKNOWN:
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
-		break;
-	}
-}	/* SkXmInitDupMd */
-
-
-/******************************************************************************
- *
- *	SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
- *
- * Description:
- *	This function initializes the Pause Mode which should
- *	be used for this port.
- *	It should be called after successfully finishing
- *	the Auto-negotiation Process
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPauseMd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U32		DWord;
-	SK_U16		Word;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-	
-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
-		/* Disable Pause Frame Reception */
-		Word |= XM_MMU_IGN_PF;
-	}
-	else {
-		/*
-		 * enabling pause frame reception is required for 1000BT
-		 * because the XMAC is not reset if the link is going down
-		 */
-		/* Enable Pause Frame Reception */
-		Word &= ~XM_MMU_IGN_PF;
-	}	
-	
-	XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
-
-	XM_IN32(IoC, Port, XM_MODE, &DWord);
-
-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
-		/*
-		 * Configure Pause Frame Generation
-		 * Use internal and external Pause Frame Generation.
-		 * Sending pause frames is edge triggered.
-		 * Send a Pause frame with the maximum pause time if
-		 * internal oder external FIFO full condition occurs.
-		 * Send a zero pause time frame to re-start transmission.
-		 */
-
-		/* XM_PAUSE_DA = '010000C28001' (default) */
-
-		/* XM_MAC_PTIME = 0xffff (maximum) */
-		/* remember this value is defined in big endian (!) */
-		XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
-
-		/* Set Pause Mode in Mode Register */
-		DWord |= XM_PAUSE_MODE;
-
-		/* Set Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
-	}
-	else {
-		/*
-		 * disable pause frame generation is required for 1000BT
-		 * because the XMAC is not reset if the link is going down
-		 */
-		/* Disable Pause Mode in Mode Register */
-		DWord &= ~XM_PAUSE_MODE;
-
-		/* Disable Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
-	}
-	
-	XM_OUT32(IoC, Port, XM_MODE, DWord);
-}	/* SkXmInitPauseMd*/
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyXmac() - Initialize the XMAC Phy registers
- *
- * Description:	initializes all the XMACs Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl;
-
-	pPrt = &pAC->GIni.GP[Port];
-	Ctrl = 0;
-	
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyXmac: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl |= PHY_CT_DUP_MD;
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLEs are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyXmac: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl |= PHY_X_AN_HD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl |= PHY_X_AN_FD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl |= PHY_X_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl |= PHY_X_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl |= PHY_X_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl |= PHY_X_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Write AutoNeg Advertisement Register */
-		SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
-
-		/* Restart Auto-negotiation */
-		Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl |= PHY_CT_LOOP;
-	}
-
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
-}	/* SkXmInitPhyXmac */
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
- *
- * Description:	initializes all the Broadcom Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyBcom(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl1;
-	SK_U16		Ctrl2;
-	SK_U16		Ctrl3;
-	SK_U16		Ctrl4;
-	SK_U16		Ctrl5;
-
-	Ctrl1 = PHY_CT_SP1000;
-	Ctrl2 = 0;
-	Ctrl3 = PHY_SEL_TYPE;
-	Ctrl4 = PHY_B_PEC_EN_LTR;
-	Ctrl5 = PHY_B_AC_TX_TST;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		Ctrl2 |= PHY_B_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			Ctrl2 |= PHY_B_1000C_MSC;
-		}
-	}
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl1 |= PHY_CT_DUP_MD;
-		}
-
-		/* Determine Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			Ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLES are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyBcom: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/*
-		 * Workaround BCOM Errata #1 for the C5 type.
-		 * 1000Base-T Link Acquisition Failure in Slave Mode
-		 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
-		 */
-		Ctrl2 |= PHY_B_1000C_RD;
-		
-		 /* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl2 |= PHY_B_1000C_AHD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl2 |= PHY_B_1000C_AFD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl3 |= PHY_B_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl3 |= PHY_B_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl3 |= PHY_B_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl3 |= PHY_B_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Restart Auto-negotiation */
-		Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-	
-	/* Initialize LED register here? */
-	/* No. Please do it in SkDgXmitLed() (if required) and swap
-	   init order of LEDs and XMAC. (MAl) */
-	
-	/* Write 1000Base-T Control Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-	
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl1 |= PHY_CT_LOOP;
-	}
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		/* configure FIFO to high latency for transmission of ext. packets */
-		Ctrl4 |= PHY_B_PEC_HIGH_LA;
-
-		/* configure reception of extended packets */
-		Ctrl5 |= PHY_B_AC_LONG_PACK;
-
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
-	}
-
-	/* Configure LED Traffic Mode and Jumbo Frame usage if specified */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
-	
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Control Reg=0x%04X\n", Ctrl1));
-}	/* SkXmInitPhyBcom */
-#endif /* GENESIS */
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmInitPhyMarv() - Initialize the Marvell Phy registers
- *
- * Description:	initializes all the Marvell Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkGmInitPhyMarv(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		PhyCtrl;
-	SK_U16		C1000BaseT;
-	SK_U16		AutoNegAdv;
-	SK_U16		ExtPhyCtrl;
-	SK_U16		LedCtrl;
-	SK_BOOL		AutoNeg;
-#if defined(SK_DIAG) || defined(DEBUG)
-	SK_U16		PhyStat;
-	SK_U16		PhyStat1;
-	SK_U16		PhySpecStat;
-#endif /* SK_DIAG || DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		AutoNeg = SK_FALSE;
-	}
-	else {
-		AutoNeg = SK_TRUE;
-	}
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("InitPhyMarv: Port %d, auto-negotiation %s\n",
-		 Port, AutoNeg ? "ON" : "OFF"));
-
-#ifdef VCPU
-	VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
-		Port, DoLoop);
-#else /* VCPU */
-	if (DoLoop) {
-		/* Set 'MAC Power up'-bit, set Manual MDI configuration */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
-			PHY_M_PC_MAC_POW_UP);
-	}
-	else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
-		/* Read Ext. PHY Specific Control */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-		
-		ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
-			PHY_M_EC_MAC_S_MSK);
-		
-		ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
-			PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
-	
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-	}
-
-	/* Read PHY Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-
-	if (!AutoNeg) {
-		/* Disable Auto-negotiation */
-		PhyCtrl &= ~PHY_CT_ANE;
-	}
-
-	PhyCtrl |= PHY_CT_RESET;
-	/* Assert software reset */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-#endif /* VCPU */
-
-	PhyCtrl = 0 /* PHY_CT_COL_TST */;
-	C1000BaseT = 0;
-	AutoNegAdv = PHY_SEL_TYPE;
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		/* enable Manual Master/Slave */
-		C1000BaseT |= PHY_M_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			C1000BaseT |= PHY_M_1000C_MSC;	/* set it to Master */
-		}
-	}
-	
-	/* Auto-negotiation ? */
-	if (!AutoNeg) {
-		
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			/* Set Full Duplex Mode */
-			PhyCtrl |= PHY_CT_DUP_MD;
-		}
-
-		/* Set Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			C1000BaseT |= PHY_M_1000C_MSE;	/* set it to Slave */
-		}
-
-		/* Set Speed */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-		case SK_LSPEED_1000MBPS:
-			PhyCtrl |= PHY_CT_SP1000;
-			break;
-		case SK_LSPEED_100MBPS:
-			PhyCtrl |= PHY_CT_SP100;
-			break;
-		case SK_LSPEED_10MBPS:
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
-				SKERR_HWI_E019MSG);
-		}
-
-		if (!DoLoop) {
-			PhyCtrl |= PHY_CT_RESET;
-		}
-	}
-	else {
-		/* Set Auto-negotiation advertisement */
-		
-		if (pAC->GIni.GICopperType) {
-			/* Set Speed capabilities */
-			switch (pPrt->PLinkSpeed) {
-			case SK_LSPEED_AUTO:
-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			case SK_LSPEED_1000MBPS:
-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
-				break;
-			case SK_LSPEED_100MBPS:
-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
-					/* advertise 10Base-T also */
-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			case SK_LSPEED_10MBPS:
-				AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
-					SKERR_HWI_E019MSG);
-			}
-
-			/* Set Full/half duplex capabilities */
-			switch (pPrt->PLinkMode) {
-			case SK_LMODE_AUTOHALF:
-				C1000BaseT &= ~PHY_M_1000C_AFD;
-				AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
-				break;
-			case SK_LMODE_AUTOFULL:
-				C1000BaseT &= ~PHY_M_1000C_AHD;
-				AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
-				break;
-			case SK_LMODE_AUTOBOTH:
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-					SKERR_HWI_E015MSG);
-			}
-			
-			/* Set Flow-control capabilities */
-			switch (pPrt->PFlowCtrlMode) {
-			case SK_FLOW_MODE_NONE:
-				AutoNegAdv |= PHY_B_P_NO_PAUSE;
-				break;
-			case SK_FLOW_MODE_LOC_SEND:
-				AutoNegAdv |= PHY_B_P_ASYM_MD;
-				break;
-			case SK_FLOW_MODE_SYMMETRIC:
-				AutoNegAdv |= PHY_B_P_SYM_MD;
-				break;
-			case SK_FLOW_MODE_SYM_OR_REM:
-				AutoNegAdv |= PHY_B_P_BOTH_MD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-					SKERR_HWI_E016MSG);
-			}
-		}
-		else {	/* special defines for FIBER (88E1011S only) */
-			
-			/* Set Full/half duplex capabilities */
-			switch (pPrt->PLinkMode) {
-			case SK_LMODE_AUTOHALF:
-				AutoNegAdv |= PHY_M_AN_1000X_AHD;
-				break;
-			case SK_LMODE_AUTOFULL:
-				AutoNegAdv |= PHY_M_AN_1000X_AFD;
-				break;
-			case SK_LMODE_AUTOBOTH:
-				AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-					SKERR_HWI_E015MSG);
-			}
-			
-			/* Set Flow-control capabilities */
-			switch (pPrt->PFlowCtrlMode) {
-			case SK_FLOW_MODE_NONE:
-				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
-				break;
-			case SK_FLOW_MODE_LOC_SEND:
-				AutoNegAdv |= PHY_M_P_ASYM_MD_X;
-				break;
-			case SK_FLOW_MODE_SYMMETRIC:
-				AutoNegAdv |= PHY_M_P_SYM_MD_X;
-				break;
-			case SK_FLOW_MODE_SYM_OR_REM:
-				AutoNegAdv |= PHY_M_P_BOTH_MD_X;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-					SKERR_HWI_E016MSG);
-			}
-		}
-
-		if (!DoLoop) {
-			/* Restart Auto-negotiation */
-			PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
-		}
-	}
-	
-#ifdef VCPU
-	/*
-	 * E-mail from Gu Lin (08-03-2002):
-	 */
-	
-	/* Program PHY register 30 as 16'h0708 for simulation speed up */
-	SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
-	
-	VCpuWait(2000);
-
-#else /* VCPU */
-	
-	/* Write 1000Base-T Control Register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-#endif /* VCPU */
-	
-	if (DoLoop) {
-		/* Set the PHY Loopback bit */
-		PhyCtrl |= PHY_CT_LOOP;
-
-#ifdef XXX
-		/* Program PHY register 16 as 16'h0400 to force link good */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
-#endif /* XXX */
-
-#ifndef VCPU
-		if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
-			/* Write Ext. PHY Specific Control */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
-				(SK_U16)((pPrt->PLinkSpeed + 2) << 4));
-		}
-#endif /* VCPU */
-	}
-#ifdef TEST_ONLY
-	else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
-			/* Write PHY Specific Control */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
-				PHY_M_PC_EN_DET_MSK);
-	}
-#endif
-
-	/* Write to the PHY Control register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-
-#ifdef VCPU
-	VCpuWait(2000);
-#else
-
-	LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
-		LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
-	}
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
-		LedCtrl |= PHY_M_LEDC_DP_CTRL;
-	}
-	
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
-		/* only in forced 100 Mbps mode */
-		if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
-
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
-				PHY_M_LED_MO_100(MO_LED_ON));
-		}
-	}
-
-#ifdef SK_DIAG
-	c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
-	c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
-	c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
-	c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
-#endif /* SK_DIAG */
-
-#if defined(SK_DIAG) || defined(DEBUG)
-	/* Read PHY Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-	
-	/* Read 1000Base-T Control Register */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl =0x%04X\n", C1000BaseT));
-	
-	/* Read AutoNeg Advertisement Register */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-	
-	/* Read Ext. PHY Specific Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-	
-	/* Read PHY Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Stat Reg.=0x%04X\n", PhyStat));
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Stat Reg.=0x%04X\n", PhyStat1));
-	
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Spec Stat=0x%04X\n", PhySpecStat));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
-	c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
-	c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
-	c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
-	c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
-	c_print("PHY Stat Reg=0x%04X\n", PhyStat);
-	c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
-	c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
-#endif /* SK_DIAG */
-
-#endif /* VCPU */
-
-}	/* SkGmInitPhyMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkXmInitPhyLone() - Initialize the Level One Phy registers
- *
- * Description:	initializes all the Level One Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyLone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl1;
-	SK_U16		Ctrl2;
-	SK_U16		Ctrl3;
-
-	Ctrl1 = PHY_CT_SP1000;
-	Ctrl2 = 0;
-	Ctrl3 = PHY_SEL_TYPE;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		Ctrl2 |= PHY_L_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			Ctrl2 |= PHY_L_1000C_MSC;
-		}
-	}
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		/*
-		 * level one spec say: "1000 Mbps: manual mode not allowed"
-		 * but lets see what happens...
-		 */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyLone: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl1 |= PHY_CT_DUP_MD;
-		}
-
-		/* Determine Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			Ctrl2 |= PHY_L_1000C_MSE;	/* set it to Slave */
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLES are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyLone: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl2 |= PHY_L_1000C_AHD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl2 |= PHY_L_1000C_AFD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl3 |= PHY_L_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl3 |= PHY_L_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl3 |= PHY_L_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl3 |= PHY_L_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Restart Auto-negotiation */
-		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-	
-	/* Write 1000Base-T Control Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl1 |= PHY_CT_LOOP;
-	}
-
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Control Reg=0x%04X\n", Ctrl1));
-}	/* SkXmInitPhyLone */
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyNat() - Initialize the National Phy registers
- *
- * Description:	initializes all the National Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyNat(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-/* todo: National */
-}	/* SkXmInitPhyNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkMacInitPhy() - Initialize the PHY registers
- *
- * Description:	calls the Init PHY routines dep. on board type
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-void SkMacInitPhy(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		switch (pPrt->PhyType) {
-		case SK_PHY_XMAC:
-			SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
-			break;
-		case SK_PHY_BCOM:
-			SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
-			break;
-		case SK_PHY_NAT:
-			SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
-			break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
-	}
-#endif /* YUKON */
-
-}	/* SkMacInitPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmAutoNegDoneXmac() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		LPAb;		/* Link Partner Ability */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneXmac, Port %d\n", Port));
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-
-	if ((LPAb & PHY_X_AN_RFB) != 0) {
-		/* At least one of the remote fault bit is set */
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	else {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_DUP_CAP);
-	}
-
-	/* Check PAUSE mismatch */
-	/* We are NOT using chapter 4.23 of the Xaqti manual */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
-	     pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
-	    (LPAb & PHY_X_P_SYM_MD) != 0) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneXmac */
-
-
-/******************************************************************************
- *
- *	SkXmAutoNegDoneBcom() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneBcom(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		AuxStat;	/* Auxiliary Status */
-
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	SK_U16		ResAb;		/* Resolved Ability */
-#endif	/* 0 */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneBcom, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-#endif	/* 0 */
-	
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
-
-	if ((LPAb & PHY_B_AN_RF) != 0) {
-		/* Remote fault bit is set: Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	else {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_DUP_CAP);
-	}
-	
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-#endif	/* 0 */
-
-	/* Check PAUSE mismatch ??? */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmAutoNegDoneMarv() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkGmAutoNegDoneMarv(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		AuxStat;	/* Auxiliary Status */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneMarv, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Link P.Abil.=0x%04X\n", LPAb));
-	
-	if ((LPAb & PHY_M_AN_RF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-	
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
-	
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
-	
-	/* Check Speed & Duplex resolved */
-	if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-		return(SK_AND_DUP_CAP);
-	}
-	
-	if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	
-	/* Check PAUSE mismatch ??? */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	
-	/* set used link speed */
-	switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
-	case (unsigned)PHY_M_PS_SPEED_1000:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-		break;
-	case PHY_M_PS_SPEED_100:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
-		break;
-	default:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
-	}
-
-	return(SK_AND_OK);
-}	/* SkGmAutoNegDoneMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkXmAutoNegDoneLone() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneLone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		QuickStat;	/* Auxiliary Status */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneLone, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
-
-	if ((LPAb & PHY_L_AN_RF) != 0) {
-		/* Remote fault bit is set */
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_L_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	else if (ResAb & PHY_L_1000S_MSR) {
-		pPrt->PMSStatus = SK_MS_STAT_MASTER;
-	}
-	else {
-		pPrt->PMSStatus = SK_MS_STAT_SLAVE;
-	}
-
-	/* Check PAUSE mismatch */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	/* we must manually resolve the abilities here */
-	pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	
-	switch (pPrt->PFlowCtrlMode) {
-	case SK_FLOW_MODE_NONE:
-		/* default */
-		break;
-	case SK_FLOW_MODE_LOC_SEND:
-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
-			(PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
-			/* Disable PAUSE receive, enable PAUSE transmit */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-		}
-		break;
-	case SK_FLOW_MODE_SYMMETRIC:
-		if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
-			/* Symmetric PAUSE */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-		}
-		break;
-	case SK_FLOW_MODE_SYM_OR_REM:
-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
-			PHY_L_QS_AS_PAUSE) {
-			/* Enable PAUSE receive, disable PAUSE transmit */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-		}
-		else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
-			/* Symmetric PAUSE */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-		}
-		break;
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-			SKERR_HWI_E016MSG);
-	}
-	
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneLone */
-
-
-/******************************************************************************
- *
- *	SkXmAutoNegDoneNat() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneNat(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-/* todo: National */
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkMacAutoNegDone() - Auto-negotiation handling
- *
- * Description:	calls the auto-negotiation done routines dep. on board type
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-int	SkMacAutoNegDone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int	Rtv;
-
-	Rtv = SK_AND_OK;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		switch (pPrt->PhyType) {
-		
-		case SK_PHY_XMAC:
-			Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
-			break;
-		case SK_PHY_BCOM:
-			Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
-			break;
-		case SK_PHY_NAT:
-			Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
-			break;
-#endif /* OTHER_PHY */
-		default:
-			return(SK_AND_OTHER);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-	
-	if (Rtv != SK_AND_OK) {
-		return(Rtv);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNeg done Port %d\n", Port));
-	
-	/* We checked everything and may now enable the link */
-	pPrt->PAutoNegFail = SK_FALSE;
-
-	SkMacRxTxEnable(pAC, IoC, Port);
-	
-	return(SK_AND_OK);
-}	/* SkMacAutoNegDone */
-
-
-/******************************************************************************
- *
- *	SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
- *
- * Description:	enables Rx/Tx dep. on board type
- *
- * Returns:
- *	0	o.k.
- *	!= 0	Error happened
- */
-int SkMacRxTxEnable(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Reg;		/* 16-bit register value */
-	SK_U16		IntMask;	/* MAC interrupt mask */
-#ifdef GENESIS
-	SK_U16		SWord;
-#endif
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (!pPrt->PHWLinkUp) {
-		/* The Hardware link is NOT up */
-		return(0);
-	}
-
-	if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
-	     pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
-	     pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
-	     pPrt->PAutoNegFail) {
-		/* Auto-negotiation is not done or failed */
-		return(0);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* set Duplex Mode and Pause Mode */
-		SkXmInitDupMd(pAC, IoC, Port);
-		
-		SkXmInitPauseMd(pAC, IoC, Port);
-	
-		/*
-		 * Initialize the Interrupt Mask Register. Default IRQs are...
-		 *	- Link Asynchronous Event
-		 *	- Link Partner requests config
-		 *	- Auto Negotiation Done
-		 *	- Rx Counter Event Overflow
-		 *	- Tx Counter Event Overflow
-		 *	- Transmit FIFO Underrun
-		 */
-		IntMask = XM_DEF_MSK;
-
-#ifdef DEBUG
-		/* add IRQ for Receive FIFO Overflow */
-		IntMask &= ~XM_IS_RXF_OV;
-#endif /* DEBUG */
-		
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			/* disable GP0 interrupt bit */
-			IntMask |= XM_IS_INP_ASS;
-		}
-		XM_OUT16(IoC, Port, XM_IMSK, IntMask);
-	
-		/* get MMU Command Reg. */
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
-		
-		if (pPrt->PhyType != SK_PHY_XMAC &&
-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
-			 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
-			/* set to Full Duplex */
-			Reg |= XM_MMU_GMII_FD;
-		}
-		
-		switch (pPrt->PhyType) {
-		case SK_PHY_BCOM:
-			/*
-			 * Workaround BCOM Errata (#10523) for all BCom Phys
-			 * Enable Power Management after link up
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-				(SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
-            SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
-				(SK_U16)PHY_B_DEF_MSK);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
-			break;
-		case SK_PHY_NAT:
-			/* todo National:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
-			/* no interrupts possible from National ??? */
-			break;
-#endif /* OTHER_PHY */
-		}
-		
-		/* enable Rx/Tx */
-		XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/*
-		 * Initialize the Interrupt Mask Register. Default IRQs are...
-		 *	- Rx Counter Event Overflow
-		 *	- Tx Counter Event Overflow
-		 *	- Transmit FIFO Underrun
-		 */
-		IntMask = GMAC_DEF_MSK;
-
-#ifdef DEBUG
-		/* add IRQ for Receive FIFO Overrun */
-		IntMask |= GM_IS_RX_FF_OR;
-#endif /* DEBUG */
-		
-		SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
-		
-		/* get General Purpose Control */
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
-		
-		if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
-			pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
-			/* set to Full Duplex */
-			Reg |= GM_GPCR_DUP_FULL;
-		}
-		
-		/* enable Rx/Tx */
-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
-			GM_GPCR_TX_ENA));
-
-#ifndef VCPU
-		/* Enable all PHY interrupts */
-        SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
-			(SK_U16)PHY_M_DEF_MSK);
-#endif /* VCPU */
-	}
-#endif /* YUKON */
-					
-	return(0);
-
-}	/* SkMacRxTxEnable */
-
-
-/******************************************************************************
- *
- *	SkMacRxTxDisable() - Disable Receiver and Transmitter
- *
- * Description:	disables Rx/Tx dep. on board type
- *
- * Returns: N/A
- */
-void SkMacRxTxDisable(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Word;
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-		
-		XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
-	
-		/* dummy read to ensure writing */
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-
-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
-			GM_GPCR_TX_ENA)));
-
-		/* dummy read to ensure writing */
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-	}
-#endif /* YUKON */
-
-}	/* SkMacRxTxDisable */
-
-
-/******************************************************************************
- *
- *	SkMacIrqDisable() - Disable IRQ from MAC
- *
- * Description:	sets the IRQ-mask to disable IRQ dep. on board type
- *
- * Returns: N/A
- */
-void SkMacIrqDisable(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-#ifdef GENESIS
-	SK_U16		Word;
-#endif
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		/* disable all XMAC IRQs */
-		XM_OUT16(IoC, Port, XM_IMSK, 0xffff);	
-		
-		/* Disable all PHY interrupts */
-		switch (pPrt->PhyType) {
-			case SK_PHY_BCOM:
-				/* Make sure that PHY is initialized */
-				if (pPrt->PState != SK_PRT_RESET) {
-					/* NOT allowed if BCOM is in RESET state */
-					/* Workaround BCOM Errata (#10523) all BCom */
-					/* Disable Power Management if link is down */
-					SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-						(SK_U16)(Word | PHY_B_AC_DIS_PM));
-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
-				}
-				break;
-#ifdef OTHER_PHY
-			case SK_PHY_LONE:
-				SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
-				break;
-			case SK_PHY_NAT:
-				/* todo: National
-				SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
-				break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* disable all GMAC IRQs */
-		SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-		
-#ifndef VCPU
-		/* Disable all PHY interrupts */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-#endif /* VCPU */
-	}
-#endif /* YUKON */
-
-}	/* SkMacIrqDisable */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkXmSendCont() - Enable / Disable Send Continuous Mode
- *
- * Description:	enable / disable Send Continuous Mode on XMAC
- *
- * Returns:
- *	nothing
- */
-void SkXmSendCont(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U32	MdReg;
-
-	XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-	if (Enable) {
-		MdReg |= XM_MD_TX_CONT;
-	}
-	else {
-		MdReg &= ~XM_MD_TX_CONT;
-	}
-	/* setup Mode Register */
-	XM_OUT32(IoC, Port, XM_MODE, MdReg);
-
-}	/* SkXmSendCont */
-
-
-/******************************************************************************
- *
- *	SkMacTimeStamp() - Enable / Disable Time Stamp
- *
- * Description:	enable / disable Time Stamp generation for Rx packets
- *
- * Returns:
- *	nothing
- */
-void SkMacTimeStamp(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U32	MdReg;
-	SK_U8	TimeCtrl;
-
-	if (pAC->GIni.GIGenesis) {
-
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		if (Enable) {
-			MdReg |= XM_MD_ATS;
-		}
-		else {
-			MdReg &= ~XM_MD_ATS;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-	else {
-		if (Enable) {
-			TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
-		}
-		else {
-			TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
-		}
-		/* Start/Stop Time Stamp Timer */
-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
-	}
-
-}	/* SkMacTimeStamp*/
-
-#else /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
- *
- *	This function analyses the Interrupt status word. If any of the
- *	Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
- *	is set true.
- */
-void SkXmAutoNegLipaXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U16	IStatus)	/* Interrupt Status word to analyse */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
-		(IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
-			Port, IStatus));
-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
-	}
-}	/* SkXmAutoNegLipaXmac */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
- *
- *	This function analyses the PHY status word.
- *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
- *	is set true.
- */
-void SkMacAutoNegLipaPhy(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U16	PhyStat)	/* PHY Status word to analyse */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
-		(PhyStat & PHY_ST_AN_OVER) != 0) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
-			Port, PhyStat));
-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
-	}
-}	/* SkMacAutoNegLipaPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmIrq() - Interrupt Service Routine
- *
- * Description:	services an Interrupt Request of the XMAC
- *
- * Note:
- *	With an external PHY, some interrupt bits are not meaningfull any more:
- *	- LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
- *	- LinkPartnerReqConfig (bit #10)	XM_IS_LIPA_RC
- *	- Page Received (bit #9)		XM_IS_RX_PAGE
- *	- NextPageLoadedForXmt (bit #8)		XM_IS_TX_PAGE
- *	- AutoNegDone (bit #7)			XM_IS_AND
- *	Also probably not valid any more is the GP0 input bit:
- *	- GPRegisterBit0set			XM_IS_INP_ASS
- *
- * Returns:
- *	nothing
- */
-static void SkXmIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_EVPARA	Para;
-	SK_U16		IStatus;	/* Interrupt status read from the XMAC */
-	SK_U16		IStatus2;
-#ifdef SK_SLIM
-    SK_U64      OverflowStatus;
-#endif	
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	XM_IN16(IoC, Port, XM_ISRC, &IStatus);
-	
-	/* LinkPartner Auto-negable? */
-	if (pPrt->PhyType == SK_PHY_XMAC) {
-		SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
-	}
-	else {
-		/* mask bits that are not used with ext. PHY */
-		IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
-			XM_IS_RX_PAGE | XM_IS_TX_PAGE |
-			XM_IS_AND | XM_IS_INP_ASS);
-	}
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
-	if (!pPrt->PHWLinkUp) {
-		/* Spurious XMAC interrupt */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: spurious interrupt on Port %d\n", Port));
-		return;
-	}
-
-	if ((IStatus & XM_IS_INP_ASS) != 0) {
-		/* Reread ISR Register if link is not in sync */
-		XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
-			 Port, IStatus, IStatus2));
-		IStatus &= ~XM_IS_INP_ASS;
-		IStatus |= IStatus2;
-	}
-
-	if ((IStatus & XM_IS_LNK_AE) != 0) {
-		/* not used, GP0 is used instead */
-	}
-
-	if ((IStatus & XM_IS_TX_ABORT) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_FRC_INT) != 0) {
-		/* not used, use ASIC IRQ instead if needed */
-	}
-
-	if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
-		SkHWLinkDown(pAC, IoC, Port);
-
-		/* Signal to RLMT */
-		Para.Para32[0] = (SK_U32)Port;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-	}
-
-	if ((IStatus & XM_IS_RX_PAGE) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_TX_PAGE) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_AND) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: AND on link that is up Port %d\n", Port));
-	}
-
-	if ((IStatus & XM_IS_TSC_OV) != 0) {
-		/* not used */
-	}
-
-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
-	if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
-#ifdef SK_SLIM
-		SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
-		Para.Para32[0] = (SK_U32)Port;
-		Para.Para32[1] = (SK_U32)IStatus;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif /* SK_SLIM */
-	}
-
-	if ((IStatus & XM_IS_RXF_OV) != 0) {
-		/* normal situation -> no effect */
-#ifdef DEBUG
-		pPrt->PRxOverCnt++;
-#endif /* DEBUG */
-	}
-
-	if ((IStatus & XM_IS_TXF_UR) != 0) {
-		/* may NOT happen -> error log */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
-	}
-
-	if ((IStatus & XM_IS_TX_COMP) != 0) {
-		/* not served here */
-	}
-
-	if ((IStatus & XM_IS_RX_COMP) != 0) {
-		/* not served here */
-	}
-}	/* SkXmIrq */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmIrq() - Interrupt Service Routine
- *
- * Description:	services an Interrupt Request of the GMAC
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkGmIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U8		IStatus;	/* Interrupt status */
-#ifdef SK_SLIM
-    SK_U64      OverflowStatus;
-#else
-	SK_EVPARA	Para;
-#endif	
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
-	
-#ifdef XXX
-	/* LinkPartner Auto-negable? */
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
-#endif /* XXX */
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
-	if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
-		/* these IRQs will be cleared by reading GMACs register */
-#ifdef SK_SLIM
-        SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
-		Para.Para32[0] = (SK_U32)Port;
-		Para.Para32[1] = (SK_U32)IStatus;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif		
-	}
-
-	if (IStatus & GM_IS_RX_FF_OR) {
-		/* clear GMAC Rx FIFO Overrun IRQ */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
-#ifdef DEBUG
-		pPrt->PRxOverCnt++;
-#endif /* DEBUG */
-	}
-
-	if (IStatus & GM_IS_TX_FF_UR) {
-		/* clear GMAC Tx FIFO Underrun IRQ */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
-		/* may NOT happen -> error log */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
-	}
-
-	if (IStatus & GM_IS_TX_COMPL) {
-		/* not served here */
-	}
-
-	if (IStatus & GM_IS_RX_COMPL) {
-		/* not served here */
-	}
-}	/* SkGmIrq */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- *	SkMacIrq() - Interrupt Service Routine for MAC
- *
- * Description:	calls the Interrupt Service Routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* IRQ from XMAC */
-		SkXmIrq(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* IRQ from GMAC */
-		SkGmIrq(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-}	/* SkMacIrq */
-
-#endif /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmUpdateStats() - Force the XMAC to output the current statistic
- *
- * Description:
- *	The XMAC holds its statistic internally. To obtain the current
- *	values a command must be sent so that the statistic data will
- *	be written to a predefined memory area on the adapter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmUpdateStats(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		StatReg;
-	int			WaitIndex;
-
-	pPrt = &pAC->GIni.GP[Port];
-	WaitIndex = 0;
-
-	/* Send an update command to XMAC specified */
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
-
-	/*
-	 * It is an auto-clearing register. If the command bits
-	 * went to zero again, the statistics are transferred.
-	 * Normally the command should be executed immediately.
-	 * But just to be sure we execute a loop.
-	 */
-	do {
-
-		XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
-		
-		if (++WaitIndex > 10) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
-
-			return(1);
-		}
-	} while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
-	
-	return(0);
-}	/* SkXmUpdateStats */
-
-
-/******************************************************************************
- *
- *	SkXmMacStatistic() - Get XMAC counter value
- *
- * Description:
- *	Gets the 32bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmMacStatistic(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-unsigned int Port,		/* Port Index (MAC_1 + n) */
-SK_U16	StatAddr,		/* MIB counter base address */
-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
-{
-	if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
-		
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-		
-		return(1);
-	}
-	
-	XM_IN32(IoC, Port, StatAddr, pVal);
-
-	return(0);
-}	/* SkXmMacStatistic */
-
-
-/******************************************************************************
- *
- *	SkXmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- *	Force the XMAC to clear its statistic counter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmResetCounter(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-	/* Clear two times according to Errata #3 */
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-
-	return(0);
-}	/* SkXmResetCounter */
-
-
-/******************************************************************************
- *
- *	SkXmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- *	Checks the source causing an counter overflow interrupt. On success the
- *	resulting counter overflow status is written to <pStatus>, whereas the
- *	upper dword stores the XMAC ReceiveCounterEvent register and the lower
- *	dword the XMAC TransmitCounterEvent register.
- *
- * Note:
- *	For XMAC the interrupt source is a self-clearing register, so the source
- *	must be checked only once. SIRQ module does another check to be sure
- *	that no interrupt get lost during process time.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmOverflowStatus(
-SK_AC	*pAC,				/* adapter context */
-SK_IOC	IoC,				/* IO context */
-unsigned int Port,			/* Port Index (MAC_1 + n) */
-SK_U16	IStatus,			/* Interupt Status from MAC */
-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
-{
-	SK_U64	Status;	/* Overflow status */
-	SK_U32	RegVal;
-
-	Status = 0;
-
-	if ((IStatus & XM_IS_RXC_OV) != 0) {
-
-		XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
-		Status |= (SK_U64)RegVal << 32;
-	}
-	
-	if ((IStatus & XM_IS_TXC_OV) != 0) {
-
-		XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
-		Status |= (SK_U64)RegVal;
-	}
-
-	*pStatus = Status;
-
-	return(0);
-}	/* SkXmOverflowStatus */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmUpdateStats() - Force the GMAC to output the current statistic
- *
- * Description:
- *	Empty function for GMAC. Statistic data is accessible in direct way.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmUpdateStats(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	return(0);
-}
-
-
-/******************************************************************************
- *
- *	SkGmMacStatistic() - Get GMAC counter value
- *
- * Description:
- *	Gets the 32bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmMacStatistic(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-unsigned int Port,		/* Port Index (MAC_1 + n) */
-SK_U16	StatAddr,		/* MIB counter base address */
-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
-{
-
-	if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
-		
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
-		return(1);
-	}
-		
-	GM_IN32(IoC, Port, StatAddr, pVal);
-
-	return(0);
-}	/* SkGmMacStatistic */
-
-
-/******************************************************************************
- *
- *	SkGmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- *	Force GMAC to clear its statistic counter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmResetCounter(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Reg;	/* Phy Address Register */
-	SK_U16	Word;
-	int		i;
-
-	GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
-
-	/* set MIB Clear Counter Mode */
-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
-	
-	/* read all MIB Counters with Clear Mode set */
-	for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
-		/* the reset is performed only when the lower 16 bits are read */
-		GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
-	}
-	
-	/* clear MIB Clear Counter Mode */
-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
-	
-	return(0);
-}	/* SkGmResetCounter */
-
-
-/******************************************************************************
- *
- *	SkGmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- *	Checks the source causing an counter overflow interrupt. On success the
- *	resulting counter overflow status is written to <pStatus>, whereas the
- *	the following bit coding is used:
- *	63:56 - unused
- *	55:48 - TxRx interrupt register bit7:0
- *	32:47 - Rx interrupt register
- *	31:24 - unused
- *	23:16 - TxRx interrupt register bit15:8
- *	15:0  - Tx interrupt register
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmOverflowStatus(
-SK_AC	*pAC,				/* adapter context */
-SK_IOC	IoC,				/* IO context */
-unsigned int Port,			/* Port Index (MAC_1 + n) */
-SK_U16	IStatus,			/* Interupt Status from MAC */
-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
-{
-	SK_U64	Status;		/* Overflow status */
-	SK_U16	RegVal;
-
-	Status = 0;
-
-	if ((IStatus & GM_IS_RX_CO_OV) != 0) {
-		/* this register is self-clearing after read */
-		GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
-		Status |= (SK_U64)RegVal << 32;
-	}
-	
-	if ((IStatus & GM_IS_TX_CO_OV) != 0) {
-		/* this register is self-clearing after read */
-		GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
-		Status |= (SK_U64)RegVal;
-	}
-	
-	/* this register is self-clearing after read */
-	GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
-	/* Rx overflow interrupt register bits (LoByte)*/
-	Status |= (SK_U64)((SK_U8)RegVal) << 48;
-	/* Tx overflow interrupt register bits (HiByte)*/
-	Status |= (SK_U64)(RegVal >> 8) << 16;
-
-	*pStatus = Status;
-
-	return(0);
-}	/* SkGmOverflowStatus */
-
-
-#ifndef SK_SLIM
-/******************************************************************************
- *
- *	SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
- *
- * Description:
- *  starts the cable diagnostic test if 'StartTest' is true
- *  gets the results if 'StartTest' is true
- *
- * NOTE:	this test is meaningful only when link is down
- *	
- * Returns:
- *	0:  success
- *	1:	no YUKON copper
- *	2:	test in progress
- */
-int SkGmCableDiagStatus(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,   		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	StartTest)	/* flag for start / get result */
-{
-	int		i;
-	SK_U16	RegVal;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-		
-		return(1);
-	}
-
-	if (StartTest) {
-		/* only start the cable test */
-		if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
-			/* apply TDR workaround from Marvell */
-			SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
-			
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
-		}
-
-		/* set address to 0 for MDI[0] */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
-
-		/* Read Cable Diagnostic Reg */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-		/* start Cable Diagnostic Test */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
-			(SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
-	
-		return(0);
-	}
-	
-	/* Read Cable Diagnostic Reg */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Cable Diag.=0x%04X\n", RegVal));
-
-	if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
-		/* test is running */
-		return(2);
-	}
-
-	/* get the test results */
-	for (i = 0; i < 4; i++)  {
-		/* set address to i for MDI[i] */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
-
-		/* get Cable Diagnostic values */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-		pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
-
-		pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
-	}
-
-	return(0);
-}	/* SkGmCableDiagStatus */
-#endif /* !SK_SLIM */
-#endif /* YUKON */
-
-/* End of file */
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 4020e9e..97bdb2a 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -220,22 +220,22 @@
 
 
 /* this enables an interrupt in the interrupt mask register */
-#define SMC_ENABLE_INT(x) do {						\
+#define SMC_ENABLE_INT(lp, x) do {					\
 	unsigned char mask;						\
 	spin_lock_irq(&lp->lock);					\
-	mask = SMC_GET_INT_MASK();					\
+	mask = SMC_GET_INT_MASK(lp);					\
 	mask |= (x);							\
-	SMC_SET_INT_MASK(mask);						\
+	SMC_SET_INT_MASK(lp, mask);					\
 	spin_unlock_irq(&lp->lock);					\
 } while (0)
 
 /* this disables an interrupt from the interrupt mask register */
-#define SMC_DISABLE_INT(x) do {						\
+#define SMC_DISABLE_INT(lp, x) do {					\
 	unsigned char mask;						\
 	spin_lock_irq(&lp->lock);					\
-	mask = SMC_GET_INT_MASK();					\
+	mask = SMC_GET_INT_MASK(lp);					\
 	mask &= ~(x);							\
-	SMC_SET_INT_MASK(mask);						\
+	SMC_SET_INT_MASK(lp, mask);					\
 	spin_unlock_irq(&lp->lock);					\
 } while (0)
 
@@ -244,10 +244,10 @@
  * if at all, but let's avoid deadlocking the system if the hardware
  * decides to go south.
  */
-#define SMC_WAIT_MMU_BUSY() do {					\
-	if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) {			\
+#define SMC_WAIT_MMU_BUSY(lp) do {					\
+	if (unlikely(SMC_GET_MMU_CMD(lp) & MC_BUSY)) {		\
 		unsigned long timeout = jiffies + 2;			\
-		while (SMC_GET_MMU_CMD() & MC_BUSY) {			\
+		while (SMC_GET_MMU_CMD(lp) & MC_BUSY) {		\
 			if (time_after(jiffies, timeout)) {		\
 				printk("%s: timeout %s line %d\n",	\
 					dev->name, __FILE__, __LINE__);	\
@@ -273,8 +273,8 @@
 
 	/* Disable all interrupts, block TX tasklet */
 	spin_lock_irq(&lp->lock);
-	SMC_SELECT_BANK(2);
-	SMC_SET_INT_MASK(0);
+	SMC_SELECT_BANK(lp, 2);
+	SMC_SET_INT_MASK(lp, 0);
 	pending_skb = lp->pending_tx_skb;
 	lp->pending_tx_skb = NULL;
 	spin_unlock_irq(&lp->lock);
@@ -290,15 +290,15 @@
 	 * This resets the registers mostly to defaults, but doesn't
 	 * affect EEPROM.  That seems unnecessary
 	 */
-	SMC_SELECT_BANK(0);
-	SMC_SET_RCR(RCR_SOFTRST);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_RCR(lp, RCR_SOFTRST);
 
 	/*
 	 * Setup the Configuration Register
 	 * This is necessary because the CONFIG_REG is not affected
 	 * by a soft reset
 	 */
-	SMC_SELECT_BANK(1);
+	SMC_SELECT_BANK(lp, 1);
 
 	cfg = CONFIG_DEFAULT;
 
@@ -316,7 +316,7 @@
 	 */
 	cfg |= CONFIG_EPH_POWER_EN;
 
-	SMC_SET_CONFIG(cfg);
+	SMC_SET_CONFIG(lp, cfg);
 
 	/* this should pause enough for the chip to be happy */
 	/*
@@ -329,12 +329,12 @@
 	udelay(1);
 
 	/* Disable transmit and receive functionality */
-	SMC_SELECT_BANK(0);
-	SMC_SET_RCR(RCR_CLEAR);
-	SMC_SET_TCR(TCR_CLEAR);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_RCR(lp, RCR_CLEAR);
+	SMC_SET_TCR(lp, TCR_CLEAR);
 
-	SMC_SELECT_BANK(1);
-	ctl = SMC_GET_CTL() | CTL_LE_ENABLE;
+	SMC_SELECT_BANK(lp, 1);
+	ctl = SMC_GET_CTL(lp) | CTL_LE_ENABLE;
 
 	/*
 	 * Set the control register to automatically release successfully
@@ -345,12 +345,12 @@
 		ctl |= CTL_AUTO_RELEASE;
 	else
 		ctl &= ~CTL_AUTO_RELEASE;
-	SMC_SET_CTL(ctl);
+	SMC_SET_CTL(lp, ctl);
 
 	/* Reset the MMU */
-	SMC_SELECT_BANK(2);
-	SMC_SET_MMU_CMD(MC_RESET);
-	SMC_WAIT_MMU_BUSY();
+	SMC_SELECT_BANK(lp, 2);
+	SMC_SET_MMU_CMD(lp, MC_RESET);
+	SMC_WAIT_MMU_BUSY(lp);
 }
 
 /*
@@ -365,19 +365,19 @@
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
 	/* see the header file for options in TCR/RCR DEFAULT */
-	SMC_SELECT_BANK(0);
-	SMC_SET_TCR(lp->tcr_cur_mode);
-	SMC_SET_RCR(lp->rcr_cur_mode);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_TCR(lp, lp->tcr_cur_mode);
+	SMC_SET_RCR(lp, lp->rcr_cur_mode);
 
-	SMC_SELECT_BANK(1);
-	SMC_SET_MAC_ADDR(dev->dev_addr);
+	SMC_SELECT_BANK(lp, 1);
+	SMC_SET_MAC_ADDR(lp, dev->dev_addr);
 
 	/* now, enable interrupts */
 	mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
 	if (lp->version >= (CHIP_91100 << 4))
 		mask |= IM_MDINT;
-	SMC_SELECT_BANK(2);
-	SMC_SET_INT_MASK(mask);
+	SMC_SELECT_BANK(lp, 2);
+	SMC_SET_INT_MASK(lp, mask);
 
 	/*
 	 * From this point the register bank must _NOT_ be switched away
@@ -400,8 +400,8 @@
 
 	/* no more interrupts for me */
 	spin_lock_irq(&lp->lock);
-	SMC_SELECT_BANK(2);
-	SMC_SET_INT_MASK(0);
+	SMC_SELECT_BANK(lp, 2);
+	SMC_SET_INT_MASK(lp, 0);
 	pending_skb = lp->pending_tx_skb;
 	lp->pending_tx_skb = NULL;
 	spin_unlock_irq(&lp->lock);
@@ -409,14 +409,14 @@
 		dev_kfree_skb(pending_skb);
 
 	/* and tell the card to stay away from that nasty outside world */
-	SMC_SELECT_BANK(0);
-	SMC_SET_RCR(RCR_CLEAR);
-	SMC_SET_TCR(TCR_CLEAR);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_RCR(lp, RCR_CLEAR);
+	SMC_SET_TCR(lp, TCR_CLEAR);
 
 #ifdef POWER_DOWN
 	/* finally, shut the chip down */
-	SMC_SELECT_BANK(1);
-	SMC_SET_CONFIG(SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN);
+	SMC_SELECT_BANK(lp, 1);
+	SMC_SET_CONFIG(lp, SMC_GET_CONFIG(lp) & ~CONFIG_EPH_POWER_EN);
 #endif
 }
 
@@ -431,17 +431,17 @@
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
-	packet_number = SMC_GET_RXFIFO();
+	packet_number = SMC_GET_RXFIFO(lp);
 	if (unlikely(packet_number & RXFIFO_REMPTY)) {
 		PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
 		return;
 	}
 
 	/* read from start of packet */
-	SMC_SET_PTR(PTR_READ | PTR_RCV | PTR_AUTOINC);
+	SMC_SET_PTR(lp, PTR_READ | PTR_RCV | PTR_AUTOINC);
 
 	/* First two words are status and packet length */
-	SMC_GET_PKT_HDR(status, packet_len);
+	SMC_GET_PKT_HDR(lp, status, packet_len);
 	packet_len &= 0x07ff;  /* mask off top bits */
 	DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
 		dev->name, packet_number, status,
@@ -460,8 +460,8 @@
 					dev->name, packet_len, status);
 			status |= RS_TOOSHORT;
 		}
-		SMC_WAIT_MMU_BUSY();
-		SMC_SET_MMU_CMD(MC_RELEASE);
+		SMC_WAIT_MMU_BUSY(lp);
+		SMC_SET_MMU_CMD(lp, MC_RELEASE);
 		dev->stats.rx_errors++;
 		if (status & RS_ALGNERR)
 			dev->stats.rx_frame_errors++;
@@ -490,8 +490,8 @@
 		if (unlikely(skb == NULL)) {
 			printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
 				dev->name);
-			SMC_WAIT_MMU_BUSY();
-			SMC_SET_MMU_CMD(MC_RELEASE);
+			SMC_WAIT_MMU_BUSY(lp);
+			SMC_SET_MMU_CMD(lp, MC_RELEASE);
 			dev->stats.rx_dropped++;
 			return;
 		}
@@ -510,10 +510,10 @@
 		 */
 		data_len = packet_len - ((status & RS_ODDFRAME) ? 5 : 6);
 		data = skb_put(skb, data_len);
-		SMC_PULL_DATA(data, packet_len - 4);
+		SMC_PULL_DATA(lp, data, packet_len - 4);
 
-		SMC_WAIT_MMU_BUSY();
-		SMC_SET_MMU_CMD(MC_RELEASE);
+		SMC_WAIT_MMU_BUSY(lp);
+		SMC_SET_MMU_CMD(lp, MC_RELEASE);
 
 		PRINT_PKT(data, packet_len - 4);
 
@@ -591,7 +591,7 @@
 	}
 	lp->pending_tx_skb = NULL;
 
-	packet_no = SMC_GET_AR();
+	packet_no = SMC_GET_AR(lp);
 	if (unlikely(packet_no & AR_FAILED)) {
 		printk("%s: Memory allocation failed.\n", dev->name);
 		dev->stats.tx_errors++;
@@ -601,8 +601,8 @@
 	}
 
 	/* point to the beginning of the packet */
-	SMC_SET_PN(packet_no);
-	SMC_SET_PTR(PTR_AUTOINC);
+	SMC_SET_PN(lp, packet_no);
+	SMC_SET_PTR(lp, PTR_AUTOINC);
 
 	buf = skb->data;
 	len = skb->len;
@@ -614,13 +614,13 @@
 	 * Send the packet length (+6 for status words, length, and ctl.
 	 * The card will pad to 64 bytes with zeroes if packet is too small.
 	 */
-	SMC_PUT_PKT_HDR(0, len + 6);
+	SMC_PUT_PKT_HDR(lp, 0, len + 6);
 
 	/* send the actual data */
-	SMC_PUSH_DATA(buf, len & ~1);
+	SMC_PUSH_DATA(lp, buf, len & ~1);
 
 	/* Send final ctl word with the last byte if there is one */
-	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG);
+	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
 
 	/*
 	 * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
@@ -634,14 +634,14 @@
 		netif_stop_queue(dev);
 
 	/* queue the packet for TX */
-	SMC_SET_MMU_CMD(MC_ENQUEUE);
+	SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
 	smc_special_unlock(&lp->lock);
 
 	dev->trans_start = jiffies;
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += len;
 
-	SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
+	SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);
 
 done:	if (!THROTTLE_TX_PKTS)
 		netif_wake_queue(dev);
@@ -688,7 +688,7 @@
 	smc_special_lock(&lp->lock);
 
 	/* now, try to allocate the memory */
-	SMC_SET_MMU_CMD(MC_ALLOC | numPages);
+	SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
 
 	/*
 	 * Poll the chip for a short amount of time in case the
@@ -696,9 +696,9 @@
 	 */
 	poll_count = MEMORY_WAIT_TIME;
 	do {
-		status = SMC_GET_INT();
+		status = SMC_GET_INT(lp);
 		if (status & IM_ALLOC_INT) {
-			SMC_ACK_INT(IM_ALLOC_INT);
+			SMC_ACK_INT(lp, IM_ALLOC_INT);
   			break;
 		}
    	} while (--poll_count);
@@ -710,7 +710,7 @@
 		/* oh well, wait until the chip finds memory later */
 		netif_stop_queue(dev);
 		DBG(2, "%s: TX memory allocation deferred.\n", dev->name);
-		SMC_ENABLE_INT(IM_ALLOC_INT);
+		SMC_ENABLE_INT(lp, IM_ALLOC_INT);
    	} else {
 		/*
 		 * Allocation succeeded: push packet to the chip's own memory
@@ -736,19 +736,19 @@
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
 	/* If the TX FIFO is empty then nothing to do */
-	packet_no = SMC_GET_TXFIFO();
+	packet_no = SMC_GET_TXFIFO(lp);
 	if (unlikely(packet_no & TXFIFO_TEMPTY)) {
 		PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
 		return;
 	}
 
 	/* select packet to read from */
-	saved_packet = SMC_GET_PN();
-	SMC_SET_PN(packet_no);
+	saved_packet = SMC_GET_PN(lp);
+	SMC_SET_PN(lp, packet_no);
 
 	/* read the first word (status word) from this packet */
-	SMC_SET_PTR(PTR_AUTOINC | PTR_READ);
-	SMC_GET_PKT_HDR(tx_status, pkt_len);
+	SMC_SET_PTR(lp, PTR_AUTOINC | PTR_READ);
+	SMC_GET_PKT_HDR(lp, tx_status, pkt_len);
 	DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
 		dev->name, tx_status, packet_no);
 
@@ -771,17 +771,17 @@
 	}
 
 	/* kill the packet */
-	SMC_WAIT_MMU_BUSY();
-	SMC_SET_MMU_CMD(MC_FREEPKT);
+	SMC_WAIT_MMU_BUSY(lp);
+	SMC_SET_MMU_CMD(lp, MC_FREEPKT);
 
 	/* Don't restore Packet Number Reg until busy bit is cleared */
-	SMC_WAIT_MMU_BUSY();
-	SMC_SET_PN(saved_packet);
+	SMC_WAIT_MMU_BUSY(lp);
+	SMC_SET_PN(lp, saved_packet);
 
 	/* re-enable transmit */
-	SMC_SELECT_BANK(0);
-	SMC_SET_TCR(lp->tcr_cur_mode);
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_TCR(lp, lp->tcr_cur_mode);
+	SMC_SELECT_BANK(lp, 2);
 }
 
 
@@ -793,7 +793,7 @@
 	void __iomem *ioaddr = lp->base;
 	unsigned int mii_reg, mask;
 
-	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
+	mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
 	mii_reg |= MII_MDOE;
 
 	for (mask = 1 << (bits - 1); mask; mask >>= 1) {
@@ -802,9 +802,9 @@
 		else
 			mii_reg &= ~MII_MDO;
 
-		SMC_SET_MII(mii_reg);
+		SMC_SET_MII(lp, mii_reg);
 		udelay(MII_DELAY);
-		SMC_SET_MII(mii_reg | MII_MCLK);
+		SMC_SET_MII(lp, mii_reg | MII_MCLK);
 		udelay(MII_DELAY);
 	}
 }
@@ -815,16 +815,16 @@
 	void __iomem *ioaddr = lp->base;
 	unsigned int mii_reg, mask, val;
 
-	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
-	SMC_SET_MII(mii_reg);
+	mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
+	SMC_SET_MII(lp, mii_reg);
 
 	for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) {
-		if (SMC_GET_MII() & MII_MDI)
+		if (SMC_GET_MII(lp) & MII_MDI)
 			val |= mask;
 
-		SMC_SET_MII(mii_reg);
+		SMC_SET_MII(lp, mii_reg);
 		udelay(MII_DELAY);
-		SMC_SET_MII(mii_reg | MII_MCLK);
+		SMC_SET_MII(lp, mii_reg | MII_MCLK);
 		udelay(MII_DELAY);
 	}
 
@@ -840,7 +840,7 @@
 	void __iomem *ioaddr = lp->base;
 	unsigned int phydata;
 
-	SMC_SELECT_BANK(3);
+	SMC_SELECT_BANK(lp, 3);
 
 	/* Idle - 32 ones */
 	smc_mii_out(dev, 0xffffffff, 32);
@@ -852,12 +852,12 @@
 	phydata = smc_mii_in(dev, 18);
 
 	/* Return to idle state */
-	SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
+	SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
 
 	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
 		__FUNCTION__, phyaddr, phyreg, phydata);
 
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 2);
 	return phydata;
 }
 
@@ -870,7 +870,7 @@
 	struct smc_local *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 
-	SMC_SELECT_BANK(3);
+	SMC_SELECT_BANK(lp, 3);
 
 	/* Idle - 32 ones */
 	smc_mii_out(dev, 0xffffffff, 32);
@@ -879,12 +879,12 @@
 	smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32);
 
 	/* Return to idle state */
-	SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
+	SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
 
 	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
 		__FUNCTION__, phyaddr, phyreg, phydata);
 
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 2);
 }
 
 /*
@@ -957,9 +957,9 @@
 	smc_phy_write(dev, phyaddr, MII_BMCR, bmcr);
 
 	/* Re-Configure the Receive/Phy Control register */
-	SMC_SELECT_BANK(0);
-	SMC_SET_RPC(lp->rpc_cur_mode);
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_RPC(lp, lp->rpc_cur_mode);
+	SMC_SELECT_BANK(lp, 2);
 
 	return 1;
 }
@@ -1050,8 +1050,8 @@
 			lp->tcr_cur_mode &= ~TCR_SWFDUP;
 		}
 
-		SMC_SELECT_BANK(0);
-		SMC_SET_TCR(lp->tcr_cur_mode);
+		SMC_SELECT_BANK(lp, 0);
+		SMC_SET_TCR(lp, lp->tcr_cur_mode);
 	}
 }
 
@@ -1100,8 +1100,8 @@
 		PHY_INT_SPDDET | PHY_INT_DPLXDET);
 
 	/* Configure the Receive/Phy Control register */
-	SMC_SELECT_BANK(0);
-	SMC_SET_RPC(lp->rpc_cur_mode);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_RPC(lp, lp->rpc_cur_mode);
 
 	/* If the user requested no auto neg, then go set his request */
 	if (lp->mii.force_media) {
@@ -1158,7 +1158,7 @@
 	smc_phy_check_media(dev, 1);
 
 smc_phy_configure_exit:
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 2);
 	spin_unlock_irq(&lp->lock);
 	lp->work_pending = 0;
 }
@@ -1200,9 +1200,9 @@
 
 	old_carrier = netif_carrier_ok(dev) ? 1 : 0;
 
-	SMC_SELECT_BANK(0);
-	new_carrier = (SMC_GET_EPH_STATUS() & ES_LINK_OK) ? 1 : 0;
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 0);
+	new_carrier = (SMC_GET_EPH_STATUS(lp) & ES_LINK_OK) ? 1 : 0;
+	SMC_SELECT_BANK(lp, 2);
 
 	if (init || (old_carrier != new_carrier)) {
 		if (!new_carrier) {
@@ -1224,11 +1224,11 @@
 
 	smc_10bt_check_media(dev, 0);
 
-	SMC_SELECT_BANK(1);
-	ctl = SMC_GET_CTL();
-	SMC_SET_CTL(ctl & ~CTL_LE_ENABLE);
-	SMC_SET_CTL(ctl);
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 1);
+	ctl = SMC_GET_CTL(lp);
+	SMC_SET_CTL(lp, ctl & ~CTL_LE_ENABLE);
+	SMC_SET_CTL(lp, ctl);
+	SMC_SELECT_BANK(lp, 2);
 }
 
 /*
@@ -1252,22 +1252,22 @@
 	 * ISR. */
 	SMC_INTERRUPT_PREAMBLE;
 
-	saved_pointer = SMC_GET_PTR();
-	mask = SMC_GET_INT_MASK();
-	SMC_SET_INT_MASK(0);
+	saved_pointer = SMC_GET_PTR(lp);
+	mask = SMC_GET_INT_MASK(lp);
+	SMC_SET_INT_MASK(lp, 0);
 
 	/* set a timeout value, so I don't stay here forever */
 	timeout = MAX_IRQ_LOOPS;
 
 	do {
-		status = SMC_GET_INT();
+		status = SMC_GET_INT(lp);
 
 		DBG(2, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
 			dev->name, status, mask,
-			({ int meminfo; SMC_SELECT_BANK(0);
-			   meminfo = SMC_GET_MIR();
-			   SMC_SELECT_BANK(2); meminfo; }),
-			SMC_GET_FIFO());
+			({ int meminfo; SMC_SELECT_BANK(lp, 0);
+			   meminfo = SMC_GET_MIR(lp);
+			   SMC_SELECT_BANK(lp, 2); meminfo; }),
+			SMC_GET_FIFO(lp));
 
 		status &= mask;
 		if (!status)
@@ -1277,7 +1277,7 @@
 			/* do this before RX as it will free memory quickly */
 			DBG(3, "%s: TX int\n", dev->name);
 			smc_tx(dev);
-			SMC_ACK_INT(IM_TX_INT);
+			SMC_ACK_INT(lp, IM_TX_INT);
 			if (THROTTLE_TX_PKTS)
 				netif_wake_queue(dev);
 		} else if (status & IM_RCV_INT) {
@@ -1292,9 +1292,9 @@
 			mask &= ~IM_TX_EMPTY_INT;
 
 			/* update stats */
-			SMC_SELECT_BANK(0);
-			card_stats = SMC_GET_COUNTER();
-			SMC_SELECT_BANK(2);
+			SMC_SELECT_BANK(lp, 0);
+			card_stats = SMC_GET_COUNTER(lp);
+			SMC_SELECT_BANK(lp, 2);
 
 			/* single collisions */
 			dev->stats.collisions += card_stats & 0xF;
@@ -1304,26 +1304,26 @@
 			dev->stats.collisions += card_stats & 0xF;
 		} else if (status & IM_RX_OVRN_INT) {
 			DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
-			       ({ int eph_st; SMC_SELECT_BANK(0);
-				  eph_st = SMC_GET_EPH_STATUS();
-				  SMC_SELECT_BANK(2); eph_st; }) );
-			SMC_ACK_INT(IM_RX_OVRN_INT);
+			       ({ int eph_st; SMC_SELECT_BANK(lp, 0);
+				  eph_st = SMC_GET_EPH_STATUS(lp);
+				  SMC_SELECT_BANK(lp, 2); eph_st; }));
+			SMC_ACK_INT(lp, IM_RX_OVRN_INT);
 			dev->stats.rx_errors++;
 			dev->stats.rx_fifo_errors++;
 		} else if (status & IM_EPH_INT) {
 			smc_eph_interrupt(dev);
 		} else if (status & IM_MDINT) {
-			SMC_ACK_INT(IM_MDINT);
+			SMC_ACK_INT(lp, IM_MDINT);
 			smc_phy_interrupt(dev);
 		} else if (status & IM_ERCV_INT) {
-			SMC_ACK_INT(IM_ERCV_INT);
+			SMC_ACK_INT(lp, IM_ERCV_INT);
 			PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
 		}
 	} while (--timeout);
 
 	/* restore register states */
-	SMC_SET_PTR(saved_pointer);
-	SMC_SET_INT_MASK(mask);
+	SMC_SET_PTR(lp, saved_pointer);
+	SMC_SET_INT_MASK(lp, mask);
 	spin_unlock(&lp->lock);
 
 	if (timeout == MAX_IRQ_LOOPS)
@@ -1366,13 +1366,13 @@
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
 	spin_lock_irq(&lp->lock);
-	status = SMC_GET_INT();
-	mask = SMC_GET_INT_MASK();
-	fifo = SMC_GET_FIFO();
-	SMC_SELECT_BANK(0);
-	eph_st = SMC_GET_EPH_STATUS();
-	meminfo = SMC_GET_MIR();
-	SMC_SELECT_BANK(2);
+	status = SMC_GET_INT(lp);
+	mask = SMC_GET_INT_MASK(lp);
+	fifo = SMC_GET_FIFO(lp);
+	SMC_SELECT_BANK(lp, 0);
+	eph_st = SMC_GET_EPH_STATUS(lp);
+	meminfo = SMC_GET_MIR(lp);
+	SMC_SELECT_BANK(lp, 2);
 	spin_unlock_irq(&lp->lock);
 	PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x "
 		"MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n",
@@ -1492,13 +1492,13 @@
 	}
 
 	spin_lock_irq(&lp->lock);
-	SMC_SELECT_BANK(0);
-	SMC_SET_RCR(lp->rcr_cur_mode);
+	SMC_SELECT_BANK(lp, 0);
+	SMC_SET_RCR(lp, lp->rcr_cur_mode);
 	if (update_multicast) {
-		SMC_SELECT_BANK(3);
-		SMC_SET_MCAST(multicast_table);
+		SMC_SELECT_BANK(lp, 3);
+		SMC_SET_MCAST(lp, multicast_table);
 	}
-	SMC_SELECT_BANK(2);
+	SMC_SELECT_BANK(lp, 2);
 	spin_unlock_irq(&lp->lock);
 }
 
@@ -1702,8 +1702,9 @@
  * I just deleted auto_irq.c, since it was never built...
  *   --jgarzik
  */
-static int __init smc_findirq(void __iomem *ioaddr)
+static int __init smc_findirq(struct smc_local *lp)
 {
+	void __iomem *ioaddr = lp->base;
 	int timeout = 20;
 	unsigned long cookie;
 
@@ -1717,14 +1718,14 @@
 	 * when done.
 	 */
 	/* enable ALLOCation interrupts ONLY */
-	SMC_SELECT_BANK(2);
-	SMC_SET_INT_MASK(IM_ALLOC_INT);
+	SMC_SELECT_BANK(lp, 2);
+	SMC_SET_INT_MASK(lp, IM_ALLOC_INT);
 
 	/*
  	 * Allocate 512 bytes of memory.  Note that the chip was just
 	 * reset so all the memory is available
 	 */
-	SMC_SET_MMU_CMD(MC_ALLOC | 1);
+	SMC_SET_MMU_CMD(lp, MC_ALLOC | 1);
 
 	/*
 	 * Wait until positive that the interrupt has been generated
@@ -1732,7 +1733,7 @@
 	do {
 		int int_status;
 		udelay(10);
-		int_status = SMC_GET_INT();
+		int_status = SMC_GET_INT(lp);
 		if (int_status & IM_ALLOC_INT)
 			break;		/* got the interrupt */
 	} while (--timeout);
@@ -1745,7 +1746,7 @@
 	 */
 
 	/* and disable all interrupts again */
-	SMC_SET_INT_MASK(0);
+	SMC_SET_INT_MASK(lp, 0);
 
 	/* and return what I found */
 	return probe_irq_off(cookie);
@@ -1788,7 +1789,7 @@
 	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
 
 	/* First, see if the high byte is 0x33 */
-	val = SMC_CURRENT_BANK();
+	val = SMC_CURRENT_BANK(lp);
 	DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
 	if ((val & 0xFF00) != 0x3300) {
 		if ((val & 0xFF) == 0x33) {
@@ -1804,8 +1805,8 @@
 	 * The above MIGHT indicate a device, but I need to write to
 	 * further test this.
 	 */
-	SMC_SELECT_BANK(0);
-	val = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(lp, 0);
+	val = SMC_CURRENT_BANK(lp);
 	if ((val & 0xFF00) != 0x3300) {
 		retval = -ENODEV;
 		goto err_out;
@@ -1817,8 +1818,8 @@
 	 * register to bank 1, so I can access the base address
 	 * register
 	 */
-	SMC_SELECT_BANK(1);
-	val = SMC_GET_BASE();
+	SMC_SELECT_BANK(lp, 1);
+	val = SMC_GET_BASE(lp);
 	val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
 	if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
 		printk("%s: IOADDR %p doesn't match configuration (%x).\n",
@@ -1830,8 +1831,8 @@
 	 * recognize.  These might need to be added to later,
 	 * as future revisions could be added.
 	 */
-	SMC_SELECT_BANK(3);
-	revision_register = SMC_GET_REV();
+	SMC_SELECT_BANK(lp, 3);
+	revision_register = SMC_GET_REV(lp);
 	DBG(2, "%s: revision = 0x%04x\n", CARDNAME, revision_register);
 	version_string = chip_ids[ (revision_register >> 4) & 0xF];
 	if (!version_string || (revision_register & 0xff00) != 0x3300) {
@@ -1855,8 +1856,8 @@
 	spin_lock_init(&lp->lock);
 
 	/* Get the MAC address */
-	SMC_SELECT_BANK(1);
-	SMC_GET_MAC_ADDR(dev->dev_addr);
+	SMC_SELECT_BANK(lp, 1);
+	SMC_GET_MAC_ADDR(lp, dev->dev_addr);
 
 	/* now, reset the chip, and put it into a known state */
 	smc_reset(dev);
@@ -1881,7 +1882,7 @@
 
 		trials = 3;
 		while (trials--) {
-			dev->irq = smc_findirq(ioaddr);
+			dev->irq = smc_findirq(lp);
 			if (dev->irq)
 				break;
 			/* kick the card and try again */
@@ -1996,6 +1997,8 @@
 
 static int smc_enable_device(struct platform_device *pdev)
 {
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct smc_local *lp = netdev_priv(ndev);
 	unsigned long flags;
 	unsigned char ecor, ecsr;
 	void __iomem *addr;
@@ -2038,7 +2041,7 @@
 	 * Set the appropriate byte/word mode.
 	 */
 	ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8;
-	if (!SMC_CAN_USE_16BIT)
+	if (!SMC_16BIT(lp))
 		ecsr |= ECSR_IOIS8;
 	writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT));
 	local_irq_restore(flags);
@@ -2123,10 +2126,11 @@
  */
 static int smc_drv_probe(struct platform_device *pdev)
 {
+	struct smc91x_platdata *pd = pdev->dev.platform_data;
+	struct smc_local *lp;
 	struct net_device *ndev;
 	struct resource *res, *ires;
 	unsigned int __iomem *addr;
-	unsigned long irq_flags = SMC_IRQ_FLAGS;
 	int ret;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
@@ -2151,6 +2155,27 @@
 	}
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
+	/* get configuration from platform data, only allow use of
+	 * bus width if both SMC_CAN_USE_xxx and SMC91X_USE_xxx are set.
+	 */
+
+	lp = netdev_priv(ndev);
+	lp->cfg.irq_flags = SMC_IRQ_FLAGS;
+
+#ifdef SMC_DYNAMIC_BUS_CONFIG
+	if (pd)
+		memcpy(&lp->cfg, pd, sizeof(lp->cfg));
+	else {
+		lp->cfg.flags = SMC91X_USE_8BIT;
+		lp->cfg.flags |= SMC91X_USE_16BIT;
+		lp->cfg.flags |= SMC91X_USE_32BIT;
+	}
+
+	lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
+	lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
+	lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
+#endif
+
 	ndev->dma = (unsigned char)-1;
 
 	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -2161,7 +2186,7 @@
 
 	ndev->irq = ires->start;
 	if (SMC_IRQ_FLAGS == -1)
-		irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+		lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
 
 	ret = smc_request_attrib(pdev);
 	if (ret)
@@ -2169,6 +2194,7 @@
 #if defined(CONFIG_SA1100_ASSABET)
 	NCR_0 |= NCR_ENET_OSC_EN;
 #endif
+	platform_set_drvdata(pdev, ndev);
 	ret = smc_enable_device(pdev);
 	if (ret)
 		goto out_release_attrib;
@@ -2187,8 +2213,7 @@
 	}
 #endif
 
-	platform_set_drvdata(pdev, ndev);
-	ret = smc_probe(ndev, addr, irq_flags);
+	ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
 	if (ret != 0)
 		goto out_iounmap;
 
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 51d4134..69e97a1 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -34,6 +34,7 @@
 #ifndef _SMC91X_H_
 #define _SMC91X_H_
 
+#include <linux/smc91x.h>
 
 /*
  * Define your architecture specific bus configuration parameters here.
@@ -291,36 +292,6 @@
 #define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
 
-#elif   defined(CONFIG_SUPERH)
-
-#ifdef CONFIG_SOLUTION_ENGINE
-#define SMC_IRQ_FLAGS		(0)
-#define SMC_CAN_USE_8BIT       0
-#define SMC_CAN_USE_16BIT      1
-#define SMC_CAN_USE_32BIT      0
-#define SMC_IO_SHIFT           0
-#define SMC_NOWAIT             1
-
-#define SMC_inw(a, r)          inw((a) + (r))
-#define SMC_outw(v, a, r)      outw(v, (a) + (r))
-#define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
-
-#else /* BOARDS */
-
-#define SMC_CAN_USE_8BIT       1
-#define SMC_CAN_USE_16BIT      1
-#define SMC_CAN_USE_32BIT      0
-
-#define SMC_inb(a, r)          inb((a) + (r))
-#define SMC_inw(a, r)          inw((a) + (r))
-#define SMC_outb(v, a, r)      outb(v, (a) + (r))
-#define SMC_outw(v, a, r)      outw(v, (a) + (r))
-#define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
-
-#endif  /* BOARDS */
-
 #elif   defined(CONFIG_M32R)
 
 #define SMC_CAN_USE_8BIT	0
@@ -475,12 +446,15 @@
 #define SMC_outb(v, a, r)	writeb(v, (a) + (r))
 #define SMC_outw(v, a, r)	writew(v, (a) + (r))
 #define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
 #define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
 #define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
 
 #define RPC_LSA_DEFAULT		RPC_LED_100_10
 #define RPC_LSB_DEFAULT		RPC_LED_TX_RX
 
+#define SMC_DYNAMIC_BUS_CONFIG
 #endif
 
 
@@ -526,8 +500,19 @@
 #endif
 	void __iomem *base;
 	void __iomem *datacs;
+
+	struct smc91x_platdata cfg;
 };
 
+#ifdef SMC_DYNAMIC_BUS_CONFIG
+#define SMC_8BIT(p) (((p)->cfg.flags & SMC91X_USE_8BIT) && SMC_CAN_USE_8BIT)
+#define SMC_16BIT(p) (((p)->cfg.flags & SMC91X_USE_16BIT) && SMC_CAN_USE_16BIT)
+#define SMC_32BIT(p) (((p)->cfg.flags & SMC91X_USE_32BIT) && SMC_CAN_USE_32BIT)
+#else
+#define SMC_8BIT(p) SMC_CAN_USE_8BIT
+#define SMC_16BIT(p) SMC_CAN_USE_16BIT
+#define SMC_32BIT(p) SMC_CAN_USE_32BIT
+#endif
 
 #ifdef SMC_USE_PXA_DMA
 /*
@@ -720,7 +705,7 @@
 
 // Transmit Control Register
 /* BANK 0  */
-#define TCR_REG 	SMC_REG(0x0000, 0)
+#define TCR_REG(lp) 	SMC_REG(lp, 0x0000, 0)
 #define TCR_ENABLE	0x0001	// When 1 we can transmit
 #define TCR_LOOP	0x0002	// Controls output pin LBK
 #define TCR_FORCOL	0x0004	// When 1 will force a collision
@@ -739,7 +724,7 @@
 
 // EPH Status Register
 /* BANK 0  */
-#define EPH_STATUS_REG	SMC_REG(0x0002, 0)
+#define EPH_STATUS_REG(lp)	SMC_REG(lp, 0x0002, 0)
 #define ES_TX_SUC	0x0001	// Last TX was successful
 #define ES_SNGL_COL	0x0002	// Single collision detected for last tx
 #define ES_MUL_COL	0x0004	// Multiple collisions detected for last tx
@@ -758,7 +743,7 @@
 
 // Receive Control Register
 /* BANK 0  */
-#define RCR_REG		SMC_REG(0x0004, 0)
+#define RCR_REG(lp)		SMC_REG(lp, 0x0004, 0)
 #define RCR_RX_ABORT	0x0001	// Set if a rx frame was aborted
 #define RCR_PRMS	0x0002	// Enable promiscuous mode
 #define RCR_ALMUL	0x0004	// When set accepts all multicast frames
@@ -775,17 +760,17 @@
 
 // Counter Register
 /* BANK 0  */
-#define COUNTER_REG	SMC_REG(0x0006, 0)
+#define COUNTER_REG(lp)	SMC_REG(lp, 0x0006, 0)
 
 
 // Memory Information Register
 /* BANK 0  */
-#define MIR_REG		SMC_REG(0x0008, 0)
+#define MIR_REG(lp)		SMC_REG(lp, 0x0008, 0)
 
 
 // Receive/Phy Control Register
 /* BANK 0  */
-#define RPC_REG		SMC_REG(0x000A, 0)
+#define RPC_REG(lp)		SMC_REG(lp, 0x000A, 0)
 #define RPC_SPEED	0x2000	// When 1 PHY is in 100Mbps mode.
 #define RPC_DPLX	0x1000	// When 1 PHY is in Full-Duplex Mode
 #define RPC_ANEG	0x0800	// When 1 PHY is in Auto-Negotiate Mode
@@ -819,7 +804,7 @@
 
 // Configuration Reg
 /* BANK 1 */
-#define CONFIG_REG	SMC_REG(0x0000,	1)
+#define CONFIG_REG(lp)	SMC_REG(lp, 0x0000,	1)
 #define CONFIG_EXT_PHY	0x0200	// 1=external MII, 0=internal Phy
 #define CONFIG_GPCNTRL	0x0400	// Inverse value drives pin nCNTRL
 #define CONFIG_NO_WAIT	0x1000	// When 1 no extra wait states on ISA bus
@@ -831,24 +816,24 @@
 
 // Base Address Register
 /* BANK 1 */
-#define BASE_REG	SMC_REG(0x0002, 1)
+#define BASE_REG(lp)	SMC_REG(lp, 0x0002, 1)
 
 
 // Individual Address Registers
 /* BANK 1 */
-#define ADDR0_REG	SMC_REG(0x0004, 1)
-#define ADDR1_REG	SMC_REG(0x0006, 1)
-#define ADDR2_REG	SMC_REG(0x0008, 1)
+#define ADDR0_REG(lp)	SMC_REG(lp, 0x0004, 1)
+#define ADDR1_REG(lp)	SMC_REG(lp, 0x0006, 1)
+#define ADDR2_REG(lp)	SMC_REG(lp, 0x0008, 1)
 
 
 // General Purpose Register
 /* BANK 1 */
-#define GP_REG		SMC_REG(0x000A, 1)
+#define GP_REG(lp)		SMC_REG(lp, 0x000A, 1)
 
 
 // Control Register
 /* BANK 1 */
-#define CTL_REG		SMC_REG(0x000C, 1)
+#define CTL_REG(lp)		SMC_REG(lp, 0x000C, 1)
 #define CTL_RCV_BAD	0x4000 // When 1 bad CRC packets are received
 #define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
 #define CTL_LE_ENABLE	0x0080 // When 1 enables Link Error interrupt
@@ -861,7 +846,7 @@
 
 // MMU Command Register
 /* BANK 2 */
-#define MMU_CMD_REG	SMC_REG(0x0000, 2)
+#define MMU_CMD_REG(lp)	SMC_REG(lp, 0x0000, 2)
 #define MC_BUSY		1	// When 1 the last release has not completed
 #define MC_NOP		(0<<5)	// No Op
 #define MC_ALLOC	(1<<5) 	// OR with number of 256 byte packets
@@ -875,30 +860,30 @@
 
 // Packet Number Register
 /* BANK 2 */
-#define PN_REG		SMC_REG(0x0002, 2)
+#define PN_REG(lp)		SMC_REG(lp, 0x0002, 2)
 
 
 // Allocation Result Register
 /* BANK 2 */
-#define AR_REG		SMC_REG(0x0003, 2)
+#define AR_REG(lp)		SMC_REG(lp, 0x0003, 2)
 #define AR_FAILED	0x80	// Alocation Failed
 
 
 // TX FIFO Ports Register
 /* BANK 2 */
-#define TXFIFO_REG	SMC_REG(0x0004, 2)
+#define TXFIFO_REG(lp)	SMC_REG(lp, 0x0004, 2)
 #define TXFIFO_TEMPTY	0x80	// TX FIFO Empty
 
 // RX FIFO Ports Register
 /* BANK 2 */
-#define RXFIFO_REG	SMC_REG(0x0005, 2)
+#define RXFIFO_REG(lp)	SMC_REG(lp, 0x0005, 2)
 #define RXFIFO_REMPTY	0x80	// RX FIFO Empty
 
-#define FIFO_REG	SMC_REG(0x0004, 2)
+#define FIFO_REG(lp)	SMC_REG(lp, 0x0004, 2)
 
 // Pointer Register
 /* BANK 2 */
-#define PTR_REG		SMC_REG(0x0006, 2)
+#define PTR_REG(lp)		SMC_REG(lp, 0x0006, 2)
 #define PTR_RCV		0x8000 // 1=Receive area, 0=Transmit area
 #define PTR_AUTOINC 	0x4000 // Auto increment the pointer on each access
 #define PTR_READ	0x2000 // When 1 the operation is a read
@@ -906,17 +891,17 @@
 
 // Data Register
 /* BANK 2 */
-#define DATA_REG	SMC_REG(0x0008, 2)
+#define DATA_REG(lp)	SMC_REG(lp, 0x0008, 2)
 
 
 // Interrupt Status/Acknowledge Register
 /* BANK 2 */
-#define INT_REG		SMC_REG(0x000C, 2)
+#define INT_REG(lp)		SMC_REG(lp, 0x000C, 2)
 
 
 // Interrupt Mask Register
 /* BANK 2 */
-#define IM_REG		SMC_REG(0x000D, 2)
+#define IM_REG(lp)		SMC_REG(lp, 0x000D, 2)
 #define IM_MDINT	0x80 // PHY MI Register 18 Interrupt
 #define IM_ERCV_INT	0x40 // Early Receive Interrupt
 #define IM_EPH_INT	0x20 // Set by Ethernet Protocol Handler section
@@ -929,15 +914,15 @@
 
 // Multicast Table Registers
 /* BANK 3 */
-#define MCAST_REG1	SMC_REG(0x0000, 3)
-#define MCAST_REG2	SMC_REG(0x0002, 3)
-#define MCAST_REG3	SMC_REG(0x0004, 3)
-#define MCAST_REG4	SMC_REG(0x0006, 3)
+#define MCAST_REG1(lp)	SMC_REG(lp, 0x0000, 3)
+#define MCAST_REG2(lp)	SMC_REG(lp, 0x0002, 3)
+#define MCAST_REG3(lp)	SMC_REG(lp, 0x0004, 3)
+#define MCAST_REG4(lp)	SMC_REG(lp, 0x0006, 3)
 
 
 // Management Interface Register (MII)
 /* BANK 3 */
-#define MII_REG		SMC_REG(0x0008, 3)
+#define MII_REG(lp)		SMC_REG(lp, 0x0008, 3)
 #define MII_MSK_CRS100	0x4000 // Disables CRS100 detection during tx half dup
 #define MII_MDOE	0x0008 // MII Output Enable
 #define MII_MCLK	0x0004 // MII Clock, pin MDCLK
@@ -948,20 +933,20 @@
 // Revision Register
 /* BANK 3 */
 /* ( hi: chip id   low: rev # ) */
-#define REV_REG		SMC_REG(0x000A, 3)
+#define REV_REG(lp)		SMC_REG(lp, 0x000A, 3)
 
 
 // Early RCV Register
 /* BANK 3 */
 /* this is NOT on SMC9192 */
-#define ERCV_REG	SMC_REG(0x000C, 3)
+#define ERCV_REG(lp)	SMC_REG(lp, 0x000C, 3)
 #define ERCV_RCV_DISCRD	0x0080 // When 1 discards a packet being received
 #define ERCV_THRESHOLD	0x001F // ERCV Threshold Mask
 
 
 // External Register
 /* BANK 7 */
-#define EXT_REG		SMC_REG(0x0000, 7)
+#define EXT_REG(lp)		SMC_REG(lp, 0x0000, 7)
 
 
 #define CHIP_9192	3
@@ -1085,9 +1070,9 @@
  */
 
 #if SMC_DEBUG > 0
-#define SMC_REG(reg, bank)						\
+#define SMC_REG(lp, reg, bank)					\
 	({								\
-		int __b = SMC_CURRENT_BANK();				\
+		int __b = SMC_CURRENT_BANK(lp);			\
 		if (unlikely((__b & ~0xf0) != (0x3300 | bank))) {	\
 			printk( "%s: bank reg screwed (0x%04x)\n",	\
 				CARDNAME, __b );			\
@@ -1096,7 +1081,7 @@
 		reg<<SMC_IO_SHIFT;					\
 	})
 #else
-#define SMC_REG(reg, bank)	(reg<<SMC_IO_SHIFT)
+#define SMC_REG(lp, reg, bank)	(reg<<SMC_IO_SHIFT)
 #endif
 
 /*
@@ -1108,212 +1093,215 @@
  *
  * Enforce it on any 32-bit capable setup for now.
  */
-#define SMC_MUST_ALIGN_WRITE	SMC_CAN_USE_32BIT
+#define SMC_MUST_ALIGN_WRITE(lp)	SMC_32BIT(lp)
 
-#define SMC_GET_PN()							\
-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, PN_REG))		\
-				: (SMC_inw(ioaddr, PN_REG) & 0xFF) )
+#define SMC_GET_PN(lp)						\
+	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, PN_REG(lp)))	\
+				: (SMC_inw(ioaddr, PN_REG(lp)) & 0xFF))
 
-#define SMC_SET_PN(x)							\
+#define SMC_SET_PN(lp, x)						\
 	do {								\
-		if (SMC_MUST_ALIGN_WRITE)				\
-			SMC_outl((x)<<16, ioaddr, SMC_REG(0, 2));	\
-		else if (SMC_CAN_USE_8BIT)				\
-			SMC_outb(x, ioaddr, PN_REG);			\
+		if (SMC_MUST_ALIGN_WRITE(lp))				\
+			SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 0, 2));	\
+		else if (SMC_8BIT(lp))				\
+			SMC_outb(x, ioaddr, PN_REG(lp));		\
 		else							\
-			SMC_outw(x, ioaddr, PN_REG);			\
+			SMC_outw(x, ioaddr, PN_REG(lp));		\
 	} while (0)
 
-#define SMC_GET_AR()							\
-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, AR_REG))		\
-	  			: (SMC_inw(ioaddr, PN_REG) >> 8) )
+#define SMC_GET_AR(lp)						\
+	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, AR_REG(lp)))	\
+				: (SMC_inw(ioaddr, PN_REG(lp)) >> 8))
 
-#define SMC_GET_TXFIFO()						\
-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, TXFIFO_REG))		\
-				: (SMC_inw(ioaddr, TXFIFO_REG) & 0xFF) )
+#define SMC_GET_TXFIFO(lp)						\
+	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, TXFIFO_REG(lp)))	\
+				: (SMC_inw(ioaddr, TXFIFO_REG(lp)) & 0xFF))
 
-#define SMC_GET_RXFIFO()						\
-	  ( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, RXFIFO_REG))		\
-				: (SMC_inw(ioaddr, TXFIFO_REG) >> 8) )
+#define SMC_GET_RXFIFO(lp)						\
+	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, RXFIFO_REG(lp)))	\
+				: (SMC_inw(ioaddr, TXFIFO_REG(lp)) >> 8))
 
-#define SMC_GET_INT()							\
-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, INT_REG))		\
-				: (SMC_inw(ioaddr, INT_REG) & 0xFF) )
+#define SMC_GET_INT(lp)						\
+	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, INT_REG(lp)))	\
+				: (SMC_inw(ioaddr, INT_REG(lp)) & 0xFF))
 
-#define SMC_ACK_INT(x)							\
+#define SMC_ACK_INT(lp, x)						\
 	do {								\
-		if (SMC_CAN_USE_8BIT)					\
-			SMC_outb(x, ioaddr, INT_REG);			\
+		if (SMC_8BIT(lp))					\
+			SMC_outb(x, ioaddr, INT_REG(lp));		\
 		else {							\
 			unsigned long __flags;				\
 			int __mask;					\
 			local_irq_save(__flags);			\
-			__mask = SMC_inw( ioaddr, INT_REG ) & ~0xff;	\
-			SMC_outw( __mask | (x), ioaddr, INT_REG );	\
+			__mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \
+			SMC_outw(__mask | (x), ioaddr, INT_REG(lp));	\
 			local_irq_restore(__flags);			\
 		}							\
 	} while (0)
 
-#define SMC_GET_INT_MASK()						\
-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, IM_REG))		\
-				: (SMC_inw( ioaddr, INT_REG ) >> 8) )
+#define SMC_GET_INT_MASK(lp)						\
+	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, IM_REG(lp)))	\
+				: (SMC_inw(ioaddr, INT_REG(lp)) >> 8))
 
-#define SMC_SET_INT_MASK(x)						\
+#define SMC_SET_INT_MASK(lp, x)					\
 	do {								\
-		if (SMC_CAN_USE_8BIT)					\
-			SMC_outb(x, ioaddr, IM_REG);			\
+		if (SMC_8BIT(lp))					\
+			SMC_outb(x, ioaddr, IM_REG(lp));		\
 		else							\
-			SMC_outw((x) << 8, ioaddr, INT_REG);		\
+			SMC_outw((x) << 8, ioaddr, INT_REG(lp));	\
 	} while (0)
 
-#define SMC_CURRENT_BANK()	SMC_inw(ioaddr, BANK_SELECT)
+#define SMC_CURRENT_BANK(lp)	SMC_inw(ioaddr, BANK_SELECT)
 
-#define SMC_SELECT_BANK(x)						\
+#define SMC_SELECT_BANK(lp, x)					\
 	do {								\
-		if (SMC_MUST_ALIGN_WRITE)				\
+		if (SMC_MUST_ALIGN_WRITE(lp))				\
 			SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT);	\
 		else							\
 			SMC_outw(x, ioaddr, BANK_SELECT);		\
 	} while (0)
 
-#define SMC_GET_BASE()		SMC_inw(ioaddr, BASE_REG)
+#define SMC_GET_BASE(lp)		SMC_inw(ioaddr, BASE_REG(lp))
 
-#define SMC_SET_BASE(x)		SMC_outw(x, ioaddr, BASE_REG)
+#define SMC_SET_BASE(lp, x)		SMC_outw(x, ioaddr, BASE_REG(lp))
 
-#define SMC_GET_CONFIG()	SMC_inw(ioaddr, CONFIG_REG)
+#define SMC_GET_CONFIG(lp)	SMC_inw(ioaddr, CONFIG_REG(lp))
 
-#define SMC_SET_CONFIG(x)	SMC_outw(x, ioaddr, CONFIG_REG)
+#define SMC_SET_CONFIG(lp, x)	SMC_outw(x, ioaddr, CONFIG_REG(lp))
 
-#define SMC_GET_COUNTER()	SMC_inw(ioaddr, COUNTER_REG)
+#define SMC_GET_COUNTER(lp)	SMC_inw(ioaddr, COUNTER_REG(lp))
 
-#define SMC_GET_CTL()		SMC_inw(ioaddr, CTL_REG)
+#define SMC_GET_CTL(lp)		SMC_inw(ioaddr, CTL_REG(lp))
 
-#define SMC_SET_CTL(x)		SMC_outw(x, ioaddr, CTL_REG)
+#define SMC_SET_CTL(lp, x)		SMC_outw(x, ioaddr, CTL_REG(lp))
 
-#define SMC_GET_MII()		SMC_inw(ioaddr, MII_REG)
+#define SMC_GET_MII(lp)		SMC_inw(ioaddr, MII_REG(lp))
 
-#define SMC_SET_MII(x)		SMC_outw(x, ioaddr, MII_REG)
+#define SMC_SET_MII(lp, x)		SMC_outw(x, ioaddr, MII_REG(lp))
 
-#define SMC_GET_MIR()		SMC_inw(ioaddr, MIR_REG)
+#define SMC_GET_MIR(lp)		SMC_inw(ioaddr, MIR_REG(lp))
 
-#define SMC_SET_MIR(x)		SMC_outw(x, ioaddr, MIR_REG)
+#define SMC_SET_MIR(lp, x)		SMC_outw(x, ioaddr, MIR_REG(lp))
 
-#define SMC_GET_MMU_CMD()	SMC_inw(ioaddr, MMU_CMD_REG)
+#define SMC_GET_MMU_CMD(lp)	SMC_inw(ioaddr, MMU_CMD_REG(lp))
 
-#define SMC_SET_MMU_CMD(x)	SMC_outw(x, ioaddr, MMU_CMD_REG)
+#define SMC_SET_MMU_CMD(lp, x)	SMC_outw(x, ioaddr, MMU_CMD_REG(lp))
 
-#define SMC_GET_FIFO()		SMC_inw(ioaddr, FIFO_REG)
+#define SMC_GET_FIFO(lp)		SMC_inw(ioaddr, FIFO_REG(lp))
 
-#define SMC_GET_PTR()		SMC_inw(ioaddr, PTR_REG)
+#define SMC_GET_PTR(lp)		SMC_inw(ioaddr, PTR_REG(lp))
 
-#define SMC_SET_PTR(x)							\
+#define SMC_SET_PTR(lp, x)						\
 	do {								\
-		if (SMC_MUST_ALIGN_WRITE)				\
-			SMC_outl((x)<<16, ioaddr, SMC_REG(4, 2));	\
+		if (SMC_MUST_ALIGN_WRITE(lp))				\
+			SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2));	\
 		else							\
-			SMC_outw(x, ioaddr, PTR_REG);			\
+			SMC_outw(x, ioaddr, PTR_REG(lp));		\
 	} while (0)
 
-#define SMC_GET_EPH_STATUS()	SMC_inw(ioaddr, EPH_STATUS_REG)
+#define SMC_GET_EPH_STATUS(lp)	SMC_inw(ioaddr, EPH_STATUS_REG(lp))
 
-#define SMC_GET_RCR()		SMC_inw(ioaddr, RCR_REG)
+#define SMC_GET_RCR(lp)		SMC_inw(ioaddr, RCR_REG(lp))
 
-#define SMC_SET_RCR(x)		SMC_outw(x, ioaddr, RCR_REG)
+#define SMC_SET_RCR(lp, x)		SMC_outw(x, ioaddr, RCR_REG(lp))
 
-#define SMC_GET_REV()		SMC_inw(ioaddr, REV_REG)
+#define SMC_GET_REV(lp)		SMC_inw(ioaddr, REV_REG(lp))
 
-#define SMC_GET_RPC()		SMC_inw(ioaddr, RPC_REG)
+#define SMC_GET_RPC(lp)		SMC_inw(ioaddr, RPC_REG(lp))
 
-#define SMC_SET_RPC(x)							\
+#define SMC_SET_RPC(lp, x)						\
 	do {								\
-		if (SMC_MUST_ALIGN_WRITE)				\
-			SMC_outl((x)<<16, ioaddr, SMC_REG(8, 0));	\
+		if (SMC_MUST_ALIGN_WRITE(lp))				\
+			SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0));	\
 		else							\
-			SMC_outw(x, ioaddr, RPC_REG);			\
+			SMC_outw(x, ioaddr, RPC_REG(lp));		\
 	} while (0)
 
-#define SMC_GET_TCR()		SMC_inw(ioaddr, TCR_REG)
+#define SMC_GET_TCR(lp)		SMC_inw(ioaddr, TCR_REG(lp))
 
-#define SMC_SET_TCR(x)		SMC_outw(x, ioaddr, TCR_REG)
+#define SMC_SET_TCR(lp, x)		SMC_outw(x, ioaddr, TCR_REG(lp))
 
 #ifndef SMC_GET_MAC_ADDR
-#define SMC_GET_MAC_ADDR(addr)						\
+#define SMC_GET_MAC_ADDR(lp, addr)					\
 	do {								\
 		unsigned int __v;					\
-		__v = SMC_inw( ioaddr, ADDR0_REG );			\
+		__v = SMC_inw(ioaddr, ADDR0_REG(lp));			\
 		addr[0] = __v; addr[1] = __v >> 8;			\
-		__v = SMC_inw( ioaddr, ADDR1_REG );			\
+		__v = SMC_inw(ioaddr, ADDR1_REG(lp));			\
 		addr[2] = __v; addr[3] = __v >> 8;			\
-		__v = SMC_inw( ioaddr, ADDR2_REG );			\
+		__v = SMC_inw(ioaddr, ADDR2_REG(lp));			\
 		addr[4] = __v; addr[5] = __v >> 8;			\
 	} while (0)
 #endif
 
-#define SMC_SET_MAC_ADDR(addr)						\
+#define SMC_SET_MAC_ADDR(lp, addr)					\
 	do {								\
-		SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG );	\
-		SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG );	\
-		SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG );	\
+		SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
+		SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
+		SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
 	} while (0)
 
-#define SMC_SET_MCAST(x)						\
+#define SMC_SET_MCAST(lp, x)						\
 	do {								\
 		const unsigned char *mt = (x);				\
-		SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 );	\
-		SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 );	\
-		SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 );	\
-		SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 );	\
+		SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
+		SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
+		SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
+		SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
 	} while (0)
 
-#define SMC_PUT_PKT_HDR(status, length)					\
+#define SMC_PUT_PKT_HDR(lp, status, length)				\
 	do {								\
-		if (SMC_CAN_USE_32BIT)					\
-			SMC_outl((status) | (length)<<16, ioaddr, DATA_REG); \
+		if (SMC_32BIT(lp))					\
+			SMC_outl((status) | (length)<<16, ioaddr,	\
+				 DATA_REG(lp));			\
 		else {							\
-			SMC_outw(status, ioaddr, DATA_REG);		\
-			SMC_outw(length, ioaddr, DATA_REG);		\
+			SMC_outw(status, ioaddr, DATA_REG(lp));	\
+			SMC_outw(length, ioaddr, DATA_REG(lp));	\
 		}							\
 	} while (0)
 
-#define SMC_GET_PKT_HDR(status, length)					\
+#define SMC_GET_PKT_HDR(lp, status, length)				\
 	do {								\
-		if (SMC_CAN_USE_32BIT) {				\
-			unsigned int __val = SMC_inl(ioaddr, DATA_REG);	\
+		if (SMC_32BIT(lp)) {				\
+			unsigned int __val = SMC_inl(ioaddr, DATA_REG(lp)); \
 			(status) = __val & 0xffff;			\
 			(length) = __val >> 16;				\
 		} else {						\
-			(status) = SMC_inw(ioaddr, DATA_REG);		\
-			(length) = SMC_inw(ioaddr, DATA_REG);		\
+			(status) = SMC_inw(ioaddr, DATA_REG(lp));	\
+			(length) = SMC_inw(ioaddr, DATA_REG(lp));	\
 		}							\
 	} while (0)
 
-#define SMC_PUSH_DATA(p, l)						\
+#define SMC_PUSH_DATA(lp, p, l)					\
 	do {								\
-		if (SMC_CAN_USE_32BIT) {				\
+		if (SMC_32BIT(lp)) {				\
 			void *__ptr = (p);				\
 			int __len = (l);				\
 			void __iomem *__ioaddr = ioaddr;		\
 			if (__len >= 2 && (unsigned long)__ptr & 2) {	\
 				__len -= 2;				\
-				SMC_outw(*(u16 *)__ptr, ioaddr, DATA_REG); \
+				SMC_outw(*(u16 *)__ptr, ioaddr,		\
+					DATA_REG(lp));		\
 				__ptr += 2;				\
 			}						\
 			if (SMC_CAN_USE_DATACS && lp->datacs)		\
 				__ioaddr = lp->datacs;			\
-			SMC_outsl(__ioaddr, DATA_REG, __ptr, __len>>2);	\
+			SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
 			if (__len & 2) {				\
 				__ptr += (__len & ~3);			\
-				SMC_outw(*((u16 *)__ptr), ioaddr, DATA_REG); \
+				SMC_outw(*((u16 *)__ptr), ioaddr,	\
+					 DATA_REG(lp));		\
 			}						\
-		} else if (SMC_CAN_USE_16BIT)				\
-			SMC_outsw(ioaddr, DATA_REG, p, (l) >> 1);	\
-		else if (SMC_CAN_USE_8BIT)				\
-			SMC_outsb(ioaddr, DATA_REG, p, l);		\
+		} else if (SMC_16BIT(lp))				\
+			SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1);	\
+		else if (SMC_8BIT(lp))				\
+			SMC_outsb(ioaddr, DATA_REG(lp), p, l);	\
 	} while (0)
 
-#define SMC_PULL_DATA(p, l)						\
+#define SMC_PULL_DATA(lp, p, l)					\
 	do {								\
-		if (SMC_CAN_USE_32BIT) {				\
+		if (SMC_32BIT(lp)) {				\
 			void *__ptr = (p);				\
 			int __len = (l);				\
 			void __iomem *__ioaddr = ioaddr;		\
@@ -1333,16 +1321,17 @@
 				 */					\
 				__ptr -= 2;				\
 				__len += 2;				\
-				SMC_SET_PTR(2|PTR_READ|PTR_RCV|PTR_AUTOINC); \
+				SMC_SET_PTR(lp,			\
+					2|PTR_READ|PTR_RCV|PTR_AUTOINC); \
 			}						\
 			if (SMC_CAN_USE_DATACS && lp->datacs)		\
 				__ioaddr = lp->datacs;			\
 			__len += 2;					\
-			SMC_insl(__ioaddr, DATA_REG, __ptr, __len>>2);	\
-		} else if (SMC_CAN_USE_16BIT)				\
-			SMC_insw(ioaddr, DATA_REG, p, (l) >> 1);	\
-		else if (SMC_CAN_USE_8BIT)				\
-			SMC_insb(ioaddr, DATA_REG, p, l);		\
+			SMC_insl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
+		} else if (SMC_16BIT(lp))				\
+			SMC_insw(ioaddr, DATA_REG(lp), p, (l) >> 1);	\
+		else if (SMC_8BIT(lp))				\
+			SMC_insb(ioaddr, DATA_REG(lp), p, l);		\
 	} while (0)
 
 #endif  /* _SMC91X_H_ */
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 20ac150..d913405 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -141,7 +141,7 @@
 	  be called uli526x.
 	  
 config PCMCIA_XIRCOM
-	tristate "Xircom CardBus support (new driver)"
+	tristate "Xircom CardBus support"
 	depends on CARDBUS
 	---help---
 	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@@ -152,17 +152,4 @@
 	  To compile this driver as a module, choose M here. The module will
 	  be called xircom_cb.  If unsure, say N.
 
-config PCMCIA_XIRTULIP
-	tristate "Xircom Tulip-like CardBus support (old driver)"
-	depends on CARDBUS && BROKEN_ON_SMP
-	select CRC32
-	---help---
-	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
-	  It should work with most DEC 21*4*-based chips/ethercards, as well
-	  as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
-	  ASIX.
-
-	  To compile this driver as a module, choose M here. The module will
-	  be called xircom_tulip_cb.  If unsure, say N.
-
 endif # NET_TULIP
diff --git a/drivers/net/tulip/Makefile b/drivers/net/tulip/Makefile
index 451090d..200cbf7 100644
--- a/drivers/net/tulip/Makefile
+++ b/drivers/net/tulip/Makefile
@@ -2,7 +2,6 @@
 # Makefile for the Linux "Tulip" family network device drivers.
 #
 
-obj-$(CONFIG_PCMCIA_XIRTULIP)	+= xircom_tulip_cb.o
 obj-$(CONFIG_PCMCIA_XIRCOM)	+= xircom_cb.o
 obj-$(CONFIG_DM9102)		+= dmfe.o
 obj-$(CONFIG_WINBOND_840)	+= winbond-840.o
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
deleted file mode 100644
index c3f8e30..0000000
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ /dev/null
@@ -1,1726 +0,0 @@
-/* xircom_tulip_cb.c: A Xircom CBE-100 ethernet driver for Linux. */
-/*
-	Written/copyright 1994-1999 by Donald Becker.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-*/
-
-#define DRV_NAME	"xircom_tulip_cb"
-#define DRV_VERSION	"0.92"
-#define DRV_RELDATE	"June 27, 2006"
-
-/* A few user-configurable values. */
-
-#define xircom_debug debug
-#ifdef XIRCOM_DEBUG
-static int xircom_debug = XIRCOM_DEBUG;
-#else
-static int xircom_debug = 1;
-#endif
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 25;
-
-#define MAX_UNITS 4
-/* Used to pass the full-duplex flag, etc. */
-static int full_duplex[MAX_UNITS];
-static int options[MAX_UNITS];
-static int mtu[MAX_UNITS];			/* Jumbo MTU for interfaces. */
-
-/* Keep the ring sizes a power of two for efficiency.
-   Making the Tx ring too large decreases the effectiveness of channel
-   bonding and packet priority.
-   There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	32
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
-#ifdef __alpha__
-static int rx_copybreak = 1518;
-#else
-static int rx_copybreak = 100;
-#endif
-
-/*
-  Set the bus performance register.
-	Typical: Set 16 longword cache alignment, no burst limit.
-	Cache alignment bits 15:14	     Burst length 13:8
-		0000	No alignment  0x00000000 unlimited		0800 8 longwords
-		4000	8  longwords		0100 1 longword		1000 16 longwords
-		8000	16 longwords		0200 2 longwords	2000 32 longwords
-		C000	32  longwords		0400 4 longwords
-	Warning: many older 486 systems are broken and require setting 0x00A04800
-	   8 longword cache alignment, 8 longword burst.
-	ToDo: Non-Intel setting could be better.
-*/
-
-#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
-static int csr0 = 0x01A00000 | 0xE000;
-#elif defined(__powerpc__)
-static int csr0 = 0x01B00000 | 0x8000;
-#elif defined(CONFIG_SPARC)
-static int csr0 = 0x01B00080 | 0x8000;
-#elif defined(__i386__)
-static int csr0 = 0x01A00000 | 0x8000;
-#else
-#warning Processor architecture undefined!
-static int csr0 = 0x00A00000 | 0x4800;
-#endif
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT		(4 * HZ)
-#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
-#define PKT_SETUP_SZ		192			/* Size of the setup frame */
-
-/* PCI registers */
-#define PCI_POWERMGMT 	0x40
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/crc32.h>
-
-#include <asm/io.h>
-#include <asm/processor.h>	/* Processor type for cache alignment. */
-#include <asm/uaccess.h>
-
-
-/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
-KERN_INFO DRV_NAME ".c derived from tulip.c:v0.91 4/14/99 becker@scyld.com\n"
-KERN_INFO " unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "\n";
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("Xircom CBE-100 ethernet driver");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRV_VERSION);
-
-module_param(debug, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param(rx_copybreak, int, 0);
-module_param(csr0, int, 0);
-
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-
-#define RUN_AT(x) (jiffies + (x))
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver was forked from the driver for the DECchip "Tulip",
-Digital's single-chip ethernet controllers for PCI.  It supports Xircom's
-almost-Tulip-compatible CBE-100 CardBus adapters.
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS preferably should assign the
-PCI INTA signal to an otherwise unused system IRQ line.
-
-III. Driver operation
-
-IIIa. Ring buffers
-
-The Xircom can use either ring buffers or lists of Tx and Rx descriptors.
-This driver uses statically allocated rings of Rx and Tx descriptors, set at
-compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
-for the Rx ring buffers at open() time and passes the skb->data field to the
-Xircom as receive data buffers.  When an incoming frame is less than
-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
-copied to the new skbuff.  When the incoming frame is larger, the skbuff is
-passed directly up the protocol stack and replaced by a newly allocated
-skbuff.
-
-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
-using a full-sized skbuff for small frames vs. the copying costs of larger
-frames.  For small frames the copying cost is negligible (esp. considering
-that we are pre-loading the cache with immediately useful header
-information).  For large frames the copying cost is non-trivial, and the
-larger copy might flush the cache of useful data.  A subtle aspect of this
-choice is that the Xircom only receives into longword aligned buffers, thus
-the IP header at offset 14 isn't longword aligned for further processing.
-Copied frames are put into the new skbuff at an offset of "+2", thus copying
-has the beneficial effect of aligning the IP header and preloading the
-cache.
-
-IIIC. Synchronization
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'tp->tx_full' flag.
-
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
-stats.)	 After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
-tx_full and tbusy flags.
-
-IV. Notes
-
-IVb. References
-
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-http://www.digital.com  (search for current 21*4* datasheets and "21X4 SROM")
-http://www.national.com/pf/DP/DP83840A.html
-
-IVc. Errata
-
-*/
-
-/* A full-duplex map for media types. */
-enum MediaIs {
-	MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
-	MediaIs100=16};
-static const char media_cap[] =
-{0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };
-
-/* Offsets to the Command and Status Registers, "CSRs".  All accesses
-   must be longword instructions and quadword aligned. */
-enum xircom_offsets {
-	CSR0=0,    CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
-	CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
-	CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x04, };
-
-/* The bits in the CSR5 status registers, mostly interrupt sources. */
-enum status_bits {
-	LinkChange=0x08000000,
-	NormalIntr=0x10000, NormalIntrMask=0x00014045,
-	AbnormalIntr=0x8000, AbnormalIntrMask=0x0a00a5a2,
-	ReservedIntrMask=0xe0001a18,
-	EarlyRxIntr=0x4000, BusErrorIntr=0x2000,
-	EarlyTxIntr=0x400, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
-	TxFIFOUnderflow=0x20, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
-};
-
-enum csr0_control_bits {
-	EnableMWI=0x01000000, EnableMRL=0x00800000,
-	EnableMRM=0x00200000, EqualBusPrio=0x02,
-	SoftwareReset=0x01,
-};
-
-enum csr6_control_bits {
-	ReceiveAllBit=0x40000000, AllMultiBit=0x80, PromiscBit=0x40,
-	HashFilterBit=0x01, FullDuplexBit=0x0200,
-	TxThresh10=0x400000, TxStoreForw=0x200000,
-	TxThreshMask=0xc000, TxThreshShift=14,
-	EnableTx=0x2000, EnableRx=0x02,
-	ReservedZeroMask=0x8d930134, ReservedOneMask=0x320c0000,
-	EnableTxRx=(EnableTx | EnableRx),
-};
-
-
-enum tbl_flag {
-	HAS_MII=1, HAS_ACPI=2,
-};
-static struct xircom_chip_table {
-	char *chip_name;
-	int valid_intrs;			/* CSR7 interrupt enable settings */
-	int flags;
-} xircom_tbl[] = {
-  { "Xircom Cardbus Adapter",
-	LinkChange | NormalIntr | AbnormalIntr | BusErrorIntr |
-	RxDied | RxNoBuf | RxIntr | TxFIFOUnderflow | TxNoBuf | TxDied | TxIntr,
-	HAS_MII | HAS_ACPI, },
-  { NULL, },
-};
-/* This matches the table above. */
-enum chips {
-	X3201_3,
-};
-
-
-/* The Xircom Rx and Tx buffer descriptors. */
-struct xircom_rx_desc {
-	s32 status;
-	s32 length;
-	u32 buffer1, buffer2;
-};
-
-struct xircom_tx_desc {
-	s32 status;
-	s32 length;
-	u32 buffer1, buffer2;				/* We use only buffer 1.  */
-};
-
-enum tx_desc0_status_bits {
-	Tx0DescOwned=0x80000000, Tx0DescError=0x8000, Tx0NoCarrier=0x0800,
-	Tx0LateColl=0x0200, Tx0ManyColl=0x0100, Tx0Underflow=0x02,
-};
-enum tx_desc1_status_bits {
-	Tx1ComplIntr=0x80000000, Tx1LastSeg=0x40000000, Tx1FirstSeg=0x20000000,
-	Tx1SetupPkt=0x08000000, Tx1DisableCRC=0x04000000, Tx1RingWrap=0x02000000,
-	Tx1ChainDesc=0x01000000, Tx1NoPad=0x800000, Tx1HashSetup=0x400000,
-	Tx1WholePkt=(Tx1FirstSeg | Tx1LastSeg),
-};
-enum rx_desc0_status_bits {
-	Rx0DescOwned=0x80000000, Rx0DescError=0x8000, Rx0NoSpace=0x4000,
-	Rx0Runt=0x0800, Rx0McastPkt=0x0400, Rx0FirstSeg=0x0200, Rx0LastSeg=0x0100,
-	Rx0HugeFrame=0x80, Rx0CRCError=0x02,
-	Rx0WholePkt=(Rx0FirstSeg | Rx0LastSeg),
-};
-enum rx_desc1_status_bits {
-	Rx1RingWrap=0x02000000, Rx1ChainDesc=0x01000000,
-};
-
-struct xircom_private {
-	struct xircom_rx_desc rx_ring[RX_RING_SIZE];
-	struct xircom_tx_desc tx_ring[TX_RING_SIZE];
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct sk_buff* tx_skbuff[TX_RING_SIZE];
-
-	/* The X3201-3 requires 4-byte aligned tx bufs */
-	struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
-
-	/* The addresses of receive-in-place skbuffs. */
-	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	u16 setup_frame[PKT_SETUP_SZ / sizeof(u16)];	/* Pseudo-Tx frame to init address table. */
-	int chip_id;
-	struct net_device_stats stats;
-	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
-	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int speed100:1;
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int autoneg:1;
-	unsigned int default_port:4;		/* Last dev->if_port value. */
-	unsigned int open:1;
-	unsigned int csr0;					/* CSR0 setting. */
-	unsigned int csr6;					/* Current CSR6 control settings. */
-	u16 to_advertise;					/* NWay capabilities advertised.  */
-	u16 advertising[4];
-	signed char phys[4], mii_cnt;		/* MII device addresses. */
-	int saved_if_port;
-	struct pci_dev *pdev;
-	spinlock_t lock;
-};
-
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static void xircom_up(struct net_device *dev);
-static void xircom_down(struct net_device *dev);
-static int xircom_open(struct net_device *dev);
-static void xircom_tx_timeout(struct net_device *dev);
-static void xircom_init_ring(struct net_device *dev);
-static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int xircom_rx(struct net_device *dev);
-static void xircom_media_change(struct net_device *dev);
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance);
-static int xircom_close(struct net_device *dev);
-static struct net_device_stats *xircom_get_stats(struct net_device *dev);
-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void set_rx_mode(struct net_device *dev);
-static void check_duplex(struct net_device *dev);
-static const struct ethtool_ops ops;
-
-
-/* The Xircom cards are picky about when certain bits in CSR6 can be
-   manipulated.  Keith Owens <kaos@ocs.com.au>. */
-static void outl_CSR6(u32 newcsr6, long ioaddr)
-{
-	const int strict_bits =
-		TxThresh10 | TxStoreForw | TxThreshMask | EnableTxRx | FullDuplexBit;
-    int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200;
-    unsigned long flags;
-    save_flags(flags);
-    cli();
-	/* mask out the reserved bits that always read 0 on the Xircom cards */
-	newcsr6 &= ~ReservedZeroMask;
-	/* or in the reserved bits that always read 1 */
-	newcsr6 |= ReservedOneMask;
-    currcsr6 = inl(ioaddr + CSR6);
-    if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) ||
-	((currcsr6 & ~EnableTxRx) == 0)) {
-		outl(newcsr6, ioaddr + CSR6);	/* safe */
-		restore_flags(flags);
-		return;
-    }
-    /* make sure the transmitter and receiver are stopped first */
-    currcsr6 &= ~EnableTxRx;
-    while (1) {
-		csr5 = inl(ioaddr + CSR5);
-		if (csr5 == 0xffffffff)
-			break;  /* cannot read csr5, card removed? */
-		csr5_22_20 = csr5 & 0x700000;
-		csr5_19_17 = csr5 & 0x0e0000;
-		if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) &&
-			(csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000))
-			break;  /* both are stopped or suspended */
-		if (!--attempts) {
-			printk(KERN_INFO DRV_NAME ": outl_CSR6 too many attempts,"
-				   "csr5=0x%08x\n", csr5);
-			outl(newcsr6, ioaddr + CSR6);  /* unsafe but do it anyway */
-			restore_flags(flags);
-			return;
-		}
-		outl(currcsr6, ioaddr + CSR6);
-		udelay(1);
-    }
-    /* now it is safe to change csr6 */
-    outl(newcsr6, ioaddr + CSR6);
-    restore_flags(flags);
-}
-
-
-static void __devinit read_mac_address(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	int i, j;
-	unsigned char tuple, link, data_id, data_count;
-
-	/* Xircom has its address stored in the CIS;
-	 * we access it through the boot rom interface for now
-	 * this might not work, as the CIS is not parsed but I
-	 * (danilo) use the offset I found on my card's CIS !!!
-	 *
-	 * Doug Ledford: I changed this routine around so that it
-	 * walks the CIS memory space, parsing the config items, and
-	 * finds the proper lan_node_id tuple and uses the data
-	 * stored there.
-	 */
-	outl(1 << 12, ioaddr + CSR9); /* enable boot rom access */
-	for (i = 0x100; i < 0x1f7; i += link+2) {
-		outl(i, ioaddr + CSR10);
-		tuple = inl(ioaddr + CSR9) & 0xff;
-		outl(i + 1, ioaddr + CSR10);
-		link = inl(ioaddr + CSR9) & 0xff;
-		outl(i + 2, ioaddr + CSR10);
-		data_id = inl(ioaddr + CSR9) & 0xff;
-		outl(i + 3, ioaddr + CSR10);
-		data_count = inl(ioaddr + CSR9) & 0xff;
-		if ( (tuple == 0x22) &&
-			 (data_id == 0x04) && (data_count == 0x06) ) {
-			/*
-			 * This is it.  We have the data we want.
-			 */
-			for (j = 0; j < 6; j++) {
-				outl(i + j + 4, ioaddr + CSR10);
-				dev->dev_addr[j] = inl(ioaddr + CSR9) & 0xff;
-			}
-			break;
-		} else if (link == 0) {
-			break;
-		}
-	}
-}
-
-
-/*
- * locate the MII interfaces and initialize them.
- * we disable full-duplex modes here,
- * because we don't know how to handle them.
- */
-static void find_mii_transceivers(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int phy, phy_idx;
-
-	if (media_cap[tp->default_port] & MediaIsMII) {
-		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
-		tp->to_advertise = media2advert[tp->default_port - 9];
-	} else
-		tp->to_advertise =
-			/*ADVERTISE_100BASE4 | ADVERTISE_100FULL |*/ ADVERTISE_100HALF |
-			/*ADVERTISE_10FULL |*/ ADVERTISE_10HALF | ADVERTISE_CSMA;
-
-	/* Find the connected MII xcvrs.
-	   Doing this in open() would allow detecting external xcvrs later,
-	   but takes much time. */
-	for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) {
-		int mii_status = mdio_read(dev, phy, MII_BMSR);
-		if ((mii_status & (BMSR_100BASE4 | BMSR_100HALF | BMSR_10HALF)) == BMSR_100BASE4 ||
-			((mii_status & BMSR_100BASE4) == 0 &&
-			 (mii_status & (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF)) != 0)) {
-			int mii_reg0 = mdio_read(dev, phy, MII_BMCR);
-			int mii_advert = mdio_read(dev, phy, MII_ADVERTISE);
-			int reg4 = ((mii_status >> 6) & tp->to_advertise) | ADVERTISE_CSMA;
-			tp->phys[phy_idx] = phy;
-			tp->advertising[phy_idx++] = reg4;
-			printk(KERN_INFO "%s:  MII transceiver #%d "
-				   "config %4.4x status %4.4x advertising %4.4x.\n",
-				   dev->name, phy, mii_reg0, mii_status, mii_advert);
-		}
-	}
-	tp->mii_cnt = phy_idx;
-	if (phy_idx == 0) {
-		printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
-			   dev->name);
-		tp->phys[0] = 0;
-	}
-}
-
-
-/*
- * To quote Arjan van de Ven:
- *   transceiver_voodoo() enables the external UTP plug thingy.
- *   it's called voodoo as I stole this code and cannot cross-reference
- *   it with the specification.
- * Actually it seems to go like this:
- * - GPIO2 enables the MII itself so we can talk to it. The MII gets reset
- *   so any prior MII settings are lost.
- * - GPIO0 enables the TP port so the MII can talk to the network.
- * - a software reset will reset both GPIO pins.
- * I also moved the software reset here, because doing it in xircom_up()
- * required enabling the GPIO pins each time, which reset the MII each time.
- * Thus we couldn't control the MII -- which sucks because we don't know
- * how to handle full-duplex modes so we *must* disable them.
- */
-static void transceiver_voodoo(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
-	outl(SoftwareReset, ioaddr + CSR0);
-	udelay(2);
-
-	/* Deassert reset. */
-	outl(tp->csr0, ioaddr + CSR0);
-
-	/* Reset the xcvr interface and turn on heartbeat. */
-	outl(0x0008, ioaddr + CSR15);
-	udelay(5);  /* The delays are Xircom-recommended to give the
-				 * chipset time to reset the actual hardware
-				 * on the PCMCIA card
-				 */
-	outl(0xa8050000, ioaddr + CSR15);
-	udelay(5);
-	outl(0xa00f0000, ioaddr + CSR15);
-	udelay(5);
-
-	outl_CSR6(0, ioaddr);
-	//outl_CSR6(FullDuplexBit, ioaddr);
-}
-
-
-static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct net_device *dev;
-	struct xircom_private *tp;
-	static int board_idx = -1;
-	int chip_idx = id->driver_data;
-	long ioaddr;
-	int i;
-
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
-	static int printed_version;
-	if (!printed_version++)
-		printk(version);
-#endif
-
-	//printk(KERN_INFO "xircom_init_one(%s)\n", pci_name(pdev));
-
-	board_idx++;
-
-	if (pci_enable_device(pdev))
-		return -ENODEV;
-
-	pci_set_master(pdev);
-
-	ioaddr = pci_resource_start(pdev, 0);
-	dev = alloc_etherdev(sizeof(*tp));
-	if (!dev) {
-		printk (KERN_ERR DRV_NAME "%d: cannot alloc etherdev, aborting\n", board_idx);
-		return -ENOMEM;
-	}
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	dev->base_addr = ioaddr;
-	dev->irq = pdev->irq;
-
-	if (pci_request_regions(pdev, dev->name)) {
-		printk (KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", board_idx);
-		goto err_out_free_netdev;
-	}
-
-	/* Bring the chip out of sleep mode.
-	   Caution: Snooze mode does not work with some boards! */
-	if (xircom_tbl[chip_idx].flags & HAS_ACPI)
-		pci_write_config_dword(pdev, PCI_POWERMGMT, 0);
-
-	/* Stop the chip's Tx and Rx processes. */
-	outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
-	/* Clear the missed-packet counter. */
-	(volatile int)inl(ioaddr + CSR8);
-
-	tp = netdev_priv(dev);
-
-	spin_lock_init(&tp->lock);
-	tp->pdev = pdev;
-	tp->chip_id = chip_idx;
-	/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */
-	/* XXX: is this necessary for Xircom? */
-	tp->csr0 = csr0 & ~EnableMWI;
-
-	pci_set_drvdata(pdev, dev);
-
-	/* The lower four bits are the media type. */
-	if (board_idx >= 0 && board_idx < MAX_UNITS) {
-		tp->default_port = options[board_idx] & 15;
-		if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
-			tp->full_duplex = 1;
-		if (mtu[board_idx] > 0)
-			dev->mtu = mtu[board_idx];
-	}
-	if (dev->mem_start)
-		tp->default_port = dev->mem_start;
-	if (tp->default_port) {
-		if (media_cap[tp->default_port] & MediaAlwaysFD)
-			tp->full_duplex = 1;
-	}
-	if (tp->full_duplex)
-		tp->autoneg = 0;
-	else
-		tp->autoneg = 1;
-	tp->speed100 = 1;
-
-	/* The Xircom-specific entries in the device structure. */
-	dev->open = &xircom_open;
-	dev->hard_start_xmit = &xircom_start_xmit;
-	dev->stop = &xircom_close;
-	dev->get_stats = &xircom_get_stats;
-	dev->do_ioctl = &xircom_ioctl;
-#ifdef HAVE_MULTICAST
-	dev->set_multicast_list = &set_rx_mode;
-#endif
-	dev->tx_timeout = xircom_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &ops);
-
-	transceiver_voodoo(dev);
-
-	read_mac_address(dev);
-
-	if (register_netdev(dev))
-		goto err_out_cleardev;
-
-	printk(KERN_INFO "%s: %s rev %d at %#3lx,",
-	       dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr);
-	for (i = 0; i < 6; i++)
-		printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
-	printk(", IRQ %d.\n", dev->irq);
-
-	if (xircom_tbl[chip_idx].flags & HAS_MII) {
-		find_mii_transceivers(dev);
-		check_duplex(dev);
-	}
-
-	return 0;
-
-err_out_cleardev:
-	pci_set_drvdata(pdev, NULL);
-	pci_release_regions(pdev);
-err_out_free_netdev:
-	free_netdev(dev);
-	return -ENODEV;
-}
-
-
-/* MII transceiver control section.
-   Read and write the MII registers using software-generated serial
-   MDIO protocol.  See the MII specifications or DP83840A data sheet
-   for details. */
-
-/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
-   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
-   "overclocking" issues or future 66Mhz PCI. */
-#define mdio_delay() inl(mdio_addr)
-
-/* Read and write the MII registers using software-generated serial
-   MDIO protocol.  It is just different enough from the EEPROM protocol
-   to not share code.  The maxium data clock rate is 2.5 Mhz. */
-#define MDIO_SHIFT_CLK	0x10000
-#define MDIO_DATA_WRITE0 0x00000
-#define MDIO_DATA_WRITE1 0x20000
-#define MDIO_ENB		0x00000		/* Ignore the 0x02000 databook setting. */
-#define MDIO_ENB_IN		0x40000
-#define MDIO_DATA_READ	0x80000
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	int i;
-	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-	int retval = 0;
-	long ioaddr = dev->base_addr;
-	long mdio_addr = ioaddr + CSR9;
-
-	/* Establish sync by sending at least 32 logic ones. */
-	for (i = 32; i >= 0; i--) {
-		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Shift the read command bits out. */
-	for (i = 15; i >= 0; i--) {
-		int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
-
-		outl(MDIO_ENB | dataval, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Read the two transition, 16 data, and wire-idle bits. */
-	for (i = 19; i > 0; i--) {
-		outl(MDIO_ENB_IN, mdio_addr);
-		mdio_delay();
-		retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
-		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	return (retval>>1) & 0xffff;
-}
-
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	int i;
-	int cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
-	long ioaddr = dev->base_addr;
-	long mdio_addr = ioaddr + CSR9;
-
-	/* Establish sync by sending 32 logic ones. */
-	for (i = 32; i >= 0; i--) {
-		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Shift the command bits out. */
-	for (i = 31; i >= 0; i--) {
-		int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
-		outl(MDIO_ENB | dataval, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Clear out extra bits. */
-	for (i = 2; i > 0; i--) {
-		outl(MDIO_ENB_IN, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	return;
-}
-
-
-static void
-xircom_up(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int i;
-
-	xircom_init_ring(dev);
-	/* Clear the tx ring */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		tp->tx_skbuff[i] = NULL;
-		tp->tx_ring[i].status = 0;
-	}
-
-	if (xircom_debug > 1)
-		printk(KERN_DEBUG "%s: xircom_up() irq %d.\n", dev->name, dev->irq);
-
-	outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);
-	outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);
-
-	tp->saved_if_port = dev->if_port;
-	if (dev->if_port == 0)
-		dev->if_port = tp->default_port;
-
-	tp->csr6 = TxThresh10 /*| FullDuplexBit*/;						/* XXX: why 10 and not 100? */
-
-	set_rx_mode(dev);
-
-	/* Start the chip's Tx to process setup frame. */
-	outl_CSR6(tp->csr6, ioaddr);
-	outl_CSR6(tp->csr6 | EnableTx, ioaddr);
-
-	/* Acknowledge all outstanding interrupts sources */
-	outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
-	/* Enable interrupts by setting the interrupt mask. */
-	outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
-	/* Enable Rx */
-	outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-	/* Rx poll demand */
-	outl(0, ioaddr + CSR2);
-
-	/* Tell the net layer we're ready */
-	netif_start_queue (dev);
-
-	/* Check current media state */
-	xircom_media_change(dev);
-
-	if (xircom_debug > 2) {
-		printk(KERN_DEBUG "%s: Done xircom_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
-			   dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),
-			   inl(ioaddr + CSR6));
-	}
-}
-
-
-static int
-xircom_open(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-
-	if (request_irq(dev->irq, &xircom_interrupt, IRQF_SHARED, dev->name, dev))
-		return -EAGAIN;
-
-	xircom_up(dev);
-	tp->open = 1;
-
-	return 0;
-}
-
-
-static void xircom_tx_timeout(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	if (media_cap[dev->if_port] & MediaIsMII) {
-		/* Do nothing -- the media monitor should handle this. */
-		if (xircom_debug > 1)
-			printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
-				   dev->name);
-	}
-
-#if defined(way_too_many_messages)
-	if (xircom_debug > 3) {
-		int i;
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			u8 *buf = (u8 *)(tp->rx_ring[i].buffer1);
-			int j;
-			printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x  "
-				   "%2.2x %2.2x %2.2x.\n",
-				   i, (unsigned int)tp->rx_ring[i].status,
-				   (unsigned int)tp->rx_ring[i].length,
-				   (unsigned int)tp->rx_ring[i].buffer1,
-				   (unsigned int)tp->rx_ring[i].buffer2,
-				   buf[0], buf[1], buf[2]);
-			for (j = 0; buf[j] != 0xee && j < 1600; j++)
-				if (j < 100) printk(" %2.2x", buf[j]);
-			printk(" j=%d.\n", j);
-		}
-		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)tp->rx_ring);
-		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
-		printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
-		printk("\n");
-	}
-#endif
-
-	/* Stop and restart the chip's Tx/Rx processes . */
-	outl_CSR6(tp->csr6 | EnableRx, ioaddr);
-	outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-	/* Trigger an immediate transmit demand. */
-	outl(0, ioaddr + CSR1);
-
-	dev->trans_start = jiffies;
-	netif_wake_queue (dev);
-	tp->stats.tx_errors++;
-}
-
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void xircom_init_ring(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int i;
-
-	tp->tx_full = 0;
-	tp->cur_rx = tp->cur_tx = 0;
-	tp->dirty_rx = tp->dirty_tx = 0;
-
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		tp->rx_ring[i].status = 0;
-		tp->rx_ring[i].length = PKT_BUF_SZ;
-		tp->rx_ring[i].buffer2 = virt_to_bus(&tp->rx_ring[i+1]);
-		tp->rx_skbuff[i] = NULL;
-	}
-	/* Mark the last entry as wrapping the ring. */
-	tp->rx_ring[i-1].length = PKT_BUF_SZ | Rx1RingWrap;
-	tp->rx_ring[i-1].buffer2 = virt_to_bus(&tp->rx_ring[0]);
-
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		/* Note the receive buffer must be longword aligned.
-		   dev_alloc_skb() provides 16 byte alignment.  But do *not*
-		   use skb_reserve() to align the IP header! */
-		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
-		tp->rx_skbuff[i] = skb;
-		if (skb == NULL)
-			break;
-		skb->dev = dev;			/* Mark as being used by this device. */
-		tp->rx_ring[i].status = Rx0DescOwned;	/* Owned by Xircom chip */
-		tp->rx_ring[i].buffer1 = virt_to_bus(skb->data);
-	}
-	tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-
-	/* The Tx buffer descriptor is filled in as needed, but we
-	   do need to clear the ownership bit. */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		tp->tx_skbuff[i] = NULL;
-		tp->tx_ring[i].status = 0;
-		tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
-		if (tp->chip_id == X3201_3)
-			tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ);
-	}
-	tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
-}
-
-
-static int
-xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int entry;
-	u32 flag;
-
-	/* Caution: the write order is important here, set the base address
-	   with the "ownership" bits last. */
-
-	/* Calculate the next Tx descriptor entry. */
-	entry = tp->cur_tx % TX_RING_SIZE;
-
-	tp->tx_skbuff[entry] = skb;
-	if (tp->chip_id == X3201_3) {
-		skb_copy_from_linear_data(skb,
-					  tp->tx_aligned_skbuff[entry]->data,
-					  skb->len);
-		tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
-	} else
-		tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
-
-	if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
-		flag = Tx1WholePkt; /* No interrupt */
-	} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
-		flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
-	} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
-		flag = Tx1WholePkt; /* No Tx-done intr. */
-	} else {
-		/* Leave room for set_rx_mode() to fill entries. */
-		flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
-		tp->tx_full = 1;
-	}
-	if (entry == TX_RING_SIZE - 1)
-		flag |= Tx1WholePkt | Tx1ComplIntr | Tx1RingWrap;
-
-	tp->tx_ring[entry].length = skb->len | flag;
-	tp->tx_ring[entry].status = Tx0DescOwned;	/* Pass ownership to the chip. */
-	tp->cur_tx++;
-	if (tp->tx_full)
-		netif_stop_queue (dev);
-	else
-		netif_wake_queue (dev);
-
-	/* Trigger an immediate transmit demand. */
-	outl(0, dev->base_addr + CSR1);
-
-	dev->trans_start = jiffies;
-
-	return 0;
-}
-
-
-static void xircom_media_change(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	u16 reg0, reg1, reg4, reg5;
-	u32 csr6 = inl(ioaddr + CSR6), newcsr6;
-
-	/* reset status first */
-	mdio_read(dev, tp->phys[0], MII_BMCR);
-	mdio_read(dev, tp->phys[0], MII_BMSR);
-
-	reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
-	reg1 = mdio_read(dev, tp->phys[0], MII_BMSR);
-
-	if (reg1 & BMSR_LSTATUS) {
-		/* link is up */
-		if (reg0 & BMCR_ANENABLE) {
-			/* autonegotiation is enabled */
-			reg4 = mdio_read(dev, tp->phys[0], MII_ADVERTISE);
-			reg5 = mdio_read(dev, tp->phys[0], MII_LPA);
-			if (reg4 & ADVERTISE_100FULL && reg5 & LPA_100FULL) {
-				tp->speed100 = 1;
-				tp->full_duplex = 1;
-			} else if (reg4 & ADVERTISE_100HALF && reg5 & LPA_100HALF) {
-				tp->speed100 = 1;
-				tp->full_duplex = 0;
-			} else if (reg4 & ADVERTISE_10FULL && reg5 & LPA_10FULL) {
-				tp->speed100 = 0;
-				tp->full_duplex = 1;
-			} else {
-				tp->speed100 = 0;
-				tp->full_duplex = 0;
-			}
-		} else {
-			/* autonegotiation is disabled */
-			if (reg0 & BMCR_SPEED100)
-				tp->speed100 = 1;
-			else
-				tp->speed100 = 0;
-			if (reg0 & BMCR_FULLDPLX)
-				tp->full_duplex = 1;
-			else
-				tp->full_duplex = 0;
-		}
-		printk(KERN_DEBUG "%s: Link is up, running at %sMbit %s-duplex\n",
-		       dev->name,
-		       tp->speed100 ? "100" : "10",
-		       tp->full_duplex ? "full" : "half");
-		netif_carrier_on(dev);
-		newcsr6 = csr6 & ~FullDuplexBit;
-		if (tp->full_duplex)
-			newcsr6 |= FullDuplexBit;
-		if (newcsr6 != csr6)
-			outl_CSR6(newcsr6, ioaddr + CSR6);
-	} else {
-		printk(KERN_DEBUG "%s: Link is down\n", dev->name);
-		netif_carrier_off(dev);
-	}
-}
-
-
-static void check_duplex(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	u16 reg0;
-
-	mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET);
-	udelay(500);
-	while (mdio_read(dev, tp->phys[0], MII_BMCR) & BMCR_RESET);
-
-	reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
-	mdio_write(dev, tp->phys[0], MII_ADVERTISE, tp->advertising[0]);
-
-	if (tp->autoneg) {
-		reg0 &= ~(BMCR_SPEED100 | BMCR_FULLDPLX);
-		reg0 |= BMCR_ANENABLE | BMCR_ANRESTART;
-	} else {
-		reg0 &= ~(BMCR_ANENABLE | BMCR_ANRESTART);
-		if (tp->speed100)
-			reg0 |= BMCR_SPEED100;
-		if (tp->full_duplex)
-			reg0 |= BMCR_FULLDPLX;
-		printk(KERN_DEBUG "%s: Link forced to %sMbit %s-duplex\n",
-		       dev->name,
-		       tp->speed100 ? "100" : "10",
-		       tp->full_duplex ? "full" : "half");
-	}
-	mdio_write(dev, tp->phys[0], MII_BMCR, reg0);
-}
-
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance)
-{
-	struct net_device *dev = dev_instance;
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int csr5, work_budget = max_interrupt_work;
-	int handled = 0;
-
-	spin_lock (&tp->lock);
-
-	do {
-		csr5 = inl(ioaddr + CSR5);
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		outl(csr5 & 0x0001ffff, ioaddr + CSR5);
-
-		if (xircom_debug > 4)
-			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
-				   dev->name, csr5, inl(dev->base_addr + CSR5));
-
-		if (csr5 == 0xffffffff)
-			break;	/* all bits set, assume PCMCIA card removed */
-
-		if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
-			break;
-
-		handled = 1;
-
-		if (csr5 & (RxIntr | RxNoBuf))
-			work_budget -= xircom_rx(dev);
-
-		if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
-			unsigned int dirty_tx;
-
-			for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
-				 dirty_tx++) {
-				int entry = dirty_tx % TX_RING_SIZE;
-				int status = tp->tx_ring[entry].status;
-
-				if (status < 0)
-					break;			/* It still hasn't been Txed */
-				/* Check for Rx filter setup frames. */
-				if (tp->tx_skbuff[entry] == NULL)
-				  continue;
-
-				if (status & Tx0DescError) {
-					/* There was an major error, log it. */
-#ifndef final_version
-					if (xircom_debug > 1)
-						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
-							   dev->name, status);
-#endif
-					tp->stats.tx_errors++;
-					if (status & Tx0ManyColl) {
-						tp->stats.tx_aborted_errors++;
-					}
-					if (status & Tx0NoCarrier) tp->stats.tx_carrier_errors++;
-					if (status & Tx0LateColl) tp->stats.tx_window_errors++;
-					if (status & Tx0Underflow) tp->stats.tx_fifo_errors++;
-				} else {
-					tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
-					tp->stats.collisions += (status >> 3) & 15;
-					tp->stats.tx_packets++;
-				}
-
-				/* Free the original skb. */
-				dev_kfree_skb_irq(tp->tx_skbuff[entry]);
-				tp->tx_skbuff[entry] = NULL;
-			}
-
-#ifndef final_version
-			if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
-				printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-
-			if (tp->tx_full &&
-			    tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2)
-				/* The ring is no longer full */
-				tp->tx_full = 0;
-
-			if (tp->tx_full)
-				netif_stop_queue (dev);
-			else
-				netif_wake_queue (dev);
-
-			tp->dirty_tx = dirty_tx;
-			if (csr5 & TxDied) {
-				if (xircom_debug > 2)
-					printk(KERN_WARNING "%s: The transmitter stopped."
-						   "  CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
-						   dev->name, csr5, inl(ioaddr + CSR6), tp->csr6);
-				outl_CSR6(tp->csr6 | EnableRx, ioaddr);
-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-			}
-		}
-
-		/* Log errors. */
-		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
-			if (csr5 & LinkChange)
-				xircom_media_change(dev);
-			if (csr5 & TxFIFOUnderflow) {
-				if ((tp->csr6 & TxThreshMask) != TxThreshMask)
-					tp->csr6 += (1 << TxThreshShift);	/* Bump up the Tx threshold */
-				else
-					tp->csr6 |= TxStoreForw;  /* Store-n-forward. */
-				/* Restart the transmit process. */
-				outl_CSR6(tp->csr6 | EnableRx, ioaddr);
-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-			}
-			if (csr5 & RxDied) {		/* Missed a Rx frame. */
-				tp->stats.rx_errors++;
-				tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-			}
-			/* Clear all error sources, included undocumented ones! */
-			outl(0x0800f7ba, ioaddr + CSR5);
-		}
-		if (--work_budget < 0) {
-			if (xircom_debug > 1)
-				printk(KERN_WARNING "%s: Too much work during an interrupt, "
-					   "csr5=0x%8.8x.\n", dev->name, csr5);
-			/* Acknowledge all interrupt sources. */
-			outl(0x8001ffff, ioaddr + CSR5);
-			break;
-		}
-	} while (1);
-
-	if (xircom_debug > 3)
-		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
-			   dev->name, inl(ioaddr + CSR5));
-
-	spin_unlock (&tp->lock);
-	return IRQ_RETVAL(handled);
-}
-
-
-static int
-xircom_rx(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int entry = tp->cur_rx % RX_RING_SIZE;
-	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
-	int work_done = 0;
-
-	if (xircom_debug > 4)
-		printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
-			   tp->rx_ring[entry].status);
-	/* If we own the next entry, it's a new packet. Send it up. */
-	while (tp->rx_ring[entry].status >= 0) {
-		s32 status = tp->rx_ring[entry].status;
-
-		if (xircom_debug > 5)
-			printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
-				   tp->rx_ring[entry].status);
-		if (--rx_work_limit < 0)
-			break;
-		if ((status & 0x38008300) != 0x0300) {
-			if ((status & 0x38000300) != 0x0300) {
-				/* Ignore earlier buffers. */
-				if ((status & 0xffff) != 0x7fff) {
-					if (xircom_debug > 1)
-						printk(KERN_WARNING "%s: Oversized Ethernet frame "
-							   "spanned multiple buffers, status %8.8x!\n",
-							   dev->name, status);
-					tp->stats.rx_length_errors++;
-				}
-			} else if (status & Rx0DescError) {
-				/* There was a fatal error. */
-				if (xircom_debug > 2)
-					printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
-						   dev->name, status);
-				tp->stats.rx_errors++; /* end of a packet.*/
-				if (status & (Rx0Runt | Rx0HugeFrame)) tp->stats.rx_length_errors++;
-				if (status & Rx0CRCError) tp->stats.rx_crc_errors++;
-			}
-		} else {
-			/* Omit the four octet CRC from the length. */
-			short pkt_len = ((status >> 16) & 0x7ff) - 4;
-			struct sk_buff *skb;
-
-#ifndef final_version
-			if (pkt_len > 1518) {
-				printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
-					   dev->name, pkt_len, pkt_len);
-				pkt_len = 1518;
-				tp->stats.rx_length_errors++;
-			}
-#endif
-			/* Check if the packet is long enough to accept without copying
-			   to a minimally-sized skbuff. */
-			if (pkt_len < rx_copybreak
-				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-#if ! defined(__alpha__)
-				skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
-								 pkt_len);
-				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len),
-					   bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
-#endif
-				work_done++;
-			} else { 	/* Pass up the skb already on the Rx ring. */
-				skb_put(skb = tp->rx_skbuff[entry], pkt_len);
-				tp->rx_skbuff[entry] = NULL;
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			tp->stats.rx_packets++;
-			tp->stats.rx_bytes += pkt_len;
-		}
-		entry = (++tp->cur_rx) % RX_RING_SIZE;
-	}
-
-	/* Refill the Rx ring buffers. */
-	for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
-		entry = tp->dirty_rx % RX_RING_SIZE;
-		if (tp->rx_skbuff[entry] == NULL) {
-			struct sk_buff *skb;
-			skb = tp->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
-			if (skb == NULL)
-				break;
-			skb->dev = dev;			/* Mark as being used by this device. */
-			tp->rx_ring[entry].buffer1 = virt_to_bus(skb->data);
-			work_done++;
-		}
-		tp->rx_ring[entry].status = Rx0DescOwned;
-	}
-
-	return work_done;
-}
-
-
-static void
-xircom_down(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct xircom_private *tp = netdev_priv(dev);
-
-	/* Disable interrupts by clearing the interrupt mask. */
-	outl(0, ioaddr + CSR7);
-	/* Stop the chip's Tx and Rx processes. */
-	outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
-
-	if (inl(ioaddr + CSR6) != 0xffffffff)
-		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-
-	dev->if_port = tp->saved_if_port;
-}
-
-
-static int
-xircom_close(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct xircom_private *tp = netdev_priv(dev);
-	int i;
-
-	if (xircom_debug > 1)
-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
-			   dev->name, inl(ioaddr + CSR5));
-
-	netif_stop_queue(dev);
-
-	if (netif_device_present(dev))
-		xircom_down(dev);
-
-	free_irq(dev->irq, dev);
-
-	/* Free all the skbuffs in the Rx queue. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = tp->rx_skbuff[i];
-		tp->rx_skbuff[i] = NULL;
-		tp->rx_ring[i].status = 0;		/* Not owned by Xircom chip. */
-		tp->rx_ring[i].length = 0;
-		tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
-		if (skb) {
-			dev_kfree_skb(skb);
-		}
-	}
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (tp->tx_skbuff[i])
-			dev_kfree_skb(tp->tx_skbuff[i]);
-		tp->tx_skbuff[i] = NULL;
-	}
-
-	tp->open = 0;
-	return 0;
-}
-
-
-static struct net_device_stats *xircom_get_stats(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	if (netif_device_present(dev))
-		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-
-	return &tp->stats;
-}
-
-static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	ecmd->supported =
-			SUPPORTED_10baseT_Half |
-			SUPPORTED_10baseT_Full |
-			SUPPORTED_100baseT_Half |
-			SUPPORTED_100baseT_Full |
-			SUPPORTED_Autoneg |
-			SUPPORTED_MII;
-
-	ecmd->advertising = ADVERTISED_MII;
-	if (tp->advertising[0] & ADVERTISE_10HALF)
-		ecmd->advertising |= ADVERTISED_10baseT_Half;
-	if (tp->advertising[0] & ADVERTISE_10FULL)
-		ecmd->advertising |= ADVERTISED_10baseT_Full;
-	if (tp->advertising[0] & ADVERTISE_100HALF)
-		ecmd->advertising |= ADVERTISED_100baseT_Half;
-	if (tp->advertising[0] & ADVERTISE_100FULL)
-		ecmd->advertising |= ADVERTISED_100baseT_Full;
-	if (tp->autoneg) {
-		ecmd->advertising |= ADVERTISED_Autoneg;
-		ecmd->autoneg = AUTONEG_ENABLE;
-	} else
-		ecmd->autoneg = AUTONEG_DISABLE;
-
-	ecmd->port = PORT_MII;
-	ecmd->transceiver = XCVR_INTERNAL;
-	ecmd->phy_address = tp->phys[0];
-	ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10;
-	ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	ecmd->maxtxpkt = TX_RING_SIZE / 2;
-	ecmd->maxrxpkt = 0;
-	return 0;
-}
-
-static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	u16 autoneg, speed100, full_duplex;
-
-	autoneg = (ecmd->autoneg == AUTONEG_ENABLE);
-	speed100 = (ecmd->speed == SPEED_100);
-	full_duplex = (ecmd->duplex == DUPLEX_FULL);
-
-	tp->autoneg = autoneg;
-	if (speed100 != tp->speed100 ||
-	    full_duplex != tp->full_duplex) {
-		tp->speed100 = speed100;
-		tp->full_duplex = full_duplex;
-		/* change advertising bits */
-		tp->advertising[0] &= ~(ADVERTISE_10HALF |
-				     ADVERTISE_10FULL |
-				     ADVERTISE_100HALF |
-				     ADVERTISE_100FULL |
-				     ADVERTISE_100BASE4);
-		if (speed100) {
-			if (full_duplex)
-				tp->advertising[0] |= ADVERTISE_100FULL;
-			else
-				tp->advertising[0] |= ADVERTISE_100HALF;
-		} else {
-			if (full_duplex)
-				tp->advertising[0] |= ADVERTISE_10FULL;
-			else
-				tp->advertising[0] |= ADVERTISE_10HALF;
-		}
-	}
-	check_duplex(dev);
-	return 0;
-}
-
-static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, pci_name(tp->pdev));
-}
-
-static const struct ethtool_ops ops = {
-	.get_settings = xircom_get_settings,
-	.set_settings = xircom_set_settings,
-	.get_drvinfo = xircom_get_drvinfo,
-};
-
-/* Provide ioctl() calls to examine the MII xcvr state. */
-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	u16 *data = (u16 *)&rq->ifr_ifru;
-	int phy = tp->phys[0] & 0x1f;
-	unsigned long flags;
-
-	switch(cmd) {
-	/* Legacy mii-diag interface */
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-		if (tp->mii_cnt)
-			data[0] = phy;
-		else
-			return -ENODEV;
-		return 0;
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-		save_flags(flags);
-		cli();
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
-		restore_flags(flags);
-		return 0;
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		save_flags(flags);
-		cli();
-		if (data[0] == tp->phys[0]) {
-			u16 value = data[2];
-			switch (data[1]) {
-			case 0:
-				if (value & (BMCR_RESET | BMCR_ANENABLE))
-					/* Autonegotiation. */
-					tp->autoneg = 1;
-				else {
-					tp->full_duplex = (value & BMCR_FULLDPLX) ? 1 : 0;
-					tp->autoneg = 0;
-				}
-				break;
-			case 4:
-				tp->advertising[0] = value;
-				break;
-			}
-			check_duplex(dev);
-		}
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
-		restore_flags(flags);
-		return 0;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return -EOPNOTSUPP;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   Note that we only use exclusion around actually queueing the
-   new frame, not around filling tp->setup_frame.  This is non-deterministic
-   when re-entered but still correct. */
-static void set_rx_mode(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	struct dev_mc_list *mclist;
-	long ioaddr = dev->base_addr;
-	int csr6 = inl(ioaddr + CSR6);
-	u16 *eaddrs, *setup_frm;
-	u32 tx_flags;
-	int i;
-
-	tp->csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
-	csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		tp->csr6 |= PromiscBit;
-		csr6 |= PromiscBit;
-		goto out;
-	}
-
-	if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
-		/* Too many to filter well -- accept all multicasts. */
-		tp->csr6 |= AllMultiBit;
-		csr6 |= AllMultiBit;
-		goto out;
-	}
-
-	tx_flags = Tx1WholePkt | Tx1SetupPkt | PKT_SETUP_SZ;
-
-	/* Note that only the low-address shortword of setup_frame is valid! */
-	setup_frm = tp->setup_frame;
-	mclist = dev->mc_list;
-
-	/* Fill the first entry with our physical address. */
-	eaddrs = (u16 *)dev->dev_addr;
-	*setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
-	*setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
-	*setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
-
-	if (dev->mc_count > 14) { /* Must use a multicast hash table. */
-		u32 *hash_table = (u32 *)(tp->setup_frame + 4 * 12);
-		u32 hash, hash2;
-
-		tx_flags |= Tx1HashSetup;
-		tp->csr6 |= HashFilterBit;
-		csr6 |= HashFilterBit;
-
-		/* Fill the unused 3 entries with the broadcast address.
-		   At least one entry *must* contain the broadcast address!!!*/
-		for (i = 0; i < 3; i++) {
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-		}
-
-		/* Truly brain-damaged hash filter layout */
-		/* XXX: not sure if I should take the last or the first 9 bits */
-		for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
-			u32 *hptr;
-			hash = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x1ff;
-			if (hash < 384) {
-				hash2 = hash + ((hash >> 4) << 4) +
-					((hash >> 5) << 5);
-			} else {
-				hash -= 384;
-				hash2 = 64 + hash + (hash >> 4) * 80;
-			}
-			hptr = &hash_table[hash2 & ~0x1f];
-			*hptr |= cpu_to_le32(1 << (hash2 & 0x1f));
-		}
-	} else {
-		/* We have <= 14 mcast addresses so we can use Xircom's
-		   wonderful 16-address perfect filter. */
-		for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
-			eaddrs = (u16 *)mclist->dmi_addr;
-			*setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
-			*setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
-			*setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
-		}
-		/* Fill the unused entries with the broadcast address.
-		   At least one entry *must* contain the broadcast address!!!*/
-		for (; i < 15; i++) {
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-		}
-	}
-
-	/* Now add this frame to the Tx list. */
-	if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
-		/* Same setup recently queued, we need not add it. */
-		/* XXX: Huh? All it means is that the Tx list is full...*/
-	} else {
-		unsigned long flags;
-		unsigned int entry;
-		int dummy = -1;
-
-		save_flags(flags); cli();
-		entry = tp->cur_tx++ % TX_RING_SIZE;
-
-		if (entry != 0) {
-			/* Avoid a chip errata by prefixing a dummy entry. */
-			tp->tx_skbuff[entry] = NULL;
-			tp->tx_ring[entry].length =
-				(entry == TX_RING_SIZE - 1) ? Tx1RingWrap : 0;
-			tp->tx_ring[entry].buffer1 = 0;
-			/* race with chip, set Tx0DescOwned later */
-			dummy = entry;
-			entry = tp->cur_tx++ % TX_RING_SIZE;
-		}
-
-		tp->tx_skbuff[entry] = NULL;
-		/* Put the setup frame on the Tx list. */
-		if (entry == TX_RING_SIZE - 1)
-			tx_flags |= Tx1RingWrap;		/* Wrap ring. */
-		tp->tx_ring[entry].length = tx_flags;
-		tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
-		tp->tx_ring[entry].status = Tx0DescOwned;
-		if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
-			tp->tx_full = 1;
-			netif_stop_queue (dev);
-		}
-		if (dummy >= 0)
-			tp->tx_ring[dummy].status = Tx0DescOwned;
-		restore_flags(flags);
-		/* Trigger an immediate transmit demand. */
-		outl(0, ioaddr + CSR1);
-	}
-
-out:
-	outl_CSR6(csr6, ioaddr);
-}
-
-
-static struct pci_device_id xircom_pci_table[] = {
-  { 0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 },
-  {0},
-};
-MODULE_DEVICE_TABLE(pci, xircom_pci_table);
-
-
-#ifdef CONFIG_PM
-static int xircom_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct xircom_private *tp = netdev_priv(dev);
-	printk(KERN_INFO "xircom_suspend(%s)\n", dev->name);
-	if (tp->open)
-		xircom_down(dev);
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, 3);
-
-	return 0;
-}
-
-
-static int xircom_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct xircom_private *tp = netdev_priv(dev);
-	printk(KERN_INFO "xircom_resume(%s)\n", dev->name);
-
-	pci_set_power_state(pdev,0);
-	pci_enable_device(pdev);
-	pci_restore_state(pdev);
-
-	/* Bring the chip out of sleep mode.
-	   Caution: Snooze mode does not work with some boards! */
-	if (xircom_tbl[tp->chip_id].flags & HAS_ACPI)
-		pci_write_config_dword(tp->pdev, PCI_POWERMGMT, 0);
-
-	transceiver_voodoo(dev);
-	if (xircom_tbl[tp->chip_id].flags & HAS_MII)
-		check_duplex(dev);
-
-	if (tp->open)
-		xircom_up(dev);
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-
-static void __devexit xircom_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-
-	printk(KERN_INFO "xircom_remove_one(%s)\n", dev->name);
-	unregister_netdev(dev);
-	pci_release_regions(pdev);
-	free_netdev(dev);
-	pci_set_drvdata(pdev, NULL);
-}
-
-
-static struct pci_driver xircom_driver = {
-	.name		= DRV_NAME,
-	.id_table	= xircom_pci_table,
-	.probe		= xircom_init_one,
-	.remove		= __devexit_p(xircom_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= xircom_suspend,
-	.resume		= xircom_resume
-#endif /* CONFIG_PM */
-};
-
-
-static int __init xircom_init(void)
-{
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-	printk(version);
-#endif
-	return pci_register_driver(&xircom_driver);
-}
-
-
-static void __exit xircom_exit(void)
-{
-	pci_unregister_driver(&xircom_driver);
-}
-
-module_init(xircom_init)
-module_exit(xircom_exit)
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index eada69d..a7745c8 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -5,22 +5,25 @@
 	tristate "Lan Channel Station Interface"
 	depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
 	help
-	   Select this option if you want to use LCS networking  on IBM S/390
-  	   or zSeries. This device driver supports Token Ring (IEEE 802.5),
-  	   FDDI (IEEE 802.7) and Ethernet. 
-	   This option is also available as a module which will be
-	   called lcs.ko. If you do not know what it is, it's safe to say "Y".
+	   Select this option if you want to use LCS networking on IBM System z.
+	   This device driver supports Token Ring (IEEE 802.5),
+	   FDDI (IEEE 802.7) and Ethernet.
+	   To compile as a module, choose M. The module name is lcs.ko.
+	   If you do not know what it is, it's safe to choose Y.
 
-config CTC
-	tristate "CTC device support"
+config CTCM
+	tristate "CTC and MPC SNA device support"
 	depends on CCW && NETDEVICES
 	help
-	  Select this option if you want to use channel-to-channel networking
-	  on IBM S/390 or zSeries. This device driver supports real CTC
-	  coupling using ESCON. It also supports virtual CTCs when running
-	  under VM. It will use the channel device configuration if this is
-	  available.  This option is also available as a module which will be
-	  called ctc.ko.  If you do not know what it is, it's safe to say "Y".
+	  Select this option if you want to use channel-to-channel
+	  point-to-point networking on IBM System z.
+	  This device driver supports real CTC coupling using ESCON.
+	  It also supports virtual CTCs when running under VM.
+	  This driver also supports channel-to-channel MPC SNA devices.
+	  MPC is an SNA protocol device used by Communication Server for Linux.
+	  To compile as a module, choose M. The module name is ctcm.ko.
+	  To compile into the kernel, choose Y.
+	  If you do not need any channel-to-channel connection, choose N.
 
 config NETIUCV
 	tristate "IUCV network device support (VM only)"
@@ -29,9 +32,9 @@
 	  Select this option if you want to use inter-user communication
 	  vehicle networking under VM or VIF. It enables a fast communication
 	  link between VM guests. Using ifconfig a point-to-point connection
-	  can be established to the Linux for zSeries and S7390 system
-	  running on the other VM guest. This option is also available
-	  as a module which will be called netiucv.ko. If unsure, say "Y".
+	  can be established to the Linux on IBM System z
+	  running on the other VM guest. To compile as a module, choose M.
+	  The module name is netiucv.ko. If unsure, choose Y.
 
 config SMSGIUCV
 	tristate "IUCV special message support (VM only)"
@@ -47,43 +50,46 @@
 	  This driver supports channel attached CLAW devices.
 	  CLAW is Common Link Access for Workstation.  Common devices
           that use CLAW are RS/6000s, Cisco Routers (CIP) and 3172 devices.
-	  To compile as a module choose M here:  The module will be called
-	  claw.ko to compile into the kernel choose Y
+	  To compile as a module, choose M. The module name is claw.ko.
+	  To compile into the kernel, choose Y.
 
 config QETH
 	tristate "Gigabit Ethernet device support"
 	depends on CCW && NETDEVICES && IP_MULTICAST && QDIO
 	help
-	  This driver supports the IBM S/390 and zSeries OSA Express adapters
+	  This driver supports the IBM System z OSA Express adapters
 	  in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN
 	  interfaces in QDIO and HIPER mode.
 	
-	  For details please refer to the documentation provided by IBM at   
-	  <http://www10.software.ibm.com/developerworks/opensource/linux390>
+	  For details please refer to the documentation provided by IBM at
+	  <http://www.ibm.com/developerworks/linux/linux390>
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called qeth.ko.
+	  To compile this driver as a module, choose M.
+	  The module name is qeth.ko.
 
+config QETH_L2
+        tristate "qeth layer 2 device support"
+        depends on QETH
+        help
+          Select this option to be able to run qeth devices in layer 2 mode.
+          To compile as a module, choose M. The module name is qeth_l2.ko.
+          If unsure, choose y.
 
-comment "Gigabit Ethernet default settings"
-	depends on QETH
+config QETH_L3
+        tristate "qeth layer 3 device support"
+        depends on QETH
+        help
+          Select this option to be able to run qeth devices in layer 3 mode.
+          To compile as a module choose M. The module name is qeth_l3.ko.
+          If unsure, choose Y.
 
 config QETH_IPV6
-	bool "IPv6 support for gigabit ethernet"
-	depends on (QETH = IPV6) || (QETH && IPV6 = 'y')
-	help
-	  If CONFIG_QETH is switched on, this option will include IPv6
-	  support in the qeth device driver.
-	
-config QETH_VLAN
-	bool "VLAN support for gigabit ethernet"
-	depends on (QETH = VLAN_8021Q) || (QETH && VLAN_8021Q = 'y')
-	help
-	  If CONFIG_QETH is switched on, this option will include IEEE
-	  802.1q VLAN support in the qeth device driver.
+        bool
+        depends on (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y')
+        default y
 
 config CCWGROUP
- 	tristate
-	default (LCS || CTC || QETH)
+	tristate
+	default (LCS || CTCM || QETH)
 
 endmenu
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index bbe3ab2..6382c04 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -2,13 +2,15 @@
 # S/390 network devices
 #
 
-ctc-objs := ctcmain.o ctcdbug.o
-
+ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
+obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
 obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
-obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
 obj-$(CONFIG_LCS) += lcs.o cu3088.o
 obj-$(CONFIG_CLAW) += claw.o cu3088.o
-qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o 
-qeth-$(CONFIG_PROC_FS) += qeth_proc.o
+qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_core_offl.o
 obj-$(CONFIG_QETH) += qeth.o
+qeth_l2-y += qeth_l2_main.o
+obj-$(CONFIG_QETH_L2) += qeth_l2.o
+qeth_l3-y += qeth_l3_main.o qeth_l3_sys.o
+obj-$(CONFIG_QETH_L3) += qeth_l3.o
diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
deleted file mode 100644
index e6e72de..0000000
--- a/drivers/s390/net/ctcdbug.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *
- * linux/drivers/s390/net/ctcdbug.c
- *
- * CTC / ESCON network driver - s390 dbf exploit.
- *
- * Copyright 2000,2003 IBM Corporation
- *
- *    Author(s): Original Code written by
- *			  Peter Tiedemann (ptiedem@de.ibm.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "ctcdbug.h"
-
-/**
- * Debug Facility Stuff
- */
-debug_info_t *ctc_dbf_setup = NULL;
-debug_info_t *ctc_dbf_data = NULL;
-debug_info_t *ctc_dbf_trace = NULL;
-
-DEFINE_PER_CPU(char[256], ctc_dbf_txt_buf);
-
-void
-ctc_unregister_dbf_views(void)
-{
-	if (ctc_dbf_setup)
-		debug_unregister(ctc_dbf_setup);
-	if (ctc_dbf_data)
-		debug_unregister(ctc_dbf_data);
-	if (ctc_dbf_trace)
-		debug_unregister(ctc_dbf_trace);
-}
-int
-ctc_register_dbf_views(void)
-{
-	ctc_dbf_setup = debug_register(CTC_DBF_SETUP_NAME,
-					CTC_DBF_SETUP_PAGES,
-					CTC_DBF_SETUP_NR_AREAS,
-					CTC_DBF_SETUP_LEN);
-	ctc_dbf_data = debug_register(CTC_DBF_DATA_NAME,
-				       CTC_DBF_DATA_PAGES,
-				       CTC_DBF_DATA_NR_AREAS,
-				       CTC_DBF_DATA_LEN);
-	ctc_dbf_trace = debug_register(CTC_DBF_TRACE_NAME,
-					CTC_DBF_TRACE_PAGES,
-					CTC_DBF_TRACE_NR_AREAS,
-					CTC_DBF_TRACE_LEN);
-
-	if ((ctc_dbf_setup == NULL) || (ctc_dbf_data == NULL) ||
-	    (ctc_dbf_trace == NULL)) {
-		ctc_unregister_dbf_views();
-		return -ENOMEM;
-	}
-	debug_register_view(ctc_dbf_setup, &debug_hex_ascii_view);
-	debug_set_level(ctc_dbf_setup, CTC_DBF_SETUP_LEVEL);
-
-	debug_register_view(ctc_dbf_data, &debug_hex_ascii_view);
-	debug_set_level(ctc_dbf_data, CTC_DBF_DATA_LEVEL);
-
-	debug_register_view(ctc_dbf_trace, &debug_hex_ascii_view);
-	debug_set_level(ctc_dbf_trace, CTC_DBF_TRACE_LEVEL);
-
-	return 0;
-}
-
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
deleted file mode 100644
index 413925e..0000000
--- a/drivers/s390/net/ctcdbug.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *
- * linux/drivers/s390/net/ctcdbug.h
- *
- * CTC / ESCON network driver - s390 dbf exploit.
- *
- * Copyright 2000,2003 IBM Corporation
- *
- *    Author(s): Original Code written by
- *			  Peter Tiedemann (ptiedem@de.ibm.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef _CTCDBUG_H_
-#define _CTCDBUG_H_
-
-#include <asm/debug.h>
-#include "ctcmain.h"
-/**
- * Debug Facility stuff
- */
-#define CTC_DBF_SETUP_NAME "ctc_setup"
-#define CTC_DBF_SETUP_LEN 16
-#define CTC_DBF_SETUP_PAGES 8
-#define CTC_DBF_SETUP_NR_AREAS 1
-#define CTC_DBF_SETUP_LEVEL 3
-
-#define CTC_DBF_DATA_NAME "ctc_data"
-#define CTC_DBF_DATA_LEN 128
-#define CTC_DBF_DATA_PAGES 8
-#define CTC_DBF_DATA_NR_AREAS 1
-#define CTC_DBF_DATA_LEVEL 3
-
-#define CTC_DBF_TRACE_NAME "ctc_trace"
-#define CTC_DBF_TRACE_LEN 16
-#define CTC_DBF_TRACE_PAGES 4
-#define CTC_DBF_TRACE_NR_AREAS 2
-#define CTC_DBF_TRACE_LEVEL 3
-
-#define DBF_TEXT(name,level,text) \
-	do { \
-		debug_text_event(ctc_dbf_##name,level,text); \
-	} while (0)
-
-#define DBF_HEX(name,level,addr,len) \
-	do { \
-		debug_event(ctc_dbf_##name,level,(void*)(addr),len); \
-	} while (0)
-
-DECLARE_PER_CPU(char[256], ctc_dbf_txt_buf);
-extern debug_info_t *ctc_dbf_setup;
-extern debug_info_t *ctc_dbf_data;
-extern debug_info_t *ctc_dbf_trace;
-
-
-#define DBF_TEXT_(name,level,text...)				\
-	do {								\
-		char* ctc_dbf_txt_buf = get_cpu_var(ctc_dbf_txt_buf);	\
-		sprintf(ctc_dbf_txt_buf, text);			  	\
-		debug_text_event(ctc_dbf_##name,level,ctc_dbf_txt_buf);	\
-		put_cpu_var(ctc_dbf_txt_buf);				\
-	} while (0)
-
-#define DBF_SPRINTF(name,level,text...) \
-	do { \
-		debug_sprintf_event(ctc_dbf_trace, level, ##text ); \
-		debug_sprintf_event(ctc_dbf_trace, level, text ); \
-	} while (0)
-
-
-int ctc_register_dbf_views(void);
-
-void ctc_unregister_dbf_views(void);
-
-/**
- * some more debug stuff
- */
-
-#define HEXDUMP16(importance,header,ptr) \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
-		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
-		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
-		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
-		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
-		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
-		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
-		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
-		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
-		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
-		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
-		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
-		   *(((char*)ptr)+30),*(((char*)ptr)+31));
-
-static inline void
-hex_dump(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; i++) {
-		if (i && !(i % 16))
-			printk("\n");
-		printk("%02x ", *(buf + i));
-	}
-	printk("\n");
-}
-
-
-#endif
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
new file mode 100644
index 0000000..8eb25d0
--- /dev/null
+++ b/drivers/s390/net/ctcm_dbug.c
@@ -0,0 +1,67 @@
+/*
+ *	drivers/s390/net/ctcm_dbug.c
+ *
+ *	Copyright IBM Corp. 2001, 2007
+ *	Authors:	Peter Tiedemann (ptiedem@de.ibm.com)
+ *
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include "ctcm_dbug.h"
+
+/*
+ * Debug Facility Stuff
+ */
+
+DEFINE_PER_CPU(char[256], ctcm_dbf_txt_buf);
+
+struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS] = {
+	[CTCM_DBF_SETUP]	= {"ctc_setup", 8, 1, 64, 5, NULL},
+	[CTCM_DBF_ERROR]	= {"ctc_error", 8, 1, 64, 3, NULL},
+	[CTCM_DBF_TRACE]	= {"ctc_trace", 8, 1, 64, 3, NULL},
+	[CTCM_DBF_MPC_SETUP]	= {"mpc_setup", 8, 1, 64, 5, NULL},
+	[CTCM_DBF_MPC_ERROR]	= {"mpc_error", 8, 1, 64, 3, NULL},
+	[CTCM_DBF_MPC_TRACE]	= {"mpc_trace", 8, 1, 64, 3, NULL},
+};
+
+void ctcm_unregister_dbf_views(void)
+{
+	int x;
+	for (x = 0; x < CTCM_DBF_INFOS; x++) {
+		debug_unregister(ctcm_dbf[x].id);
+		ctcm_dbf[x].id = NULL;
+	}
+}
+
+int ctcm_register_dbf_views(void)
+{
+	int x;
+	for (x = 0; x < CTCM_DBF_INFOS; x++) {
+		/* register the areas */
+		ctcm_dbf[x].id = debug_register(ctcm_dbf[x].name,
+						ctcm_dbf[x].pages,
+						ctcm_dbf[x].areas,
+						ctcm_dbf[x].len);
+		if (ctcm_dbf[x].id == NULL) {
+			ctcm_unregister_dbf_views();
+			return -ENOMEM;
+		}
+
+		/* register a view */
+		debug_register_view(ctcm_dbf[x].id, &debug_hex_ascii_view);
+		/* set a passing level */
+		debug_set_level(ctcm_dbf[x].id, ctcm_dbf[x].level);
+	}
+
+	return 0;
+}
+
diff --git a/drivers/s390/net/ctcm_dbug.h b/drivers/s390/net/ctcm_dbug.h
new file mode 100644
index 0000000..fdff34f
--- /dev/null
+++ b/drivers/s390/net/ctcm_dbug.h
@@ -0,0 +1,158 @@
+/*
+ *	drivers/s390/net/ctcm_dbug.h
+ *
+ *	Copyright IBM Corp. 2001, 2007
+ *	Authors:	Peter Tiedemann (ptiedem@de.ibm.com)
+ *
+ */
+
+#ifndef _CTCM_DBUG_H_
+#define _CTCM_DBUG_H_
+
+/*
+ * Debug Facility stuff
+ */
+
+#include <asm/debug.h>
+
+#ifdef DEBUG
+ #define do_debug 1
+#else
+ #define do_debug 0
+#endif
+#ifdef DEBUGDATA
+ #define do_debug_data 1
+#else
+ #define do_debug_data 0
+#endif
+#ifdef DEBUGCCW
+ #define do_debug_ccw 1
+#else
+ #define do_debug_ccw 0
+#endif
+
+/* define dbf debug levels similar to kernel msg levels */
+#define	CTC_DBF_ALWAYS	0	/* always print this 			*/
+#define	CTC_DBF_EMERG	0	/* system is unusable			*/
+#define	CTC_DBF_ALERT	1	/* action must be taken immediately	*/
+#define	CTC_DBF_CRIT	2	/* critical conditions			*/
+#define	CTC_DBF_ERROR	3	/* error conditions			*/
+#define	CTC_DBF_WARN	4	/* warning conditions			*/
+#define	CTC_DBF_NOTICE	5	/* normal but significant condition	*/
+#define	CTC_DBF_INFO	5	/* informational			*/
+#define	CTC_DBF_DEBUG	6	/* debug-level messages			*/
+
+DECLARE_PER_CPU(char[256], ctcm_dbf_txt_buf);
+
+enum ctcm_dbf_names {
+	CTCM_DBF_SETUP,
+	CTCM_DBF_ERROR,
+	CTCM_DBF_TRACE,
+	CTCM_DBF_MPC_SETUP,
+	CTCM_DBF_MPC_ERROR,
+	CTCM_DBF_MPC_TRACE,
+	CTCM_DBF_INFOS	/* must be last element */
+};
+
+struct ctcm_dbf_info {
+	char name[DEBUG_MAX_NAME_LEN];
+	int pages;
+	int areas;
+	int len;
+	int level;
+	debug_info_t *id;
+};
+
+extern struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS];
+
+int ctcm_register_dbf_views(void);
+void ctcm_unregister_dbf_views(void);
+
+static inline const char *strtail(const char *s, int n)
+{
+	int l = strlen(s);
+	return (l > n) ? s + (l - n) : s;
+}
+
+/* sort out levels early to avoid unnecessary sprintfs */
+static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
+{
+	return (dbf_grp->level >= level);
+}
+
+#define CTCM_FUNTAIL strtail((char *)__func__, 16)
+
+#define CTCM_DBF_TEXT(name, level, text) \
+	do { \
+		debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, level, text); \
+	} while (0)
+
+#define CTCM_DBF_HEX(name, level, addr, len) \
+	do { \
+		debug_event(ctcm_dbf[CTCM_DBF_##name].id, \
+					level, (void *)(addr), len); \
+	} while (0)
+
+#define CTCM_DBF_TEXT_(name, level, text...) \
+	do { \
+		if (ctcm_dbf_passes(ctcm_dbf[CTCM_DBF_##name].id, level)) { \
+			char *ctcm_dbf_txt_buf = \
+					 get_cpu_var(ctcm_dbf_txt_buf); \
+			sprintf(ctcm_dbf_txt_buf, text); \
+			debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, \
+					level, ctcm_dbf_txt_buf); \
+			put_cpu_var(ctcm_dbf_txt_buf); \
+		} \
+	} while (0)
+
+/*
+ * cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
+ * dev : netdevice with valid name field.
+ * text: any text string.
+ */
+#define CTCM_DBF_DEV_NAME(cat, dev, text) \
+	do { \
+		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) : %s", \
+			CTCM_FUNTAIL, dev->name, text); \
+	} while (0)
+
+#define MPC_DBF_DEV_NAME(cat, dev, text) \
+	do { \
+		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) : %s", \
+			CTCM_FUNTAIL, dev->name, text); \
+	} while (0)
+
+#define CTCMY_DBF_DEV_NAME(cat, dev, text) \
+	do { \
+		if (IS_MPCDEV(dev)) \
+			MPC_DBF_DEV_NAME(cat, dev, text); \
+		else \
+			CTCM_DBF_DEV_NAME(cat, dev, text); \
+	} while (0)
+
+/*
+ * cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
+ * dev : netdevice.
+ * text: any text string.
+ */
+#define CTCM_DBF_DEV(cat, dev, text) \
+	do { \
+		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) : %s", \
+			CTCM_FUNTAIL, dev, text); \
+	} while (0)
+
+#define MPC_DBF_DEV(cat, dev, text) \
+	do { \
+		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) : %s", \
+			CTCM_FUNTAIL, dev, text); \
+	} while (0)
+
+#define CTCMY_DBF_DEV(cat, dev, text) \
+	do { \
+		if (IS_MPCDEV(dev)) \
+			MPC_DBF_DEV(cat, dev, text); \
+		else \
+			CTCM_DBF_DEV(cat, dev, text); \
+	} while (0)
+
+#endif
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
new file mode 100644
index 0000000..2a106f3
--- /dev/null
+++ b/drivers/s390/net/ctcm_fsms.c
@@ -0,0 +1,2347 @@
+/*
+ * drivers/s390/net/ctcm_fsms.c
+ *
+ * Copyright IBM Corp. 2001, 2007
+ * Authors:	Fritz Elfert (felfert@millenux.com)
+ * 		Peter Tiedemann (ptiedem@de.ibm.com)
+ *	MPC additions :
+ *		Belinda Thompson (belindat@us.ibm.com)
+ *		Andy Richter (richtera@us.ibm.com)
+ */
+
+#undef DEBUG
+#undef DEBUGDATA
+#undef DEBUGCCW
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/bitops.h>
+
+#include <linux/signal.h>
+#include <linux/string.h>
+
+#include <linux/ip.h>
+#include <linux/if_arp.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/ctype.h>
+#include <net/dst.h>
+
+#include <linux/io.h>
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+#include <linux/uaccess.h>
+
+#include <asm/idals.h>
+
+#include "fsm.h"
+#include "cu3088.h"
+
+#include "ctcm_dbug.h"
+#include "ctcm_main.h"
+#include "ctcm_fsms.h"
+
+const char *dev_state_names[] = {
+	[DEV_STATE_STOPPED]		= "Stopped",
+	[DEV_STATE_STARTWAIT_RXTX]	= "StartWait RXTX",
+	[DEV_STATE_STARTWAIT_RX]	= "StartWait RX",
+	[DEV_STATE_STARTWAIT_TX]	= "StartWait TX",
+	[DEV_STATE_STOPWAIT_RXTX]	= "StopWait RXTX",
+	[DEV_STATE_STOPWAIT_RX]		= "StopWait RX",
+	[DEV_STATE_STOPWAIT_TX]		= "StopWait TX",
+	[DEV_STATE_RUNNING]		= "Running",
+};
+
+const char *dev_event_names[] = {
+	[DEV_EVENT_START]	= "Start",
+	[DEV_EVENT_STOP]	= "Stop",
+	[DEV_EVENT_RXUP]	= "RX up",
+	[DEV_EVENT_TXUP]	= "TX up",
+	[DEV_EVENT_RXDOWN]	= "RX down",
+	[DEV_EVENT_TXDOWN]	= "TX down",
+	[DEV_EVENT_RESTART]	= "Restart",
+};
+
+const char *ctc_ch_event_names[] = {
+	[CTC_EVENT_IO_SUCCESS]	= "ccw_device success",
+	[CTC_EVENT_IO_EBUSY]	= "ccw_device busy",
+	[CTC_EVENT_IO_ENODEV]	= "ccw_device enodev",
+	[CTC_EVENT_IO_UNKNOWN]	= "ccw_device unknown",
+	[CTC_EVENT_ATTNBUSY]	= "Status ATTN & BUSY",
+	[CTC_EVENT_ATTN]	= "Status ATTN",
+	[CTC_EVENT_BUSY]	= "Status BUSY",
+	[CTC_EVENT_UC_RCRESET]	= "Unit check remote reset",
+	[CTC_EVENT_UC_RSRESET]	= "Unit check remote system reset",
+	[CTC_EVENT_UC_TXTIMEOUT] = "Unit check TX timeout",
+	[CTC_EVENT_UC_TXPARITY]	= "Unit check TX parity",
+	[CTC_EVENT_UC_HWFAIL]	= "Unit check Hardware failure",
+	[CTC_EVENT_UC_RXPARITY]	= "Unit check RX parity",
+	[CTC_EVENT_UC_ZERO]	= "Unit check ZERO",
+	[CTC_EVENT_UC_UNKNOWN]	= "Unit check Unknown",
+	[CTC_EVENT_SC_UNKNOWN]	= "SubChannel check Unknown",
+	[CTC_EVENT_MC_FAIL]	= "Machine check failure",
+	[CTC_EVENT_MC_GOOD]	= "Machine check operational",
+	[CTC_EVENT_IRQ]		= "IRQ normal",
+	[CTC_EVENT_FINSTAT]	= "IRQ final",
+	[CTC_EVENT_TIMER]	= "Timer",
+	[CTC_EVENT_START]	= "Start",
+	[CTC_EVENT_STOP]	= "Stop",
+	/*
+	* additional MPC events
+	*/
+	[CTC_EVENT_SEND_XID]	= "XID Exchange",
+	[CTC_EVENT_RSWEEP_TIMER] = "MPC Group Sweep Timer",
+};
+
+const char *ctc_ch_state_names[] = {
+	[CTC_STATE_IDLE]	= "Idle",
+	[CTC_STATE_STOPPED]	= "Stopped",
+	[CTC_STATE_STARTWAIT]	= "StartWait",
+	[CTC_STATE_STARTRETRY]	= "StartRetry",
+	[CTC_STATE_SETUPWAIT]	= "SetupWait",
+	[CTC_STATE_RXINIT]	= "RX init",
+	[CTC_STATE_TXINIT]	= "TX init",
+	[CTC_STATE_RX]		= "RX",
+	[CTC_STATE_TX]		= "TX",
+	[CTC_STATE_RXIDLE]	= "RX idle",
+	[CTC_STATE_TXIDLE]	= "TX idle",
+	[CTC_STATE_RXERR]	= "RX error",
+	[CTC_STATE_TXERR]	= "TX error",
+	[CTC_STATE_TERM]	= "Terminating",
+	[CTC_STATE_DTERM]	= "Restarting",
+	[CTC_STATE_NOTOP]	= "Not operational",
+	/*
+	* additional MPC states
+	*/
+	[CH_XID0_PENDING]	= "Pending XID0 Start",
+	[CH_XID0_INPROGRESS]	= "In XID0 Negotiations ",
+	[CH_XID7_PENDING]	= "Pending XID7 P1 Start",
+	[CH_XID7_PENDING1]	= "Active XID7 P1 Exchange ",
+	[CH_XID7_PENDING2]	= "Pending XID7 P2 Start ",
+	[CH_XID7_PENDING3]	= "Active XID7 P2 Exchange ",
+	[CH_XID7_PENDING4]	= "XID7 Complete - Pending READY ",
+};
+
+static void ctcm_action_nop(fsm_instance *fi, int event, void *arg);
+
+/*
+ * ----- static ctcm actions for channel statemachine -----
+ *
+*/
+static void chx_txdone(fsm_instance *fi, int event, void *arg);
+static void chx_rx(fsm_instance *fi, int event, void *arg);
+static void chx_rxidle(fsm_instance *fi, int event, void *arg);
+static void chx_firstio(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);
+
+/*
+ * ----- static ctcmpc actions for ctcmpc channel statemachine -----
+ *
+*/
+static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg);
+static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg);
+static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg);
+/* shared :
+static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);
+static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);
+*/
+static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg);
+static void ctcmpc_chx_attnbusy(fsm_instance *, int, void *);
+static void ctcmpc_chx_resend(fsm_instance *, int, void *);
+static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg);
+
+/**
+ * Check return code of a preceeding ccw_device call, halt_IO etc...
+ *
+ * ch	:	The channel, the error belongs to.
+ * Returns the error code (!= 0) to inspect.
+ */
+void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg)
+{
+	CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+			"ccw error %s (%s): %04x\n", ch->id, msg, rc);
+	switch (rc) {
+	case -EBUSY:
+		ctcm_pr_warn("%s (%s): Busy !\n", ch->id, msg);
+		fsm_event(ch->fsm, CTC_EVENT_IO_EBUSY, ch);
+		break;
+	case -ENODEV:
+		ctcm_pr_emerg("%s (%s): Invalid device called for IO\n",
+			     ch->id, msg);
+		fsm_event(ch->fsm, CTC_EVENT_IO_ENODEV, ch);
+		break;
+	default:
+		ctcm_pr_emerg("%s (%s): Unknown error in do_IO %04x\n",
+			     ch->id, msg, rc);
+		fsm_event(ch->fsm, CTC_EVENT_IO_UNKNOWN, ch);
+	}
+}
+
+void ctcm_purge_skb_queue(struct sk_buff_head *q)
+{
+	struct sk_buff *skb;
+
+	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+
+	while ((skb = skb_dequeue(q))) {
+		atomic_dec(&skb->users);
+		dev_kfree_skb_any(skb);
+	}
+}
+
+/**
+ * NOP action for statemachines
+ */
+static void ctcm_action_nop(fsm_instance *fi, int event, void *arg)
+{
+}
+
+/*
+ * Actions for channel - statemachines.
+ */
+
+/**
+ * Normal data has been send. Free the corresponding
+ * skb (it's in io_queue), reset dev->tbusy and
+ * revert to idle state.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void chx_txdone(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	struct sk_buff *skb;
+	int first = 1;
+	int i;
+	unsigned long duration;
+	struct timespec done_stamp = current_kernel_time(); /* xtime */
+
+	duration =
+	    (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
+	    (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
+	if (duration > ch->prof.tx_time)
+		ch->prof.tx_time = duration;
+
+	if (ch->irb->scsw.count != 0)
+		ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
+			     dev->name, ch->irb->scsw.count);
+	fsm_deltimer(&ch->timer);
+	while ((skb = skb_dequeue(&ch->io_queue))) {
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+		if (first) {
+			priv->stats.tx_bytes += 2;
+			first = 0;
+		}
+		atomic_dec(&skb->users);
+		dev_kfree_skb_irq(skb);
+	}
+	spin_lock(&ch->collect_lock);
+	clear_normalized_cda(&ch->ccw[4]);
+	if (ch->collect_len > 0) {
+		int rc;
+
+		if (ctcm_checkalloc_buffer(ch)) {
+			spin_unlock(&ch->collect_lock);
+			return;
+		}
+		ch->trans_skb->data = ch->trans_skb_data;
+		skb_reset_tail_pointer(ch->trans_skb);
+		ch->trans_skb->len = 0;
+		if (ch->prof.maxmulti < (ch->collect_len + 2))
+			ch->prof.maxmulti = ch->collect_len + 2;
+		if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
+			ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
+		*((__u16 *)skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;
+		i = 0;
+		while ((skb = skb_dequeue(&ch->collect_queue))) {
+			skb_copy_from_linear_data(skb,
+				skb_put(ch->trans_skb, skb->len), skb->len);
+			priv->stats.tx_packets++;
+			priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+			atomic_dec(&skb->users);
+			dev_kfree_skb_irq(skb);
+			i++;
+		}
+		ch->collect_len = 0;
+		spin_unlock(&ch->collect_lock);
+		ch->ccw[1].count = ch->trans_skb->len;
+		fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+		ch->prof.send_stamp = current_kernel_time(); /* xtime */
+		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+						(unsigned long)ch, 0xff, 0);
+		ch->prof.doios_multi++;
+		if (rc != 0) {
+			priv->stats.tx_dropped += i;
+			priv->stats.tx_errors += i;
+			fsm_deltimer(&ch->timer);
+			ctcm_ccw_check_rc(ch, rc, "chained TX");
+		}
+	} else {
+		spin_unlock(&ch->collect_lock);
+		fsm_newstate(fi, CTC_STATE_TXIDLE);
+	}
+	ctcm_clear_busy_do(dev);
+}
+
+/**
+ * Initial data is sent.
+ * Notify device statemachine that we are up and
+ * running.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+	fsm_deltimer(&ch->timer);
+	fsm_newstate(fi, CTC_STATE_TXIDLE);
+	fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);
+}
+
+/**
+ * Got normal data, check for sanity, queue it up, allocate new buffer
+ * trigger bottom half, and initiate next read.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void chx_rx(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	int len = ch->max_bufsize - ch->irb->scsw.count;
+	struct sk_buff *skb = ch->trans_skb;
+	__u16 block_len = *((__u16 *)skb->data);
+	int check_len;
+	int rc;
+
+	fsm_deltimer(&ch->timer);
+	if (len < 8) {
+		ctcm_pr_debug("%s: got packet with length %d < 8\n",
+			     dev->name, len);
+		priv->stats.rx_dropped++;
+		priv->stats.rx_length_errors++;
+						goto again;
+	}
+	if (len > ch->max_bufsize) {
+		ctcm_pr_debug("%s: got packet with length %d > %d\n",
+			     dev->name, len, ch->max_bufsize);
+		priv->stats.rx_dropped++;
+		priv->stats.rx_length_errors++;
+						goto again;
+	}
+
+	/*
+	 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
+	 */
+	switch (ch->protocol) {
+	case CTCM_PROTO_S390:
+	case CTCM_PROTO_OS390:
+		check_len = block_len + 2;
+		break;
+	default:
+		check_len = block_len;
+		break;
+	}
+	if ((len < block_len) || (len > check_len)) {
+		ctcm_pr_debug("%s: got block length %d != rx length %d\n",
+			     dev->name, block_len, len);
+		if (do_debug)
+			ctcmpc_dump_skb(skb, 0);
+
+		*((__u16 *)skb->data) = len;
+		priv->stats.rx_dropped++;
+		priv->stats.rx_length_errors++;
+						goto again;
+	}
+	block_len -= 2;
+	if (block_len > 0) {
+		*((__u16 *)skb->data) = block_len;
+		ctcm_unpack_skb(ch, skb);
+	}
+ again:
+	skb->data = ch->trans_skb_data;
+	skb_reset_tail_pointer(skb);
+	skb->len = 0;
+	if (ctcm_checkalloc_buffer(ch))
+		return;
+	ch->ccw[1].count = ch->max_bufsize;
+	rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+					(unsigned long)ch, 0xff, 0);
+	if (rc != 0)
+		ctcm_ccw_check_rc(ch, rc, "normal RX");
+}
+
+/**
+ * Initialize connection by sending a __u16 of value 0.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void chx_firstio(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	int rc;
+
+	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+
+	if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
+		ctcm_pr_debug("%s: remote side issued READ?, init.\n", ch->id);
+	fsm_deltimer(&ch->timer);
+	if (ctcm_checkalloc_buffer(ch))
+		return;
+	if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
+	    (ch->protocol == CTCM_PROTO_OS390)) {
+		/* OS/390 resp. z/OS */
+		if (CHANNEL_DIRECTION(ch->flags) == READ) {
+			*((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
+			fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC,
+				     CTC_EVENT_TIMER, ch);
+			chx_rxidle(fi, event, arg);
+		} else {
+			struct net_device *dev = ch->netdev;
+			struct ctcm_priv *priv = dev->priv;
+			fsm_newstate(fi, CTC_STATE_TXIDLE);
+			fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);
+		}
+		return;
+	}
+
+	/*
+	 * Don't setup a timer for receiving the initial RX frame
+	 * if in compatibility mode, since VM TCP delays the initial
+	 * frame until it has some data to send.
+	 */
+	if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
+	    (ch->protocol != CTCM_PROTO_S390))
+		fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+
+	*((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
+	ch->ccw[1].count = 2;	/* Transfer only length */
+
+	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
+		     ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
+	rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+					(unsigned long)ch, 0xff, 0);
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		fsm_newstate(fi, CTC_STATE_SETUPWAIT);
+		ctcm_ccw_check_rc(ch, rc, "init IO");
+	}
+	/*
+	 * If in compatibility mode since we don't setup a timer, we
+	 * also signal RX channel up immediately. This enables us
+	 * to send packets early which in turn usually triggers some
+	 * reply from VM TCP which brings up the RX channel to it's
+	 * final state.
+	 */
+	if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
+	    (ch->protocol == CTCM_PROTO_S390)) {
+		struct net_device *dev = ch->netdev;
+		struct ctcm_priv *priv = dev->priv;
+		fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
+	}
+}
+
+/**
+ * Got initial data, check it. If OK,
+ * notify device statemachine that we are up and
+ * running.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void chx_rxidle(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	__u16 buflen;
+	int rc;
+
+	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+	fsm_deltimer(&ch->timer);
+	buflen = *((__u16 *)ch->trans_skb->data);
+	if (do_debug)
+		ctcm_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+
+	if (buflen >= CTCM_INITIAL_BLOCKLEN) {
+		if (ctcm_checkalloc_buffer(ch))
+			return;
+		ch->ccw[1].count = ch->max_bufsize;
+		fsm_newstate(fi, CTC_STATE_RXIDLE);
+		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+						(unsigned long)ch, 0xff, 0);
+		if (rc != 0) {
+			fsm_newstate(fi, CTC_STATE_RXINIT);
+			ctcm_ccw_check_rc(ch, rc, "initial RX");
+		} else
+			fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
+	} else {
+		if (do_debug)
+			ctcm_pr_debug("%s: Initial RX count %d not %d\n",
+				dev->name, buflen, CTCM_INITIAL_BLOCKLEN);
+		chx_firstio(fi, event, arg);
+	}
+}
+
+/**
+ * Set channel into extended mode.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	int rc;
+	unsigned long saveflags = 0;
+	int timeout = CTCM_TIME_5_SEC;
+
+	fsm_deltimer(&ch->timer);
+	if (IS_MPC(ch)) {
+		timeout = 1500;
+		if (do_debug)
+			ctcm_pr_debug("ctcm enter: %s(): cp=%i ch=0x%p id=%s\n",
+				__FUNCTION__, smp_processor_id(), ch, ch->id);
+	}
+	fsm_addtimer(&ch->timer, timeout, CTC_EVENT_TIMER, ch);
+	fsm_newstate(fi, CTC_STATE_SETUPWAIT);
+	if (do_debug_ccw && IS_MPC(ch))
+		ctcmpc_dumpit((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
+
+	if (event == CTC_EVENT_TIMER)	/* only for timer not yet locked */
+		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+			/* Such conditional locking is undeterministic in
+			 * static view. => ignore sparse warnings here. */
+
+	rc = ccw_device_start(ch->cdev, &ch->ccw[6],
+					(unsigned long)ch, 0xff, 0);
+	if (event == CTC_EVENT_TIMER)	/* see above comments */
+		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		fsm_newstate(fi, CTC_STATE_STARTWAIT);
+		ctcm_ccw_check_rc(ch, rc, "set Mode");
+	} else
+		ch->retry = 0;
+}
+
+/**
+ * Setup channel.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	int rc;
+	struct net_device *dev;
+	unsigned long saveflags;
+
+	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
+	if (ch == NULL) {
+		ctcm_pr_warn("chx_start ch=NULL\n");
+		return;
+	}
+	if (ch->netdev == NULL) {
+		ctcm_pr_warn("chx_start dev=NULL, id=%s\n", ch->id);
+		return;
+	}
+	dev = ch->netdev;
+
+	if (do_debug)
+		ctcm_pr_debug("%s: %s channel start\n", dev->name,
+			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+
+	if (ch->trans_skb != NULL) {
+		clear_normalized_cda(&ch->ccw[1]);
+		dev_kfree_skb(ch->trans_skb);
+		ch->trans_skb = NULL;
+	}
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		ch->ccw[1].cmd_code = CCW_CMD_READ;
+		ch->ccw[1].flags = CCW_FLAG_SLI;
+		ch->ccw[1].count = 0;
+	} else {
+		ch->ccw[1].cmd_code = CCW_CMD_WRITE;
+		ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[1].count = 0;
+	}
+	if (ctcm_checkalloc_buffer(ch)) {
+		ctcm_pr_notice("%s: %s trans_skb allocation delayed "
+				"until first transfer\n", dev->name,
+			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+	}
+
+	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
+	ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+	ch->ccw[0].count = 0;
+	ch->ccw[0].cda = 0;
+	ch->ccw[2].cmd_code = CCW_CMD_NOOP;	/* jointed CE + DE */
+	ch->ccw[2].flags = CCW_FLAG_SLI;
+	ch->ccw[2].count = 0;
+	ch->ccw[2].cda = 0;
+	memcpy(&ch->ccw[3], &ch->ccw[0], sizeof(struct ccw1) * 3);
+	ch->ccw[4].cda = 0;
+	ch->ccw[4].flags &= ~CCW_FLAG_IDA;
+
+	fsm_newstate(fi, CTC_STATE_STARTWAIT);
+	fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);
+	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+	rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
+	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+	if (rc != 0) {
+		if (rc != -EBUSY)
+			fsm_deltimer(&ch->timer);
+		ctcm_ccw_check_rc(ch, rc, "initial HaltIO");
+	}
+}
+
+/**
+ * Shutdown a channel.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	unsigned long saveflags = 0;
+	int rc;
+	int oldstate;
+
+	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+	fsm_deltimer(&ch->timer);
+	if (IS_MPC(ch))
+		fsm_deltimer(&ch->sweep_timer);
+
+	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+
+	if (event == CTC_EVENT_STOP)	/* only for STOP not yet locked */
+		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+			/* Such conditional locking is undeterministic in
+			 * static view. => ignore sparse warnings here. */
+	oldstate = fsm_getstate(fi);
+	fsm_newstate(fi, CTC_STATE_TERM);
+	rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
+
+	if (event == CTC_EVENT_STOP)
+		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+			/* see remark above about conditional locking */
+
+	if (rc != 0 && rc != -EBUSY) {
+		fsm_deltimer(&ch->timer);
+		if (event != CTC_EVENT_STOP) {
+			fsm_newstate(fi, oldstate);
+			ctcm_ccw_check_rc(ch, rc, (char *)__FUNCTION__);
+		}
+	}
+}
+
+/**
+ * Cleanup helper for chx_fail and chx_stopped
+ * cleanup channels queue and notify interface statemachine.
+ *
+ * fi		An instance of a channel statemachine.
+ * state	The next state (depending on caller).
+ * ch		The channel to operate on.
+ */
+static void ctcm_chx_cleanup(fsm_instance *fi, int state,
+		struct channel *ch)
+{
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+
+	fsm_deltimer(&ch->timer);
+	if (IS_MPC(ch))
+		fsm_deltimer(&ch->sweep_timer);
+
+	fsm_newstate(fi, state);
+	if (state == CTC_STATE_STOPPED && ch->trans_skb != NULL) {
+		clear_normalized_cda(&ch->ccw[1]);
+		dev_kfree_skb_any(ch->trans_skb);
+		ch->trans_skb = NULL;
+	}
+
+	ch->th_seg = 0x00;
+	ch->th_seq_num = 0x00;
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		skb_queue_purge(&ch->io_queue);
+		fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
+	} else {
+		ctcm_purge_skb_queue(&ch->io_queue);
+		if (IS_MPC(ch))
+			ctcm_purge_skb_queue(&ch->sweep_queue);
+		spin_lock(&ch->collect_lock);
+		ctcm_purge_skb_queue(&ch->collect_queue);
+		ch->collect_len = 0;
+		spin_unlock(&ch->collect_lock);
+		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
+	}
+}
+
+/**
+ * A channel has successfully been halted.
+ * Cleanup it's queue and notify interface statemachine.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg)
+{
+	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+	ctcm_chx_cleanup(fi, CTC_STATE_STOPPED, arg);
+}
+
+/**
+ * A stop command from device statemachine arrived and we are in
+ * not operational mode. Set state to stopped.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg)
+{
+	fsm_newstate(fi, CTC_STATE_STOPPED);
+}
+
+/**
+ * A machine check for no path, not operational status or gone device has
+ * happened.
+ * Cleanup queue and notify interface statemachine.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg)
+{
+	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+	ctcm_chx_cleanup(fi, CTC_STATE_NOTOP, arg);
+}
+
+/**
+ * Handle error during setup of channel.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	/*
+	 * Special case: Got UC_RCRESET on setmode.
+	 * This means that remote side isn't setup. In this case
+	 * simply retry after some 10 secs...
+	 */
+	if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
+	    ((event == CTC_EVENT_UC_RCRESET) ||
+	     (event == CTC_EVENT_UC_RSRESET))) {
+		fsm_newstate(fi, CTC_STATE_STARTRETRY);
+		fsm_deltimer(&ch->timer);
+		fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+		if (!IS_MPC(ch) && (CHANNEL_DIRECTION(ch->flags) == READ)) {
+			int rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
+			if (rc != 0)
+				ctcm_ccw_check_rc(ch, rc,
+					"HaltIO in chx_setuperr");
+		}
+		return;
+	}
+
+	CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
+		"%s : %s error during %s channel setup state=%s\n",
+		dev->name, ctc_ch_event_names[event],
+		(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
+		fsm_getstate_str(fi));
+
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		fsm_newstate(fi, CTC_STATE_RXERR);
+		fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
+	} else {
+		fsm_newstate(fi, CTC_STATE_TXERR);
+		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
+	}
+}
+
+/**
+ * Restart a channel after an error.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	unsigned long saveflags = 0;
+	int oldstate;
+	int rc;
+
+	CTCM_DBF_TEXT(TRACE, CTC_DBF_NOTICE, __FUNCTION__);
+	fsm_deltimer(&ch->timer);
+	ctcm_pr_debug("%s: %s channel restart\n", dev->name,
+		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+	oldstate = fsm_getstate(fi);
+	fsm_newstate(fi, CTC_STATE_STARTWAIT);
+	if (event == CTC_EVENT_TIMER)	/* only for timer not yet locked */
+		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+			/* Such conditional locking is a known problem for
+			 * sparse because its undeterministic in static view.
+			 * Warnings should be ignored here. */
+	rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
+	if (event == CTC_EVENT_TIMER)
+		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+	if (rc != 0) {
+		if (rc != -EBUSY) {
+		    fsm_deltimer(&ch->timer);
+		    fsm_newstate(fi, oldstate);
+		}
+		ctcm_ccw_check_rc(ch, rc, "HaltIO in ctcm_chx_restart");
+	}
+}
+
+/**
+ * Handle error during RX initial handshake (exchange of
+ * 0-length block header)
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
+	if (event == CTC_EVENT_TIMER) {
+		if (!IS_MPCDEV(dev))
+			/* TODO : check if MPC deletes timer somewhere */
+			fsm_deltimer(&ch->timer);
+		ctcm_pr_debug("%s: Timeout during RX init handshake\n",
+				dev->name);
+		if (ch->retry++ < 3)
+			ctcm_chx_restart(fi, event, arg);
+		else {
+			fsm_newstate(fi, CTC_STATE_RXERR);
+			fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
+		}
+	} else
+		ctcm_pr_warn("%s: Error during RX init handshake\n", dev->name);
+}
+
+/**
+ * Notify device statemachine if we gave up initialization
+ * of RX channel.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
+	fsm_newstate(fi, CTC_STATE_RXERR);
+	ctcm_pr_warn("%s: RX busy. Initialization failed\n", dev->name);
+	fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
+}
+
+/**
+ * Handle RX Unit check remote reset (remote disconnected)
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct channel *ch2;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCM_DBF_DEV_NAME(TRACE, dev, "Got remote disconnect, re-initializing");
+	fsm_deltimer(&ch->timer);
+	if (do_debug)
+		ctcm_pr_debug("%s: Got remote disconnect, "
+				"re-initializing ...\n", dev->name);
+	/*
+	 * Notify device statemachine
+	 */
+	fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
+	fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
+
+	fsm_newstate(fi, CTC_STATE_DTERM);
+	ch2 = priv->channel[WRITE];
+	fsm_newstate(ch2->fsm, CTC_STATE_DTERM);
+
+	ccw_device_halt(ch->cdev, (unsigned long)ch);
+	ccw_device_halt(ch2->cdev, (unsigned long)ch2);
+}
+
+/**
+ * Handle error during TX channel initialization.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	if (event == CTC_EVENT_TIMER) {
+		fsm_deltimer(&ch->timer);
+		CTCM_DBF_DEV_NAME(ERROR, dev,
+				"Timeout during TX init handshake");
+		if (ch->retry++ < 3)
+			ctcm_chx_restart(fi, event, arg);
+		else {
+			fsm_newstate(fi, CTC_STATE_TXERR);
+			fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
+		}
+	} else {
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+			"%s : %s error during channel setup state=%s",
+			dev->name, ctc_ch_event_names[event],
+			fsm_getstate_str(fi));
+
+		ctcm_pr_warn("%s: Error during TX init handshake\n", dev->name);
+	}
+}
+
+/**
+ * Handle TX timeout by retrying operation.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	struct sk_buff *skb;
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+			__FUNCTION__, smp_processor_id(), ch, ch->id);
+
+	fsm_deltimer(&ch->timer);
+	if (ch->retry++ > 3) {
+		struct mpc_group *gptr = priv->mpcg;
+		ctcm_pr_debug("%s: TX retry failed, restarting channel\n",
+			     dev->name);
+		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
+		/* call restart if not MPC or if MPC and mpcg fsm is ready.
+			use gptr as mpc indicator */
+		if (!(gptr && (fsm_getstate(gptr->fsm) != MPCG_STATE_READY)))
+			ctcm_chx_restart(fi, event, arg);
+				goto done;
+	}
+
+	ctcm_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
+	skb = skb_peek(&ch->io_queue);
+	if (skb) {
+		int rc = 0;
+		unsigned long saveflags = 0;
+		clear_normalized_cda(&ch->ccw[4]);
+		ch->ccw[4].count = skb->len;
+		if (set_normalized_cda(&ch->ccw[4], skb->data)) {
+			ctcm_pr_debug("%s: IDAL alloc failed, chan restart\n",
+						dev->name);
+			fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
+			ctcm_chx_restart(fi, event, arg);
+				goto done;
+		}
+		fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);
+		if (event == CTC_EVENT_TIMER) /* for TIMER not yet locked */
+			spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+			/* Such conditional locking is a known problem for
+			 * sparse because its undeterministic in static view.
+			 * Warnings should be ignored here. */
+		if (do_debug_ccw)
+			ctcmpc_dumpit((char *)&ch->ccw[3],
+					sizeof(struct ccw1) * 3);
+
+		rc = ccw_device_start(ch->cdev, &ch->ccw[3],
+						(unsigned long)ch, 0xff, 0);
+		if (event == CTC_EVENT_TIMER)
+			spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),
+					saveflags);
+		if (rc != 0) {
+			fsm_deltimer(&ch->timer);
+			ctcm_ccw_check_rc(ch, rc, "TX in chx_txretry");
+			ctcm_purge_skb_queue(&ch->io_queue);
+		}
+	}
+done:
+	return;
+}
+
+/**
+ * Handle fatal errors during an I/O command.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+	fsm_deltimer(&ch->timer);
+	ctcm_pr_warn("%s %s : unrecoverable channel error\n",
+			CTC_DRIVER_NAME, dev->name);
+	if (IS_MPC(ch)) {
+		priv->stats.tx_dropped++;
+		priv->stats.tx_errors++;
+	}
+
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		ctcm_pr_debug("%s: RX I/O error\n", dev->name);
+		fsm_newstate(fi, CTC_STATE_RXERR);
+		fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
+	} else {
+		ctcm_pr_debug("%s: TX I/O error\n", dev->name);
+		fsm_newstate(fi, CTC_STATE_TXERR);
+		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
+	}
+}
+
+/*
+ * The ctcm statemachine for a channel.
+ */
+const fsm_node ch_fsm[] = {
+	{ CTC_STATE_STOPPED,	CTC_EVENT_STOP,		ctcm_action_nop  },
+	{ CTC_STATE_STOPPED,	CTC_EVENT_START,	ctcm_chx_start  },
+	{ CTC_STATE_STOPPED,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
+	{ CTC_STATE_STOPPED,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
+
+	{ CTC_STATE_NOTOP,	CTC_EVENT_STOP,		ctcm_chx_stop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_GOOD,	ctcm_chx_start  },
+
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setuperr  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_FINSTAT,	chx_firstio  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_RXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_FINSTAT,	chx_rxidle  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxiniterr  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_rxiniterr  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_TIMER,	ctcm_chx_rxiniterr  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_ATTNBUSY,	ctcm_chx_rxinitfail  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_ZERO,	chx_firstio  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_FINSTAT,	chx_rx  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxdisc  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_ZERO,	chx_rx  },
+
+	{ CTC_STATE_TXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_FINSTAT,	ctcm_chx_txidle  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_txiniterr  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_txiniterr  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_TIMER,	ctcm_chx_txiniterr  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_FINSTAT,	chx_firstio  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_TERM,	CTC_EVENT_STOP,		ctcm_action_nop  },
+	{ CTC_STATE_TERM,	CTC_EVENT_START,	ctcm_chx_restart  },
+	{ CTC_STATE_TERM,	CTC_EVENT_FINSTAT,	ctcm_chx_stopped  },
+	{ CTC_STATE_TERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
+	{ CTC_STATE_TERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
+	{ CTC_STATE_TERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_DTERM,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_START,	ctcm_chx_restart  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_TX,		CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TX,		CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_TX,		CTC_EVENT_FINSTAT,	chx_txdone  },
+	{ CTC_STATE_TX,		CTC_EVENT_UC_RCRESET,	ctcm_chx_txretry  },
+	{ CTC_STATE_TX,		CTC_EVENT_UC_RSRESET,	ctcm_chx_txretry  },
+	{ CTC_STATE_TX,		CTC_EVENT_TIMER,	ctcm_chx_txretry  },
+	{ CTC_STATE_TX,		CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_TX,		CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_RXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_RXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+};
+
+int ch_fsm_len = ARRAY_SIZE(ch_fsm);
+
+/*
+ * MPC actions for mpc channel statemachine
+ * handling of MPC protocol requires extra
+ * statemachine and actions which are prefixed ctcmpc_ .
+ * The ctc_ch_states and ctc_ch_state_names,
+ * ctc_ch_events and ctc_ch_event_names share the ctcm definitions
+ * which are expanded by some elements.
+ */
+
+/*
+ * Actions for mpc channel statemachine.
+ */
+
+/**
+ * Normal data has been send. Free the corresponding
+ * skb (it's in io_queue), reset dev->tbusy and
+ * revert to idle state.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
+{
+	struct channel		*ch = arg;
+	struct net_device	*dev = ch->netdev;
+	struct ctcm_priv	*priv = dev->priv;
+	struct mpc_group	*grp = priv->mpcg;
+	struct sk_buff		*skb;
+	int		first = 1;
+	int		i;
+	struct timespec done_stamp;
+	__u32		data_space;
+	unsigned long	duration;
+	struct sk_buff	*peekskb;
+	int		rc;
+	struct th_header *header;
+	struct pdu	*p_header;
+
+	if (do_debug)
+		ctcm_pr_debug("%s cp:%i enter:  %s()\n",
+			dev->name, smp_processor_id(), __FUNCTION__);
+
+	done_stamp = current_kernel_time(); /* xtime */
+	duration = (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000
+		+ (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
+	if (duration > ch->prof.tx_time)
+		ch->prof.tx_time = duration;
+
+	if (ch->irb->scsw.count != 0)
+		ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
+				dev->name, ch->irb->scsw.count);
+	fsm_deltimer(&ch->timer);
+	while ((skb = skb_dequeue(&ch->io_queue))) {
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
+		if (first) {
+			priv->stats.tx_bytes += 2;
+			first = 0;
+		}
+		atomic_dec(&skb->users);
+		dev_kfree_skb_irq(skb);
+	}
+	spin_lock(&ch->collect_lock);
+	clear_normalized_cda(&ch->ccw[4]);
+
+	if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) {
+		spin_unlock(&ch->collect_lock);
+		fsm_newstate(fi, CTC_STATE_TXIDLE);
+				goto done;
+	}
+
+	if (ctcm_checkalloc_buffer(ch)) {
+		spin_unlock(&ch->collect_lock);
+				goto done;
+	}
+	ch->trans_skb->data = ch->trans_skb_data;
+	skb_reset_tail_pointer(ch->trans_skb);
+	ch->trans_skb->len = 0;
+	if (ch->prof.maxmulti < (ch->collect_len + TH_HEADER_LENGTH))
+		ch->prof.maxmulti = ch->collect_len + TH_HEADER_LENGTH;
+	if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
+		ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
+	i = 0;
+
+	if (do_debug_data)
+		ctcm_pr_debug("ctcmpc: %s() building "
+			       "trans_skb from collect_q \n", __FUNCTION__);
+
+	data_space = grp->group_max_buflen - TH_HEADER_LENGTH;
+
+	if (do_debug_data)
+		ctcm_pr_debug("ctcmpc: %s() building trans_skb from collect_q"
+		       " data_space:%04x\n", __FUNCTION__, data_space);
+	p_header = NULL;
+	while ((skb = skb_dequeue(&ch->collect_queue))) {
+		memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
+		p_header = (struct pdu *)
+			(skb_tail_pointer(ch->trans_skb) - skb->len);
+		p_header->pdu_flag = 0x00;
+		if (skb->protocol == ntohs(ETH_P_SNAP))
+			p_header->pdu_flag |= 0x60;
+		else
+			p_header->pdu_flag |= 0x20;
+
+		if (do_debug_data) {
+			ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
+				       __FUNCTION__, ch->trans_skb->len);
+			ctcm_pr_debug("ctcmpc: %s() pdu header and data"
+				       " for up to 32 bytes sent to vtam\n",
+				       __FUNCTION__);
+			ctcmpc_dumpit((char *)p_header,
+						min_t(int, skb->len, 32));
+		}
+		ch->collect_len -= skb->len;
+		data_space -= skb->len;
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len;
+		atomic_dec(&skb->users);
+		dev_kfree_skb_any(skb);
+		peekskb = skb_peek(&ch->collect_queue);
+		if (peekskb->len > data_space)
+			break;
+		i++;
+	}
+	/* p_header points to the last one we handled */
+	if (p_header)
+		p_header->pdu_flag |= PDU_LAST;	/*Say it's the last one*/
+	header = kzalloc(TH_HEADER_LENGTH, gfp_type());
+
+	if (!header) {
+		printk(KERN_WARNING "ctcmpc: OUT OF MEMORY IN %s()"
+		       ": Data Lost \n", __FUNCTION__);
+		spin_unlock(&ch->collect_lock);
+		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+		goto done;
+	}
+
+	header->th_ch_flag = TH_HAS_PDU;  /* Normal data */
+	ch->th_seq_num++;
+	header->th_seq_num = ch->th_seq_num;
+
+	if (do_debug_data)
+		ctcm_pr_debug("%s: ToVTAM_th_seq= %08x\n" ,
+					__FUNCTION__, ch->th_seq_num);
+
+	memcpy(skb_push(ch->trans_skb, TH_HEADER_LENGTH), header,
+		TH_HEADER_LENGTH);	/* put the TH on the packet */
+
+	kfree(header);
+
+	if (do_debug_data) {
+		ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
+		       __FUNCTION__, ch->trans_skb->len);
+
+		ctcm_pr_debug("ctcmpc: %s() up-to-50 bytes of trans_skb "
+			"data to vtam from collect_q\n", __FUNCTION__);
+		ctcmpc_dumpit((char *)ch->trans_skb->data,
+				min_t(int, ch->trans_skb->len, 50));
+	}
+
+	spin_unlock(&ch->collect_lock);
+	clear_normalized_cda(&ch->ccw[1]);
+	if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
+		dev_kfree_skb_any(ch->trans_skb);
+		ch->trans_skb = NULL;
+		printk(KERN_WARNING
+		       "ctcmpc: %s()CCW failure - data lost\n",
+		       __FUNCTION__);
+		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+		return;
+	}
+	ch->ccw[1].count = ch->trans_skb->len;
+	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+	ch->prof.send_stamp = current_kernel_time(); /* xtime */
+	if (do_debug_ccw)
+		ctcmpc_dumpit((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);
+	rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+					(unsigned long)ch, 0xff, 0);
+	ch->prof.doios_multi++;
+	if (rc != 0) {
+		priv->stats.tx_dropped += i;
+		priv->stats.tx_errors += i;
+		fsm_deltimer(&ch->timer);
+		ctcm_ccw_check_rc(ch, rc, "chained TX");
+	}
+done:
+	ctcm_clear_busy(dev);
+	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
+	return;
+}
+
+/**
+ * Got normal data, check for sanity, queue it up, allocate new buffer
+ * trigger bottom half, and initiate next read.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
+{
+	struct channel		*ch = arg;
+	struct net_device	*dev = ch->netdev;
+	struct ctcm_priv	*priv = dev->priv;
+	struct mpc_group	*grp = priv->mpcg;
+	struct sk_buff		*skb = ch->trans_skb;
+	struct sk_buff		*new_skb;
+	unsigned long	saveflags = 0;	/* avoids compiler warning */
+	int len	= ch->max_bufsize - ch->irb->scsw.count;
+
+	if (do_debug_data) {
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx %s cp:%i %s\n",
+				dev->name, smp_processor_id(), ch->id);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx: maxbuf: %04x "
+				"len: %04x\n", ch->max_bufsize, len);
+	}
+	fsm_deltimer(&ch->timer);
+
+	if (skb == NULL) {
+		ctcm_pr_debug("ctcmpc exit:  %s() TRANS_SKB = NULL \n",
+			       __FUNCTION__);
+					goto again;
+	}
+
+	if (len < TH_HEADER_LENGTH) {
+		ctcm_pr_info("%s: got packet with invalid length %d\n",
+				dev->name, len);
+		priv->stats.rx_dropped++;
+		priv->stats.rx_length_errors++;
+	} else {
+		/* must have valid th header or game over */
+		__u32	block_len = len;
+		len = TH_HEADER_LENGTH + XID2_LENGTH + 4;
+		new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);
+
+		if (new_skb == NULL) {
+			printk(KERN_INFO "ctcmpc:%s() NEW_SKB = NULL\n",
+			       __FUNCTION__);
+			printk(KERN_WARNING "ctcmpc: %s() MEMORY ALLOC FAILED"
+			       " - DATA LOST - MPC FAILED\n",
+			       __FUNCTION__);
+			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+					goto again;
+		}
+		switch (fsm_getstate(grp->fsm)) {
+		case MPCG_STATE_RESET:
+		case MPCG_STATE_INOP:
+			dev_kfree_skb_any(new_skb);
+			break;
+		case MPCG_STATE_FLOWC:
+		case MPCG_STATE_READY:
+			memcpy(skb_put(new_skb, block_len),
+					       skb->data, block_len);
+			skb_queue_tail(&ch->io_queue, new_skb);
+			tasklet_schedule(&ch->ch_tasklet);
+			break;
+		default:
+			memcpy(skb_put(new_skb, len), skb->data, len);
+			skb_queue_tail(&ch->io_queue, new_skb);
+			tasklet_hi_schedule(&ch->ch_tasklet);
+			break;
+		}
+	}
+
+again:
+	switch (fsm_getstate(grp->fsm)) {
+	int rc, dolock;
+	case MPCG_STATE_FLOWC:
+	case MPCG_STATE_READY:
+		if (ctcm_checkalloc_buffer(ch))
+			break;
+		ch->trans_skb->data = ch->trans_skb_data;
+		skb_reset_tail_pointer(ch->trans_skb);
+		ch->trans_skb->len = 0;
+		ch->ccw[1].count = ch->max_bufsize;
+			if (do_debug_ccw)
+			ctcmpc_dumpit((char *)&ch->ccw[0],
+					sizeof(struct ccw1) * 3);
+		dolock = !in_irq();
+		if (dolock)
+			spin_lock_irqsave(
+				get_ccwdev_lock(ch->cdev), saveflags);
+		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+						(unsigned long)ch, 0xff, 0);
+		if (dolock) /* see remark about conditional locking */
+			spin_unlock_irqrestore(
+				get_ccwdev_lock(ch->cdev), saveflags);
+		if (rc != 0)
+			ctcm_ccw_check_rc(ch, rc, "normal RX");
+	default:
+		break;
+	}
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
+				dev->name, __FUNCTION__, ch, ch->id);
+
+}
+
+/**
+ * Initialize connection by sending a __u16 of value 0.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
+{
+	struct channel		*ch = arg;
+	struct net_device	*dev = ch->netdev;
+	struct ctcm_priv	*priv = dev->priv;
+
+	if (do_debug) {
+		struct mpc_group *gptr = priv->mpcg;
+		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
+				__FUNCTION__, ch, ch->id);
+		ctcm_pr_debug("%s() %s chstate:%i grpstate:%i chprotocol:%i\n",
+				__FUNCTION__, ch->id, fsm_getstate(fi),
+				fsm_getstate(gptr->fsm), ch->protocol);
+	}
+	if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
+		MPC_DBF_DEV_NAME(TRACE, dev, "remote side issued READ? ");
+
+	fsm_deltimer(&ch->timer);
+	if (ctcm_checkalloc_buffer(ch))
+				goto done;
+
+	switch (fsm_getstate(fi)) {
+	case CTC_STATE_STARTRETRY:
+	case CTC_STATE_SETUPWAIT:
+		if (CHANNEL_DIRECTION(ch->flags) == READ) {
+			ctcmpc_chx_rxidle(fi, event, arg);
+		} else {
+			fsm_newstate(fi, CTC_STATE_TXIDLE);
+			fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);
+		}
+				goto done;
+	default:
+		break;
+	};
+
+	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
+		     ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
+
+done:
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
+			__FUNCTION__, ch, ch->id);
+	return;
+}
+
+/**
+ * Got initial data, check it. If OK,
+ * notify device statemachine that we are up and
+ * running.
+ *
+ * fi		An instance of a channel statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from channel * upon call.
+ */
+void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
+{
+	struct channel *ch = arg;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv  *priv = dev->priv;
+	struct mpc_group  *grp = priv->mpcg;
+	int rc;
+	unsigned long saveflags = 0;	/* avoids compiler warning */
+
+	fsm_deltimer(&ch->timer);
+	ctcm_pr_debug("%s cp:%i enter:  %s()\n",
+		       dev->name, smp_processor_id(), __FUNCTION__);
+	if (do_debug)
+		ctcm_pr_debug("%s() %s chstate:%i grpstate:%i\n",
+			__FUNCTION__, ch->id,
+			fsm_getstate(fi), fsm_getstate(grp->fsm));
+
+	fsm_newstate(fi, CTC_STATE_RXIDLE);
+	/* XID processing complete */
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_FLOWC:
+	case MPCG_STATE_READY:
+		if (ctcm_checkalloc_buffer(ch))
+				goto done;
+		ch->trans_skb->data = ch->trans_skb_data;
+		skb_reset_tail_pointer(ch->trans_skb);
+		ch->trans_skb->len = 0;
+		ch->ccw[1].count = ch->max_bufsize;
+		if (do_debug_ccw)
+			ctcmpc_dumpit((char *)&ch->ccw[0],
+						sizeof(struct ccw1) * 3);
+		if (event == CTC_EVENT_START)
+			/* see remark about conditional locking */
+			spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+						(unsigned long)ch, 0xff, 0);
+		if (event == CTC_EVENT_START)
+			spin_unlock_irqrestore(
+					get_ccwdev_lock(ch->cdev), saveflags);
+		if (rc != 0) {
+			fsm_newstate(fi, CTC_STATE_RXINIT);
+			ctcm_ccw_check_rc(ch, rc, "initial RX");
+				goto done;
+		}
+		break;
+	default:
+		break;
+	}
+
+	fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
+done:
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit: %s  %s()\n",
+					dev->name, __FUNCTION__);
+	return;
+}
+
+/*
+ * ctcmpc channel FSM action
+ * called from several points in ctcmpc_ch_fsm
+ * ctcmpc only
+ */
+static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)
+{
+	struct channel	  *ch     = arg;
+	struct net_device *dev    = ch->netdev;
+	struct ctcm_priv  *priv   = dev->priv;
+	struct mpc_group  *grp = priv->mpcg;
+
+	if (do_debug) {
+		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s"
+				"GrpState:%s ChState:%s\n",
+				__FUNCTION__, smp_processor_id(), ch, ch->id,
+		fsm_getstate_str(grp->fsm),
+		fsm_getstate_str(ch->fsm));
+	}
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_XID2INITW:
+		/* ok..start yside xid exchanges */
+		if (!ch->in_mpcgroup)
+			break;
+		if (fsm_getstate(ch->fsm) ==  CH_XID0_PENDING) {
+			fsm_deltimer(&grp->timer);
+			fsm_addtimer(&grp->timer,
+				MPC_XID_TIMEOUT_VALUE,
+				MPCG_EVENT_TIMER, dev);
+			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
+
+		} else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)
+			/* attn rcvd before xid0 processed via bh */
+			fsm_newstate(ch->fsm, CH_XID7_PENDING1);
+		break;
+	case MPCG_STATE_XID2INITX:
+	case MPCG_STATE_XID0IOWAIT:
+	case MPCG_STATE_XID0IOWAIX:
+		/* attn rcvd before xid0 processed on ch
+		but mid-xid0 processing for group    */
+		if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)
+			fsm_newstate(ch->fsm, CH_XID7_PENDING1);
+		break;
+	case MPCG_STATE_XID7INITW:
+	case MPCG_STATE_XID7INITX:
+	case MPCG_STATE_XID7INITI:
+	case MPCG_STATE_XID7INITZ:
+		switch (fsm_getstate(ch->fsm)) {
+		case CH_XID7_PENDING:
+			fsm_newstate(ch->fsm, CH_XID7_PENDING1);
+			break;
+		case CH_XID7_PENDING2:
+			fsm_newstate(ch->fsm, CH_XID7_PENDING3);
+			break;
+		}
+		fsm_event(grp->fsm, MPCG_EVENT_XID7DONE, dev);
+		break;
+	}
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s(): cp=%i ch=0x%p id=%s\n",
+			__FUNCTION__, smp_processor_id(), ch, ch->id);
+	return;
+
+}
+
+/*
+ * ctcmpc channel FSM action
+ * called from one point in ctcmpc_ch_fsm
+ * ctcmpc only
+ */
+static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
+{
+	struct channel	  *ch     = arg;
+	struct net_device *dev    = ch->netdev;
+	struct ctcm_priv  *priv   = dev->priv;
+	struct mpc_group  *grp    = priv->mpcg;
+
+	ctcm_pr_debug("ctcmpc enter: %s  %s() %s  \nGrpState:%s ChState:%s\n",
+		       dev->name,
+		       __FUNCTION__, ch->id,
+		       fsm_getstate_str(grp->fsm),
+		       fsm_getstate_str(ch->fsm));
+
+	fsm_deltimer(&ch->timer);
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_XID0IOWAIT:
+		/* vtam wants to be primary.start yside xid exchanges*/
+		/* only receive one attn-busy at a time so must not  */
+		/* change state each time			     */
+		grp->changed_side = 1;
+		fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
+		break;
+	case MPCG_STATE_XID2INITW:
+		if (grp->changed_side == 1) {
+			grp->changed_side = 2;
+			break;
+		}
+		/* process began via call to establish_conn	 */
+		/* so must report failure instead of reverting	 */
+		/* back to ready-for-xid passive state		 */
+		if (grp->estconnfunc)
+				goto done;
+		/* this attnbusy is NOT the result of xside xid  */
+		/* collisions so yside must have been triggered  */
+		/* by an ATTN that was not intended to start XID */
+		/* processing. Revert back to ready-for-xid and  */
+		/* wait for ATTN interrupt to signal xid start	 */
+		if (fsm_getstate(ch->fsm) == CH_XID0_INPROGRESS) {
+			fsm_newstate(ch->fsm, CH_XID0_PENDING) ;
+			fsm_deltimer(&grp->timer);
+				goto done;
+		}
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+				goto done;
+	case MPCG_STATE_XID2INITX:
+		/* XID2 was received before ATTN Busy for second
+		   channel.Send yside xid for second channel.
+		*/
+		if (grp->changed_side == 1) {
+			grp->changed_side = 2;
+			break;
+		}
+	case MPCG_STATE_XID0IOWAIX:
+	case MPCG_STATE_XID7INITW:
+	case MPCG_STATE_XID7INITX:
+	case MPCG_STATE_XID7INITI:
+	case MPCG_STATE_XID7INITZ:
+	default:
+		/* multiple attn-busy indicates too out-of-sync      */
+		/* and they are certainly not being received as part */
+		/* of valid mpc group negotiations..		     */
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+				goto done;
+	}
+
+	if (grp->changed_side == 1) {
+		fsm_deltimer(&grp->timer);
+		fsm_addtimer(&grp->timer, MPC_XID_TIMEOUT_VALUE,
+			     MPCG_EVENT_TIMER, dev);
+	}
+	if (ch->in_mpcgroup)
+		fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
+	else
+		printk(KERN_WARNING "ctcmpc: %s() Not all channels have"
+			" been added to group\n", __FUNCTION__);
+
+done:
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s()%s ch=0x%p id=%s\n",
+				__FUNCTION__, dev->name, ch, ch->id);
+
+	return;
+
+}
+
+/*
+ * ctcmpc channel FSM action
+ * called from several points in ctcmpc_ch_fsm
+ * ctcmpc only
+ */
+static void ctcmpc_chx_resend(fsm_instance *fsm, int event, void *arg)
+{
+	struct channel	   *ch	   = arg;
+	struct net_device  *dev    = ch->netdev;
+	struct ctcm_priv   *priv   = dev->priv;
+	struct mpc_group   *grp    = priv->mpcg;
+
+	ctcm_pr_debug("ctcmpc enter: %s  %s() %s  \nGrpState:%s ChState:%s\n",
+		       dev->name, __FUNCTION__, ch->id,
+		       fsm_getstate_str(grp->fsm),
+		       fsm_getstate_str(ch->fsm));
+
+	fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
+
+	return;
+}
+
+/*
+ * ctcmpc channel FSM action
+ * called from several points in ctcmpc_ch_fsm
+ * ctcmpc only
+ */
+static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
+{
+	struct channel *ach = arg;
+	struct net_device *dev = ach->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp = priv->mpcg;
+	struct channel *wch = priv->channel[WRITE];
+	struct channel *rch = priv->channel[READ];
+	struct sk_buff *skb;
+	struct th_sweep *header;
+	int rc = 0;
+	unsigned long saveflags = 0;
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+			__FUNCTION__, smp_processor_id(), ach, ach->id);
+
+	if (grp->in_sweep == 0)
+				goto done;
+
+	if (do_debug_data) {
+		ctcm_pr_debug("ctcmpc: %s() 1: ToVTAM_th_seq= %08x\n" ,
+			       __FUNCTION__, wch->th_seq_num);
+		ctcm_pr_debug("ctcmpc: %s() 1: FromVTAM_th_seq= %08x\n" ,
+				__FUNCTION__, rch->th_seq_num);
+	}
+
+	if (fsm_getstate(wch->fsm) != CTC_STATE_TXIDLE) {
+		/* give the previous IO time to complete */
+		fsm_addtimer(&wch->sweep_timer,
+			200, CTC_EVENT_RSWEEP_TIMER, wch);
+				goto done;
+	}
+
+	skb = skb_dequeue(&wch->sweep_queue);
+	if (!skb)
+				goto done;
+
+	if (set_normalized_cda(&wch->ccw[4], skb->data)) {
+		grp->in_sweep = 0;
+		ctcm_clear_busy_do(dev);
+		dev_kfree_skb_any(skb);
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+				goto done;
+	} else {
+		atomic_inc(&skb->users);
+		skb_queue_tail(&wch->io_queue, skb);
+	}
+
+	/* send out the sweep */
+	wch->ccw[4].count = skb->len;
+
+	header = (struct th_sweep *)skb->data;
+	switch (header->th.th_ch_flag) {
+	case TH_SWEEP_REQ:
+		grp->sweep_req_pend_num--;
+		break;
+	case TH_SWEEP_RESP:
+		grp->sweep_rsp_pend_num--;
+		break;
+	}
+
+	header->sw.th_last_seq = wch->th_seq_num;
+
+	if (do_debug_ccw)
+		ctcmpc_dumpit((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
+
+	ctcm_pr_debug("ctcmpc: %s() sweep packet\n", __FUNCTION__);
+	ctcmpc_dumpit((char *)header, TH_SWEEP_LENGTH);
+
+	fsm_addtimer(&wch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, wch);
+	fsm_newstate(wch->fsm, CTC_STATE_TX);
+
+	spin_lock_irqsave(get_ccwdev_lock(wch->cdev), saveflags);
+	wch->prof.send_stamp = current_kernel_time(); /* xtime */
+	rc = ccw_device_start(wch->cdev, &wch->ccw[3],
+					(unsigned long) wch, 0xff, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(wch->cdev), saveflags);
+
+	if ((grp->sweep_req_pend_num == 0) &&
+	   (grp->sweep_rsp_pend_num == 0)) {
+		grp->in_sweep = 0;
+		rch->th_seq_num = 0x00;
+		wch->th_seq_num = 0x00;
+		ctcm_clear_busy_do(dev);
+	}
+
+	if (do_debug_data) {
+		ctcm_pr_debug("ctcmpc: %s()2: ToVTAM_th_seq= %08x\n" ,
+			       __FUNCTION__, wch->th_seq_num);
+		ctcm_pr_debug("ctcmpc: %s()2: FromVTAM_th_seq= %08x\n" ,
+			       __FUNCTION__, rch->th_seq_num);
+	}
+
+	if (rc != 0)
+		ctcm_ccw_check_rc(wch, rc, "send sweep");
+
+done:
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit:  %s() %s\n", __FUNCTION__, ach->id);
+	return;
+}
+
+
+/*
+ * The ctcmpc statemachine for a channel.
+ */
+
+const fsm_node ctcmpc_ch_fsm[] = {
+	{ CTC_STATE_STOPPED,	CTC_EVENT_STOP,		ctcm_action_nop  },
+	{ CTC_STATE_STOPPED,	CTC_EVENT_START,	ctcm_chx_start  },
+	{ CTC_STATE_STOPPED,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_STOPPED,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
+	{ CTC_STATE_STOPPED,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
+
+	{ CTC_STATE_NOTOP,	CTC_EVENT_STOP,		ctcm_chx_stop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_GOOD,	ctcm_chx_start  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_UC_RCRESET,	ctcm_chx_stop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_UC_RSRESET,	ctcm_chx_stop  },
+	{ CTC_STATE_NOTOP,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setuperr  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_STARTWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_STARTRETRY,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_FINSTAT,	ctcmpc_chx_firstio  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CTC_STATE_RXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rxidle  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxiniterr  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_rxiniterr  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_TIMER,	ctcm_chx_rxiniterr  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_ATTNBUSY,	ctcm_chx_rxinitfail  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_firstio  },
+	{ CTC_STATE_RXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+
+	{ CH_XID0_PENDING,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
+	{ CH_XID0_PENDING,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
+	{ CH_XID0_PENDING,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CH_XID0_PENDING,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CH_XID0_PENDING,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CH_XID0_PENDING,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CH_XID0_PENDING,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CH_XID0_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID0_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID0_PENDING,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
+
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_ATTNBUSY,	ctcmpc_chx_attnbusy  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
+	{ CH_XID0_INPROGRESS,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+
+	{ CH_XID7_PENDING,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
+	{ CH_XID7_PENDING,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CH_XID7_PENDING,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CH_XID7_PENDING,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CH_XID7_PENDING,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
+	{ CH_XID7_PENDING,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+
+	{ CH_XID7_PENDING1,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
+	{ CH_XID7_PENDING1,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+
+	{ CH_XID7_PENDING2,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
+	{ CH_XID7_PENDING2,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+
+	{ CH_XID7_PENDING3,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
+	{ CH_XID7_PENDING3,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+
+	{ CH_XID7_PENDING4,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
+	{ CH_XID7_PENDING4,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxdisc  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_RSRESET,	ctcm_chx_fail  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
+
+	{ CTC_STATE_TXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_FINSTAT,	ctcm_chx_txidle  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_txiniterr  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_txiniterr  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_TIMER,	ctcm_chx_txiniterr  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_TXINIT,	CTC_EVENT_RSWEEP_TIMER,	ctcmpc_chx_send_sweep },
+
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_FINSTAT,	ctcmpc_chx_firstio  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_chx_fail  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RSRESET,	ctcm_chx_fail  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_TXIDLE,	CTC_EVENT_RSWEEP_TIMER,	ctcmpc_chx_send_sweep },
+
+	{ CTC_STATE_TERM,	CTC_EVENT_STOP,		ctcm_action_nop  },
+	{ CTC_STATE_TERM,	CTC_EVENT_START,	ctcm_chx_restart  },
+	{ CTC_STATE_TERM,	CTC_EVENT_FINSTAT,	ctcm_chx_stopped  },
+	{ CTC_STATE_TERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
+	{ CTC_STATE_TERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
+	{ CTC_STATE_TERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_TERM,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+	{ CTC_STATE_TERM,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+
+	{ CTC_STATE_DTERM,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_START,	ctcm_chx_restart  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_DTERM,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+
+	{ CTC_STATE_TX,		CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TX,		CTC_EVENT_START,	ctcm_action_nop  },
+	{ CTC_STATE_TX,		CTC_EVENT_FINSTAT,	ctcmpc_chx_txdone  },
+	{ CTC_STATE_TX,		CTC_EVENT_UC_RCRESET,	ctcm_chx_fail  },
+	{ CTC_STATE_TX,		CTC_EVENT_UC_RSRESET,	ctcm_chx_fail  },
+	{ CTC_STATE_TX,		CTC_EVENT_TIMER,	ctcm_chx_txretry  },
+	{ CTC_STATE_TX,		CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_TX,		CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_TX,		CTC_EVENT_RSWEEP_TIMER,	ctcmpc_chx_send_sweep },
+	{ CTC_STATE_TX,		CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
+
+	{ CTC_STATE_RXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
+	{ CTC_STATE_TXERR,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
+	{ CTC_STATE_TXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+	{ CTC_STATE_RXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
+};
+
+int mpc_ch_fsm_len = ARRAY_SIZE(ctcmpc_ch_fsm);
+
+/*
+ * Actions for interface - statemachine.
+ */
+
+/**
+ * Startup channels by sending CTC_EVENT_START to each channel.
+ *
+ * fi		An instance of an interface statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from struct net_device * upon call.
+ */
+static void dev_action_start(fsm_instance *fi, int event, void *arg)
+{
+	struct net_device *dev = arg;
+	struct ctcm_priv *priv = dev->priv;
+	int direction;
+
+	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+
+	fsm_deltimer(&priv->restart_timer);
+	fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+	if (IS_MPC(priv))
+		priv->mpcg->channels_terminating = 0;
+	for (direction = READ; direction <= WRITE; direction++) {
+		struct channel *ch = priv->channel[direction];
+		fsm_event(ch->fsm, CTC_EVENT_START, ch);
+	}
+}
+
+/**
+ * Shutdown channels by sending CTC_EVENT_STOP to each channel.
+ *
+ * fi		An instance of an interface statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from struct net_device * upon call.
+ */
+static void dev_action_stop(fsm_instance *fi, int event, void *arg)
+{
+	int direction;
+	struct net_device *dev = arg;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+
+	fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+	for (direction = READ; direction <= WRITE; direction++) {
+		struct channel *ch = priv->channel[direction];
+		fsm_event(ch->fsm, CTC_EVENT_STOP, ch);
+		ch->th_seq_num = 0x00;
+	if (do_debug)
+		ctcm_pr_debug("ctcm: %s() CH_th_seq= %08x\n",
+				__FUNCTION__, ch->th_seq_num);
+	}
+	if (IS_MPC(priv))
+		fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
+}
+
+static void dev_action_restart(fsm_instance *fi, int event, void *arg)
+{
+	int restart_timer;
+	struct net_device *dev = arg;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCMY_DBF_DEV_NAME(TRACE, dev, "");
+
+	if (IS_MPC(priv)) {
+		ctcm_pr_info("ctcm: %s Restarting Device and "
+		       "MPC Group in 5 seconds\n",
+		       dev->name);
+		restart_timer = CTCM_TIME_1_SEC;
+	} else {
+		ctcm_pr_info("%s: Restarting\n", dev->name);
+		restart_timer = CTCM_TIME_5_SEC;
+	}
+
+	dev_action_stop(fi, event, arg);
+	fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
+	if (IS_MPC(priv))
+		fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
+
+	/* going back into start sequence too quickly can	  */
+	/* result in the other side becoming unreachable   due	  */
+	/* to sense reported when IO is aborted			  */
+	fsm_addtimer(&priv->restart_timer, restart_timer,
+			DEV_EVENT_START, dev);
+}
+
+/**
+ * Called from channel statemachine
+ * when a channel is up and running.
+ *
+ * fi		An instance of an interface statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from struct net_device * upon call.
+ */
+static void dev_action_chup(fsm_instance *fi, int event, void *arg)
+{
+	struct net_device *dev = arg;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+
+	switch (fsm_getstate(fi)) {
+	case DEV_STATE_STARTWAIT_RXTX:
+		if (event == DEV_EVENT_RXUP)
+			fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+		else
+			fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+		break;
+	case DEV_STATE_STARTWAIT_RX:
+		if (event == DEV_EVENT_RXUP) {
+			fsm_newstate(fi, DEV_STATE_RUNNING);
+			ctcm_pr_info("%s: connected with remote side\n",
+				    dev->name);
+			ctcm_clear_busy(dev);
+		}
+		break;
+	case DEV_STATE_STARTWAIT_TX:
+		if (event == DEV_EVENT_TXUP) {
+			fsm_newstate(fi, DEV_STATE_RUNNING);
+			ctcm_pr_info("%s: connected with remote side\n",
+				    dev->name);
+			ctcm_clear_busy(dev);
+		}
+		break;
+	case DEV_STATE_STOPWAIT_TX:
+		if (event == DEV_EVENT_RXUP)
+			fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+		break;
+	case DEV_STATE_STOPWAIT_RX:
+		if (event == DEV_EVENT_TXUP)
+			fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+		break;
+	}
+
+	if (IS_MPC(priv)) {
+		if (event == DEV_EVENT_RXUP)
+			mpc_channel_action(priv->channel[READ],
+				READ, MPC_CHANNEL_ADD);
+		else
+			mpc_channel_action(priv->channel[WRITE],
+				WRITE, MPC_CHANNEL_ADD);
+	}
+}
+
+/**
+ * Called from device statemachine
+ * when a channel has been shutdown.
+ *
+ * fi		An instance of an interface statemachine.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from struct net_device * upon call.
+ */
+static void dev_action_chdown(fsm_instance *fi, int event, void *arg)
+{
+
+	struct net_device *dev = arg;
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+
+	switch (fsm_getstate(fi)) {
+	case DEV_STATE_RUNNING:
+		if (event == DEV_EVENT_TXDOWN)
+			fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+		else
+			fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+		break;
+	case DEV_STATE_STARTWAIT_RX:
+		if (event == DEV_EVENT_TXDOWN)
+			fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+		break;
+	case DEV_STATE_STARTWAIT_TX:
+		if (event == DEV_EVENT_RXDOWN)
+			fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+		break;
+	case DEV_STATE_STOPWAIT_RXTX:
+		if (event == DEV_EVENT_TXDOWN)
+			fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
+		else
+			fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
+		break;
+	case DEV_STATE_STOPWAIT_RX:
+		if (event == DEV_EVENT_RXDOWN)
+			fsm_newstate(fi, DEV_STATE_STOPPED);
+		break;
+	case DEV_STATE_STOPWAIT_TX:
+		if (event == DEV_EVENT_TXDOWN)
+			fsm_newstate(fi, DEV_STATE_STOPPED);
+		break;
+	}
+	if (IS_MPC(priv)) {
+		if (event == DEV_EVENT_RXDOWN)
+			mpc_channel_action(priv->channel[READ],
+				READ, MPC_CHANNEL_REMOVE);
+		else
+			mpc_channel_action(priv->channel[WRITE],
+				WRITE, MPC_CHANNEL_REMOVE);
+	}
+}
+
+const fsm_node dev_fsm[] = {
+	{ DEV_STATE_STOPPED,        DEV_EVENT_START,   dev_action_start   },
+	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_START,   dev_action_start   },
+	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_TXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RESTART, dev_action_restart },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_START,   dev_action_start   },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXUP,    dev_action_chup    },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_TXUP,    dev_action_chup    },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RESTART, dev_action_restart },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_START,   dev_action_start   },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RXUP,    dev_action_chup    },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXUP,    dev_action_chup    },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RESTART, dev_action_restart },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP,    dev_action_stop    },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP,    dev_action_chup    },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP,    dev_action_chup    },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_STOP,    dev_action_stop    },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXUP,    dev_action_chup    },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_TXUP,    dev_action_chup    },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RESTART, dev_action_restart },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_STOP,    dev_action_stop    },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RXUP,    dev_action_chup    },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXUP,    dev_action_chup    },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RESTART, dev_action_restart },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_STOP,    dev_action_stop    },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_TXDOWN,  dev_action_chdown  },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_TXUP,    ctcm_action_nop    },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_RXUP,    ctcm_action_nop    },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_RESTART, dev_action_restart },
+};
+
+int dev_fsm_len = ARRAY_SIZE(dev_fsm);
+
+/* --- This is the END my friend --- */
+
diff --git a/drivers/s390/net/ctcm_fsms.h b/drivers/s390/net/ctcm_fsms.h
new file mode 100644
index 0000000..2326aba
--- /dev/null
+++ b/drivers/s390/net/ctcm_fsms.h
@@ -0,0 +1,359 @@
+/*
+ * drivers/s390/net/ctcm_fsms.h
+ *
+ * Copyright IBM Corp. 2001, 2007
+ * Authors: 	Fritz Elfert (felfert@millenux.com)
+ * 		Peter Tiedemann (ptiedem@de.ibm.com)
+ * 	MPC additions :
+ *		Belinda Thompson (belindat@us.ibm.com)
+ *		Andy Richter (richtera@us.ibm.com)
+ */
+#ifndef _CTCM_FSMS_H_
+#define _CTCM_FSMS_H_
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/bitops.h>
+
+#include <linux/signal.h>
+#include <linux/string.h>
+
+#include <linux/ip.h>
+#include <linux/if_arp.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/ctype.h>
+#include <net/dst.h>
+
+#include <linux/io.h>
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+#include <linux/uaccess.h>
+
+#include <asm/idals.h>
+
+#include "fsm.h"
+#include "cu3088.h"
+#include "ctcm_main.h"
+
+/*
+ * Definitions for the channel statemachine(s) for ctc and ctcmpc
+ *
+ * To allow better kerntyping, prefix-less definitions for channel states
+ * and channel events have been replaced :
+ * ch_event... -> ctc_ch_event...
+ * CH_EVENT... -> CTC_EVENT...
+ * ch_state... -> ctc_ch_state...
+ * CH_STATE... -> CTC_STATE...
+ */
+/*
+ * Events of the channel statemachine(s) for ctc and ctcmpc
+ */
+enum ctc_ch_events {
+	/*
+	 * Events, representing return code of
+	 * I/O operations (ccw_device_start, ccw_device_halt et al.)
+	 */
+	CTC_EVENT_IO_SUCCESS,
+	CTC_EVENT_IO_EBUSY,
+	CTC_EVENT_IO_ENODEV,
+	CTC_EVENT_IO_UNKNOWN,
+
+	CTC_EVENT_ATTNBUSY,
+	CTC_EVENT_ATTN,
+	CTC_EVENT_BUSY,
+	/*
+	 * Events, representing unit-check
+	 */
+	CTC_EVENT_UC_RCRESET,
+	CTC_EVENT_UC_RSRESET,
+	CTC_EVENT_UC_TXTIMEOUT,
+	CTC_EVENT_UC_TXPARITY,
+	CTC_EVENT_UC_HWFAIL,
+	CTC_EVENT_UC_RXPARITY,
+	CTC_EVENT_UC_ZERO,
+	CTC_EVENT_UC_UNKNOWN,
+	/*
+	 * Events, representing subchannel-check
+	 */
+	CTC_EVENT_SC_UNKNOWN,
+	/*
+	 * Events, representing machine checks
+	 */
+	CTC_EVENT_MC_FAIL,
+	CTC_EVENT_MC_GOOD,
+	/*
+	 * Event, representing normal IRQ
+	 */
+	CTC_EVENT_IRQ,
+	CTC_EVENT_FINSTAT,
+	/*
+	 * Event, representing timer expiry.
+	 */
+	CTC_EVENT_TIMER,
+	/*
+	 * Events, representing commands from upper levels.
+	 */
+	CTC_EVENT_START,
+	CTC_EVENT_STOP,
+	CTC_NR_EVENTS,
+	/*
+	 * additional MPC events
+	 */
+	CTC_EVENT_SEND_XID = CTC_NR_EVENTS,
+	CTC_EVENT_RSWEEP_TIMER,
+	/*
+	 * MUST be always the last element!!
+	 */
+	CTC_MPC_NR_EVENTS,
+};
+
+/*
+ * States of the channel statemachine(s) for ctc and ctcmpc.
+ */
+enum ctc_ch_states {
+	/*
+	 * Channel not assigned to any device,
+	 * initial state, direction invalid
+	 */
+	CTC_STATE_IDLE,
+	/*
+	 * Channel assigned but not operating
+	 */
+	CTC_STATE_STOPPED,
+	CTC_STATE_STARTWAIT,
+	CTC_STATE_STARTRETRY,
+	CTC_STATE_SETUPWAIT,
+	CTC_STATE_RXINIT,
+	CTC_STATE_TXINIT,
+	CTC_STATE_RX,
+	CTC_STATE_TX,
+	CTC_STATE_RXIDLE,
+	CTC_STATE_TXIDLE,
+	CTC_STATE_RXERR,
+	CTC_STATE_TXERR,
+	CTC_STATE_TERM,
+	CTC_STATE_DTERM,
+	CTC_STATE_NOTOP,
+	CTC_NR_STATES,     /* MUST be the last element of non-expanded states */
+	/*
+	 * additional MPC states
+	 */
+	CH_XID0_PENDING = CTC_NR_STATES,
+	CH_XID0_INPROGRESS,
+	CH_XID7_PENDING,
+	CH_XID7_PENDING1,
+	CH_XID7_PENDING2,
+	CH_XID7_PENDING3,
+	CH_XID7_PENDING4,
+	CTC_MPC_NR_STATES, /* MUST be the last element of expanded mpc states */
+};
+
+extern const char *ctc_ch_event_names[];
+
+extern const char *ctc_ch_state_names[];
+
+void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg);
+void ctcm_purge_skb_queue(struct sk_buff_head *q);
+void fsm_action_nop(fsm_instance *fi, int event, void *arg);
+
+/*
+ * ----- non-static actions for ctcm channel statemachine -----
+ *
+ */
+void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg);
+
+/*
+ * ----- FSM (state/event/action) of the ctcm channel statemachine -----
+ */
+extern const fsm_node ch_fsm[];
+extern int ch_fsm_len;
+
+
+/*
+ * ----- non-static actions for ctcmpc channel statemachine ----
+ *
+ */
+/* shared :
+void ctcm_chx_txidle(fsm_instance * fi, int event, void *arg);
+ */
+void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg);
+
+/*
+ * ----- FSM (state/event/action) of the ctcmpc channel statemachine -----
+ */
+extern const fsm_node ctcmpc_ch_fsm[];
+extern int mpc_ch_fsm_len;
+
+/*
+ * Definitions for the device interface statemachine for ctc and mpc
+ */
+
+/*
+ * States of the device interface statemachine.
+ */
+enum dev_states {
+	DEV_STATE_STOPPED,
+	DEV_STATE_STARTWAIT_RXTX,
+	DEV_STATE_STARTWAIT_RX,
+	DEV_STATE_STARTWAIT_TX,
+	DEV_STATE_STOPWAIT_RXTX,
+	DEV_STATE_STOPWAIT_RX,
+	DEV_STATE_STOPWAIT_TX,
+	DEV_STATE_RUNNING,
+	/*
+	 * MUST be always the last element!!
+	 */
+	CTCM_NR_DEV_STATES
+};
+
+extern const char *dev_state_names[];
+
+/*
+ * Events of the device interface statemachine.
+ * ctcm and ctcmpc
+ */
+enum dev_events {
+	DEV_EVENT_START,
+	DEV_EVENT_STOP,
+	DEV_EVENT_RXUP,
+	DEV_EVENT_TXUP,
+	DEV_EVENT_RXDOWN,
+	DEV_EVENT_TXDOWN,
+	DEV_EVENT_RESTART,
+	/*
+	 * MUST be always the last element!!
+	 */
+	CTCM_NR_DEV_EVENTS
+};
+
+extern const char *dev_event_names[];
+
+/*
+ * Actions for the device interface statemachine.
+ * ctc and ctcmpc
+ */
+/*
+static void dev_action_start(fsm_instance * fi, int event, void *arg);
+static void dev_action_stop(fsm_instance * fi, int event, void *arg);
+static void dev_action_restart(fsm_instance *fi, int event, void *arg);
+static void dev_action_chup(fsm_instance * fi, int event, void *arg);
+static void dev_action_chdown(fsm_instance * fi, int event, void *arg);
+*/
+
+/*
+ * The (state/event/action) fsm table of the device interface statemachine.
+ * ctcm and ctcmpc
+ */
+extern const fsm_node dev_fsm[];
+extern int dev_fsm_len;
+
+
+/*
+ * Definitions for the MPC Group statemachine
+ */
+
+/*
+ * MPC Group Station FSM States
+
+State Name		When In This State
+======================	=======================================
+MPCG_STATE_RESET	Initial State When Driver Loaded
+			We receive and send NOTHING
+
+MPCG_STATE_INOP         INOP Received.
+			Group level non-recoverable error
+
+MPCG_STATE_READY	XID exchanges for at least 1 write and
+			1 read channel have completed.
+			Group is ready for data transfer.
+
+States from ctc_mpc_alloc_channel
+==============================================================
+MPCG_STATE_XID2INITW	Awaiting XID2(0) Initiation
+			      ATTN from other side will start
+			      XID negotiations.
+			      Y-side protocol only.
+
+MPCG_STATE_XID2INITX	XID2(0) negotiations are in progress.
+			      At least 1, but not all, XID2(0)'s
+			      have been received from partner.
+
+MPCG_STATE_XID7INITW	XID2(0) complete
+			      No XID2(7)'s have yet been received.
+			      XID2(7) negotiations pending.
+
+MPCG_STATE_XID7INITX	XID2(7) negotiations in progress.
+			      At least 1, but not all, XID2(7)'s
+			      have been received from partner.
+
+MPCG_STATE_XID7INITF	XID2(7) negotiations complete.
+			      Transitioning to READY.
+
+MPCG_STATE_READY	      Ready for Data Transfer.
+
+
+States from ctc_mpc_establish_connectivity call
+==============================================================
+MPCG_STATE_XID0IOWAIT	Initiating XID2(0) negotiations.
+			      X-side protocol only.
+			      ATTN-BUSY from other side will convert
+			      this to Y-side protocol and the
+			      ctc_mpc_alloc_channel flow will begin.
+
+MPCG_STATE_XID0IOWAIX	XID2(0) negotiations are in progress.
+			      At least 1, but not all, XID2(0)'s
+			      have been received from partner.
+
+MPCG_STATE_XID7INITI	XID2(0) complete
+			      No XID2(7)'s have yet been received.
+			      XID2(7) negotiations pending.
+
+MPCG_STATE_XID7INITZ	XID2(7) negotiations in progress.
+			      At least 1, but not all, XID2(7)'s
+			      have been received from partner.
+
+MPCG_STATE_XID7INITF	XID2(7) negotiations complete.
+			      Transitioning to READY.
+
+MPCG_STATE_READY	      Ready for Data Transfer.
+
+*/
+
+enum mpcg_events {
+	MPCG_EVENT_INOP,
+	MPCG_EVENT_DISCONC,
+	MPCG_EVENT_XID0DO,
+	MPCG_EVENT_XID2,
+	MPCG_EVENT_XID2DONE,
+	MPCG_EVENT_XID7DONE,
+	MPCG_EVENT_TIMER,
+	MPCG_EVENT_DOIO,
+	MPCG_NR_EVENTS,
+};
+
+enum mpcg_states {
+	MPCG_STATE_RESET,
+	MPCG_STATE_INOP,
+	MPCG_STATE_XID2INITW,
+	MPCG_STATE_XID2INITX,
+	MPCG_STATE_XID7INITW,
+	MPCG_STATE_XID7INITX,
+	MPCG_STATE_XID0IOWAIT,
+	MPCG_STATE_XID0IOWAIX,
+	MPCG_STATE_XID7INITI,
+	MPCG_STATE_XID7INITZ,
+	MPCG_STATE_XID7INITF,
+	MPCG_STATE_FLOWC,
+	MPCG_STATE_READY,
+	MPCG_NR_STATES,
+};
+
+#endif
+/* --- This is the END my friend --- */
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
new file mode 100644
index 0000000..d52843d
--- /dev/null
+++ b/drivers/s390/net/ctcm_main.c
@@ -0,0 +1,1772 @@
+/*
+ * drivers/s390/net/ctcm_main.c
+ *
+ * Copyright IBM Corp. 2001, 2007
+ * Author(s):
+ *	Original CTC driver(s):
+ *		Fritz Elfert (felfert@millenux.com)
+ *		Dieter Wellerdiek (wel@de.ibm.com)
+ *		Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *		Denis Joseph Barrow (barrow_dj@yahoo.com)
+ *		Jochen Roehrig (roehrig@de.ibm.com)
+ *		Cornelia Huck <cornelia.huck@de.ibm.com>
+ *	MPC additions:
+ *		Belinda Thompson (belindat@us.ibm.com)
+ *		Andy Richter (richtera@us.ibm.com)
+ *	Revived by:
+ *		Peter Tiedemann (ptiedem@de.ibm.com)
+ */
+
+#undef DEBUG
+#undef DEBUGDATA
+#undef DEBUGCCW
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/bitops.h>
+
+#include <linux/signal.h>
+#include <linux/string.h>
+
+#include <linux/ip.h>
+#include <linux/if_arp.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/ctype.h>
+#include <net/dst.h>
+
+#include <linux/io.h>
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+#include <linux/uaccess.h>
+
+#include <asm/idals.h>
+
+#include "cu3088.h"
+#include "ctcm_fsms.h"
+#include "ctcm_main.h"
+
+/* Some common global variables */
+
+/*
+ * Linked list of all detected channels.
+ */
+struct channel *channels;
+
+/**
+ * Unpack a just received skb and hand it over to
+ * upper layers.
+ *
+ *  ch		The channel where this skb has been received.
+ *  pskb	The received skb.
+ */
+void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
+{
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	__u16 len = *((__u16 *) pskb->data);
+
+	skb_put(pskb, 2 + LL_HEADER_LENGTH);
+	skb_pull(pskb, 2);
+	pskb->dev = dev;
+	pskb->ip_summed = CHECKSUM_UNNECESSARY;
+	while (len > 0) {
+		struct sk_buff *skb;
+		int skblen;
+		struct ll_header *header = (struct ll_header *)pskb->data;
+
+		skb_pull(pskb, LL_HEADER_LENGTH);
+		if ((ch->protocol == CTCM_PROTO_S390) &&
+		    (header->type != ETH_P_IP)) {
+
+			if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
+				/*
+				 * Check packet type only if we stick strictly
+				 * to S/390's protocol of OS390. This only
+				 * supports IP. Otherwise allow any packet
+				 * type.
+				 */
+				ctcm_pr_warn("%s Illegal packet type 0x%04x "
+						"received, dropping\n",
+						dev->name, header->type);
+				ch->logflags |= LOG_FLAG_ILLEGALPKT;
+			}
+
+			priv->stats.rx_dropped++;
+			priv->stats.rx_frame_errors++;
+			return;
+		}
+		pskb->protocol = ntohs(header->type);
+		if (header->length <= LL_HEADER_LENGTH) {
+			if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
+				ctcm_pr_warn(
+					"%s Illegal packet size %d "
+					"received (MTU=%d blocklen=%d), "
+					"dropping\n", dev->name, header->length,
+					dev->mtu, len);
+				ch->logflags |= LOG_FLAG_ILLEGALSIZE;
+			}
+
+			priv->stats.rx_dropped++;
+			priv->stats.rx_length_errors++;
+			return;
+		}
+		header->length -= LL_HEADER_LENGTH;
+		len -= LL_HEADER_LENGTH;
+		if ((header->length > skb_tailroom(pskb)) ||
+			(header->length > len)) {
+			if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+				ctcm_pr_warn(
+					"%s Illegal packet size %d (beyond the"
+					" end of received data), dropping\n",
+					dev->name, header->length);
+				ch->logflags |= LOG_FLAG_OVERRUN;
+			}
+
+			priv->stats.rx_dropped++;
+			priv->stats.rx_length_errors++;
+			return;
+		}
+		skb_put(pskb, header->length);
+		skb_reset_mac_header(pskb);
+		len -= header->length;
+		skb = dev_alloc_skb(pskb->len);
+		if (!skb) {
+			if (!(ch->logflags & LOG_FLAG_NOMEM)) {
+				ctcm_pr_warn(
+					"%s Out of memory in ctcm_unpack_skb\n",
+					dev->name);
+				ch->logflags |= LOG_FLAG_NOMEM;
+			}
+			priv->stats.rx_dropped++;
+			return;
+		}
+		skb_copy_from_linear_data(pskb, skb_put(skb, pskb->len),
+					  pskb->len);
+		skb_reset_mac_header(skb);
+		skb->dev = pskb->dev;
+		skb->protocol = pskb->protocol;
+		pskb->ip_summed = CHECKSUM_UNNECESSARY;
+		skblen = skb->len;
+		/*
+		 * reset logflags
+		 */
+		ch->logflags = 0;
+		priv->stats.rx_packets++;
+		priv->stats.rx_bytes += skblen;
+		netif_rx_ni(skb);
+		dev->last_rx = jiffies;
+		if (len > 0) {
+			skb_pull(pskb, header->length);
+			if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
+				if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+					CTCM_DBF_DEV_NAME(TRACE, dev,
+						"Overrun in ctcm_unpack_skb");
+					ch->logflags |= LOG_FLAG_OVERRUN;
+				}
+				return;
+			}
+			skb_put(pskb, LL_HEADER_LENGTH);
+		}
+	}
+}
+
+/**
+ * Release a specific channel in the channel list.
+ *
+ *  ch		Pointer to channel struct to be released.
+ */
+static void channel_free(struct channel *ch)
+{
+	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+	ch->flags &= ~CHANNEL_FLAGS_INUSE;
+	fsm_newstate(ch->fsm, CTC_STATE_IDLE);
+}
+
+/**
+ * Remove a specific channel in the channel list.
+ *
+ *  ch		Pointer to channel struct to be released.
+ */
+static void channel_remove(struct channel *ch)
+{
+	struct channel **c = &channels;
+	char chid[CTCM_ID_SIZE+1];
+	int ok = 0;
+
+	if (ch == NULL)
+		return;
+	else
+		strncpy(chid, ch->id, CTCM_ID_SIZE);
+
+	channel_free(ch);
+	while (*c) {
+		if (*c == ch) {
+			*c = ch->next;
+			fsm_deltimer(&ch->timer);
+			if (IS_MPC(ch))
+				fsm_deltimer(&ch->sweep_timer);
+
+			kfree_fsm(ch->fsm);
+			clear_normalized_cda(&ch->ccw[4]);
+			if (ch->trans_skb != NULL) {
+				clear_normalized_cda(&ch->ccw[1]);
+				dev_kfree_skb_any(ch->trans_skb);
+			}
+			if (IS_MPC(ch)) {
+				tasklet_kill(&ch->ch_tasklet);
+				tasklet_kill(&ch->ch_disc_tasklet);
+				kfree(ch->discontact_th);
+			}
+			kfree(ch->ccw);
+			kfree(ch->irb);
+			kfree(ch);
+			ok = 1;
+			break;
+		}
+		c = &((*c)->next);
+	}
+
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s) %s", CTCM_FUNTAIL,
+			chid, ok ? "OK" : "failed");
+}
+
+/**
+ * Get a specific channel from the channel list.
+ *
+ *  type	Type of channel we are interested in.
+ *  id		Id of channel we are interested in.
+ *  direction	Direction we want to use this channel for.
+ *
+ * returns Pointer to a channel or NULL if no matching channel available.
+ */
+static struct channel *channel_get(enum channel_types type,
+					char *id, int direction)
+{
+	struct channel *ch = channels;
+
+	if (do_debug) {
+		char buf[64];
+		sprintf(buf, "%s(%d, %s, %d)\n",
+				CTCM_FUNTAIL, type, id, direction);
+		CTCM_DBF_TEXT(TRACE, CTC_DBF_INFO, buf);
+	}
+	while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type)))
+		ch = ch->next;
+	if (!ch) {
+		char buf[64];
+		sprintf(buf, "%s(%d, %s, %d) not found in channel list\n",
+				CTCM_FUNTAIL, type, id, direction);
+		CTCM_DBF_TEXT(ERROR, CTC_DBF_ERROR, buf);
+	} else {
+		if (ch->flags & CHANNEL_FLAGS_INUSE)
+			ch = NULL;
+		else {
+			ch->flags |= CHANNEL_FLAGS_INUSE;
+			ch->flags &= ~CHANNEL_FLAGS_RWMASK;
+			ch->flags |= (direction == WRITE)
+			    ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
+			fsm_newstate(ch->fsm, CTC_STATE_STOPPED);
+		}
+	}
+	return ch;
+}
+
+static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
+{
+	if (!IS_ERR(irb))
+		return 0;
+
+	CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n",
+			PTR_ERR(irb), cdev->dev.bus_id);
+
+	switch (PTR_ERR(irb)) {
+	case -EIO:
+		ctcm_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
+		break;
+	case -ETIMEDOUT:
+		ctcm_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
+		break;
+	default:
+		ctcm_pr_warn("unknown error %ld on device %s\n",
+				PTR_ERR(irb), cdev->dev.bus_id);
+	}
+	return PTR_ERR(irb);
+}
+
+
+/**
+ * Check sense of a unit check.
+ *
+ *  ch		The channel, the sense code belongs to.
+ *  sense	The sense code to inspect.
+ */
+static inline void ccw_unit_check(struct channel *ch, unsigned char sense)
+{
+	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
+	if (sense & SNS0_INTERVENTION_REQ) {
+		if (sense & 0x01) {
+			ctcm_pr_debug("%s: Interface disc. or Sel. reset "
+					"(remote)\n", ch->id);
+			fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch);
+		} else {
+			ctcm_pr_debug("%s: System reset (remote)\n", ch->id);
+			fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch);
+		}
+	} else if (sense & SNS0_EQUIPMENT_CHECK) {
+		if (sense & SNS0_BUS_OUT_CHECK) {
+			ctcm_pr_warn("%s: Hardware malfunction (remote)\n",
+				ch->id);
+			fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch);
+		} else {
+			ctcm_pr_warn("%s: Read-data parity error (remote)\n",
+				ch->id);
+			fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch);
+		}
+	} else if (sense & SNS0_BUS_OUT_CHECK) {
+		if (sense & 0x04) {
+			ctcm_pr_warn("%s: Data-streaming timeout)\n", ch->id);
+			fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
+		} else {
+			ctcm_pr_warn("%s: Data-transfer parity error\n",
+					ch->id);
+			fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
+		}
+	} else if (sense & SNS0_CMD_REJECT) {
+		ctcm_pr_warn("%s: Command reject\n", ch->id);
+	} else if (sense == 0) {
+		ctcm_pr_debug("%s: Unit check ZERO\n", ch->id);
+		fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch);
+	} else {
+		ctcm_pr_warn("%s: Unit Check with sense code: %02x\n",
+			    ch->id, sense);
+		fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch);
+	}
+}
+
+int ctcm_ch_alloc_buffer(struct channel *ch)
+{
+	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
+
+	clear_normalized_cda(&ch->ccw[1]);
+	ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA);
+	if (ch->trans_skb == NULL) {
+		ctcm_pr_warn("%s: Couldn't alloc %s trans_skb\n",
+			ch->id,
+			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+		return -ENOMEM;
+	}
+
+	ch->ccw[1].count = ch->max_bufsize;
+	if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
+		dev_kfree_skb(ch->trans_skb);
+		ch->trans_skb = NULL;
+		ctcm_pr_warn("%s: set_normalized_cda for %s "
+			"trans_skb failed, dropping packets\n",
+			ch->id,
+			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+		return -ENOMEM;
+	}
+
+	ch->ccw[1].count = 0;
+	ch->trans_skb_data = ch->trans_skb->data;
+	ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
+	return 0;
+}
+
+/*
+ * Interface API for upper network layers
+ */
+
+/**
+ * Open an interface.
+ * Called from generic network layer when ifconfig up is run.
+ *
+ *  dev		Pointer to interface struct.
+ *
+ * returns 0 on success, -ERRNO on failure. (Never fails.)
+ */
+int ctcm_open(struct net_device *dev)
+{
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+	if (!IS_MPC(priv))
+		fsm_event(priv->fsm,	DEV_EVENT_START, dev);
+	return 0;
+}
+
+/**
+ * Close an interface.
+ * Called from generic network layer when ifconfig down is run.
+ *
+ *  dev		Pointer to interface struct.
+ *
+ * returns 0 on success, -ERRNO on failure. (Never fails.)
+ */
+int ctcm_close(struct net_device *dev)
+{
+	struct ctcm_priv *priv = dev->priv;
+
+	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+	if (!IS_MPC(priv))
+		fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
+	return 0;
+}
+
+
+/**
+ * Transmit a packet.
+ * This is a helper function for ctcm_tx().
+ *
+ *  ch		Channel to be used for sending.
+ *  skb		Pointer to struct sk_buff of packet to send.
+ *            The linklevel header has already been set up
+ *            by ctcm_tx().
+ *
+ * returns 0 on success, -ERRNO on failure. (Never fails.)
+ */
+static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
+{
+	unsigned long saveflags;
+	struct ll_header header;
+	int rc = 0;
+	__u16 block_len;
+	int ccw_idx;
+	struct sk_buff *nskb;
+	unsigned long hi;
+
+	/* we need to acquire the lock for testing the state
+	 * otherwise we can have an IRQ changing the state to
+	 * TXIDLE after the test but before acquiring the lock.
+	 */
+	spin_lock_irqsave(&ch->collect_lock, saveflags);
+	if (fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) {
+		int l = skb->len + LL_HEADER_LENGTH;
+
+		if (ch->collect_len + l > ch->max_bufsize - 2) {
+			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+			return -EBUSY;
+		} else {
+			atomic_inc(&skb->users);
+			header.length = l;
+			header.type = skb->protocol;
+			header.unused = 0;
+			memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
+			       LL_HEADER_LENGTH);
+			skb_queue_tail(&ch->collect_queue, skb);
+			ch->collect_len += l;
+		}
+		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+				goto done;
+	}
+	spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+	/*
+	 * Protect skb against beeing free'd by upper
+	 * layers.
+	 */
+	atomic_inc(&skb->users);
+	ch->prof.txlen += skb->len;
+	header.length = skb->len + LL_HEADER_LENGTH;
+	header.type = skb->protocol;
+	header.unused = 0;
+	memcpy(skb_push(skb, LL_HEADER_LENGTH), &header, LL_HEADER_LENGTH);
+	block_len = skb->len + 2;
+	*((__u16 *)skb_push(skb, 2)) = block_len;
+
+	/*
+	 * IDAL support in CTCM is broken, so we have to
+	 * care about skb's above 2G ourselves.
+	 */
+	hi = ((unsigned long)skb_tail_pointer(skb) + LL_HEADER_LENGTH) >> 31;
+	if (hi) {
+		nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
+		if (!nskb) {
+			atomic_dec(&skb->users);
+			skb_pull(skb, LL_HEADER_LENGTH + 2);
+			ctcm_clear_busy(ch->netdev);
+			return -ENOMEM;
+		} else {
+			memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
+			atomic_inc(&nskb->users);
+			atomic_dec(&skb->users);
+			dev_kfree_skb_irq(skb);
+			skb = nskb;
+		}
+	}
+
+	ch->ccw[4].count = block_len;
+	if (set_normalized_cda(&ch->ccw[4], skb->data)) {
+		/*
+		 * idal allocation failed, try via copying to
+		 * trans_skb. trans_skb usually has a pre-allocated
+		 * idal.
+		 */
+		if (ctcm_checkalloc_buffer(ch)) {
+			/*
+			 * Remove our header. It gets added
+			 * again on retransmit.
+			 */
+			atomic_dec(&skb->users);
+			skb_pull(skb, LL_HEADER_LENGTH + 2);
+			ctcm_clear_busy(ch->netdev);
+			return -EBUSY;
+		}
+
+		skb_reset_tail_pointer(ch->trans_skb);
+		ch->trans_skb->len = 0;
+		ch->ccw[1].count = skb->len;
+		skb_copy_from_linear_data(skb,
+				skb_put(ch->trans_skb, skb->len), skb->len);
+		atomic_dec(&skb->users);
+		dev_kfree_skb_irq(skb);
+		ccw_idx = 0;
+	} else {
+		skb_queue_tail(&ch->io_queue, skb);
+		ccw_idx = 3;
+	}
+	ch->retry = 0;
+	fsm_newstate(ch->fsm, CTC_STATE_TX);
+	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+	ch->prof.send_stamp = current_kernel_time(); /* xtime */
+	rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
+					(unsigned long)ch, 0xff, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+	if (ccw_idx == 3)
+		ch->prof.doios_single++;
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		ctcm_ccw_check_rc(ch, rc, "single skb TX");
+		if (ccw_idx == 3)
+			skb_dequeue_tail(&ch->io_queue);
+		/*
+		 * Remove our header. It gets added
+		 * again on retransmit.
+		 */
+		skb_pull(skb, LL_HEADER_LENGTH + 2);
+	} else if (ccw_idx == 0) {
+		struct net_device *dev = ch->netdev;
+		struct ctcm_priv *priv = dev->priv;
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+	}
+done:
+	ctcm_clear_busy(ch->netdev);
+	return rc;
+}
+
+static void ctcmpc_send_sweep_req(struct channel *rch)
+{
+	struct net_device *dev = rch->netdev;
+	struct ctcm_priv *priv;
+	struct mpc_group *grp;
+	struct th_sweep *header;
+	struct sk_buff *sweep_skb;
+	struct channel *ch;
+	int rc = 0;
+
+	priv = dev->priv;
+	grp = priv->mpcg;
+	ch = priv->channel[WRITE];
+
+	if (do_debug)
+		MPC_DBF_DEV_NAME(TRACE, dev, ch->id);
+
+	/* sweep processing is not complete until response and request */
+	/* has completed for all read channels in group		       */
+	if (grp->in_sweep == 0) {
+		grp->in_sweep = 1;
+		grp->sweep_rsp_pend_num = grp->active_channels[READ];
+		grp->sweep_req_pend_num = grp->active_channels[READ];
+	}
+
+	sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
+
+	if (sweep_skb == NULL)	{
+		printk(KERN_INFO "Couldn't alloc sweep_skb\n");
+		rc = -ENOMEM;
+					goto done;
+	}
+
+	header = kmalloc(TH_SWEEP_LENGTH, gfp_type());
+
+	if (!header) {
+		dev_kfree_skb_any(sweep_skb);
+		rc = -ENOMEM;
+					goto done;
+	}
+
+	header->th.th_seg	= 0x00 ;
+	header->th.th_ch_flag	= TH_SWEEP_REQ;  /* 0x0f */
+	header->th.th_blk_flag	= 0x00;
+	header->th.th_is_xid	= 0x00;
+	header->th.th_seq_num	= 0x00;
+	header->sw.th_last_seq	= ch->th_seq_num;
+
+	memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
+
+	kfree(header);
+
+	dev->trans_start = jiffies;
+	skb_queue_tail(&ch->sweep_queue, sweep_skb);
+
+	fsm_addtimer(&ch->sweep_timer, 100, CTC_EVENT_RSWEEP_TIMER, ch);
+
+	return;
+
+done:
+	if (rc != 0) {
+		grp->in_sweep = 0;
+		ctcm_clear_busy(dev);
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+	}
+
+	return;
+}
+
+/*
+ * MPC mode version of transmit_skb
+ */
+static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
+{
+	struct pdu *p_header;
+	struct net_device *dev = ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp = priv->mpcg;
+	struct th_header *header;
+	struct sk_buff *nskb;
+	int rc = 0;
+	int ccw_idx;
+	unsigned long hi;
+	unsigned long saveflags = 0;	/* avoids compiler warning */
+	__u16 block_len;
+
+	if (do_debug)
+		ctcm_pr_debug(
+			"ctcm enter: %s(): %s cp=%i ch=0x%p id=%s state=%s\n",
+			__FUNCTION__, dev->name, smp_processor_id(), ch,
+			ch->id, fsm_getstate_str(ch->fsm));
+
+	if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
+		spin_lock_irqsave(&ch->collect_lock, saveflags);
+		atomic_inc(&skb->users);
+		p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
+
+		if (!p_header) {
+			printk(KERN_WARNING "ctcm: OUT OF MEMORY IN %s():"
+			       " Data Lost \n", __FUNCTION__);
+
+			atomic_dec(&skb->users);
+			dev_kfree_skb_any(skb);
+			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+					goto done;
+		}
+
+		p_header->pdu_offset = skb->len;
+		p_header->pdu_proto = 0x01;
+		p_header->pdu_flag = 0x00;
+		if (skb->protocol == ntohs(ETH_P_SNAP)) {
+			p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
+		} else {
+			p_header->pdu_flag |= PDU_FIRST;
+		}
+		p_header->pdu_seq = 0;
+		memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header,
+		       PDU_HEADER_LENGTH);
+
+		if (do_debug_data) {
+			ctcm_pr_debug("ctcm: %s() Putting on collect_q"
+			       " - skb len: %04x \n", __FUNCTION__, skb->len);
+			ctcm_pr_debug("ctcm: %s() pdu header and data"
+			       " for up to 32 bytes\n", __FUNCTION__);
+			ctcmpc_dump32((char *)skb->data, skb->len);
+		}
+
+		skb_queue_tail(&ch->collect_queue, skb);
+		ch->collect_len += skb->len;
+		kfree(p_header);
+
+		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+			goto done;
+	}
+
+	/*
+	 * Protect skb against beeing free'd by upper
+	 * layers.
+	 */
+	atomic_inc(&skb->users);
+
+	block_len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+	/*
+	 * IDAL support in CTCM is broken, so we have to
+	 * care about skb's above 2G ourselves.
+	 */
+	hi = ((unsigned long)skb->tail + TH_HEADER_LENGTH) >> 31;
+	if (hi) {
+		nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
+		if (!nskb) {
+			printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
+				"-  Data Lost \n", __FUNCTION__);
+			atomic_dec(&skb->users);
+			dev_kfree_skb_any(skb);
+			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+				goto done;
+		} else {
+			memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
+			atomic_inc(&nskb->users);
+			atomic_dec(&skb->users);
+			dev_kfree_skb_irq(skb);
+			skb = nskb;
+		}
+	}
+
+	p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
+
+	if (!p_header) {
+		printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
+		       ": Data Lost \n", __FUNCTION__);
+
+		atomic_dec(&skb->users);
+		dev_kfree_skb_any(skb);
+		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+				goto done;
+	}
+
+	p_header->pdu_offset = skb->len;
+	p_header->pdu_proto = 0x01;
+	p_header->pdu_flag = 0x00;
+	p_header->pdu_seq = 0;
+	if (skb->protocol == ntohs(ETH_P_SNAP)) {
+		p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
+	} else {
+		p_header->pdu_flag |= PDU_FIRST;
+	}
+	memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, PDU_HEADER_LENGTH);
+
+	kfree(p_header);
+
+	if (ch->collect_len > 0) {
+		spin_lock_irqsave(&ch->collect_lock, saveflags);
+		skb_queue_tail(&ch->collect_queue, skb);
+		ch->collect_len += skb->len;
+		skb = skb_dequeue(&ch->collect_queue);
+		ch->collect_len -= skb->len;
+		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+	}
+
+	p_header = (struct pdu *)skb->data;
+	p_header->pdu_flag |= PDU_LAST;
+
+	ch->prof.txlen += skb->len - PDU_HEADER_LENGTH;
+
+	header = kmalloc(TH_HEADER_LENGTH, gfp_type());
+
+	if (!header) {
+		printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY: Data Lost \n",
+				__FUNCTION__);
+		atomic_dec(&skb->users);
+		dev_kfree_skb_any(skb);
+		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+				goto done;
+	}
+
+	header->th_seg = 0x00;
+	header->th_ch_flag = TH_HAS_PDU;  /* Normal data */
+	header->th_blk_flag = 0x00;
+	header->th_is_xid = 0x00;          /* Just data here */
+	ch->th_seq_num++;
+	header->th_seq_num = ch->th_seq_num;
+
+	if (do_debug_data)
+		ctcm_pr_debug("ctcm: %s() ToVTAM_th_seq= %08x\n" ,
+		       __FUNCTION__, ch->th_seq_num);
+
+	/* put the TH on the packet */
+	memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH);
+
+	kfree(header);
+
+	if (do_debug_data) {
+		ctcm_pr_debug("ctcm: %s(): skb len: %04x \n",
+				__FUNCTION__, skb->len);
+		ctcm_pr_debug("ctcm: %s(): pdu header and data for up to 32 "
+				"bytes sent to vtam\n", __FUNCTION__);
+		ctcmpc_dump32((char *)skb->data, skb->len);
+	}
+
+	ch->ccw[4].count = skb->len;
+	if (set_normalized_cda(&ch->ccw[4], skb->data)) {
+		/*
+		 * idal allocation failed, try via copying to
+		 * trans_skb. trans_skb usually has a pre-allocated
+		 * idal.
+		 */
+		if (ctcm_checkalloc_buffer(ch)) {
+			/*
+			 * Remove our header. It gets added
+			 * again on retransmit.
+			 */
+			atomic_dec(&skb->users);
+			dev_kfree_skb_any(skb);
+			printk(KERN_WARNING "ctcm: %s()OUT OF MEMORY:"
+					" Data Lost \n", __FUNCTION__);
+			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
+				goto done;
+		}
+
+		skb_reset_tail_pointer(ch->trans_skb);
+		ch->trans_skb->len = 0;
+		ch->ccw[1].count = skb->len;
+		memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
+		atomic_dec(&skb->users);
+		dev_kfree_skb_irq(skb);
+		ccw_idx = 0;
+		if (do_debug_data) {
+			ctcm_pr_debug("ctcm: %s() TRANS skb len: %d \n",
+			       __FUNCTION__, ch->trans_skb->len);
+			ctcm_pr_debug("ctcm: %s up to 32 bytes of data"
+				" sent to vtam\n", __FUNCTION__);
+			ctcmpc_dump32((char *)ch->trans_skb->data,
+					ch->trans_skb->len);
+		}
+	} else {
+		skb_queue_tail(&ch->io_queue, skb);
+		ccw_idx = 3;
+	}
+	ch->retry = 0;
+	fsm_newstate(ch->fsm, CTC_STATE_TX);
+	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
+
+	if (do_debug_ccw)
+		ctcmpc_dumpit((char *)&ch->ccw[ccw_idx],
+					sizeof(struct ccw1) * 3);
+
+	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+	ch->prof.send_stamp = current_kernel_time(); /* xtime */
+	rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
+					(unsigned long)ch, 0xff, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+	if (ccw_idx == 3)
+		ch->prof.doios_single++;
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		ctcm_ccw_check_rc(ch, rc, "single skb TX");
+		if (ccw_idx == 3)
+			skb_dequeue_tail(&ch->io_queue);
+	} else if (ccw_idx == 0) {
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
+	}
+	if (ch->th_seq_num > 0xf0000000)	/* Chose 4Billion at random. */
+		ctcmpc_send_sweep_req(ch);
+
+done:
+	if (do_debug)
+		ctcm_pr_debug("ctcm exit: %s  %s()\n", dev->name, __FUNCTION__);
+	return 0;
+}
+
+/**
+ * Start transmission of a packet.
+ * Called from generic network device layer.
+ *
+ *  skb		Pointer to buffer containing the packet.
+ *  dev		Pointer to interface struct.
+ *
+ * returns 0 if packet consumed, !0 if packet rejected.
+ *         Note: If we return !0, then the packet is free'd by
+ *               the generic network layer.
+ */
+/* first merge version - leaving both functions separated */
+static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	int rc = 0;
+	struct ctcm_priv *priv;
+
+	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
+	priv = dev->priv;
+
+	if (skb == NULL) {
+		ctcm_pr_warn("%s: NULL sk_buff passed\n", dev->name);
+		priv->stats.tx_dropped++;
+		return 0;
+	}
+	if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
+		ctcm_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
+			    dev->name, LL_HEADER_LENGTH + 2);
+		dev_kfree_skb(skb);
+		priv->stats.tx_dropped++;
+		return 0;
+	}
+
+	/*
+	 * If channels are not running, try to restart them
+	 * and throw away packet.
+	 */
+	if (fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) {
+		fsm_event(priv->fsm, DEV_EVENT_START, dev);
+		dev_kfree_skb(skb);
+		priv->stats.tx_dropped++;
+		priv->stats.tx_errors++;
+		priv->stats.tx_carrier_errors++;
+		return 0;
+	}
+
+	if (ctcm_test_and_set_busy(dev))
+		return -EBUSY;
+
+	dev->trans_start = jiffies;
+	if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
+		rc = 1;
+	return rc;
+}
+
+/* unmerged MPC variant of ctcm_tx */
+static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	int len = 0;
+	struct ctcm_priv *priv = NULL;
+	struct mpc_group *grp  = NULL;
+	struct sk_buff *newskb = NULL;
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): skb:%0lx\n",
+			__FUNCTION__, (unsigned long)skb);
+
+	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+			"ctcmpc enter: %s(): skb:%0lx\n",
+			__FUNCTION__, (unsigned long)skb);
+
+	priv = dev->priv;
+	grp  = priv->mpcg;
+	/*
+	 * Some sanity checks ...
+	 */
+	if (skb == NULL) {
+		ctcm_pr_warn("ctcmpc: %s: NULL sk_buff passed\n", dev->name);
+		priv->stats.tx_dropped++;
+					goto done;
+	}
+	if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) {
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_WARN,
+			"%s: Got sk_buff with head room < %ld bytes\n",
+			dev->name, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
+
+		if (do_debug_data)
+			ctcmpc_dump32((char *)skb->data, skb->len);
+
+		len =  skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+		newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA);
+
+		if (!newskb) {
+			printk(KERN_WARNING "ctcmpc: %s() OUT OF MEMORY-"
+			       "Data Lost\n",
+			       __FUNCTION__);
+
+			dev_kfree_skb_any(skb);
+			priv->stats.tx_dropped++;
+			priv->stats.tx_errors++;
+			priv->stats.tx_carrier_errors++;
+			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+					goto done;
+		}
+		newskb->protocol = skb->protocol;
+		skb_reserve(newskb, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
+		memcpy(skb_put(newskb, skb->len), skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = newskb;
+	}
+
+	/*
+	 * If channels are not running,
+	 * notify anybody about a link failure and throw
+	 * away packet.
+	 */
+	if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) ||
+	   (fsm_getstate(grp->fsm) <  MPCG_STATE_XID2INITW)) {
+		dev_kfree_skb_any(skb);
+		printk(KERN_INFO "ctcmpc: %s() DATA RCVD - MPC GROUP "
+		       "NOT ACTIVE - DROPPED\n",
+		       __FUNCTION__);
+		priv->stats.tx_dropped++;
+		priv->stats.tx_errors++;
+		priv->stats.tx_carrier_errors++;
+					goto done;
+	}
+
+	if (ctcm_test_and_set_busy(dev)) {
+		printk(KERN_WARNING "%s:DEVICE ERR - UNRECOVERABLE DATA LOSS\n",
+		       __FUNCTION__);
+		dev_kfree_skb_any(skb);
+		priv->stats.tx_dropped++;
+		priv->stats.tx_errors++;
+		priv->stats.tx_carrier_errors++;
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+					goto done;
+	}
+
+	dev->trans_start = jiffies;
+	if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) {
+		printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
+		       ": Data Lost \n",
+		       __FUNCTION__);
+		printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
+		       " - UNRECOVERABLE DATA LOSS\n",
+		       __FUNCTION__);
+		dev_kfree_skb_any(skb);
+		priv->stats.tx_dropped++;
+		priv->stats.tx_errors++;
+		priv->stats.tx_carrier_errors++;
+		ctcm_clear_busy(dev);
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+					goto done;
+	}
+	ctcm_clear_busy(dev);
+done:
+	if (do_debug)
+		MPC_DBF_DEV_NAME(TRACE, dev, "exit");
+
+	return 0;	/* handle freeing of skb here */
+}
+
+
+/**
+ * Sets MTU of an interface.
+ *
+ *  dev		Pointer to interface struct.
+ *  new_mtu	The new MTU to use for this interface.
+ *
+ * returns 0 on success, -EINVAL if MTU is out of valid range.
+ *         (valid range is 576 .. 65527). If VM is on the
+ *         remote side, maximum MTU is 32760, however this is
+ *         not checked here.
+ */
+static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct ctcm_priv *priv;
+	int max_bufsize;
+
+	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
+
+	if (new_mtu < 576 || new_mtu > 65527)
+		return -EINVAL;
+
+	priv = dev->priv;
+	max_bufsize = priv->channel[READ]->max_bufsize;
+
+	if (IS_MPC(priv)) {
+		if (new_mtu > max_bufsize - TH_HEADER_LENGTH)
+			return -EINVAL;
+		dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+	} else {
+		if (new_mtu > max_bufsize - LL_HEADER_LENGTH - 2)
+			return -EINVAL;
+		dev->hard_header_len = LL_HEADER_LENGTH + 2;
+	}
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+/**
+ * Returns interface statistics of a device.
+ *
+ *  dev		Pointer to interface struct.
+ *
+ * returns Pointer to stats struct of this interface.
+ */
+static struct net_device_stats *ctcm_stats(struct net_device *dev)
+{
+	return &((struct ctcm_priv *)dev->priv)->stats;
+}
+
+
+static void ctcm_netdev_unregister(struct net_device *dev)
+{
+	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
+	if (!dev)
+		return;
+	unregister_netdev(dev);
+}
+
+static int ctcm_netdev_register(struct net_device *dev)
+{
+	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
+	return register_netdev(dev);
+}
+
+static void ctcm_free_netdevice(struct net_device *dev)
+{
+	struct ctcm_priv *priv;
+	struct mpc_group *grp;
+
+	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
+
+	if (!dev)
+		return;
+	priv = dev->priv;
+	if (priv) {
+		grp = priv->mpcg;
+		if (grp) {
+			if (grp->fsm)
+				kfree_fsm(grp->fsm);
+			if (grp->xid_skb)
+				dev_kfree_skb(grp->xid_skb);
+			if (grp->rcvd_xid_skb)
+				dev_kfree_skb(grp->rcvd_xid_skb);
+			tasklet_kill(&grp->mpc_tasklet2);
+			kfree(grp);
+			priv->mpcg = NULL;
+		}
+		if (priv->fsm) {
+			kfree_fsm(priv->fsm);
+			priv->fsm = NULL;
+		}
+		kfree(priv->xid);
+		priv->xid = NULL;
+	/*
+	 * Note: kfree(priv); is done in "opposite" function of
+	 * allocator function probe_device which is remove_device.
+	 */
+	}
+#ifdef MODULE
+	free_netdev(dev);
+#endif
+}
+
+struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
+
+void static ctcm_dev_setup(struct net_device *dev)
+{
+	dev->open = ctcm_open;
+	dev->stop = ctcm_close;
+	dev->get_stats = ctcm_stats;
+	dev->change_mtu = ctcm_change_mtu;
+	dev->type = ARPHRD_SLIP;
+	dev->tx_queue_len = 100;
+	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+}
+
+/*
+ * Initialize everything of the net device except the name and the
+ * channel structs.
+ */
+static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
+{
+	struct net_device *dev;
+	struct mpc_group *grp;
+	if (!priv)
+		return NULL;
+
+	if (IS_MPC(priv))
+		dev = alloc_netdev(0, MPC_DEVICE_GENE, ctcm_dev_setup);
+	else
+		dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
+
+	if (!dev) {
+		ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+		return NULL;
+	}
+	dev->priv = priv;
+	priv->fsm = init_fsm("ctcmdev", dev_state_names, dev_event_names,
+				CTCM_NR_DEV_STATES, CTCM_NR_DEV_EVENTS,
+				dev_fsm, dev_fsm_len, GFP_KERNEL);
+	if (priv->fsm == NULL) {
+		CTCMY_DBF_DEV(SETUP, dev, "init_fsm error");
+		kfree(dev);
+		return NULL;
+	}
+	fsm_newstate(priv->fsm, DEV_STATE_STOPPED);
+	fsm_settimer(priv->fsm, &priv->restart_timer);
+
+	if (IS_MPC(priv)) {
+		/*  MPC Group Initializations  */
+		grp = ctcmpc_init_mpc_group(priv);
+		if (grp == NULL) {
+			MPC_DBF_DEV(SETUP, dev, "init_mpc_group error");
+			kfree(dev);
+			return NULL;
+		}
+		tasklet_init(&grp->mpc_tasklet2,
+				mpc_group_ready, (unsigned long)dev);
+		dev->mtu = MPC_BUFSIZE_DEFAULT -
+				TH_HEADER_LENGTH - PDU_HEADER_LENGTH;
+
+		dev->hard_start_xmit = ctcmpc_tx;
+		dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+		priv->buffer_size = MPC_BUFSIZE_DEFAULT;
+	} else {
+		dev->mtu = CTCM_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
+		dev->hard_start_xmit = ctcm_tx;
+		dev->hard_header_len = LL_HEADER_LENGTH + 2;
+	}
+
+	CTCMY_DBF_DEV(SETUP, dev, "finished");
+	return dev;
+}
+
+/**
+ * Main IRQ handler.
+ *
+ *  cdev	The ccw_device the interrupt is for.
+ *  intparm	interruption parameter.
+ *  irb		interruption response block.
+ */
+static void ctcm_irq_handler(struct ccw_device *cdev,
+				unsigned long intparm, struct irb *irb)
+{
+	struct channel		*ch;
+	struct net_device	*dev;
+	struct ctcm_priv	*priv;
+	struct ccwgroup_device	*cgdev;
+
+	CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __FUNCTION__);
+	if (ctcm_check_irb_error(cdev, irb))
+		return;
+
+	cgdev = dev_get_drvdata(&cdev->dev);
+
+	/* Check for unsolicited interrupts. */
+	if (cgdev == NULL) {
+		ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n",
+			    cdev->dev.bus_id, irb->scsw.cstat,
+			    irb->scsw.dstat);
+		return;
+	}
+
+	priv = dev_get_drvdata(&cgdev->dev);
+
+	/* Try to extract channel from driver data. */
+	if (priv->channel[READ]->cdev == cdev)
+		ch = priv->channel[READ];
+	else if (priv->channel[WRITE]->cdev == cdev)
+		ch = priv->channel[WRITE];
+	else {
+		ctcm_pr_err("ctcm: Can't determine channel for interrupt, "
+			   "device %s\n", cdev->dev.bus_id);
+		return;
+	}
+
+	dev = (struct net_device *)(ch->netdev);
+	if (dev == NULL) {
+		ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
+				__FUNCTION__, cdev->dev.bus_id, ch);
+		return;
+	}
+
+	if (do_debug)
+		ctcm_pr_debug("%s: interrupt for device: %s "
+				"received c-%02x d-%02x\n",
+				dev->name,
+				ch->id,
+				irb->scsw.cstat,
+				irb->scsw.dstat);
+
+	/* Copy interruption response block. */
+	memcpy(ch->irb, irb, sizeof(struct irb));
+
+	/* Check for good subchannel return code, otherwise error message */
+	if (irb->scsw.cstat) {
+		fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
+		ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n",
+			    dev->name, ch->id, irb->scsw.cstat,
+			    irb->scsw.dstat);
+		return;
+	}
+
+	/* Check the reason-code of a unit check */
+	if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+		ccw_unit_check(ch, irb->ecw[0]);
+		return;
+	}
+	if (irb->scsw.dstat & DEV_STAT_BUSY) {
+		if (irb->scsw.dstat & DEV_STAT_ATTENTION)
+			fsm_event(ch->fsm, CTC_EVENT_ATTNBUSY, ch);
+		else
+			fsm_event(ch->fsm, CTC_EVENT_BUSY, ch);
+		return;
+	}
+	if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
+		fsm_event(ch->fsm, CTC_EVENT_ATTN, ch);
+		return;
+	}
+	if ((irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
+	    (irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
+	    (irb->scsw.stctl ==
+	     (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
+		fsm_event(ch->fsm, CTC_EVENT_FINSTAT, ch);
+	else
+		fsm_event(ch->fsm, CTC_EVENT_IRQ, ch);
+
+}
+
+/**
+ * Add ctcm specific attributes.
+ * Add ctcm private data.
+ *
+ *  cgdev	pointer to ccwgroup_device just added
+ *
+ * returns 0 on success, !0 on failure.
+ */
+static int ctcm_probe_device(struct ccwgroup_device *cgdev)
+{
+	struct ctcm_priv *priv;
+	int rc;
+
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s %p", __FUNCTION__, cgdev);
+
+	if (!get_device(&cgdev->dev))
+		return -ENODEV;
+
+	priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL);
+	if (!priv) {
+		ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+		put_device(&cgdev->dev);
+		return -ENOMEM;
+	}
+
+	rc = ctcm_add_files(&cgdev->dev);
+	if (rc) {
+		kfree(priv);
+		put_device(&cgdev->dev);
+		return rc;
+	}
+	priv->buffer_size = CTCM_BUFSIZE_DEFAULT;
+	cgdev->cdev[0]->handler = ctcm_irq_handler;
+	cgdev->cdev[1]->handler = ctcm_irq_handler;
+	dev_set_drvdata(&cgdev->dev, priv);
+
+	return 0;
+}
+
+/**
+ * Add a new channel to the list of channels.
+ * Keeps the channel list sorted.
+ *
+ *  cdev	The ccw_device to be added.
+ *  type	The type class of the new channel.
+ *  priv	Points to the private data of the ccwgroup_device.
+ *
+ * returns 0 on success, !0 on error.
+ */
+static int add_channel(struct ccw_device *cdev, enum channel_types type,
+				struct ctcm_priv *priv)
+{
+	struct channel **c = &channels;
+	struct channel *ch;
+	int ccw_num;
+	int rc = 0;
+
+	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+	ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
+	if (ch == NULL)
+					goto nomem_return;
+
+	ch->protocol = priv->protocol;
+	if (IS_MPC(priv)) {
+		ch->discontact_th = (struct th_header *)
+				kzalloc(TH_HEADER_LENGTH, gfp_type());
+		if (ch->discontact_th == NULL)
+					goto nomem_return;
+
+		ch->discontact_th->th_blk_flag = TH_DISCONTACT;
+		tasklet_init(&ch->ch_disc_tasklet,
+			mpc_action_send_discontact, (unsigned long)ch);
+
+		tasklet_init(&ch->ch_tasklet, ctcmpc_bh, (unsigned long)ch);
+		ch->max_bufsize = (MPC_BUFSIZE_DEFAULT - 35);
+		ccw_num = 17;
+	} else
+		ccw_num = 8;
+
+	ch->ccw = (struct ccw1 *)
+		kzalloc(ccw_num * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
+	if (ch->ccw == NULL)
+					goto nomem_return;
+
+	ch->cdev = cdev;
+	snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", cdev->dev.bus_id);
+	ch->type = type;
+
+	/**
+	 * "static" ccws are used in the following way:
+	 *
+	 * ccw[0..2] (Channel program for generic I/O):
+	 *           0: prepare
+	 *           1: read or write (depending on direction) with fixed
+	 *              buffer (idal allocated once when buffer is allocated)
+	 *           2: nop
+	 * ccw[3..5] (Channel program for direct write of packets)
+	 *           3: prepare
+	 *           4: write (idal allocated on every write).
+	 *           5: nop
+	 * ccw[6..7] (Channel program for initial channel setup):
+	 *           6: set extended mode
+	 *           7: nop
+	 *
+	 * ch->ccw[0..5] are initialized in ch_action_start because
+	 * the channel's direction is yet unknown here.
+	 *
+	 * ccws used for xid2 negotiations
+	 *  ch-ccw[8-14] need to be used for the XID exchange either
+	 *    X side XID2 Processing
+	 *       8:  write control
+	 *       9:  write th
+	 *	     10: write XID
+	 *	     11: read th from secondary
+	 *	     12: read XID   from secondary
+	 *	     13: read 4 byte ID
+	 *	     14: nop
+	 *    Y side XID Processing
+	 *	     8:  sense
+	 *       9:  read th
+	 *	     10: read XID
+	 *	     11: write th
+	 *	     12: write XID
+	 *	     13: write 4 byte ID
+	 *	     14: nop
+	 *
+	 *  ccws used for double noop due to VM timing issues
+	 *  which result in unrecoverable Busy on channel
+	 *       15: nop
+	 *       16: nop
+	 */
+	ch->ccw[6].cmd_code	= CCW_CMD_SET_EXTENDED;
+	ch->ccw[6].flags	= CCW_FLAG_SLI;
+
+	ch->ccw[7].cmd_code	= CCW_CMD_NOOP;
+	ch->ccw[7].flags	= CCW_FLAG_SLI;
+
+	if (IS_MPC(priv)) {
+		ch->ccw[15].cmd_code = CCW_CMD_WRITE;
+		ch->ccw[15].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[15].count    = TH_HEADER_LENGTH;
+		ch->ccw[15].cda      = virt_to_phys(ch->discontact_th);
+
+		ch->ccw[16].cmd_code = CCW_CMD_NOOP;
+		ch->ccw[16].flags    = CCW_FLAG_SLI;
+
+		ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
+				ctc_ch_event_names, CTC_MPC_NR_STATES,
+				CTC_MPC_NR_EVENTS, ctcmpc_ch_fsm,
+				mpc_ch_fsm_len, GFP_KERNEL);
+	} else {
+		ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
+				ctc_ch_event_names, CTC_NR_STATES,
+				CTC_NR_EVENTS, ch_fsm,
+				ch_fsm_len, GFP_KERNEL);
+	}
+	if (ch->fsm == NULL)
+				goto free_return;
+
+	fsm_newstate(ch->fsm, CTC_STATE_IDLE);
+
+	ch->irb = kzalloc(sizeof(struct irb), GFP_KERNEL);
+	if (ch->irb == NULL)
+				goto nomem_return;
+
+	while (*c && ctcm_less_than((*c)->id, ch->id))
+		c = &(*c)->next;
+
+	if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) {
+		CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+				"%s (%s) already in list, using old entry",
+				__FUNCTION__, (*c)->id);
+
+				goto free_return;
+	}
+
+	spin_lock_init(&ch->collect_lock);
+
+	fsm_settimer(ch->fsm, &ch->timer);
+	skb_queue_head_init(&ch->io_queue);
+	skb_queue_head_init(&ch->collect_queue);
+
+	if (IS_MPC(priv)) {
+		fsm_settimer(ch->fsm, &ch->sweep_timer);
+		skb_queue_head_init(&ch->sweep_queue);
+	}
+	ch->next = *c;
+	*c = ch;
+	return 0;
+
+nomem_return:
+	ctcm_pr_warn("ctcm: Out of memory in %s\n", __FUNCTION__);
+	rc = -ENOMEM;
+
+free_return:	/* note that all channel pointers are 0 or valid */
+	kfree(ch->ccw);		/* TODO: check that again */
+	kfree(ch->discontact_th);
+	kfree_fsm(ch->fsm);
+	kfree(ch->irb);
+	kfree(ch);
+	return rc;
+}
+
+/*
+ * Return type of a detected device.
+ */
+static enum channel_types get_channel_type(struct ccw_device_id *id)
+{
+	enum channel_types type;
+	type = (enum channel_types)id->driver_info;
+
+	if (type == channel_type_ficon)
+		type = channel_type_escon;
+
+	return type;
+}
+
+/**
+ *
+ * Setup an interface.
+ *
+ *  cgdev	Device to be setup.
+ *
+ * returns 0 on success, !0 on failure.
+ */
+static int ctcm_new_device(struct ccwgroup_device *cgdev)
+{
+	char read_id[CTCM_ID_SIZE];
+	char write_id[CTCM_ID_SIZE];
+	int direction;
+	enum channel_types type;
+	struct ctcm_priv *priv;
+	struct net_device *dev;
+	int ret;
+
+	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
+
+	priv = dev_get_drvdata(&cgdev->dev);
+	if (!priv)
+		return -ENODEV;
+
+	type = get_channel_type(&cgdev->cdev[0]->id);
+
+	snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
+	snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
+
+	ret = add_channel(cgdev->cdev[0], type, priv);
+	if (ret)
+		return ret;
+	ret = add_channel(cgdev->cdev[1], type, priv);
+	if (ret)
+		return ret;
+
+	ret = ccw_device_set_online(cgdev->cdev[0]);
+	if (ret != 0) {
+		CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
+				"ccw_device_set_online (cdev[0]) failed ");
+		ctcm_pr_warn("ccw_device_set_online (cdev[0]) failed "
+				"with ret = %d\n", ret);
+	}
+
+	ret = ccw_device_set_online(cgdev->cdev[1]);
+	if (ret != 0) {
+		CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
+				"ccw_device_set_online (cdev[1]) failed ");
+		ctcm_pr_warn("ccw_device_set_online (cdev[1]) failed "
+				"with ret = %d\n", ret);
+	}
+
+	dev = ctcm_init_netdevice(priv);
+
+	if (dev == NULL) {
+		ctcm_pr_warn("ctcm_init_netdevice failed\n");
+					goto out;
+	}
+
+	for (direction = READ; direction <= WRITE; direction++) {
+		priv->channel[direction] =
+		    channel_get(type, direction == READ ? read_id : write_id,
+				direction);
+		if (priv->channel[direction] == NULL) {
+			if (direction == WRITE)
+				channel_free(priv->channel[READ]);
+			ctcm_free_netdevice(dev);
+					goto out;
+		}
+		priv->channel[direction]->netdev = dev;
+		priv->channel[direction]->protocol = priv->protocol;
+		priv->channel[direction]->max_bufsize = priv->buffer_size;
+	}
+	/* sysfs magic */
+	SET_NETDEV_DEV(dev, &cgdev->dev);
+
+	if (ctcm_netdev_register(dev) != 0) {
+		ctcm_free_netdevice(dev);
+					goto out;
+	}
+
+	if (ctcm_add_attributes(&cgdev->dev)) {
+		ctcm_netdev_unregister(dev);
+/*		dev->priv = NULL;	why that ????	*/
+		ctcm_free_netdevice(dev);
+					goto out;
+	}
+
+	strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
+
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+			"setup(%s) ok : r/w = %s / %s, proto : %d",
+			dev->name, priv->channel[READ]->id,
+			priv->channel[WRITE]->id, priv->protocol);
+
+	return 0;
+out:
+	ccw_device_set_offline(cgdev->cdev[1]);
+	ccw_device_set_offline(cgdev->cdev[0]);
+
+	return -ENODEV;
+}
+
+/**
+ * Shutdown an interface.
+ *
+ *  cgdev	Device to be shut down.
+ *
+ * returns 0 on success, !0 on failure.
+ */
+static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
+{
+	struct ctcm_priv *priv;
+	struct net_device *dev;
+
+	priv = dev_get_drvdata(&cgdev->dev);
+	if (!priv)
+		return -ENODEV;
+
+	if (priv->channel[READ]) {
+		dev = priv->channel[READ]->netdev;
+		CTCM_DBF_DEV(SETUP, dev, "");
+		/* Close the device */
+		ctcm_close(dev);
+		dev->flags &= ~IFF_RUNNING;
+		ctcm_remove_attributes(&cgdev->dev);
+		channel_free(priv->channel[READ]);
+	} else
+		dev = NULL;
+
+	if (priv->channel[WRITE])
+		channel_free(priv->channel[WRITE]);
+
+	if (dev) {
+		ctcm_netdev_unregister(dev);
+/*		dev->priv = NULL;	why that ???	*/
+		ctcm_free_netdevice(dev);
+	}
+
+	if (priv->fsm)
+		kfree_fsm(priv->fsm);
+
+	ccw_device_set_offline(cgdev->cdev[1]);
+	ccw_device_set_offline(cgdev->cdev[0]);
+
+	if (priv->channel[READ])
+		channel_remove(priv->channel[READ]);
+	if (priv->channel[WRITE])
+		channel_remove(priv->channel[WRITE]);
+	priv->channel[READ] = priv->channel[WRITE] = NULL;
+
+	return 0;
+
+}
+
+
+static void ctcm_remove_device(struct ccwgroup_device *cgdev)
+{
+	struct ctcm_priv *priv;
+
+	CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, __FUNCTION__);
+
+	priv = dev_get_drvdata(&cgdev->dev);
+	if (!priv)
+		return;
+	if (cgdev->state == CCWGROUP_ONLINE)
+		ctcm_shutdown_device(cgdev);
+	ctcm_remove_files(&cgdev->dev);
+	dev_set_drvdata(&cgdev->dev, NULL);
+	kfree(priv);
+	put_device(&cgdev->dev);
+}
+
+static struct ccwgroup_driver ctcm_group_driver = {
+	.owner       = THIS_MODULE,
+	.name        = CTC_DRIVER_NAME,
+	.max_slaves  = 2,
+	.driver_id   = 0xC3E3C3D4,	/* CTCM */
+	.probe       = ctcm_probe_device,
+	.remove      = ctcm_remove_device,
+	.set_online  = ctcm_new_device,
+	.set_offline = ctcm_shutdown_device,
+};
+
+
+/*
+ * Module related routines
+ */
+
+/*
+ * Prepare to be unloaded. Free IRQ's and release all resources.
+ * This is called just before this module is unloaded. It is
+ * not called, if the usage count is !0, so we don't need to check
+ * for that.
+ */
+static void __exit ctcm_exit(void)
+{
+	unregister_cu3088_discipline(&ctcm_group_driver);
+	ctcm_unregister_dbf_views();
+	ctcm_pr_info("CTCM driver unloaded\n");
+}
+
+/*
+ * Print Banner.
+ */
+static void print_banner(void)
+{
+	printk(KERN_INFO "CTCM driver initialized\n");
+}
+
+/**
+ * Initialize module.
+ * This is called just after the module is loaded.
+ *
+ * returns 0 on success, !0 on error.
+ */
+static int __init ctcm_init(void)
+{
+	int ret;
+
+	channels = NULL;
+
+	ret = ctcm_register_dbf_views();
+	if (ret) {
+		ctcm_pr_crit("ctcm_init failed with ctcm_register_dbf_views "
+				"rc = %d\n", ret);
+		return ret;
+	}
+	ret = register_cu3088_discipline(&ctcm_group_driver);
+	if (ret) {
+		ctcm_unregister_dbf_views();
+		ctcm_pr_crit("ctcm_init failed with register_cu3088_discipline "
+				"(rc = %d)\n", ret);
+		return ret;
+	}
+	print_banner();
+	return ret;
+}
+
+module_init(ctcm_init);
+module_exit(ctcm_exit);
+
+MODULE_AUTHOR("Peter Tiedemann <ptiedem@de.ibm.com>");
+MODULE_DESCRIPTION("Network driver for S/390 CTC + CTCMPC (SNA)");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
new file mode 100644
index 0000000..95b0c0b
--- /dev/null
+++ b/drivers/s390/net/ctcm_main.h
@@ -0,0 +1,287 @@
+/*
+ *	drivers/s390/net/ctcm_main.h
+ *
+ *	Copyright IBM Corp. 2001, 2007
+ *	Authors:	Fritz Elfert (felfert@millenux.com)
+ *			Peter Tiedemann (ptiedem@de.ibm.com)
+ */
+
+#ifndef _CTCM_MAIN_H_
+#define _CTCM_MAIN_H_
+
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include "fsm.h"
+#include "cu3088.h"
+#include "ctcm_dbug.h"
+#include "ctcm_mpc.h"
+
+#define CTC_DRIVER_NAME	"ctcm"
+#define CTC_DEVICE_NAME	"ctc"
+#define CTC_DEVICE_GENE	"ctc%d"
+#define MPC_DEVICE_NAME	"mpc"
+#define MPC_DEVICE_GENE	"mpc%d"
+
+#define CHANNEL_FLAGS_READ	0
+#define CHANNEL_FLAGS_WRITE	1
+#define CHANNEL_FLAGS_INUSE	2
+#define CHANNEL_FLAGS_BUFSIZE_CHANGED	4
+#define CHANNEL_FLAGS_FAILED	8
+#define CHANNEL_FLAGS_WAITIRQ	16
+#define CHANNEL_FLAGS_RWMASK	1
+#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
+
+#define LOG_FLAG_ILLEGALPKT	1
+#define LOG_FLAG_ILLEGALSIZE	2
+#define LOG_FLAG_OVERRUN	4
+#define LOG_FLAG_NOMEM		8
+
+#define ctcm_pr_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
+#define ctcm_pr_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
+#define ctcm_pr_notice(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
+#define ctcm_pr_warn(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
+#define ctcm_pr_emerg(fmt, arg...) printk(KERN_EMERG fmt, ##arg)
+#define ctcm_pr_err(fmt, arg...) printk(KERN_ERR fmt, ##arg)
+#define ctcm_pr_crit(fmt, arg...) printk(KERN_CRIT fmt, ##arg)
+
+/*
+ * CCW commands, used in this driver.
+ */
+#define CCW_CMD_WRITE		0x01
+#define CCW_CMD_READ		0x02
+#define CCW_CMD_NOOP		0x03
+#define CCW_CMD_TIC             0x08
+#define CCW_CMD_SENSE_CMD	0x14
+#define CCW_CMD_WRITE_CTL	0x17
+#define CCW_CMD_SET_EXTENDED	0xc3
+#define CCW_CMD_PREPARE		0xe3
+
+#define CTCM_PROTO_S390		0
+#define CTCM_PROTO_LINUX	1
+#define CTCM_PROTO_LINUX_TTY	2
+#define CTCM_PROTO_OS390	3
+#define CTCM_PROTO_MPC		4
+#define CTCM_PROTO_MAX		4
+
+#define CTCM_BUFSIZE_LIMIT	65535
+#define CTCM_BUFSIZE_DEFAULT	32768
+#define MPC_BUFSIZE_DEFAULT	CTCM_BUFSIZE_LIMIT
+
+#define CTCM_TIME_1_SEC		1000
+#define CTCM_TIME_5_SEC		5000
+#define CTCM_TIME_10_SEC	10000
+
+#define CTCM_INITIAL_BLOCKLEN	2
+
+#define READ			0
+#define WRITE			1
+
+#define CTCM_ID_SIZE		BUS_ID_SIZE+3
+
+struct ctcm_profile {
+	unsigned long maxmulti;
+	unsigned long maxcqueue;
+	unsigned long doios_single;
+	unsigned long doios_multi;
+	unsigned long txlen;
+	unsigned long tx_time;
+	struct timespec send_stamp;
+};
+
+/*
+ * Definition of one channel
+ */
+struct channel {
+	struct channel *next;
+	char id[CTCM_ID_SIZE];
+	struct ccw_device *cdev;
+	/*
+	 * Type of this channel.
+	 * CTC/A or Escon for valid channels.
+	 */
+	enum channel_types type;
+	/*
+	 * Misc. flags. See CHANNEL_FLAGS_... below
+	 */
+	__u32 flags;
+	__u16 protocol;		/* protocol of this channel (4 = MPC) */
+	/*
+	 * I/O and irq related stuff
+	 */
+	struct ccw1 *ccw;
+	struct irb *irb;
+	/*
+	 * RX/TX buffer size
+	 */
+	int max_bufsize;
+	struct sk_buff *trans_skb;	/* transmit/receive buffer */
+	struct sk_buff_head io_queue;	/* universal I/O queue */
+	struct tasklet_struct ch_tasklet;	/* MPC ONLY */
+	/*
+	 * TX queue for collecting skb's during busy.
+	 */
+	struct sk_buff_head collect_queue;
+	/*
+	 * Amount of data in collect_queue.
+	 */
+	int collect_len;
+	/*
+	 * spinlock for collect_queue and collect_len
+	 */
+	spinlock_t collect_lock;
+	/*
+	 * Timer for detecting unresposive
+	 * I/O operations.
+	 */
+	fsm_timer timer;
+	/* MPC ONLY section begin */
+	__u32	th_seq_num;	/* SNA TH seq number */
+	__u8	th_seg;
+	__u32	pdu_seq;
+	struct sk_buff		*xid_skb;
+	char			*xid_skb_data;
+	struct th_header	*xid_th;
+	struct xid2		*xid;
+	char			*xid_id;
+	struct th_header	*rcvd_xid_th;
+	struct xid2		*rcvd_xid;
+	char			*rcvd_xid_id;
+	__u8			in_mpcgroup;
+	fsm_timer		sweep_timer;
+	struct sk_buff_head	sweep_queue;
+	struct th_header	*discontact_th;
+	struct tasklet_struct	ch_disc_tasklet;
+	/* MPC ONLY section end */
+
+	int retry;		/* retry counter for misc. operations */
+	fsm_instance *fsm;	/* finite state machine of this channel */
+	struct net_device *netdev;	/* corresponding net_device */
+	struct ctcm_profile prof;
+	unsigned char *trans_skb_data;
+	__u16 logflags;
+};
+
+struct ctcm_priv {
+	struct net_device_stats	stats;
+	unsigned long	tbusy;
+
+	/* The MPC group struct of this interface */
+	struct	mpc_group	*mpcg;	/* MPC only */
+	struct	xid2		*xid;	/* MPC only */
+
+	/* The finite state machine of this interface */
+	fsm_instance *fsm;
+
+	/* The protocol of this device */
+	__u16 protocol;
+
+	/* Timer for restarting after I/O Errors */
+	fsm_timer	restart_timer;
+
+	int buffer_size;	/* ctc only */
+
+	struct channel *channel[2];
+};
+
+int ctcm_open(struct net_device *dev);
+int ctcm_close(struct net_device *dev);
+
+/*
+ * prototypes for non-static sysfs functions
+ */
+int ctcm_add_attributes(struct device *dev);
+void ctcm_remove_attributes(struct device *dev);
+int ctcm_add_files(struct device *dev);
+void ctcm_remove_files(struct device *dev);
+
+/*
+ * Compatibility macros for busy handling
+ * of network devices.
+ */
+static inline void ctcm_clear_busy_do(struct net_device *dev)
+{
+	clear_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
+	netif_wake_queue(dev);
+}
+
+static inline void ctcm_clear_busy(struct net_device *dev)
+{
+	struct mpc_group *grp;
+	grp = ((struct ctcm_priv *)dev->priv)->mpcg;
+
+	if (!(grp && grp->in_sweep))
+		ctcm_clear_busy_do(dev);
+}
+
+
+static inline int ctcm_test_and_set_busy(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	return test_and_set_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
+}
+
+extern int loglevel;
+extern struct channel *channels;
+
+void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb);
+
+/*
+ * Functions related to setup and device detection.
+ */
+
+static inline int ctcm_less_than(char *id1, char *id2)
+{
+	unsigned long dev1, dev2;
+
+	id1 = id1 + 5;
+	id2 = id2 + 5;
+
+	dev1 = simple_strtoul(id1, &id1, 16);
+	dev2 = simple_strtoul(id2, &id2, 16);
+
+	return (dev1 < dev2);
+}
+
+int ctcm_ch_alloc_buffer(struct channel *ch);
+
+static inline int ctcm_checkalloc_buffer(struct channel *ch)
+{
+	if (ch->trans_skb == NULL)
+		return ctcm_ch_alloc_buffer(ch);
+	if (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED) {
+		dev_kfree_skb(ch->trans_skb);
+		return ctcm_ch_alloc_buffer(ch);
+	}
+	return 0;
+}
+
+struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
+
+/* test if protocol attribute (of struct ctcm_priv or struct channel)
+ * has MPC protocol setting. Type is not checked
+ */
+#define IS_MPC(p) ((p)->protocol == CTCM_PROTO_MPC)
+
+/* test if struct ctcm_priv of struct net_device has MPC protocol setting */
+#define IS_MPCDEV(d) IS_MPC((struct ctcm_priv *)d->priv)
+
+static inline gfp_t gfp_type(void)
+{
+	return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+}
+
+/*
+ * Definition of our link level header.
+ */
+struct ll_header {
+	__u16 length;
+	__u16 type;
+	__u16 unused;
+};
+#define LL_HEADER_LENGTH (sizeof(struct ll_header))
+
+#endif
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
new file mode 100644
index 0000000..044adde
--- /dev/null
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -0,0 +1,2472 @@
+/*
+ *	drivers/s390/net/ctcm_mpc.c
+ *
+ *	Copyright IBM Corp. 2004, 2007
+ *	Authors:	Belinda Thompson (belindat@us.ibm.com)
+ *			Andy Richter (richtera@us.ibm.com)
+ *			Peter Tiedemann (ptiedem@de.ibm.com)
+ */
+
+/*
+	This module exports functions to be used by CCS:
+	EXPORT_SYMBOL(ctc_mpc_alloc_channel);
+	EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
+	EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
+	EXPORT_SYMBOL(ctc_mpc_flow_control);
+*/
+
+#undef DEBUG
+#undef DEBUGDATA
+#undef DEBUGCCW
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+
+#include <linux/signal.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+
+#include <linux/ip.h>
+#include <linux/if_arp.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/ctype.h>
+#include <linux/netdevice.h>
+#include <net/dst.h>
+
+#include <linux/io.h>		/* instead of <asm/io.h> ok ? */
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+#include <linux/bitops.h>	/* instead of <asm/bitops.h> ok ? */
+#include <linux/uaccess.h>	/* instead of <asm/uaccess.h> ok ? */
+#include <linux/wait.h>
+#include <linux/moduleparam.h>
+#include <asm/idals.h>
+
+#include "cu3088.h"
+#include "ctcm_mpc.h"
+#include "ctcm_main.h"
+#include "ctcm_fsms.h"
+
+static const struct xid2 init_xid = {
+	.xid2_type_id	=	XID_FM2,
+	.xid2_len	=	0x45,
+	.xid2_adj_id	=	0,
+	.xid2_rlen	=	0x31,
+	.xid2_resv1	=	0,
+	.xid2_flag1	=	0,
+	.xid2_fmtt	=	0,
+	.xid2_flag4	=	0x80,
+	.xid2_resv2	=	0,
+	.xid2_tgnum	=	0,
+	.xid2_sender_id	=	0,
+	.xid2_flag2	=	0,
+	.xid2_option	=	XID2_0,
+	.xid2_resv3	=	"\x00",
+	.xid2_resv4	=	0,
+	.xid2_dlc_type	=	XID2_READ_SIDE,
+	.xid2_resv5	=	0,
+	.xid2_mpc_flag	=	0,
+	.xid2_resv6	=	0,
+	.xid2_buf_len	=	(MPC_BUFSIZE_DEFAULT - 35),
+};
+
+static const struct th_header thnorm = {
+	.th_seg		=	0x00,
+	.th_ch_flag	=	TH_IS_XID,
+	.th_blk_flag	=	TH_DATA_IS_XID,
+	.th_is_xid	=	0x01,
+	.th_seq_num	=	0x00000000,
+};
+
+static const struct th_header thdummy = {
+	.th_seg		=	0x00,
+	.th_ch_flag	=	0x00,
+	.th_blk_flag	=	TH_DATA_IS_XID,
+	.th_is_xid	=	0x01,
+	.th_seq_num	=	0x00000000,
+};
+
+/*
+ * Definition of one MPC group
+ */
+
+/*
+ * Compatibility macros for busy handling
+ * of network devices.
+ */
+
+static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb);
+
+/*
+ * MPC Group state machine actions (static prototypes)
+ */
+static void mpc_action_nop(fsm_instance *fsm, int event, void *arg);
+static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg);
+static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg);
+static void mpc_action_timeout(fsm_instance *fi, int event, void *arg);
+static int  mpc_validate_xid(struct mpcg_info *mpcginfo);
+static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg);
+static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg);
+static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg);
+static void mpc_action_xside_xid(fsm_instance *fsm, int event, void *arg);
+static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg);
+static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg);
+
+#ifdef DEBUGDATA
+/*-------------------------------------------------------------------*
+* Dump buffer format						     *
+*								     *
+*--------------------------------------------------------------------*/
+void ctcmpc_dumpit(char *buf, int len)
+{
+	__u32	ct, sw, rm, dup;
+	char	*ptr, *rptr;
+	char	tbuf[82], tdup[82];
+	#if (UTS_MACHINE == s390x)
+	char	addr[22];
+	#else
+	char	addr[12];
+	#endif
+	char	boff[12];
+	char	bhex[82], duphex[82];
+	char	basc[40];
+
+	sw  = 0;
+	rptr = ptr = buf;
+	rm  = 16;
+	duphex[0] = 0x00;
+	dup = 0;
+
+	for (ct = 0; ct < len; ct++, ptr++, rptr++) {
+		if (sw == 0) {
+			#if (UTS_MACHINE == s390x)
+			sprintf(addr, "%16.16lx", (unsigned long)rptr);
+			#else
+			sprintf(addr, "%8.8X", (__u32)rptr);
+			#endif
+
+			sprintf(boff, "%4.4X", (__u32)ct);
+			bhex[0] = '\0';
+			basc[0] = '\0';
+		}
+		if ((sw == 4) || (sw == 12))
+			strcat(bhex, " ");
+		if (sw == 8)
+			strcat(bhex, "	");
+
+		#if (UTS_MACHINE == s390x)
+		sprintf(tbuf, "%2.2lX", (unsigned long)*ptr);
+		#else
+		sprintf(tbuf, "%2.2X", (__u32)*ptr);
+		#endif
+
+		tbuf[2] = '\0';
+		strcat(bhex, tbuf);
+		if ((0 != isprint(*ptr)) && (*ptr >= 0x20))
+			basc[sw] = *ptr;
+		else
+			basc[sw] = '.';
+
+		basc[sw+1] = '\0';
+		sw++;
+		rm--;
+		if (sw == 16) {
+			if ((strcmp(duphex, bhex)) != 0) {
+				if (dup != 0) {
+					sprintf(tdup, "Duplicate as above "
+						"to %s", addr);
+					printk(KERN_INFO "		  "
+						"     --- %s ---\n", tdup);
+				}
+				printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
+					addr, boff, bhex, basc);
+				dup = 0;
+				strcpy(duphex, bhex);
+			} else
+				dup++;
+
+			sw = 0;
+			rm = 16;
+		}
+	}  /* endfor */
+
+	if (sw != 0) {
+		for ( ; rm > 0; rm--, sw++) {
+			if ((sw == 4) || (sw == 12))
+				strcat(bhex, " ");
+			if (sw == 8)
+				strcat(bhex, "	");
+			strcat(bhex, "	");
+			strcat(basc, " ");
+		}
+		if (dup != 0) {
+			sprintf(tdup, "Duplicate as above to %s", addr);
+			printk(KERN_INFO "		  "
+				"     --- %s ---\n", tdup);
+		}
+		printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
+			addr, boff, bhex, basc);
+	} else {
+		if (dup >= 1) {
+			sprintf(tdup, "Duplicate as above to %s", addr);
+			printk(KERN_INFO "		  "
+				"     --- %s ---\n", tdup);
+		}
+		if (dup != 0) {
+			printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
+				addr, boff, bhex, basc);
+		}
+	}
+
+	return;
+
+}   /*	 end of ctcmpc_dumpit  */
+#endif
+
+#ifdef DEBUGDATA
+/*
+ * Dump header and first 16 bytes of an sk_buff for debugging purposes.
+ *
+ * skb		The sk_buff to dump.
+ * offset	Offset relative to skb-data, where to start the dump.
+ */
+void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
+{
+	unsigned char *p = skb->data;
+	struct th_header *header;
+	struct pdu *pheader;
+	int bl = skb->len;
+	int i;
+
+	if (p == NULL)
+		return;
+
+	p += offset;
+	header = (struct th_header *)p;
+
+	printk(KERN_INFO "dump:\n");
+	printk(KERN_INFO "skb len=%d \n", skb->len);
+	if (skb->len > 2) {
+		switch (header->th_ch_flag) {
+		case TH_HAS_PDU:
+			break;
+		case 0x00:
+		case TH_IS_XID:
+			if ((header->th_blk_flag == TH_DATA_IS_XID) &&
+			   (header->th_is_xid == 0x01))
+				goto dumpth;
+		case TH_SWEEP_REQ:
+				goto dumpth;
+		case TH_SWEEP_RESP:
+				goto dumpth;
+		default:
+			break;
+		}
+
+		pheader = (struct pdu *)p;
+		printk(KERN_INFO "pdu->offset: %d hex: %04x\n",
+		       pheader->pdu_offset, pheader->pdu_offset);
+		printk(KERN_INFO "pdu->flag  : %02x\n", pheader->pdu_flag);
+		printk(KERN_INFO "pdu->proto : %02x\n", pheader->pdu_proto);
+		printk(KERN_INFO "pdu->seq   : %02x\n", pheader->pdu_seq);
+					goto dumpdata;
+
+dumpth:
+		printk(KERN_INFO "th->seg     : %02x\n", header->th_seg);
+		printk(KERN_INFO "th->ch      : %02x\n", header->th_ch_flag);
+		printk(KERN_INFO "th->blk_flag: %02x\n", header->th_blk_flag);
+		printk(KERN_INFO "th->type    : %s\n",
+		       (header->th_is_xid) ? "DATA" : "XID");
+		printk(KERN_INFO "th->seqnum  : %04x\n", header->th_seq_num);
+
+	}
+dumpdata:
+	if (bl > 32)
+		bl = 32;
+	printk(KERN_INFO "data: ");
+	for (i = 0; i < bl; i++)
+		printk(KERN_INFO "%02x%s", *p++, (i % 16) ? " " : "\n<7>");
+	printk(KERN_INFO "\n");
+}
+#endif
+
+/*
+ * ctc_mpc_alloc_channel
+ *	(exported interface)
+ *
+ * Device Initialization :
+ *	ACTPATH  driven IO operations
+ */
+int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
+{
+	char device[20];
+	struct net_device *dev;
+	struct mpc_group *grp;
+	struct ctcm_priv *priv;
+
+	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
+
+	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+	dev = __dev_get_by_name(&init_net, device);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "ctc_mpc_alloc_channel %s dev=NULL\n", device);
+		return 1;
+	}
+
+	priv = dev->priv;
+	grp = priv->mpcg;
+	if (!grp)
+		return 1;
+
+	grp->allochanfunc = callback;
+	grp->port_num = port_num;
+	grp->port_persist = 1;
+
+	ctcm_pr_debug("ctcmpc: %s called for device %s state=%s\n",
+		       __FUNCTION__,
+		       dev->name,
+		       fsm_getstate_str(grp->fsm));
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_INOP:
+		/* Group is in the process of terminating */
+		grp->alloc_called = 1;
+		break;
+	case MPCG_STATE_RESET:
+		/* MPC Group will transition to state		  */
+		/* MPCG_STATE_XID2INITW iff the minimum number	  */
+		/* of 1 read and 1 write channel have successfully*/
+		/* activated					  */
+		/*fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);*/
+		if (callback)
+			grp->send_qllc_disc = 1;
+	case MPCG_STATE_XID0IOWAIT:
+		fsm_deltimer(&grp->timer);
+		grp->outstanding_xid2 = 0;
+		grp->outstanding_xid7 = 0;
+		grp->outstanding_xid7_p2 = 0;
+		grp->saved_xid2 = NULL;
+		if (callback)
+			ctcm_open(dev);
+		fsm_event(priv->fsm, DEV_EVENT_START, dev);
+		break;
+	case MPCG_STATE_READY:
+		/* XID exchanges completed after PORT was activated */
+		/* Link station already active			    */
+		/* Maybe timing issue...retry callback		    */
+		grp->allocchan_callback_retries++;
+		if (grp->allocchan_callback_retries < 4) {
+			if (grp->allochanfunc)
+				grp->allochanfunc(grp->port_num,
+					      grp->group_max_buflen);
+		} else {
+			/* there are problems...bail out	    */
+			/* there may be a state mismatch so restart */
+			grp->port_persist = 1;
+			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+			grp->allocchan_callback_retries = 0;
+		}
+		break;
+	default:
+		return 0;
+
+	}
+
+	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
+	return 0;
+}
+EXPORT_SYMBOL(ctc_mpc_alloc_channel);
+
+/*
+ * ctc_mpc_establish_connectivity
+ *	(exported interface)
+ */
+void ctc_mpc_establish_connectivity(int port_num,
+				void (*callback)(int, int, int))
+{
+	char device[20];
+	struct net_device *dev;
+	struct mpc_group *grp;
+	struct ctcm_priv *priv;
+	struct channel *rch, *wch;
+
+	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
+
+	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+	dev = __dev_get_by_name(&init_net, device);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "ctc_mpc_establish_connectivity "
+				"%s dev=NULL\n", device);
+		return;
+	}
+	priv = dev->priv;
+	rch = priv->channel[READ];
+	wch = priv->channel[WRITE];
+
+	grp = priv->mpcg;
+
+	ctcm_pr_debug("ctcmpc: %s() called for device %s state=%s\n",
+			__FUNCTION__, dev->name,
+			fsm_getstate_str(grp->fsm));
+
+	grp->estconnfunc = callback;
+	grp->port_num = port_num;
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_READY:
+		/* XID exchanges completed after PORT was activated */
+		/* Link station already active			    */
+		/* Maybe timing issue...retry callback		    */
+		fsm_deltimer(&grp->timer);
+		grp->estconn_callback_retries++;
+		if (grp->estconn_callback_retries < 4) {
+			if (grp->estconnfunc) {
+				grp->estconnfunc(grp->port_num, 0,
+						grp->group_max_buflen);
+				grp->estconnfunc = NULL;
+			}
+		} else {
+			/* there are problems...bail out	 */
+			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+			grp->estconn_callback_retries = 0;
+		}
+		break;
+	case MPCG_STATE_INOP:
+	case MPCG_STATE_RESET:
+		/* MPC Group is not ready to start XID - min num of */
+		/* 1 read and 1 write channel have not been acquired*/
+		printk(KERN_WARNING "ctcmpc: %s() REJECTED ACTIVE XID Req"
+			"uest - Channel Pair is not Active\n", __FUNCTION__);
+		if (grp->estconnfunc) {
+			grp->estconnfunc(grp->port_num, -1, 0);
+			grp->estconnfunc = NULL;
+		}
+		break;
+	case MPCG_STATE_XID2INITW:
+		/* alloc channel was called but no XID exchange    */
+		/* has occurred. initiate xside XID exchange	   */
+		/* make sure yside XID0 processing has not started */
+		if ((fsm_getstate(rch->fsm) > CH_XID0_PENDING) ||
+			(fsm_getstate(wch->fsm) > CH_XID0_PENDING)) {
+			printk(KERN_WARNING "mpc: %s() ABORT ACTIVE XID"
+			       " Request- PASSIVE XID in process\n"
+			       , __FUNCTION__);
+			break;
+		}
+		grp->send_qllc_disc = 1;
+		fsm_newstate(grp->fsm, MPCG_STATE_XID0IOWAIT);
+		fsm_deltimer(&grp->timer);
+		fsm_addtimer(&grp->timer, MPC_XID_TIMEOUT_VALUE,
+						MPCG_EVENT_TIMER, dev);
+		grp->outstanding_xid7 = 0;
+		grp->outstanding_xid7_p2 = 0;
+		grp->saved_xid2 = NULL;
+		if ((rch->in_mpcgroup) &&
+				(fsm_getstate(rch->fsm) == CH_XID0_PENDING))
+			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, rch);
+		else {
+			printk(KERN_WARNING "mpc: %s() Unable to start"
+			       " ACTIVE XID0 on read channel\n",
+			       __FUNCTION__);
+			if (grp->estconnfunc) {
+				grp->estconnfunc(grp->port_num, -1, 0);
+				grp->estconnfunc = NULL;
+			}
+			fsm_deltimer(&grp->timer);
+				goto done;
+		}
+		if ((wch->in_mpcgroup) &&
+				(fsm_getstate(wch->fsm) == CH_XID0_PENDING))
+			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, wch);
+		else {
+			printk(KERN_WARNING "mpc: %s() Unable to start"
+				" ACTIVE XID0 on write channel\n",
+					__FUNCTION__);
+			if (grp->estconnfunc) {
+				grp->estconnfunc(grp->port_num, -1, 0);
+				grp->estconnfunc = NULL;
+			}
+			fsm_deltimer(&grp->timer);
+				goto done;
+			}
+		break;
+	case MPCG_STATE_XID0IOWAIT:
+		/* already in active XID negotiations */
+	default:
+		break;
+	}
+
+done:
+	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
+	return;
+}
+EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
+
+/*
+ * ctc_mpc_dealloc_ch
+ *	(exported interface)
+ */
+void ctc_mpc_dealloc_ch(int port_num)
+{
+	struct net_device *dev;
+	char device[20];
+	struct ctcm_priv *priv;
+	struct mpc_group *grp;
+
+	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
+	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+	dev = __dev_get_by_name(&init_net, device);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
+					goto done;
+	}
+
+	ctcm_pr_debug("ctcmpc:%s %s() called for device %s refcount=%d\n",
+			dev->name, __FUNCTION__,
+			dev->name, atomic_read(&dev->refcnt));
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO "%s() %s priv=NULL\n",
+				__FUNCTION__, device);
+					goto done;
+	}
+	fsm_deltimer(&priv->restart_timer);
+
+	grp = priv->mpcg;
+	if (grp == NULL) {
+		printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
+					goto done;
+	}
+	grp->channels_terminating = 0;
+
+	fsm_deltimer(&grp->timer);
+
+	grp->allochanfunc = NULL;
+	grp->estconnfunc = NULL;
+	grp->port_persist = 0;
+	grp->send_qllc_disc = 0;
+	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+
+	ctcm_close(dev);
+done:
+	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
+	return;
+}
+EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
+
+/*
+ * ctc_mpc_flow_control
+ *	(exported interface)
+ */
+void ctc_mpc_flow_control(int port_num, int flowc)
+{
+	char device[20];
+	struct ctcm_priv *priv;
+	struct mpc_group *grp;
+	struct net_device *dev;
+	struct channel *rch;
+	int mpcg_state;
+
+	ctcm_pr_debug("ctcmpc enter:	%s() %i\n", __FUNCTION__, flowc);
+
+	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+	dev = __dev_get_by_name(&init_net, device);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "ctc_mpc_flow_control %s dev=NULL\n", device);
+		return;
+	}
+
+	ctcm_pr_debug("ctcmpc: %s %s called \n", dev->name, __FUNCTION__);
+
+	priv  = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO "ctcmpc:%s() %s priv=NULL\n",
+		       __FUNCTION__, device);
+		return;
+	}
+	grp = priv->mpcg;
+	rch = priv->channel[READ];
+
+	mpcg_state = fsm_getstate(grp->fsm);
+	switch (flowc) {
+	case 1:
+		if (mpcg_state == MPCG_STATE_FLOWC)
+			break;
+		if (mpcg_state == MPCG_STATE_READY) {
+			if (grp->flow_off_called == 1)
+				grp->flow_off_called = 0;
+			else
+				fsm_newstate(grp->fsm, MPCG_STATE_FLOWC);
+			break;
+		}
+		break;
+	case 0:
+		if (mpcg_state == MPCG_STATE_FLOWC) {
+			fsm_newstate(grp->fsm, MPCG_STATE_READY);
+			/* ensure any data that has accumulated */
+			/* on the io_queue will now be sen t	*/
+			tasklet_schedule(&rch->ch_tasklet);
+		}
+		/* possible race condition			*/
+		if (mpcg_state == MPCG_STATE_READY) {
+			grp->flow_off_called = 1;
+			break;
+		}
+		break;
+	}
+
+	ctcm_pr_debug("ctcmpc exit:  %s() %i\n", __FUNCTION__, flowc);
+}
+EXPORT_SYMBOL(ctc_mpc_flow_control);
+
+static int mpc_send_qllc_discontact(struct net_device *);
+
+/*
+ * helper function of ctcmpc_unpack_skb
+*/
+static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo)
+{
+	struct channel	  *rch = mpcginfo->ch;
+	struct net_device *dev = rch->netdev;
+	struct ctcm_priv   *priv = dev->priv;
+	struct mpc_group  *grp = priv->mpcg;
+	struct channel	  *ch = priv->channel[WRITE];
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
+			__FUNCTION__, ch, ch->id);
+
+	if (do_debug_data)
+		ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+
+	grp->sweep_rsp_pend_num--;
+
+	if ((grp->sweep_req_pend_num == 0) &&
+			(grp->sweep_rsp_pend_num == 0)) {
+		fsm_deltimer(&ch->sweep_timer);
+		grp->in_sweep = 0;
+		rch->th_seq_num = 0x00;
+		ch->th_seq_num = 0x00;
+		ctcm_clear_busy_do(dev);
+	}
+
+	kfree(mpcginfo);
+
+	return;
+
+}
+
+/*
+ * helper function of mpc_rcvd_sweep_req
+ * which is a helper of ctcmpc_unpack_skb
+ */
+static void ctcmpc_send_sweep_resp(struct channel *rch)
+{
+	struct net_device *dev = rch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp = priv->mpcg;
+	int rc = 0;
+	struct th_sweep *header;
+	struct sk_buff *sweep_skb;
+	struct channel *ch  = priv->channel[WRITE];
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
+			__FUNCTION__, rch, rch->id);
+
+	sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
+				    GFP_ATOMIC|GFP_DMA);
+	if (sweep_skb == NULL) {
+		printk(KERN_INFO "Couldn't alloc sweep_skb\n");
+		rc = -ENOMEM;
+				goto done;
+	}
+
+	header = (struct th_sweep *)
+			kmalloc(sizeof(struct th_sweep), gfp_type());
+
+	if (!header) {
+		dev_kfree_skb_any(sweep_skb);
+		rc = -ENOMEM;
+				goto done;
+	}
+
+	header->th.th_seg	= 0x00 ;
+	header->th.th_ch_flag	= TH_SWEEP_RESP;
+	header->th.th_blk_flag	= 0x00;
+	header->th.th_is_xid	= 0x00;
+	header->th.th_seq_num	= 0x00;
+	header->sw.th_last_seq	= ch->th_seq_num;
+
+	memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
+
+	kfree(header);
+
+	dev->trans_start = jiffies;
+	skb_queue_tail(&ch->sweep_queue, sweep_skb);
+
+	fsm_addtimer(&ch->sweep_timer, 100, CTC_EVENT_RSWEEP_TIMER, ch);
+
+	return;
+
+done:
+	if (rc != 0) {
+		grp->in_sweep = 0;
+		ctcm_clear_busy_do(dev);
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+	}
+
+	return;
+}
+
+/*
+ * helper function of ctcmpc_unpack_skb
+ */
+static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
+{
+	struct channel	  *rch     = mpcginfo->ch;
+	struct net_device *dev     = rch->netdev;
+	struct ctcm_priv  *priv = dev->priv;
+	struct mpc_group  *grp  = priv->mpcg;
+	struct channel	  *ch	   = priv->channel[WRITE];
+
+	if (do_debug)
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+			" %s(): ch=0x%p id=%s\n", __FUNCTION__, ch, ch->id);
+
+	if (grp->in_sweep == 0) {
+		grp->in_sweep = 1;
+		ctcm_test_and_set_busy(dev);
+		grp->sweep_req_pend_num = grp->active_channels[READ];
+		grp->sweep_rsp_pend_num = grp->active_channels[READ];
+	}
+
+	if (do_debug_data)
+		ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+
+	grp->sweep_req_pend_num--;
+	ctcmpc_send_sweep_resp(ch);
+	kfree(mpcginfo);
+	return;
+}
+
+/*
+  * MPC Group Station FSM definitions
+ */
+static const char *mpcg_event_names[] = {
+	[MPCG_EVENT_INOP]	= "INOP Condition",
+	[MPCG_EVENT_DISCONC]	= "Discontact Received",
+	[MPCG_EVENT_XID0DO]	= "Channel Active - Start XID",
+	[MPCG_EVENT_XID2]	= "XID2 Received",
+	[MPCG_EVENT_XID2DONE]	= "XID0 Complete",
+	[MPCG_EVENT_XID7DONE]	= "XID7 Complete",
+	[MPCG_EVENT_TIMER]	= "XID Setup Timer",
+	[MPCG_EVENT_DOIO]	= "XID DoIO",
+};
+
+static const char *mpcg_state_names[] = {
+	[MPCG_STATE_RESET]	= "Reset",
+	[MPCG_STATE_INOP]	= "INOP",
+	[MPCG_STATE_XID2INITW]	= "Passive XID- XID0 Pending Start",
+	[MPCG_STATE_XID2INITX]	= "Passive XID- XID0 Pending Complete",
+	[MPCG_STATE_XID7INITW]	= "Passive XID- XID7 Pending P1 Start",
+	[MPCG_STATE_XID7INITX]	= "Passive XID- XID7 Pending P2 Complete",
+	[MPCG_STATE_XID0IOWAIT]	= "Active  XID- XID0 Pending Start",
+	[MPCG_STATE_XID0IOWAIX]	= "Active  XID- XID0 Pending Complete",
+	[MPCG_STATE_XID7INITI]	= "Active  XID- XID7 Pending Start",
+	[MPCG_STATE_XID7INITZ]	= "Active  XID- XID7 Pending Complete ",
+	[MPCG_STATE_XID7INITF]	= "XID        - XID7 Complete ",
+	[MPCG_STATE_FLOWC]	= "FLOW CONTROL ON",
+	[MPCG_STATE_READY]	= "READY",
+};
+
+/*
+ * The MPC Group Station FSM
+ *   22 events
+ */
+static const fsm_node mpcg_fsm[] = {
+	{ MPCG_STATE_RESET,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_INOP,	MPCG_EVENT_INOP,	mpc_action_nop        },
+	{ MPCG_STATE_FLOWC,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+
+	{ MPCG_STATE_READY,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
+	{ MPCG_STATE_READY,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+
+	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
+	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
+	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
+
+	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
+	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
+	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
+
+	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_XID2DONE,	mpc_action_doxid7     },
+	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
+	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
+	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
+	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
+
+	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
+	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
+	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
+	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
+
+	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
+	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_DISCONC,	mpc_action_discontact },
+	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
+	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
+
+	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
+	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_DISCONC,	mpc_action_discontact },
+	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
+	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
+
+	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_XID2DONE,	mpc_action_doxid7     },
+	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
+	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
+	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
+	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
+
+	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
+	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
+	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
+	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
+	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
+
+	{ MPCG_STATE_XID7INITF,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
+	{ MPCG_STATE_XID7INITF,	MPCG_EVENT_XID7DONE,	mpc_action_go_ready   },
+};
+
+static int mpcg_fsm_len = ARRAY_SIZE(mpcg_fsm);
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
+{
+	struct net_device *dev = arg;
+	struct ctcm_priv *priv = NULL;
+	struct mpc_group *grp = NULL;
+
+	if (dev == NULL) {
+		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	grp = priv->mpcg;
+	if (grp == NULL) {
+		printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	fsm_deltimer(&grp->timer);
+
+	if (grp->saved_xid2->xid2_flag2 == 0x40) {
+		priv->xid->xid2_flag2 = 0x00;
+		if (grp->estconnfunc) {
+			grp->estconnfunc(grp->port_num, 1,
+					grp->group_max_buflen);
+			grp->estconnfunc = NULL;
+		} else if (grp->allochanfunc)
+			grp->send_qllc_disc = 1;
+					goto done;
+	}
+
+	grp->port_persist = 1;
+	grp->out_of_sequence = 0;
+	grp->estconn_called = 0;
+
+	tasklet_hi_schedule(&grp->mpc_tasklet2);
+
+	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
+	return;
+
+done:
+	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+
+
+	ctcm_pr_info("ctcmpc: %s()failure occurred\n", __FUNCTION__);
+}
+
+/*
+ * helper of ctcm_init_netdevice
+ * CTCM_PROTO_MPC only
+ */
+void mpc_group_ready(unsigned long adev)
+{
+	struct net_device *dev = (struct net_device *)adev;
+	struct ctcm_priv *priv = NULL;
+	struct mpc_group  *grp = NULL;
+	struct channel *ch = NULL;
+
+
+	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	grp = priv->mpcg;
+	if (grp == NULL) {
+		printk(KERN_INFO "ctcmpc:%s() grp=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	printk(KERN_NOTICE "ctcmpc: %s GROUP TRANSITIONED TO READY"
+	       "  maxbuf:%d\n",
+	       dev->name, grp->group_max_buflen);
+
+	fsm_newstate(grp->fsm, MPCG_STATE_READY);
+
+	/* Put up a read on the channel */
+	ch = priv->channel[READ];
+	ch->pdu_seq = 0;
+	if (do_debug_data)
+		ctcm_pr_debug("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
+			__FUNCTION__, ch->pdu_seq);
+
+	ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch);
+	/* Put the write channel in idle state */
+	ch = priv->channel[WRITE];
+	if (ch->collect_len > 0) {
+		spin_lock(&ch->collect_lock);
+		ctcm_purge_skb_queue(&ch->collect_queue);
+		ch->collect_len = 0;
+		spin_unlock(&ch->collect_lock);
+	}
+	ctcm_chx_txidle(ch->fsm, CTC_EVENT_START, ch);
+
+	ctcm_clear_busy(dev);
+
+	if (grp->estconnfunc) {
+		grp->estconnfunc(grp->port_num, 0,
+				    grp->group_max_buflen);
+		grp->estconnfunc = NULL;
+	} else
+		if (grp->allochanfunc)
+		grp->allochanfunc(grp->port_num,
+				     grp->group_max_buflen);
+
+	grp->send_qllc_disc = 1;
+	grp->changed_side = 0;
+
+	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
+	return;
+
+}
+
+/*
+ * Increment the MPC Group Active Channel Counts
+ * helper of dev_action (called from channel fsm)
+ */
+int mpc_channel_action(struct channel *ch, int direction, int action)
+{
+	struct net_device  *dev     = ch->netdev;
+	struct ctcm_priv    *priv;
+	struct mpc_group   *grp  = NULL;
+	int	    rc = 0;
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
+			__FUNCTION__, ch, ch->id);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "ctcmpc_channel_action %i dev=NULL\n",
+		       action);
+		rc = 1;
+					goto done;
+	}
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO
+		       "ctcmpc_channel_action%i priv=NULL, dev=%s\n",
+		       action, dev->name);
+		rc = 2;
+					goto done;
+	}
+
+	grp = priv->mpcg;
+
+	if (grp == NULL) {
+		printk(KERN_INFO "ctcmpc: %s()%i mpcgroup=NULL, dev=%s\n",
+		       __FUNCTION__, action, dev->name);
+		rc = 3;
+					goto done;
+	}
+
+	ctcm_pr_info(
+		      "ctcmpc: %s() %i(): Grp:%s total_channel_paths=%i "
+		      "active_channels read=%i, write=%i\n",
+		      __FUNCTION__,
+		      action,
+		      fsm_getstate_str(grp->fsm),
+		      grp->num_channel_paths,
+		      grp->active_channels[READ],
+		      grp->active_channels[WRITE]);
+
+	if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) {
+		grp->num_channel_paths++;
+		grp->active_channels[direction]++;
+		grp->outstanding_xid2++;
+		ch->in_mpcgroup = 1;
+
+		if (ch->xid_skb != NULL)
+			dev_kfree_skb_any(ch->xid_skb);
+
+		ch->xid_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
+					GFP_ATOMIC | GFP_DMA);
+		if (ch->xid_skb == NULL) {
+			printk(KERN_INFO "ctcmpc: %s()"
+			       "Couldn't alloc ch xid_skb\n", __FUNCTION__);
+			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+			return 1;
+		}
+		ch->xid_skb_data = ch->xid_skb->data;
+		ch->xid_th = (struct th_header *)ch->xid_skb->data;
+		skb_put(ch->xid_skb, TH_HEADER_LENGTH);
+		ch->xid = (struct xid2 *)skb_tail_pointer(ch->xid_skb);
+		skb_put(ch->xid_skb, XID2_LENGTH);
+		ch->xid_id = skb_tail_pointer(ch->xid_skb);
+		ch->xid_skb->data = ch->xid_skb_data;
+		skb_reset_tail_pointer(ch->xid_skb);
+		ch->xid_skb->len = 0;
+
+		memcpy(skb_put(ch->xid_skb, grp->xid_skb->len),
+				grp->xid_skb->data,
+				grp->xid_skb->len);
+
+		ch->xid->xid2_dlc_type = ((CHANNEL_DIRECTION(ch->flags) == READ)
+				? XID2_READ_SIDE : XID2_WRITE_SIDE);
+
+		if (CHANNEL_DIRECTION(ch->flags) == WRITE)
+			ch->xid->xid2_buf_len = 0x00;
+
+		ch->xid_skb->data = ch->xid_skb_data;
+		skb_reset_tail_pointer(ch->xid_skb);
+		ch->xid_skb->len = 0;
+
+		fsm_newstate(ch->fsm, CH_XID0_PENDING);
+
+		if ((grp->active_channels[READ]  > 0) &&
+		    (grp->active_channels[WRITE] > 0) &&
+			(fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
+			fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
+			printk(KERN_NOTICE "ctcmpc: %s MPC GROUP "
+					"CHANNELS ACTIVE\n", dev->name);
+		}
+	} else if ((action == MPC_CHANNEL_REMOVE) &&
+			(ch->in_mpcgroup == 1)) {
+		ch->in_mpcgroup = 0;
+		grp->num_channel_paths--;
+		grp->active_channels[direction]--;
+
+		if (ch->xid_skb != NULL)
+			dev_kfree_skb_any(ch->xid_skb);
+		ch->xid_skb = NULL;
+
+		if (grp->channels_terminating)
+					goto done;
+
+		if (((grp->active_channels[READ] == 0) &&
+					(grp->active_channels[WRITE] > 0))
+			|| ((grp->active_channels[WRITE] == 0) &&
+					(grp->active_channels[READ] > 0)))
+			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+	}
+
+done:
+
+	if (do_debug) {
+		ctcm_pr_debug(
+		       "ctcmpc: %s() %i Grp:%s ttl_chan_paths=%i "
+		       "active_chans read=%i, write=%i\n",
+		       __FUNCTION__,
+		       action,
+		       fsm_getstate_str(grp->fsm),
+		       grp->num_channel_paths,
+		       grp->active_channels[READ],
+		       grp->active_channels[WRITE]);
+
+		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
+				__FUNCTION__, ch, ch->id);
+	}
+	return rc;
+
+}
+
+/**
+ * Unpack a just received skb and hand it over to
+ * upper layers.
+ * special MPC version of unpack_skb.
+ *
+ * ch		The channel where this skb has been received.
+ * pskb		The received skb.
+ */
+static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
+{
+	struct net_device *dev	= ch->netdev;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp = priv->mpcg;
+	struct pdu *curr_pdu;
+	struct mpcg_info *mpcginfo;
+	struct th_header *header = NULL;
+	struct th_sweep *sweep = NULL;
+	int pdu_last_seen = 0;
+	__u32 new_len;
+	struct sk_buff *skb;
+	int skblen;
+	int sendrc = 0;
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s() %s cp:%i ch:%s\n",
+		       __FUNCTION__, dev->name, smp_processor_id(), ch->id);
+
+	header = (struct th_header *)pskb->data;
+	if ((header->th_seg == 0) &&
+		(header->th_ch_flag == 0) &&
+		(header->th_blk_flag == 0) &&
+		(header->th_seq_num == 0))
+		/* nothing for us */	goto done;
+
+	if (do_debug_data) {
+		ctcm_pr_debug("ctcmpc: %s() th_header\n", __FUNCTION__);
+		ctcmpc_dumpit((char *)header, TH_HEADER_LENGTH);
+		ctcm_pr_debug("ctcmpc: %s() pskb len: %04x \n",
+		       __FUNCTION__, pskb->len);
+	}
+
+	pskb->dev = dev;
+	pskb->ip_summed = CHECKSUM_UNNECESSARY;
+	skb_pull(pskb, TH_HEADER_LENGTH);
+
+	if (likely(header->th_ch_flag == TH_HAS_PDU)) {
+		if (do_debug_data)
+			ctcm_pr_debug("ctcmpc: %s() came into th_has_pdu\n",
+			       __FUNCTION__);
+		if ((fsm_getstate(grp->fsm) == MPCG_STATE_FLOWC) ||
+		   ((fsm_getstate(grp->fsm) == MPCG_STATE_READY) &&
+		    (header->th_seq_num != ch->th_seq_num + 1) &&
+		    (ch->th_seq_num != 0))) {
+			/* This is NOT the next segment		*
+			 * we are not the correct race winner	*
+			 * go away and let someone else win	*
+			 * BUT..this only applies if xid negot	*
+			 * is done				*
+			*/
+			grp->out_of_sequence += 1;
+			__skb_push(pskb, TH_HEADER_LENGTH);
+			skb_queue_tail(&ch->io_queue, pskb);
+			if (do_debug_data)
+				ctcm_pr_debug("ctcmpc: %s() th_seq_num "
+				       "expect:%08x got:%08x\n", __FUNCTION__,
+				       ch->th_seq_num + 1, header->th_seq_num);
+
+			return;
+		}
+		grp->out_of_sequence = 0;
+		ch->th_seq_num = header->th_seq_num;
+
+		if (do_debug_data)
+			ctcm_pr_debug("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
+			       __FUNCTION__, ch->th_seq_num);
+
+		if (unlikely(fsm_getstate(grp->fsm) != MPCG_STATE_READY))
+					goto done;
+		pdu_last_seen = 0;
+		while ((pskb->len > 0) && !pdu_last_seen) {
+			curr_pdu = (struct pdu *)pskb->data;
+			if (do_debug_data) {
+				ctcm_pr_debug("ctcm: %s() pdu_header\n",
+				       __FUNCTION__);
+				ctcmpc_dumpit((char *)pskb->data,
+						PDU_HEADER_LENGTH);
+				ctcm_pr_debug("ctcm: %s() pskb len: %04x \n",
+				       __FUNCTION__, pskb->len);
+			}
+			skb_pull(pskb, PDU_HEADER_LENGTH);
+
+			if (curr_pdu->pdu_flag & PDU_LAST)
+				pdu_last_seen = 1;
+			if (curr_pdu->pdu_flag & PDU_CNTL)
+				pskb->protocol = htons(ETH_P_SNAP);
+			else
+				pskb->protocol = htons(ETH_P_SNA_DIX);
+
+			if ((pskb->len <= 0) || (pskb->len > ch->max_bufsize)) {
+				printk(KERN_INFO
+				       "%s Illegal packet size %d "
+				       "received "
+				       "dropping\n", dev->name,
+				       pskb->len);
+				priv->stats.rx_dropped++;
+				priv->stats.rx_length_errors++;
+					goto done;
+			}
+			skb_reset_mac_header(pskb);
+			new_len = curr_pdu->pdu_offset;
+			if (do_debug_data)
+				ctcm_pr_debug("ctcmpc: %s() new_len: %04x \n",
+				       __FUNCTION__, new_len);
+			if ((new_len == 0) || (new_len > pskb->len)) {
+				/* should never happen		    */
+				/* pskb len must be hosed...bail out */
+				printk(KERN_INFO
+				       "ctcmpc: %s(): invalid pdu"
+				       " offset of %04x - data may be"
+				       "lost\n", __FUNCTION__, new_len);
+						goto done;
+			}
+			skb = __dev_alloc_skb(new_len+4, GFP_ATOMIC);
+
+			if (!skb) {
+				printk(KERN_INFO
+				       "ctcm: %s Out of memory in "
+				       "%s()- request-len:%04x \n",
+				       dev->name,
+				       __FUNCTION__,
+				       new_len+4);
+				priv->stats.rx_dropped++;
+				fsm_event(grp->fsm,
+					  MPCG_EVENT_INOP, dev);
+						goto done;
+			}
+
+			memcpy(skb_put(skb, new_len),
+					pskb->data, new_len);
+
+			skb_reset_mac_header(skb);
+			skb->dev = pskb->dev;
+			skb->protocol = pskb->protocol;
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			*((__u32 *) skb_push(skb, 4)) = ch->pdu_seq;
+			ch->pdu_seq++;
+
+			if (do_debug_data)
+				ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
+				       __FUNCTION__, ch->pdu_seq);
+
+			ctcm_pr_debug("ctcm: %s() skb:%0lx "
+				"skb len: %d \n", __FUNCTION__,
+			       (unsigned long)skb, skb->len);
+			if (do_debug_data) {
+				ctcm_pr_debug("ctcmpc: %s() up to 32 bytes"
+					       " of pdu_data sent\n",
+					       __FUNCTION__);
+				ctcmpc_dump32((char *)skb->data, skb->len);
+			}
+
+			skblen = skb->len;
+			sendrc = netif_rx(skb);
+			priv->stats.rx_packets++;
+			priv->stats.rx_bytes += skblen;
+			skb_pull(pskb, new_len); /* point to next PDU */
+		}
+	} else {
+		mpcginfo = (struct mpcg_info *)
+				kmalloc(sizeof(struct mpcg_info), gfp_type());
+		if (mpcginfo == NULL)
+					goto done;
+
+		mpcginfo->ch = ch;
+		mpcginfo->th = header;
+		mpcginfo->skb = pskb;
+		ctcm_pr_debug("ctcmpc: %s() Not PDU - may be control pkt\n",
+			       __FUNCTION__);
+		/*  it's a sweep?   */
+		sweep = (struct th_sweep *)pskb->data;
+		mpcginfo->sweep = sweep;
+		if (header->th_ch_flag == TH_SWEEP_REQ)
+			mpc_rcvd_sweep_req(mpcginfo);
+		else if (header->th_ch_flag == TH_SWEEP_RESP)
+			mpc_rcvd_sweep_resp(mpcginfo);
+		else if (header->th_blk_flag == TH_DATA_IS_XID) {
+			struct xid2 *thisxid = (struct xid2 *)pskb->data;
+			skb_pull(pskb, XID2_LENGTH);
+			mpcginfo->xid = thisxid;
+			fsm_event(grp->fsm, MPCG_EVENT_XID2, mpcginfo);
+		} else if (header->th_blk_flag == TH_DISCONTACT)
+			fsm_event(grp->fsm, MPCG_EVENT_DISCONC, mpcginfo);
+		else if (header->th_seq_num != 0) {
+			printk(KERN_INFO "%s unexpected packet"
+					" expected control pkt\n", dev->name);
+			priv->stats.rx_dropped++;
+			/* mpcginfo only used for non-data transfers */
+			kfree(mpcginfo);
+			if (do_debug_data)
+				ctcmpc_dump_skb(pskb, -8);
+		}
+	}
+done:
+
+	dev_kfree_skb_any(pskb);
+	if (sendrc == NET_RX_DROP) {
+		printk(KERN_WARNING "%s %s() NETWORK BACKLOG EXCEEDED"
+		       " - PACKET DROPPED\n", dev->name, __FUNCTION__);
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+	}
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
+				dev->name, __FUNCTION__, ch, ch->id);
+}
+
+/**
+ * tasklet helper for mpc's skb unpacking.
+ *
+ * ch		The channel to work on.
+ * Allow flow control back pressure to occur here.
+ * Throttling back channel can result in excessive
+ * channel inactivity and system deact of channel
+ */
+void ctcmpc_bh(unsigned long thischan)
+{
+	struct channel	  *ch	    = (struct channel *)thischan;
+	struct sk_buff	  *skb;
+	struct net_device *dev	    = ch->netdev;
+	struct ctcm_priv  *priv  = dev->priv;
+	struct mpc_group  *grp   = priv->mpcg;
+
+	if (do_debug)
+		ctcm_pr_debug("%s cp:%i enter:  %s() %s\n",
+		       dev->name, smp_processor_id(), __FUNCTION__, ch->id);
+	/* caller has requested driver to throttle back */
+	while ((fsm_getstate(grp->fsm) != MPCG_STATE_FLOWC) &&
+			(skb = skb_dequeue(&ch->io_queue))) {
+		ctcmpc_unpack_skb(ch, skb);
+		if (grp->out_of_sequence > 20) {
+			/* assume data loss has occurred if */
+			/* missing seq_num for extended     */
+			/* period of time		    */
+			grp->out_of_sequence = 0;
+			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+			break;
+		}
+		if (skb == skb_peek(&ch->io_queue))
+			break;
+	}
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
+			dev->name, __FUNCTION__, ch,  ch->id);
+	return;
+}
+
+/*
+ *  MPC Group Initializations
+ */
+struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
+{
+	struct mpc_group *grp;
+
+	CTCM_DBF_TEXT(MPC_SETUP, 3, __FUNCTION__);
+
+	grp = kzalloc(sizeof(struct mpc_group), GFP_KERNEL);
+	if (grp == NULL)
+		return NULL;
+
+	grp->fsm =
+		init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
+				 MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
+				 mpcg_fsm_len, GFP_KERNEL);
+	if (grp->fsm == NULL) {
+		kfree(grp);
+		return NULL;
+	}
+
+	fsm_newstate(grp->fsm, MPCG_STATE_RESET);
+	fsm_settimer(grp->fsm, &grp->timer);
+
+	grp->xid_skb =
+		 __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
+	if (grp->xid_skb == NULL) {
+		printk(KERN_INFO "Couldn't alloc MPCgroup xid_skb\n");
+		kfree_fsm(grp->fsm);
+		kfree(grp);
+		return NULL;
+	}
+	/*  base xid for all channels in group  */
+	grp->xid_skb_data = grp->xid_skb->data;
+	grp->xid_th = (struct th_header *)grp->xid_skb->data;
+	memcpy(skb_put(grp->xid_skb, TH_HEADER_LENGTH),
+			&thnorm, TH_HEADER_LENGTH);
+
+	grp->xid = (struct xid2 *) skb_tail_pointer(grp->xid_skb);
+	memcpy(skb_put(grp->xid_skb, XID2_LENGTH), &init_xid, XID2_LENGTH);
+	grp->xid->xid2_adj_id = jiffies | 0xfff00000;
+	grp->xid->xid2_sender_id = jiffies;
+
+	grp->xid_id = skb_tail_pointer(grp->xid_skb);
+	memcpy(skb_put(grp->xid_skb, 4), "VTAM", 4);
+
+	grp->rcvd_xid_skb =
+		__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
+	if (grp->rcvd_xid_skb == NULL) {
+		printk(KERN_INFO "Couldn't alloc MPCgroup rcvd_xid_skb\n");
+		kfree_fsm(grp->fsm);
+		dev_kfree_skb(grp->xid_skb);
+		kfree(grp);
+		return NULL;
+	}
+	grp->rcvd_xid_data = grp->rcvd_xid_skb->data;
+	grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
+	memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH),
+			&thnorm, TH_HEADER_LENGTH);
+	grp->saved_xid2 = NULL;
+	priv->xid = grp->xid;
+	priv->mpcg = grp;
+	return grp;
+}
+
+/*
+ * The MPC Group Station FSM
+ */
+
+/*
+ * MPC Group Station FSM actions
+ * CTCM_PROTO_MPC only
+ */
+
+/**
+ * NOP action for statemachines
+ */
+static void mpc_action_nop(fsm_instance *fi, int event, void *arg)
+{
+}
+
+/*
+ * invoked when the device transitions to dev_stopped
+ * MPC will stop each individual channel if a single XID failure
+ * occurs, or will intitiate all channels be stopped if a GROUP
+ * level failure occurs.
+ */
+static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
+{
+	struct net_device  *dev = arg;
+	struct ctcm_priv    *priv;
+	struct mpc_group *grp;
+	int rc = 0;
+	struct channel *wch, *rch;
+
+	if (dev == NULL) {
+		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
+
+	priv  = dev->priv;
+	grp =  priv->mpcg;
+	grp->flow_off_called = 0;
+
+	fsm_deltimer(&grp->timer);
+
+	if (grp->channels_terminating)
+					goto done;
+
+	grp->channels_terminating = 1;
+
+	grp->saved_state = fsm_getstate(grp->fsm);
+	fsm_newstate(grp->fsm, MPCG_STATE_INOP);
+	if (grp->saved_state > MPCG_STATE_XID7INITF)
+		printk(KERN_NOTICE "%s:MPC GROUP INOPERATIVE\n", dev->name);
+	if ((grp->saved_state != MPCG_STATE_RESET) ||
+		/* dealloc_channel has been called */
+		((grp->saved_state == MPCG_STATE_RESET) &&
+				(grp->port_persist == 0)))
+		fsm_deltimer(&priv->restart_timer);
+
+	wch = priv->channel[WRITE];
+	rch = priv->channel[READ];
+
+	switch (grp->saved_state) {
+	case MPCG_STATE_RESET:
+	case MPCG_STATE_INOP:
+	case MPCG_STATE_XID2INITW:
+	case MPCG_STATE_XID0IOWAIT:
+	case MPCG_STATE_XID2INITX:
+	case MPCG_STATE_XID7INITW:
+	case MPCG_STATE_XID7INITX:
+	case MPCG_STATE_XID0IOWAIX:
+	case MPCG_STATE_XID7INITI:
+	case MPCG_STATE_XID7INITZ:
+	case MPCG_STATE_XID7INITF:
+		break;
+	case MPCG_STATE_FLOWC:
+	case MPCG_STATE_READY:
+	default:
+		tasklet_hi_schedule(&wch->ch_disc_tasklet);
+	}
+
+	grp->xid2_tgnum = 0;
+	grp->group_max_buflen = 0;  /*min of all received */
+	grp->outstanding_xid2 = 0;
+	grp->outstanding_xid7 = 0;
+	grp->outstanding_xid7_p2 = 0;
+	grp->saved_xid2 = NULL;
+	grp->xidnogood = 0;
+	grp->changed_side = 0;
+
+	grp->rcvd_xid_skb->data = grp->rcvd_xid_data;
+	skb_reset_tail_pointer(grp->rcvd_xid_skb);
+	grp->rcvd_xid_skb->len = 0;
+	grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
+	memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH), &thnorm,
+	       TH_HEADER_LENGTH);
+
+	if (grp->send_qllc_disc == 1) {
+		grp->send_qllc_disc = 0;
+		rc = mpc_send_qllc_discontact(dev);
+	}
+
+	/* DO NOT issue DEV_EVENT_STOP directly out of this code */
+	/* This can result in INOP of VTAM PU due to halting of  */
+	/* outstanding IO which causes a sense to be returned	 */
+	/* Only about 3 senses are allowed and then IOS/VTAM will*/
+	/* ebcome unreachable without manual intervention	 */
+	if ((grp->port_persist == 1)	|| (grp->alloc_called)) {
+		grp->alloc_called = 0;
+		fsm_deltimer(&priv->restart_timer);
+		fsm_addtimer(&priv->restart_timer,
+			     500,
+			     DEV_EVENT_RESTART,
+			     dev);
+		fsm_newstate(grp->fsm, MPCG_STATE_RESET);
+		if (grp->saved_state > MPCG_STATE_XID7INITF)
+			printk(KERN_NOTICE "%s:MPC GROUP RECOVERY SCHEDULED\n",
+			       dev->name);
+	} else {
+		fsm_deltimer(&priv->restart_timer);
+		fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_STOP, dev);
+		fsm_newstate(grp->fsm, MPCG_STATE_RESET);
+		printk(KERN_NOTICE "%s:MPC GROUP RECOVERY NOT ATTEMPTED\n",
+		       dev->name);
+	}
+
+done:
+	ctcm_pr_debug("ctcmpc exit:%s  %s()\n", dev->name, __FUNCTION__);
+	return;
+}
+
+/**
+ * Handle mpc group  action timeout.
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ *
+ * fi		An instance of an mpc_group fsm.
+ * event	The event, just happened.
+ * arg		Generic pointer, casted from net_device * upon call.
+ */
+static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
+{
+	struct net_device *dev = arg;
+	struct ctcm_priv *priv;
+	struct mpc_group *grp;
+	struct channel *wch;
+	struct channel *rch;
+
+	CTCM_DBF_TEXT(MPC_TRACE, 6, __FUNCTION__);
+
+	if (dev == NULL) {
+		CTCM_DBF_TEXT_(MPC_ERROR, 4, "%s: dev=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	priv = dev->priv;
+	grp = priv->mpcg;
+	wch = priv->channel[WRITE];
+	rch = priv->channel[READ];
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_XID2INITW:
+		/* Unless there is outstanding IO on the  */
+		/* channel just return and wait for ATTN  */
+		/* interrupt to begin XID negotiations	  */
+		if ((fsm_getstate(rch->fsm) == CH_XID0_PENDING) &&
+		   (fsm_getstate(wch->fsm) == CH_XID0_PENDING))
+			break;
+	default:
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+	}
+
+	CTCM_DBF_TEXT_(MPC_TRACE, 6, "%s: dev=%s exit",
+					__FUNCTION__, dev->name);
+	return;
+}
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+void mpc_action_discontact(fsm_instance *fi, int event, void *arg)
+{
+	struct mpcg_info   *mpcginfo   = arg;
+	struct channel	   *ch	       = mpcginfo->ch;
+	struct net_device  *dev        = ch->netdev;
+	struct ctcm_priv   *priv    = dev->priv;
+	struct mpc_group   *grp     = priv->mpcg;
+
+	if (ch == NULL)	{
+		printk(KERN_INFO "%s() ch=NULL\n", __FUNCTION__);
+		return;
+	}
+	if (ch->netdev == NULL)	{
+		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
+		return;
+	}
+
+	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
+
+	grp->send_qllc_disc = 1;
+	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+
+	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
+	return;
+}
+
+/*
+ * MPC Group Station - not part of FSM
+ * CTCM_PROTO_MPC only
+ * called from add_channel in ctcm_main.c
+ */
+void mpc_action_send_discontact(unsigned long thischan)
+{
+	struct channel	   *ch;
+	struct net_device  *dev;
+	struct ctcm_priv    *priv;
+	struct mpc_group   *grp;
+	int rc = 0;
+	unsigned long	  saveflags;
+
+	ch = (struct channel *)thischan;
+	dev = ch->netdev;
+	priv = dev->priv;
+	grp = priv->mpcg;
+
+	ctcm_pr_info("ctcmpc: %s cp:%i enter: %s() GrpState:%s ChState:%s\n",
+		       dev->name,
+		       smp_processor_id(),
+		       __FUNCTION__,
+		       fsm_getstate_str(grp->fsm),
+		       fsm_getstate_str(ch->fsm));
+	saveflags = 0;	/* avoids compiler warning with
+			   spin_unlock_irqrestore */
+
+	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+	rc = ccw_device_start(ch->cdev, &ch->ccw[15],
+					(unsigned long)ch, 0xff, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+
+	if (rc != 0) {
+		ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
+			       __FUNCTION__,
+			       ch->id);
+		ctcm_ccw_check_rc(ch, rc, "send discontact");
+		/* Not checking return code value here */
+		/* Making best effort to notify partner*/
+		/* that MPC Group is going down        */
+	}
+
+	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
+	return;
+}
+
+
+/*
+ * helper function of mpc FSM
+ * CTCM_PROTO_MPC only
+ * mpc_action_rcvd_xid7
+*/
+static int mpc_validate_xid(struct mpcg_info *mpcginfo)
+{
+	struct channel	   *ch	    = mpcginfo->ch;
+	struct net_device  *dev     = ch->netdev;
+	struct ctcm_priv   *priv = dev->priv;
+	struct mpc_group   *grp  = priv->mpcg;
+	struct xid2	   *xid     = mpcginfo->xid;
+	int	failed	= 0;
+	int	rc	= 0;
+	__u64	our_id, their_id = 0;
+	int	len;
+
+	len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+
+	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
+
+	if (mpcginfo->xid == NULL) {
+		printk(KERN_INFO "%s() xid=NULL\n", __FUNCTION__);
+		rc = 1;
+					goto done;
+	}
+
+	ctcm_pr_debug("ctcmpc :  %s  xid received()\n", __FUNCTION__);
+	ctcmpc_dumpit((char *)mpcginfo->xid, XID2_LENGTH);
+
+	/*the received direction should be the opposite of ours  */
+	if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE :
+				XID2_READ_SIDE) != xid->xid2_dlc_type) {
+		failed = 1;
+		printk(KERN_INFO "ctcmpc:%s() XID REJECTED - READ-WRITE CH "
+			"Pairing Invalid \n", __FUNCTION__);
+	}
+
+	if (xid->xid2_dlc_type == XID2_READ_SIDE) {
+		ctcm_pr_debug("ctcmpc: %s(): grpmaxbuf:%d xid2buflen:%d\n",
+				__FUNCTION__, grp->group_max_buflen,
+				xid->xid2_buf_len);
+
+		if (grp->group_max_buflen == 0 ||
+			grp->group_max_buflen > xid->xid2_buf_len - len)
+			grp->group_max_buflen = xid->xid2_buf_len - len;
+	}
+
+
+	if (grp->saved_xid2 == NULL)	{
+		grp->saved_xid2 =
+			(struct xid2 *)skb_tail_pointer(grp->rcvd_xid_skb);
+
+		memcpy(skb_put(grp->rcvd_xid_skb,
+					XID2_LENGTH), xid, XID2_LENGTH);
+		grp->rcvd_xid_skb->data = grp->rcvd_xid_data;
+
+		skb_reset_tail_pointer(grp->rcvd_xid_skb);
+		grp->rcvd_xid_skb->len = 0;
+
+		/* convert two 32 bit numbers into 1 64 bit for id compare */
+		our_id = (__u64)priv->xid->xid2_adj_id;
+		our_id = our_id << 32;
+		our_id = our_id + priv->xid->xid2_sender_id;
+		their_id = (__u64)xid->xid2_adj_id;
+		their_id = their_id << 32;
+		their_id = their_id + xid->xid2_sender_id;
+		/* lower id assume the xside role */
+		if (our_id < their_id) {
+			grp->roll = XSIDE;
+			ctcm_pr_debug("ctcmpc :%s() WE HAVE LOW ID-"
+				       "TAKE XSIDE\n", __FUNCTION__);
+		} else {
+			grp->roll = YSIDE;
+			ctcm_pr_debug("ctcmpc :%s() WE HAVE HIGH ID-"
+				       "TAKE YSIDE\n", __FUNCTION__);
+		}
+
+	} else {
+		if (xid->xid2_flag4 != grp->saved_xid2->xid2_flag4) {
+			failed = 1;
+			printk(KERN_INFO "%s XID REJECTED - XID Flag Byte4\n",
+			       __FUNCTION__);
+		}
+		if (xid->xid2_flag2 == 0x40) {
+			failed = 1;
+			printk(KERN_INFO "%s XID REJECTED - XID NOGOOD\n",
+			       __FUNCTION__);
+		}
+		if (xid->xid2_adj_id != grp->saved_xid2->xid2_adj_id) {
+			failed = 1;
+			printk(KERN_INFO "%s XID REJECTED - "
+				"Adjacent Station ID Mismatch\n",
+				__FUNCTION__);
+		}
+		if (xid->xid2_sender_id != grp->saved_xid2->xid2_sender_id) {
+			failed = 1;
+			printk(KERN_INFO "%s XID REJECTED - "
+				"Sender Address Mismatch\n", __FUNCTION__);
+
+		}
+	}
+
+	if (failed) {
+		ctcm_pr_info("ctcmpc	   :  %s() failed\n", __FUNCTION__);
+		priv->xid->xid2_flag2 = 0x40;
+		grp->saved_xid2->xid2_flag2 = 0x40;
+		rc = 1;
+	}
+
+done:
+
+	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
+	return rc;
+}
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
+{
+	struct channel *ch = arg;
+	struct ctcm_priv *priv;
+	struct mpc_group *grp = NULL;
+	struct net_device *dev = NULL;
+	int rc = 0;
+	int gotlock = 0;
+	unsigned long saveflags = 0;	/* avoids compiler warning with
+			   spin_unlock_irqrestore */
+
+	if (ch == NULL)	{
+		printk(KERN_INFO "%s ch=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+			__FUNCTION__, smp_processor_id(), ch, ch->id);
+
+	dev = ch->netdev;
+	if (dev == NULL) {
+		printk(KERN_INFO "%s dev=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO "%s priv=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	grp = priv->mpcg;
+	if (grp == NULL) {
+		printk(KERN_INFO "%s grp=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	if (ctcm_checkalloc_buffer(ch))
+					goto done;
+
+	/* skb data-buffer referencing: */
+
+	ch->trans_skb->data = ch->trans_skb_data;
+	skb_reset_tail_pointer(ch->trans_skb);
+	ch->trans_skb->len = 0;
+	/* result of the previous 3 statements is NOT always
+	 * already set after ctcm_checkalloc_buffer
+	 * because of possible reuse of the trans_skb
+	 */
+	memset(ch->trans_skb->data, 0, 16);
+	ch->rcvd_xid_th =  (struct th_header *)ch->trans_skb_data;
+	/* check is main purpose here: */
+	skb_put(ch->trans_skb, TH_HEADER_LENGTH);
+	ch->rcvd_xid = (struct xid2 *)skb_tail_pointer(ch->trans_skb);
+	/* check is main purpose here: */
+	skb_put(ch->trans_skb, XID2_LENGTH);
+	ch->rcvd_xid_id = skb_tail_pointer(ch->trans_skb);
+	/* cleanup back to startpoint */
+	ch->trans_skb->data = ch->trans_skb_data;
+	skb_reset_tail_pointer(ch->trans_skb);
+	ch->trans_skb->len = 0;
+
+	/* non-checking rewrite of above skb data-buffer referencing: */
+	/*
+	memset(ch->trans_skb->data, 0, 16);
+	ch->rcvd_xid_th =  (struct th_header *)ch->trans_skb_data;
+	ch->rcvd_xid = (struct xid2 *)(ch->trans_skb_data + TH_HEADER_LENGTH);
+	ch->rcvd_xid_id = ch->trans_skb_data + TH_HEADER_LENGTH + XID2_LENGTH;
+	 */
+
+	ch->ccw[8].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+	ch->ccw[8].count	= 0;
+	ch->ccw[8].cda		= 0x00;
+
+	if (side == XSIDE) {
+		/* mpc_action_xside_xid */
+		if (ch->xid_th == NULL) {
+			printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
+					goto done;
+		}
+		ch->ccw[9].cmd_code	= CCW_CMD_WRITE;
+		ch->ccw[9].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[9].count	= TH_HEADER_LENGTH;
+		ch->ccw[9].cda		= virt_to_phys(ch->xid_th);
+
+		if (ch->xid == NULL) {
+			printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
+					goto done;
+		}
+
+		ch->ccw[10].cmd_code	= CCW_CMD_WRITE;
+		ch->ccw[10].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[10].count	= XID2_LENGTH;
+		ch->ccw[10].cda		= virt_to_phys(ch->xid);
+
+		ch->ccw[11].cmd_code	= CCW_CMD_READ;
+		ch->ccw[11].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[11].count	= TH_HEADER_LENGTH;
+		ch->ccw[11].cda		= virt_to_phys(ch->rcvd_xid_th);
+
+		ch->ccw[12].cmd_code	= CCW_CMD_READ;
+		ch->ccw[12].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[12].count	= XID2_LENGTH;
+		ch->ccw[12].cda		= virt_to_phys(ch->rcvd_xid);
+
+		ch->ccw[13].cmd_code	= CCW_CMD_READ;
+		ch->ccw[13].cda		= virt_to_phys(ch->rcvd_xid_id);
+
+	} else { /* side == YSIDE : mpc_action_yside_xid */
+		ch->ccw[9].cmd_code	= CCW_CMD_READ;
+		ch->ccw[9].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[9].count	= TH_HEADER_LENGTH;
+		ch->ccw[9].cda		= virt_to_phys(ch->rcvd_xid_th);
+
+		ch->ccw[10].cmd_code	= CCW_CMD_READ;
+		ch->ccw[10].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[10].count	= XID2_LENGTH;
+		ch->ccw[10].cda		= virt_to_phys(ch->rcvd_xid);
+
+		if (ch->xid_th == NULL)	{
+			printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
+					goto done;
+		}
+		ch->ccw[11].cmd_code	= CCW_CMD_WRITE;
+		ch->ccw[11].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[11].count	= TH_HEADER_LENGTH;
+		ch->ccw[11].cda		= virt_to_phys(ch->xid_th);
+
+		if (ch->xid == NULL) {
+			printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
+					goto done;
+		}
+		ch->ccw[12].cmd_code	= CCW_CMD_WRITE;
+		ch->ccw[12].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[12].count	= XID2_LENGTH;
+		ch->ccw[12].cda		= virt_to_phys(ch->xid);
+
+		if (ch->xid_id == NULL)	{
+			printk(KERN_INFO "%s ch->xid_id=NULL\n", __FUNCTION__);
+					goto done;
+		}
+		ch->ccw[13].cmd_code	= CCW_CMD_WRITE;
+		ch->ccw[13].cda		= virt_to_phys(ch->xid_id);
+
+	}
+	ch->ccw[13].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
+	ch->ccw[13].count	= 4;
+
+	ch->ccw[14].cmd_code	= CCW_CMD_NOOP;
+	ch->ccw[14].flags	= CCW_FLAG_SLI;
+	ch->ccw[14].count	= 0;
+	ch->ccw[14].cda		= 0;
+
+	if (do_debug_ccw)
+		ctcmpc_dumpit((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
+
+	ctcmpc_dumpit((char *)ch->xid_th, TH_HEADER_LENGTH);
+	ctcmpc_dumpit((char *)ch->xid, XID2_LENGTH);
+	ctcmpc_dumpit((char *)ch->xid_id, 4);
+	if (!in_irq()) {
+			 /* Such conditional locking is a known problem for
+			  * sparse because its static undeterministic.
+			  * Warnings should be ignored here. */
+		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+		gotlock = 1;
+	}
+
+	fsm_addtimer(&ch->timer, 5000 , CTC_EVENT_TIMER, ch);
+	rc = ccw_device_start(ch->cdev, &ch->ccw[8],
+				(unsigned long)ch, 0xff, 0);
+
+	if (gotlock)	/* see remark above about conditional locking */
+		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+
+	if (rc != 0) {
+		ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
+				__FUNCTION__, ch->id);
+		ctcm_ccw_check_rc(ch, rc,
+				(side == XSIDE) ? "x-side XID" : "y-side XID");
+	}
+
+done:
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
+				__FUNCTION__, ch, ch->id);
+	return;
+
+}
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static void mpc_action_xside_xid(fsm_instance *fsm, int event, void *arg)
+{
+	mpc_action_side_xid(fsm, arg, XSIDE);
+}
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg)
+{
+	mpc_action_side_xid(fsm, arg, YSIDE);
+}
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
+{
+	struct channel	   *ch = arg;
+	struct ctcm_priv    *priv;
+	struct mpc_group   *grp     = NULL;
+	struct net_device *dev = NULL;
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+			__FUNCTION__, smp_processor_id(), ch, ch->id);
+
+	if (ch == NULL) {
+		printk(KERN_WARNING "%s ch=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	dev = ch->netdev;
+	if (dev == NULL) {
+		printk(KERN_WARNING "%s dev=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_WARNING "%s priv=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	grp = priv->mpcg;
+	if (grp == NULL) {
+		printk(KERN_WARNING "%s grp=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	if (ch->xid == NULL) {
+		printk(KERN_WARNING "%s ch-xid=NULL\n", __FUNCTION__);
+					goto done;
+	}
+
+	fsm_newstate(ch->fsm, CH_XID0_INPROGRESS);
+
+	ch->xid->xid2_option =	XID2_0;
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_XID2INITW:
+	case MPCG_STATE_XID2INITX:
+		ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
+		break;
+	case MPCG_STATE_XID0IOWAIT:
+	case MPCG_STATE_XID0IOWAIX:
+		ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
+		break;
+	}
+
+	fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
+
+done:
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
+			__FUNCTION__, ch, ch->id);
+	return;
+
+}
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+*/
+static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
+{
+	struct net_device *dev = arg;
+	struct ctcm_priv   *priv = NULL;
+	struct mpc_group  *grp = NULL;
+	int direction;
+	int rc = 0;
+	int send = 0;
+
+	ctcm_pr_debug("ctcmpc enter:	%s() \n", __FUNCTION__);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "%s dev=NULL \n", __FUNCTION__);
+		rc = 1;
+					goto done;
+	}
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO "%s priv=NULL \n", __FUNCTION__);
+		rc = 1;
+					goto done;
+	}
+
+	grp = priv->mpcg;
+	if (grp == NULL) {
+		printk(KERN_INFO "%s grp=NULL \n", __FUNCTION__);
+		rc = 1;
+					goto done;
+	}
+
+	for (direction = READ; direction <= WRITE; direction++)	{
+		struct channel *ch = priv->channel[direction];
+		struct xid2 *thisxid = ch->xid;
+		ch->xid_skb->data = ch->xid_skb_data;
+		skb_reset_tail_pointer(ch->xid_skb);
+		ch->xid_skb->len = 0;
+		thisxid->xid2_option = XID2_7;
+		send = 0;
+
+		/* xid7 phase 1 */
+		if (grp->outstanding_xid7_p2 > 0) {
+			if (grp->roll == YSIDE) {
+				if (fsm_getstate(ch->fsm) == CH_XID7_PENDING1) {
+					fsm_newstate(ch->fsm, CH_XID7_PENDING2);
+					ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
+					memcpy(skb_put(ch->xid_skb,
+							TH_HEADER_LENGTH),
+					       &thdummy, TH_HEADER_LENGTH);
+					send = 1;
+				}
+			} else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING2) {
+					fsm_newstate(ch->fsm, CH_XID7_PENDING2);
+					ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
+					memcpy(skb_put(ch->xid_skb,
+						       TH_HEADER_LENGTH),
+					       &thnorm, TH_HEADER_LENGTH);
+					send = 1;
+			}
+		} else {
+			/* xid7 phase 2 */
+			if (grp->roll == YSIDE) {
+				if (fsm_getstate(ch->fsm) < CH_XID7_PENDING4) {
+					fsm_newstate(ch->fsm, CH_XID7_PENDING4);
+					memcpy(skb_put(ch->xid_skb,
+						       TH_HEADER_LENGTH),
+					       &thnorm, TH_HEADER_LENGTH);
+					ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
+					send = 1;
+				}
+			} else if (fsm_getstate(ch->fsm) == CH_XID7_PENDING3) {
+				fsm_newstate(ch->fsm, CH_XID7_PENDING4);
+				ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
+				memcpy(skb_put(ch->xid_skb, TH_HEADER_LENGTH),
+						&thdummy, TH_HEADER_LENGTH);
+				send = 1;
+			}
+		}
+
+		if (send)
+			fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
+	}
+
+done:
+
+	if (rc != 0)
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+
+	return;
+}
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
+{
+
+	struct mpcg_info   *mpcginfo   = arg;
+	struct channel	   *ch	       = mpcginfo->ch;
+	struct net_device  *dev        = ch->netdev;
+	struct ctcm_priv   *priv;
+	struct mpc_group   *grp;
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+			__FUNCTION__, smp_processor_id(), ch, ch->id);
+
+	priv = dev->priv;
+	grp = priv->mpcg;
+
+	ctcm_pr_debug("ctcmpc in:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
+		       __FUNCTION__, ch->id,
+		       grp->outstanding_xid2,
+		       grp->outstanding_xid7,
+		       grp->outstanding_xid7_p2);
+
+	if (fsm_getstate(ch->fsm) < CH_XID7_PENDING)
+		fsm_newstate(ch->fsm, CH_XID7_PENDING);
+
+	grp->outstanding_xid2--;
+	grp->outstanding_xid7++;
+	grp->outstanding_xid7_p2++;
+
+	/* must change state before validating xid to */
+	/* properly handle interim interrupts received*/
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_XID2INITW:
+		fsm_newstate(grp->fsm, MPCG_STATE_XID2INITX);
+		mpc_validate_xid(mpcginfo);
+		break;
+	case MPCG_STATE_XID0IOWAIT:
+		fsm_newstate(grp->fsm, MPCG_STATE_XID0IOWAIX);
+		mpc_validate_xid(mpcginfo);
+		break;
+	case MPCG_STATE_XID2INITX:
+		if (grp->outstanding_xid2 == 0) {
+			fsm_newstate(grp->fsm, MPCG_STATE_XID7INITW);
+			mpc_validate_xid(mpcginfo);
+			fsm_event(grp->fsm, MPCG_EVENT_XID2DONE, dev);
+		}
+		break;
+	case MPCG_STATE_XID0IOWAIX:
+		if (grp->outstanding_xid2 == 0) {
+			fsm_newstate(grp->fsm, MPCG_STATE_XID7INITI);
+			mpc_validate_xid(mpcginfo);
+			fsm_event(grp->fsm, MPCG_EVENT_XID2DONE, dev);
+		}
+		break;
+	}
+	kfree(mpcginfo);
+
+	if (do_debug) {
+		ctcm_pr_debug("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
+				__FUNCTION__, ch->id,
+				grp->outstanding_xid2,
+				grp->outstanding_xid7,
+				grp->outstanding_xid7_p2);
+		ctcm_pr_debug("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
+				__FUNCTION__, ch->id,
+				fsm_getstate_str(grp->fsm),
+				fsm_getstate_str(ch->fsm));
+	}
+	return;
+
+}
+
+
+/*
+ * MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
+{
+	struct mpcg_info   *mpcginfo   = arg;
+	struct channel	   *ch	       = mpcginfo->ch;
+	struct net_device  *dev        = ch->netdev;
+	struct ctcm_priv   *priv    = dev->priv;
+	struct mpc_group   *grp     = priv->mpcg;
+
+	if (do_debug) {
+		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+				__FUNCTION__, smp_processor_id(), ch, ch->id);
+
+		ctcm_pr_debug("ctcmpc:  outstanding_xid7: %i, "
+				" outstanding_xid7_p2: %i\n",
+				grp->outstanding_xid7,
+				grp->outstanding_xid7_p2);
+	}
+
+	grp->outstanding_xid7--;
+	ch->xid_skb->data = ch->xid_skb_data;
+	skb_reset_tail_pointer(ch->xid_skb);
+	ch->xid_skb->len = 0;
+
+	switch (fsm_getstate(grp->fsm)) {
+	case MPCG_STATE_XID7INITI:
+		fsm_newstate(grp->fsm, MPCG_STATE_XID7INITZ);
+		mpc_validate_xid(mpcginfo);
+		break;
+	case MPCG_STATE_XID7INITW:
+		fsm_newstate(grp->fsm, MPCG_STATE_XID7INITX);
+		mpc_validate_xid(mpcginfo);
+		break;
+	case MPCG_STATE_XID7INITZ:
+	case MPCG_STATE_XID7INITX:
+		if (grp->outstanding_xid7 == 0) {
+			if (grp->outstanding_xid7_p2 > 0) {
+				grp->outstanding_xid7 =
+					grp->outstanding_xid7_p2;
+				grp->outstanding_xid7_p2 = 0;
+			} else
+				fsm_newstate(grp->fsm, MPCG_STATE_XID7INITF);
+
+			mpc_validate_xid(mpcginfo);
+			fsm_event(grp->fsm, MPCG_EVENT_XID7DONE, dev);
+			break;
+		}
+		mpc_validate_xid(mpcginfo);
+		break;
+	}
+
+	kfree(mpcginfo);
+
+	if (do_debug)
+		ctcm_pr_debug("ctcmpc exit: %s(): cp=%i ch=0x%p id=%s\n",
+			__FUNCTION__, smp_processor_id(), ch, ch->id);
+	return;
+
+}
+
+/*
+ * mpc_action helper of an MPC Group Station FSM action
+ * CTCM_PROTO_MPC only
+ */
+static int mpc_send_qllc_discontact(struct net_device *dev)
+{
+	int	rc	= 0;
+	__u32	new_len	= 0;
+	struct sk_buff   *skb;
+	struct qllc      *qllcptr;
+	struct ctcm_priv *priv;
+	struct mpc_group *grp;
+
+	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
+
+	if (dev == NULL) {
+		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
+		rc = 1;
+					goto done;
+	}
+
+	priv = dev->priv;
+	if (priv == NULL) {
+		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
+		rc = 1;
+					goto done;
+	}
+
+	grp = priv->mpcg;
+	if (grp == NULL) {
+		printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
+		rc = 1;
+					goto done;
+	}
+	ctcm_pr_info("ctcmpc: %s() GROUP STATE: %s\n", __FUNCTION__,
+			mpcg_state_names[grp->saved_state]);
+
+	switch (grp->saved_state) {
+	/*
+	 * establish conn callback function is
+	 * preferred method to report failure
+	 */
+	case MPCG_STATE_XID0IOWAIT:
+	case MPCG_STATE_XID0IOWAIX:
+	case MPCG_STATE_XID7INITI:
+	case MPCG_STATE_XID7INITZ:
+	case MPCG_STATE_XID2INITW:
+	case MPCG_STATE_XID2INITX:
+	case MPCG_STATE_XID7INITW:
+	case MPCG_STATE_XID7INITX:
+		if (grp->estconnfunc) {
+			grp->estconnfunc(grp->port_num, -1, 0);
+			grp->estconnfunc = NULL;
+			break;
+		}
+	case MPCG_STATE_FLOWC:
+	case MPCG_STATE_READY:
+		grp->send_qllc_disc = 2;
+		new_len = sizeof(struct qllc);
+		qllcptr = kzalloc(new_len, gfp_type() | GFP_DMA);
+		if (qllcptr == NULL) {
+			printk(KERN_INFO
+			       "ctcmpc: Out of memory in %s()\n",
+			       dev->name);
+			rc = 1;
+				goto done;
+		}
+
+		qllcptr->qllc_address = 0xcc;
+		qllcptr->qllc_commands = 0x03;
+
+		skb = __dev_alloc_skb(new_len, GFP_ATOMIC);
+
+		if (skb == NULL) {
+			printk(KERN_INFO "%s Out of memory in mpc_send_qllc\n",
+			       dev->name);
+			priv->stats.rx_dropped++;
+			rc = 1;
+			kfree(qllcptr);
+				goto done;
+		}
+
+		memcpy(skb_put(skb, new_len), qllcptr, new_len);
+		kfree(qllcptr);
+
+		if (skb_headroom(skb) < 4) {
+			printk(KERN_INFO "ctcmpc: %s() Unable to"
+			       " build discontact for %s\n",
+			       __FUNCTION__, dev->name);
+			rc = 1;
+			dev_kfree_skb_any(skb);
+				goto done;
+		}
+
+		*((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq;
+		priv->channel[READ]->pdu_seq++;
+		if (do_debug_data)
+			ctcm_pr_debug("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
+				__FUNCTION__, priv->channel[READ]->pdu_seq);
+
+		/* receipt of CC03 resets anticipated sequence number on
+		      receiving side */
+		priv->channel[READ]->pdu_seq = 0x00;
+		skb_reset_mac_header(skb);
+		skb->dev = dev;
+		skb->protocol = htons(ETH_P_SNAP);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		ctcmpc_dumpit((char *)skb->data, (sizeof(struct qllc) + 4));
+
+		netif_rx(skb);
+		break;
+	default:
+		break;
+
+	}
+
+done:
+	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
+	return rc;
+}
+/* --- This is the END my friend --- */
+
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
new file mode 100644
index 0000000..f996860
--- /dev/null
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -0,0 +1,239 @@
+/*
+ * drivers/s390/net/ctcm_mpc.h
+ *
+ * Copyright IBM Corp. 2007
+ * Authors:	Peter Tiedemann (ptiedem@de.ibm.com)
+ *
+ * 	MPC additions:
+ *		Belinda Thompson (belindat@us.ibm.com)
+ *		Andy Richter (richtera@us.ibm.com)
+ */
+
+#ifndef _CTC_MPC_H_
+#define _CTC_MPC_H_
+
+#include <linux/skbuff.h>
+#include "fsm.h"
+
+/*
+ * MPC external interface
+ * Note that ctc_mpc_xyz are called with a lock on ................
+ */
+
+/*  port_number is the mpc device 0, 1, 2 etc mpc2 is port_number 2 */
+
+/*  passive open  Just wait for XID2 exchange */
+extern int ctc_mpc_alloc_channel(int port,
+		void (*callback)(int port_num, int max_write_size));
+/* active open  Alloc then send XID2 */
+extern void ctc_mpc_establish_connectivity(int port,
+		void (*callback)(int port_num, int rc, int max_write_size));
+
+extern void ctc_mpc_dealloc_ch(int port);
+extern void ctc_mpc_flow_control(int port, int flowc);
+
+/*
+ * other MPC Group prototypes and structures
+ */
+
+#define ETH_P_SNA_DIX	0x80D5
+
+/*
+ * Declaration of an XID2
+ *
+ */
+#define ALLZEROS 0x0000000000000000
+
+#define XID_FM2		0x20
+#define XID2_0		0x00
+#define XID2_7		0x07
+#define XID2_WRITE_SIDE 0x04
+#define XID2_READ_SIDE	0x05
+
+struct xid2 {
+	__u8	xid2_type_id;
+	__u8	xid2_len;
+	__u32	xid2_adj_id;
+	__u8	xid2_rlen;
+	__u8	xid2_resv1;
+	__u8	xid2_flag1;
+	__u8	xid2_fmtt;
+	__u8	xid2_flag4;
+	__u16	xid2_resv2;
+	__u8	xid2_tgnum;
+	__u32	xid2_sender_id;
+	__u8	xid2_flag2;
+	__u8	xid2_option;
+	char  xid2_resv3[8];
+	__u16	xid2_resv4;
+	__u8	xid2_dlc_type;
+	__u16	xid2_resv5;
+	__u8	xid2_mpc_flag;
+	__u8	xid2_resv6;
+	__u16	xid2_buf_len;
+	char xid2_buffer[255 - (13 * sizeof(__u8) +
+				2 * sizeof(__u32) +
+				4 * sizeof(__u16) +
+				8 * sizeof(char))];
+} __attribute__ ((packed));
+
+#define XID2_LENGTH  (sizeof(struct xid2))
+
+struct th_header {
+	__u8	th_seg;
+	__u8	th_ch_flag;
+#define TH_HAS_PDU	0xf0
+#define TH_IS_XID	0x01
+#define TH_SWEEP_REQ	0xfe
+#define TH_SWEEP_RESP	0xff
+	__u8	th_blk_flag;
+#define TH_DATA_IS_XID	0x80
+#define TH_RETRY	0x40
+#define TH_DISCONTACT	0xc0
+#define TH_SEG_BLK	0x20
+#define TH_LAST_SEG	0x10
+#define TH_PDU_PART	0x08
+	__u8	th_is_xid;	/* is 0x01 if this is XID  */
+	__u32	th_seq_num;
+} __attribute__ ((packed));
+
+struct th_addon {
+	__u32	th_last_seq;
+	__u32	th_resvd;
+} __attribute__ ((packed));
+
+struct th_sweep {
+	struct th_header th;
+	struct th_addon sw;
+} __attribute__ ((packed));
+
+#define TH_HEADER_LENGTH (sizeof(struct th_header))
+#define TH_SWEEP_LENGTH (sizeof(struct th_sweep))
+
+#define PDU_LAST	0x80
+#define PDU_CNTL	0x40
+#define PDU_FIRST	0x20
+
+struct pdu {
+	__u32	pdu_offset;
+	__u8	pdu_flag;
+	__u8	pdu_proto;   /*  0x01 is APPN SNA  */
+	__u16	pdu_seq;
+} __attribute__ ((packed));
+
+#define PDU_HEADER_LENGTH  (sizeof(struct pdu))
+
+struct qllc {
+	__u8	qllc_address;
+#define QLLC_REQ	0xFF
+#define QLLC_RESP	0x00
+	__u8	qllc_commands;
+#define QLLC_DISCONNECT 0x53
+#define QLLC_UNSEQACK	0x73
+#define QLLC_SETMODE	0x93
+#define QLLC_EXCHID	0xBF
+} __attribute__ ((packed));
+
+
+/*
+ * Definition of one MPC group
+ */
+
+#define MAX_MPCGCHAN		10
+#define MPC_XID_TIMEOUT_VALUE	10000
+#define MPC_CHANNEL_ADD		0
+#define MPC_CHANNEL_REMOVE	1
+#define MPC_CHANNEL_ATTN	2
+#define XSIDE	1
+#define YSIDE	0
+
+struct mpcg_info {
+	struct sk_buff	*skb;
+	struct channel	*ch;
+	struct xid2	*xid;
+	struct th_sweep	*sweep;
+	struct th_header *th;
+};
+
+struct mpc_group {
+	struct tasklet_struct mpc_tasklet;
+	struct tasklet_struct mpc_tasklet2;
+	int	changed_side;
+	int	saved_state;
+	int	channels_terminating;
+	int	out_of_sequence;
+	int	flow_off_called;
+	int	port_num;
+	int	port_persist;
+	int	alloc_called;
+	__u32	xid2_adj_id;
+	__u8	xid2_tgnum;
+	__u32	xid2_sender_id;
+	int	num_channel_paths;
+	int	active_channels[2];
+	__u16	group_max_buflen;
+	int	outstanding_xid2;
+	int	outstanding_xid7;
+	int	outstanding_xid7_p2;
+	int	sweep_req_pend_num;
+	int	sweep_rsp_pend_num;
+	struct sk_buff	*xid_skb;
+	char		*xid_skb_data;
+	struct th_header *xid_th;
+	struct xid2	*xid;
+	char		*xid_id;
+	struct th_header *rcvd_xid_th;
+	struct sk_buff	*rcvd_xid_skb;
+	char		*rcvd_xid_data;
+	__u8		in_sweep;
+	__u8		roll;
+	struct xid2	*saved_xid2;
+	void 		(*allochanfunc)(int, int);
+	int		allocchan_callback_retries;
+	void 		(*estconnfunc)(int, int, int);
+	int		estconn_callback_retries;
+	int		estconn_called;
+	int		xidnogood;
+	int		send_qllc_disc;
+	fsm_timer	timer;
+	fsm_instance	*fsm; /* group xid fsm */
+};
+
+#ifdef DEBUGDATA
+void ctcmpc_dumpit(char *buf, int len);
+#else
+static inline void ctcmpc_dumpit(char *buf, int len)
+{
+}
+#endif
+
+#ifdef DEBUGDATA
+/*
+ * Dump header and first 16 bytes of an sk_buff for debugging purposes.
+ *
+ * skb	 The struct sk_buff to dump.
+ * offset Offset relative to skb-data, where to start the dump.
+ */
+void ctcmpc_dump_skb(struct sk_buff *skb, int offset);
+#else
+static inline void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
+{}
+#endif
+
+static inline void ctcmpc_dump32(char *buf, int len)
+{
+	if (len < 32)
+		ctcmpc_dumpit(buf, len);
+	else
+		ctcmpc_dumpit(buf, 32);
+}
+
+int ctcmpc_open(struct net_device *);
+void ctcm_ccw_check_rc(struct channel *, int, char *);
+void mpc_group_ready(unsigned long adev);
+int mpc_channel_action(struct channel *ch, int direction, int action);
+void mpc_action_send_discontact(unsigned long thischan);
+void mpc_action_discontact(fsm_instance *fi, int event, void *arg);
+void ctcmpc_bh(unsigned long thischan);
+#endif
+/* --- This is the END my friend --- */
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
new file mode 100644
index 0000000..bb2d137
--- /dev/null
+++ b/drivers/s390/net/ctcm_sysfs.c
@@ -0,0 +1,210 @@
+/*
+ * drivers/s390/net/ctcm_sysfs.c
+ *
+ * Copyright IBM Corp. 2007, 2007
+ * Authors:	Peter Tiedemann (ptiedem@de.ibm.com)
+ *
+ */
+
+#undef DEBUG
+#undef DEBUGDATA
+#undef DEBUGCCW
+
+#include <linux/sysfs.h>
+#include "ctcm_main.h"
+
+/*
+ * sysfs attributes
+ */
+
+static ssize_t ctcm_buffer_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ctcm_priv *priv = dev_get_drvdata(dev);
+
+	if (!priv)
+		return -ENODEV;
+	return sprintf(buf, "%d\n", priv->buffer_size);
+}
+
+static ssize_t ctcm_buffer_write(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct net_device *ndev;
+	int bs1;
+	struct ctcm_priv *priv = dev_get_drvdata(dev);
+
+	if (!(priv && priv->channel[READ] &&
+			(ndev = priv->channel[READ]->netdev))) {
+		CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
+		return -ENODEV;
+	}
+
+	sscanf(buf, "%u", &bs1);
+	if (bs1 > CTCM_BUFSIZE_LIMIT)
+					goto einval;
+	if (bs1 < (576 + LL_HEADER_LENGTH + 2))
+					goto einval;
+	priv->buffer_size = bs1;	/* just to overwrite the default */
+
+	if ((ndev->flags & IFF_RUNNING) &&
+	    (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
+					goto einval;
+
+	priv->channel[READ]->max_bufsize = bs1;
+	priv->channel[WRITE]->max_bufsize = bs1;
+	if (!(ndev->flags & IFF_RUNNING))
+		ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
+	priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+	priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+
+	CTCM_DBF_DEV(SETUP, ndev, buf);
+	return count;
+
+einval:
+	CTCM_DBF_DEV(SETUP, ndev, "buff_err");
+	return -EINVAL;
+}
+
+static void ctcm_print_statistics(struct ctcm_priv *priv)
+{
+	char *sbuf;
+	char *p;
+
+	if (!priv)
+		return;
+	sbuf = kmalloc(2048, GFP_KERNEL);
+	if (sbuf == NULL)
+		return;
+	p = sbuf;
+
+	p += sprintf(p, "  Device FSM state: %s\n",
+		     fsm_getstate_str(priv->fsm));
+	p += sprintf(p, "  RX channel FSM state: %s\n",
+		     fsm_getstate_str(priv->channel[READ]->fsm));
+	p += sprintf(p, "  TX channel FSM state: %s\n",
+		     fsm_getstate_str(priv->channel[WRITE]->fsm));
+	p += sprintf(p, "  Max. TX buffer used: %ld\n",
+		     priv->channel[WRITE]->prof.maxmulti);
+	p += sprintf(p, "  Max. chained SKBs: %ld\n",
+		     priv->channel[WRITE]->prof.maxcqueue);
+	p += sprintf(p, "  TX single write ops: %ld\n",
+		     priv->channel[WRITE]->prof.doios_single);
+	p += sprintf(p, "  TX multi write ops: %ld\n",
+		     priv->channel[WRITE]->prof.doios_multi);
+	p += sprintf(p, "  Netto bytes written: %ld\n",
+		     priv->channel[WRITE]->prof.txlen);
+	p += sprintf(p, "  Max. TX IO-time: %ld\n",
+		     priv->channel[WRITE]->prof.tx_time);
+
+	printk(KERN_INFO "Statistics for %s:\n%s",
+				priv->channel[WRITE]->netdev->name, sbuf);
+	kfree(sbuf);
+	return;
+}
+
+static ssize_t stats_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ctcm_priv *priv = dev_get_drvdata(dev);
+	if (!priv)
+		return -ENODEV;
+	ctcm_print_statistics(priv);
+	return sprintf(buf, "0\n");
+}
+
+static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct ctcm_priv *priv = dev_get_drvdata(dev);
+	if (!priv)
+		return -ENODEV;
+	/* Reset statistics */
+	memset(&priv->channel[WRITE]->prof, 0,
+				sizeof(priv->channel[WRITE]->prof));
+	return count;
+}
+
+static ssize_t ctcm_proto_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ctcm_priv *priv = dev_get_drvdata(dev);
+	if (!priv)
+		return -ENODEV;
+
+	return sprintf(buf, "%d\n", priv->protocol);
+}
+
+static ssize_t ctcm_proto_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int value;
+	struct ctcm_priv *priv = dev_get_drvdata(dev);
+
+	if (!priv)
+		return -ENODEV;
+	sscanf(buf, "%u", &value);
+	if (!((value == CTCM_PROTO_S390)  ||
+	      (value == CTCM_PROTO_LINUX) ||
+	      (value == CTCM_PROTO_MPC) ||
+	      (value == CTCM_PROTO_OS390)))
+		return -EINVAL;
+	priv->protocol = value;
+	CTCM_DBF_DEV(SETUP, dev, buf);
+
+	return count;
+}
+
+static ssize_t ctcm_type_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ccwgroup_device *cgdev;
+
+	cgdev = to_ccwgroupdev(dev);
+	if (!cgdev)
+		return -ENODEV;
+
+	return sprintf(buf, "%s\n",
+			cu3088_type[cgdev->cdev[0]->id.driver_info]);
+}
+
+static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
+static DEVICE_ATTR(protocol, 0644, ctcm_proto_show, ctcm_proto_store);
+static DEVICE_ATTR(type, 0444, ctcm_type_show, NULL);
+static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
+
+static struct attribute *ctcm_attr[] = {
+	&dev_attr_protocol.attr,
+	&dev_attr_type.attr,
+	&dev_attr_buffer.attr,
+	NULL,
+};
+
+static struct attribute_group ctcm_attr_group = {
+	.attrs = ctcm_attr,
+};
+
+int ctcm_add_attributes(struct device *dev)
+{
+	int rc;
+
+	rc = device_create_file(dev, &dev_attr_stats);
+
+	return rc;
+}
+
+void ctcm_remove_attributes(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_stats);
+}
+
+int ctcm_add_files(struct device *dev)
+{
+	return sysfs_create_group(&dev->kobj, &ctcm_attr_group);
+}
+
+void ctcm_remove_files(struct device *dev)
+{
+	sysfs_remove_group(&dev->kobj, &ctcm_attr_group);
+}
+
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
deleted file mode 100644
index 77a5031..0000000
--- a/drivers/s390/net/ctcmain.c
+++ /dev/null
@@ -1,3062 +0,0 @@
-/*
- * CTC / ESCON network driver
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
- *            Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-	      Peter Tiedemann (ptiedem@de.ibm.com)
- * Driver Model stuff by : Cornelia Huck <cornelia.huck@de.ibm.com>
- *
- * Documentation used:
- *  - Principles of Operation (IBM doc#: SA22-7201-06)
- *  - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
- *  - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
- *  - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
- *  - ESCON I/O Interface (IBM doc#: SA22-7202-029
- *
- * and the source of the original CTC driver by:
- *  Dieter Wellerdiek (wel@de.ibm.com)
- *  Martin Schwidefsky (schwidefsky@de.ibm.com)
- *  Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- *  Jochen Röhrig (roehrig@de.ibm.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#undef DEBUG
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/bitops.h>
-
-#include <linux/signal.h>
-#include <linux/string.h>
-
-#include <linux/ip.h>
-#include <linux/if_arp.h>
-#include <linux/tcp.h>
-#include <linux/skbuff.h>
-#include <linux/ctype.h>
-#include <net/dst.h>
-
-#include <asm/io.h>
-#include <asm/ccwdev.h>
-#include <asm/ccwgroup.h>
-#include <asm/uaccess.h>
-
-#include <asm/idals.h>
-
-#include "fsm.h"
-#include "cu3088.h"
-
-#include "ctcdbug.h"
-#include "ctcmain.h"
-
-MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
-MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
-MODULE_LICENSE("GPL");
-/**
- * States of the interface statemachine.
- */
-enum dev_states {
-	DEV_STATE_STOPPED,
-	DEV_STATE_STARTWAIT_RXTX,
-	DEV_STATE_STARTWAIT_RX,
-	DEV_STATE_STARTWAIT_TX,
-	DEV_STATE_STOPWAIT_RXTX,
-	DEV_STATE_STOPWAIT_RX,
-	DEV_STATE_STOPWAIT_TX,
-	DEV_STATE_RUNNING,
-	/**
-	 * MUST be always the last element!!
-	 */
-	CTC_NR_DEV_STATES
-};
-
-static const char *dev_state_names[] = {
-	"Stopped",
-	"StartWait RXTX",
-	"StartWait RX",
-	"StartWait TX",
-	"StopWait RXTX",
-	"StopWait RX",
-	"StopWait TX",
-	"Running",
-};
-
-/**
- * Events of the interface statemachine.
- */
-enum dev_events {
-	DEV_EVENT_START,
-	DEV_EVENT_STOP,
-	DEV_EVENT_RXUP,
-	DEV_EVENT_TXUP,
-	DEV_EVENT_RXDOWN,
-	DEV_EVENT_TXDOWN,
-	DEV_EVENT_RESTART,
-	/**
-	 * MUST be always the last element!!
-	 */
-	CTC_NR_DEV_EVENTS
-};
-
-static const char *dev_event_names[] = {
-	"Start",
-	"Stop",
-	"RX up",
-	"TX up",
-	"RX down",
-	"TX down",
-	"Restart",
-};
-
-/**
- * Events of the channel statemachine
- */
-enum ch_events {
-	/**
-	 * Events, representing return code of
-	 * I/O operations (ccw_device_start, ccw_device_halt et al.)
-	 */
-	CH_EVENT_IO_SUCCESS,
-	CH_EVENT_IO_EBUSY,
-	CH_EVENT_IO_ENODEV,
-	CH_EVENT_IO_EIO,
-	CH_EVENT_IO_UNKNOWN,
-
-	CH_EVENT_ATTNBUSY,
-	CH_EVENT_ATTN,
-	CH_EVENT_BUSY,
-
-	/**
-	 * Events, representing unit-check
-	 */
-	CH_EVENT_UC_RCRESET,
-	CH_EVENT_UC_RSRESET,
-	CH_EVENT_UC_TXTIMEOUT,
-	CH_EVENT_UC_TXPARITY,
-	CH_EVENT_UC_HWFAIL,
-	CH_EVENT_UC_RXPARITY,
-	CH_EVENT_UC_ZERO,
-	CH_EVENT_UC_UNKNOWN,
-
-	/**
-	 * Events, representing subchannel-check
-	 */
-	CH_EVENT_SC_UNKNOWN,
-
-	/**
-	 * Events, representing machine checks
-	 */
-	CH_EVENT_MC_FAIL,
-	CH_EVENT_MC_GOOD,
-
-	/**
-	 * Event, representing normal IRQ
-	 */
-	CH_EVENT_IRQ,
-	CH_EVENT_FINSTAT,
-
-	/**
-	 * Event, representing timer expiry.
-	 */
-	CH_EVENT_TIMER,
-
-	/**
-	 * Events, representing commands from upper levels.
-	 */
-	CH_EVENT_START,
-	CH_EVENT_STOP,
-
-	/**
-	 * MUST be always the last element!!
-	 */
-	NR_CH_EVENTS,
-};
-
-/**
- * States of the channel statemachine.
- */
-enum ch_states {
-	/**
-	 * Channel not assigned to any device,
-	 * initial state, direction invalid
-	 */
-	CH_STATE_IDLE,
-
-	/**
-	 * Channel assigned but not operating
-	 */
-	CH_STATE_STOPPED,
-	CH_STATE_STARTWAIT,
-	CH_STATE_STARTRETRY,
-	CH_STATE_SETUPWAIT,
-	CH_STATE_RXINIT,
-	CH_STATE_TXINIT,
-	CH_STATE_RX,
-	CH_STATE_TX,
-	CH_STATE_RXIDLE,
-	CH_STATE_TXIDLE,
-	CH_STATE_RXERR,
-	CH_STATE_TXERR,
-	CH_STATE_TERM,
-	CH_STATE_DTERM,
-	CH_STATE_NOTOP,
-
-	/**
-	 * MUST be always the last element!!
-	 */
-	NR_CH_STATES,
-};
-
-static int loglevel = CTC_LOGLEVEL_DEFAULT;
-
-/**
- * Linked list of all detected channels.
- */
-static struct channel *channels = NULL;
-
-/**
- * Print Banner.
- */
-static void
-print_banner(void)
-{
-	static int printed = 0;
-
-	if (printed)
-		return;
-
-	printk(KERN_INFO "CTC driver initialized\n");
-	printed = 1;
-}
-
-/**
- * Return type of a detected device.
- */
-static enum channel_types
-get_channel_type(struct ccw_device_id *id)
-{
-	enum channel_types type = (enum channel_types) id->driver_info;
-
-	if (type == channel_type_ficon)
-		type = channel_type_escon;
-
-	return type;
-}
-
-static const char *ch_event_names[] = {
-	"ccw_device success",
-	"ccw_device busy",
-	"ccw_device enodev",
-	"ccw_device ioerr",
-	"ccw_device unknown",
-
-	"Status ATTN & BUSY",
-	"Status ATTN",
-	"Status BUSY",
-
-	"Unit check remote reset",
-	"Unit check remote system reset",
-	"Unit check TX timeout",
-	"Unit check TX parity",
-	"Unit check Hardware failure",
-	"Unit check RX parity",
-	"Unit check ZERO",
-	"Unit check Unknown",
-
-	"SubChannel check Unknown",
-
-	"Machine check failure",
-	"Machine check operational",
-
-	"IRQ normal",
-	"IRQ final",
-
-	"Timer",
-
-	"Start",
-	"Stop",
-};
-
-static const char *ch_state_names[] = {
-	"Idle",
-	"Stopped",
-	"StartWait",
-	"StartRetry",
-	"SetupWait",
-	"RX init",
-	"TX init",
-	"RX",
-	"TX",
-	"RX idle",
-	"TX idle",
-	"RX error",
-	"TX error",
-	"Terminating",
-	"Restarting",
-	"Not operational",
-};
-
-#ifdef DEBUG
-/**
- * Dump header and first 16 bytes of an sk_buff for debugging purposes.
- *
- * @param skb    The sk_buff to dump.
- * @param offset Offset relative to skb-data, where to start the dump.
- */
-static void
-ctc_dump_skb(struct sk_buff *skb, int offset)
-{
-	unsigned char *p = skb->data;
-	__u16 bl;
-	struct ll_header *header;
-	int i;
-
-	if (!(loglevel & CTC_LOGLEVEL_DEBUG))
-		return;
-	p += offset;
-	bl = *((__u16 *) p);
-	p += 2;
-	header = (struct ll_header *) p;
-	p -= 2;
-
-	printk(KERN_DEBUG "dump:\n");
-	printk(KERN_DEBUG "blocklen=%d %04x\n", bl, bl);
-
-	printk(KERN_DEBUG "h->length=%d %04x\n", header->length,
-	       header->length);
-	printk(KERN_DEBUG "h->type=%04x\n", header->type);
-	printk(KERN_DEBUG "h->unused=%04x\n", header->unused);
-	if (bl > 16)
-		bl = 16;
-	printk(KERN_DEBUG "data: ");
-	for (i = 0; i < bl; i++)
-		printk("%02x%s", *p++, (i % 16) ? " " : "\n<7>");
-	printk("\n");
-}
-#else
-static inline void
-ctc_dump_skb(struct sk_buff *skb, int offset)
-{
-}
-#endif
-
-/**
- * Unpack a just received skb and hand it over to
- * upper layers.
- *
- * @param ch The channel where this skb has been received.
- * @param pskb The received skb.
- */
-static void
-ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
-{
-	struct net_device *dev = ch->netdev;
-	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
-	__u16 len = *((__u16 *) pskb->data);
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	skb_put(pskb, 2 + LL_HEADER_LENGTH);
-	skb_pull(pskb, 2);
-	pskb->dev = dev;
-	pskb->ip_summed = CHECKSUM_UNNECESSARY;
-	while (len > 0) {
-		struct sk_buff *skb;
-		struct ll_header *header = (struct ll_header *) pskb->data;
-
-		skb_pull(pskb, LL_HEADER_LENGTH);
-		if ((ch->protocol == CTC_PROTO_S390) &&
-		    (header->type != ETH_P_IP)) {
-
-#ifndef DEBUG
-		        if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
-#endif
-				/**
-				 * Check packet type only if we stick strictly
-				 * to S/390's protocol of OS390. This only
-				 * supports IP. Otherwise allow any packet
-				 * type.
-				 */
-				ctc_pr_warn(
-					"%s Illegal packet type 0x%04x received, dropping\n",
-					dev->name, header->type);
-				ch->logflags |= LOG_FLAG_ILLEGALPKT;
-#ifndef DEBUG
-			}
-#endif
-#ifdef DEBUG
-			ctc_dump_skb(pskb, -6);
-#endif
-			privptr->stats.rx_dropped++;
-			privptr->stats.rx_frame_errors++;
-			return;
-		}
-		pskb->protocol = ntohs(header->type);
-		if (header->length <= LL_HEADER_LENGTH) {
-#ifndef DEBUG
-		        if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
-#endif
-				ctc_pr_warn(
-				       "%s Illegal packet size %d "
-				       "received (MTU=%d blocklen=%d), "
-				       "dropping\n", dev->name, header->length,
-				       dev->mtu, len);
-				ch->logflags |= LOG_FLAG_ILLEGALSIZE;
-#ifndef DEBUG
-			}
-#endif
-#ifdef DEBUG
-			ctc_dump_skb(pskb, -6);
-#endif
-			privptr->stats.rx_dropped++;
-			privptr->stats.rx_length_errors++;
-			return;
-		}
-		header->length -= LL_HEADER_LENGTH;
-		len -= LL_HEADER_LENGTH;
-		if ((header->length > skb_tailroom(pskb)) ||
-		    (header->length > len)) {
-#ifndef DEBUG
-		        if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
-#endif
-				ctc_pr_warn(
-					"%s Illegal packet size %d "
-					"(beyond the end of received data), "
-					"dropping\n", dev->name, header->length);
-				ch->logflags |= LOG_FLAG_OVERRUN;
-#ifndef DEBUG
-			}
-#endif
-#ifdef DEBUG
-			ctc_dump_skb(pskb, -6);
-#endif
-			privptr->stats.rx_dropped++;
-			privptr->stats.rx_length_errors++;
-			return;
-		}
-		skb_put(pskb, header->length);
-		skb_reset_mac_header(pskb);
-		len -= header->length;
-		skb = dev_alloc_skb(pskb->len);
-		if (!skb) {
-#ifndef DEBUG
-		        if (!(ch->logflags & LOG_FLAG_NOMEM)) {
-#endif
-				ctc_pr_warn(
-					"%s Out of memory in ctc_unpack_skb\n",
-					dev->name);
-				ch->logflags |= LOG_FLAG_NOMEM;
-#ifndef DEBUG
-			}
-#endif
-			privptr->stats.rx_dropped++;
-			return;
-		}
-		skb_copy_from_linear_data(pskb, skb_put(skb, pskb->len),
-					  pskb->len);
-		skb_reset_mac_header(skb);
-		skb->dev = pskb->dev;
-		skb->protocol = pskb->protocol;
-		pskb->ip_summed = CHECKSUM_UNNECESSARY;
-		/**
-		 * reset logflags
-		 */
-		ch->logflags = 0;
-		privptr->stats.rx_packets++;
-		privptr->stats.rx_bytes += skb->len;
-		netif_rx_ni(skb);
-		dev->last_rx = jiffies;
-		if (len > 0) {
-			skb_pull(pskb, header->length);
-			if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
-#ifndef DEBUG
-				if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
-#endif
-					ctc_pr_warn(
-						"%s Overrun in ctc_unpack_skb\n",
-						dev->name);
-					ch->logflags |= LOG_FLAG_OVERRUN;
-#ifndef DEBUG
-				}
-#endif
-				return;
-			}
-			skb_put(pskb, LL_HEADER_LENGTH);
-		}
-	}
-}
-
-/**
- * Check return code of a preceeding ccw_device call, halt_IO etc...
- *
- * @param ch          The channel, the error belongs to.
- * @param return_code The error code to inspect.
- */
-static void
-ccw_check_return_code(struct channel *ch, int return_code, char *msg)
-{
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	switch (return_code) {
-		case 0:
-			fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch);
-			break;
-		case -EBUSY:
-			ctc_pr_warn("%s (%s): Busy !\n", ch->id, msg);
-			fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch);
-			break;
-		case -ENODEV:
-			ctc_pr_emerg("%s (%s): Invalid device called for IO\n",
-				     ch->id, msg);
-			fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch);
-			break;
-		case -EIO:
-			ctc_pr_emerg("%s (%s): Status pending... \n",
-				     ch->id, msg);
-			fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch);
-			break;
-		default:
-			ctc_pr_emerg("%s (%s): Unknown error in do_IO %04x\n",
-				     ch->id, msg, return_code);
-			fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch);
-	}
-}
-
-/**
- * Check sense of a unit check.
- *
- * @param ch    The channel, the sense code belongs to.
- * @param sense The sense code to inspect.
- */
-static void
-ccw_unit_check(struct channel *ch, unsigned char sense)
-{
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if (sense & SNS0_INTERVENTION_REQ) {
-		if (sense & 0x01) {
-			ctc_pr_debug("%s: Interface disc. or Sel. reset "
-					"(remote)\n", ch->id);
-			fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
-		} else {
-			ctc_pr_debug("%s: System reset (remote)\n", ch->id);
-			fsm_event(ch->fsm, CH_EVENT_UC_RSRESET, ch);
-		}
-	} else if (sense & SNS0_EQUIPMENT_CHECK) {
-		if (sense & SNS0_BUS_OUT_CHECK) {
-			ctc_pr_warn("%s: Hardware malfunction (remote)\n",
-				    ch->id);
-			fsm_event(ch->fsm, CH_EVENT_UC_HWFAIL, ch);
-		} else {
-			ctc_pr_warn("%s: Read-data parity error (remote)\n",
-				    ch->id);
-			fsm_event(ch->fsm, CH_EVENT_UC_RXPARITY, ch);
-		}
-	} else if (sense & SNS0_BUS_OUT_CHECK) {
-		if (sense & 0x04) {
-			ctc_pr_warn("%s: Data-streaming timeout)\n", ch->id);
-			fsm_event(ch->fsm, CH_EVENT_UC_TXTIMEOUT, ch);
-		} else {
-			ctc_pr_warn("%s: Data-transfer parity error\n", ch->id);
-			fsm_event(ch->fsm, CH_EVENT_UC_TXPARITY, ch);
-		}
-	} else if (sense & SNS0_CMD_REJECT) {
-		ctc_pr_warn("%s: Command reject\n", ch->id);
-	} else if (sense == 0) {
-		ctc_pr_debug("%s: Unit check ZERO\n", ch->id);
-		fsm_event(ch->fsm, CH_EVENT_UC_ZERO, ch);
-	} else {
-		ctc_pr_warn("%s: Unit Check with sense code: %02x\n",
-			    ch->id, sense);
-		fsm_event(ch->fsm, CH_EVENT_UC_UNKNOWN, ch);
-	}
-}
-
-static void
-ctc_purge_skb_queue(struct sk_buff_head *q)
-{
-	struct sk_buff *skb;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-
-	while ((skb = skb_dequeue(q))) {
-		atomic_dec(&skb->users);
-		dev_kfree_skb_irq(skb);
-	}
-}
-
-static int
-ctc_checkalloc_buffer(struct channel *ch, int warn)
-{
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if ((ch->trans_skb == NULL) ||
-	    (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED)) {
-		if (ch->trans_skb != NULL)
-			dev_kfree_skb(ch->trans_skb);
-		clear_normalized_cda(&ch->ccw[1]);
-		ch->trans_skb = __dev_alloc_skb(ch->max_bufsize,
-						GFP_ATOMIC | GFP_DMA);
-		if (ch->trans_skb == NULL) {
-			if (warn)
-				ctc_pr_warn(
-					"%s: Couldn't alloc %s trans_skb\n",
-					ch->id,
-					(CHANNEL_DIRECTION(ch->flags) == READ) ?
-					"RX" : "TX");
-			return -ENOMEM;
-		}
-		ch->ccw[1].count = ch->max_bufsize;
-		if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
-			dev_kfree_skb(ch->trans_skb);
-			ch->trans_skb = NULL;
-			if (warn)
-				ctc_pr_warn(
-					"%s: set_normalized_cda for %s "
-					"trans_skb failed, dropping packets\n",
-					ch->id,
-					(CHANNEL_DIRECTION(ch->flags) == READ) ?
-					"RX" : "TX");
-			return -ENOMEM;
-		}
-		ch->ccw[1].count = 0;
-		ch->trans_skb_data = ch->trans_skb->data;
-		ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
-	}
-	return 0;
-}
-
-/**
- * Dummy NOP action for statemachines
- */
-static void
-fsm_action_nop(fsm_instance * fi, int event, void *arg)
-{
-}
-
-/**
- * Actions for channel - statemachines.
- *****************************************************************************/
-
-/**
- * Normal data has been send. Free the corresponding
- * skb (it's in io_queue), reset dev->tbusy and
- * revert to idle state.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_txdone(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-	struct ctc_priv *privptr = dev->priv;
-	struct sk_buff *skb;
-	int first = 1;
-	int i;
-	unsigned long duration;
-	struct timespec done_stamp = current_kernel_time();
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-
-	duration =
-	    (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
-	    (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
-	if (duration > ch->prof.tx_time)
-		ch->prof.tx_time = duration;
-
-	if (ch->irb->scsw.count != 0)
-		ctc_pr_debug("%s: TX not complete, remaining %d bytes\n",
-			     dev->name, ch->irb->scsw.count);
-	fsm_deltimer(&ch->timer);
-	while ((skb = skb_dequeue(&ch->io_queue))) {
-		privptr->stats.tx_packets++;
-		privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
-		if (first) {
-			privptr->stats.tx_bytes += 2;
-			first = 0;
-		}
-		atomic_dec(&skb->users);
-		dev_kfree_skb_irq(skb);
-	}
-	spin_lock(&ch->collect_lock);
-	clear_normalized_cda(&ch->ccw[4]);
-	if (ch->collect_len > 0) {
-		int rc;
-
-		if (ctc_checkalloc_buffer(ch, 1)) {
-			spin_unlock(&ch->collect_lock);
-			return;
-		}
-		ch->trans_skb->data = ch->trans_skb_data;
-		skb_reset_tail_pointer(ch->trans_skb);
-		ch->trans_skb->len = 0;
-		if (ch->prof.maxmulti < (ch->collect_len + 2))
-			ch->prof.maxmulti = ch->collect_len + 2;
-		if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
-			ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
-		*((__u16 *) skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;
-		i = 0;
-		while ((skb = skb_dequeue(&ch->collect_queue))) {
-			skb_copy_from_linear_data(skb, skb_put(ch->trans_skb,
-							       skb->len),
-						  skb->len);
-			privptr->stats.tx_packets++;
-			privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
-			atomic_dec(&skb->users);
-			dev_kfree_skb_irq(skb);
-			i++;
-		}
-		ch->collect_len = 0;
-		spin_unlock(&ch->collect_lock);
-		ch->ccw[1].count = ch->trans_skb->len;
-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
-		ch->prof.send_stamp = current_kernel_time();
-		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
-				      (unsigned long) ch, 0xff, 0);
-		ch->prof.doios_multi++;
-		if (rc != 0) {
-			privptr->stats.tx_dropped += i;
-			privptr->stats.tx_errors += i;
-			fsm_deltimer(&ch->timer);
-			ccw_check_return_code(ch, rc, "chained TX");
-		}
-	} else {
-		spin_unlock(&ch->collect_lock);
-		fsm_newstate(fi, CH_STATE_TXIDLE);
-	}
-	ctc_clear_busy(dev);
-}
-
-/**
- * Initial data is sent.
- * Notify device statemachine that we are up and
- * running.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_txidle(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	fsm_newstate(fi, CH_STATE_TXIDLE);
-	fsm_event(((struct ctc_priv *) ch->netdev->priv)->fsm, DEV_EVENT_TXUP,
-		  ch->netdev);
-}
-
-/**
- * Got normal data, check for sanity, queue it up, allocate new buffer
- * trigger bottom half, and initiate next read.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_rx(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-	struct ctc_priv *privptr = dev->priv;
-	int len = ch->max_bufsize - ch->irb->scsw.count;
-	struct sk_buff *skb = ch->trans_skb;
-	__u16 block_len = *((__u16 *) skb->data);
-	int check_len;
-	int rc;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	if (len < 8) {
-		ctc_pr_debug("%s: got packet with length %d < 8\n",
-			     dev->name, len);
-		privptr->stats.rx_dropped++;
-		privptr->stats.rx_length_errors++;
-		goto again;
-	}
-	if (len > ch->max_bufsize) {
-		ctc_pr_debug("%s: got packet with length %d > %d\n",
-			     dev->name, len, ch->max_bufsize);
-		privptr->stats.rx_dropped++;
-		privptr->stats.rx_length_errors++;
-		goto again;
-	}
-
-	/**
-	 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
-	 */
-	switch (ch->protocol) {
-		case CTC_PROTO_S390:
-		case CTC_PROTO_OS390:
-			check_len = block_len + 2;
-			break;
-		default:
-			check_len = block_len;
-			break;
-	}
-	if ((len < block_len) || (len > check_len)) {
-		ctc_pr_debug("%s: got block length %d != rx length %d\n",
-			     dev->name, block_len, len);
-#ifdef DEBUG
-		ctc_dump_skb(skb, 0);
-#endif
-		*((__u16 *) skb->data) = len;
-		privptr->stats.rx_dropped++;
-		privptr->stats.rx_length_errors++;
-		goto again;
-	}
-	block_len -= 2;
-	if (block_len > 0) {
-		*((__u16 *) skb->data) = block_len;
-		ctc_unpack_skb(ch, skb);
-	}
- again:
-	skb->data = ch->trans_skb_data;
-	skb_reset_tail_pointer(skb);
-	skb->len = 0;
-	if (ctc_checkalloc_buffer(ch, 1))
-		return;
-	ch->ccw[1].count = ch->max_bufsize;
-	rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
-	if (rc != 0)
-		ccw_check_return_code(ch, rc, "normal RX");
-}
-
-static void ch_action_rxidle(fsm_instance * fi, int event, void *arg);
-
-/**
- * Initialize connection by sending a __u16 of value 0.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_firstio(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	int rc;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-
-	if (fsm_getstate(fi) == CH_STATE_TXIDLE)
-		ctc_pr_debug("%s: remote side issued READ?, init ...\n", ch->id);
-	fsm_deltimer(&ch->timer);
-	if (ctc_checkalloc_buffer(ch, 1))
-		return;
-	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&
-	    (ch->protocol == CTC_PROTO_OS390)) {
-		/* OS/390 resp. z/OS */
-		if (CHANNEL_DIRECTION(ch->flags) == READ) {
-			*((__u16 *) ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;
-			fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC,
-				     CH_EVENT_TIMER, ch);
-			ch_action_rxidle(fi, event, arg);
-		} else {
-			struct net_device *dev = ch->netdev;
-			fsm_newstate(fi, CH_STATE_TXIDLE);
-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-				  DEV_EVENT_TXUP, dev);
-		}
-		return;
-	}
-
-	/**
-	 * Don't setup a timer for receiving the initial RX frame
-	 * if in compatibility mode, since VM TCP delays the initial
-	 * frame until it has some data to send.
-	 */
-	if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
-	    (ch->protocol != CTC_PROTO_S390))
-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
-
-	*((__u16 *) ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;
-	ch->ccw[1].count = 2;	/* Transfer only length */
-
-	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
-		     ? CH_STATE_RXINIT : CH_STATE_TXINIT);
-	rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
-	if (rc != 0) {
-		fsm_deltimer(&ch->timer);
-		fsm_newstate(fi, CH_STATE_SETUPWAIT);
-		ccw_check_return_code(ch, rc, "init IO");
-	}
-	/**
-	 * If in compatibility mode since we don't setup a timer, we
-	 * also signal RX channel up immediately. This enables us
-	 * to send packets early which in turn usually triggers some
-	 * reply from VM TCP which brings up the RX channel to it's
-	 * final state.
-	 */
-	if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
-	    (ch->protocol == CTC_PROTO_S390)) {
-		struct net_device *dev = ch->netdev;
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXUP,
-			  dev);
-	}
-}
-
-/**
- * Got initial data, check it. If OK,
- * notify device statemachine that we are up and
- * running.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_rxidle(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-	__u16 buflen;
-	int rc;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	buflen = *((__u16 *) ch->trans_skb->data);
-#ifdef DEBUG
-	ctc_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
-#endif
-	if (buflen >= CTC_INITIAL_BLOCKLEN) {
-		if (ctc_checkalloc_buffer(ch, 1))
-			return;
-		ch->ccw[1].count = ch->max_bufsize;
-		fsm_newstate(fi, CH_STATE_RXIDLE);
-		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
-				      (unsigned long) ch, 0xff, 0);
-		if (rc != 0) {
-			fsm_newstate(fi, CH_STATE_RXINIT);
-			ccw_check_return_code(ch, rc, "initial RX");
-		} else
-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-				  DEV_EVENT_RXUP, dev);
-	} else {
-		ctc_pr_debug("%s: Initial RX count %d not %d\n",
-			     dev->name, buflen, CTC_INITIAL_BLOCKLEN);
-		ch_action_firstio(fi, event, arg);
-	}
-}
-
-/**
- * Set channel into extended mode.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_setmode(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	int rc;
-	unsigned long saveflags;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
-	fsm_newstate(fi, CH_STATE_SETUPWAIT);
-	saveflags = 0;	/* avoids compiler warning with
-			   spin_unlock_irqrestore */
-	if (event == CH_EVENT_TIMER)	// only for timer not yet locked
-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
-	rc = ccw_device_start(ch->cdev, &ch->ccw[6], (unsigned long) ch, 0xff, 0);
-	if (event == CH_EVENT_TIMER)
-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
-	if (rc != 0) {
-		fsm_deltimer(&ch->timer);
-		fsm_newstate(fi, CH_STATE_STARTWAIT);
-		ccw_check_return_code(ch, rc, "set Mode");
-	} else
-		ch->retry = 0;
-}
-
-/**
- * Setup channel.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_start(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	unsigned long saveflags;
-	int rc;
-	struct net_device *dev;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ch == NULL) {
-		ctc_pr_warn("ch_action_start ch=NULL\n");
-		return;
-	}
-	if (ch->netdev == NULL) {
-		ctc_pr_warn("ch_action_start dev=NULL, id=%s\n", ch->id);
-		return;
-	}
-	dev = ch->netdev;
-
-#ifdef DEBUG
-	ctc_pr_debug("%s: %s channel start\n", dev->name,
-		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
-#endif
-
-	if (ch->trans_skb != NULL) {
-		clear_normalized_cda(&ch->ccw[1]);
-		dev_kfree_skb(ch->trans_skb);
-		ch->trans_skb = NULL;
-	}
-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
-		ch->ccw[1].cmd_code = CCW_CMD_READ;
-		ch->ccw[1].flags = CCW_FLAG_SLI;
-		ch->ccw[1].count = 0;
-	} else {
-		ch->ccw[1].cmd_code = CCW_CMD_WRITE;
-		ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
-		ch->ccw[1].count = 0;
-	}
-	if (ctc_checkalloc_buffer(ch, 0)) {
-		ctc_pr_notice(
-			"%s: Could not allocate %s trans_skb, delaying "
-			"allocation until first transfer\n",
-			dev->name,
-			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
-	}
-
-	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
-	ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
-	ch->ccw[0].count = 0;
-	ch->ccw[0].cda = 0;
-	ch->ccw[2].cmd_code = CCW_CMD_NOOP;	/* jointed CE + DE */
-	ch->ccw[2].flags = CCW_FLAG_SLI;
-	ch->ccw[2].count = 0;
-	ch->ccw[2].cda = 0;
-	memcpy(&ch->ccw[3], &ch->ccw[0], sizeof (struct ccw1) * 3);
-	ch->ccw[4].cda = 0;
-	ch->ccw[4].flags &= ~CCW_FLAG_IDA;
-
-	fsm_newstate(fi, CH_STATE_STARTWAIT);
-	fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
-	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
-	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
-	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
-	if (rc != 0) {
-		if (rc != -EBUSY)
-		    fsm_deltimer(&ch->timer);
-		ccw_check_return_code(ch, rc, "initial HaltIO");
-	}
-#ifdef DEBUG
-	ctc_pr_debug("ctc: %s(): leaving\n", __func__);
-#endif
-}
-
-/**
- * Shutdown a channel.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_haltio(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	unsigned long saveflags;
-	int rc;
-	int oldstate;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
-	saveflags = 0;	/* avoids comp warning with
-			   spin_unlock_irqrestore */
-	if (event == CH_EVENT_STOP)	// only for STOP not yet locked
-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
-	oldstate = fsm_getstate(fi);
-	fsm_newstate(fi, CH_STATE_TERM);
-	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
-	if (event == CH_EVENT_STOP)
-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
-	if (rc != 0) {
-		if (rc != -EBUSY) {
-		    fsm_deltimer(&ch->timer);
-		    fsm_newstate(fi, oldstate);
-		}
-		ccw_check_return_code(ch, rc, "HaltIO in ch_action_haltio");
-	}
-}
-
-/**
- * A channel has successfully been halted.
- * Cleanup it's queue and notify interface statemachine.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_stopped(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	fsm_newstate(fi, CH_STATE_STOPPED);
-	if (ch->trans_skb != NULL) {
-		clear_normalized_cda(&ch->ccw[1]);
-		dev_kfree_skb(ch->trans_skb);
-		ch->trans_skb = NULL;
-	}
-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
-		skb_queue_purge(&ch->io_queue);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_RXDOWN, dev);
-	} else {
-		ctc_purge_skb_queue(&ch->io_queue);
-		spin_lock(&ch->collect_lock);
-		ctc_purge_skb_queue(&ch->collect_queue);
-		ch->collect_len = 0;
-		spin_unlock(&ch->collect_lock);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_TXDOWN, dev);
-	}
-}
-
-/**
- * A stop command from device statemachine arrived and we are in
- * not operational mode. Set state to stopped.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_stop(fsm_instance * fi, int event, void *arg)
-{
-	fsm_newstate(fi, CH_STATE_STOPPED);
-}
-
-/**
- * A machine check for no path, not operational status or gone device has
- * happened.
- * Cleanup queue and notify interface statemachine.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_fail(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	fsm_newstate(fi, CH_STATE_NOTOP);
-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
-		skb_queue_purge(&ch->io_queue);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_RXDOWN, dev);
-	} else {
-		ctc_purge_skb_queue(&ch->io_queue);
-		spin_lock(&ch->collect_lock);
-		ctc_purge_skb_queue(&ch->collect_queue);
-		ch->collect_len = 0;
-		spin_unlock(&ch->collect_lock);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_TXDOWN, dev);
-	}
-}
-
-/**
- * Handle error during setup of channel.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_setuperr(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(setup, 3, __FUNCTION__);
-	/**
-	 * Special case: Got UC_RCRESET on setmode.
-	 * This means that remote side isn't setup. In this case
-	 * simply retry after some 10 secs...
-	 */
-	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&
-	    ((event == CH_EVENT_UC_RCRESET) ||
-	     (event == CH_EVENT_UC_RSRESET))) {
-		fsm_newstate(fi, CH_STATE_STARTRETRY);
-		fsm_deltimer(&ch->timer);
-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
-		if (CHANNEL_DIRECTION(ch->flags) == READ) {
-			int rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
-			if (rc != 0)
-				ccw_check_return_code(
-					ch, rc, "HaltIO in ch_action_setuperr");
-		}
-		return;
-	}
-
-	ctc_pr_debug("%s: Error %s during %s channel setup state=%s\n",
-		     dev->name, ch_event_names[event],
-		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
-		     fsm_getstate_str(fi));
-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
-		fsm_newstate(fi, CH_STATE_RXERR);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_RXDOWN, dev);
-	} else {
-		fsm_newstate(fi, CH_STATE_TXERR);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_TXDOWN, dev);
-	}
-}
-
-/**
- * Restart a channel after an error.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_restart(fsm_instance * fi, int event, void *arg)
-{
-	unsigned long saveflags;
-	int oldstate;
-	int rc;
-
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	ctc_pr_debug("%s: %s channel restart\n", dev->name,
-		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
-	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
-	oldstate = fsm_getstate(fi);
-	fsm_newstate(fi, CH_STATE_STARTWAIT);
-	saveflags = 0;	/* avoids compiler warning with
-			   spin_unlock_irqrestore */
-	if (event == CH_EVENT_TIMER)	// only for timer not yet locked
-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
-	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
-	if (event == CH_EVENT_TIMER)
-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
-	if (rc != 0) {
-		if (rc != -EBUSY) {
-		    fsm_deltimer(&ch->timer);
-		    fsm_newstate(fi, oldstate);
-		}
-		ccw_check_return_code(ch, rc, "HaltIO in ch_action_restart");
-	}
-}
-
-/**
- * Handle error during RX initial handshake (exchange of
- * 0-length block header)
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_rxiniterr(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(setup, 3, __FUNCTION__);
-	if (event == CH_EVENT_TIMER) {
-		fsm_deltimer(&ch->timer);
-		ctc_pr_debug("%s: Timeout during RX init handshake\n", dev->name);
-		if (ch->retry++ < 3)
-			ch_action_restart(fi, event, arg);
-		else {
-			fsm_newstate(fi, CH_STATE_RXERR);
-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-				  DEV_EVENT_RXDOWN, dev);
-		}
-	} else
-		ctc_pr_warn("%s: Error during RX init handshake\n", dev->name);
-}
-
-/**
- * Notify device statemachine if we gave up initialization
- * of RX channel.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_rxinitfail(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(setup, 3, __FUNCTION__);
-	fsm_newstate(fi, CH_STATE_RXERR);
-	ctc_pr_warn("%s: RX initialization failed\n", dev->name);
-	ctc_pr_warn("%s: RX <-> RX connection detected\n", dev->name);
-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
-}
-
-/**
- * Handle RX Unit check remote reset (remote disconnected)
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_rxdisc(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct channel *ch2;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	ctc_pr_debug("%s: Got remote disconnect, re-initializing ...\n",
-		     dev->name);
-
-	/**
-	 * Notify device statemachine
-	 */
-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
-
-	fsm_newstate(fi, CH_STATE_DTERM);
-	ch2 = ((struct ctc_priv *) dev->priv)->channel[WRITE];
-	fsm_newstate(ch2->fsm, CH_STATE_DTERM);
-
-	ccw_device_halt(ch->cdev, (unsigned long) ch);
-	ccw_device_halt(ch2->cdev, (unsigned long) ch2);
-}
-
-/**
- * Handle error during TX channel initialization.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_txiniterr(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(setup, 2, __FUNCTION__);
-	if (event == CH_EVENT_TIMER) {
-		fsm_deltimer(&ch->timer);
-		ctc_pr_debug("%s: Timeout during TX init handshake\n", dev->name);
-		if (ch->retry++ < 3)
-			ch_action_restart(fi, event, arg);
-		else {
-			fsm_newstate(fi, CH_STATE_TXERR);
-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-				  DEV_EVENT_TXDOWN, dev);
-		}
-	} else
-		ctc_pr_warn("%s: Error during TX init handshake\n", dev->name);
-}
-
-/**
- * Handle TX timeout by retrying operation.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_txretry(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-	unsigned long saveflags;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	if (ch->retry++ > 3) {
-		ctc_pr_debug("%s: TX retry failed, restarting channel\n",
-			     dev->name);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_TXDOWN, dev);
-		ch_action_restart(fi, event, arg);
-	} else {
-		struct sk_buff *skb;
-
-		ctc_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
-		if ((skb = skb_peek(&ch->io_queue))) {
-			int rc = 0;
-
-			clear_normalized_cda(&ch->ccw[4]);
-			ch->ccw[4].count = skb->len;
-			if (set_normalized_cda(&ch->ccw[4], skb->data)) {
-				ctc_pr_debug(
-					"%s: IDAL alloc failed, chan restart\n",
-					dev->name);
-				fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-					  DEV_EVENT_TXDOWN, dev);
-				ch_action_restart(fi, event, arg);
-				return;
-			}
-			fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
-			saveflags = 0;	/* avoids compiler warning with
-					   spin_unlock_irqrestore */
-			if (event == CH_EVENT_TIMER) // only for TIMER not yet locked
-				spin_lock_irqsave(get_ccwdev_lock(ch->cdev),
-						  saveflags);
-			rc = ccw_device_start(ch->cdev, &ch->ccw[3],
-					      (unsigned long) ch, 0xff, 0);
-			if (event == CH_EVENT_TIMER)
-				spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),
-						       saveflags);
-			if (rc != 0) {
-				fsm_deltimer(&ch->timer);
-				ccw_check_return_code(ch, rc, "TX in ch_action_txretry");
-				ctc_purge_skb_queue(&ch->io_queue);
-			}
-		}
-	}
-
-}
-
-/**
- * Handle fatal errors during an I/O command.
- *
- * @param fi    An instance of a channel statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from channel * upon call.
- */
-static void
-ch_action_iofatal(fsm_instance * fi, int event, void *arg)
-{
-	struct channel *ch = (struct channel *) arg;
-	struct net_device *dev = ch->netdev;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	fsm_deltimer(&ch->timer);
-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
-		ctc_pr_debug("%s: RX I/O error\n", dev->name);
-		fsm_newstate(fi, CH_STATE_RXERR);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_RXDOWN, dev);
-	} else {
-		ctc_pr_debug("%s: TX I/O error\n", dev->name);
-		fsm_newstate(fi, CH_STATE_TXERR);
-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
-			  DEV_EVENT_TXDOWN, dev);
-	}
-}
-
-static void
-ch_action_reinit(fsm_instance *fi, int event, void *arg)
-{
- 	struct channel *ch = (struct channel *)arg;
- 	struct net_device *dev = ch->netdev;
- 	struct ctc_priv *privptr = dev->priv;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
- 	ch_action_iofatal(fi, event, arg);
- 	fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
-}
-
-/**
- * The statemachine for a channel.
- */
-static const fsm_node ch_fsm[] = {
-	{CH_STATE_STOPPED,    CH_EVENT_STOP,       fsm_action_nop       },
-	{CH_STATE_STOPPED,    CH_EVENT_START,      ch_action_start      },
-	{CH_STATE_STOPPED,    CH_EVENT_FINSTAT,    fsm_action_nop       },
-	{CH_STATE_STOPPED,    CH_EVENT_MC_FAIL,    fsm_action_nop       },
-
-	{CH_STATE_NOTOP,      CH_EVENT_STOP,       ch_action_stop       },
-	{CH_STATE_NOTOP,      CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_NOTOP,      CH_EVENT_FINSTAT,    fsm_action_nop       },
-	{CH_STATE_NOTOP,      CH_EVENT_MC_FAIL,    fsm_action_nop       },
-	{CH_STATE_NOTOP,      CH_EVENT_MC_GOOD,    ch_action_start      },
-
-	{CH_STATE_STARTWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_STARTWAIT,  CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_STARTWAIT,  CH_EVENT_FINSTAT,    ch_action_setmode    },
-	{CH_STATE_STARTWAIT,  CH_EVENT_TIMER,      ch_action_setuperr   },
-	{CH_STATE_STARTWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
-	{CH_STATE_STARTWAIT,  CH_EVENT_IO_EIO,     ch_action_reinit     },
-	{CH_STATE_STARTWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_STARTRETRY, CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_STARTRETRY, CH_EVENT_TIMER,      ch_action_setmode    },
-	{CH_STATE_STARTRETRY, CH_EVENT_FINSTAT,    fsm_action_nop       },
-	{CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_SETUPWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_FINSTAT,    ch_action_firstio    },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_UC_RCRESET, ch_action_setuperr   },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_UC_RSRESET, ch_action_setuperr   },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_TIMER,      ch_action_setmode    },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_IO_EIO,     ch_action_reinit     },
-	{CH_STATE_SETUPWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_RXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_RXINIT,     CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_RXINIT,     CH_EVENT_FINSTAT,    ch_action_rxidle     },
-	{CH_STATE_RXINIT,     CH_EVENT_UC_RCRESET, ch_action_rxiniterr  },
-	{CH_STATE_RXINIT,     CH_EVENT_UC_RSRESET, ch_action_rxiniterr  },
-	{CH_STATE_RXINIT,     CH_EVENT_TIMER,      ch_action_rxiniterr  },
-	{CH_STATE_RXINIT,     CH_EVENT_ATTNBUSY,   ch_action_rxinitfail },
-	{CH_STATE_RXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
-	{CH_STATE_RXINIT,     CH_EVENT_IO_EIO,     ch_action_reinit     },
-	{CH_STATE_RXINIT,     CH_EVENT_UC_ZERO,    ch_action_firstio    },
-	{CH_STATE_RXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_RXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_RXIDLE,     CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_RXIDLE,     CH_EVENT_FINSTAT,    ch_action_rx         },
-	{CH_STATE_RXIDLE,     CH_EVENT_UC_RCRESET, ch_action_rxdisc     },
-//      {CH_STATE_RXIDLE,     CH_EVENT_UC_RSRESET, ch_action_rxretry    },
-	{CH_STATE_RXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
-	{CH_STATE_RXIDLE,     CH_EVENT_IO_EIO,     ch_action_reinit     },
-	{CH_STATE_RXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },
-	{CH_STATE_RXIDLE,     CH_EVENT_UC_ZERO,    ch_action_rx         },
-
-	{CH_STATE_TXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_TXINIT,     CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_TXINIT,     CH_EVENT_FINSTAT,    ch_action_txidle     },
-	{CH_STATE_TXINIT,     CH_EVENT_UC_RCRESET, ch_action_txiniterr  },
-	{CH_STATE_TXINIT,     CH_EVENT_UC_RSRESET, ch_action_txiniterr  },
-	{CH_STATE_TXINIT,     CH_EVENT_TIMER,      ch_action_txiniterr  },
-	{CH_STATE_TXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
-	{CH_STATE_TXINIT,     CH_EVENT_IO_EIO,     ch_action_reinit     },
-	{CH_STATE_TXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_TXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_TXIDLE,     CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_TXIDLE,     CH_EVENT_FINSTAT,    ch_action_firstio    },
-	{CH_STATE_TXIDLE,     CH_EVENT_UC_RCRESET, fsm_action_nop       },
-	{CH_STATE_TXIDLE,     CH_EVENT_UC_RSRESET, fsm_action_nop       },
-	{CH_STATE_TXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
-	{CH_STATE_TXIDLE,     CH_EVENT_IO_EIO,     ch_action_reinit     },
-	{CH_STATE_TXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_TERM,       CH_EVENT_STOP,       fsm_action_nop       },
-	{CH_STATE_TERM,       CH_EVENT_START,      ch_action_restart    },
-	{CH_STATE_TERM,       CH_EVENT_FINSTAT,    ch_action_stopped    },
-	{CH_STATE_TERM,       CH_EVENT_UC_RCRESET, fsm_action_nop       },
-	{CH_STATE_TERM,       CH_EVENT_UC_RSRESET, fsm_action_nop       },
-	{CH_STATE_TERM,       CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_DTERM,      CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_DTERM,      CH_EVENT_START,      ch_action_restart    },
-	{CH_STATE_DTERM,      CH_EVENT_FINSTAT,    ch_action_setmode    },
-	{CH_STATE_DTERM,      CH_EVENT_UC_RCRESET, fsm_action_nop       },
-	{CH_STATE_DTERM,      CH_EVENT_UC_RSRESET, fsm_action_nop       },
-	{CH_STATE_DTERM,      CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_TX,         CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_TX,         CH_EVENT_START,      fsm_action_nop       },
-	{CH_STATE_TX,         CH_EVENT_FINSTAT,    ch_action_txdone     },
-	{CH_STATE_TX,         CH_EVENT_UC_RCRESET, ch_action_txretry    },
-	{CH_STATE_TX,         CH_EVENT_UC_RSRESET, ch_action_txretry    },
-	{CH_STATE_TX,         CH_EVENT_TIMER,      ch_action_txretry    },
-	{CH_STATE_TX,         CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
-	{CH_STATE_TX,         CH_EVENT_IO_EIO,     ch_action_reinit     },
-	{CH_STATE_TX,         CH_EVENT_MC_FAIL,    ch_action_fail       },
-
-	{CH_STATE_RXERR,      CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_TXERR,      CH_EVENT_STOP,       ch_action_haltio     },
-	{CH_STATE_TXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },
-	{CH_STATE_RXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },
-};
-
-static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
-
-/**
- * Functions related to setup and device detection.
- *****************************************************************************/
-
-static inline int
-less_than(char *id1, char *id2)
-{
-	int dev1, dev2, i;
-
-	for (i = 0; i < 5; i++) {
-		id1++;
-		id2++;
-	}
-	dev1 = simple_strtoul(id1, &id1, 16);
-	dev2 = simple_strtoul(id2, &id2, 16);
-
-	return (dev1 < dev2);
-}
-
-/**
- * Add a new channel to the list of channels.
- * Keeps the channel list sorted.
- *
- * @param cdev  The ccw_device to be added.
- * @param type  The type class of the new channel.
- *
- * @return 0 on success, !0 on error.
- */
-static int
-add_channel(struct ccw_device *cdev, enum channel_types type)
-{
-	struct channel **c = &channels;
-	struct channel *ch;
-
-	DBF_TEXT(trace, 2, __FUNCTION__);
-	ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
-	if (!ch) {
-		ctc_pr_warn("ctc: Out of memory in add_channel\n");
-		return -1;
-	}
-	/* assure all flags and counters are reset */
-	ch->ccw = kzalloc(8 * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
-	if (!ch->ccw) {
-		kfree(ch);
-		ctc_pr_warn("ctc: Out of memory in add_channel\n");
-		return -1;
-	}
-
-
-	/**
-	 * "static" ccws are used in the following way:
-	 *
-	 * ccw[0..2] (Channel program for generic I/O):
-	 *           0: prepare
-	 *           1: read or write (depending on direction) with fixed
-	 *              buffer (idal allocated once when buffer is allocated)
-	 *           2: nop
-	 * ccw[3..5] (Channel program for direct write of packets)
-	 *           3: prepare
-	 *           4: write (idal allocated on every write).
-	 *           5: nop
-	 * ccw[6..7] (Channel program for initial channel setup):
-	 *           6: set extended mode
-	 *           7: nop
-	 *
-	 * ch->ccw[0..5] are initialized in ch_action_start because
-	 * the channel's direction is yet unknown here.
-	 */
-	ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;
-	ch->ccw[6].flags = CCW_FLAG_SLI;
-
-	ch->ccw[7].cmd_code = CCW_CMD_NOOP;
-	ch->ccw[7].flags = CCW_FLAG_SLI;
-
-	ch->cdev = cdev;
-	snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
-	ch->type = type;
-	ch->fsm = init_fsm(ch->id, ch_state_names,
-			   ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
-			   ch_fsm, CH_FSM_LEN, GFP_KERNEL);
-	if (ch->fsm == NULL) {
-		ctc_pr_warn("ctc: Could not create FSM in add_channel\n");
-		kfree(ch->ccw);
-		kfree(ch);
-		return -1;
-	}
-	fsm_newstate(ch->fsm, CH_STATE_IDLE);
-	ch->irb = kzalloc(sizeof(struct irb), GFP_KERNEL);
-	if (!ch->irb) {
-		ctc_pr_warn("ctc: Out of memory in add_channel\n");
-		kfree_fsm(ch->fsm);
-		kfree(ch->ccw);
-		kfree(ch);
-		return -1;
-	}
-	while (*c && less_than((*c)->id, ch->id))
-		c = &(*c)->next;
-	if (*c && (!strncmp((*c)->id, ch->id, CTC_ID_SIZE))) {
-		ctc_pr_debug(
-			"ctc: add_channel: device %s already in list, "
-			"using old entry\n", (*c)->id);
-		kfree(ch->irb);
-		kfree_fsm(ch->fsm);
-		kfree(ch->ccw);
-		kfree(ch);
-		return 0;
-	}
-
-	spin_lock_init(&ch->collect_lock);
-
-	fsm_settimer(ch->fsm, &ch->timer);
-	skb_queue_head_init(&ch->io_queue);
-	skb_queue_head_init(&ch->collect_queue);
-	ch->next = *c;
-	*c = ch;
-	return 0;
-}
-
-/**
- * Release a specific channel in the channel list.
- *
- * @param ch Pointer to channel struct to be released.
- */
-static void
-channel_free(struct channel *ch)
-{
-	ch->flags &= ~CHANNEL_FLAGS_INUSE;
-	fsm_newstate(ch->fsm, CH_STATE_IDLE);
-}
-
-/**
- * Remove a specific channel in the channel list.
- *
- * @param ch Pointer to channel struct to be released.
- */
-static void
-channel_remove(struct channel *ch)
-{
-	struct channel **c = &channels;
-
-	DBF_TEXT(trace, 2, __FUNCTION__);
-	if (ch == NULL)
-		return;
-
-	channel_free(ch);
-	while (*c) {
-		if (*c == ch) {
-			*c = ch->next;
-			fsm_deltimer(&ch->timer);
-			kfree_fsm(ch->fsm);
-			clear_normalized_cda(&ch->ccw[4]);
-			if (ch->trans_skb != NULL) {
-				clear_normalized_cda(&ch->ccw[1]);
-				dev_kfree_skb(ch->trans_skb);
-			}
-			kfree(ch->ccw);
-			kfree(ch->irb);
-			kfree(ch);
-			return;
-		}
-		c = &((*c)->next);
-	}
-}
-
-/**
- * Get a specific channel from the channel list.
- *
- * @param type Type of channel we are interested in.
- * @param id Id of channel we are interested in.
- * @param direction Direction we want to use this channel for.
- *
- * @return Pointer to a channel or NULL if no matching channel available.
- */
-static struct channel
-*
-channel_get(enum channel_types type, char *id, int direction)
-{
-	struct channel *ch = channels;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-#ifdef DEBUG
-	ctc_pr_debug("ctc: %s(): searching for ch with id %s and type %d\n",
-		     __func__, id, type);
-#endif
-
-	while (ch && ((strncmp(ch->id, id, CTC_ID_SIZE)) || (ch->type != type))) {
-#ifdef DEBUG
-		ctc_pr_debug("ctc: %s(): ch=0x%p (id=%s, type=%d\n",
-			     __func__, ch, ch->id, ch->type);
-#endif
-		ch = ch->next;
-	}
-#ifdef DEBUG
-	ctc_pr_debug("ctc: %s(): ch=0x%pq (id=%s, type=%d\n",
-		     __func__, ch, ch->id, ch->type);
-#endif
-	if (!ch) {
-		ctc_pr_warn("ctc: %s(): channel with id %s "
-			    "and type %d not found in channel list\n",
-			    __func__, id, type);
-	} else {
-		if (ch->flags & CHANNEL_FLAGS_INUSE)
-			ch = NULL;
-		else {
-			ch->flags |= CHANNEL_FLAGS_INUSE;
-			ch->flags &= ~CHANNEL_FLAGS_RWMASK;
-			ch->flags |= (direction == WRITE)
-			    ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
-			fsm_newstate(ch->fsm, CH_STATE_STOPPED);
-		}
-	}
-	return ch;
-}
-
-/**
- * Return the channel type by name.
- *
- * @param name Name of network interface.
- *
- * @return Type class of channel to be used for that interface.
- */
-static enum channel_types inline
-extract_channel_media(char *name)
-{
-	enum channel_types ret = channel_type_unknown;
-
-	if (name != NULL) {
-		if (strncmp(name, "ctc", 3) == 0)
-			ret = channel_type_parallel;
-		if (strncmp(name, "escon", 5) == 0)
-			ret = channel_type_escon;
-	}
-	return ret;
-}
-
-static long
-__ctc_check_irb_error(struct ccw_device *cdev, struct irb *irb)
-{
-	if (!IS_ERR(irb))
-		return 0;
-
-	switch (PTR_ERR(irb)) {
-	case -EIO:
-		ctc_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
-//		CTC_DBF_TEXT(trace, 2, "ckirberr");
-//		CTC_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
-		break;
-	case -ETIMEDOUT:
-		ctc_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
-//		CTC_DBF_TEXT(trace, 2, "ckirberr");
-//		CTC_DBF_TEXT_(trace, 2, "  rc%d", -ETIMEDOUT);
-		break;
-	default:
-		ctc_pr_warn("unknown error %ld on device %s\n", PTR_ERR(irb),
-			   cdev->dev.bus_id);
-//		CTC_DBF_TEXT(trace, 2, "ckirberr");
-//		CTC_DBF_TEXT(trace, 2, "  rc???");
-	}
-	return PTR_ERR(irb);
-}
-
-/**
- * Main IRQ handler.
- *
- * @param cdev    The ccw_device the interrupt is for.
- * @param intparm interruption parameter.
- * @param irb     interruption response block.
- */
-static void
-ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
-{
-	struct channel *ch;
-	struct net_device *dev;
-	struct ctc_priv *priv;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if (__ctc_check_irb_error(cdev, irb))
-		return;
-
-	/* Check for unsolicited interrupts. */
-	if (!cdev->dev.driver_data) {
-		ctc_pr_warn("ctc: Got unsolicited irq: %s c-%02x d-%02x\n",
-			    cdev->dev.bus_id, irb->scsw.cstat,
-			    irb->scsw.dstat);
-		return;
-	}
-
-	priv = ((struct ccwgroup_device *)cdev->dev.driver_data)
-		->dev.driver_data;
-
-	/* Try to extract channel from driver data. */
-	if (priv->channel[READ]->cdev == cdev)
-		ch = priv->channel[READ];
-	else if (priv->channel[WRITE]->cdev == cdev)
-		ch = priv->channel[WRITE];
-	else {
-		ctc_pr_err("ctc: Can't determine channel for interrupt, "
-			   "device %s\n", cdev->dev.bus_id);
-		return;
-	}
-
-	dev = (struct net_device *) (ch->netdev);
-	if (dev == NULL) {
-		ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n",
-			    cdev->dev.bus_id, ch);
-		return;
-	}
-
-#ifdef DEBUG
-	ctc_pr_debug("%s: interrupt for device: %s received c-%02x d-%02x\n",
-		     dev->name, ch->id, irb->scsw.cstat, irb->scsw.dstat);
-#endif
-
-	/* Copy interruption response block. */
-	memcpy(ch->irb, irb, sizeof(struct irb));
-
-	/* Check for good subchannel return code, otherwise error message */
-	if (ch->irb->scsw.cstat) {
-		fsm_event(ch->fsm, CH_EVENT_SC_UNKNOWN, ch);
-		ctc_pr_warn("%s: subchannel check for device: %s - %02x %02x\n",
-			    dev->name, ch->id, ch->irb->scsw.cstat,
-			    ch->irb->scsw.dstat);
-		return;
-	}
-
-	/* Check the reason-code of a unit check */
-	if (ch->irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
-		ccw_unit_check(ch, ch->irb->ecw[0]);
-		return;
-	}
-	if (ch->irb->scsw.dstat & DEV_STAT_BUSY) {
-		if (ch->irb->scsw.dstat & DEV_STAT_ATTENTION)
-			fsm_event(ch->fsm, CH_EVENT_ATTNBUSY, ch);
-		else
-			fsm_event(ch->fsm, CH_EVENT_BUSY, ch);
-		return;
-	}
-	if (ch->irb->scsw.dstat & DEV_STAT_ATTENTION) {
-		fsm_event(ch->fsm, CH_EVENT_ATTN, ch);
-		return;
-	}
-	if ((ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
-	    (ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
-	    (ch->irb->scsw.stctl ==
-	     (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
-		fsm_event(ch->fsm, CH_EVENT_FINSTAT, ch);
-	else
-		fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
-
-}
-
-/**
- * Actions for interface - statemachine.
- *****************************************************************************/
-
-/**
- * Startup channels by sending CH_EVENT_START to each channel.
- *
- * @param fi    An instance of an interface statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from struct net_device * upon call.
- */
-static void
-dev_action_start(fsm_instance * fi, int event, void *arg)
-{
-	struct net_device *dev = (struct net_device *) arg;
-	struct ctc_priv *privptr = dev->priv;
-	int direction;
-
-	DBF_TEXT(setup, 3, __FUNCTION__);
-	fsm_deltimer(&privptr->restart_timer);
-	fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
-	for (direction = READ; direction <= WRITE; direction++) {
-		struct channel *ch = privptr->channel[direction];
-		fsm_event(ch->fsm, CH_EVENT_START, ch);
-	}
-}
-
-/**
- * Shutdown channels by sending CH_EVENT_STOP to each channel.
- *
- * @param fi    An instance of an interface statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from struct net_device * upon call.
- */
-static void
-dev_action_stop(fsm_instance * fi, int event, void *arg)
-{
-	struct net_device *dev = (struct net_device *) arg;
-	struct ctc_priv *privptr = dev->priv;
-	int direction;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
-	for (direction = READ; direction <= WRITE; direction++) {
-		struct channel *ch = privptr->channel[direction];
-		fsm_event(ch->fsm, CH_EVENT_STOP, ch);
-	}
-}
-static void
-dev_action_restart(fsm_instance *fi, int event, void *arg)
-{
-	struct net_device *dev = (struct net_device *)arg;
-	struct ctc_priv *privptr = dev->priv;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	ctc_pr_debug("%s: Restarting\n", dev->name);
-	dev_action_stop(fi, event, arg);
-	fsm_event(privptr->fsm, DEV_EVENT_STOP, dev);
-	fsm_addtimer(&privptr->restart_timer, CTC_TIMEOUT_5SEC,
-		     DEV_EVENT_START, dev);
-}
-
-/**
- * Called from channel statemachine
- * when a channel is up and running.
- *
- * @param fi    An instance of an interface statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from struct net_device * upon call.
- */
-static void
-dev_action_chup(fsm_instance * fi, int event, void *arg)
-{
-	struct net_device *dev = (struct net_device *) arg;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	switch (fsm_getstate(fi)) {
-		case DEV_STATE_STARTWAIT_RXTX:
-			if (event == DEV_EVENT_RXUP)
-				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
-			else
-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
-			break;
-		case DEV_STATE_STARTWAIT_RX:
-			if (event == DEV_EVENT_RXUP) {
-				fsm_newstate(fi, DEV_STATE_RUNNING);
-				ctc_pr_info("%s: connected with remote side\n",
-					    dev->name);
-				ctc_clear_busy(dev);
-			}
-			break;
-		case DEV_STATE_STARTWAIT_TX:
-			if (event == DEV_EVENT_TXUP) {
-				fsm_newstate(fi, DEV_STATE_RUNNING);
-				ctc_pr_info("%s: connected with remote side\n",
-					    dev->name);
-				ctc_clear_busy(dev);
-			}
-			break;
-		case DEV_STATE_STOPWAIT_TX:
-			if (event == DEV_EVENT_RXUP)
-				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
-			break;
-		case DEV_STATE_STOPWAIT_RX:
-			if (event == DEV_EVENT_TXUP)
-				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
-			break;
-	}
-}
-
-/**
- * Called from channel statemachine
- * when a channel has been shutdown.
- *
- * @param fi    An instance of an interface statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from struct net_device * upon call.
- */
-static void
-dev_action_chdown(fsm_instance * fi, int event, void *arg)
-{
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	switch (fsm_getstate(fi)) {
-		case DEV_STATE_RUNNING:
-			if (event == DEV_EVENT_TXDOWN)
-				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
-			else
-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
-			break;
-		case DEV_STATE_STARTWAIT_RX:
-			if (event == DEV_EVENT_TXDOWN)
-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
-			break;
-		case DEV_STATE_STARTWAIT_TX:
-			if (event == DEV_EVENT_RXDOWN)
-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
-			break;
-		case DEV_STATE_STOPWAIT_RXTX:
-			if (event == DEV_EVENT_TXDOWN)
-				fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
-			else
-				fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
-			break;
-		case DEV_STATE_STOPWAIT_RX:
-			if (event == DEV_EVENT_RXDOWN)
-				fsm_newstate(fi, DEV_STATE_STOPPED);
-			break;
-		case DEV_STATE_STOPWAIT_TX:
-			if (event == DEV_EVENT_TXDOWN)
-				fsm_newstate(fi, DEV_STATE_STOPPED);
-			break;
-	}
-}
-
-static const fsm_node dev_fsm[] = {
-	{DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start},
-
-	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_START,   dev_action_start   },
-	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RXDOWN,  dev_action_chdown  },
-	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_TXDOWN,  dev_action_chdown  },
- 	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_START,   dev_action_start   },
-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXUP,    dev_action_chup    },
-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_TXUP,    dev_action_chup    },
-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXDOWN,  dev_action_chdown  },
- 	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_START,   dev_action_start   },
-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RXUP,    dev_action_chup    },
-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXUP,    dev_action_chup    },
-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXDOWN,  dev_action_chdown  },
- 	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP,    dev_action_stop    },
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP,    dev_action_chup    },
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP,    dev_action_chup    },
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN,  dev_action_chdown  },
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN,  dev_action_chdown  },
- 	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_STOP,    dev_action_stop    },
-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXUP,    dev_action_chup    },
-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_TXUP,    dev_action_chup    },
-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXDOWN,  dev_action_chdown  },
- 	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_STOP,    dev_action_stop    },
-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RXUP,    dev_action_chup    },
-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXUP,    dev_action_chup    },
-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXDOWN,  dev_action_chdown  },
- 	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_RUNNING,        DEV_EVENT_STOP,    dev_action_stop    },
-	{DEV_STATE_RUNNING,        DEV_EVENT_RXDOWN,  dev_action_chdown  },
-	{DEV_STATE_RUNNING,        DEV_EVENT_TXDOWN,  dev_action_chdown  },
-	{DEV_STATE_RUNNING,        DEV_EVENT_TXUP,    fsm_action_nop     },
-	{DEV_STATE_RUNNING,        DEV_EVENT_RXUP,    fsm_action_nop     },
- 	{DEV_STATE_RUNNING,        DEV_EVENT_RESTART, dev_action_restart },
-};
-
-static const int DEV_FSM_LEN = sizeof (dev_fsm) / sizeof (fsm_node);
-
-/**
- * Transmit a packet.
- * This is a helper function for ctc_tx().
- *
- * @param ch Channel to be used for sending.
- * @param skb Pointer to struct sk_buff of packet to send.
- *            The linklevel header has already been set up
- *            by ctc_tx().
- *
- * @return 0 on success, -ERRNO on failure. (Never fails.)
- */
-static int
-transmit_skb(struct channel *ch, struct sk_buff *skb)
-{
-	unsigned long saveflags;
-	struct ll_header header;
-	int rc = 0;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	/* we need to acquire the lock for testing the state
-	 * otherwise we can have an IRQ changing the state to
-	 * TXIDLE after the test but before acquiring the lock.
-	 */
-	spin_lock_irqsave(&ch->collect_lock, saveflags);
-	if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
-		int l = skb->len + LL_HEADER_LENGTH;
-
-		if (ch->collect_len + l > ch->max_bufsize - 2) {
-			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
-			return -EBUSY;
-		} else {
-			atomic_inc(&skb->users);
-			header.length = l;
-			header.type = skb->protocol;
-			header.unused = 0;
-			memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
-			       LL_HEADER_LENGTH);
-			skb_queue_tail(&ch->collect_queue, skb);
-			ch->collect_len += l;
-		}
-		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
-	} else {
-		__u16 block_len;
-		int ccw_idx;
-		struct sk_buff *nskb;
-		unsigned long hi;
-		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
-		/**
-		 * Protect skb against beeing free'd by upper
-		 * layers.
-		 */
-		atomic_inc(&skb->users);
-		ch->prof.txlen += skb->len;
-		header.length = skb->len + LL_HEADER_LENGTH;
-		header.type = skb->protocol;
-		header.unused = 0;
-		memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
-		       LL_HEADER_LENGTH);
-		block_len = skb->len + 2;
-		*((__u16 *) skb_push(skb, 2)) = block_len;
-
-		/**
-		 * IDAL support in CTC is broken, so we have to
-		 * care about skb's above 2G ourselves.
-		 */
-		hi = ((unsigned long)skb_tail_pointer(skb) +
-		      LL_HEADER_LENGTH) >> 31;
-		if (hi) {
-			nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
-			if (!nskb) {
-				atomic_dec(&skb->users);
-				skb_pull(skb, LL_HEADER_LENGTH + 2);
-				ctc_clear_busy(ch->netdev);
-				return -ENOMEM;
-			} else {
-				memcpy(skb_put(nskb, skb->len),
-				       skb->data, skb->len);
-				atomic_inc(&nskb->users);
-				atomic_dec(&skb->users);
-				dev_kfree_skb_irq(skb);
-				skb = nskb;
-			}
-		}
-
-		ch->ccw[4].count = block_len;
-		if (set_normalized_cda(&ch->ccw[4], skb->data)) {
-			/**
-			 * idal allocation failed, try via copying to
-			 * trans_skb. trans_skb usually has a pre-allocated
-			 * idal.
-			 */
-			if (ctc_checkalloc_buffer(ch, 1)) {
-				/**
-				 * Remove our header. It gets added
-				 * again on retransmit.
-				 */
-				atomic_dec(&skb->users);
-				skb_pull(skb, LL_HEADER_LENGTH + 2);
-				ctc_clear_busy(ch->netdev);
-				return -EBUSY;
-			}
-
-			skb_reset_tail_pointer(ch->trans_skb);
-			ch->trans_skb->len = 0;
-			ch->ccw[1].count = skb->len;
-			skb_copy_from_linear_data(skb, skb_put(ch->trans_skb,
-							       skb->len),
-						  skb->len);
-			atomic_dec(&skb->users);
-			dev_kfree_skb_irq(skb);
-			ccw_idx = 0;
-		} else {
-			skb_queue_tail(&ch->io_queue, skb);
-			ccw_idx = 3;
-		}
-		ch->retry = 0;
-		fsm_newstate(ch->fsm, CH_STATE_TX);
-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
-		ch->prof.send_stamp = current_kernel_time();
-		rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
-				      (unsigned long) ch, 0xff, 0);
-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
-		if (ccw_idx == 3)
-			ch->prof.doios_single++;
-		if (rc != 0) {
-			fsm_deltimer(&ch->timer);
-			ccw_check_return_code(ch, rc, "single skb TX");
-			if (ccw_idx == 3)
-				skb_dequeue_tail(&ch->io_queue);
-			/**
-			 * Remove our header. It gets added
-			 * again on retransmit.
-			 */
-			skb_pull(skb, LL_HEADER_LENGTH + 2);
-		} else {
-			if (ccw_idx == 0) {
-				struct net_device *dev = ch->netdev;
-				struct ctc_priv *privptr = dev->priv;
-				privptr->stats.tx_packets++;
-				privptr->stats.tx_bytes +=
-				    skb->len - LL_HEADER_LENGTH;
-			}
-		}
-	}
-
-	ctc_clear_busy(ch->netdev);
-	return rc;
-}
-
-/**
- * Interface API for upper network layers
- *****************************************************************************/
-
-/**
- * Open an interface.
- * Called from generic network layer when ifconfig up is run.
- *
- * @param dev Pointer to interface struct.
- *
- * @return 0 on success, -ERRNO on failure. (Never fails.)
- */
-static int
-ctc_open(struct net_device * dev)
-{
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_START, dev);
-	return 0;
-}
-
-/**
- * Close an interface.
- * Called from generic network layer when ifconfig down is run.
- *
- * @param dev Pointer to interface struct.
- *
- * @return 0 on success, -ERRNO on failure. (Never fails.)
- */
-static int
-ctc_close(struct net_device * dev)
-{
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_STOP, dev);
-	return 0;
-}
-
-/**
- * Start transmission of a packet.
- * Called from generic network device layer.
- *
- * @param skb Pointer to buffer containing the packet.
- * @param dev Pointer to interface struct.
- *
- * @return 0 if packet consumed, !0 if packet rejected.
- *         Note: If we return !0, then the packet is free'd by
- *               the generic network layer.
- */
-static int
-ctc_tx(struct sk_buff *skb, struct net_device * dev)
-{
-	int rc = 0;
-	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	/**
-	 * Some sanity checks ...
-	 */
-	if (skb == NULL) {
-		ctc_pr_warn("%s: NULL sk_buff passed\n", dev->name);
-		privptr->stats.tx_dropped++;
-		return 0;
-	}
-	if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
-		ctc_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
-			    dev->name, LL_HEADER_LENGTH + 2);
-		dev_kfree_skb(skb);
-		privptr->stats.tx_dropped++;
-		return 0;
-	}
-
-	/**
-	 * If channels are not running, try to restart them
-	 * and throw away packet.
-	 */
-	if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
-		fsm_event(privptr->fsm, DEV_EVENT_START, dev);
-		dev_kfree_skb(skb);
-		privptr->stats.tx_dropped++;
-		privptr->stats.tx_errors++;
-		privptr->stats.tx_carrier_errors++;
-		return 0;
-	}
-
-	if (ctc_test_and_set_busy(dev))
-		return -EBUSY;
-
-	dev->trans_start = jiffies;
-	if (transmit_skb(privptr->channel[WRITE], skb) != 0)
-		rc = 1;
-	return rc;
-}
-
-/**
- * Sets MTU of an interface.
- *
- * @param dev     Pointer to interface struct.
- * @param new_mtu The new MTU to use for this interface.
- *
- * @return 0 on success, -EINVAL if MTU is out of valid range.
- *         (valid range is 576 .. 65527). If VM is on the
- *         remote side, maximum MTU is 32760, however this is
- *         <em>not</em> checked here.
- */
-static int
-ctc_change_mtu(struct net_device * dev, int new_mtu)
-{
-	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	if ((new_mtu < 576) || (new_mtu > 65527) ||
-	    (new_mtu > (privptr->channel[READ]->max_bufsize -
-			LL_HEADER_LENGTH - 2)))
-		return -EINVAL;
-	dev->mtu = new_mtu;
-	dev->hard_header_len = LL_HEADER_LENGTH + 2;
-	return 0;
-}
-
-/**
- * Returns interface statistics of a device.
- *
- * @param dev Pointer to interface struct.
- *
- * @return Pointer to stats struct of this interface.
- */
-static struct net_device_stats *
-ctc_stats(struct net_device * dev)
-{
-	return &((struct ctc_priv *) dev->priv)->stats;
-}
-
-/*
- * sysfs attributes
- */
-
-static ssize_t
-buffer_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct ctc_priv *priv;
-
-	priv = dev->driver_data;
-	if (!priv)
-		return -ENODEV;
-	return sprintf(buf, "%d\n",
-			priv->buffer_size);
-}
-
-static ssize_t
-buffer_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct ctc_priv *priv;
-	struct net_device *ndev;
-	int bs1;
-	char buffer[16];
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	DBF_TEXT(trace, 3, buf);
-	priv = dev->driver_data;
-	if (!priv) {
-		DBF_TEXT(trace, 3, "bfnopriv");
-		return -ENODEV;
-	}
-
-	sscanf(buf, "%u", &bs1);
-	if (bs1 > CTC_BUFSIZE_LIMIT)
-		goto einval;
-	if (bs1 < (576 + LL_HEADER_LENGTH + 2))
-		goto einval;
-	priv->buffer_size = bs1;	// just to overwrite the default
-
-	ndev = priv->channel[READ]->netdev;
-	if (!ndev) {
-		DBF_TEXT(trace, 3, "bfnondev");
-		return -ENODEV;
-	}
-
-	if ((ndev->flags & IFF_RUNNING) &&
-	    (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
-		goto einval;
-
-	priv->channel[READ]->max_bufsize = bs1;
-	priv->channel[WRITE]->max_bufsize = bs1;
-	if (!(ndev->flags & IFF_RUNNING))
-		ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
-	priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
-	priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
-
-	sprintf(buffer, "%d",priv->buffer_size);
-	DBF_TEXT(trace, 3, buffer);
-	return count;
-
-einval:
-	DBF_TEXT(trace, 3, "buff_err");
-	return -EINVAL;
-}
-
-static ssize_t
-loglevel_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n", loglevel);
-}
-
-static ssize_t
-loglevel_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	int ll1;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	sscanf(buf, "%i", &ll1);
-
-	if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
-		return -EINVAL;
-	loglevel = ll1;
-	return count;
-}
-
-static void
-ctc_print_statistics(struct ctc_priv *priv)
-{
-	char *sbuf;
-	char *p;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (!priv)
-		return;
-	sbuf = kmalloc(2048, GFP_KERNEL);
-	if (sbuf == NULL)
-		return;
-	p = sbuf;
-
-	p += sprintf(p, "  Device FSM state: %s\n",
-		     fsm_getstate_str(priv->fsm));
-	p += sprintf(p, "  RX channel FSM state: %s\n",
-		     fsm_getstate_str(priv->channel[READ]->fsm));
-	p += sprintf(p, "  TX channel FSM state: %s\n",
-		     fsm_getstate_str(priv->channel[WRITE]->fsm));
-	p += sprintf(p, "  Max. TX buffer used: %ld\n",
-		     priv->channel[WRITE]->prof.maxmulti);
-	p += sprintf(p, "  Max. chained SKBs: %ld\n",
-		     priv->channel[WRITE]->prof.maxcqueue);
-	p += sprintf(p, "  TX single write ops: %ld\n",
-		     priv->channel[WRITE]->prof.doios_single);
-	p += sprintf(p, "  TX multi write ops: %ld\n",
-		     priv->channel[WRITE]->prof.doios_multi);
-	p += sprintf(p, "  Netto bytes written: %ld\n",
-		     priv->channel[WRITE]->prof.txlen);
-	p += sprintf(p, "  Max. TX IO-time: %ld\n",
-		     priv->channel[WRITE]->prof.tx_time);
-
-	ctc_pr_debug("Statistics for %s:\n%s",
-		     priv->channel[WRITE]->netdev->name, sbuf);
-	kfree(sbuf);
-	return;
-}
-
-static ssize_t
-stats_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct ctc_priv *priv = dev->driver_data;
-	if (!priv)
-		return -ENODEV;
-	ctc_print_statistics(priv);
-	return sprintf(buf, "0\n");
-}
-
-static ssize_t
-stats_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct ctc_priv *priv = dev->driver_data;
-	if (!priv)
-		return -ENODEV;
-	/* Reset statistics */
-	memset(&priv->channel[WRITE]->prof, 0,
-			sizeof(priv->channel[WRITE]->prof));
-	return count;
-}
-
-static void
-ctc_netdev_unregister(struct net_device * dev)
-{
-	struct ctc_priv *privptr;
-
-	if (!dev)
-		return;
-	privptr = (struct ctc_priv *) dev->priv;
-	unregister_netdev(dev);
-}
-
-static int
-ctc_netdev_register(struct net_device * dev)
-{
-	return register_netdev(dev);
-}
-
-static void
-ctc_free_netdevice(struct net_device * dev, int free_dev)
-{
-	struct ctc_priv *privptr;
-	if (!dev)
-		return;
-	privptr = dev->priv;
-	if (privptr) {
-		if (privptr->fsm)
-			kfree_fsm(privptr->fsm);
-		kfree(privptr);
-	}
-#ifdef MODULE
-	if (free_dev)
-		free_netdev(dev);
-#endif
-}
-
-static ssize_t
-ctc_proto_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct ctc_priv *priv;
-
-	priv = dev->driver_data;
-	if (!priv)
-		return -ENODEV;
-
-	return sprintf(buf, "%d\n", priv->protocol);
-}
-
-static ssize_t
-ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct ctc_priv *priv;
-	int value;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	pr_debug("%s() called\n", __FUNCTION__);
-
-	priv = dev->driver_data;
-	if (!priv)
-		return -ENODEV;
-	sscanf(buf, "%u", &value);
-	if (!((value == CTC_PROTO_S390)  ||
-	      (value == CTC_PROTO_LINUX) ||
-	      (value == CTC_PROTO_OS390)))
-		return -EINVAL;
-	priv->protocol = value;
-
-	return count;
-}
-
-static ssize_t
-ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct ccwgroup_device *cgdev;
-
-	cgdev = to_ccwgroupdev(dev);
-	if (!cgdev)
-		return -ENODEV;
-
-	return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
-}
-
-static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
-static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
-static DEVICE_ATTR(type, 0444, ctc_type_show, NULL);
-
-static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
-static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
-
-static struct attribute *ctc_attr[] = {
-	&dev_attr_protocol.attr,
-	&dev_attr_type.attr,
-	&dev_attr_buffer.attr,
-	NULL,
-};
-
-static struct attribute_group ctc_attr_group = {
-	.attrs = ctc_attr,
-};
-
-static int
-ctc_add_attributes(struct device *dev)
-{
-	int rc;
-
-	rc = device_create_file(dev, &dev_attr_loglevel);
-	if (rc)
-		goto out;
-	rc = device_create_file(dev, &dev_attr_stats);
-	if (!rc)
-		goto out;
-	device_remove_file(dev, &dev_attr_loglevel);
-out:
-	return rc;
-}
-
-static void
-ctc_remove_attributes(struct device *dev)
-{
-	device_remove_file(dev, &dev_attr_stats);
-	device_remove_file(dev, &dev_attr_loglevel);
-}
-
-static int
-ctc_add_files(struct device *dev)
-{
-	pr_debug("%s() called\n", __FUNCTION__);
-
-	return sysfs_create_group(&dev->kobj, &ctc_attr_group);
-}
-
-static void
-ctc_remove_files(struct device *dev)
-{
-	pr_debug("%s() called\n", __FUNCTION__);
-
-	sysfs_remove_group(&dev->kobj, &ctc_attr_group);
-}
-
-/**
- * Add ctc specific attributes.
- * Add ctc private data.
- *
- * @param cgdev pointer to ccwgroup_device just added
- *
- * @returns 0 on success, !0 on failure.
- */
-static int
-ctc_probe_device(struct ccwgroup_device *cgdev)
-{
-	struct ctc_priv *priv;
-	int rc;
-	char buffer[16];
-
-	pr_debug("%s() called\n", __FUNCTION__);
-	DBF_TEXT(setup, 3, __FUNCTION__);
-
-	if (!get_device(&cgdev->dev))
-		return -ENODEV;
-
-	priv = kzalloc(sizeof(struct ctc_priv), GFP_KERNEL);
-	if (!priv) {
-		ctc_pr_err("%s: Out of memory\n", __func__);
-		put_device(&cgdev->dev);
-		return -ENOMEM;
-	}
-
-	rc = ctc_add_files(&cgdev->dev);
-	if (rc) {
-		kfree(priv);
-		put_device(&cgdev->dev);
-		return rc;
-	}
-	priv->buffer_size = CTC_BUFSIZE_DEFAULT;
-	cgdev->cdev[0]->handler = ctc_irq_handler;
-	cgdev->cdev[1]->handler = ctc_irq_handler;
-	cgdev->dev.driver_data = priv;
-
-	sprintf(buffer, "%p", priv);
-	DBF_TEXT(data, 3, buffer);
-
-	sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv));
-	DBF_TEXT(data, 3, buffer);
-
-	sprintf(buffer, "%p", &channels);
-	DBF_TEXT(data, 3, buffer);
-
-	sprintf(buffer, "%u", (unsigned int)sizeof(struct channel));
-	DBF_TEXT(data, 3, buffer);
-
-	return 0;
-}
-
-/**
- * Device setup function called by alloc_netdev().
- *
- * @param dev  Device to be setup.
- */
-void ctc_init_netdevice(struct net_device * dev)
-{
-	DBF_TEXT(setup, 3, __FUNCTION__);
-
-	if (dev->mtu == 0)
-		dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
-	dev->hard_start_xmit = ctc_tx;
-	dev->open = ctc_open;
-	dev->stop = ctc_close;
-	dev->get_stats = ctc_stats;
-	dev->change_mtu = ctc_change_mtu;
-	dev->hard_header_len = LL_HEADER_LENGTH + 2;
-	dev->addr_len = 0;
-	dev->type = ARPHRD_SLIP;
-	dev->tx_queue_len = 100;
-	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-}
-
-
-/**
- *
- * Setup an interface.
- *
- * @param cgdev  Device to be setup.
- *
- * @returns 0 on success, !0 on failure.
- */
-static int
-ctc_new_device(struct ccwgroup_device *cgdev)
-{
-	char read_id[CTC_ID_SIZE];
-	char write_id[CTC_ID_SIZE];
-	int direction;
-	enum channel_types type;
-	struct ctc_priv *privptr;
-	struct net_device *dev;
-	int ret;
-	char buffer[16];
-
-	pr_debug("%s() called\n", __FUNCTION__);
-	DBF_TEXT(setup, 3, __FUNCTION__);
-
-	privptr = cgdev->dev.driver_data;
-	if (!privptr)
-		return -ENODEV;
-
-	sprintf(buffer, "%d", privptr->buffer_size);
-	DBF_TEXT(setup, 3, buffer);
-
-	type = get_channel_type(&cgdev->cdev[0]->id);
-
-	snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
-	snprintf(write_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
-
-	if (add_channel(cgdev->cdev[0], type))
-		return -ENOMEM;
-	if (add_channel(cgdev->cdev[1], type))
-		return -ENOMEM;
-
-	ret = ccw_device_set_online(cgdev->cdev[0]);
-	if (ret != 0) {
-			printk(KERN_WARNING
-		 	"ccw_device_set_online (cdev[0]) failed with ret = %d\n", ret);
-	}
-
-	ret = ccw_device_set_online(cgdev->cdev[1]);
-	if (ret != 0) {
-			printk(KERN_WARNING
-		 	"ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret);
-	}
-
-	dev = alloc_netdev(0, "ctc%d", ctc_init_netdevice);
-	if (!dev) {
-		ctc_pr_warn("ctc_init_netdevice failed\n");
-		goto out;
-	}
-	dev->priv = privptr;
-
-	privptr->fsm = init_fsm("ctcdev", dev_state_names,
-			dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
-			dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
-	if (privptr->fsm == NULL) {
-		free_netdev(dev);
-		goto out;
-	}
-	fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
-	fsm_settimer(privptr->fsm, &privptr->restart_timer);
-
-	for (direction = READ; direction <= WRITE; direction++) {
-		privptr->channel[direction] =
-		    channel_get(type, direction == READ ? read_id : write_id,
-				direction);
-		if (privptr->channel[direction] == NULL) {
-			if (direction == WRITE)
-				channel_free(privptr->channel[READ]);
-
-			ctc_free_netdevice(dev, 1);
-			goto out;
-		}
-		privptr->channel[direction]->netdev = dev;
-		privptr->channel[direction]->protocol = privptr->protocol;
-		privptr->channel[direction]->max_bufsize = privptr->buffer_size;
-	}
-	/* sysfs magic */
-	SET_NETDEV_DEV(dev, &cgdev->dev);
-
-	if (ctc_netdev_register(dev) != 0) {
-		ctc_free_netdevice(dev, 1);
-		goto out;
-	}
-
-	if (ctc_add_attributes(&cgdev->dev)) {
-		ctc_netdev_unregister(dev);
-		dev->priv = NULL;
-		ctc_free_netdevice(dev, 1);
-		goto out;
-	}
-
-	strlcpy(privptr->fsm->name, dev->name, sizeof (privptr->fsm->name));
-
-	print_banner();
-
-	ctc_pr_info("%s: read: %s, write: %s, proto: %d\n",
-		    dev->name, privptr->channel[READ]->id,
-		    privptr->channel[WRITE]->id, privptr->protocol);
-
-	return 0;
-out:
-	ccw_device_set_offline(cgdev->cdev[1]);
-	ccw_device_set_offline(cgdev->cdev[0]);
-
-	return -ENODEV;
-}
-
-/**
- * Shutdown an interface.
- *
- * @param cgdev  Device to be shut down.
- *
- * @returns 0 on success, !0 on failure.
- */
-static int
-ctc_shutdown_device(struct ccwgroup_device *cgdev)
-{
-	struct ctc_priv *priv;
-	struct net_device *ndev;
-
-	DBF_TEXT(setup, 3, __FUNCTION__);
-	pr_debug("%s() called\n", __FUNCTION__);
-
-
-	priv = cgdev->dev.driver_data;
-	ndev = NULL;
-	if (!priv)
-		return -ENODEV;
-
-	if (priv->channel[READ]) {
-		ndev = priv->channel[READ]->netdev;
-
-		/* Close the device */
-		ctc_close(ndev);
-		ndev->flags &=~IFF_RUNNING;
-
-		ctc_remove_attributes(&cgdev->dev);
-
-		channel_free(priv->channel[READ]);
-	}
-	if (priv->channel[WRITE])
-		channel_free(priv->channel[WRITE]);
-
-	if (ndev) {
-		ctc_netdev_unregister(ndev);
-		ndev->priv = NULL;
-		ctc_free_netdevice(ndev, 1);
-	}
-
-	if (priv->fsm)
-		kfree_fsm(priv->fsm);
-
-	ccw_device_set_offline(cgdev->cdev[1]);
-	ccw_device_set_offline(cgdev->cdev[0]);
-
-	if (priv->channel[READ])
-		channel_remove(priv->channel[READ]);
-	if (priv->channel[WRITE])
-		channel_remove(priv->channel[WRITE]);
-	priv->channel[READ] = priv->channel[WRITE] = NULL;
-
-	return 0;
-
-}
-
-static void
-ctc_remove_device(struct ccwgroup_device *cgdev)
-{
-	struct ctc_priv *priv;
-
-	pr_debug("%s() called\n", __FUNCTION__);
-	DBF_TEXT(setup, 3, __FUNCTION__);
-
-	priv = cgdev->dev.driver_data;
-	if (!priv)
-		return;
-	if (cgdev->state == CCWGROUP_ONLINE)
-		ctc_shutdown_device(cgdev);
-	ctc_remove_files(&cgdev->dev);
-	cgdev->dev.driver_data = NULL;
-	kfree(priv);
-	put_device(&cgdev->dev);
-}
-
-static struct ccwgroup_driver ctc_group_driver = {
-	.owner       = THIS_MODULE,
-	.name        = "ctc",
-	.max_slaves  = 2,
-	.driver_id   = 0xC3E3C3,
-	.probe       = ctc_probe_device,
-	.remove      = ctc_remove_device,
-	.set_online  = ctc_new_device,
-	.set_offline = ctc_shutdown_device,
-};
-
-/**
- * Module related routines
- *****************************************************************************/
-
-/**
- * Prepare to be unloaded. Free IRQ's and release all resources.
- * This is called just before this module is unloaded. It is
- * <em>not</em> called, if the usage count is !0, so we don't need to check
- * for that.
- */
-static void __exit
-ctc_exit(void)
-{
-	DBF_TEXT(setup, 3, __FUNCTION__);
-	unregister_cu3088_discipline(&ctc_group_driver);
-	ctc_unregister_dbf_views();
-	ctc_pr_info("CTC driver unloaded\n");
-}
-
-/**
- * Initialize module.
- * This is called just after the module is loaded.
- *
- * @return 0 on success, !0 on error.
- */
-static int __init
-ctc_init(void)
-{
-	int ret = 0;
-
-	loglevel = CTC_LOGLEVEL_DEFAULT;
-
-	DBF_TEXT(setup, 3, __FUNCTION__);
-
-	print_banner();
-
-	ret = ctc_register_dbf_views();
-	if (ret){
-		ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret);
-		return ret;
-	}
-	ret = register_cu3088_discipline(&ctc_group_driver);
-	if (ret) {
-		ctc_unregister_dbf_views();
-	}
-	return ret;
-}
-
-module_init(ctc_init);
-module_exit(ctc_exit);
-
-/* --- This is the END my friend --- */
diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
deleted file mode 100644
index 7f305d1..0000000
--- a/drivers/s390/net/ctcmain.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * CTC / ESCON network driver
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
-	      Peter Tiedemann (ptiedem@de.ibm.com)
- *
- *
- * Documentation used:
- *  - Principles of Operation (IBM doc#: SA22-7201-06)
- *  - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
- *  - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
- *  - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
- *  - ESCON I/O Interface (IBM doc#: SA22-7202-029
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef _CTCMAIN_H_
-#define _CTCMAIN_H_
-
-#include <asm/ccwdev.h>
-#include <asm/ccwgroup.h>
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-#include "fsm.h"
-#include "cu3088.h"
-
-
-/**
- * CCW commands, used in this driver.
- */
-#define CCW_CMD_WRITE		0x01
-#define CCW_CMD_READ		0x02
-#define CCW_CMD_SET_EXTENDED	0xc3
-#define CCW_CMD_PREPARE		0xe3
-
-#define CTC_PROTO_S390          0
-#define CTC_PROTO_LINUX         1
-#define CTC_PROTO_OS390         3
-
-#define CTC_BUFSIZE_LIMIT       65535
-#define CTC_BUFSIZE_DEFAULT     32768
-
-#define CTC_TIMEOUT_5SEC        5000
-
-#define CTC_INITIAL_BLOCKLEN    2
-
-#define READ			0
-#define WRITE			1
-
-#define CTC_ID_SIZE             BUS_ID_SIZE+3
-
-
-struct ctc_profile {
-	unsigned long maxmulti;
-	unsigned long maxcqueue;
-	unsigned long doios_single;
-	unsigned long doios_multi;
-	unsigned long txlen;
-	unsigned long tx_time;
-	struct timespec send_stamp;
-};
-
-/**
- * Definition of one channel
- */
-struct channel {
-
-	/**
-	 * Pointer to next channel in list.
-	 */
-	struct channel *next;
-	char id[CTC_ID_SIZE];
-	struct ccw_device *cdev;
-
-	/**
-	 * Type of this channel.
-	 * CTC/A or Escon for valid channels.
-	 */
-	enum channel_types type;
-
-	/**
-	 * Misc. flags. See CHANNEL_FLAGS_... below
-	 */
-	__u32 flags;
-
-	/**
-	 * The protocol of this channel
-	 */
-	__u16 protocol;
-
-	/**
-	 * I/O and irq related stuff
-	 */
-	struct ccw1 *ccw;
-	struct irb *irb;
-
-	/**
-	 * RX/TX buffer size
-	 */
-	int max_bufsize;
-
-	/**
-	 * Transmit/Receive buffer.
-	 */
-	struct sk_buff *trans_skb;
-
-	/**
-	 * Universal I/O queue.
-	 */
-	struct sk_buff_head io_queue;
-
-	/**
-	 * TX queue for collecting skb's during busy.
-	 */
-	struct sk_buff_head collect_queue;
-
-	/**
-	 * Amount of data in collect_queue.
-	 */
-	int collect_len;
-
-	/**
-	 * spinlock for collect_queue and collect_len
-	 */
-	spinlock_t collect_lock;
-
-	/**
-	 * Timer for detecting unresposive
-	 * I/O operations.
-	 */
-	fsm_timer timer;
-
-	/**
-	 * Retry counter for misc. operations.
-	 */
-	int retry;
-
-	/**
-	 * The finite state machine of this channel
-	 */
-	fsm_instance *fsm;
-
-	/**
-	 * The corresponding net_device this channel
-	 * belongs to.
-	 */
-	struct net_device *netdev;
-
-	struct ctc_profile prof;
-
-	unsigned char *trans_skb_data;
-
-	__u16 logflags;
-};
-
-#define CHANNEL_FLAGS_READ            0
-#define CHANNEL_FLAGS_WRITE           1
-#define CHANNEL_FLAGS_INUSE           2
-#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
-#define CHANNEL_FLAGS_FAILED          8
-#define CHANNEL_FLAGS_WAITIRQ        16
-#define CHANNEL_FLAGS_RWMASK 1
-#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
-
-#define LOG_FLAG_ILLEGALPKT  1
-#define LOG_FLAG_ILLEGALSIZE 2
-#define LOG_FLAG_OVERRUN     4
-#define LOG_FLAG_NOMEM       8
-
-#define CTC_LOGLEVEL_INFO     1
-#define CTC_LOGLEVEL_NOTICE   2
-#define CTC_LOGLEVEL_WARN     4
-#define CTC_LOGLEVEL_EMERG    8
-#define CTC_LOGLEVEL_ERR     16
-#define CTC_LOGLEVEL_DEBUG   32
-#define CTC_LOGLEVEL_CRIT    64
-
-#define CTC_LOGLEVEL_DEFAULT \
-(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
-
-#define CTC_LOGLEVEL_MAX     ((CTC_LOGLEVEL_CRIT<<1)-1)
-
-#define ctc_pr_debug(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
-
-#define ctc_pr_info(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
-
-#define ctc_pr_notice(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
-
-#define ctc_pr_warn(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
-
-#define ctc_pr_emerg(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
-
-#define ctc_pr_err(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
-
-#define ctc_pr_crit(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
-
-struct ctc_priv {
-	struct net_device_stats stats;
-	unsigned long tbusy;
-	/**
-	 * The finite state machine of this interface.
-	 */
-	fsm_instance *fsm;
-	/**
-	 * The protocol of this device
-	 */
-	__u16 protocol;
- 	/**
- 	 * Timer for restarting after I/O Errors
- 	 */
- 	fsm_timer               restart_timer;
-
-	int buffer_size;
-
-	struct channel *channel[2];
-};
-
-/**
- * Definition of our link level header.
- */
-struct ll_header {
-	__u16 length;
-	__u16 type;
-	__u16 unused;
-};
-#define LL_HEADER_LENGTH (sizeof(struct ll_header))
-
-/**
- * Compatibility macros for busy handling
- * of network devices.
- */
-static __inline__ void
-ctc_clear_busy(struct net_device * dev)
-{
-	clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
-	netif_wake_queue(dev);
-}
-
-static __inline__ int
-ctc_test_and_set_busy(struct net_device * dev)
-{
-	netif_stop_queue(dev);
-	return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
-}
-
-#endif
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
deleted file mode 100644
index 8c6b72d..0000000
--- a/drivers/s390/net/qeth.h
+++ /dev/null
@@ -1,1253 +0,0 @@
-#ifndef __QETH_H__
-#define __QETH_H__
-
-#include <linux/if.h>
-#include <linux/if_arp.h>
-
-#include <linux/if_tr.h>
-#include <linux/trdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/ctype.h>
-
-#include <net/ipv6.h>
-#include <linux/in6.h>
-#include <net/if_inet6.h>
-#include <net/addrconf.h>
-
-
-#include <linux/bitops.h>
-
-#include <asm/debug.h>
-#include <asm/qdio.h>
-#include <asm/ccwdev.h>
-#include <asm/ccwgroup.h>
-
-#include "qeth_mpc.h"
-
-#ifdef CONFIG_QETH_IPV6
-#define QETH_VERSION_IPV6 	":IPv6"
-#else
-#define QETH_VERSION_IPV6 	""
-#endif
-#ifdef CONFIG_QETH_VLAN
-#define QETH_VERSION_VLAN 	":VLAN"
-#else
-#define QETH_VERSION_VLAN 	""
-#endif
-
-/**
- * Debug Facility stuff
- */
-#define QETH_DBF_SETUP_NAME "qeth_setup"
-#define QETH_DBF_SETUP_LEN 8
-#define QETH_DBF_SETUP_PAGES 8
-#define QETH_DBF_SETUP_NR_AREAS 1
-#define QETH_DBF_SETUP_LEVEL 5
-
-#define QETH_DBF_MISC_NAME "qeth_misc"
-#define QETH_DBF_MISC_LEN 128
-#define QETH_DBF_MISC_PAGES 2
-#define QETH_DBF_MISC_NR_AREAS 1
-#define QETH_DBF_MISC_LEVEL 2
-
-#define QETH_DBF_DATA_NAME "qeth_data"
-#define QETH_DBF_DATA_LEN 96
-#define QETH_DBF_DATA_PAGES 8
-#define QETH_DBF_DATA_NR_AREAS 1
-#define QETH_DBF_DATA_LEVEL 2
-
-#define QETH_DBF_CONTROL_NAME "qeth_control"
-#define QETH_DBF_CONTROL_LEN 256
-#define QETH_DBF_CONTROL_PAGES 8
-#define QETH_DBF_CONTROL_NR_AREAS 2
-#define QETH_DBF_CONTROL_LEVEL 5
-
-#define QETH_DBF_TRACE_NAME "qeth_trace"
-#define QETH_DBF_TRACE_LEN 8
-#define QETH_DBF_TRACE_PAGES 4
-#define QETH_DBF_TRACE_NR_AREAS 2
-#define QETH_DBF_TRACE_LEVEL 3
-extern debug_info_t *qeth_dbf_trace;
-
-#define QETH_DBF_SENSE_NAME "qeth_sense"
-#define QETH_DBF_SENSE_LEN 64
-#define QETH_DBF_SENSE_PAGES 2
-#define QETH_DBF_SENSE_NR_AREAS 1
-#define QETH_DBF_SENSE_LEVEL 2
-
-#define QETH_DBF_QERR_NAME "qeth_qerr"
-#define QETH_DBF_QERR_LEN 8
-#define QETH_DBF_QERR_PAGES 2
-#define QETH_DBF_QERR_NR_AREAS 2
-#define QETH_DBF_QERR_LEVEL 2
-
-#define QETH_DBF_TEXT(name,level,text) \
-	do { \
-		debug_text_event(qeth_dbf_##name,level,text); \
-	} while (0)
-
-#define QETH_DBF_HEX(name,level,addr,len) \
-	do { \
-		debug_event(qeth_dbf_##name,level,(void*)(addr),len); \
-	} while (0)
-
-DECLARE_PER_CPU(char[256], qeth_dbf_txt_buf);
-
-#define QETH_DBF_TEXT_(name,level,text...)				\
-	do {								\
-		char* dbf_txt_buf = get_cpu_var(qeth_dbf_txt_buf);	\
-		sprintf(dbf_txt_buf, text);			  	\
-		debug_text_event(qeth_dbf_##name,level,dbf_txt_buf);	\
-		put_cpu_var(qeth_dbf_txt_buf);				\
-	} while (0)
-
-#define QETH_DBF_SPRINTF(name,level,text...) \
-	do { \
-		debug_sprintf_event(qeth_dbf_trace, level, ##text ); \
-		debug_sprintf_event(qeth_dbf_trace, level, text ); \
-	} while (0)
-
-/**
- * some more debug stuff
- */
-#define PRINTK_HEADER 	"qeth: "
-
-#define HEXDUMP16(importance,header,ptr) \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
-		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
-		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
-		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
-		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
-		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
-		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
-		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
-		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
-		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
-		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
-		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
-		   *(((char*)ptr)+30),*(((char*)ptr)+31));
-
-static inline void
-qeth_hex_dump(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; i++) {
-		if (i && !(i % 16))
-			printk("\n");
-		printk("%02x ", *(buf + i));
-	}
-	printk("\n");
-}
-
-#define SENSE_COMMAND_REJECT_BYTE 0
-#define SENSE_COMMAND_REJECT_FLAG 0x80
-#define SENSE_RESETTING_EVENT_BYTE 1
-#define SENSE_RESETTING_EVENT_FLAG 0x80
-
-/*
- * Common IO related definitions
- */
-extern struct device *qeth_root_dev;
-extern struct ccw_driver qeth_ccw_driver;
-extern struct ccwgroup_driver qeth_ccwgroup_driver;
-
-#define CARD_RDEV(card) card->read.ccwdev
-#define CARD_WDEV(card) card->write.ccwdev
-#define CARD_DDEV(card) card->data.ccwdev
-#define CARD_BUS_ID(card) card->gdev->dev.bus_id
-#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
-#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
-#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
-#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
-
-#define CARD_FROM_CDEV(cdev) (struct qeth_card *) \
-		((struct ccwgroup_device *)cdev->dev.driver_data)\
-		->dev.driver_data;
-
-/**
- * card stuff
- */
-struct qeth_perf_stats {
-	unsigned int bufs_rec;
-	unsigned int bufs_sent;
-
-	unsigned int skbs_sent_pack;
-	unsigned int bufs_sent_pack;
-
-	unsigned int sc_dp_p;
-	unsigned int sc_p_dp;
-	/* qdio_input_handler: number of times called, time spent in */
-	__u64 inbound_start_time;
-	unsigned int inbound_cnt;
-	unsigned int inbound_time;
-	/* qeth_send_packet: number of times called, time spent in */
-	__u64 outbound_start_time;
-	unsigned int outbound_cnt;
-	unsigned int outbound_time;
-	/* qdio_output_handler: number of times called, time spent in */
-	__u64 outbound_handler_start_time;
-	unsigned int outbound_handler_cnt;
-	unsigned int outbound_handler_time;
-	/* number of calls to and time spent in do_QDIO for inbound queue */
-	__u64 inbound_do_qdio_start_time;
-	unsigned int inbound_do_qdio_cnt;
-	unsigned int inbound_do_qdio_time;
-	/* number of calls to and time spent in do_QDIO for outbound queues */
-	__u64 outbound_do_qdio_start_time;
-	unsigned int outbound_do_qdio_cnt;
-	unsigned int outbound_do_qdio_time;
-	/* eddp data */
-	unsigned int large_send_bytes;
-	unsigned int large_send_cnt;
-	unsigned int sg_skbs_sent;
-	unsigned int sg_frags_sent;
-	/* initial values when measuring starts */
-	unsigned long initial_rx_packets;
-	unsigned long initial_tx_packets;
-	/* inbound scatter gather data */
-	unsigned int sg_skbs_rx;
-	unsigned int sg_frags_rx;
-	unsigned int sg_alloc_page_rx;
-};
-
-/* Routing stuff */
-struct qeth_routing_info {
-	enum qeth_routing_types type;
-};
-
-/* IPA stuff */
-struct qeth_ipa_info {
-	__u32 supported_funcs;
-	__u32 enabled_funcs;
-};
-
-static inline int
-qeth_is_ipa_supported(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
-{
-	return (ipa->supported_funcs & func);
-}
-
-static inline int
-qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
-{
-	return (ipa->supported_funcs & ipa->enabled_funcs & func);
-}
-
-#define qeth_adp_supported(c,f) \
-	qeth_is_ipa_supported(&c->options.adp, f)
-#define qeth_adp_enabled(c,f) \
-	qeth_is_ipa_enabled(&c->options.adp, f)
-#define qeth_is_supported(c,f) \
-	qeth_is_ipa_supported(&c->options.ipa4, f)
-#define qeth_is_enabled(c,f) \
-	qeth_is_ipa_enabled(&c->options.ipa4, f)
-#ifdef CONFIG_QETH_IPV6
-#define qeth_is_supported6(c,f) \
-	qeth_is_ipa_supported(&c->options.ipa6, f)
-#define qeth_is_enabled6(c,f) \
-	qeth_is_ipa_enabled(&c->options.ipa6, f)
-#else /* CONFIG_QETH_IPV6 */
-#define qeth_is_supported6(c,f) 0
-#define qeth_is_enabled6(c,f) 0
-#endif /* CONFIG_QETH_IPV6 */
-#define qeth_is_ipafunc_supported(c,prot,f) \
-	 (prot==QETH_PROT_IPV6)? qeth_is_supported6(c,f):qeth_is_supported(c,f)
-#define qeth_is_ipafunc_enabled(c,prot,f) \
-	 (prot==QETH_PROT_IPV6)? qeth_is_enabled6(c,f):qeth_is_enabled(c,f)
-
-
-#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
-#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
-#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
-#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
-
-#define QETH_MODELLIST_ARRAY \
-	{{0x1731,0x01,0x1732,0x01,QETH_CARD_TYPE_OSAE,1, \
-	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
-	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
-	QETH_MAX_QUEUES,0}, \
-	{0x1731,0x05,0x1732,0x05,QETH_CARD_TYPE_IQD,0, \
-	QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
-	QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
-	QETH_MAX_QUEUES,0x103}, \
-	{0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
-	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
-	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
-	QETH_MAX_QUEUES,0}, \
-	{0,0,0,0,0,0,0,0,0}}
-
-#define QETH_REAL_CARD		1
-#define QETH_VLAN_CARD		2
-#define QETH_BUFSIZE	 	4096
-
-/**
- * some more defs
- */
-#define IF_NAME_LEN	 	16
-#define QETH_TX_TIMEOUT		100 * HZ
-#define QETH_RCD_TIMEOUT	60 * HZ
-#define QETH_HEADER_SIZE	32
-#define MAX_PORTNO 		15
-#define QETH_FAKE_LL_LEN_ETH	ETH_HLEN
-#define QETH_FAKE_LL_LEN_TR	(sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc))
-#define QETH_FAKE_LL_V6_ADDR_POS 24
-
-/*IPv6 address autoconfiguration stuff*/
-#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe
-#define UNIQUE_ID_NOT_BY_CARD 		0x10000
-
-/*****************************************************************************/
-/* QDIO queue and buffer handling                                            */
-/*****************************************************************************/
-#define QETH_MAX_QUEUES 4
-#define QETH_IN_BUF_SIZE_DEFAULT 65536
-#define QETH_IN_BUF_COUNT_DEFAULT 16
-#define QETH_IN_BUF_COUNT_MIN 8
-#define QETH_IN_BUF_COUNT_MAX 128
-#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
-#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
-		((card)->qdio.in_buf_pool.buf_count / 2)
-
-/* buffers we have to be behind before we get a PCI */
-#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
-/*enqueued free buffers left before we get a PCI*/
-#define QETH_PCI_THRESHOLD_B(card) 0
-/*not used unless the microcode gets patched*/
-#define QETH_PCI_TIMER_VALUE(card) 3
-
-#define QETH_MIN_INPUT_THRESHOLD 1
-#define QETH_MAX_INPUT_THRESHOLD 500
-#define QETH_MIN_OUTPUT_THRESHOLD 1
-#define QETH_MAX_OUTPUT_THRESHOLD 300
-
-/* priority queing */
-#define QETH_PRIOQ_DEFAULT QETH_NO_PRIO_QUEUEING
-#define QETH_DEFAULT_QUEUE    2
-#define QETH_NO_PRIO_QUEUEING 0
-#define QETH_PRIO_Q_ING_PREC  1
-#define QETH_PRIO_Q_ING_TOS   2
-#define IP_TOS_LOWDELAY 0x10
-#define IP_TOS_HIGHTHROUGHPUT 0x08
-#define IP_TOS_HIGHRELIABILITY 0x04
-#define IP_TOS_NOTIMPORTANT 0x02
-
-/* Packing */
-#define QETH_LOW_WATERMARK_PACK  2
-#define QETH_HIGH_WATERMARK_PACK 5
-#define QETH_WATERMARK_PACK_FUZZ 1
-
-#define QETH_IP_HEADER_SIZE 40
-
-/* large receive scatter gather copy break */
-#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
-
-struct qeth_hdr_layer3 {
-	__u8  id;
-	__u8  flags;
-	__u16 inbound_checksum; /*TSO:__u16 seqno */
-	__u32 token;		/*TSO: __u32 reserved */
-	__u16 length;
-	__u8  vlan_prio;
-	__u8  ext_flags;
-	__u16 vlan_id;
-	__u16 frame_offset;
-	__u8  dest_addr[16];
-} __attribute__ ((packed));
-
-struct qeth_hdr_layer2 {
-	__u8 id;
-	__u8 flags[3];
-	__u8 port_no;
-	__u8 hdr_length;
-	__u16 pkt_length;
-	__u16 seq_no;
-	__u16 vlan_id;
-	__u32 reserved;
-	__u8 reserved2[16];
-} __attribute__ ((packed));
-
-struct qeth_hdr_osn {
-	__u8 id;
-	__u8 reserved;
-	__u16 seq_no;
-	__u16 reserved2;
-	__u16 control_flags;
-	__u16 pdu_length;
-	__u8 reserved3[18];
-	__u32 ccid;
-} __attribute__ ((packed));
-
-struct qeth_hdr {
-	union {
-		struct qeth_hdr_layer2 l2;
-		struct qeth_hdr_layer3 l3;
-		struct qeth_hdr_osn    osn;
-	} hdr;
-} __attribute__ ((packed));
-
-/*TCP Segmentation Offload header*/
-struct qeth_hdr_ext_tso {
-        __u16 hdr_tot_len;
-        __u8  imb_hdr_no;
-        __u8  reserved;
-        __u8  hdr_type;
-        __u8  hdr_version;
-        __u16 hdr_len;
-        __u32 payload_len;
-        __u16 mss;
-        __u16 dg_hdr_len;
-        __u8  padding[16];
-} __attribute__ ((packed));
-
-struct qeth_hdr_tso {
-        struct qeth_hdr hdr; 	/*hdr->hdr.l3.xxx*/
-	struct qeth_hdr_ext_tso ext;
-} __attribute__ ((packed));
-
-
-/* flags for qeth_hdr.flags */
-#define QETH_HDR_PASSTHRU 0x10
-#define QETH_HDR_IPV6     0x80
-#define QETH_HDR_CAST_MASK 0x07
-enum qeth_cast_flags {
-	QETH_CAST_UNICAST   = 0x06,
-	QETH_CAST_MULTICAST = 0x04,
-	QETH_CAST_BROADCAST = 0x05,
-	QETH_CAST_ANYCAST   = 0x07,
-	QETH_CAST_NOCAST    = 0x00,
-};
-
-enum qeth_layer2_frame_flags {
-	QETH_LAYER2_FLAG_MULTICAST = 0x01,
-	QETH_LAYER2_FLAG_BROADCAST = 0x02,
-	QETH_LAYER2_FLAG_UNICAST   = 0x04,
-	QETH_LAYER2_FLAG_VLAN      = 0x10,
-};
-
-enum qeth_header_ids {
-	QETH_HEADER_TYPE_LAYER3 = 0x01,
-	QETH_HEADER_TYPE_LAYER2 = 0x02,
-	QETH_HEADER_TYPE_TSO	= 0x03,
-	QETH_HEADER_TYPE_OSN    = 0x04,
-};
-/* flags for qeth_hdr.ext_flags */
-#define QETH_HDR_EXT_VLAN_FRAME       0x01
-#define QETH_HDR_EXT_TOKEN_ID         0x02
-#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
-#define QETH_HDR_EXT_SRC_MAC_ADDR     0x08
-#define QETH_HDR_EXT_CSUM_HDR_REQ     0x10
-#define QETH_HDR_EXT_CSUM_TRANSP_REQ  0x20
-#define QETH_HDR_EXT_UDP_TSO          0x40 /*bit off for TCP*/
-
-static inline int
-qeth_is_last_sbale(struct qdio_buffer_element *sbale)
-{
-	return (sbale->flags & SBAL_FLAGS_LAST_ENTRY);
-}
-
-enum qeth_qdio_buffer_states {
-	/*
-	 * inbound: read out by driver; owned by hardware in order to be filled
-	 * outbound: owned by driver in order to be filled
-	 */
-	QETH_QDIO_BUF_EMPTY,
-	/*
-	 * inbound: filled by hardware; owned by driver in order to be read out
-	 * outbound: filled by driver; owned by hardware in order to be sent
-	 */
-	QETH_QDIO_BUF_PRIMED,
-};
-
-enum qeth_qdio_info_states {
-	QETH_QDIO_UNINITIALIZED,
-	QETH_QDIO_ALLOCATED,
-	QETH_QDIO_ESTABLISHED,
-	QETH_QDIO_CLEANING
-};
-
-struct qeth_buffer_pool_entry {
-	struct list_head list;
-	struct list_head init_list;
-	void *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
-};
-
-struct qeth_qdio_buffer_pool {
-	struct list_head entry_list;
-	int buf_count;
-};
-
-struct qeth_qdio_buffer {
-	struct qdio_buffer *buffer;
-	volatile enum qeth_qdio_buffer_states state;
-	/* the buffer pool entry currently associated to this buffer */
-	struct qeth_buffer_pool_entry *pool_entry;
-};
-
-struct qeth_qdio_q {
-	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
-	struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
-	/*
-	 * buf_to_init means "buffer must be initialized by driver and must
-	 * be made available for hardware" -> state is set to EMPTY
-	 */
-	volatile int next_buf_to_init;
-} __attribute__ ((aligned(256)));
-
-/* possible types of qeth large_send support */
-enum qeth_large_send_types {
-	QETH_LARGE_SEND_NO,
-	QETH_LARGE_SEND_EDDP,
-	QETH_LARGE_SEND_TSO,
-};
-
-struct qeth_qdio_out_buffer {
-	struct qdio_buffer *buffer;
-	atomic_t state;
-	volatile int next_element_to_fill;
-	struct sk_buff_head skb_list;
-	struct list_head ctx_list;
-};
-
-struct qeth_card;
-
-enum qeth_out_q_states {
-       QETH_OUT_Q_UNLOCKED,
-       QETH_OUT_Q_LOCKED,
-       QETH_OUT_Q_LOCKED_FLUSH,
-};
-
-struct qeth_qdio_out_q {
-	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
-	struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
-	int queue_no;
-	struct qeth_card *card;
-	atomic_t state;
-	volatile int do_pack;
-	/*
-	 * index of buffer to be filled by driver; state EMPTY or PACKING
-	 */
-	volatile int next_buf_to_fill;
-	/*
-	 * number of buffers that are currently filled (PRIMED)
-	 * -> these buffers are hardware-owned
-	 */
-	atomic_t used_buffers;
-	/* indicates whether PCI flag must be set (or if one is outstanding) */
-	atomic_t set_pci_flags_count;
-} __attribute__ ((aligned(256)));
-
-struct qeth_qdio_info {
-	atomic_t state;
-	/* input */
-	struct qeth_qdio_q *in_q;
-	struct qeth_qdio_buffer_pool in_buf_pool;
-	struct qeth_qdio_buffer_pool init_pool;
-	int in_buf_size;
-
-	/* output */
-	int no_out_queues;
-	struct qeth_qdio_out_q **out_qs;
-
-	/* priority queueing */
-	int do_prio_queueing;
-	int default_out_queue;
-};
-
-enum qeth_send_errors {
-	QETH_SEND_ERROR_NONE,
-	QETH_SEND_ERROR_LINK_FAILURE,
-	QETH_SEND_ERROR_RETRY,
-	QETH_SEND_ERROR_KICK_IT,
-};
-
-#define QETH_ETH_MAC_V4      0x0100 /* like v4 */
-#define QETH_ETH_MAC_V6      0x3333 /* like v6 */
-/* tr mc mac is longer, but that will be enough to detect mc frames */
-#define QETH_TR_MAC_NC       0xc000 /* non-canonical */
-#define QETH_TR_MAC_C        0x0300 /* canonical */
-
-#define DEFAULT_ADD_HHLEN 0
-#define MAX_ADD_HHLEN 1024
-
-/**
- * buffer stuff for read channel
- */
-#define QETH_CMD_BUFFER_NO	8
-
-/**
- *  channel state machine
- */
-enum qeth_channel_states {
-	CH_STATE_UP,
-	CH_STATE_DOWN,
-	CH_STATE_ACTIVATING,
-	CH_STATE_HALTED,
-	CH_STATE_STOPPED,
-	CH_STATE_RCD,
-	CH_STATE_RCD_DONE,
-};
-/**
- * card state machine
- */
-enum qeth_card_states {
-	CARD_STATE_DOWN,
-	CARD_STATE_HARDSETUP,
-	CARD_STATE_SOFTSETUP,
-	CARD_STATE_UP,
-	CARD_STATE_RECOVER,
-};
-
-/**
- * Protocol versions
- */
-enum qeth_prot_versions {
-	QETH_PROT_IPV4 = 0x0004,
-	QETH_PROT_IPV6 = 0x0006,
-};
-
-enum qeth_ip_types {
-	QETH_IP_TYPE_NORMAL,
-	QETH_IP_TYPE_VIPA,
-	QETH_IP_TYPE_RXIP,
-	QETH_IP_TYPE_DEL_ALL_MC,
-};
-
-enum qeth_cmd_buffer_state {
-	BUF_STATE_FREE,
-	BUF_STATE_LOCKED,
-	BUF_STATE_PROCESSED,
-};
-/**
- * IP address and multicast list
- */
-struct qeth_ipaddr {
-	struct list_head entry;
-	enum qeth_ip_types type;
-	enum qeth_ipa_setdelip_flags set_flags;
-	enum qeth_ipa_setdelip_flags del_flags;
-	int is_multicast;
-	volatile int users;
-	enum qeth_prot_versions proto;
-	unsigned char mac[OSA_ADDR_LEN];
-	union {
-		struct {
-			unsigned int addr;
-			unsigned int mask;
-		} a4;
-		struct {
-			struct in6_addr addr;
-			unsigned int pfxlen;
-		} a6;
-	} u;
-};
-
-struct qeth_ipato_entry {
-	struct list_head entry;
-	enum qeth_prot_versions proto;
-	char addr[16];
-	int mask_bits;
-};
-
-struct qeth_ipato {
-	int enabled;
-	int invert4;
-	int invert6;
-	struct list_head entries;
-};
-
-struct qeth_channel;
-
-struct qeth_cmd_buffer {
-	enum qeth_cmd_buffer_state state;
-	struct qeth_channel *channel;
-	unsigned char *data;
-	int rc;
-	void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
-};
-
-
-/**
- * definition of a qeth channel, used for read and write
- */
-struct qeth_channel {
-	enum qeth_channel_states state;
-	struct ccw1 ccw;
-	spinlock_t iob_lock;
-	wait_queue_head_t wait_q;
-	struct tasklet_struct irq_tasklet;
-	struct ccw_device *ccwdev;
-/*command buffer for control data*/
-	struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
-	atomic_t irq_pending;
-	volatile int io_buf_no;
-	volatile int buf_no;
-};
-
-/**
- *  OSA card related definitions
- */
-struct qeth_token {
-	__u32 issuer_rm_w;
-	__u32 issuer_rm_r;
-	__u32 cm_filter_w;
-	__u32 cm_filter_r;
-	__u32 cm_connection_w;
-	__u32 cm_connection_r;
-	__u32 ulp_filter_w;
-	__u32 ulp_filter_r;
-	__u32 ulp_connection_w;
-	__u32 ulp_connection_r;
-};
-
-struct qeth_seqno {
-	__u32 trans_hdr;
-	__u32 pdu_hdr;
-	__u32 pdu_hdr_ack;
-	__u16 ipa;
-	__u32 pkt_seqno;
-};
-
-struct qeth_reply {
-	struct list_head list;
-	wait_queue_head_t wait_q;
-	int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
- 	u32 seqno;
-	unsigned long offset;
-	atomic_t received;
-	int rc;
-	void *param;
-	struct qeth_card *card;
-	atomic_t refcnt;
-};
-
-
-struct qeth_card_blkt {
-	int time_total;
-	int inter_packet;
-	int inter_packet_jumbo;
-};
-
-#define QETH_BROADCAST_WITH_ECHO    0x01
-#define QETH_BROADCAST_WITHOUT_ECHO 0x02
-#define QETH_LAYER2_MAC_READ	    0x01
-#define QETH_LAYER2_MAC_REGISTERED  0x02
-struct qeth_card_info {
-	unsigned short unit_addr2;
-	unsigned short cula;
-	unsigned short chpid;
-	__u16 func_level;
-	char mcl_level[QETH_MCL_LENGTH + 1];
-	int guestlan;
-	int mac_bits;
-	int portname_required;
-	int portno;
-	char portname[9];
-	enum qeth_card_types type;
-	enum qeth_link_types link_type;
-	int is_multicast_different;
-	int initial_mtu;
-	int max_mtu;
-	int broadcast_capable;
-	int unique_id;
-	struct qeth_card_blkt blkt;
-	__u32 csum_mask;
-	enum qeth_ipa_promisc_modes promisc_mode;
-};
-
-struct qeth_card_options {
-	struct qeth_routing_info route4;
-	struct qeth_ipa_info ipa4;
-	struct qeth_ipa_info adp; /*Adapter parameters*/
-#ifdef CONFIG_QETH_IPV6
-	struct qeth_routing_info route6;
-	struct qeth_ipa_info ipa6;
-#endif /* QETH_IPV6 */
-	enum qeth_checksum_types checksum_type;
-	int broadcast_mode;
-	int macaddr_mode;
-	int fake_broadcast;
-	int add_hhlen;
-	int fake_ll;
-	int layer2;
-	enum qeth_large_send_types large_send;
-	int performance_stats;
-	int rx_sg_cb;
-};
-
-/*
- * thread bits for qeth_card thread masks
- */
-enum qeth_threads {
-	QETH_SET_IP_THREAD  = 1,
-	QETH_RECOVER_THREAD = 2,
-	QETH_SET_PROMISC_MODE_THREAD = 4,
-};
-
-struct qeth_osn_info {
-	int (*assist_cb)(struct net_device *dev, void *data);
-	int (*data_cb)(struct sk_buff *skb);
-};
-
-struct qeth_card {
-	struct list_head list;
-	enum qeth_card_states state;
-	int lan_online;
-	spinlock_t lock;
-/*hardware and sysfs stuff*/
-	struct ccwgroup_device *gdev;
-	struct qeth_channel read;
-	struct qeth_channel write;
-	struct qeth_channel data;
-
-	struct net_device *dev;
-	struct net_device_stats stats;
-
-	struct qeth_card_info info;
-	struct qeth_token token;
-	struct qeth_seqno seqno;
-	struct qeth_card_options options;
-
-	wait_queue_head_t wait_q;
-#ifdef CONFIG_QETH_VLAN
-	spinlock_t vlanlock;
-	struct vlan_group *vlangrp;
-#endif
-	struct work_struct kernel_thread_starter;
-	spinlock_t thread_mask_lock;
-	volatile unsigned long thread_start_mask;
-	volatile unsigned long thread_allowed_mask;
-	volatile unsigned long thread_running_mask;
-	spinlock_t ip_lock;
-	struct list_head ip_list;
-	struct list_head *ip_tbd_list;
-	struct qeth_ipato ipato;
-	struct list_head cmd_waiter_list;
-	/* QDIO buffer handling */
-	struct qeth_qdio_info qdio;
-	struct qeth_perf_stats perf_stats;
-	int use_hard_stop;
-	const struct header_ops *orig_header_ops;
-	struct qeth_osn_info osn_info;
-	atomic_t force_alloc_skb;
-};
-
-struct qeth_card_list_struct {
-	struct list_head list;
-	rwlock_t rwlock;
-};
-
-extern struct qeth_card_list_struct qeth_card_list;
-
-/*notifier list */
-struct qeth_notify_list_struct {
-	struct list_head list;
-	struct task_struct *task;
-	int signum;
-};
-extern spinlock_t qeth_notify_lock;
-extern struct list_head qeth_notify_list;
-
-/*some helper functions*/
-
-#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
-
-static inline __u8
-qeth_get_ipa_adp_type(enum qeth_link_types link_type)
-{
-	switch (link_type) {
-	case QETH_LINK_TYPE_HSTR:
-		return 2;
-	default:
-		return 1;
-	}
-}
-
-static inline struct sk_buff *
-qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
-{
-	struct sk_buff *new_skb = skb;
-
-	if (skb_headroom(skb) >= size)
-		return skb;
-	new_skb = skb_realloc_headroom(skb, size);
-	if (!new_skb) 
-		PRINT_ERR("Could not realloc headroom for qeth_hdr "
-			  "on interface %s", QETH_CARD_IFNAME(card));
-	return new_skb;
-}
-
-static inline struct sk_buff *
-qeth_pskb_unshare(struct sk_buff *skb, gfp_t pri)
-{
-        struct sk_buff *nskb;
-        if (!skb_cloned(skb))
-                return skb;
-        nskb = skb_copy(skb, pri);
-        return nskb;
-}
-
-static inline void *
-qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size)
-{
-        void *hdr;
-
-	hdr = (void *) skb_push(skb, size);
-        /*
-         * sanity check, the Linux memory allocation scheme should
-         * never present us cases like this one (the qdio header size plus
-         * the first 40 bytes of the paket cross a 4k boundary)
-         */
-        if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
-            (((unsigned long) hdr + size +
-              QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
-                PRINT_ERR("Misaligned packet on interface %s. Discarded.",
-                          QETH_CARD_IFNAME(card));
-                return NULL;
-        }
-        return hdr;
-}
-
-
-static inline int
-qeth_get_hlen(__u8 link_type)
-{
-#ifdef CONFIG_QETH_IPV6
-	switch (link_type) {
-	case QETH_LINK_TYPE_HSTR:
-	case QETH_LINK_TYPE_LANE_TR:
-		return sizeof(struct qeth_hdr_tso) + TR_HLEN;
-	default:
-#ifdef CONFIG_QETH_VLAN
-		return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
-#else
-		return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
-#endif
-	}
-#else  /* CONFIG_QETH_IPV6 */
-#ifdef CONFIG_QETH_VLAN
-	return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
-#else
-	return sizeof(struct qeth_hdr_tso);
-#endif
-#endif /* CONFIG_QETH_IPV6 */
-}
-
-static inline unsigned short
-qeth_get_netdev_flags(struct qeth_card *card)
-{
-	if (card->options.layer2 &&
-	   (card->info.type == QETH_CARD_TYPE_OSAE))
-		return 0;
-	switch (card->info.type) {
-	case QETH_CARD_TYPE_IQD:
-	case QETH_CARD_TYPE_OSN:
-		return IFF_NOARP;
-#ifdef CONFIG_QETH_IPV6
-	default:
-		return 0;
-#else
-	default:
-		return IFF_NOARP;
-#endif
-	}
-}
-
-static inline int
-qeth_get_initial_mtu_for_card(struct qeth_card * card)
-{
-	switch (card->info.type) {
-	case QETH_CARD_TYPE_UNKNOWN:
-		return 1500;
-	case QETH_CARD_TYPE_IQD:
-		return card->info.max_mtu;
-	case QETH_CARD_TYPE_OSAE:
-		switch (card->info.link_type) {
-		case QETH_LINK_TYPE_HSTR:
-		case QETH_LINK_TYPE_LANE_TR:
-			return 2000;
-		default:
-			return 1492;
-		}
-	default:
-		return 1500;
-	}
-}
-
-static inline int
-qeth_get_max_mtu_for_card(int cardtype)
-{
-	switch (cardtype) {
-
-	case QETH_CARD_TYPE_UNKNOWN:
-	case QETH_CARD_TYPE_OSAE:
-	case QETH_CARD_TYPE_OSN:
-		return 61440;
-	case QETH_CARD_TYPE_IQD:
-		return 57344;
-	default:
-		return 1500;
-	}
-}
-
-static inline int
-qeth_get_mtu_out_of_mpc(int cardtype)
-{
-	switch (cardtype) {
-	case QETH_CARD_TYPE_IQD:
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-static inline int
-qeth_get_mtu_outof_framesize(int framesize)
-{
-	switch (framesize) {
-	case 0x4000:
-		return 8192;
-	case 0x6000:
-		return 16384;
-	case 0xa000:
-		return 32768;
-	case 0xffff:
-		return 57344;
-	default:
-		return 0;
-	}
-}
-
-static inline int
-qeth_mtu_is_valid(struct qeth_card * card, int mtu)
-{
-	switch (card->info.type) {
-	case QETH_CARD_TYPE_OSAE:
-		return ((mtu >= 576) && (mtu <= 61440));
-	case QETH_CARD_TYPE_IQD:
-		return ((mtu >= 576) &&
-			(mtu <= card->info.max_mtu + 4096 - 32));
-	case QETH_CARD_TYPE_OSN:
-	case QETH_CARD_TYPE_UNKNOWN:
-	default:
-		return 1;
-	}
-}
-
-static inline int
-qeth_get_arphdr_type(int cardtype, int linktype)
-{
-	switch (cardtype) {
-	case QETH_CARD_TYPE_OSAE:
-	case QETH_CARD_TYPE_OSN:
-		switch (linktype) {
-		case QETH_LINK_TYPE_LANE_TR:
-		case QETH_LINK_TYPE_HSTR:
-			return ARPHRD_IEEE802_TR;
-		default:
-			return ARPHRD_ETHER;
-		}
-	case QETH_CARD_TYPE_IQD:
-	default:
-		return ARPHRD_ETHER;
-	}
-}
-
-static inline int
-qeth_get_micros(void)
-{
-	return (int) (get_clock() >> 12);
-}
-
-static inline int
-qeth_get_qdio_q_format(struct qeth_card *card)
-{
-	switch (card->info.type) {
-	case QETH_CARD_TYPE_IQD:
-		return 2;
-	default:
-		return 0;
-	}
-}
-
-static inline int
-qeth_isxdigit(char * buf)
-{
-	while (*buf) {
-		if (!isxdigit(*buf++))
-			return 0;
-	}
-	return 1;
-}
-
-static inline void
-qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
-{
-	sprintf(buf, "%i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
-}
-
-static inline int
-qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
-{
-	int count = 0, rc = 0;
-	int in[4];
-	char c;
-
-	rc = sscanf(buf, "%u.%u.%u.%u%c",
-		    &in[0], &in[1], &in[2], &in[3], &c);
-	if (rc != 4 && (rc != 5 || c != '\n'))
-		return -EINVAL;
-	for (count = 0; count < 4; count++) {
-		if (in[count] > 255)
-			return -EINVAL;
-		addr[count] = in[count];
-	}
-	return 0;
-}
-
-static inline void
-qeth_ipaddr6_to_string(const __u8 *addr, char *buf)
-{
-	sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
-		     ":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
-		     addr[0], addr[1], addr[2], addr[3],
-		     addr[4], addr[5], addr[6], addr[7],
-		     addr[8], addr[9], addr[10], addr[11],
-		     addr[12], addr[13], addr[14], addr[15]);
-}
-
-static inline int
-qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
-{
-	const char *end, *end_tmp, *start;
-	__u16 *in;
-        char num[5];
-        int num2, cnt, out, found, save_cnt;
-        unsigned short in_tmp[8] = {0, };
-
-	cnt = out = found = save_cnt = num2 = 0;
-        end = start = buf;
-	in = (__u16 *) addr;
-	memset(in, 0, 16);
-        while (*end) {
-                end = strchr(start,':');
-                if (end == NULL) {
-                        end = buf + strlen(buf);
-			if ((end_tmp = strchr(start, '\n')) != NULL)
-				end = end_tmp;
-			out = 1;
-                }
-                if ((end - start)) {
-                        memset(num, 0, 5);
-			if ((end - start) > 4)
-				return -EINVAL;
-                        memcpy(num, start, end - start);
-			if (!qeth_isxdigit(num))
-				return -EINVAL;
-                        sscanf(start, "%x", &num2);
-                        if (found)
-                                in_tmp[save_cnt++] = num2;
-                        else
-                                in[cnt++] = num2;
-                        if (out)
-                                break;
-                } else {
-			if (found)
-				return -EINVAL;
-                        found = 1;
-		}
-		start = ++end;
-        }
-	if (cnt + save_cnt > 8)
-		return -EINVAL;
-        cnt = 7;
-	while (save_cnt)
-                in[cnt--] = in_tmp[--save_cnt];
-	return 0;
-}
-
-static inline void
-qeth_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
-		      char *buf)
-{
-	if (proto == QETH_PROT_IPV4)
-		qeth_ipaddr4_to_string(addr, buf);
-	else if (proto == QETH_PROT_IPV6)
-		qeth_ipaddr6_to_string(addr, buf);
-}
-
-static inline int
-qeth_string_to_ipaddr(const char *buf, enum qeth_prot_versions proto,
-		      __u8 *addr)
-{
-	if (proto == QETH_PROT_IPV4)
-		return qeth_string_to_ipaddr4(buf, addr);
-	else if (proto == QETH_PROT_IPV6)
-		return qeth_string_to_ipaddr6(buf, addr);
-	else
-		return -EINVAL;
-}
-
-extern int
-qeth_setrouting_v4(struct qeth_card *);
-extern int
-qeth_setrouting_v6(struct qeth_card *);
-
-extern int
-qeth_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
-
-extern void
-qeth_del_ipato_entry(struct qeth_card *, enum qeth_prot_versions, u8 *, int);
-
-extern int
-qeth_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
-
-extern void
-qeth_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
-
-extern int
-qeth_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
-
-extern void
-qeth_del_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
-
-extern int
-qeth_notifier_register(struct task_struct *, int );
-
-extern int
-qeth_notifier_unregister(struct task_struct * );
-
-extern void
-qeth_schedule_recovery(struct qeth_card *);
-
-extern int
-qeth_realloc_buffer_pool(struct qeth_card *, int);
-
-extern int
-qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
-
-extern void
-qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
-		 struct sk_buff *, int, int);
-extern void
-qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
-
-extern int
-qeth_osn_assist(struct net_device *, void *, int);
-
-extern int
-qeth_osn_register(unsigned char *read_dev_no,
-                 struct net_device **,
-                 int (*assist_cb)(struct net_device *, void *),
-                 int (*data_cb)(struct sk_buff *));
-
-extern void
-qeth_osn_deregister(struct net_device *);
-
-#endif /* __QETH_H__ */
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
new file mode 100644
index 0000000..9485e36
--- /dev/null
+++ b/drivers/s390/net/qeth_core.h
@@ -0,0 +1,916 @@
+/*
+ *  drivers/s390/net/qeth_core.h
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
+ *		 Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#ifndef __QETH_CORE_H__
+#define __QETH_CORE_H__
+
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/if_tr.h>
+#include <linux/trdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/ctype.h>
+#include <linux/in6.h>
+#include <linux/bitops.h>
+#include <linux/seq_file.h>
+#include <linux/ethtool.h>
+
+#include <net/ipv6.h>
+#include <net/if_inet6.h>
+#include <net/addrconf.h>
+
+#include <asm/debug.h>
+#include <asm/qdio.h>
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+
+#include "qeth_core_mpc.h"
+
+/**
+ * Debug Facility stuff
+ */
+#define QETH_DBF_SETUP_NAME "qeth_setup"
+#define QETH_DBF_SETUP_LEN 8
+#define QETH_DBF_SETUP_PAGES 8
+#define QETH_DBF_SETUP_NR_AREAS 1
+#define QETH_DBF_SETUP_LEVEL 5
+
+#define QETH_DBF_MISC_NAME "qeth_misc"
+#define QETH_DBF_MISC_LEN 128
+#define QETH_DBF_MISC_PAGES 2
+#define QETH_DBF_MISC_NR_AREAS 1
+#define QETH_DBF_MISC_LEVEL 2
+
+#define QETH_DBF_DATA_NAME "qeth_data"
+#define QETH_DBF_DATA_LEN 96
+#define QETH_DBF_DATA_PAGES 8
+#define QETH_DBF_DATA_NR_AREAS 1
+#define QETH_DBF_DATA_LEVEL 2
+
+#define QETH_DBF_CONTROL_NAME "qeth_control"
+#define QETH_DBF_CONTROL_LEN 256
+#define QETH_DBF_CONTROL_PAGES 8
+#define QETH_DBF_CONTROL_NR_AREAS 1
+#define QETH_DBF_CONTROL_LEVEL 5
+
+#define QETH_DBF_TRACE_NAME "qeth_trace"
+#define QETH_DBF_TRACE_LEN 8
+#define QETH_DBF_TRACE_PAGES 4
+#define QETH_DBF_TRACE_NR_AREAS 1
+#define QETH_DBF_TRACE_LEVEL 3
+
+#define QETH_DBF_SENSE_NAME "qeth_sense"
+#define QETH_DBF_SENSE_LEN 64
+#define QETH_DBF_SENSE_PAGES 2
+#define QETH_DBF_SENSE_NR_AREAS 1
+#define QETH_DBF_SENSE_LEVEL 2
+
+#define QETH_DBF_QERR_NAME "qeth_qerr"
+#define QETH_DBF_QERR_LEN 8
+#define QETH_DBF_QERR_PAGES 2
+#define QETH_DBF_QERR_NR_AREAS 1
+#define QETH_DBF_QERR_LEVEL 2
+
+#define QETH_DBF_TEXT(name, level, text) \
+	do { \
+		debug_text_event(qeth_dbf_##name, level, text); \
+	} while (0)
+
+#define QETH_DBF_HEX(name, level, addr, len) \
+	do { \
+		debug_event(qeth_dbf_##name, level, (void *)(addr), len); \
+	} while (0)
+
+/* Allow to sort out low debug levels early to avoid wasted sprints */
+static inline int qeth_dbf_passes(debug_info_t *dbf_grp, int level)
+{
+	return (level <= dbf_grp->level);
+}
+
+/**
+ * some more debug stuff
+ */
+#define PRINTK_HEADER	"qeth: "
+
+#define SENSE_COMMAND_REJECT_BYTE 0
+#define SENSE_COMMAND_REJECT_FLAG 0x80
+#define SENSE_RESETTING_EVENT_BYTE 1
+#define SENSE_RESETTING_EVENT_FLAG 0x80
+
+/*
+ * Common IO related definitions
+ */
+#define CARD_RDEV(card) card->read.ccwdev
+#define CARD_WDEV(card) card->write.ccwdev
+#define CARD_DDEV(card) card->data.ccwdev
+#define CARD_BUS_ID(card) card->gdev->dev.bus_id
+#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
+#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
+#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
+#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
+
+/**
+ * card stuff
+ */
+struct qeth_perf_stats {
+	unsigned int bufs_rec;
+	unsigned int bufs_sent;
+
+	unsigned int skbs_sent_pack;
+	unsigned int bufs_sent_pack;
+
+	unsigned int sc_dp_p;
+	unsigned int sc_p_dp;
+	/* qdio_input_handler: number of times called, time spent in */
+	__u64 inbound_start_time;
+	unsigned int inbound_cnt;
+	unsigned int inbound_time;
+	/* qeth_send_packet: number of times called, time spent in */
+	__u64 outbound_start_time;
+	unsigned int outbound_cnt;
+	unsigned int outbound_time;
+	/* qdio_output_handler: number of times called, time spent in */
+	__u64 outbound_handler_start_time;
+	unsigned int outbound_handler_cnt;
+	unsigned int outbound_handler_time;
+	/* number of calls to and time spent in do_QDIO for inbound queue */
+	__u64 inbound_do_qdio_start_time;
+	unsigned int inbound_do_qdio_cnt;
+	unsigned int inbound_do_qdio_time;
+	/* number of calls to and time spent in do_QDIO for outbound queues */
+	__u64 outbound_do_qdio_start_time;
+	unsigned int outbound_do_qdio_cnt;
+	unsigned int outbound_do_qdio_time;
+	/* eddp data */
+	unsigned int large_send_bytes;
+	unsigned int large_send_cnt;
+	unsigned int sg_skbs_sent;
+	unsigned int sg_frags_sent;
+	/* initial values when measuring starts */
+	unsigned long initial_rx_packets;
+	unsigned long initial_tx_packets;
+	/* inbound scatter gather data */
+	unsigned int sg_skbs_rx;
+	unsigned int sg_frags_rx;
+	unsigned int sg_alloc_page_rx;
+};
+
+/* Routing stuff */
+struct qeth_routing_info {
+	enum qeth_routing_types type;
+};
+
+/* IPA stuff */
+struct qeth_ipa_info {
+	__u32 supported_funcs;
+	__u32 enabled_funcs;
+};
+
+static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
+		enum qeth_ipa_funcs func)
+{
+	return (ipa->supported_funcs & func);
+}
+
+static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
+		enum qeth_ipa_funcs func)
+{
+	return (ipa->supported_funcs & ipa->enabled_funcs & func);
+}
+
+#define qeth_adp_supported(c, f) \
+	qeth_is_ipa_supported(&c->options.adp, f)
+#define qeth_adp_enabled(c, f) \
+	qeth_is_ipa_enabled(&c->options.adp, f)
+#define qeth_is_supported(c, f) \
+	qeth_is_ipa_supported(&c->options.ipa4, f)
+#define qeth_is_enabled(c, f) \
+	qeth_is_ipa_enabled(&c->options.ipa4, f)
+#define qeth_is_supported6(c, f) \
+	qeth_is_ipa_supported(&c->options.ipa6, f)
+#define qeth_is_enabled6(c, f) \
+	qeth_is_ipa_enabled(&c->options.ipa6, f)
+#define qeth_is_ipafunc_supported(c, prot, f) \
+	 ((prot == QETH_PROT_IPV6) ? \
+		qeth_is_supported6(c, f) : qeth_is_supported(c, f))
+#define qeth_is_ipafunc_enabled(c, prot, f) \
+	 ((prot == QETH_PROT_IPV6) ? \
+		qeth_is_enabled6(c, f) : qeth_is_enabled(c, f))
+
+#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
+#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
+#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
+#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
+
+#define QETH_MODELLIST_ARRAY \
+	{{0x1731, 0x01, 0x1732, 0x01, QETH_CARD_TYPE_OSAE, 1, \
+	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+	QETH_MAX_QUEUES, 0}, \
+	{0x1731, 0x05, 0x1732, 0x05, QETH_CARD_TYPE_IQD, 0, \
+	QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
+	QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
+	QETH_MAX_QUEUES, 0x103}, \
+	{0x1731, 0x06, 0x1732, 0x06, QETH_CARD_TYPE_OSN, 0, \
+	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+	QETH_MAX_QUEUES, 0}, \
+	{0, 0, 0, 0, 0, 0, 0, 0, 0} }
+
+#define QETH_REAL_CARD		1
+#define QETH_VLAN_CARD		2
+#define QETH_BUFSIZE		4096
+
+/**
+ * some more defs
+ */
+#define QETH_TX_TIMEOUT		100 * HZ
+#define QETH_RCD_TIMEOUT	60 * HZ
+#define QETH_HEADER_SIZE	32
+#define QETH_MAX_PORTNO		15
+
+/*IPv6 address autoconfiguration stuff*/
+#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe
+#define UNIQUE_ID_NOT_BY_CARD		0x10000
+
+/*****************************************************************************/
+/* QDIO queue and buffer handling                                            */
+/*****************************************************************************/
+#define QETH_MAX_QUEUES 4
+#define QETH_IN_BUF_SIZE_DEFAULT 65536
+#define QETH_IN_BUF_COUNT_DEFAULT 16
+#define QETH_IN_BUF_COUNT_MIN 8
+#define QETH_IN_BUF_COUNT_MAX 128
+#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
+#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
+		((card)->qdio.in_buf_pool.buf_count / 2)
+
+/* buffers we have to be behind before we get a PCI */
+#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
+/*enqueued free buffers left before we get a PCI*/
+#define QETH_PCI_THRESHOLD_B(card) 0
+/*not used unless the microcode gets patched*/
+#define QETH_PCI_TIMER_VALUE(card) 3
+
+#define QETH_MIN_INPUT_THRESHOLD 1
+#define QETH_MAX_INPUT_THRESHOLD 500
+#define QETH_MIN_OUTPUT_THRESHOLD 1
+#define QETH_MAX_OUTPUT_THRESHOLD 300
+
+/* priority queing */
+#define QETH_PRIOQ_DEFAULT QETH_NO_PRIO_QUEUEING
+#define QETH_DEFAULT_QUEUE    2
+#define QETH_NO_PRIO_QUEUEING 0
+#define QETH_PRIO_Q_ING_PREC  1
+#define QETH_PRIO_Q_ING_TOS   2
+#define IP_TOS_LOWDELAY 0x10
+#define IP_TOS_HIGHTHROUGHPUT 0x08
+#define IP_TOS_HIGHRELIABILITY 0x04
+#define IP_TOS_NOTIMPORTANT 0x02
+
+/* Packing */
+#define QETH_LOW_WATERMARK_PACK  2
+#define QETH_HIGH_WATERMARK_PACK 5
+#define QETH_WATERMARK_PACK_FUZZ 1
+
+#define QETH_IP_HEADER_SIZE 40
+
+/* large receive scatter gather copy break */
+#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+
+struct qeth_hdr_layer3 {
+	__u8  id;
+	__u8  flags;
+	__u16 inbound_checksum; /*TSO:__u16 seqno */
+	__u32 token;		/*TSO: __u32 reserved */
+	__u16 length;
+	__u8  vlan_prio;
+	__u8  ext_flags;
+	__u16 vlan_id;
+	__u16 frame_offset;
+	__u8  dest_addr[16];
+} __attribute__ ((packed));
+
+struct qeth_hdr_layer2 {
+	__u8 id;
+	__u8 flags[3];
+	__u8 port_no;
+	__u8 hdr_length;
+	__u16 pkt_length;
+	__u16 seq_no;
+	__u16 vlan_id;
+	__u32 reserved;
+	__u8 reserved2[16];
+} __attribute__ ((packed));
+
+struct qeth_hdr_osn {
+	__u8 id;
+	__u8 reserved;
+	__u16 seq_no;
+	__u16 reserved2;
+	__u16 control_flags;
+	__u16 pdu_length;
+	__u8 reserved3[18];
+	__u32 ccid;
+} __attribute__ ((packed));
+
+struct qeth_hdr {
+	union {
+		struct qeth_hdr_layer2 l2;
+		struct qeth_hdr_layer3 l3;
+		struct qeth_hdr_osn    osn;
+	} hdr;
+} __attribute__ ((packed));
+
+/*TCP Segmentation Offload header*/
+struct qeth_hdr_ext_tso {
+	__u16 hdr_tot_len;
+	__u8  imb_hdr_no;
+	__u8  reserved;
+	__u8  hdr_type;
+	__u8  hdr_version;
+	__u16 hdr_len;
+	__u32 payload_len;
+	__u16 mss;
+	__u16 dg_hdr_len;
+	__u8  padding[16];
+} __attribute__ ((packed));
+
+struct qeth_hdr_tso {
+	struct qeth_hdr hdr;	/*hdr->hdr.l3.xxx*/
+	struct qeth_hdr_ext_tso ext;
+} __attribute__ ((packed));
+
+
+/* flags for qeth_hdr.flags */
+#define QETH_HDR_PASSTHRU 0x10
+#define QETH_HDR_IPV6     0x80
+#define QETH_HDR_CAST_MASK 0x07
+enum qeth_cast_flags {
+	QETH_CAST_UNICAST   = 0x06,
+	QETH_CAST_MULTICAST = 0x04,
+	QETH_CAST_BROADCAST = 0x05,
+	QETH_CAST_ANYCAST   = 0x07,
+	QETH_CAST_NOCAST    = 0x00,
+};
+
+enum qeth_layer2_frame_flags {
+	QETH_LAYER2_FLAG_MULTICAST = 0x01,
+	QETH_LAYER2_FLAG_BROADCAST = 0x02,
+	QETH_LAYER2_FLAG_UNICAST   = 0x04,
+	QETH_LAYER2_FLAG_VLAN      = 0x10,
+};
+
+enum qeth_header_ids {
+	QETH_HEADER_TYPE_LAYER3 = 0x01,
+	QETH_HEADER_TYPE_LAYER2 = 0x02,
+	QETH_HEADER_TYPE_TSO	= 0x03,
+	QETH_HEADER_TYPE_OSN    = 0x04,
+};
+/* flags for qeth_hdr.ext_flags */
+#define QETH_HDR_EXT_VLAN_FRAME       0x01
+#define QETH_HDR_EXT_TOKEN_ID         0x02
+#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
+#define QETH_HDR_EXT_SRC_MAC_ADDR     0x08
+#define QETH_HDR_EXT_CSUM_HDR_REQ     0x10
+#define QETH_HDR_EXT_CSUM_TRANSP_REQ  0x20
+#define QETH_HDR_EXT_UDP_TSO          0x40 /*bit off for TCP*/
+
+static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale)
+{
+	return (sbale->flags & SBAL_FLAGS_LAST_ENTRY);
+}
+
+enum qeth_qdio_buffer_states {
+	/*
+	 * inbound: read out by driver; owned by hardware in order to be filled
+	 * outbound: owned by driver in order to be filled
+	 */
+	QETH_QDIO_BUF_EMPTY,
+	/*
+	 * inbound: filled by hardware; owned by driver in order to be read out
+	 * outbound: filled by driver; owned by hardware in order to be sent
+	 */
+	QETH_QDIO_BUF_PRIMED,
+};
+
+enum qeth_qdio_info_states {
+	QETH_QDIO_UNINITIALIZED,
+	QETH_QDIO_ALLOCATED,
+	QETH_QDIO_ESTABLISHED,
+	QETH_QDIO_CLEANING
+};
+
+struct qeth_buffer_pool_entry {
+	struct list_head list;
+	struct list_head init_list;
+	void *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
+};
+
+struct qeth_qdio_buffer_pool {
+	struct list_head entry_list;
+	int buf_count;
+};
+
+struct qeth_qdio_buffer {
+	struct qdio_buffer *buffer;
+	/* the buffer pool entry currently associated to this buffer */
+	struct qeth_buffer_pool_entry *pool_entry;
+};
+
+struct qeth_qdio_q {
+	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+	struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+	int next_buf_to_init;
+} __attribute__ ((aligned(256)));
+
+/* possible types of qeth large_send support */
+enum qeth_large_send_types {
+	QETH_LARGE_SEND_NO,
+	QETH_LARGE_SEND_EDDP,
+	QETH_LARGE_SEND_TSO,
+};
+
+struct qeth_qdio_out_buffer {
+	struct qdio_buffer *buffer;
+	atomic_t state;
+	int next_element_to_fill;
+	struct sk_buff_head skb_list;
+	struct list_head ctx_list;
+};
+
+struct qeth_card;
+
+enum qeth_out_q_states {
+       QETH_OUT_Q_UNLOCKED,
+       QETH_OUT_Q_LOCKED,
+       QETH_OUT_Q_LOCKED_FLUSH,
+};
+
+struct qeth_qdio_out_q {
+	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+	struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+	int queue_no;
+	struct qeth_card *card;
+	atomic_t state;
+	int do_pack;
+	/*
+	 * index of buffer to be filled by driver; state EMPTY or PACKING
+	 */
+	int next_buf_to_fill;
+	/*
+	 * number of buffers that are currently filled (PRIMED)
+	 * -> these buffers are hardware-owned
+	 */
+	atomic_t used_buffers;
+	/* indicates whether PCI flag must be set (or if one is outstanding) */
+	atomic_t set_pci_flags_count;
+} __attribute__ ((aligned(256)));
+
+struct qeth_qdio_info {
+	atomic_t state;
+	/* input */
+	struct qeth_qdio_q *in_q;
+	struct qeth_qdio_buffer_pool in_buf_pool;
+	struct qeth_qdio_buffer_pool init_pool;
+	int in_buf_size;
+
+	/* output */
+	int no_out_queues;
+	struct qeth_qdio_out_q **out_qs;
+
+	/* priority queueing */
+	int do_prio_queueing;
+	int default_out_queue;
+};
+
+enum qeth_send_errors {
+	QETH_SEND_ERROR_NONE,
+	QETH_SEND_ERROR_LINK_FAILURE,
+	QETH_SEND_ERROR_RETRY,
+	QETH_SEND_ERROR_KICK_IT,
+};
+
+#define QETH_ETH_MAC_V4      0x0100 /* like v4 */
+#define QETH_ETH_MAC_V6      0x3333 /* like v6 */
+/* tr mc mac is longer, but that will be enough to detect mc frames */
+#define QETH_TR_MAC_NC       0xc000 /* non-canonical */
+#define QETH_TR_MAC_C        0x0300 /* canonical */
+
+#define DEFAULT_ADD_HHLEN 0
+#define MAX_ADD_HHLEN 1024
+
+/**
+ * buffer stuff for read channel
+ */
+#define QETH_CMD_BUFFER_NO	8
+
+/**
+ *  channel state machine
+ */
+enum qeth_channel_states {
+	CH_STATE_UP,
+	CH_STATE_DOWN,
+	CH_STATE_ACTIVATING,
+	CH_STATE_HALTED,
+	CH_STATE_STOPPED,
+	CH_STATE_RCD,
+	CH_STATE_RCD_DONE,
+};
+/**
+ * card state machine
+ */
+enum qeth_card_states {
+	CARD_STATE_DOWN,
+	CARD_STATE_HARDSETUP,
+	CARD_STATE_SOFTSETUP,
+	CARD_STATE_UP,
+	CARD_STATE_RECOVER,
+};
+
+/**
+ * Protocol versions
+ */
+enum qeth_prot_versions {
+	QETH_PROT_IPV4 = 0x0004,
+	QETH_PROT_IPV6 = 0x0006,
+};
+
+enum qeth_ip_types {
+	QETH_IP_TYPE_NORMAL,
+	QETH_IP_TYPE_VIPA,
+	QETH_IP_TYPE_RXIP,
+	QETH_IP_TYPE_DEL_ALL_MC,
+};
+
+enum qeth_cmd_buffer_state {
+	BUF_STATE_FREE,
+	BUF_STATE_LOCKED,
+	BUF_STATE_PROCESSED,
+};
+
+struct qeth_ipato {
+	int enabled;
+	int invert4;
+	int invert6;
+	struct list_head entries;
+};
+
+struct qeth_channel;
+
+struct qeth_cmd_buffer {
+	enum qeth_cmd_buffer_state state;
+	struct qeth_channel *channel;
+	unsigned char *data;
+	int rc;
+	void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
+};
+
+/**
+ * definition of a qeth channel, used for read and write
+ */
+struct qeth_channel {
+	enum qeth_channel_states state;
+	struct ccw1 ccw;
+	spinlock_t iob_lock;
+	wait_queue_head_t wait_q;
+	struct tasklet_struct irq_tasklet;
+	struct ccw_device *ccwdev;
+/*command buffer for control data*/
+	struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
+	atomic_t irq_pending;
+	int io_buf_no;
+	int buf_no;
+};
+
+/**
+ *  OSA card related definitions
+ */
+struct qeth_token {
+	__u32 issuer_rm_w;
+	__u32 issuer_rm_r;
+	__u32 cm_filter_w;
+	__u32 cm_filter_r;
+	__u32 cm_connection_w;
+	__u32 cm_connection_r;
+	__u32 ulp_filter_w;
+	__u32 ulp_filter_r;
+	__u32 ulp_connection_w;
+	__u32 ulp_connection_r;
+};
+
+struct qeth_seqno {
+	__u32 trans_hdr;
+	__u32 pdu_hdr;
+	__u32 pdu_hdr_ack;
+	__u16 ipa;
+	__u32 pkt_seqno;
+};
+
+struct qeth_reply {
+	struct list_head list;
+	wait_queue_head_t wait_q;
+	int (*callback)(struct qeth_card *, struct qeth_reply *,
+		unsigned long);
+	u32 seqno;
+	unsigned long offset;
+	atomic_t received;
+	int rc;
+	void *param;
+	struct qeth_card *card;
+	atomic_t refcnt;
+};
+
+
+struct qeth_card_blkt {
+	int time_total;
+	int inter_packet;
+	int inter_packet_jumbo;
+};
+
+#define QETH_BROADCAST_WITH_ECHO    0x01
+#define QETH_BROADCAST_WITHOUT_ECHO 0x02
+#define QETH_LAYER2_MAC_READ	    0x01
+#define QETH_LAYER2_MAC_REGISTERED  0x02
+struct qeth_card_info {
+	unsigned short unit_addr2;
+	unsigned short cula;
+	unsigned short chpid;
+	__u16 func_level;
+	char mcl_level[QETH_MCL_LENGTH + 1];
+	int guestlan;
+	int mac_bits;
+	int portname_required;
+	int portno;
+	char portname[9];
+	enum qeth_card_types type;
+	enum qeth_link_types link_type;
+	int is_multicast_different;
+	int initial_mtu;
+	int max_mtu;
+	int broadcast_capable;
+	int unique_id;
+	struct qeth_card_blkt blkt;
+	__u32 csum_mask;
+	enum qeth_ipa_promisc_modes promisc_mode;
+};
+
+struct qeth_card_options {
+	struct qeth_routing_info route4;
+	struct qeth_ipa_info ipa4;
+	struct qeth_ipa_info adp; /*Adapter parameters*/
+	struct qeth_routing_info route6;
+	struct qeth_ipa_info ipa6;
+	enum qeth_checksum_types checksum_type;
+	int broadcast_mode;
+	int macaddr_mode;
+	int fake_broadcast;
+	int add_hhlen;
+	int fake_ll;
+	int layer2;
+	enum qeth_large_send_types large_send;
+	int performance_stats;
+	int rx_sg_cb;
+};
+
+/*
+ * thread bits for qeth_card thread masks
+ */
+enum qeth_threads {
+	QETH_RECOVER_THREAD = 1,
+};
+
+struct qeth_osn_info {
+	int (*assist_cb)(struct net_device *dev, void *data);
+	int (*data_cb)(struct sk_buff *skb);
+};
+
+enum qeth_discipline_id {
+	QETH_DISCIPLINE_LAYER3 = 0,
+	QETH_DISCIPLINE_LAYER2 = 1,
+};
+
+struct qeth_discipline {
+	qdio_handler_t *input_handler;
+	qdio_handler_t *output_handler;
+	int (*recover)(void *ptr);
+	struct ccwgroup_driver *ccwgdriver;
+};
+
+struct qeth_vlan_vid {
+	struct list_head list;
+	unsigned short vid;
+};
+
+struct qeth_mc_mac {
+	struct list_head list;
+	__u8 mc_addr[MAX_ADDR_LEN];
+	unsigned char mc_addrlen;
+};
+
+struct qeth_card {
+	struct list_head list;
+	enum qeth_card_states state;
+	int lan_online;
+	spinlock_t lock;
+	struct ccwgroup_device *gdev;
+	struct qeth_channel read;
+	struct qeth_channel write;
+	struct qeth_channel data;
+
+	struct net_device *dev;
+	struct net_device_stats stats;
+
+	struct qeth_card_info info;
+	struct qeth_token token;
+	struct qeth_seqno seqno;
+	struct qeth_card_options options;
+
+	wait_queue_head_t wait_q;
+	spinlock_t vlanlock;
+	spinlock_t mclock;
+	struct vlan_group *vlangrp;
+	struct list_head vid_list;
+	struct list_head mc_list;
+	struct work_struct kernel_thread_starter;
+	spinlock_t thread_mask_lock;
+	unsigned long thread_start_mask;
+	unsigned long thread_allowed_mask;
+	unsigned long thread_running_mask;
+	spinlock_t ip_lock;
+	struct list_head ip_list;
+	struct list_head *ip_tbd_list;
+	struct qeth_ipato ipato;
+	struct list_head cmd_waiter_list;
+	/* QDIO buffer handling */
+	struct qeth_qdio_info qdio;
+	struct qeth_perf_stats perf_stats;
+	int use_hard_stop;
+	struct qeth_osn_info osn_info;
+	struct qeth_discipline discipline;
+	atomic_t force_alloc_skb;
+};
+
+struct qeth_card_list_struct {
+	struct list_head list;
+	rwlock_t rwlock;
+};
+
+/*some helper functions*/
+#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
+
+static inline struct qeth_card *CARD_FROM_CDEV(struct ccw_device *cdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&((struct ccwgroup_device *)
+		dev_get_drvdata(&cdev->dev))->dev);
+	return card;
+}
+
+static inline int qeth_get_micros(void)
+{
+	return (int) (get_clock() >> 12);
+}
+
+static inline void *qeth_push_skb(struct qeth_card *card, struct sk_buff *skb,
+		int size)
+{
+	void *hdr;
+
+	hdr = (void *) skb_push(skb, size);
+	/*
+	 * sanity check, the Linux memory allocation scheme should
+	 * never present us cases like this one (the qdio header size plus
+	 * the first 40 bytes of the paket cross a 4k boundary)
+	 */
+	if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
+	    (((unsigned long) hdr + size +
+	    QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
+		PRINT_ERR("Misaligned packet on interface %s. Discarded.",
+			QETH_CARD_IFNAME(card));
+		return NULL;
+	}
+	return hdr;
+}
+
+static inline int qeth_get_ip_version(struct sk_buff *skb)
+{
+	switch (skb->protocol) {
+	case ETH_P_IPV6:
+		return 6;
+	case ETH_P_IP:
+		return 4;
+	default:
+		return 0;
+	}
+}
+
+struct qeth_eddp_context;
+extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
+extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
+const char *qeth_get_cardname_short(struct qeth_card *);
+int qeth_realloc_buffer_pool(struct qeth_card *, int);
+int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
+void qeth_core_free_discipline(struct qeth_card *);
+int qeth_core_create_device_attributes(struct device *);
+void qeth_core_remove_device_attributes(struct device *);
+int qeth_core_create_osn_attributes(struct device *);
+void qeth_core_remove_osn_attributes(struct device *);
+
+/* exports for qeth discipline device drivers */
+extern struct qeth_card_list_struct qeth_core_card_list;
+extern debug_info_t *qeth_dbf_setup;
+extern debug_info_t *qeth_dbf_data;
+extern debug_info_t *qeth_dbf_misc;
+extern debug_info_t *qeth_dbf_control;
+extern debug_info_t *qeth_dbf_trace;
+extern debug_info_t *qeth_dbf_sense;
+extern debug_info_t *qeth_dbf_qerr;
+
+void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
+int qeth_threads_running(struct qeth_card *, unsigned long);
+int qeth_wait_for_threads(struct qeth_card *, unsigned long);
+int qeth_do_run_thread(struct qeth_card *, unsigned long);
+void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
+void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
+int qeth_core_hardsetup_card(struct qeth_card *);
+void qeth_print_status_message(struct qeth_card *);
+int qeth_init_qdio_queues(struct qeth_card *);
+int qeth_send_startlan(struct qeth_card *);
+int qeth_send_stoplan(struct qeth_card *);
+int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
+		  int (*reply_cb)
+		  (struct qeth_card *, struct qeth_reply *, unsigned long),
+		  void *);
+struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
+			enum qeth_ipa_cmds, enum qeth_prot_versions);
+int qeth_query_setadapterparms(struct qeth_card *);
+int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int,
+		       unsigned int, const char *);
+void qeth_put_buffer_pool_entry(struct qeth_card *,
+			   struct qeth_buffer_pool_entry *);
+void qeth_queue_input_buffer(struct qeth_card *, int);
+struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
+		struct qdio_buffer *, struct qdio_buffer_element **, int *,
+		struct qeth_hdr **);
+void qeth_schedule_recovery(struct qeth_card *);
+void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
+			unsigned int, unsigned int,
+			unsigned int, int, int,
+			unsigned long);
+void qeth_clear_ipacmd_list(struct qeth_card *);
+int qeth_qdio_clear_card(struct qeth_card *, int);
+void qeth_clear_working_pool_list(struct qeth_card *);
+void qeth_clear_cmd_buffers(struct qeth_channel *);
+void qeth_clear_qdio_buffers(struct qeth_card *);
+void qeth_setadp_promisc_mode(struct qeth_card *);
+struct net_device_stats *qeth_get_stats(struct net_device *);
+int qeth_change_mtu(struct net_device *, int);
+int qeth_setadpparms_change_macaddr(struct qeth_card *);
+void qeth_tx_timeout(struct net_device *);
+void qeth_prepare_control_data(struct qeth_card *, int,
+				struct qeth_cmd_buffer *);
+void qeth_release_buffer(struct qeth_channel *, struct qeth_cmd_buffer *);
+void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char);
+struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
+int qeth_mdio_read(struct net_device *, int, int);
+int qeth_snmp_command(struct qeth_card *, char __user *);
+int qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
+struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32);
+int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *,
+					unsigned long);
+int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
+	int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
+	void *reply_param);
+int qeth_get_cast_type(struct qeth_card *, struct sk_buff *);
+int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
+struct sk_buff *qeth_prepare_skb(struct qeth_card *, struct sk_buff *,
+		 struct qeth_hdr **);
+int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
+int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
+			struct sk_buff *, struct qeth_hdr *, int,
+			struct qeth_eddp_context *);
+int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *,
+		    struct sk_buff *, struct qeth_hdr *,
+		    int, struct qeth_eddp_context *);
+int qeth_core_get_stats_count(struct net_device *);
+void qeth_core_get_ethtool_stats(struct net_device *,
+				struct ethtool_stats *, u64 *);
+void qeth_core_get_strings(struct net_device *, u32, u8 *);
+void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
+
+/* exports for OSN */
+int qeth_osn_assist(struct net_device *, void *, int);
+int qeth_osn_register(unsigned char *read_dev_no, struct net_device **,
+		int (*assist_cb)(struct net_device *, void *),
+		int (*data_cb)(struct sk_buff *));
+void qeth_osn_deregister(struct net_device *);
+
+#endif /* __QETH_CORE_H__ */
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
new file mode 100644
index 0000000..95c6fcf
--- /dev/null
+++ b/drivers/s390/net/qeth_core_main.c
@@ -0,0 +1,4540 @@
+/*
+ *  drivers/s390/net/qeth_core_main.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
+ *		 Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/mii.h>
+#include <linux/kthread.h>
+
+#include <asm-s390/ebcdic.h>
+#include <asm-s390/io.h>
+#include <asm/s390_rdev.h>
+
+#include "qeth_core.h"
+#include "qeth_core_offl.h"
+
+#define QETH_DBF_TEXT_(name, level, text...) \
+	do { \
+		if (qeth_dbf_passes(qeth_dbf_##name, level)) { \
+			char *dbf_txt_buf = \
+				get_cpu_var(qeth_core_dbf_txt_buf); \
+			sprintf(dbf_txt_buf, text); \
+			debug_text_event(qeth_dbf_##name, level, dbf_txt_buf); \
+			put_cpu_var(qeth_core_dbf_txt_buf); \
+		} \
+	} while (0)
+
+struct qeth_card_list_struct qeth_core_card_list;
+EXPORT_SYMBOL_GPL(qeth_core_card_list);
+debug_info_t *qeth_dbf_setup;
+EXPORT_SYMBOL_GPL(qeth_dbf_setup);
+debug_info_t *qeth_dbf_data;
+EXPORT_SYMBOL_GPL(qeth_dbf_data);
+debug_info_t *qeth_dbf_misc;
+EXPORT_SYMBOL_GPL(qeth_dbf_misc);
+debug_info_t *qeth_dbf_control;
+EXPORT_SYMBOL_GPL(qeth_dbf_control);
+debug_info_t *qeth_dbf_trace;
+EXPORT_SYMBOL_GPL(qeth_dbf_trace);
+debug_info_t *qeth_dbf_sense;
+EXPORT_SYMBOL_GPL(qeth_dbf_sense);
+debug_info_t *qeth_dbf_qerr;
+EXPORT_SYMBOL_GPL(qeth_dbf_qerr);
+
+static struct device *qeth_core_root_dev;
+static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+static struct lock_class_key qdio_out_skb_queue_key;
+static DEFINE_PER_CPU(char[256], qeth_core_dbf_txt_buf);
+
+static void qeth_send_control_data_cb(struct qeth_channel *,
+			struct qeth_cmd_buffer *);
+static int qeth_issue_next_read(struct qeth_card *);
+static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *);
+static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32);
+static void qeth_free_buffer_pool(struct qeth_card *);
+static int qeth_qdio_establish(struct qeth_card *);
+
+
+static inline void __qeth_fill_buffer_frag(struct sk_buff *skb,
+		struct qdio_buffer *buffer, int is_tso,
+		int *next_element_to_fill)
+{
+	struct skb_frag_struct *frag;
+	int fragno;
+	unsigned long addr;
+	int element, cnt, dlen;
+
+	fragno = skb_shinfo(skb)->nr_frags;
+	element = *next_element_to_fill;
+	dlen = 0;
+
+	if (is_tso)
+		buffer->element[element].flags =
+			SBAL_FLAGS_MIDDLE_FRAG;
+	else
+		buffer->element[element].flags =
+			SBAL_FLAGS_FIRST_FRAG;
+	dlen = skb->len - skb->data_len;
+	if (dlen) {
+		buffer->element[element].addr = skb->data;
+		buffer->element[element].length = dlen;
+		element++;
+	}
+	for (cnt = 0; cnt < fragno; cnt++) {
+		frag = &skb_shinfo(skb)->frags[cnt];
+		addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+			frag->page_offset;
+		buffer->element[element].addr = (char *)addr;
+		buffer->element[element].length = frag->size;
+		if (cnt < (fragno - 1))
+			buffer->element[element].flags =
+				SBAL_FLAGS_MIDDLE_FRAG;
+		else
+			buffer->element[element].flags =
+				SBAL_FLAGS_LAST_FRAG;
+		element++;
+	}
+	*next_element_to_fill = element;
+}
+
+static inline const char *qeth_get_cardname(struct qeth_card *card)
+{
+	if (card->info.guestlan) {
+		switch (card->info.type) {
+		case QETH_CARD_TYPE_OSAE:
+			return " Guest LAN QDIO";
+		case QETH_CARD_TYPE_IQD:
+			return " Guest LAN Hiper";
+		default:
+			return " unknown";
+		}
+	} else {
+		switch (card->info.type) {
+		case QETH_CARD_TYPE_OSAE:
+			return " OSD Express";
+		case QETH_CARD_TYPE_IQD:
+			return " HiperSockets";
+		case QETH_CARD_TYPE_OSN:
+			return " OSN QDIO";
+		default:
+			return " unknown";
+		}
+	}
+	return " n/a";
+}
+
+/* max length to be returned: 14 */
+const char *qeth_get_cardname_short(struct qeth_card *card)
+{
+	if (card->info.guestlan) {
+		switch (card->info.type) {
+		case QETH_CARD_TYPE_OSAE:
+			return "GuestLAN QDIO";
+		case QETH_CARD_TYPE_IQD:
+			return "GuestLAN Hiper";
+		default:
+			return "unknown";
+		}
+	} else {
+		switch (card->info.type) {
+		case QETH_CARD_TYPE_OSAE:
+			switch (card->info.link_type) {
+			case QETH_LINK_TYPE_FAST_ETH:
+				return "OSD_100";
+			case QETH_LINK_TYPE_HSTR:
+				return "HSTR";
+			case QETH_LINK_TYPE_GBIT_ETH:
+				return "OSD_1000";
+			case QETH_LINK_TYPE_10GBIT_ETH:
+				return "OSD_10GIG";
+			case QETH_LINK_TYPE_LANE_ETH100:
+				return "OSD_FE_LANE";
+			case QETH_LINK_TYPE_LANE_TR:
+				return "OSD_TR_LANE";
+			case QETH_LINK_TYPE_LANE_ETH1000:
+				return "OSD_GbE_LANE";
+			case QETH_LINK_TYPE_LANE:
+				return "OSD_ATM_LANE";
+			default:
+				return "OSD_Express";
+			}
+		case QETH_CARD_TYPE_IQD:
+			return "HiperSockets";
+		case QETH_CARD_TYPE_OSN:
+			return "OSN";
+		default:
+			return "unknown";
+		}
+	}
+	return "n/a";
+}
+
+void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
+			 int clear_start_mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->thread_mask_lock, flags);
+	card->thread_allowed_mask = threads;
+	if (clear_start_mask)
+		card->thread_start_mask &= threads;
+	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+	wake_up(&card->wait_q);
+}
+EXPORT_SYMBOL_GPL(qeth_set_allowed_threads);
+
+int qeth_threads_running(struct qeth_card *card, unsigned long threads)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&card->thread_mask_lock, flags);
+	rc = (card->thread_running_mask & threads);
+	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_threads_running);
+
+int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
+{
+	return wait_event_interruptible(card->wait_q,
+			qeth_threads_running(card, threads) == 0);
+}
+EXPORT_SYMBOL_GPL(qeth_wait_for_threads);
+
+void qeth_clear_working_pool_list(struct qeth_card *card)
+{
+	struct qeth_buffer_pool_entry *pool_entry, *tmp;
+
+	QETH_DBF_TEXT(trace, 5, "clwrklst");
+	list_for_each_entry_safe(pool_entry, tmp,
+			    &card->qdio.in_buf_pool.entry_list, list){
+			list_del(&pool_entry->list);
+	}
+}
+EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list);
+
+static int qeth_alloc_buffer_pool(struct qeth_card *card)
+{
+	struct qeth_buffer_pool_entry *pool_entry;
+	void *ptr;
+	int i, j;
+
+	QETH_DBF_TEXT(trace, 5, "alocpool");
+	for (i = 0; i < card->qdio.init_pool.buf_count; ++i) {
+		pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
+		if (!pool_entry) {
+			qeth_free_buffer_pool(card);
+			return -ENOMEM;
+		}
+		for (j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j) {
+			ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA);
+			if (!ptr) {
+				while (j > 0)
+					free_page((unsigned long)
+						  pool_entry->elements[--j]);
+				kfree(pool_entry);
+				qeth_free_buffer_pool(card);
+				return -ENOMEM;
+			}
+			pool_entry->elements[j] = ptr;
+		}
+		list_add(&pool_entry->init_list,
+			 &card->qdio.init_pool.entry_list);
+	}
+	return 0;
+}
+
+int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
+{
+	QETH_DBF_TEXT(trace, 2, "realcbp");
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	/* TODO: steel/add buffers from/to a running card's buffer pool (?) */
+	qeth_clear_working_pool_list(card);
+	qeth_free_buffer_pool(card);
+	card->qdio.in_buf_pool.buf_count = bufcnt;
+	card->qdio.init_pool.buf_count = bufcnt;
+	return qeth_alloc_buffer_pool(card);
+}
+
+int qeth_set_large_send(struct qeth_card *card,
+		enum qeth_large_send_types type)
+{
+	int rc = 0;
+
+	if (card->dev == NULL) {
+		card->options.large_send = type;
+		return 0;
+	}
+	if (card->state == CARD_STATE_UP)
+		netif_tx_disable(card->dev);
+	card->options.large_send = type;
+	switch (card->options.large_send) {
+	case QETH_LARGE_SEND_EDDP:
+		card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+					NETIF_F_HW_CSUM;
+		break;
+	case QETH_LARGE_SEND_TSO:
+		if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
+			card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+						NETIF_F_HW_CSUM;
+		} else {
+			PRINT_WARN("TSO not supported on %s. "
+				   "large_send set to 'no'.\n",
+				   card->dev->name);
+			card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+						NETIF_F_HW_CSUM);
+			card->options.large_send = QETH_LARGE_SEND_NO;
+			rc = -EOPNOTSUPP;
+		}
+		break;
+	default: /* includes QETH_LARGE_SEND_NO */
+		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+					NETIF_F_HW_CSUM);
+		break;
+	}
+	if (card->state == CARD_STATE_UP)
+		netif_wake_queue(card->dev);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_set_large_send);
+
+static int qeth_issue_next_read(struct qeth_card *card)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(trace, 5, "issnxrd");
+	if (card->read.state != CH_STATE_UP)
+		return -EIO;
+	iob = qeth_get_buffer(&card->read);
+	if (!iob) {
+		PRINT_WARN("issue_next_read failed: no iob available!\n");
+		return -ENOMEM;
+	}
+	qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
+	QETH_DBF_TEXT(trace, 6, "noirqpnd");
+	rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
+			      (addr_t) iob, 0, 0);
+	if (rc) {
+		PRINT_ERR("Error in starting next read ccw! rc=%i\n", rc);
+		atomic_set(&card->read.irq_pending, 0);
+		qeth_schedule_recovery(card);
+		wake_up(&card->wait_q);
+	}
+	return rc;
+}
+
+static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
+{
+	struct qeth_reply *reply;
+
+	reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
+	if (reply) {
+		atomic_set(&reply->refcnt, 1);
+		atomic_set(&reply->received, 0);
+		reply->card = card;
+	};
+	return reply;
+}
+
+static void qeth_get_reply(struct qeth_reply *reply)
+{
+	WARN_ON(atomic_read(&reply->refcnt) <= 0);
+	atomic_inc(&reply->refcnt);
+}
+
+static void qeth_put_reply(struct qeth_reply *reply)
+{
+	WARN_ON(atomic_read(&reply->refcnt) <= 0);
+	if (atomic_dec_and_test(&reply->refcnt))
+		kfree(reply);
+}
+
+static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd,
+		struct qeth_card *card)
+{
+	int rc;
+	int com;
+	char *ipa_name;
+
+	com = cmd->hdr.command;
+	rc  = cmd->hdr.return_code;
+	ipa_name = qeth_get_ipa_cmd_name(com);
+
+	PRINT_ERR("%s(x%X) for %s returned x%X \"%s\"\n", ipa_name, com,
+		   QETH_CARD_IFNAME(card), rc, qeth_get_ipa_msg(rc));
+}
+
+static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
+		struct qeth_cmd_buffer *iob)
+{
+	struct qeth_ipa_cmd *cmd = NULL;
+
+	QETH_DBF_TEXT(trace, 5, "chkipad");
+	if (IS_IPA(iob->data)) {
+		cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
+		if (IS_IPA_REPLY(cmd)) {
+			if (cmd->hdr.return_code &&
+			    (cmd->hdr.command < IPA_CMD_SETCCID ||
+			     cmd->hdr.command > IPA_CMD_MODCCID))
+				qeth_issue_ipa_msg(cmd, card);
+			return cmd;
+		} else {
+			switch (cmd->hdr.command) {
+			case IPA_CMD_STOPLAN:
+				PRINT_WARN("Link failure on %s (CHPID 0x%X) - "
+					   "there is a network problem or "
+					   "someone pulled the cable or "
+					   "disabled the port.\n",
+					   QETH_CARD_IFNAME(card),
+					   card->info.chpid);
+				card->lan_online = 0;
+				if (card->dev && netif_carrier_ok(card->dev))
+					netif_carrier_off(card->dev);
+				return NULL;
+			case IPA_CMD_STARTLAN:
+				PRINT_INFO("Link reestablished on %s "
+					   "(CHPID 0x%X). Scheduling "
+					   "IP address reset.\n",
+					   QETH_CARD_IFNAME(card),
+					   card->info.chpid);
+				netif_carrier_on(card->dev);
+				qeth_schedule_recovery(card);
+				return NULL;
+			case IPA_CMD_MODCCID:
+				return cmd;
+			case IPA_CMD_REGISTER_LOCAL_ADDR:
+				QETH_DBF_TEXT(trace, 3, "irla");
+				break;
+			case IPA_CMD_UNREGISTER_LOCAL_ADDR:
+				QETH_DBF_TEXT(trace, 3, "urla");
+				break;
+			default:
+				PRINT_WARN("Received data is IPA "
+					   "but not a reply!\n");
+				break;
+			}
+		}
+	}
+	return cmd;
+}
+
+void qeth_clear_ipacmd_list(struct qeth_card *card)
+{
+	struct qeth_reply *reply, *r;
+	unsigned long flags;
+
+	QETH_DBF_TEXT(trace, 4, "clipalst");
+
+	spin_lock_irqsave(&card->lock, flags);
+	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+		qeth_get_reply(reply);
+		reply->rc = -EIO;
+		atomic_inc(&reply->received);
+		list_del_init(&reply->list);
+		wake_up(&reply->wait_q);
+		qeth_put_reply(reply);
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+}
+EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
+
+static int qeth_check_idx_response(unsigned char *buffer)
+{
+	if (!buffer)
+		return 0;
+
+	QETH_DBF_HEX(control, 2, buffer, QETH_DBF_CONTROL_LEN);
+	if ((buffer[2] & 0xc0) == 0xc0) {
+		PRINT_WARN("received an IDX TERMINATE "
+			   "with cause code 0x%02x%s\n",
+			   buffer[4],
+			   ((buffer[4] == 0x22) ?
+			    " -- try another portname" : ""));
+		QETH_DBF_TEXT(trace, 2, "ckidxres");
+		QETH_DBF_TEXT(trace, 2, " idxterm");
+		QETH_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
+		return -EIO;
+	}
+	return 0;
+}
+
+static void qeth_setup_ccw(struct qeth_channel *channel, unsigned char *iob,
+		__u32 len)
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT(trace, 4, "setupccw");
+	card = CARD_FROM_CDEV(channel->ccwdev);
+	if (channel == &card->read)
+		memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+	else
+		memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+	channel->ccw.count = len;
+	channel->ccw.cda = (__u32) __pa(iob);
+}
+
+static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel)
+{
+	__u8 index;
+
+	QETH_DBF_TEXT(trace, 6, "getbuff");
+	index = channel->io_buf_no;
+	do {
+		if (channel->iob[index].state == BUF_STATE_FREE) {
+			channel->iob[index].state = BUF_STATE_LOCKED;
+			channel->io_buf_no = (channel->io_buf_no + 1) %
+				QETH_CMD_BUFFER_NO;
+			memset(channel->iob[index].data, 0, QETH_BUFSIZE);
+			return channel->iob + index;
+		}
+		index = (index + 1) % QETH_CMD_BUFFER_NO;
+	} while (index != channel->io_buf_no);
+
+	return NULL;
+}
+
+void qeth_release_buffer(struct qeth_channel *channel,
+		struct qeth_cmd_buffer *iob)
+{
+	unsigned long flags;
+
+	QETH_DBF_TEXT(trace, 6, "relbuff");
+	spin_lock_irqsave(&channel->iob_lock, flags);
+	memset(iob->data, 0, QETH_BUFSIZE);
+	iob->state = BUF_STATE_FREE;
+	iob->callback = qeth_send_control_data_cb;
+	iob->rc = 0;
+	spin_unlock_irqrestore(&channel->iob_lock, flags);
+}
+EXPORT_SYMBOL_GPL(qeth_release_buffer);
+
+static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel)
+{
+	struct qeth_cmd_buffer *buffer = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&channel->iob_lock, flags);
+	buffer = __qeth_get_buffer(channel);
+	spin_unlock_irqrestore(&channel->iob_lock, flags);
+	return buffer;
+}
+
+struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *channel)
+{
+	struct qeth_cmd_buffer *buffer;
+	wait_event(channel->wait_q,
+		   ((buffer = qeth_get_buffer(channel)) != NULL));
+	return buffer;
+}
+EXPORT_SYMBOL_GPL(qeth_wait_for_buffer);
+
+void qeth_clear_cmd_buffers(struct qeth_channel *channel)
+{
+	int cnt;
+
+	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+		qeth_release_buffer(channel, &channel->iob[cnt]);
+	channel->buf_no = 0;
+	channel->io_buf_no = 0;
+}
+EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
+
+static void qeth_send_control_data_cb(struct qeth_channel *channel,
+		  struct qeth_cmd_buffer *iob)
+{
+	struct qeth_card *card;
+	struct qeth_reply *reply, *r;
+	struct qeth_ipa_cmd *cmd;
+	unsigned long flags;
+	int keep_reply;
+
+	QETH_DBF_TEXT(trace, 4, "sndctlcb");
+
+	card = CARD_FROM_CDEV(channel->ccwdev);
+	if (qeth_check_idx_response(iob->data)) {
+		qeth_clear_ipacmd_list(card);
+		qeth_schedule_recovery(card);
+		goto out;
+	}
+
+	cmd = qeth_check_ipa_data(card, iob);
+	if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
+		goto out;
+	/*in case of OSN : check if cmd is set */
+	if (card->info.type == QETH_CARD_TYPE_OSN &&
+	    cmd &&
+	    cmd->hdr.command != IPA_CMD_STARTLAN &&
+	    card->osn_info.assist_cb != NULL) {
+		card->osn_info.assist_cb(card->dev, cmd);
+		goto out;
+	}
+
+	spin_lock_irqsave(&card->lock, flags);
+	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+		if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
+		    ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
+			qeth_get_reply(reply);
+			list_del_init(&reply->list);
+			spin_unlock_irqrestore(&card->lock, flags);
+			keep_reply = 0;
+			if (reply->callback != NULL) {
+				if (cmd) {
+					reply->offset = (__u16)((char *)cmd -
+							(char *)iob->data);
+					keep_reply = reply->callback(card,
+							reply,
+							(unsigned long)cmd);
+				} else
+					keep_reply = reply->callback(card,
+							reply,
+							(unsigned long)iob);
+			}
+			if (cmd)
+				reply->rc = (u16) cmd->hdr.return_code;
+			else if (iob->rc)
+				reply->rc = iob->rc;
+			if (keep_reply) {
+				spin_lock_irqsave(&card->lock, flags);
+				list_add_tail(&reply->list,
+					      &card->cmd_waiter_list);
+				spin_unlock_irqrestore(&card->lock, flags);
+			} else {
+				atomic_inc(&reply->received);
+				wake_up(&reply->wait_q);
+			}
+			qeth_put_reply(reply);
+			goto out;
+		}
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+out:
+	memcpy(&card->seqno.pdu_hdr_ack,
+		QETH_PDU_HEADER_SEQ_NO(iob->data),
+		QETH_SEQ_NO_LENGTH);
+	qeth_release_buffer(channel, iob);
+}
+
+static int qeth_setup_channel(struct qeth_channel *channel)
+{
+	int cnt;
+
+	QETH_DBF_TEXT(setup, 2, "setupch");
+	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
+		channel->iob[cnt].data = (char *)
+			kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
+		if (channel->iob[cnt].data == NULL)
+			break;
+		channel->iob[cnt].state = BUF_STATE_FREE;
+		channel->iob[cnt].channel = channel;
+		channel->iob[cnt].callback = qeth_send_control_data_cb;
+		channel->iob[cnt].rc = 0;
+	}
+	if (cnt < QETH_CMD_BUFFER_NO) {
+		while (cnt-- > 0)
+			kfree(channel->iob[cnt].data);
+		return -ENOMEM;
+	}
+	channel->buf_no = 0;
+	channel->io_buf_no = 0;
+	atomic_set(&channel->irq_pending, 0);
+	spin_lock_init(&channel->iob_lock);
+
+	init_waitqueue_head(&channel->wait_q);
+	return 0;
+}
+
+static int qeth_set_thread_start_bit(struct qeth_card *card,
+		unsigned long thread)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->thread_mask_lock, flags);
+	if (!(card->thread_allowed_mask & thread) ||
+	      (card->thread_start_mask & thread)) {
+		spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+		return -EPERM;
+	}
+	card->thread_start_mask |= thread;
+	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+	return 0;
+}
+
+void qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->thread_mask_lock, flags);
+	card->thread_start_mask &= ~thread;
+	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+	wake_up(&card->wait_q);
+}
+EXPORT_SYMBOL_GPL(qeth_clear_thread_start_bit);
+
+void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->thread_mask_lock, flags);
+	card->thread_running_mask &= ~thread;
+	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+	wake_up(&card->wait_q);
+}
+EXPORT_SYMBOL_GPL(qeth_clear_thread_running_bit);
+
+static int __qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&card->thread_mask_lock, flags);
+	if (card->thread_start_mask & thread) {
+		if ((card->thread_allowed_mask & thread) &&
+		    !(card->thread_running_mask & thread)) {
+			rc = 1;
+			card->thread_start_mask &= ~thread;
+			card->thread_running_mask |= thread;
+		} else
+			rc = -EPERM;
+	}
+	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+	return rc;
+}
+
+int qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+{
+	int rc = 0;
+
+	wait_event(card->wait_q,
+		   (rc = __qeth_do_run_thread(card, thread)) >= 0);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_do_run_thread);
+
+void qeth_schedule_recovery(struct qeth_card *card)
+{
+	QETH_DBF_TEXT(trace, 2, "startrec");
+	if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
+		schedule_work(&card->kernel_thread_starter);
+}
+EXPORT_SYMBOL_GPL(qeth_schedule_recovery);
+
+static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
+{
+	int dstat, cstat;
+	char *sense;
+
+	sense = (char *) irb->ecw;
+	cstat = irb->scsw.cstat;
+	dstat = irb->scsw.dstat;
+
+	if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+		     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+		     SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
+		QETH_DBF_TEXT(trace, 2, "CGENCHK");
+		PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
+			   cdev->dev.bus_id, dstat, cstat);
+		print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
+				16, 1, irb, 64, 1);
+		return 1;
+	}
+
+	if (dstat & DEV_STAT_UNIT_CHECK) {
+		if (sense[SENSE_RESETTING_EVENT_BYTE] &
+		    SENSE_RESETTING_EVENT_FLAG) {
+			QETH_DBF_TEXT(trace, 2, "REVIND");
+			return 1;
+		}
+		if (sense[SENSE_COMMAND_REJECT_BYTE] &
+		    SENSE_COMMAND_REJECT_FLAG) {
+			QETH_DBF_TEXT(trace, 2, "CMDREJi");
+			return 0;
+		}
+		if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
+			QETH_DBF_TEXT(trace, 2, "AFFE");
+			return 1;
+		}
+		if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
+			QETH_DBF_TEXT(trace, 2, "ZEROSEN");
+			return 0;
+		}
+		QETH_DBF_TEXT(trace, 2, "DGENCHK");
+			return 1;
+	}
+	return 0;
+}
+
+static long __qeth_check_irb_error(struct ccw_device *cdev,
+		unsigned long intparm, struct irb *irb)
+{
+	if (!IS_ERR(irb))
+		return 0;
+
+	switch (PTR_ERR(irb)) {
+	case -EIO:
+		PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
+		QETH_DBF_TEXT(trace, 2, "ckirberr");
+		QETH_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
+		break;
+	case -ETIMEDOUT:
+		PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
+		QETH_DBF_TEXT(trace, 2, "ckirberr");
+		QETH_DBF_TEXT_(trace, 2, "  rc%d", -ETIMEDOUT);
+		if (intparm == QETH_RCD_PARM) {
+			struct qeth_card *card = CARD_FROM_CDEV(cdev);
+
+			if (card && (card->data.ccwdev == cdev)) {
+				card->data.state = CH_STATE_DOWN;
+				wake_up(&card->wait_q);
+			}
+		}
+		break;
+	default:
+		PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
+			   cdev->dev.bus_id);
+		QETH_DBF_TEXT(trace, 2, "ckirberr");
+		QETH_DBF_TEXT(trace, 2, "  rc???");
+	}
+	return PTR_ERR(irb);
+}
+
+static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
+		struct irb *irb)
+{
+	int rc;
+	int cstat, dstat;
+	struct qeth_cmd_buffer *buffer;
+	struct qeth_channel *channel;
+	struct qeth_card *card;
+	struct qeth_cmd_buffer *iob;
+	__u8 index;
+
+	QETH_DBF_TEXT(trace, 5, "irq");
+
+	if (__qeth_check_irb_error(cdev, intparm, irb))
+		return;
+	cstat = irb->scsw.cstat;
+	dstat = irb->scsw.dstat;
+
+	card = CARD_FROM_CDEV(cdev);
+	if (!card)
+		return;
+
+	if (card->read.ccwdev == cdev) {
+		channel = &card->read;
+		QETH_DBF_TEXT(trace, 5, "read");
+	} else if (card->write.ccwdev == cdev) {
+		channel = &card->write;
+		QETH_DBF_TEXT(trace, 5, "write");
+	} else {
+		channel = &card->data;
+		QETH_DBF_TEXT(trace, 5, "data");
+	}
+	atomic_set(&channel->irq_pending, 0);
+
+	if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
+		channel->state = CH_STATE_STOPPED;
+
+	if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
+		channel->state = CH_STATE_HALTED;
+
+	/*let's wake up immediately on data channel*/
+	if ((channel == &card->data) && (intparm != 0) &&
+	    (intparm != QETH_RCD_PARM))
+		goto out;
+
+	if (intparm == QETH_CLEAR_CHANNEL_PARM) {
+		QETH_DBF_TEXT(trace, 6, "clrchpar");
+		/* we don't have to handle this further */
+		intparm = 0;
+	}
+	if (intparm == QETH_HALT_CHANNEL_PARM) {
+		QETH_DBF_TEXT(trace, 6, "hltchpar");
+		/* we don't have to handle this further */
+		intparm = 0;
+	}
+	if ((dstat & DEV_STAT_UNIT_EXCEP) ||
+	    (dstat & DEV_STAT_UNIT_CHECK) ||
+	    (cstat)) {
+		if (irb->esw.esw0.erw.cons) {
+			/* TODO: we should make this s390dbf */
+			PRINT_WARN("sense data available on channel %s.\n",
+				   CHANNEL_ID(channel));
+			PRINT_WARN(" cstat 0x%X\n dstat 0x%X\n", cstat, dstat);
+			print_hex_dump(KERN_WARNING, "qeth: irb ",
+				DUMP_PREFIX_OFFSET, 16, 1, irb, 32, 1);
+			print_hex_dump(KERN_WARNING, "qeth: sense data ",
+				DUMP_PREFIX_OFFSET, 16, 1, irb->ecw, 32, 1);
+		}
+		if (intparm == QETH_RCD_PARM) {
+			channel->state = CH_STATE_DOWN;
+			goto out;
+		}
+		rc = qeth_get_problem(cdev, irb);
+		if (rc) {
+			qeth_schedule_recovery(card);
+			goto out;
+		}
+	}
+
+	if (intparm == QETH_RCD_PARM) {
+		channel->state = CH_STATE_RCD_DONE;
+		goto out;
+	}
+	if (intparm) {
+		buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
+		buffer->state = BUF_STATE_PROCESSED;
+	}
+	if (channel == &card->data)
+		return;
+	if (channel == &card->read &&
+	    channel->state == CH_STATE_UP)
+		qeth_issue_next_read(card);
+
+	iob = channel->iob;
+	index = channel->buf_no;
+	while (iob[index].state == BUF_STATE_PROCESSED) {
+		if (iob[index].callback != NULL)
+			iob[index].callback(channel, iob + index);
+
+		index = (index + 1) % QETH_CMD_BUFFER_NO;
+	}
+	channel->buf_no = index;
+out:
+	wake_up(&card->wait_q);
+	return;
+}
+
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+		 struct qeth_qdio_out_buffer *buf)
+{
+	int i;
+	struct sk_buff *skb;
+
+	/* is PCI flag set on buffer? */
+	if (buf->buffer->element[0].flags & 0x40)
+		atomic_dec(&queue->set_pci_flags_count);
+
+	skb = skb_dequeue(&buf->skb_list);
+	while (skb) {
+		atomic_dec(&skb->users);
+		dev_kfree_skb_any(skb);
+		skb = skb_dequeue(&buf->skb_list);
+	}
+	qeth_eddp_buf_release_contexts(buf);
+	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
+		buf->buffer->element[i].length = 0;
+		buf->buffer->element[i].addr = NULL;
+		buf->buffer->element[i].flags = 0;
+	}
+	buf->next_element_to_fill = 0;
+	atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
+}
+
+void qeth_clear_qdio_buffers(struct qeth_card *card)
+{
+	int i, j;
+
+	QETH_DBF_TEXT(trace, 2, "clearqdbf");
+	/* clear outbound buffers to free skbs */
+	for (i = 0; i < card->qdio.no_out_queues; ++i)
+		if (card->qdio.out_qs[i]) {
+			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+				qeth_clear_output_buffer(card->qdio.out_qs[i],
+						&card->qdio.out_qs[i]->bufs[j]);
+		}
+}
+EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers);
+
+static void qeth_free_buffer_pool(struct qeth_card *card)
+{
+	struct qeth_buffer_pool_entry *pool_entry, *tmp;
+	int i = 0;
+	QETH_DBF_TEXT(trace, 5, "freepool");
+	list_for_each_entry_safe(pool_entry, tmp,
+				 &card->qdio.init_pool.entry_list, init_list){
+		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
+			free_page((unsigned long)pool_entry->elements[i]);
+		list_del(&pool_entry->init_list);
+		kfree(pool_entry);
+	}
+}
+
+static void qeth_free_qdio_buffers(struct qeth_card *card)
+{
+	int i, j;
+
+	QETH_DBF_TEXT(trace, 2, "freeqdbf");
+	if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
+		QETH_QDIO_UNINITIALIZED)
+		return;
+	kfree(card->qdio.in_q);
+	card->qdio.in_q = NULL;
+	/* inbound buffer pool */
+	qeth_free_buffer_pool(card);
+	/* free outbound qdio_qs */
+	if (card->qdio.out_qs) {
+		for (i = 0; i < card->qdio.no_out_queues; ++i) {
+			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+				qeth_clear_output_buffer(card->qdio.out_qs[i],
+						&card->qdio.out_qs[i]->bufs[j]);
+			kfree(card->qdio.out_qs[i]);
+		}
+		kfree(card->qdio.out_qs);
+		card->qdio.out_qs = NULL;
+	}
+}
+
+static void qeth_clean_channel(struct qeth_channel *channel)
+{
+	int cnt;
+
+	QETH_DBF_TEXT(setup, 2, "freech");
+	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+		kfree(channel->iob[cnt].data);
+}
+
+static int qeth_is_1920_device(struct qeth_card *card)
+{
+	int single_queue = 0;
+	struct ccw_device *ccwdev;
+	struct channelPath_dsc {
+		u8 flags;
+		u8 lsn;
+		u8 desc;
+		u8 chpid;
+		u8 swla;
+		u8 zeroes;
+		u8 chla;
+		u8 chpp;
+	} *chp_dsc;
+
+	QETH_DBF_TEXT(setup, 2, "chk_1920");
+
+	ccwdev = card->data.ccwdev;
+	chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
+	if (chp_dsc != NULL) {
+		/* CHPP field bit 6 == 1 -> single queue */
+		single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
+		kfree(chp_dsc);
+	}
+	QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);
+	return single_queue;
+}
+
+static void qeth_init_qdio_info(struct qeth_card *card)
+{
+	QETH_DBF_TEXT(setup, 4, "intqdinf");
+	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+	/* inbound */
+	card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+	card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
+	card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
+	INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
+	INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
+}
+
+static void qeth_set_intial_options(struct qeth_card *card)
+{
+	card->options.route4.type = NO_ROUTER;
+	card->options.route6.type = NO_ROUTER;
+	card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
+	card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
+	card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
+	card->options.fake_broadcast = 0;
+	card->options.add_hhlen = DEFAULT_ADD_HHLEN;
+	card->options.fake_ll = 0;
+	card->options.performance_stats = 0;
+	card->options.rx_sg_cb = QETH_RX_SG_CB;
+}
+
+static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&card->thread_mask_lock, flags);
+	QETH_DBF_TEXT_(trace, 4, "  %02x%02x%02x",
+			(u8) card->thread_start_mask,
+			(u8) card->thread_allowed_mask,
+			(u8) card->thread_running_mask);
+	rc = (card->thread_start_mask & thread);
+	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+	return rc;
+}
+
+static void qeth_start_kernel_thread(struct work_struct *work)
+{
+	struct qeth_card *card = container_of(work, struct qeth_card,
+					kernel_thread_starter);
+	QETH_DBF_TEXT(trace , 2, "strthrd");
+
+	if (card->read.state != CH_STATE_UP &&
+	    card->write.state != CH_STATE_UP)
+		return;
+	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
+		kthread_run(card->discipline.recover, (void *) card,
+				"qeth_recover");
+}
+
+static int qeth_setup_card(struct qeth_card *card)
+{
+
+	QETH_DBF_TEXT(setup, 2, "setupcrd");
+	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+
+	card->read.state  = CH_STATE_DOWN;
+	card->write.state = CH_STATE_DOWN;
+	card->data.state  = CH_STATE_DOWN;
+	card->state = CARD_STATE_DOWN;
+	card->lan_online = 0;
+	card->use_hard_stop = 0;
+	card->dev = NULL;
+	spin_lock_init(&card->vlanlock);
+	spin_lock_init(&card->mclock);
+	card->vlangrp = NULL;
+	spin_lock_init(&card->lock);
+	spin_lock_init(&card->ip_lock);
+	spin_lock_init(&card->thread_mask_lock);
+	card->thread_start_mask = 0;
+	card->thread_allowed_mask = 0;
+	card->thread_running_mask = 0;
+	INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
+	INIT_LIST_HEAD(&card->ip_list);
+	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+	if (!card->ip_tbd_list) {
+		QETH_DBF_TEXT(setup, 0, "iptbdnom");
+		return -ENOMEM;
+	}
+	INIT_LIST_HEAD(card->ip_tbd_list);
+	INIT_LIST_HEAD(&card->cmd_waiter_list);
+	init_waitqueue_head(&card->wait_q);
+	/* intial options */
+	qeth_set_intial_options(card);
+	/* IP address takeover */
+	INIT_LIST_HEAD(&card->ipato.entries);
+	card->ipato.enabled = 0;
+	card->ipato.invert4 = 0;
+	card->ipato.invert6 = 0;
+	/* init QDIO stuff */
+	qeth_init_qdio_info(card);
+	return 0;
+}
+
+static struct qeth_card *qeth_alloc_card(void)
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT(setup, 2, "alloccrd");
+	card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
+	if (!card)
+		return NULL;
+	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+	if (qeth_setup_channel(&card->read)) {
+		kfree(card);
+		return NULL;
+	}
+	if (qeth_setup_channel(&card->write)) {
+		qeth_clean_channel(&card->read);
+		kfree(card);
+		return NULL;
+	}
+	card->options.layer2 = -1;
+	return card;
+}
+
+static int qeth_determine_card_type(struct qeth_card *card)
+{
+	int i = 0;
+
+	QETH_DBF_TEXT(setup, 2, "detcdtyp");
+
+	card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+	card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
+	while (known_devices[i][4]) {
+		if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
+		    (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
+			card->info.type = known_devices[i][4];
+			card->qdio.no_out_queues = known_devices[i][8];
+			card->info.is_multicast_different = known_devices[i][9];
+			if (qeth_is_1920_device(card)) {
+				PRINT_INFO("Priority Queueing not able "
+					   "due to hardware limitations!\n");
+				card->qdio.no_out_queues = 1;
+				card->qdio.default_out_queue = 0;
+			}
+			return 0;
+		}
+		i++;
+	}
+	card->info.type = QETH_CARD_TYPE_UNKNOWN;
+	PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
+	return -ENOENT;
+}
+
+static int qeth_clear_channel(struct qeth_channel *channel)
+{
+	unsigned long flags;
+	struct qeth_card *card;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "clearch");
+	card = CARD_FROM_CDEV(channel->ccwdev);
+	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+	rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
+	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+
+	if (rc)
+		return rc;
+	rc = wait_event_interruptible_timeout(card->wait_q,
+			channel->state == CH_STATE_STOPPED, QETH_TIMEOUT);
+	if (rc == -ERESTARTSYS)
+		return rc;
+	if (channel->state != CH_STATE_STOPPED)
+		return -ETIME;
+	channel->state = CH_STATE_DOWN;
+	return 0;
+}
+
+static int qeth_halt_channel(struct qeth_channel *channel)
+{
+	unsigned long flags;
+	struct qeth_card *card;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "haltch");
+	card = CARD_FROM_CDEV(channel->ccwdev);
+	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+	rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
+	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+
+	if (rc)
+		return rc;
+	rc = wait_event_interruptible_timeout(card->wait_q,
+			channel->state == CH_STATE_HALTED, QETH_TIMEOUT);
+	if (rc == -ERESTARTSYS)
+		return rc;
+	if (channel->state != CH_STATE_HALTED)
+		return -ETIME;
+	return 0;
+}
+
+static int qeth_halt_channels(struct qeth_card *card)
+{
+	int rc1 = 0, rc2 = 0, rc3 = 0;
+
+	QETH_DBF_TEXT(trace, 3, "haltchs");
+	rc1 = qeth_halt_channel(&card->read);
+	rc2 = qeth_halt_channel(&card->write);
+	rc3 = qeth_halt_channel(&card->data);
+	if (rc1)
+		return rc1;
+	if (rc2)
+		return rc2;
+	return rc3;
+}
+
+static int qeth_clear_channels(struct qeth_card *card)
+{
+	int rc1 = 0, rc2 = 0, rc3 = 0;
+
+	QETH_DBF_TEXT(trace, 3, "clearchs");
+	rc1 = qeth_clear_channel(&card->read);
+	rc2 = qeth_clear_channel(&card->write);
+	rc3 = qeth_clear_channel(&card->data);
+	if (rc1)
+		return rc1;
+	if (rc2)
+		return rc2;
+	return rc3;
+}
+
+static int qeth_clear_halt_card(struct qeth_card *card, int halt)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "clhacrd");
+	QETH_DBF_HEX(trace, 3, &card, sizeof(void *));
+
+	if (halt)
+		rc = qeth_halt_channels(card);
+	if (rc)
+		return rc;
+	return qeth_clear_channels(card);
+}
+
+int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "qdioclr");
+	switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED,
+		QETH_QDIO_CLEANING)) {
+	case QETH_QDIO_ESTABLISHED:
+		if (card->info.type == QETH_CARD_TYPE_IQD)
+			rc = qdio_cleanup(CARD_DDEV(card),
+				QDIO_FLAG_CLEANUP_USING_HALT);
+		else
+			rc = qdio_cleanup(CARD_DDEV(card),
+				QDIO_FLAG_CLEANUP_USING_CLEAR);
+		if (rc)
+			QETH_DBF_TEXT_(trace, 3, "1err%d", rc);
+		atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+		break;
+	case QETH_QDIO_CLEANING:
+		return rc;
+	default:
+		break;
+	}
+	rc = qeth_clear_halt_card(card, use_halt);
+	if (rc)
+		QETH_DBF_TEXT_(trace, 3, "2err%d", rc);
+	card->state = CARD_STATE_DOWN;
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_qdio_clear_card);
+
+static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
+			       int *length)
+{
+	struct ciw *ciw;
+	char *rcd_buf;
+	int ret;
+	struct qeth_channel *channel = &card->data;
+	unsigned long flags;
+
+	/*
+	 * scan for RCD command in extended SenseID data
+	 */
+	ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
+	if (!ciw || ciw->cmd == 0)
+		return -EOPNOTSUPP;
+	rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+	if (!rcd_buf)
+		return -ENOMEM;
+
+	channel->ccw.cmd_code = ciw->cmd;
+	channel->ccw.cda = (__u32) __pa(rcd_buf);
+	channel->ccw.count = ciw->count;
+	channel->ccw.flags = CCW_FLAG_SLI;
+	channel->state = CH_STATE_RCD;
+	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+	ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+				       QETH_RCD_PARM, LPM_ANYPATH, 0,
+				       QETH_RCD_TIMEOUT);
+	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+	if (!ret)
+		wait_event(card->wait_q,
+			   (channel->state == CH_STATE_RCD_DONE ||
+			    channel->state == CH_STATE_DOWN));
+	if (channel->state == CH_STATE_DOWN)
+		ret = -EIO;
+	else
+		channel->state = CH_STATE_DOWN;
+	if (ret) {
+		kfree(rcd_buf);
+		*buffer = NULL;
+		*length = 0;
+	} else {
+		*length = ciw->count;
+		*buffer = rcd_buf;
+	}
+	return ret;
+}
+
+static int qeth_get_unitaddr(struct qeth_card *card)
+{
+	int length;
+	char *prcd;
+	int rc;
+
+	QETH_DBF_TEXT(setup, 2, "getunit");
+	rc = qeth_read_conf_data(card, (void **) &prcd, &length);
+	if (rc) {
+		PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
+			CARD_DDEV_ID(card), rc);
+		return rc;
+	}
+	card->info.chpid = prcd[30];
+	card->info.unit_addr2 = prcd[31];
+	card->info.cula = prcd[63];
+	card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
+			       (prcd[0x11] == _ascebc['M']));
+	kfree(prcd);
+	return 0;
+}
+
+static void qeth_init_tokens(struct qeth_card *card)
+{
+	card->token.issuer_rm_w = 0x00010103UL;
+	card->token.cm_filter_w = 0x00010108UL;
+	card->token.cm_connection_w = 0x0001010aUL;
+	card->token.ulp_filter_w = 0x0001010bUL;
+	card->token.ulp_connection_w = 0x0001010dUL;
+}
+
+static void qeth_init_func_level(struct qeth_card *card)
+{
+	if (card->ipato.enabled) {
+		if (card->info.type == QETH_CARD_TYPE_IQD)
+				card->info.func_level =
+					QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
+		else
+				card->info.func_level =
+					QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
+	} else {
+		if (card->info.type == QETH_CARD_TYPE_IQD)
+		/*FIXME:why do we have same values for  dis and ena for
+		  osae??? */
+			card->info.func_level =
+				QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
+		else
+			card->info.func_level =
+				QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
+	}
+}
+
+static inline __u16 qeth_raw_devno_from_bus_id(char *id)
+{
+	id += (strlen(id) - 4);
+	return (__u16) simple_strtoul(id, &id, 16);
+}
+
+static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
+		void (*idx_reply_cb)(struct qeth_channel *,
+			struct qeth_cmd_buffer *))
+{
+	struct qeth_cmd_buffer *iob;
+	unsigned long flags;
+	int rc;
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT(setup, 2, "idxanswr");
+	card = CARD_FROM_CDEV(channel->ccwdev);
+	iob = qeth_get_buffer(channel);
+	iob->callback = idx_reply_cb;
+	memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+	channel->ccw.count = QETH_BUFSIZE;
+	channel->ccw.cda = (__u32) __pa(iob->data);
+
+	wait_event(card->wait_q,
+		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+	QETH_DBF_TEXT(setup, 6, "noirqpnd");
+	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+	rc = ccw_device_start(channel->ccwdev,
+			      &channel->ccw, (addr_t) iob, 0, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+
+	if (rc) {
+		PRINT_ERR("Error2 in activating channel rc=%d\n", rc);
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		atomic_set(&channel->irq_pending, 0);
+		wake_up(&card->wait_q);
+		return rc;
+	}
+	rc = wait_event_interruptible_timeout(card->wait_q,
+			 channel->state == CH_STATE_UP, QETH_TIMEOUT);
+	if (rc == -ERESTARTSYS)
+		return rc;
+	if (channel->state != CH_STATE_UP) {
+		rc = -ETIME;
+		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+		qeth_clear_cmd_buffers(channel);
+	} else
+		rc = 0;
+	return rc;
+}
+
+static int qeth_idx_activate_channel(struct qeth_channel *channel,
+		void (*idx_reply_cb)(struct qeth_channel *,
+			struct qeth_cmd_buffer *))
+{
+	struct qeth_card *card;
+	struct qeth_cmd_buffer *iob;
+	unsigned long flags;
+	__u16 temp;
+	__u8 tmp;
+	int rc;
+
+	card = CARD_FROM_CDEV(channel->ccwdev);
+
+	QETH_DBF_TEXT(setup, 2, "idxactch");
+
+	iob = qeth_get_buffer(channel);
+	iob->callback = idx_reply_cb;
+	memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+	channel->ccw.count = IDX_ACTIVATE_SIZE;
+	channel->ccw.cda = (__u32) __pa(iob->data);
+	if (channel == &card->write) {
+		memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
+		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+		card->seqno.trans_hdr++;
+	} else {
+		memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
+		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+	}
+	tmp = ((__u8)card->info.portno) | 0x80;
+	memcpy(QETH_IDX_ACT_PNO(iob->data), &tmp, 1);
+	memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+	       &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),
+	       &card->info.func_level, sizeof(__u16));
+	temp = qeth_raw_devno_from_bus_id(CARD_DDEV_ID(card));
+	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);
+	temp = (card->info.cula << 8) + card->info.unit_addr2;
+	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
+
+	wait_event(card->wait_q,
+		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+	QETH_DBF_TEXT(setup, 6, "noirqpnd");
+	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+	rc = ccw_device_start(channel->ccwdev,
+			      &channel->ccw, (addr_t) iob, 0, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+
+	if (rc) {
+		PRINT_ERR("Error1 in activating channel. rc=%d\n", rc);
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		atomic_set(&channel->irq_pending, 0);
+		wake_up(&card->wait_q);
+		return rc;
+	}
+	rc = wait_event_interruptible_timeout(card->wait_q,
+			channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);
+	if (rc == -ERESTARTSYS)
+		return rc;
+	if (channel->state != CH_STATE_ACTIVATING) {
+		PRINT_WARN("IDX activate timed out!\n");
+		QETH_DBF_TEXT_(setup, 2, "2err%d", -ETIME);
+		qeth_clear_cmd_buffers(channel);
+		return -ETIME;
+	}
+	return qeth_idx_activate_get_answer(channel, idx_reply_cb);
+}
+
+static int qeth_peer_func_level(int level)
+{
+	if ((level & 0xff) == 8)
+		return (level & 0xff) + 0x400;
+	if (((level >> 8) & 3) == 1)
+		return (level & 0xff) + 0x200;
+	return level;
+}
+
+static void qeth_idx_write_cb(struct qeth_channel *channel,
+		struct qeth_cmd_buffer *iob)
+{
+	struct qeth_card *card;
+	__u16 temp;
+
+	QETH_DBF_TEXT(setup , 2, "idxwrcb");
+
+	if (channel->state == CH_STATE_DOWN) {
+		channel->state = CH_STATE_ACTIVATING;
+		goto out;
+	}
+	card = CARD_FROM_CDEV(channel->ccwdev);
+
+	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+				"adapter exclusively used by another host\n",
+			CARD_WDEV_ID(card));
+		else
+			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+				"negative reply\n", CARD_WDEV_ID(card));
+		goto out;
+	}
+	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+	if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
+		PRINT_WARN("IDX_ACTIVATE on write channel device %s: "
+			   "function level mismatch "
+			   "(sent: 0x%x, received: 0x%x)\n",
+			   CARD_WDEV_ID(card), card->info.func_level, temp);
+		goto out;
+	}
+	channel->state = CH_STATE_UP;
+out:
+	qeth_release_buffer(channel, iob);
+}
+
+static void qeth_idx_read_cb(struct qeth_channel *channel,
+		struct qeth_cmd_buffer *iob)
+{
+	struct qeth_card *card;
+	__u16 temp;
+
+	QETH_DBF_TEXT(setup , 2, "idxrdcb");
+	if (channel->state == CH_STATE_DOWN) {
+		channel->state = CH_STATE_ACTIVATING;
+		goto out;
+	}
+
+	card = CARD_FROM_CDEV(channel->ccwdev);
+	if (qeth_check_idx_response(iob->data))
+			goto out;
+
+	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+				"adapter exclusively used by another host\n",
+				CARD_RDEV_ID(card));
+		else
+			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+				"negative reply\n", CARD_RDEV_ID(card));
+		goto out;
+	}
+
+/**
+ * temporary fix for microcode bug
+ * to revert it,replace OR by AND
+ */
+	if ((!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
+	     (card->info.type == QETH_CARD_TYPE_OSAE))
+		card->info.portname_required = 1;
+
+	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+	if (temp != qeth_peer_func_level(card->info.func_level)) {
+		PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
+			   "level mismatch (sent: 0x%x, received: 0x%x)\n",
+			   CARD_RDEV_ID(card), card->info.func_level, temp);
+		goto out;
+	}
+	memcpy(&card->token.issuer_rm_r,
+	       QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+	       QETH_MPC_TOKEN_LENGTH);
+	memcpy(&card->info.mcl_level[0],
+	       QETH_IDX_REPLY_LEVEL(iob->data), QETH_MCL_LENGTH);
+	channel->state = CH_STATE_UP;
+out:
+	qeth_release_buffer(channel, iob);
+}
+
+void qeth_prepare_control_data(struct qeth_card *card, int len,
+		struct qeth_cmd_buffer *iob)
+{
+	qeth_setup_ccw(&card->write, iob->data, len);
+	iob->callback = qeth_release_buffer;
+
+	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+	card->seqno.trans_hdr++;
+	memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+	       &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+	card->seqno.pdu_hdr++;
+	memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+	       &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+}
+EXPORT_SYMBOL_GPL(qeth_prepare_control_data);
+
+int qeth_send_control_data(struct qeth_card *card, int len,
+		struct qeth_cmd_buffer *iob,
+		int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
+			unsigned long),
+		void *reply_param)
+{
+	int rc;
+	unsigned long flags;
+	struct qeth_reply *reply = NULL;
+	unsigned long timeout;
+
+	QETH_DBF_TEXT(trace, 2, "sendctl");
+
+	reply = qeth_alloc_reply(card);
+	if (!reply) {
+		PRINT_WARN("Could no alloc qeth_reply!\n");
+		return -ENOMEM;
+	}
+	reply->callback = reply_cb;
+	reply->param = reply_param;
+	if (card->state == CARD_STATE_DOWN)
+		reply->seqno = QETH_IDX_COMMAND_SEQNO;
+	else
+		reply->seqno = card->seqno.ipa++;
+	init_waitqueue_head(&reply->wait_q);
+	spin_lock_irqsave(&card->lock, flags);
+	list_add_tail(&reply->list, &card->cmd_waiter_list);
+	spin_unlock_irqrestore(&card->lock, flags);
+	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+
+	while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
+	qeth_prepare_control_data(card, len, iob);
+
+	if (IS_IPA(iob->data))
+		timeout = jiffies + QETH_IPA_TIMEOUT;
+	else
+		timeout = jiffies + QETH_TIMEOUT;
+
+	QETH_DBF_TEXT(trace, 6, "noirqpnd");
+	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+			      (addr_t) iob, 0, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+	if (rc) {
+		PRINT_WARN("qeth_send_control_data: "
+			   "ccw_device_start rc = %i\n", rc);
+		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+		spin_lock_irqsave(&card->lock, flags);
+		list_del_init(&reply->list);
+		qeth_put_reply(reply);
+		spin_unlock_irqrestore(&card->lock, flags);
+		qeth_release_buffer(iob->channel, iob);
+		atomic_set(&card->write.irq_pending, 0);
+		wake_up(&card->wait_q);
+		return rc;
+	}
+	while (!atomic_read(&reply->received)) {
+		if (time_after(jiffies, timeout)) {
+			spin_lock_irqsave(&reply->card->lock, flags);
+			list_del_init(&reply->list);
+			spin_unlock_irqrestore(&reply->card->lock, flags);
+			reply->rc = -ETIME;
+			atomic_inc(&reply->received);
+			wake_up(&reply->wait_q);
+		}
+		cpu_relax();
+	};
+	rc = reply->rc;
+	qeth_put_reply(reply);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_control_data);
+
+static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+		unsigned long data)
+{
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(setup, 2, "cmenblcb");
+
+	iob = (struct qeth_cmd_buffer *) data;
+	memcpy(&card->token.cm_filter_r,
+	       QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
+	       QETH_MPC_TOKEN_LENGTH);
+	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+	return 0;
+}
+
+static int qeth_cm_enable(struct qeth_card *card)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(setup, 2, "cmenable");
+
+	iob = qeth_wait_for_buffer(&card->write);
+	memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
+	memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
+	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
+	       &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
+
+	rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
+				    qeth_cm_enable_cb, NULL);
+	return rc;
+}
+
+static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+		unsigned long data)
+{
+
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(setup, 2, "cmsetpcb");
+
+	iob = (struct qeth_cmd_buffer *) data;
+	memcpy(&card->token.cm_connection_r,
+	       QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
+	       QETH_MPC_TOKEN_LENGTH);
+	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+	return 0;
+}
+
+static int qeth_cm_setup(struct qeth_card *card)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(setup, 2, "cmsetup");
+
+	iob = qeth_wait_for_buffer(&card->write);
+	memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
+	memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
+	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
+	       &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
+	       &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
+	rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
+				    qeth_cm_setup_cb, NULL);
+	return rc;
+
+}
+
+static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card)
+{
+	switch (card->info.type) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return 1500;
+	case QETH_CARD_TYPE_IQD:
+		return card->info.max_mtu;
+	case QETH_CARD_TYPE_OSAE:
+		switch (card->info.link_type) {
+		case QETH_LINK_TYPE_HSTR:
+		case QETH_LINK_TYPE_LANE_TR:
+			return 2000;
+		default:
+			return 1492;
+		}
+	default:
+		return 1500;
+	}
+}
+
+static inline int qeth_get_max_mtu_for_card(int cardtype)
+{
+	switch (cardtype) {
+
+	case QETH_CARD_TYPE_UNKNOWN:
+	case QETH_CARD_TYPE_OSAE:
+	case QETH_CARD_TYPE_OSN:
+		return 61440;
+	case QETH_CARD_TYPE_IQD:
+		return 57344;
+	default:
+		return 1500;
+	}
+}
+
+static inline int qeth_get_mtu_out_of_mpc(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_IQD:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static inline int qeth_get_mtu_outof_framesize(int framesize)
+{
+	switch (framesize) {
+	case 0x4000:
+		return 8192;
+	case 0x6000:
+		return 16384;
+	case 0xa000:
+		return 32768;
+	case 0xffff:
+		return 57344;
+	default:
+		return 0;
+	}
+}
+
+static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu)
+{
+	switch (card->info.type) {
+	case QETH_CARD_TYPE_OSAE:
+		return ((mtu >= 576) && (mtu <= 61440));
+	case QETH_CARD_TYPE_IQD:
+		return ((mtu >= 576) &&
+			(mtu <= card->info.max_mtu + 4096 - 32));
+	case QETH_CARD_TYPE_OSN:
+	case QETH_CARD_TYPE_UNKNOWN:
+	default:
+		return 1;
+	}
+}
+
+static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+		unsigned long data)
+{
+
+	__u16 mtu, framesize;
+	__u16 len;
+	__u8 link_type;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(setup, 2, "ulpenacb");
+
+	iob = (struct qeth_cmd_buffer *) data;
+	memcpy(&card->token.ulp_filter_r,
+	       QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
+	       QETH_MPC_TOKEN_LENGTH);
+	if (qeth_get_mtu_out_of_mpc(card->info.type)) {
+		memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
+		mtu = qeth_get_mtu_outof_framesize(framesize);
+		if (!mtu) {
+			iob->rc = -EINVAL;
+			QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+			return 0;
+		}
+		card->info.max_mtu = mtu;
+		card->info.initial_mtu = mtu;
+		card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
+	} else {
+		card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
+		card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
+		card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+	}
+
+	memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
+	if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
+		memcpy(&link_type,
+		       QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
+		card->info.link_type = link_type;
+	} else
+		card->info.link_type = 0;
+	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+	return 0;
+}
+
+static int qeth_ulp_enable(struct qeth_card *card)
+{
+	int rc;
+	char prot_type;
+	struct qeth_cmd_buffer *iob;
+
+	/*FIXME: trace view callbacks*/
+	QETH_DBF_TEXT(setup, 2, "ulpenabl");
+
+	iob = qeth_wait_for_buffer(&card->write);
+	memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
+
+	*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
+		(__u8) card->info.portno;
+	if (card->options.layer2)
+		if (card->info.type == QETH_CARD_TYPE_OSN)
+			prot_type = QETH_PROT_OSN2;
+		else
+			prot_type = QETH_PROT_LAYER2;
+	else
+		prot_type = QETH_PROT_TCPIP;
+
+	memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data), &prot_type, 1);
+	memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
+	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
+	       &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
+	       card->info.portname, 9);
+	rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
+				    qeth_ulp_enable_cb, NULL);
+	return rc;
+
+}
+
+static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+		unsigned long data)
+{
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(setup, 2, "ulpstpcb");
+
+	iob = (struct qeth_cmd_buffer *) data;
+	memcpy(&card->token.ulp_connection_r,
+	       QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
+	       QETH_MPC_TOKEN_LENGTH);
+	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+	return 0;
+}
+
+static int qeth_ulp_setup(struct qeth_card *card)
+{
+	int rc;
+	__u16 temp;
+	struct qeth_cmd_buffer *iob;
+	struct ccw_dev_id dev_id;
+
+	QETH_DBF_TEXT(setup, 2, "ulpsetup");
+
+	iob = qeth_wait_for_buffer(&card->write);
+	memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
+
+	memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
+	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
+	       &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
+	       &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
+
+	ccw_device_get_id(CARD_DDEV(card), &dev_id);
+	memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
+	temp = (card->info.cula << 8) + card->info.unit_addr2;
+	memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
+	rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
+				    qeth_ulp_setup_cb, NULL);
+	return rc;
+}
+
+static int qeth_alloc_qdio_buffers(struct qeth_card *card)
+{
+	int i, j;
+
+	QETH_DBF_TEXT(setup, 2, "allcqdbf");
+
+	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
+		QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
+		return 0;
+
+	card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
+				  GFP_KERNEL|GFP_DMA);
+	if (!card->qdio.in_q)
+		goto out_nomem;
+	QETH_DBF_TEXT(setup, 2, "inq");
+	QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *));
+	memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
+	/* give inbound qeth_qdio_buffers their qdio_buffers */
+	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+		card->qdio.in_q->bufs[i].buffer =
+			&card->qdio.in_q->qdio_bufs[i];
+	/* inbound buffer pool */
+	if (qeth_alloc_buffer_pool(card))
+		goto out_freeinq;
+	/* outbound */
+	card->qdio.out_qs =
+		kmalloc(card->qdio.no_out_queues *
+			sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
+	if (!card->qdio.out_qs)
+		goto out_freepool;
+	for (i = 0; i < card->qdio.no_out_queues; ++i) {
+		card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
+					       GFP_KERNEL|GFP_DMA);
+		if (!card->qdio.out_qs[i])
+			goto out_freeoutq;
+		QETH_DBF_TEXT_(setup, 2, "outq %i", i);
+		QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *));
+		memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
+		card->qdio.out_qs[i]->queue_no = i;
+		/* give outbound qeth_qdio_buffers their qdio_buffers */
+		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+			card->qdio.out_qs[i]->bufs[j].buffer =
+				&card->qdio.out_qs[i]->qdio_bufs[j];
+			skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
+					    skb_list);
+			lockdep_set_class(
+				&card->qdio.out_qs[i]->bufs[j].skb_list.lock,
+				&qdio_out_skb_queue_key);
+			INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
+		}
+	}
+	return 0;
+
+out_freeoutq:
+	while (i > 0)
+		kfree(card->qdio.out_qs[--i]);
+	kfree(card->qdio.out_qs);
+	card->qdio.out_qs = NULL;
+out_freepool:
+	qeth_free_buffer_pool(card);
+out_freeinq:
+	kfree(card->qdio.in_q);
+	card->qdio.in_q = NULL;
+out_nomem:
+	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+	return -ENOMEM;
+}
+
+static void qeth_create_qib_param_field(struct qeth_card *card,
+		char *param_field)
+{
+
+	param_field[0] = _ascebc['P'];
+	param_field[1] = _ascebc['C'];
+	param_field[2] = _ascebc['I'];
+	param_field[3] = _ascebc['T'];
+	*((unsigned int *) (&param_field[4])) = QETH_PCI_THRESHOLD_A(card);
+	*((unsigned int *) (&param_field[8])) = QETH_PCI_THRESHOLD_B(card);
+	*((unsigned int *) (&param_field[12])) = QETH_PCI_TIMER_VALUE(card);
+}
+
+static void qeth_create_qib_param_field_blkt(struct qeth_card *card,
+		char *param_field)
+{
+	param_field[16] = _ascebc['B'];
+	param_field[17] = _ascebc['L'];
+	param_field[18] = _ascebc['K'];
+	param_field[19] = _ascebc['T'];
+	*((unsigned int *) (&param_field[20])) = card->info.blkt.time_total;
+	*((unsigned int *) (&param_field[24])) = card->info.blkt.inter_packet;
+	*((unsigned int *) (&param_field[28])) =
+		card->info.blkt.inter_packet_jumbo;
+}
+
+static int qeth_qdio_activate(struct qeth_card *card)
+{
+	QETH_DBF_TEXT(setup, 3, "qdioact");
+	return qdio_activate(CARD_DDEV(card), 0);
+}
+
+static int qeth_dm_act(struct qeth_card *card)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(setup, 2, "dmact");
+
+	iob = qeth_wait_for_buffer(&card->write);
+	memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
+
+	memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
+	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+	rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
+	return rc;
+}
+
+static int qeth_mpc_initialize(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(setup, 2, "mpcinit");
+
+	rc = qeth_issue_next_read(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return rc;
+	}
+	rc = qeth_cm_enable(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		goto out_qdio;
+	}
+	rc = qeth_cm_setup(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+		goto out_qdio;
+	}
+	rc = qeth_ulp_enable(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+		goto out_qdio;
+	}
+	rc = qeth_ulp_setup(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+		goto out_qdio;
+	}
+	rc = qeth_alloc_qdio_buffers(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+		goto out_qdio;
+	}
+	rc = qeth_qdio_establish(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+		qeth_free_qdio_buffers(card);
+		goto out_qdio;
+	}
+	rc = qeth_qdio_activate(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "7err%d", rc);
+		goto out_qdio;
+	}
+	rc = qeth_dm_act(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "8err%d", rc);
+		goto out_qdio;
+	}
+
+	return 0;
+out_qdio:
+	qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
+	return rc;
+}
+
+static void qeth_print_status_with_portname(struct qeth_card *card)
+{
+	char dbf_text[15];
+	int i;
+
+	sprintf(dbf_text, "%s", card->info.portname + 1);
+	for (i = 0; i < 8; i++)
+		dbf_text[i] =
+			(char) _ebcasc[(__u8) dbf_text[i]];
+	dbf_text[8] = 0;
+	PRINT_INFO("Device %s/%s/%s is a%s card%s%s%s\n"
+	       "with link type %s (portname: %s)\n",
+	       CARD_RDEV_ID(card),
+	       CARD_WDEV_ID(card),
+	       CARD_DDEV_ID(card),
+	       qeth_get_cardname(card),
+	       (card->info.mcl_level[0]) ? " (level: " : "",
+	       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+	       (card->info.mcl_level[0]) ? ")" : "",
+	       qeth_get_cardname_short(card),
+	       dbf_text);
+
+}
+
+static void qeth_print_status_no_portname(struct qeth_card *card)
+{
+	if (card->info.portname[0])
+		PRINT_INFO("Device %s/%s/%s is a%s "
+		       "card%s%s%s\nwith link type %s "
+		       "(no portname needed by interface).\n",
+		       CARD_RDEV_ID(card),
+		       CARD_WDEV_ID(card),
+		       CARD_DDEV_ID(card),
+		       qeth_get_cardname(card),
+		       (card->info.mcl_level[0]) ? " (level: " : "",
+		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+		       (card->info.mcl_level[0]) ? ")" : "",
+		       qeth_get_cardname_short(card));
+	else
+		PRINT_INFO("Device %s/%s/%s is a%s "
+		       "card%s%s%s\nwith link type %s.\n",
+		       CARD_RDEV_ID(card),
+		       CARD_WDEV_ID(card),
+		       CARD_DDEV_ID(card),
+		       qeth_get_cardname(card),
+		       (card->info.mcl_level[0]) ? " (level: " : "",
+		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+		       (card->info.mcl_level[0]) ? ")" : "",
+		       qeth_get_cardname_short(card));
+}
+
+void qeth_print_status_message(struct qeth_card *card)
+{
+	switch (card->info.type) {
+	case QETH_CARD_TYPE_OSAE:
+		/* VM will use a non-zero first character
+		 * to indicate a HiperSockets like reporting
+		 * of the level OSA sets the first character to zero
+		 * */
+		if (!card->info.mcl_level[0]) {
+			sprintf(card->info.mcl_level, "%02x%02x",
+				card->info.mcl_level[2],
+				card->info.mcl_level[3]);
+
+			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+			break;
+		}
+		/* fallthrough */
+	case QETH_CARD_TYPE_IQD:
+		if (card->info.guestlan) {
+			card->info.mcl_level[0] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[0]];
+			card->info.mcl_level[1] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[1]];
+			card->info.mcl_level[2] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[2]];
+			card->info.mcl_level[3] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[3]];
+			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+		}
+		break;
+	default:
+		memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
+	}
+	if (card->info.portname_required)
+		qeth_print_status_with_portname(card);
+	else
+		qeth_print_status_no_portname(card);
+}
+EXPORT_SYMBOL_GPL(qeth_print_status_message);
+
+void qeth_put_buffer_pool_entry(struct qeth_card *card,
+		struct qeth_buffer_pool_entry *entry)
+{
+	QETH_DBF_TEXT(trace, 6, "ptbfplen");
+	list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
+}
+EXPORT_SYMBOL_GPL(qeth_put_buffer_pool_entry);
+
+static void qeth_initialize_working_pool_list(struct qeth_card *card)
+{
+	struct qeth_buffer_pool_entry *entry;
+
+	QETH_DBF_TEXT(trace, 5, "inwrklst");
+
+	list_for_each_entry(entry,
+			    &card->qdio.init_pool.entry_list, init_list) {
+		qeth_put_buffer_pool_entry(card, entry);
+	}
+}
+
+static inline struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
+		struct qeth_card *card)
+{
+	struct list_head *plh;
+	struct qeth_buffer_pool_entry *entry;
+	int i, free;
+	struct page *page;
+
+	if (list_empty(&card->qdio.in_buf_pool.entry_list))
+		return NULL;
+
+	list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
+		entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
+		free = 1;
+		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+			if (page_count(virt_to_page(entry->elements[i])) > 1) {
+				free = 0;
+				break;
+			}
+		}
+		if (free) {
+			list_del_init(&entry->list);
+			return entry;
+		}
+	}
+
+	/* no free buffer in pool so take first one and swap pages */
+	entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
+			struct qeth_buffer_pool_entry, list);
+	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+		if (page_count(virt_to_page(entry->elements[i])) > 1) {
+			page = alloc_page(GFP_ATOMIC|GFP_DMA);
+			if (!page) {
+				return NULL;
+			} else {
+				free_page((unsigned long)entry->elements[i]);
+				entry->elements[i] = page_address(page);
+				if (card->options.performance_stats)
+					card->perf_stats.sg_alloc_page_rx++;
+			}
+		}
+	}
+	list_del_init(&entry->list);
+	return entry;
+}
+
+static int qeth_init_input_buffer(struct qeth_card *card,
+		struct qeth_qdio_buffer *buf)
+{
+	struct qeth_buffer_pool_entry *pool_entry;
+	int i;
+
+	pool_entry = qeth_find_free_buffer_pool_entry(card);
+	if (!pool_entry)
+		return 1;
+
+	/*
+	 * since the buffer is accessed only from the input_tasklet
+	 * there shouldn't be a need to synchronize; also, since we use
+	 * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run  out off
+	 * buffers
+	 */
+	BUG_ON(!pool_entry);
+
+	buf->pool_entry = pool_entry;
+	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+		buf->buffer->element[i].length = PAGE_SIZE;
+		buf->buffer->element[i].addr =  pool_entry->elements[i];
+		if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
+			buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
+		else
+			buf->buffer->element[i].flags = 0;
+	}
+	return 0;
+}
+
+int qeth_init_qdio_queues(struct qeth_card *card)
+{
+	int i, j;
+	int rc;
+
+	QETH_DBF_TEXT(setup, 2, "initqdqs");
+
+	/* inbound queue */
+	memset(card->qdio.in_q->qdio_bufs, 0,
+	       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+	qeth_initialize_working_pool_list(card);
+	/*give only as many buffers to hardware as we have buffer pool entries*/
+	for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
+		qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+	card->qdio.in_q->next_buf_to_init =
+		card->qdio.in_buf_pool.buf_count - 1;
+	rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
+		     card->qdio.in_buf_pool.buf_count - 1, NULL);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return rc;
+	}
+	rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		return rc;
+	}
+	/* outbound queue */
+	for (i = 0; i < card->qdio.no_out_queues; ++i) {
+		memset(card->qdio.out_qs[i]->qdio_bufs, 0,
+		       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+			qeth_clear_output_buffer(card->qdio.out_qs[i],
+					&card->qdio.out_qs[i]->bufs[j]);
+		}
+		card->qdio.out_qs[i]->card = card;
+		card->qdio.out_qs[i]->next_buf_to_fill = 0;
+		card->qdio.out_qs[i]->do_pack = 0;
+		atomic_set(&card->qdio.out_qs[i]->used_buffers, 0);
+		atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
+		atomic_set(&card->qdio.out_qs[i]->state,
+			   QETH_OUT_Q_UNLOCKED);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_init_qdio_queues);
+
+static inline __u8 qeth_get_ipa_adp_type(enum qeth_link_types link_type)
+{
+	switch (link_type) {
+	case QETH_LINK_TYPE_HSTR:
+		return 2;
+	default:
+		return 1;
+	}
+}
+
+static void qeth_fill_ipacmd_header(struct qeth_card *card,
+		struct qeth_ipa_cmd *cmd, __u8 command,
+		enum qeth_prot_versions prot)
+{
+	memset(cmd, 0, sizeof(struct qeth_ipa_cmd));
+	cmd->hdr.command = command;
+	cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
+	cmd->hdr.seqno = card->seqno.ipa;
+	cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
+	cmd->hdr.rel_adapter_no = (__u8) card->info.portno;
+	if (card->options.layer2)
+		cmd->hdr.prim_version_no = 2;
+	else
+		cmd->hdr.prim_version_no = 1;
+	cmd->hdr.param_count = 1;
+	cmd->hdr.prot_version = prot;
+	cmd->hdr.ipa_supported = 0;
+	cmd->hdr.ipa_enabled = 0;
+}
+
+struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
+		enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
+{
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	iob = qeth_wait_for_buffer(&card->write);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
+
+	return iob;
+}
+EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer);
+
+void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+		char prot_type)
+{
+	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);
+	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+}
+EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);
+
+int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+		int (*reply_cb)(struct qeth_card *, struct qeth_reply*,
+			unsigned long),
+		void *reply_param)
+{
+	int rc;
+	char prot_type;
+	int cmd;
+	cmd = ((struct qeth_ipa_cmd *)
+		(iob->data+IPA_PDU_HEADER_SIZE))->hdr.command;
+
+	QETH_DBF_TEXT(trace, 4, "sendipa");
+
+	if (card->options.layer2)
+		if (card->info.type == QETH_CARD_TYPE_OSN)
+			prot_type = QETH_PROT_OSN2;
+		else
+			prot_type = QETH_PROT_LAYER2;
+	else
+		prot_type = QETH_PROT_TCPIP;
+	qeth_prepare_ipa_cmd(card, iob, prot_type);
+	rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
+				    reply_cb, reply_param);
+	if (rc != 0) {
+		char *ipa_cmd_name;
+		ipa_cmd_name = qeth_get_ipa_cmd_name(cmd);
+		PRINT_ERR("%s %s(%x) returned %s(%x)\n", __FUNCTION__,
+			ipa_cmd_name, cmd, qeth_get_ipa_msg(rc), rc);
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
+
+static int qeth_send_startstoplan(struct qeth_card *card,
+		enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	iob = qeth_get_ipacmd_buffer(card, ipacmd, prot);
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+
+	return rc;
+}
+
+int qeth_send_startlan(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(setup, 2, "strtlan");
+
+	rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, 0);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_startlan);
+
+int qeth_send_stoplan(struct qeth_card *card)
+{
+	int rc = 0;
+
+	/*
+	 * TODO: according to the IPA format document page 14,
+	 * TCP/IP (we!) never issue a STOPLAN
+	 * is this right ?!?
+	 */
+	QETH_DBF_TEXT(setup, 2, "stoplan");
+
+	rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 0);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_stoplan);
+
+int qeth_default_setadapterparms_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "defadpcb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code == 0)
+		cmd->hdr.return_code =
+			cmd->data.setadapterparms.hdr.return_code;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_default_setadapterparms_cb);
+
+static int qeth_query_setadapterparms_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 3, "quyadpcb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
+		card->info.link_type =
+		      cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
+	card->options.adp.supported_funcs =
+		cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
+	return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+}
+
+struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
+		__u32 command, __u32 cmdlen)
+{
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETADAPTERPARMS,
+				     QETH_PROT_IPV4);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
+	cmd->data.setadapterparms.hdr.command_code = command;
+	cmd->data.setadapterparms.hdr.used_total = 1;
+	cmd->data.setadapterparms.hdr.seq_no = 1;
+
+	return iob;
+}
+EXPORT_SYMBOL_GPL(qeth_get_adapter_cmd);
+
+int qeth_query_setadapterparms(struct qeth_card *card)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(trace, 3, "queryadp");
+	iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_COMMANDS_SUPPORTED,
+				   sizeof(struct qeth_ipacmd_setadpparms));
+	rc = qeth_send_ipa_cmd(card, iob, qeth_query_setadapterparms_cb, NULL);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_query_setadapterparms);
+
+int qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
+		unsigned int siga_error, const char *dbftext)
+{
+	if (qdio_error || siga_error) {
+		QETH_DBF_TEXT(trace, 2, dbftext);
+		QETH_DBF_TEXT(qerr, 2, dbftext);
+		QETH_DBF_TEXT_(qerr, 2, " F15=%02X",
+			       buf->element[15].flags & 0xff);
+		QETH_DBF_TEXT_(qerr, 2, " F14=%02X",
+			       buf->element[14].flags & 0xff);
+		QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error);
+		QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error);
+		return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_check_qdio_errors);
+
+void qeth_queue_input_buffer(struct qeth_card *card, int index)
+{
+	struct qeth_qdio_q *queue = card->qdio.in_q;
+	int count;
+	int i;
+	int rc;
+	int newcount = 0;
+
+	QETH_DBF_TEXT(trace, 6, "queinbuf");
+	count = (index < queue->next_buf_to_init)?
+		card->qdio.in_buf_pool.buf_count -
+		(queue->next_buf_to_init - index) :
+		card->qdio.in_buf_pool.buf_count -
+		(queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
+	/* only requeue at a certain threshold to avoid SIGAs */
+	if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)) {
+		for (i = queue->next_buf_to_init;
+		     i < queue->next_buf_to_init + count; ++i) {
+			if (qeth_init_input_buffer(card,
+				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
+				break;
+			} else {
+				newcount++;
+			}
+		}
+
+		if (newcount < count) {
+			/* we are in memory shortage so we switch back to
+			   traditional skb allocation and drop packages */
+			if (!atomic_read(&card->force_alloc_skb) &&
+			    net_ratelimit())
+				PRINT_WARN("Switch to alloc skb\n");
+			atomic_set(&card->force_alloc_skb, 3);
+			count = newcount;
+		} else {
+			if ((atomic_read(&card->force_alloc_skb) == 1) &&
+			    net_ratelimit())
+				PRINT_WARN("Switch to sg\n");
+			atomic_add_unless(&card->force_alloc_skb, -1, 0);
+		}
+
+		/*
+		 * according to old code it should be avoided to requeue all
+		 * 128 buffers in order to benefit from PCI avoidance.
+		 * this function keeps at least one buffer (the buffer at
+		 * 'index') un-requeued -> this buffer is the first buffer that
+		 * will be requeued the next time
+		 */
+		if (card->options.performance_stats) {
+			card->perf_stats.inbound_do_qdio_cnt++;
+			card->perf_stats.inbound_do_qdio_start_time =
+				qeth_get_micros();
+		}
+		rc = do_QDIO(CARD_DDEV(card),
+			     QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
+			     0, queue->next_buf_to_init, count, NULL);
+		if (card->options.performance_stats)
+			card->perf_stats.inbound_do_qdio_time +=
+				qeth_get_micros() -
+				card->perf_stats.inbound_do_qdio_start_time;
+		if (rc) {
+			PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
+				   "return %i (device %s).\n",
+				   rc, CARD_DDEV_ID(card));
+			QETH_DBF_TEXT(trace, 2, "qinberr");
+			QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
+		}
+		queue->next_buf_to_init = (queue->next_buf_to_init + count) %
+					  QDIO_MAX_BUFFERS_PER_Q;
+	}
+}
+EXPORT_SYMBOL_GPL(qeth_queue_input_buffer);
+
+static int qeth_handle_send_error(struct qeth_card *card,
+		struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err,
+		unsigned int siga_err)
+{
+	int sbalf15 = buffer->buffer->element[15].flags & 0xff;
+	int cc = siga_err & 3;
+
+	QETH_DBF_TEXT(trace, 6, "hdsnderr");
+	qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
+	switch (cc) {
+	case 0:
+		if (qdio_err) {
+			QETH_DBF_TEXT(trace, 1, "lnkfail");
+			QETH_DBF_TEXT_(trace, 1, "%s", CARD_BUS_ID(card));
+			QETH_DBF_TEXT_(trace, 1, "%04x %02x",
+				       (u16)qdio_err, (u8)sbalf15);
+			return QETH_SEND_ERROR_LINK_FAILURE;
+		}
+		return QETH_SEND_ERROR_NONE;
+	case 2:
+		if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
+			QETH_DBF_TEXT(trace, 1, "SIGAcc2B");
+			QETH_DBF_TEXT_(trace, 1, "%s", CARD_BUS_ID(card));
+			return QETH_SEND_ERROR_KICK_IT;
+		}
+		if ((sbalf15 >= 15) && (sbalf15 <= 31))
+			return QETH_SEND_ERROR_RETRY;
+		return QETH_SEND_ERROR_LINK_FAILURE;
+		/* look at qdio_error and sbalf 15 */
+	case 1:
+		QETH_DBF_TEXT(trace, 1, "SIGAcc1");
+		QETH_DBF_TEXT_(trace, 1, "%s", CARD_BUS_ID(card));
+		return QETH_SEND_ERROR_LINK_FAILURE;
+	case 3:
+	default:
+		QETH_DBF_TEXT(trace, 1, "SIGAcc3");
+		QETH_DBF_TEXT_(trace, 1, "%s", CARD_BUS_ID(card));
+		return QETH_SEND_ERROR_KICK_IT;
+	}
+}
+
+/*
+ * Switched to packing state if the number of used buffers on a queue
+ * reaches a certain limit.
+ */
+static void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
+{
+	if (!queue->do_pack) {
+		if (atomic_read(&queue->used_buffers)
+		    >= QETH_HIGH_WATERMARK_PACK){
+			/* switch non-PACKING -> PACKING */
+			QETH_DBF_TEXT(trace, 6, "np->pack");
+			if (queue->card->options.performance_stats)
+				queue->card->perf_stats.sc_dp_p++;
+			queue->do_pack = 1;
+		}
+	}
+}
+
+/*
+ * Switches from packing to non-packing mode. If there is a packing
+ * buffer on the queue this buffer will be prepared to be flushed.
+ * In that case 1 is returned to inform the caller. If no buffer
+ * has to be flushed, zero is returned.
+ */
+static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
+{
+	struct qeth_qdio_out_buffer *buffer;
+	int flush_count = 0;
+
+	if (queue->do_pack) {
+		if (atomic_read(&queue->used_buffers)
+		    <= QETH_LOW_WATERMARK_PACK) {
+			/* switch PACKING -> non-PACKING */
+			QETH_DBF_TEXT(trace, 6, "pack->np");
+			if (queue->card->options.performance_stats)
+				queue->card->perf_stats.sc_p_dp++;
+			queue->do_pack = 0;
+			/* flush packing buffers */
+			buffer = &queue->bufs[queue->next_buf_to_fill];
+			if ((atomic_read(&buffer->state) ==
+						QETH_QDIO_BUF_EMPTY) &&
+			    (buffer->next_element_to_fill > 0)) {
+				atomic_set(&buffer->state,
+						QETH_QDIO_BUF_PRIMED);
+				flush_count++;
+				queue->next_buf_to_fill =
+					(queue->next_buf_to_fill + 1) %
+					QDIO_MAX_BUFFERS_PER_Q;
+			}
+		}
+	}
+	return flush_count;
+}
+
+/*
+ * Called to flush a packing buffer if no more pci flags are on the queue.
+ * Checks if there is a packing buffer and prepares it to be flushed.
+ * In that case returns 1, otherwise zero.
+ */
+static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
+{
+	struct qeth_qdio_out_buffer *buffer;
+
+	buffer = &queue->bufs[queue->next_buf_to_fill];
+	if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
+	   (buffer->next_element_to_fill > 0)) {
+		/* it's a packing buffer */
+		atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
+		queue->next_buf_to_fill =
+			(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
+		return 1;
+	}
+	return 0;
+}
+
+static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
+		int index, int count)
+{
+	struct qeth_qdio_out_buffer *buf;
+	int rc;
+	int i;
+	unsigned int qdio_flags;
+
+	QETH_DBF_TEXT(trace, 6, "flushbuf");
+
+	for (i = index; i < index + count; ++i) {
+		buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+		buf->buffer->element[buf->next_element_to_fill - 1].flags |=
+				SBAL_FLAGS_LAST_ENTRY;
+
+		if (queue->card->info.type == QETH_CARD_TYPE_IQD)
+			continue;
+
+		if (!queue->do_pack) {
+			if ((atomic_read(&queue->used_buffers) >=
+				(QETH_HIGH_WATERMARK_PACK -
+				 QETH_WATERMARK_PACK_FUZZ)) &&
+			    !atomic_read(&queue->set_pci_flags_count)) {
+				/* it's likely that we'll go to packing
+				 * mode soon */
+				atomic_inc(&queue->set_pci_flags_count);
+				buf->buffer->element[0].flags |= 0x40;
+			}
+		} else {
+			if (!atomic_read(&queue->set_pci_flags_count)) {
+				/*
+				 * there's no outstanding PCI any more, so we
+				 * have to request a PCI to be sure the the PCI
+				 * will wake at some time in the future then we
+				 * can flush packed buffers that might still be
+				 * hanging around, which can happen if no
+				 * further send was requested by the stack
+				 */
+				atomic_inc(&queue->set_pci_flags_count);
+				buf->buffer->element[0].flags |= 0x40;
+			}
+		}
+	}
+
+	queue->card->dev->trans_start = jiffies;
+	if (queue->card->options.performance_stats) {
+		queue->card->perf_stats.outbound_do_qdio_cnt++;
+		queue->card->perf_stats.outbound_do_qdio_start_time =
+			qeth_get_micros();
+	}
+	qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
+	if (under_int)
+		qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
+	if (atomic_read(&queue->set_pci_flags_count))
+		qdio_flags |= QDIO_FLAG_PCI_OUT;
+	rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
+		     queue->queue_no, index, count, NULL);
+	if (queue->card->options.performance_stats)
+		queue->card->perf_stats.outbound_do_qdio_time +=
+			qeth_get_micros() -
+			queue->card->perf_stats.outbound_do_qdio_start_time;
+	if (rc) {
+		QETH_DBF_TEXT(trace, 2, "flushbuf");
+		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+		QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
+		queue->card->stats.tx_errors += count;
+		/* this must not happen under normal circumstances. if it
+		 * happens something is really wrong -> recover */
+		qeth_schedule_recovery(queue->card);
+		return;
+	}
+	atomic_add(count, &queue->used_buffers);
+	if (queue->card->options.performance_stats)
+		queue->card->perf_stats.bufs_sent += count;
+}
+
+static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
+{
+	int index;
+	int flush_cnt = 0;
+	int q_was_packing = 0;
+
+	/*
+	 * check if weed have to switch to non-packing mode or if
+	 * we have to get a pci flag out on the queue
+	 */
+	if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) ||
+	    !atomic_read(&queue->set_pci_flags_count)) {
+		if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) ==
+				QETH_OUT_Q_UNLOCKED) {
+			/*
+			 * If we get in here, there was no action in
+			 * do_send_packet. So, we check if there is a
+			 * packing buffer to be flushed here.
+			 */
+			netif_stop_queue(queue->card->dev);
+			index = queue->next_buf_to_fill;
+			q_was_packing = queue->do_pack;
+			/* queue->do_pack may change */
+			barrier();
+			flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
+			if (!flush_cnt &&
+			    !atomic_read(&queue->set_pci_flags_count))
+				flush_cnt +=
+					qeth_flush_buffers_on_no_pci(queue);
+			if (queue->card->options.performance_stats &&
+			    q_was_packing)
+				queue->card->perf_stats.bufs_sent_pack +=
+					flush_cnt;
+			if (flush_cnt)
+				qeth_flush_buffers(queue, 1, index, flush_cnt);
+			atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+		}
+	}
+}
+
+void qeth_qdio_output_handler(struct ccw_device *ccwdev, unsigned int status,
+		unsigned int qdio_error, unsigned int siga_error,
+		unsigned int __queue, int first_element, int count,
+		unsigned long card_ptr)
+{
+	struct qeth_card *card        = (struct qeth_card *) card_ptr;
+	struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
+	struct qeth_qdio_out_buffer *buffer;
+	int i;
+
+	QETH_DBF_TEXT(trace, 6, "qdouhdl");
+	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
+			QETH_DBF_TEXT(trace, 2, "achkcond");
+			QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
+			QETH_DBF_TEXT_(trace, 2, "%08x", status);
+			netif_stop_queue(card->dev);
+			qeth_schedule_recovery(card);
+			return;
+		}
+	}
+	if (card->options.performance_stats) {
+		card->perf_stats.outbound_handler_cnt++;
+		card->perf_stats.outbound_handler_start_time =
+			qeth_get_micros();
+	}
+	for (i = first_element; i < (first_element + count); ++i) {
+		buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+		/*we only handle the KICK_IT error by doing a recovery */
+		if (qeth_handle_send_error(card, buffer,
+					   qdio_error, siga_error)
+				== QETH_SEND_ERROR_KICK_IT){
+			netif_stop_queue(card->dev);
+			qeth_schedule_recovery(card);
+			return;
+		}
+		qeth_clear_output_buffer(queue, buffer);
+	}
+	atomic_sub(count, &queue->used_buffers);
+	/* check if we need to do something on this outbound queue */
+	if (card->info.type != QETH_CARD_TYPE_IQD)
+		qeth_check_outbound_queue(queue);
+
+	netif_wake_queue(queue->card->dev);
+	if (card->options.performance_stats)
+		card->perf_stats.outbound_handler_time += qeth_get_micros() -
+			card->perf_stats.outbound_handler_start_time;
+}
+EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
+
+int qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
+{
+	int cast_type = RTN_UNSPEC;
+
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return cast_type;
+
+	if (skb->dst && skb->dst->neighbour) {
+		cast_type = skb->dst->neighbour->type;
+		if ((cast_type == RTN_BROADCAST) ||
+		    (cast_type == RTN_MULTICAST) ||
+		    (cast_type == RTN_ANYCAST))
+			return cast_type;
+		else
+			return RTN_UNSPEC;
+	}
+	/* try something else */
+	if (skb->protocol == ETH_P_IPV6)
+		return (skb_network_header(skb)[24] == 0xff) ?
+				RTN_MULTICAST : 0;
+	else if (skb->protocol == ETH_P_IP)
+		return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
+				RTN_MULTICAST : 0;
+	/* ... */
+	if (!memcmp(skb->data, skb->dev->broadcast, 6))
+		return RTN_BROADCAST;
+	else {
+		u16 hdr_mac;
+
+		hdr_mac = *((u16 *)skb->data);
+		/* tr multicast? */
+		switch (card->info.link_type) {
+		case QETH_LINK_TYPE_HSTR:
+		case QETH_LINK_TYPE_LANE_TR:
+			if ((hdr_mac == QETH_TR_MAC_NC) ||
+			    (hdr_mac == QETH_TR_MAC_C))
+				return RTN_MULTICAST;
+			break;
+		/* eth or so multicast? */
+		default:
+		if ((hdr_mac == QETH_ETH_MAC_V4) ||
+			    (hdr_mac == QETH_ETH_MAC_V6))
+				return RTN_MULTICAST;
+		}
+	}
+	return cast_type;
+}
+EXPORT_SYMBOL_GPL(qeth_get_cast_type);
+
+int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
+			int ipv, int cast_type)
+{
+	if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
+		return card->qdio.default_out_queue;
+	switch (card->qdio.no_out_queues) {
+	case 4:
+		if (cast_type && card->info.is_multicast_different)
+			return card->info.is_multicast_different &
+				(card->qdio.no_out_queues - 1);
+		if (card->qdio.do_prio_queueing && (ipv == 4)) {
+			const u8 tos = ip_hdr(skb)->tos;
+
+			if (card->qdio.do_prio_queueing ==
+				QETH_PRIO_Q_ING_TOS) {
+				if (tos & IP_TOS_NOTIMPORTANT)
+					return 3;
+				if (tos & IP_TOS_HIGHRELIABILITY)
+					return 2;
+				if (tos & IP_TOS_HIGHTHROUGHPUT)
+					return 1;
+				if (tos & IP_TOS_LOWDELAY)
+					return 0;
+			}
+			if (card->qdio.do_prio_queueing ==
+				QETH_PRIO_Q_ING_PREC)
+				return 3 - (tos >> 6);
+		} else if (card->qdio.do_prio_queueing && (ipv == 6)) {
+			/* TODO: IPv6!!! */
+		}
+		return card->qdio.default_out_queue;
+	case 1: /* fallthrough for single-out-queue 1920-device */
+	default:
+		return card->qdio.default_out_queue;
+	}
+}
+EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
+
+static void __qeth_free_new_skb(struct sk_buff *orig_skb,
+		struct sk_buff *new_skb)
+{
+	if (orig_skb != new_skb)
+		dev_kfree_skb_any(new_skb);
+}
+
+static inline struct sk_buff *qeth_realloc_headroom(struct qeth_card *card,
+		struct sk_buff *skb, int size)
+{
+	struct sk_buff *new_skb = skb;
+
+	if (skb_headroom(skb) >= size)
+		return skb;
+	new_skb = skb_realloc_headroom(skb, size);
+	if (!new_skb)
+		PRINT_ERR("Could not realloc headroom for qeth_hdr "
+			  "on interface %s", QETH_CARD_IFNAME(card));
+	return new_skb;
+}
+
+struct sk_buff *qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
+		 struct qeth_hdr **hdr)
+{
+	struct sk_buff *new_skb;
+
+	QETH_DBF_TEXT(trace, 6, "prepskb");
+
+	new_skb = qeth_realloc_headroom(card, skb,
+			sizeof(struct qeth_hdr));
+	if (!new_skb)
+		return NULL;
+
+	*hdr = ((struct qeth_hdr *)qeth_push_skb(card, new_skb,
+			sizeof(struct qeth_hdr)));
+	if (*hdr == NULL) {
+		__qeth_free_new_skb(skb, new_skb);
+		return NULL;
+	}
+	return new_skb;
+}
+EXPORT_SYMBOL_GPL(qeth_prepare_skb);
+
+int qeth_get_elements_no(struct qeth_card *card, void *hdr,
+		     struct sk_buff *skb, int elems)
+{
+	int elements_needed = 0;
+
+	if (skb_shinfo(skb)->nr_frags > 0)
+		elements_needed = (skb_shinfo(skb)->nr_frags + 1);
+	if (elements_needed == 0)
+		elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+			+ skb->len) >> PAGE_SHIFT);
+	if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
+		PRINT_ERR("Invalid size of IP packet "
+			"(Number=%d / Length=%d). Discarded.\n",
+			(elements_needed+elems), skb->len);
+		return 0;
+	}
+	return elements_needed;
+}
+EXPORT_SYMBOL_GPL(qeth_get_elements_no);
+
+static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
+		int is_tso, int *next_element_to_fill)
+{
+	int length = skb->len;
+	int length_here;
+	int element;
+	char *data;
+	int first_lap ;
+
+	element = *next_element_to_fill;
+	data = skb->data;
+	first_lap = (is_tso == 0 ? 1 : 0);
+
+	while (length > 0) {
+		/* length_here is the remaining amount of data in this page */
+		length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
+		if (length < length_here)
+			length_here = length;
+
+		buffer->element[element].addr = data;
+		buffer->element[element].length = length_here;
+		length -= length_here;
+		if (!length) {
+			if (first_lap)
+				buffer->element[element].flags = 0;
+			else
+				buffer->element[element].flags =
+				    SBAL_FLAGS_LAST_FRAG;
+		} else {
+			if (first_lap)
+				buffer->element[element].flags =
+				    SBAL_FLAGS_FIRST_FRAG;
+			else
+				buffer->element[element].flags =
+				    SBAL_FLAGS_MIDDLE_FRAG;
+		}
+		data += length_here;
+		element++;
+		first_lap = 0;
+	}
+	*next_element_to_fill = element;
+}
+
+static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
+		struct qeth_qdio_out_buffer *buf, struct sk_buff *skb)
+{
+	struct qdio_buffer *buffer;
+	struct qeth_hdr_tso *hdr;
+	int flush_cnt = 0, hdr_len, large_send = 0;
+
+	QETH_DBF_TEXT(trace, 6, "qdfillbf");
+
+	buffer = buf->buffer;
+	atomic_inc(&skb->users);
+	skb_queue_tail(&buf->skb_list, skb);
+
+	hdr  = (struct qeth_hdr_tso *) skb->data;
+	/*check first on TSO ....*/
+	if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
+		int element = buf->next_element_to_fill;
+
+		hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
+		/*fill first buffer entry only with header information */
+		buffer->element[element].addr = skb->data;
+		buffer->element[element].length = hdr_len;
+		buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+		buf->next_element_to_fill++;
+		skb->data += hdr_len;
+		skb->len  -= hdr_len;
+		large_send = 1;
+	}
+	if (skb_shinfo(skb)->nr_frags == 0)
+		__qeth_fill_buffer(skb, buffer, large_send,
+				   (int *)&buf->next_element_to_fill);
+	else
+		__qeth_fill_buffer_frag(skb, buffer, large_send,
+					(int *)&buf->next_element_to_fill);
+
+	if (!queue->do_pack) {
+		QETH_DBF_TEXT(trace, 6, "fillbfnp");
+		/* set state to PRIMED -> will be flushed */
+		atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+		flush_cnt = 1;
+	} else {
+		QETH_DBF_TEXT(trace, 6, "fillbfpa");
+		if (queue->card->options.performance_stats)
+			queue->card->perf_stats.skbs_sent_pack++;
+		if (buf->next_element_to_fill >=
+				QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
+			/*
+			 * packed buffer if full -> set state PRIMED
+			 * -> will be flushed
+			 */
+			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+			flush_cnt = 1;
+		}
+	}
+	return flush_cnt;
+}
+
+int qeth_do_send_packet_fast(struct qeth_card *card,
+		struct qeth_qdio_out_q *queue, struct sk_buff *skb,
+		struct qeth_hdr *hdr, int elements_needed,
+		struct qeth_eddp_context *ctx)
+{
+	struct qeth_qdio_out_buffer *buffer;
+	int buffers_needed = 0;
+	int flush_cnt = 0;
+	int index;
+
+	QETH_DBF_TEXT(trace, 6, "dosndpfa");
+
+	/* spin until we get the queue ... */
+	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+	/* ... now we've got the queue */
+	index = queue->next_buf_to_fill;
+	buffer = &queue->bufs[queue->next_buf_to_fill];
+	/*
+	 * check if buffer is empty to make sure that we do not 'overtake'
+	 * ourselves and try to fill a buffer that is already primed
+	 */
+	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
+		goto out;
+	if (ctx == NULL)
+		queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+					  QDIO_MAX_BUFFERS_PER_Q;
+	else {
+		buffers_needed = qeth_eddp_check_buffers_for_context(queue,
+									ctx);
+		if (buffers_needed < 0)
+			goto out;
+		queue->next_buf_to_fill =
+			(queue->next_buf_to_fill + buffers_needed) %
+			QDIO_MAX_BUFFERS_PER_Q;
+	}
+	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+	if (ctx == NULL) {
+		qeth_fill_buffer(queue, buffer, skb);
+		qeth_flush_buffers(queue, 0, index, 1);
+	} else {
+		flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
+		WARN_ON(buffers_needed != flush_cnt);
+		qeth_flush_buffers(queue, 0, index, flush_cnt);
+	}
+	return 0;
+out:
+	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+	return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(qeth_do_send_packet_fast);
+
+int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
+		struct sk_buff *skb, struct qeth_hdr *hdr,
+		int elements_needed, struct qeth_eddp_context *ctx)
+{
+	struct qeth_qdio_out_buffer *buffer;
+	int start_index;
+	int flush_count = 0;
+	int do_pack = 0;
+	int tmp;
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 6, "dosndpkt");
+
+	/* spin until we get the queue ... */
+	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+	start_index = queue->next_buf_to_fill;
+	buffer = &queue->bufs[queue->next_buf_to_fill];
+	/*
+	 * check if buffer is empty to make sure that we do not 'overtake'
+	 * ourselves and try to fill a buffer that is already primed
+	 */
+	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
+		atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+		return -EBUSY;
+	}
+	/* check if we need to switch packing state of this queue */
+	qeth_switch_to_packing_if_needed(queue);
+	if (queue->do_pack) {
+		do_pack = 1;
+		if (ctx == NULL) {
+			/* does packet fit in current buffer? */
+			if ((QETH_MAX_BUFFER_ELEMENTS(card) -
+			    buffer->next_element_to_fill) < elements_needed) {
+				/* ... no -> set state PRIMED */
+				atomic_set(&buffer->state,
+					QETH_QDIO_BUF_PRIMED);
+				flush_count++;
+				queue->next_buf_to_fill =
+					(queue->next_buf_to_fill + 1) %
+					QDIO_MAX_BUFFERS_PER_Q;
+				buffer = &queue->bufs[queue->next_buf_to_fill];
+				/* we did a step forward, so check buffer state
+				 * again */
+				if (atomic_read(&buffer->state) !=
+						QETH_QDIO_BUF_EMPTY){
+					qeth_flush_buffers(queue, 0,
+						start_index, flush_count);
+					atomic_set(&queue->state,
+						QETH_OUT_Q_UNLOCKED);
+					return -EBUSY;
+				}
+			}
+		} else {
+			/* check if we have enough elements (including following
+			 * free buffers) to handle eddp context */
+			if (qeth_eddp_check_buffers_for_context(queue, ctx)
+				< 0) {
+				if (net_ratelimit())
+					PRINT_WARN("eddp tx_dropped 1\n");
+				rc = -EBUSY;
+				goto out;
+			}
+		}
+	}
+	if (ctx == NULL)
+		tmp = qeth_fill_buffer(queue, buffer, skb);
+	else {
+		tmp = qeth_eddp_fill_buffer(queue, ctx,
+						queue->next_buf_to_fill);
+		if (tmp < 0) {
+			PRINT_ERR("eddp tx_dropped 2\n");
+			rc = -EBUSY;
+			goto out;
+		}
+	}
+	queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
+				  QDIO_MAX_BUFFERS_PER_Q;
+	flush_count += tmp;
+out:
+	if (flush_count)
+		qeth_flush_buffers(queue, 0, start_index, flush_count);
+	else if (!atomic_read(&queue->set_pci_flags_count))
+		atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
+	/*
+	 * queue->state will go from LOCKED -> UNLOCKED or from
+	 * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
+	 * (switch packing state or flush buffer to get another pci flag out).
+	 * In that case we will enter this loop
+	 */
+	while (atomic_dec_return(&queue->state)) {
+		flush_count = 0;
+		start_index = queue->next_buf_to_fill;
+		/* check if we can go back to non-packing state */
+		flush_count += qeth_switch_to_nonpacking_if_needed(queue);
+		/*
+		 * check if we need to flush a packing buffer to get a pci
+		 * flag out on the queue
+		 */
+		if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
+			flush_count += qeth_flush_buffers_on_no_pci(queue);
+		if (flush_count)
+			qeth_flush_buffers(queue, 0, start_index, flush_count);
+	}
+	/* at this point the queue is UNLOCKED again */
+	if (queue->card->options.performance_stats && do_pack)
+		queue->card->perf_stats.bufs_sent_pack += flush_count;
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_do_send_packet);
+
+static int qeth_setadp_promisc_mode_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_ipacmd_setadpparms *setparms;
+
+	QETH_DBF_TEXT(trace, 4, "prmadpcb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	setparms = &(cmd->data.setadapterparms);
+
+	qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+	if (cmd->hdr.return_code) {
+		QETH_DBF_TEXT_(trace, 4, "prmrc%2.2x", cmd->hdr.return_code);
+		setparms->data.mode = SET_PROMISC_MODE_OFF;
+	}
+	card->info.promisc_mode = setparms->data.mode;
+	return 0;
+}
+
+void qeth_setadp_promisc_mode(struct qeth_card *card)
+{
+	enum qeth_ipa_promisc_modes mode;
+	struct net_device *dev = card->dev;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "setprom");
+
+	if (((dev->flags & IFF_PROMISC) &&
+	     (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
+	    (!(dev->flags & IFF_PROMISC) &&
+	     (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
+		return;
+	mode = SET_PROMISC_MODE_OFF;
+	if (dev->flags & IFF_PROMISC)
+		mode = SET_PROMISC_MODE_ON;
+	QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
+
+	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
+			sizeof(struct qeth_ipacmd_setadpparms));
+	cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+	cmd->data.setadapterparms.data.mode = mode;
+	qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
+}
+EXPORT_SYMBOL_GPL(qeth_setadp_promisc_mode);
+
+int qeth_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct qeth_card *card;
+	char dbf_text[15];
+
+	card = netdev_priv(dev);
+
+	QETH_DBF_TEXT(trace, 4, "chgmtu");
+	sprintf(dbf_text, "%8x", new_mtu);
+	QETH_DBF_TEXT(trace, 4, dbf_text);
+
+	if (new_mtu < 64)
+		return -EINVAL;
+	if (new_mtu > 65535)
+		return -EINVAL;
+	if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) &&
+	    (!qeth_mtu_is_valid(card, new_mtu)))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_change_mtu);
+
+struct net_device_stats *qeth_get_stats(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = netdev_priv(dev);
+
+	QETH_DBF_TEXT(trace, 5, "getstat");
+
+	return &card->stats;
+}
+EXPORT_SYMBOL_GPL(qeth_get_stats);
+
+static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "chgmaccb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (!card->options.layer2 ||
+	    !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
+		memcpy(card->dev->dev_addr,
+		       &cmd->data.setadapterparms.data.change_addr.addr,
+		       OSA_ADDR_LEN);
+		card->info.mac_bits |= QETH_LAYER2_MAC_READ;
+	}
+	qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
+	return 0;
+}
+
+int qeth_setadpparms_change_macaddr(struct qeth_card *card)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "chgmac");
+
+	iob = qeth_get_adapter_cmd(card, IPA_SETADP_ALTER_MAC_ADDRESS,
+				   sizeof(struct qeth_ipacmd_setadpparms));
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
+	cmd->data.setadapterparms.data.change_addr.addr_size = OSA_ADDR_LEN;
+	memcpy(&cmd->data.setadapterparms.data.change_addr.addr,
+	       card->dev->dev_addr, OSA_ADDR_LEN);
+	rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_change_macaddr_cb,
+			       NULL);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr);
+
+void qeth_tx_timeout(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = netdev_priv(dev);
+	card->stats.tx_errors++;
+	qeth_schedule_recovery(card);
+}
+EXPORT_SYMBOL_GPL(qeth_tx_timeout);
+
+int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	int rc = 0;
+
+	switch (regnum) {
+	case MII_BMCR: /* Basic mode control register */
+		rc = BMCR_FULLDPLX;
+		if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH) &&
+		    (card->info.link_type != QETH_LINK_TYPE_OSN) &&
+		    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
+			rc |= BMCR_SPEED100;
+		break;
+	case MII_BMSR: /* Basic mode status register */
+		rc = BMSR_ERCAP | BMSR_ANEGCOMPLETE | BMSR_LSTATUS |
+		     BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL |
+		     BMSR_100BASE4;
+		break;
+	case MII_PHYSID1: /* PHYS ID 1 */
+		rc = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 8) |
+		     dev->dev_addr[2];
+		rc = (rc >> 5) & 0xFFFF;
+		break;
+	case MII_PHYSID2: /* PHYS ID 2 */
+		rc = (dev->dev_addr[2] << 10) & 0xFFFF;
+		break;
+	case MII_ADVERTISE: /* Advertisement control reg */
+		rc = ADVERTISE_ALL;
+		break;
+	case MII_LPA: /* Link partner ability reg */
+		rc = LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL |
+		     LPA_100BASE4 | LPA_LPACK;
+		break;
+	case MII_EXPANSION: /* Expansion register */
+		break;
+	case MII_DCOUNTER: /* disconnect counter */
+		break;
+	case MII_FCSCOUNTER: /* false carrier counter */
+		break;
+	case MII_NWAYTEST: /* N-way auto-neg test register */
+		break;
+	case MII_RERRCOUNTER: /* rx error counter */
+		rc = card->stats.rx_errors;
+		break;
+	case MII_SREVISION: /* silicon revision */
+		break;
+	case MII_RESV1: /* reserved 1 */
+		break;
+	case MII_LBRERROR: /* loopback, rx, bypass error */
+		break;
+	case MII_PHYADDR: /* physical address */
+		break;
+	case MII_RESV2: /* reserved 2 */
+		break;
+	case MII_TPISTATUS: /* TPI status for 10mbps */
+		break;
+	case MII_NCONFIG: /* network interface config */
+		break;
+	default:
+		break;
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_mdio_read);
+
+static int qeth_send_ipa_snmp_cmd(struct qeth_card *card,
+		struct qeth_cmd_buffer *iob, int len,
+		int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
+			unsigned long),
+		void *reply_param)
+{
+	u16 s1, s2;
+
+	QETH_DBF_TEXT(trace, 4, "sendsnmp");
+
+	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+	/* adjust PDU length fields in IPA_PDU_HEADER */
+	s1 = (u32) IPA_PDU_HEADER_SIZE + len;
+	s2 = (u32) len;
+	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+				      reply_cb, reply_param);
+}
+
+static int qeth_snmp_command_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long sdata)
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_arp_query_info *qinfo;
+	struct qeth_snmp_cmd *snmp;
+	unsigned char *data;
+	__u16 data_len;
+
+	QETH_DBF_TEXT(trace, 3, "snpcmdcb");
+
+	cmd = (struct qeth_ipa_cmd *) sdata;
+	data = (unsigned char *)((char *)cmd - reply->offset);
+	qinfo = (struct qeth_arp_query_info *) reply->param;
+	snmp = &cmd->data.setadapterparms.data.snmp;
+
+	if (cmd->hdr.return_code) {
+		QETH_DBF_TEXT_(trace, 4, "scer1%i", cmd->hdr.return_code);
+		return 0;
+	}
+	if (cmd->data.setadapterparms.hdr.return_code) {
+		cmd->hdr.return_code =
+			cmd->data.setadapterparms.hdr.return_code;
+		QETH_DBF_TEXT_(trace, 4, "scer2%i", cmd->hdr.return_code);
+		return 0;
+	}
+	data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
+	if (cmd->data.setadapterparms.hdr.seq_no == 1)
+		data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
+	else
+		data_len -= (__u16)((char *)&snmp->request - (char *)cmd);
+
+	/* check if there is enough room in userspace */
+	if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
+		QETH_DBF_TEXT_(trace, 4, "scer3%i", -ENOMEM);
+		cmd->hdr.return_code = -ENOMEM;
+		return 0;
+	}
+	QETH_DBF_TEXT_(trace, 4, "snore%i",
+		       cmd->data.setadapterparms.hdr.used_total);
+	QETH_DBF_TEXT_(trace, 4, "sseqn%i",
+		cmd->data.setadapterparms.hdr.seq_no);
+	/*copy entries to user buffer*/
+	if (cmd->data.setadapterparms.hdr.seq_no == 1) {
+		memcpy(qinfo->udata + qinfo->udata_offset,
+		       (char *)snmp,
+		       data_len + offsetof(struct qeth_snmp_cmd, data));
+		qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
+	} else {
+		memcpy(qinfo->udata + qinfo->udata_offset,
+		       (char *)&snmp->request, data_len);
+	}
+	qinfo->udata_offset += data_len;
+	/* check if all replies received ... */
+		QETH_DBF_TEXT_(trace, 4, "srtot%i",
+			       cmd->data.setadapterparms.hdr.used_total);
+		QETH_DBF_TEXT_(trace, 4, "srseq%i",
+			       cmd->data.setadapterparms.hdr.seq_no);
+	if (cmd->data.setadapterparms.hdr.seq_no <
+	    cmd->data.setadapterparms.hdr.used_total)
+		return 1;
+	return 0;
+}
+
+int qeth_snmp_command(struct qeth_card *card, char __user *udata)
+{
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_snmp_ureq *ureq;
+	int req_len;
+	struct qeth_arp_query_info qinfo = {0, };
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "snmpcmd");
+
+	if (card->info.guestlan)
+		return -EOPNOTSUPP;
+
+	if ((!qeth_adp_supported(card, IPA_SETADP_SET_SNMP_CONTROL)) &&
+	    (!card->options.layer2)) {
+		PRINT_WARN("SNMP Query MIBS not supported "
+			   "on %s!\n", QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+	/* skip 4 bytes (data_len struct member) to get req_len */
+	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
+		return -EFAULT;
+	ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
+	if (!ureq) {
+		QETH_DBF_TEXT(trace, 2, "snmpnome");
+		return -ENOMEM;
+	}
+	if (copy_from_user(ureq, udata,
+			req_len + sizeof(struct qeth_snmp_ureq_hdr))) {
+		kfree(ureq);
+		return -EFAULT;
+	}
+	qinfo.udata_len = ureq->hdr.data_len;
+	qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
+	if (!qinfo.udata) {
+		kfree(ureq);
+		return -ENOMEM;
+	}
+	qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
+
+	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
+				   QETH_SNMP_SETADP_CMDLENGTH + req_len);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
+	rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
+				    qeth_snmp_command_cb, (void *)&qinfo);
+	if (rc)
+		PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
+			   QETH_CARD_IFNAME(card), rc);
+	else {
+		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+			rc = -EFAULT;
+	}
+
+	kfree(ureq);
+	kfree(qinfo.udata);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_snmp_command);
+
+static inline int qeth_get_qdio_q_format(struct qeth_card *card)
+{
+	switch (card->info.type) {
+	case QETH_CARD_TYPE_IQD:
+		return 2;
+	default:
+		return 0;
+	}
+}
+
+static int qeth_qdio_establish(struct qeth_card *card)
+{
+	struct qdio_initialize init_data;
+	char *qib_param_field;
+	struct qdio_buffer **in_sbal_ptrs;
+	struct qdio_buffer **out_sbal_ptrs;
+	int i, j, k;
+	int rc = 0;
+
+	QETH_DBF_TEXT(setup, 2, "qdioest");
+
+	qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
+			      GFP_KERNEL);
+	if (!qib_param_field)
+		return -ENOMEM;
+
+	qeth_create_qib_param_field(card, qib_param_field);
+	qeth_create_qib_param_field_blkt(card, qib_param_field);
+
+	in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+			       GFP_KERNEL);
+	if (!in_sbal_ptrs) {
+		kfree(qib_param_field);
+		return -ENOMEM;
+	}
+	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+		in_sbal_ptrs[i] = (struct qdio_buffer *)
+			virt_to_phys(card->qdio.in_q->bufs[i].buffer);
+
+	out_sbal_ptrs =
+		kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
+			sizeof(void *), GFP_KERNEL);
+	if (!out_sbal_ptrs) {
+		kfree(in_sbal_ptrs);
+		kfree(qib_param_field);
+		return -ENOMEM;
+	}
+	for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
+		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
+			out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
+				card->qdio.out_qs[i]->bufs[j].buffer);
+		}
+
+	memset(&init_data, 0, sizeof(struct qdio_initialize));
+	init_data.cdev                   = CARD_DDEV(card);
+	init_data.q_format               = qeth_get_qdio_q_format(card);
+	init_data.qib_param_field_format = 0;
+	init_data.qib_param_field        = qib_param_field;
+	init_data.min_input_threshold    = QETH_MIN_INPUT_THRESHOLD;
+	init_data.max_input_threshold    = QETH_MAX_INPUT_THRESHOLD;
+	init_data.min_output_threshold   = QETH_MIN_OUTPUT_THRESHOLD;
+	init_data.max_output_threshold   = QETH_MAX_OUTPUT_THRESHOLD;
+	init_data.no_input_qs            = 1;
+	init_data.no_output_qs           = card->qdio.no_out_queues;
+	init_data.input_handler          = card->discipline.input_handler;
+	init_data.output_handler         = card->discipline.output_handler;
+	init_data.int_parm               = (unsigned long) card;
+	init_data.flags                  = QDIO_INBOUND_0COPY_SBALS |
+					   QDIO_OUTBOUND_0COPY_SBALS |
+					   QDIO_USE_OUTBOUND_PCIS;
+	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
+	init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+
+	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
+		QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
+		rc = qdio_initialize(&init_data);
+		if (rc)
+			atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+	}
+	kfree(out_sbal_ptrs);
+	kfree(in_sbal_ptrs);
+	kfree(qib_param_field);
+	return rc;
+}
+
+static void qeth_core_free_card(struct qeth_card *card)
+{
+
+	QETH_DBF_TEXT(setup, 2, "freecrd");
+	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+	qeth_clean_channel(&card->read);
+	qeth_clean_channel(&card->write);
+	if (card->dev)
+		free_netdev(card->dev);
+	kfree(card->ip_tbd_list);
+	qeth_free_qdio_buffers(card);
+	kfree(card);
+}
+
+static struct ccw_device_id qeth_ids[] = {
+	{CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
+	{CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
+	{CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
+	{},
+};
+MODULE_DEVICE_TABLE(ccw, qeth_ids);
+
+static struct ccw_driver qeth_ccw_driver = {
+	.name = "qeth",
+	.ids = qeth_ids,
+	.probe = ccwgroup_probe_ccwdev,
+	.remove = ccwgroup_remove_ccwdev,
+};
+
+static int qeth_core_driver_group(const char *buf, struct device *root_dev,
+				unsigned long driver_id)
+{
+	const char *start, *end;
+	char bus_ids[3][BUS_ID_SIZE], *argv[3];
+	int i;
+
+	start = buf;
+	for (i = 0; i < 3; i++) {
+		static const char delim[] = { ',', ',', '\n' };
+		int len;
+
+		end = strchr(start, delim[i]);
+		if (!end)
+			return -EINVAL;
+		len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
+		strncpy(bus_ids[i], start, len);
+		bus_ids[i][len] = '\0';
+		start = end + 1;
+		argv[i] = bus_ids[i];
+	}
+
+	return (ccwgroup_create(root_dev, driver_id,
+				&qeth_ccw_driver, 3, argv));
+}
+
+int qeth_core_hardsetup_card(struct qeth_card *card)
+{
+	int retries = 3;
+	int mpno;
+	int rc;
+
+	QETH_DBF_TEXT(setup, 2, "hrdsetup");
+	atomic_set(&card->force_alloc_skb, 0);
+retry:
+	if (retries < 3) {
+		PRINT_WARN("Retrying to do IDX activates.\n");
+		ccw_device_set_offline(CARD_DDEV(card));
+		ccw_device_set_offline(CARD_WDEV(card));
+		ccw_device_set_offline(CARD_RDEV(card));
+		ccw_device_set_online(CARD_RDEV(card));
+		ccw_device_set_online(CARD_WDEV(card));
+		ccw_device_set_online(CARD_DDEV(card));
+	}
+	rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
+	if (rc == -ERESTARTSYS) {
+		QETH_DBF_TEXT(setup, 2, "break1");
+		return rc;
+	} else if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		if (--retries < 0)
+			goto out;
+		else
+			goto retry;
+	}
+
+	rc = qeth_get_unitaddr(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		return rc;
+	}
+
+	mpno = QETH_MAX_PORTNO;
+	if (card->info.portno > mpno) {
+		PRINT_ERR("Device %s does not offer port number %d \n.",
+			CARD_BUS_ID(card), card->info.portno);
+		rc = -ENODEV;
+		goto out;
+	}
+	qeth_init_tokens(card);
+	qeth_init_func_level(card);
+	rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
+	if (rc == -ERESTARTSYS) {
+		QETH_DBF_TEXT(setup, 2, "break2");
+		return rc;
+	} else if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+		if (--retries < 0)
+			goto out;
+		else
+			goto retry;
+	}
+	rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb);
+	if (rc == -ERESTARTSYS) {
+		QETH_DBF_TEXT(setup, 2, "break3");
+		return rc;
+	} else if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+		if (--retries < 0)
+			goto out;
+		else
+			goto retry;
+	}
+	rc = qeth_mpc_initialize(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+		goto out;
+	}
+	return 0;
+out:
+	PRINT_ERR("Initialization in hardsetup failed! rc=%d\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
+
+static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
+		struct sk_buff **pskb, int offset, int *pfrag, int data_len)
+{
+	struct page *page = virt_to_page(element->addr);
+	if (*pskb == NULL) {
+		/* the upper protocol layers assume that there is data in the
+		 * skb itself. Copy a small amount (64 bytes) to make them
+		 * happy. */
+		*pskb = dev_alloc_skb(64 + ETH_HLEN);
+		if (!(*pskb))
+			return -ENOMEM;
+		skb_reserve(*pskb, ETH_HLEN);
+		if (data_len <= 64) {
+			memcpy(skb_put(*pskb, data_len), element->addr + offset,
+				data_len);
+		} else {
+			get_page(page);
+			memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
+			skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
+				data_len - 64);
+			(*pskb)->data_len += data_len - 64;
+			(*pskb)->len      += data_len - 64;
+			(*pskb)->truesize += data_len - 64;
+			(*pfrag)++;
+		}
+	} else {
+		get_page(page);
+		skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
+		(*pskb)->data_len += data_len;
+		(*pskb)->len      += data_len;
+		(*pskb)->truesize += data_len;
+		(*pfrag)++;
+	}
+	return 0;
+}
+
+struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
+		struct qdio_buffer *buffer,
+		struct qdio_buffer_element **__element, int *__offset,
+		struct qeth_hdr **hdr)
+{
+	struct qdio_buffer_element *element = *__element;
+	int offset = *__offset;
+	struct sk_buff *skb = NULL;
+	int skb_len;
+	void *data_ptr;
+	int data_len;
+	int headroom = 0;
+	int use_rx_sg = 0;
+	int frag = 0;
+
+	QETH_DBF_TEXT(trace, 6, "nextskb");
+	/* qeth_hdr must not cross element boundaries */
+	if (element->length < offset + sizeof(struct qeth_hdr)) {
+		if (qeth_is_last_sbale(element))
+			return NULL;
+		element++;
+		offset = 0;
+		if (element->length < sizeof(struct qeth_hdr))
+			return NULL;
+	}
+	*hdr = element->addr + offset;
+
+	offset += sizeof(struct qeth_hdr);
+	if (card->options.layer2) {
+		if (card->info.type == QETH_CARD_TYPE_OSN) {
+			skb_len = (*hdr)->hdr.osn.pdu_length;
+			headroom = sizeof(struct qeth_hdr);
+		} else {
+			skb_len = (*hdr)->hdr.l2.pkt_length;
+		}
+	} else {
+		skb_len = (*hdr)->hdr.l3.length;
+		headroom = max((int)ETH_HLEN, (int)TR_HLEN);
+	}
+
+	if (!skb_len)
+		return NULL;
+
+	if ((skb_len >= card->options.rx_sg_cb) &&
+	    (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+	    (!atomic_read(&card->force_alloc_skb))) {
+		use_rx_sg = 1;
+	} else {
+		skb = dev_alloc_skb(skb_len + headroom);
+		if (!skb)
+			goto no_mem;
+		if (headroom)
+			skb_reserve(skb, headroom);
+	}
+
+	data_ptr = element->addr + offset;
+	while (skb_len) {
+		data_len = min(skb_len, (int)(element->length - offset));
+		if (data_len) {
+			if (use_rx_sg) {
+				if (qeth_create_skb_frag(element, &skb, offset,
+				    &frag, data_len))
+					goto no_mem;
+			} else {
+				memcpy(skb_put(skb, data_len), data_ptr,
+					data_len);
+			}
+		}
+		skb_len -= data_len;
+		if (skb_len) {
+			if (qeth_is_last_sbale(element)) {
+				QETH_DBF_TEXT(trace, 4, "unexeob");
+				QETH_DBF_TEXT_(trace, 4, "%s",
+					CARD_BUS_ID(card));
+				QETH_DBF_TEXT(qerr, 2, "unexeob");
+				QETH_DBF_TEXT_(qerr, 2, "%s",
+					CARD_BUS_ID(card));
+				QETH_DBF_HEX(misc, 4, buffer, sizeof(*buffer));
+				dev_kfree_skb_any(skb);
+				card->stats.rx_errors++;
+				return NULL;
+			}
+			element++;
+			offset = 0;
+			data_ptr = element->addr;
+		} else {
+			offset += data_len;
+		}
+	}
+	*__element = element;
+	*__offset = offset;
+	if (use_rx_sg && card->options.performance_stats) {
+		card->perf_stats.sg_skbs_rx++;
+		card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+	}
+	return skb;
+no_mem:
+	if (net_ratelimit()) {
+		PRINT_WARN("No memory for packet received on %s.\n",
+			   QETH_CARD_IFNAME(card));
+		QETH_DBF_TEXT(trace, 2, "noskbmem");
+		QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
+	}
+	card->stats.rx_dropped++;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(qeth_core_get_next_skb);
+
+static void qeth_unregister_dbf_views(void)
+{
+	if (qeth_dbf_setup)
+		debug_unregister(qeth_dbf_setup);
+	if (qeth_dbf_qerr)
+		debug_unregister(qeth_dbf_qerr);
+	if (qeth_dbf_sense)
+		debug_unregister(qeth_dbf_sense);
+	if (qeth_dbf_misc)
+		debug_unregister(qeth_dbf_misc);
+	if (qeth_dbf_data)
+		debug_unregister(qeth_dbf_data);
+	if (qeth_dbf_control)
+		debug_unregister(qeth_dbf_control);
+	if (qeth_dbf_trace)
+		debug_unregister(qeth_dbf_trace);
+}
+
+static int qeth_register_dbf_views(void)
+{
+	qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
+					QETH_DBF_SETUP_PAGES,
+					QETH_DBF_SETUP_NR_AREAS,
+					QETH_DBF_SETUP_LEN);
+	qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
+				       QETH_DBF_MISC_PAGES,
+				       QETH_DBF_MISC_NR_AREAS,
+				       QETH_DBF_MISC_LEN);
+	qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
+				       QETH_DBF_DATA_PAGES,
+				       QETH_DBF_DATA_NR_AREAS,
+				       QETH_DBF_DATA_LEN);
+	qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
+					  QETH_DBF_CONTROL_PAGES,
+					  QETH_DBF_CONTROL_NR_AREAS,
+					  QETH_DBF_CONTROL_LEN);
+	qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
+					QETH_DBF_SENSE_PAGES,
+					QETH_DBF_SENSE_NR_AREAS,
+					QETH_DBF_SENSE_LEN);
+	qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
+				       QETH_DBF_QERR_PAGES,
+				       QETH_DBF_QERR_NR_AREAS,
+				       QETH_DBF_QERR_LEN);
+	qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
+					QETH_DBF_TRACE_PAGES,
+					QETH_DBF_TRACE_NR_AREAS,
+					QETH_DBF_TRACE_LEN);
+
+	if ((qeth_dbf_setup == NULL) || (qeth_dbf_misc == NULL)    ||
+	    (qeth_dbf_data == NULL)  || (qeth_dbf_control == NULL) ||
+	    (qeth_dbf_sense == NULL) || (qeth_dbf_qerr == NULL)    ||
+	    (qeth_dbf_trace == NULL)) {
+		qeth_unregister_dbf_views();
+		return -ENOMEM;
+	}
+	debug_register_view(qeth_dbf_setup, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_setup, QETH_DBF_SETUP_LEVEL);
+
+	debug_register_view(qeth_dbf_misc, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_misc, QETH_DBF_MISC_LEVEL);
+
+	debug_register_view(qeth_dbf_data, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_data, QETH_DBF_DATA_LEVEL);
+
+	debug_register_view(qeth_dbf_control, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL);
+
+	debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL);
+
+	debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL);
+
+	debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL);
+
+	return 0;
+}
+
+int qeth_core_load_discipline(struct qeth_card *card,
+		enum qeth_discipline_id discipline)
+{
+	int rc = 0;
+	switch (discipline) {
+	case QETH_DISCIPLINE_LAYER3:
+		card->discipline.ccwgdriver = try_then_request_module(
+			symbol_get(qeth_l3_ccwgroup_driver),
+			"qeth_l3");
+		break;
+	case QETH_DISCIPLINE_LAYER2:
+		card->discipline.ccwgdriver = try_then_request_module(
+			symbol_get(qeth_l2_ccwgroup_driver),
+			"qeth_l2");
+		break;
+	}
+	if (!card->discipline.ccwgdriver) {
+		PRINT_ERR("Support for discipline %d not present\n",
+				discipline);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+void qeth_core_free_discipline(struct qeth_card *card)
+{
+	if (card->options.layer2)
+		symbol_put(qeth_l2_ccwgroup_driver);
+	else
+		symbol_put(qeth_l3_ccwgroup_driver);
+	card->discipline.ccwgdriver = NULL;
+}
+
+static int qeth_core_probe_device(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card;
+	struct device *dev;
+	int rc;
+	unsigned long flags;
+
+	QETH_DBF_TEXT(setup, 2, "probedev");
+
+	dev = &gdev->dev;
+	if (!get_device(dev))
+		return -ENODEV;
+
+	QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+
+	card = qeth_alloc_card();
+	if (!card) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);
+		rc = -ENOMEM;
+		goto err_dev;
+	}
+	card->read.ccwdev  = gdev->cdev[0];
+	card->write.ccwdev = gdev->cdev[1];
+	card->data.ccwdev  = gdev->cdev[2];
+	dev_set_drvdata(&gdev->dev, card);
+	card->gdev = gdev;
+	gdev->cdev[0]->handler = qeth_irq;
+	gdev->cdev[1]->handler = qeth_irq;
+	gdev->cdev[2]->handler = qeth_irq;
+
+	rc = qeth_determine_card_type(card);
+	if (rc) {
+		PRINT_WARN("%s: not a valid card type\n", __func__);
+		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+		goto err_card;
+	}
+	rc = qeth_setup_card(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		goto err_card;
+	}
+
+	if (card->info.type == QETH_CARD_TYPE_OSN) {
+		rc = qeth_core_create_osn_attributes(dev);
+		if (rc)
+			goto err_card;
+		rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
+		if (rc) {
+			qeth_core_remove_osn_attributes(dev);
+			goto err_card;
+		}
+		rc = card->discipline.ccwgdriver->probe(card->gdev);
+		if (rc) {
+			qeth_core_free_discipline(card);
+			qeth_core_remove_osn_attributes(dev);
+			goto err_card;
+		}
+	} else {
+		rc = qeth_core_create_device_attributes(dev);
+		if (rc)
+			goto err_card;
+	}
+
+	write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
+	list_add_tail(&card->list, &qeth_core_card_list.list);
+	write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
+	return 0;
+
+err_card:
+	qeth_core_free_card(card);
+err_dev:
+	put_device(dev);
+	return rc;
+}
+
+static void qeth_core_remove_device(struct ccwgroup_device *gdev)
+{
+	unsigned long flags;
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+
+	if (card->discipline.ccwgdriver) {
+		card->discipline.ccwgdriver->remove(gdev);
+		qeth_core_free_discipline(card);
+	}
+
+	if (card->info.type == QETH_CARD_TYPE_OSN) {
+		qeth_core_remove_osn_attributes(&gdev->dev);
+	} else {
+		qeth_core_remove_device_attributes(&gdev->dev);
+	}
+	write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
+	list_del(&card->list);
+	write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
+	qeth_core_free_card(card);
+	dev_set_drvdata(&gdev->dev, NULL);
+	put_device(&gdev->dev);
+	return;
+}
+
+static int qeth_core_set_online(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	int rc = 0;
+	int def_discipline;
+
+	if (!card->discipline.ccwgdriver) {
+		if (card->info.type == QETH_CARD_TYPE_IQD)
+			def_discipline = QETH_DISCIPLINE_LAYER3;
+		else
+			def_discipline = QETH_DISCIPLINE_LAYER2;
+		rc = qeth_core_load_discipline(card, def_discipline);
+		if (rc)
+			goto err;
+		rc = card->discipline.ccwgdriver->probe(card->gdev);
+		if (rc)
+			goto err;
+	}
+	rc = card->discipline.ccwgdriver->set_online(gdev);
+err:
+	return rc;
+}
+
+static int qeth_core_set_offline(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	return card->discipline.ccwgdriver->set_offline(gdev);
+}
+
+static void qeth_core_shutdown(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	if (card->discipline.ccwgdriver &&
+	    card->discipline.ccwgdriver->shutdown)
+		card->discipline.ccwgdriver->shutdown(gdev);
+}
+
+static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
+	.owner = THIS_MODULE,
+	.name = "qeth",
+	.driver_id = 0xD8C5E3C8,
+	.probe = qeth_core_probe_device,
+	.remove = qeth_core_remove_device,
+	.set_online = qeth_core_set_online,
+	.set_offline = qeth_core_set_offline,
+	.shutdown = qeth_core_shutdown,
+};
+
+static ssize_t
+qeth_core_driver_group_store(struct device_driver *ddrv, const char *buf,
+			   size_t count)
+{
+	int err;
+	err = qeth_core_driver_group(buf, qeth_core_root_dev,
+					qeth_core_ccwgroup_driver.driver_id);
+	if (err)
+		return err;
+	else
+		return count;
+}
+
+static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store);
+
+static struct {
+	const char str[ETH_GSTRING_LEN];
+} qeth_ethtool_stats_keys[] = {
+/*  0 */{"rx skbs"},
+	{"rx buffers"},
+	{"tx skbs"},
+	{"tx buffers"},
+	{"tx skbs no packing"},
+	{"tx buffers no packing"},
+	{"tx skbs packing"},
+	{"tx buffers packing"},
+	{"tx sg skbs"},
+	{"tx sg frags"},
+/* 10 */{"rx sg skbs"},
+	{"rx sg frags"},
+	{"rx sg page allocs"},
+	{"tx large kbytes"},
+	{"tx large count"},
+	{"tx pk state ch n->p"},
+	{"tx pk state ch p->n"},
+	{"tx pk watermark low"},
+	{"tx pk watermark high"},
+	{"queue 0 buffer usage"},
+/* 20 */{"queue 1 buffer usage"},
+	{"queue 2 buffer usage"},
+	{"queue 3 buffer usage"},
+	{"rx handler time"},
+	{"rx handler count"},
+	{"rx do_QDIO time"},
+	{"rx do_QDIO count"},
+	{"tx handler time"},
+	{"tx handler count"},
+	{"tx time"},
+/* 30 */{"tx count"},
+	{"tx do_QDIO time"},
+	{"tx do_QDIO count"},
+};
+
+int qeth_core_get_stats_count(struct net_device *dev)
+{
+	return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
+}
+EXPORT_SYMBOL_GPL(qeth_core_get_stats_count);
+
+void qeth_core_get_ethtool_stats(struct net_device *dev,
+		struct ethtool_stats *stats, u64 *data)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	data[0] = card->stats.rx_packets -
+				card->perf_stats.initial_rx_packets;
+	data[1] = card->perf_stats.bufs_rec;
+	data[2] = card->stats.tx_packets -
+				card->perf_stats.initial_tx_packets;
+	data[3] = card->perf_stats.bufs_sent;
+	data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets
+			- card->perf_stats.skbs_sent_pack;
+	data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack;
+	data[6] = card->perf_stats.skbs_sent_pack;
+	data[7] = card->perf_stats.bufs_sent_pack;
+	data[8] = card->perf_stats.sg_skbs_sent;
+	data[9] = card->perf_stats.sg_frags_sent;
+	data[10] = card->perf_stats.sg_skbs_rx;
+	data[11] = card->perf_stats.sg_frags_rx;
+	data[12] = card->perf_stats.sg_alloc_page_rx;
+	data[13] = (card->perf_stats.large_send_bytes >> 10);
+	data[14] = card->perf_stats.large_send_cnt;
+	data[15] = card->perf_stats.sc_dp_p;
+	data[16] = card->perf_stats.sc_p_dp;
+	data[17] = QETH_LOW_WATERMARK_PACK;
+	data[18] = QETH_HIGH_WATERMARK_PACK;
+	data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers);
+	data[20] = (card->qdio.no_out_queues > 1) ?
+			atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0;
+	data[21] = (card->qdio.no_out_queues > 2) ?
+			atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0;
+	data[22] = (card->qdio.no_out_queues > 3) ?
+			atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0;
+	data[23] = card->perf_stats.inbound_time;
+	data[24] = card->perf_stats.inbound_cnt;
+	data[25] = card->perf_stats.inbound_do_qdio_time;
+	data[26] = card->perf_stats.inbound_do_qdio_cnt;
+	data[27] = card->perf_stats.outbound_handler_time;
+	data[28] = card->perf_stats.outbound_handler_cnt;
+	data[29] = card->perf_stats.outbound_time;
+	data[30] = card->perf_stats.outbound_cnt;
+	data[31] = card->perf_stats.outbound_do_qdio_time;
+	data[32] = card->perf_stats.outbound_do_qdio_cnt;
+}
+EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
+
+void qeth_core_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, &qeth_ethtool_stats_keys,
+			sizeof(qeth_ethtool_stats_keys));
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(qeth_core_get_strings);
+
+void qeth_core_get_drvinfo(struct net_device *dev,
+		struct ethtool_drvinfo *info)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	if (card->options.layer2)
+		strcpy(info->driver, "qeth_l2");
+	else
+		strcpy(info->driver, "qeth_l3");
+
+	strcpy(info->version, "1.0");
+	strcpy(info->fw_version, card->info.mcl_level);
+	sprintf(info->bus_info, "%s/%s/%s",
+			CARD_RDEV_ID(card),
+			CARD_WDEV_ID(card),
+			CARD_DDEV_ID(card));
+}
+EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
+
+static int __init qeth_core_init(void)
+{
+	int rc;
+
+	PRINT_INFO("loading core functions\n");
+	INIT_LIST_HEAD(&qeth_core_card_list.list);
+	rwlock_init(&qeth_core_card_list.rwlock);
+
+	rc = qeth_register_dbf_views();
+	if (rc)
+		goto out_err;
+	rc = ccw_driver_register(&qeth_ccw_driver);
+	if (rc)
+		goto ccw_err;
+	rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver);
+	if (rc)
+		goto ccwgroup_err;
+	rc = driver_create_file(&qeth_core_ccwgroup_driver.driver,
+				&driver_attr_group);
+	if (rc)
+		goto driver_err;
+	qeth_core_root_dev = s390_root_dev_register("qeth");
+	rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
+	if (rc)
+		goto register_err;
+	return 0;
+
+register_err:
+	driver_remove_file(&qeth_core_ccwgroup_driver.driver,
+			   &driver_attr_group);
+driver_err:
+	ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
+ccwgroup_err:
+	ccw_driver_unregister(&qeth_ccw_driver);
+ccw_err:
+	qeth_unregister_dbf_views();
+out_err:
+	PRINT_ERR("Initialization failed with code %d\n", rc);
+	return rc;
+}
+
+static void __exit qeth_core_exit(void)
+{
+	s390_root_dev_unregister(qeth_core_root_dev);
+	driver_remove_file(&qeth_core_ccwgroup_driver.driver,
+			   &driver_attr_group);
+	ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
+	ccw_driver_unregister(&qeth_ccw_driver);
+	qeth_unregister_dbf_views();
+	PRINT_INFO("core functions removed\n");
+}
+
+module_init(qeth_core_init);
+module_exit(qeth_core_exit);
+MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
+MODULE_DESCRIPTION("qeth core functions");
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
new file mode 100644
index 0000000..8653b73
--- /dev/null
+++ b/drivers/s390/net/qeth_core_mpc.c
@@ -0,0 +1,266 @@
+/*
+ *  drivers/s390/net/qeth_core_mpc.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <asm/cio.h>
+#include "qeth_core_mpc.h"
+
+unsigned char IDX_ACTIVATE_READ[] = {
+	0x00, 0x00, 0x80, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x19, 0x01, 0x01, 0x80,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0xc8, 0xc1,
+	0xd3, 0xd3, 0xd6, 0xd3,  0xc5, 0x40, 0x00, 0x00,
+	0x00, 0x00
+};
+
+unsigned char IDX_ACTIVATE_WRITE[] = {
+	0x00, 0x00, 0x80, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x15, 0x01, 0x01, 0x80,  0x00, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0x00, 0x00,  0x00, 0x00, 0xc8, 0xc1,
+	0xd3, 0xd3, 0xd6, 0xd3,  0xc5, 0x40, 0x00, 0x00,
+	0x00, 0x00
+};
+
+unsigned char CM_ENABLE[] = {
+	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x63,
+	0x10, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00,
+	0x81, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x23,
+	0x00, 0x00, 0x23, 0x05,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x23,  0x00, 0x00, 0x00, 0x40,
+	0x00, 0x0c, 0x41, 0x02,  0x00, 0x17, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x0b, 0x04, 0x01,
+	0x7e, 0x04, 0x05, 0x00,  0x01, 0x01, 0x0f,
+	0x00,
+	0x0c, 0x04, 0x02, 0xff,  0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff
+};
+
+unsigned char CM_SETUP[] = {
+	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x64,
+	0x10, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00,
+	0x81, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x24,
+	0x00, 0x00, 0x24, 0x05,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x24,  0x00, 0x00, 0x00, 0x40,
+	0x00, 0x0c, 0x41, 0x04,  0x00, 0x18, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x09, 0x04, 0x04,
+	0x05, 0x00, 0x01, 0x01,  0x11,
+	0x00, 0x09, 0x04,
+	0x05, 0x05, 0x00, 0x00,  0x00, 0x00,
+	0x00, 0x06,
+	0x04, 0x06, 0xc8, 0x00
+};
+
+unsigned char ULP_ENABLE[] = {
+	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x03,
+	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x6b,
+	0x10, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00,
+	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x2b,
+	0x00, 0x00, 0x2b, 0x05,  0x20, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x2b,  0x00, 0x00, 0x00, 0x40,
+	0x00, 0x0c, 0x41, 0x02,  0x00, 0x1f, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x0b, 0x04, 0x01,
+	0x03, 0x04, 0x05, 0x00,  0x01, 0x01, 0x12,
+	0x00,
+	0x14, 0x04, 0x0a, 0x00,  0x20, 0x00, 0x00, 0xff,
+	0xff, 0x00, 0x08, 0xc8,  0xe8, 0xc4, 0xf1, 0xc7,
+	0xf1, 0x00, 0x00
+};
+
+unsigned char ULP_SETUP[] = {
+	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x04,
+	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x6c,
+	0x10, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00,
+	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x01,  0x00, 0x24, 0x00, 0x2c,
+	0x00, 0x00, 0x2c, 0x05,  0x20, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x2c,  0x00, 0x00, 0x00, 0x40,
+	0x00, 0x0c, 0x41, 0x04,  0x00, 0x20, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x09, 0x04, 0x04,
+	0x05, 0x00, 0x01, 0x01,  0x14,
+	0x00, 0x09, 0x04,
+	0x05, 0x05, 0x30, 0x01,  0x00, 0x00,
+	0x00, 0x06,
+	0x04, 0x06, 0x40, 0x00,
+	0x00, 0x08, 0x04, 0x0b,
+	0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char DM_ACT[] = {
+	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x05,
+	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x55,
+	0x10, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00,
+	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x03,
+	0x00, 0x00, 0x00, 0x02,  0x00, 0x24, 0x00, 0x15,
+	0x00, 0x00, 0x2c, 0x05,  0x20, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x15,  0x00, 0x00, 0x00, 0x40,
+	0x00, 0x0c, 0x43, 0x60,  0x00, 0x09, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x09, 0x04, 0x04,
+	0x05, 0x40, 0x01, 0x01,  0x00
+};
+
+unsigned char IPA_PDU_HEADER[] = {
+	0x00, 0xe0, 0x00, 0x00,  0x77, 0x77, 0x77, 0x77,
+	0x00, 0x00, 0x00, 0x14,  0x00, 0x00,
+		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) / 256,
+		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) % 256,
+	0x10, 0x00, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
+	0xc1, 0x03, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x24,
+		sizeof(struct qeth_ipa_cmd) / 256,
+		sizeof(struct qeth_ipa_cmd) % 256,
+	0x00,
+		sizeof(struct qeth_ipa_cmd) / 256,
+		sizeof(struct qeth_ipa_cmd) % 256,
+	0x05,
+	0x77, 0x77, 0x77, 0x77,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00,
+		sizeof(struct qeth_ipa_cmd) / 256,
+		sizeof(struct qeth_ipa_cmd) % 256,
+	0x00, 0x00, 0x00, 0x40,
+};
+EXPORT_SYMBOL_GPL(IPA_PDU_HEADER);
+
+unsigned char WRITE_CCW[] = {
+	0x01, CCW_FLAG_SLI, 0, 0,
+	0, 0, 0, 0
+};
+
+unsigned char READ_CCW[] = {
+	0x02, CCW_FLAG_SLI, 0, 0,
+	0, 0, 0, 0
+};
+
+
+struct ipa_rc_msg {
+	enum qeth_ipa_return_codes rc;
+	char *msg;
+};
+
+static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
+	{IPA_RC_SUCCESS,		"success"},
+	{IPA_RC_NOTSUPP,		"Command not supported"},
+	{IPA_RC_IP_TABLE_FULL,		"Add Addr IP Table Full - ipv6"},
+	{IPA_RC_UNKNOWN_ERROR,		"IPA command failed - reason unknown"},
+	{IPA_RC_UNSUPPORTED_COMMAND,	"Command not supported"},
+	{IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"},
+	{IPA_RC_DUP_IPV6_HOME,		"ipv6 address already registered"},
+	{IPA_RC_UNREGISTERED_ADDR,	"Address not registered"},
+	{IPA_RC_NO_ID_AVAILABLE,	"No identifiers available"},
+	{IPA_RC_ID_NOT_FOUND,		"Identifier not found"},
+	{IPA_RC_INVALID_IP_VERSION,	"IP version incorrect"},
+	{IPA_RC_LAN_FRAME_MISMATCH,	"LAN and frame mismatch"},
+	{IPA_RC_L2_UNSUPPORTED_CMD,	"Unsupported layer 2 command"},
+	{IPA_RC_L2_DUP_MAC,		"Duplicate MAC address"},
+	{IPA_RC_L2_ADDR_TABLE_FULL,	"Layer2 address table full"},
+	{IPA_RC_L2_DUP_LAYER3_MAC,	"Duplicate with layer 3 MAC"},
+	{IPA_RC_L2_GMAC_NOT_FOUND,	"GMAC not found"},
+	{IPA_RC_L2_MAC_NOT_FOUND,	"L2 mac address not found"},
+	{IPA_RC_L2_INVALID_VLAN_ID,	"L2 invalid vlan id"},
+	{IPA_RC_L2_DUP_VLAN_ID,		"L2 duplicate vlan id"},
+	{IPA_RC_L2_VLAN_ID_NOT_FOUND,	"L2 vlan id not found"},
+	{IPA_RC_DATA_MISMATCH,		"Data field mismatch (v4/v6 mixed)"},
+	{IPA_RC_INVALID_MTU_SIZE,	"Invalid MTU size"},
+	{IPA_RC_INVALID_LANTYPE,	"Invalid LAN type"},
+	{IPA_RC_INVALID_LANNUM,		"Invalid LAN num"},
+	{IPA_RC_DUPLICATE_IP_ADDRESS,	"Address already registered"},
+	{IPA_RC_IP_ADDR_TABLE_FULL,	"IP address table full"},
+	{IPA_RC_LAN_PORT_STATE_ERROR,	"LAN port state error"},
+	{IPA_RC_SETIP_NO_STARTLAN,	"Setip no startlan received"},
+	{IPA_RC_SETIP_ALREADY_RECEIVED,	"Setip already received"},
+	{IPA_RC_IP_ADDR_ALREADY_USED,	"IP address already in use on LAN"},
+	{IPA_RC_MULTICAST_FULL,		"No task available, multicast full"},
+	{IPA_RC_SETIP_INVALID_VERSION,	"SETIP invalid IP version"},
+	{IPA_RC_UNSUPPORTED_SUBCMD,	"Unsupported assist subcommand"},
+	{IPA_RC_ARP_ASSIST_NO_ENABLE,	"Only partial success, no enable"},
+	{IPA_RC_PRIMARY_ALREADY_DEFINED, "Primary already defined"},
+	{IPA_RC_SECOND_ALREADY_DEFINED,	"Secondary already defined"},
+	{IPA_RC_INVALID_SETRTG_INDICATOR, "Invalid SETRTG indicator"},
+	{IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"},
+	{IPA_RC_LAN_OFFLINE,		"STRTLAN_LAN_DISABLED - LAN offline"},
+	{IPA_RC_INVALID_IP_VERSION2,	"Invalid IP version"},
+	{IPA_RC_FFFF,			"Unknown Error"}
+};
+
+
+
+char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
+{
+	int x = 0;
+	qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
+			sizeof(struct ipa_rc_msg) - 1].rc = rc;
+	while (qeth_ipa_rc_msg[x].rc != rc)
+		x++;
+	return qeth_ipa_rc_msg[x].msg;
+}
+
+
+struct ipa_cmd_names {
+	enum qeth_ipa_cmds cmd;
+	char *name;
+};
+
+static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
+	{IPA_CMD_STARTLAN,	"startlan"},
+	{IPA_CMD_STOPLAN,	"stoplan"},
+	{IPA_CMD_SETVMAC,	"setvmac"},
+	{IPA_CMD_DELVMAC,	"delvmca"},
+	{IPA_CMD_SETGMAC,	"setgmac"},
+	{IPA_CMD_DELGMAC,	"delgmac"},
+	{IPA_CMD_SETVLAN,	"setvlan"},
+	{IPA_CMD_DELVLAN,	"delvlan"},
+	{IPA_CMD_SETCCID,	"setccid"},
+	{IPA_CMD_DELCCID,	"delccid"},
+	{IPA_CMD_MODCCID,	"modccid"},
+	{IPA_CMD_SETIP,		"setip"},
+	{IPA_CMD_QIPASSIST,	"qipassist"},
+	{IPA_CMD_SETASSPARMS,	"setassparms"},
+	{IPA_CMD_SETIPM,	"setipm"},
+	{IPA_CMD_DELIPM,	"delipm"},
+	{IPA_CMD_SETRTG,	"setrtg"},
+	{IPA_CMD_DELIP,		"delip"},
+	{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
+	{IPA_CMD_SET_DIAG_ASS,	"set_diag_ass"},
+	{IPA_CMD_CREATE_ADDR,	"create_addr"},
+	{IPA_CMD_DESTROY_ADDR,	"destroy_addr"},
+	{IPA_CMD_REGISTER_LOCAL_ADDR,	"register_local_addr"},
+	{IPA_CMD_UNREGISTER_LOCAL_ADDR,	"unregister_local_addr"},
+	{IPA_CMD_UNKNOWN,	"unknown"},
+};
+
+char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
+{
+	int x = 0;
+	qeth_ipa_cmd_names[
+		sizeof(qeth_ipa_cmd_names) /
+			sizeof(struct ipa_cmd_names)-1].cmd = cmd;
+	while (qeth_ipa_cmd_names[x].cmd != cmd)
+		x++;
+	return qeth_ipa_cmd_names[x].name;
+}
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_core_mpc.h
similarity index 78%
rename from drivers/s390/net/qeth_mpc.h
rename to drivers/s390/net/qeth_core_mpc.h
index 6de2da5..de22193 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -1,27 +1,25 @@
 /*
- * linux/drivers/s390/net/qeth_mpc.h
+ *  drivers/s390/net/qeth_core_mpc.h
  *
- * Linux on zSeries OSA Express and HiperSockets support
- *
- * Copyright 2000,2003 IBM Corporation
- * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
- *            Thomas Spatzier <tspat@de.ibm.com>
- *            Frank Pavlic <fpavlic@de.ibm.com>
- *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
  */
-#ifndef __QETH_MPC_H__
-#define __QETH_MPC_H__
+
+#ifndef __QETH_CORE_MPC_H__
+#define __QETH_CORE_MPC_H__
 
 #include <asm/qeth.h>
 
 #define IPA_PDU_HEADER_SIZE	0x40
-#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e)
-#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26)
-#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x29)
-#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a)
+#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e)
+#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer + 0x26)
+#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer + 0x29)
+#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer + 0x3a)
 
 extern unsigned char IPA_PDU_HEADER[];
-#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer+0x2c)
+#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c)
 
 #define IPA_CMD_LENGTH	(IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
 
@@ -93,7 +91,8 @@
  */
 #define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */
 enum qeth_routing_types {
-	NO_ROUTER		= 0, /* TODO: set to bit flag used in IPA Command */
+	/* TODO: set to bit flag used in IPA Command */
+	NO_ROUTER		= 0,
 	PRIMARY_ROUTER		= 1,
 	SECONDARY_ROUTER	= 2,
 	MULTICAST_ROUTER	= 3,
@@ -233,14 +232,14 @@
 
 /* SETADAPTER IPA Command: ****************************************************/
 enum qeth_ipa_setadp_cmd {
-	IPA_SETADP_QUERY_COMMANDS_SUPPORTED	= 0x01,
-	IPA_SETADP_ALTER_MAC_ADDRESS		= 0x02,
-	IPA_SETADP_ADD_DELETE_GROUP_ADDRESS	= 0x04,
-	IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR	= 0x08,
-	IPA_SETADP_SET_ADDRESSING_MODE		= 0x10,
-	IPA_SETADP_SET_CONFIG_PARMS		= 0x20,
-	IPA_SETADP_SET_CONFIG_PARMS_EXTENDED	= 0x40,
-	IPA_SETADP_SET_BROADCAST_MODE		= 0x80,
+	IPA_SETADP_QUERY_COMMANDS_SUPPORTED	= 0x0001,
+	IPA_SETADP_ALTER_MAC_ADDRESS		= 0x0002,
+	IPA_SETADP_ADD_DELETE_GROUP_ADDRESS	= 0x0004,
+	IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR	= 0x0008,
+	IPA_SETADP_SET_ADDRESSING_MODE		= 0x0010,
+	IPA_SETADP_SET_CONFIG_PARMS		= 0x0020,
+	IPA_SETADP_SET_CONFIG_PARMS_EXTENDED	= 0x0040,
+	IPA_SETADP_SET_BROADCAST_MODE		= 0x0080,
 	IPA_SETADP_SEND_OSA_MESSAGE		= 0x0100,
 	IPA_SETADP_SET_SNMP_CONTROL		= 0x0200,
 	IPA_SETADP_QUERY_CARD_INFO		= 0x0400,
@@ -397,26 +396,11 @@
 	} data;
 } __attribute__ ((packed));
 
-/* IPFRAME IPA Command:    ***************************************************/
-/* TODO: define in analogy to commands define above */
-
-/* ADD_ADDR_ENTRY IPA Command:    ********************************************/
-/* TODO: define in analogy to commands define above */
-
-/* DELETE_ADDR_ENTRY IPA Command:    *****************************************/
-/* TODO: define in analogy to commands define above */
-
 /* CREATE_ADDR IPA Command:    ***********************************************/
 struct qeth_create_destroy_address {
 	__u8 unique_id[8];
 } __attribute__ ((packed));
 
-/* REGISTER_LOCAL_ADDR IPA Command:    ***************************************/
-/* TODO: define in analogy to commands define above */
-
-/* UNREGISTER_LOCAL_ADDR IPA Command:    *************************************/
-/* TODO: define in analogy to commands define above */
-
 /* Header for each IPA command */
 struct qeth_ipacmd_hdr {
 	__u8   command;
@@ -463,10 +447,8 @@
 };
 
 
-extern char *
-qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
-extern char *
-qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
+extern char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
+extern char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
 
 #define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
 			       sizeof(struct qeth_ipacmd_setassparms_hdr))
@@ -492,88 +474,89 @@
 
 extern unsigned char CM_ENABLE[];
 #define CM_ENABLE_SIZE 0x63
-#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer+0x2c)
-#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
-#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer+0x5b)
+#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer + 0x2c)
+#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
+#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer + 0x5b)
 
 #define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
-		(PDU_ENCAPSULATION(buffer)+ 0x13)
+		(PDU_ENCAPSULATION(buffer) + 0x13)
 
 
 extern unsigned char CM_SETUP[];
 #define CM_SETUP_SIZE 0x64
-#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
-#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
-#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
+#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
+#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
+#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
 
 #define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
 		(PDU_ENCAPSULATION(buffer) + 0x1a)
 
 extern unsigned char ULP_ENABLE[];
 #define ULP_ENABLE_SIZE 0x6b
-#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer+0x61)
-#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer+0x2c)
-#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
-#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer+0x62)
+#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer + 0x61)
+#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer + 0x2c)
+#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
+#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer + 0x62)
 #define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) \
 		(PDU_ENCAPSULATION(buffer) + 0x13)
 #define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) \
-		(PDU_ENCAPSULATION(buffer)+ 0x1f)
+		(PDU_ENCAPSULATION(buffer) + 0x1f)
 #define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) \
 		(PDU_ENCAPSULATION(buffer) + 0x17)
 #define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) \
-		(PDU_ENCAPSULATION(buffer)+ 0x2b)
+		(PDU_ENCAPSULATION(buffer) + 0x2b)
 /* Layer 2 defintions */
 #define QETH_PROT_LAYER2 0x08
 #define QETH_PROT_TCPIP  0x03
 #define QETH_PROT_OSN2   0x0a
-#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
-#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
+#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer + 0x50)
+#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer + 0x19)
 
 extern unsigned char ULP_SETUP[];
 #define ULP_SETUP_SIZE 0x6c
-#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
-#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
-#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
-#define QETH_ULP_SETUP_CUA(buffer) (buffer+0x68)
-#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer+0x6a)
+#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
+#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
+#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
+#define QETH_ULP_SETUP_CUA(buffer) (buffer + 0x68)
+#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer + 0x6a)
 
 #define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
-		(PDU_ENCAPSULATION(buffer)+0x1a)
+		(PDU_ENCAPSULATION(buffer) + 0x1a)
 
 
 extern unsigned char DM_ACT[];
 #define DM_ACT_SIZE 0x55
-#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer+0x2c)
-#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer+0x51)
+#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer + 0x2c)
+#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer + 0x51)
 
 
 
-#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer+4)
-#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer+0x1c)
-#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer+0x20)
+#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer + 4)
+#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer + 0x1c)
+#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer + 0x20)
 
 extern unsigned char IDX_ACTIVATE_READ[];
 extern unsigned char IDX_ACTIVATE_WRITE[];
 
 #define IDX_ACTIVATE_SIZE	0x22
-#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer+0x0c)
-#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b]&0x80)
-#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer+0x10)
-#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer+0x16)
-#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer+0x1e)
-#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer+0x20)
-#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08]&3)==2)
-#define QETH_IDX_REPLY_LEVEL(buffer) (buffer+0x12)
+#define QETH_IDX_ACT_PNO(buffer) (buffer+0x0b)
+#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer + 0x0c)
+#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b] & 0x80)
+#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer + 0x10)
+#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer + 0x16)
+#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer + 0x1e)
+#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer + 0x20)
+#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08] & 3) == 2)
+#define QETH_IDX_REPLY_LEVEL(buffer) (buffer + 0x12)
 #define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
 
 #define PDU_ENCAPSULATION(buffer) \
-	(buffer + *(buffer + (*(buffer+0x0b)) + \
-	 *(buffer + *(buffer+0x0b)+0x11) +0x07))
+	(buffer + *(buffer + (*(buffer + 0x0b)) + \
+	 *(buffer + *(buffer + 0x0b) + 0x11) + 0x07))
 
 #define IS_IPA(buffer) \
 	((buffer) && \
-	 ( *(buffer + ((*(buffer+0x0b))+4) )==0xc1) )
+	 (*(buffer + ((*(buffer + 0x0b)) + 4)) == 0xc1))
 
 #define ADDR_FRAME_TYPE_DIX 1
 #define ADDR_FRAME_TYPE_802_3 2
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_core_offl.c
similarity index 67%
rename from drivers/s390/net/qeth_eddp.c
rename to drivers/s390/net/qeth_core_offl.c
index e3c268c..8b407d6 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_core_offl.c
@@ -1,13 +1,11 @@
 /*
- * linux/drivers/s390/net/qeth_eddp.c
+ *  drivers/s390/net/qeth_core_offl.c
  *
- * Enhanced Device Driver Packing (EDDP) support for the qeth driver.
- *
- * Copyright 2004 IBM Corporation
- *
- *    Author(s): Thomas Spatzier <tspat@de.ibm.com>
- *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
  */
+
 #include <linux/errno.h>
 #include <linux/ip.h>
 #include <linux/inetdevice.h>
@@ -18,14 +16,14 @@
 #include <linux/skbuff.h>
 
 #include <net/ip.h>
+#include <net/ip6_checksum.h>
 
-#include "qeth.h"
-#include "qeth_mpc.h"
-#include "qeth_eddp.h"
+#include "qeth_core.h"
+#include "qeth_core_mpc.h"
+#include "qeth_core_offl.h"
 
-int
-qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
-				    struct qeth_eddp_context *ctx)
+int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
+		struct qeth_eddp_context *ctx)
 {
 	int index = queue->next_buf_to_fill;
 	int elements_needed = ctx->num_elements;
@@ -34,7 +32,7 @@
 	int buffers_needed = 0;
 
 	QETH_DBF_TEXT(trace, 5, "eddpcbfc");
-	while(elements_needed > 0) {
+	while (elements_needed > 0) {
 		buffers_needed++;
 		if (atomic_read(&queue->bufs[index].state) !=
 				QETH_QDIO_BUF_EMPTY)
@@ -49,8 +47,7 @@
 	return buffers_needed;
 }
 
-static void
-qeth_eddp_free_context(struct qeth_eddp_context *ctx)
+static void qeth_eddp_free_context(struct qeth_eddp_context *ctx)
 {
 	int i;
 
@@ -63,26 +60,24 @@
 }
 
 
-static inline void
-qeth_eddp_get_context(struct qeth_eddp_context *ctx)
+static void qeth_eddp_get_context(struct qeth_eddp_context *ctx)
 {
 	atomic_inc(&ctx->refcnt);
 }
 
-void
-qeth_eddp_put_context(struct qeth_eddp_context *ctx)
+void qeth_eddp_put_context(struct qeth_eddp_context *ctx)
 {
 	if (atomic_dec_return(&ctx->refcnt) == 0)
 		qeth_eddp_free_context(ctx);
 }
+EXPORT_SYMBOL_GPL(qeth_eddp_put_context);
 
-void
-qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
+void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
 {
 	struct qeth_eddp_context_reference *ref;
 
 	QETH_DBF_TEXT(trace, 6, "eddprctx");
-	while (!list_empty(&buf->ctx_list)){
+	while (!list_empty(&buf->ctx_list)) {
 		ref = list_entry(buf->ctx_list.next,
 				 struct qeth_eddp_context_reference, list);
 		qeth_eddp_put_context(ref->ctx);
@@ -91,9 +86,8 @@
 	}
 }
 
-static int
-qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
-			  struct qeth_eddp_context *ctx)
+static int qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
+		struct qeth_eddp_context *ctx)
 {
 	struct qeth_eddp_context_reference *ref;
 
@@ -107,10 +101,8 @@
 	return 0;
 }
 
-int
-qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
-		      struct qeth_eddp_context *ctx,
-		      int index)
+int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
+		struct qeth_eddp_context *ctx, int index)
 {
 	struct qeth_qdio_out_buffer *buf = NULL;
 	struct qdio_buffer *buffer;
@@ -123,7 +115,7 @@
 	QETH_DBF_TEXT(trace, 5, "eddpfibu");
 	while (elements > 0) {
 		buf = &queue->bufs[index];
-		if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY){
+		if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY) {
 			/* normally this should not happen since we checked for
 			 * available elements in qeth_check_elements_for_context
 			 */
@@ -148,9 +140,9 @@
 			must_refcnt = 1;
 			continue;
 		}
-		if (must_refcnt){
+		if (must_refcnt) {
 			must_refcnt = 0;
-			if (qeth_eddp_buf_ref_context(buf, ctx)){
+			if (qeth_eddp_buf_ref_context(buf, ctx)) {
 				PRINT_WARN("no memory to create eddp context "
 					   "reference\n");
 				goto out_check;
@@ -158,7 +150,7 @@
 		}
 		buffer = buf->buffer;
 		/* fill one skb into buffer */
-		for (i = 0; i < ctx->elements_per_skb; ++i){
+		for (i = 0; i < ctx->elements_per_skb; ++i) {
 			if (ctx->elements[element].length != 0) {
 				buffer->element[buf->next_element_to_fill].
 				addr = ctx->elements[element].addr;
@@ -176,7 +168,7 @@
 	if (!queue->do_pack) {
 		QETH_DBF_TEXT(trace, 6, "fillbfnp");
 		/* set state to PRIMED -> will be flushed */
-		if (buf->next_element_to_fill > 0){
+		if (buf->next_element_to_fill > 0) {
 			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
 			flush_cnt++;
 		}
@@ -198,9 +190,8 @@
 	return flush_cnt;
 }
 
-static void
-qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
-			      struct qeth_eddp_data *eddp, int data_len)
+static void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
+		struct qeth_eddp_data *eddp, int data_len)
 {
 	u8 *page;
 	int page_remainder;
@@ -220,7 +211,7 @@
 		pkt_len += VLAN_HLEN;
 	/* does complete packet fit in current page ? */
 	page_remainder = PAGE_SIZE - page_offset;
-	if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
+	if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)) {
 		/* no -> go to start of next page */
 		ctx->offset += page_remainder;
 		page = ctx->pages[ctx->offset >> PAGE_SHIFT];
@@ -232,14 +223,14 @@
 	ctx->offset += sizeof(struct qeth_hdr);
 	page_offset += sizeof(struct qeth_hdr);
 	/* add mac header (?) */
-	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
 		memcpy(page + page_offset, &eddp->mac, ETH_HLEN);
 		element->length += ETH_HLEN;
 		ctx->offset += ETH_HLEN;
 		page_offset += ETH_HLEN;
 	}
 	/* add VLAN tag */
-	if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)){
+	if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
 		memcpy(page + page_offset, &eddp->vlan, VLAN_HLEN);
 		element->length += VLAN_HLEN;
 		ctx->offset += VLAN_HLEN;
@@ -258,9 +249,8 @@
 	ctx->offset += eddp->thl;
 }
 
-static void
-qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
-			__wsum *hcsum)
+static void qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp,
+		int len, __wsum *hcsum)
 {
 	struct skb_frag_struct *frag;
 	int left_in_frag;
@@ -278,16 +268,17 @@
 		while (len > 0) {
 			if (eddp->frag < 0) {
 				/* we're in skb->data */
-				left_in_frag = (eddp->skb->len - eddp->skb->data_len)
+				left_in_frag = (eddp->skb->len -
+						eddp->skb->data_len)
 						- eddp->skb_offset;
 				src = eddp->skb->data + eddp->skb_offset;
 			} else {
-				frag = &skb_shinfo(eddp->skb)->
-					frags[eddp->frag];
+				frag = &skb_shinfo(eddp->skb)->frags[
+					eddp->frag];
 				left_in_frag = frag->size - eddp->frag_offset;
-				src = (u8 *)(
-					(page_to_pfn(frag->page) << PAGE_SHIFT)+
-					frag->page_offset + eddp->frag_offset);
+				src = (u8 *)((page_to_pfn(frag->page) <<
+					PAGE_SHIFT) + frag->page_offset +
+					eddp->frag_offset);
 			}
 			if (left_in_frag <= 0) {
 				eddp->frag++;
@@ -305,10 +296,8 @@
 	}
 }
 
-static void
-qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
-				  struct qeth_eddp_data *eddp, int data_len,
-				  __wsum hcsum)
+static void qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
+		struct qeth_eddp_data *eddp, int data_len, __wsum hcsum)
 {
 	u8 *page;
 	int page_remainder;
@@ -320,9 +309,9 @@
 	page = ctx->pages[ctx->offset >> PAGE_SHIFT];
 	page_offset = ctx->offset % PAGE_SIZE;
 	element = &ctx->elements[ctx->num_elements];
-	while (data_len){
+	while (data_len) {
 		page_remainder = PAGE_SIZE - page_offset;
-		if (page_remainder < data_len){
+		if (page_remainder < data_len) {
 			qeth_eddp_copy_data_tcp(page + page_offset, eddp,
 						page_remainder, &hcsum);
 			element->length += page_remainder;
@@ -352,8 +341,8 @@
 	((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
 }
 
-static __wsum
-qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
+static __wsum qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp,
+		int data_len)
 {
 	__wsum phcsum; /* pseudo header checksum */
 
@@ -366,8 +355,8 @@
 	return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
 }
 
-static __wsum
-qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
+static __wsum qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp,
+		int data_len)
 {
 	__be32 proto;
 	__wsum phcsum; /* pseudo header checksum */
@@ -384,14 +373,14 @@
 	return phcsum;
 }
 
-static struct qeth_eddp_data *
-qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl)
+static struct qeth_eddp_data *qeth_eddp_create_eddp_data(struct qeth_hdr *qh,
+		u8 *nh, u8 nhl, u8 *th, u8 thl)
 {
 	struct qeth_eddp_data *eddp;
 
 	QETH_DBF_TEXT(trace, 5, "eddpcrda");
 	eddp = kzalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC);
-	if (eddp){
+	if (eddp) {
 		eddp->nhl = nhl;
 		eddp->thl = thl;
 		memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr));
@@ -402,9 +391,8 @@
 	return eddp;
 }
 
-static void
-__qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
-			     struct qeth_eddp_data *eddp)
+static void __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+		struct qeth_eddp_data *eddp)
 {
 	struct tcphdr *tcph;
 	int data_len;
@@ -412,30 +400,26 @@
 
 	QETH_DBF_TEXT(trace, 5, "eddpftcp");
 	eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
-       if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
-               eddp->skb_offset += sizeof(struct ethhdr);
-#ifdef CONFIG_QETH_VLAN
-               if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
-                       eddp->skb_offset += VLAN_HLEN;
-#endif /* CONFIG_QETH_VLAN */
-       }
+	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+		eddp->skb_offset += sizeof(struct ethhdr);
+		if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+			eddp->skb_offset += VLAN_HLEN;
+	}
 	tcph = tcp_hdr(eddp->skb);
 	while (eddp->skb_offset < eddp->skb->len) {
 		data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
 			       (int)(eddp->skb->len - eddp->skb_offset));
 		/* prepare qdio hdr */
-		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
 			eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
 						     eddp->nhl + eddp->thl;
-#ifdef CONFIG_QETH_VLAN
 			if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
 				eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
-#endif /* CONFIG_QETH_VLAN */
 		} else
 			eddp->qh.hdr.l3.length = data_len + eddp->nhl +
 						 eddp->thl;
 		/* prepare ip hdr */
-		if (eddp->skb->protocol == htons(ETH_P_IP)){
+		if (eddp->skb->protocol == htons(ETH_P_IP)) {
 			eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl +
 						 eddp->thl);
 			eddp->nh.ip4.h.check = 0;
@@ -443,9 +427,10 @@
 				ip_fast_csum((u8 *)&eddp->nh.ip4.h,
 						eddp->nh.ip4.h.ihl);
 		} else
-			eddp->nh.ip6.h.payload_len = htons(data_len + eddp->thl);
+			eddp->nh.ip6.h.payload_len = htons(data_len +
+								eddp->thl);
 		/* prepare tcp hdr */
-		if (data_len == (eddp->skb->len - eddp->skb_offset)){
+		if (data_len == (eddp->skb->len - eddp->skb_offset)) {
 			/* last segment -> set FIN and PSH flags */
 			eddp->th.tcp.h.fin = tcph->fin;
 			eddp->th.tcp.h.psh = tcph->psh;
@@ -462,13 +447,13 @@
 		/* prepare headers for next round */
 		if (eddp->skb->protocol == htons(ETH_P_IP))
 			eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1);
-		eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) + data_len);
+		eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) +
+			data_len);
 	}
 }
 
-static int
-qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
-			   struct sk_buff *skb, struct qeth_hdr *qhdr)
+static int qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+		struct sk_buff *skb, struct qeth_hdr *qhdr)
 {
 	struct qeth_eddp_data *eddp = NULL;
 
@@ -494,12 +479,10 @@
 	if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
 		skb_set_mac_header(skb, sizeof(struct qeth_hdr));
 		memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
-#ifdef CONFIG_QETH_VLAN
 		if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
 			eddp->vlan[0] = skb->protocol;
 			eddp->vlan[1] = htons(vlan_tx_tag_get(skb));
 		}
-#endif /* CONFIG_QETH_VLAN */
 	}
 	/* the next flags will only be set on the last segment */
 	eddp->th.tcp.h.fin = 0;
@@ -511,16 +494,15 @@
 	return 0;
 }
 
-static void
-qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
-			 int hdr_len)
+static void qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx,
+		struct sk_buff *skb, int hdr_len)
 {
 	int skbs_per_page;
 
 	QETH_DBF_TEXT(trace, 5, "eddpcanp");
 	/* can we put multiple skbs in one page? */
 	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
-	if (skbs_per_page > 1){
+	if (skbs_per_page > 1) {
 		ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
 				 skbs_per_page + 1;
 		ctx->elements_per_skb = 1;
@@ -535,9 +517,8 @@
 			    (skb_shinfo(skb)->gso_segs + 1);
 }
 
-static struct qeth_eddp_context *
-qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb,
-				 int hdr_len)
+static struct qeth_eddp_context *qeth_eddp_create_context_generic(
+		struct qeth_card *card, struct sk_buff *skb, int hdr_len)
 {
 	struct qeth_eddp_context *ctx = NULL;
 	u8 *addr;
@@ -546,37 +527,36 @@
 	QETH_DBF_TEXT(trace, 5, "creddpcg");
 	/* create the context and allocate pages */
 	ctx = kzalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC);
-	if (ctx == NULL){
+	if (ctx == NULL) {
 		QETH_DBF_TEXT(trace, 2, "ceddpcn1");
 		return NULL;
 	}
 	ctx->type = QETH_LARGE_SEND_EDDP;
 	qeth_eddp_calc_num_pages(ctx, skb, hdr_len);
-	if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)){
+	if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)) {
 		QETH_DBF_TEXT(trace, 2, "ceddpcis");
 		kfree(ctx);
 		return NULL;
 	}
 	ctx->pages = kcalloc(ctx->num_pages, sizeof(u8 *), GFP_ATOMIC);
-	if (ctx->pages == NULL){
+	if (ctx->pages == NULL) {
 		QETH_DBF_TEXT(trace, 2, "ceddpcn2");
 		kfree(ctx);
 		return NULL;
 	}
-	for (i = 0; i < ctx->num_pages; ++i){
-		addr = (u8 *)__get_free_page(GFP_ATOMIC);
-		if (addr == NULL){
+	for (i = 0; i < ctx->num_pages; ++i) {
+		addr = (u8 *)get_zeroed_page(GFP_ATOMIC);
+		if (addr == NULL) {
 			QETH_DBF_TEXT(trace, 2, "ceddpcn3");
 			ctx->num_pages = i;
 			qeth_eddp_free_context(ctx);
 			return NULL;
 		}
-		memset(addr, 0, PAGE_SIZE);
 		ctx->pages[i] = addr;
 	}
 	ctx->elements = kcalloc(ctx->num_elements,
 				sizeof(struct qeth_eddp_element), GFP_ATOMIC);
-	if (ctx->elements == NULL){
+	if (ctx->elements == NULL) {
 		QETH_DBF_TEXT(trace, 2, "ceddpcn4");
 		qeth_eddp_free_context(ctx);
 		return NULL;
@@ -587,18 +567,18 @@
 	return ctx;
 }
 
-static struct qeth_eddp_context *
-qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
-			     struct qeth_hdr *qhdr)
+static struct qeth_eddp_context *qeth_eddp_create_context_tcp(
+		struct qeth_card *card, struct sk_buff *skb,
+		struct qeth_hdr *qhdr)
 {
 	struct qeth_eddp_context *ctx = NULL;
 
 	QETH_DBF_TEXT(trace, 5, "creddpct");
 	if (skb->protocol == htons(ETH_P_IP))
 		ctx = qeth_eddp_create_context_generic(card, skb,
-						       (sizeof(struct qeth_hdr) +
-						        ip_hdrlen(skb) +
-							tcp_hdrlen(skb)));
+						(sizeof(struct qeth_hdr) +
+						ip_hdrlen(skb) +
+						tcp_hdrlen(skb)));
 	else if (skb->protocol == htons(ETH_P_IPV6))
 		ctx = qeth_eddp_create_context_generic(card, skb,
 			sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) +
@@ -610,7 +590,7 @@
 		QETH_DBF_TEXT(trace, 2, "creddpnl");
 		return NULL;
 	}
-	if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)){
+	if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)) {
 		QETH_DBF_TEXT(trace, 2, "ceddptfe");
 		qeth_eddp_free_context(ctx);
 		return NULL;
@@ -619,9 +599,9 @@
 	return ctx;
 }
 
-struct qeth_eddp_context *
-qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb,
-			 struct qeth_hdr *qhdr, unsigned char sk_protocol)
+struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *card,
+		struct sk_buff *skb, struct qeth_hdr *qhdr,
+		unsigned char sk_protocol)
 {
 	QETH_DBF_TEXT(trace, 5, "creddpc");
 	switch (sk_protocol) {
@@ -632,3 +612,90 @@
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(qeth_eddp_create_context);
+
+void qeth_tso_fill_header(struct qeth_card *card, struct qeth_hdr *qhdr,
+		struct sk_buff *skb)
+{
+	struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr;
+	struct tcphdr *tcph = tcp_hdr(skb);
+	struct iphdr *iph = ip_hdr(skb);
+	struct ipv6hdr *ip6h = ipv6_hdr(skb);
+
+	QETH_DBF_TEXT(trace, 5, "tsofhdr");
+
+	/*fix header to TSO values ...*/
+	hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
+	/*set values which are fix for the first approach ...*/
+	hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
+	hdr->ext.imb_hdr_no  = 1;
+	hdr->ext.hdr_type    = 1;
+	hdr->ext.hdr_version = 1;
+	hdr->ext.hdr_len     = 28;
+	/*insert non-fix values */
+	hdr->ext.mss = skb_shinfo(skb)->gso_size;
+	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
+	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
+				       sizeof(struct qeth_hdr_tso));
+	tcph->check = 0;
+	if (skb->protocol == ETH_P_IPV6) {
+		ip6h->payload_len = 0;
+		tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+					       0, IPPROTO_TCP, 0);
+	} else {
+		/*OSA want us to set these values ...*/
+		tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+					 0, IPPROTO_TCP, 0);
+		iph->tot_len = 0;
+		iph->check = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(qeth_tso_fill_header);
+
+void qeth_tx_csum(struct sk_buff *skb)
+{
+	int tlen;
+	if (skb->protocol == htons(ETH_P_IP)) {
+		tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
+		switch (ip_hdr(skb)->protocol) {
+		case IPPROTO_TCP:
+			tcp_hdr(skb)->check = 0;
+			tcp_hdr(skb)->check = csum_tcpudp_magic(
+				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+				tlen, ip_hdr(skb)->protocol,
+				skb_checksum(skb, skb_transport_offset(skb),
+					tlen, 0));
+			break;
+		case IPPROTO_UDP:
+			udp_hdr(skb)->check = 0;
+			udp_hdr(skb)->check = csum_tcpudp_magic(
+				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+				tlen, ip_hdr(skb)->protocol,
+				skb_checksum(skb, skb_transport_offset(skb),
+					tlen, 0));
+			break;
+		}
+	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		switch (ipv6_hdr(skb)->nexthdr) {
+		case IPPROTO_TCP:
+			tcp_hdr(skb)->check = 0;
+			tcp_hdr(skb)->check = csum_ipv6_magic(
+				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+				ipv6_hdr(skb)->payload_len,
+				ipv6_hdr(skb)->nexthdr,
+				skb_checksum(skb, skb_transport_offset(skb),
+					ipv6_hdr(skb)->payload_len, 0));
+			break;
+		case IPPROTO_UDP:
+			udp_hdr(skb)->check = 0;
+			udp_hdr(skb)->check = csum_ipv6_magic(
+				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+				ipv6_hdr(skb)->payload_len,
+				ipv6_hdr(skb)->nexthdr,
+				skb_checksum(skb, skb_transport_offset(skb),
+					ipv6_hdr(skb)->payload_len, 0));
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(qeth_tx_csum);
diff --git a/drivers/s390/net/qeth_core_offl.h b/drivers/s390/net/qeth_core_offl.h
new file mode 100644
index 0000000..86bf7df
--- /dev/null
+++ b/drivers/s390/net/qeth_core_offl.h
@@ -0,0 +1,76 @@
+/*
+ *  drivers/s390/net/qeth_core_offl.h
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#ifndef __QETH_CORE_OFFL_H__
+#define __QETH_CORE_OFFL_H__
+
+struct qeth_eddp_element {
+	u32 flags;
+	u32 length;
+	void *addr;
+};
+
+struct qeth_eddp_context {
+	atomic_t refcnt;
+	enum qeth_large_send_types type;
+	int num_pages;			    /* # of allocated pages */
+	u8 **pages;			    /* pointers to pages */
+	int offset;			    /* offset in ctx during creation */
+	int num_elements;		    /* # of required 'SBALEs' */
+	struct qeth_eddp_element *elements; /* array of 'SBALEs' */
+	int elements_per_skb;		    /* # of 'SBALEs' per skb **/
+};
+
+struct qeth_eddp_context_reference {
+	struct list_head list;
+	struct qeth_eddp_context *ctx;
+};
+
+struct qeth_eddp_data {
+	struct qeth_hdr qh;
+	struct ethhdr mac;
+	__be16 vlan[2];
+	union {
+		struct {
+			struct iphdr h;
+			u8 options[40];
+		} ip4;
+		struct {
+			struct ipv6hdr h;
+		} ip6;
+	} nh;
+	u8 nhl;
+	void *nh_in_ctx;	/* address of nh within the ctx */
+	union {
+		struct {
+			struct tcphdr h;
+			u8 options[40];
+		} tcp;
+	} th;
+	u8 thl;
+	void *th_in_ctx;	/* address of th within the ctx */
+	struct sk_buff *skb;
+	int skb_offset;
+	int frag;
+	int frag_offset;
+} __attribute__ ((packed));
+
+extern struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *,
+		 struct sk_buff *, struct qeth_hdr *, unsigned char);
+extern void qeth_eddp_put_context(struct qeth_eddp_context *);
+extern int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,
+		struct qeth_eddp_context *, int);
+extern void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
+extern int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
+		struct qeth_eddp_context *);
+
+void qeth_tso_fill_header(struct qeth_card *, struct qeth_hdr *,
+		struct sk_buff *);
+void qeth_tx_csum(struct sk_buff *skb);
+
+#endif /* __QETH_CORE_EDDP_H__ */
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
new file mode 100644
index 0000000..08a50f0
--- /dev/null
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -0,0 +1,651 @@
+/*
+ *  drivers/s390/net/qeth_core_sys.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
+ *		 Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#include <linux/list.h>
+#include <linux/rwsem.h>
+#include <asm/ebcdic.h>
+
+#include "qeth_core.h"
+
+static ssize_t qeth_dev_state_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	if (!card)
+		return -EINVAL;
+
+	switch (card->state) {
+	case CARD_STATE_DOWN:
+		return sprintf(buf, "DOWN\n");
+	case CARD_STATE_HARDSETUP:
+		return sprintf(buf, "HARDSETUP\n");
+	case CARD_STATE_SOFTSETUP:
+		return sprintf(buf, "SOFTSETUP\n");
+	case CARD_STATE_UP:
+		if (card->lan_online)
+		return sprintf(buf, "UP (LAN ONLINE)\n");
+		else
+			return sprintf(buf, "UP (LAN OFFLINE)\n");
+	case CARD_STATE_RECOVER:
+		return sprintf(buf, "RECOVER\n");
+	default:
+		return sprintf(buf, "UNKNOWN\n");
+	}
+}
+
+static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
+
+static ssize_t qeth_dev_chpid_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%02X\n", card->info.chpid);
+}
+
+static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
+
+static ssize_t qeth_dev_if_name_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	if (!card)
+		return -EINVAL;
+	return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
+}
+
+static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
+
+static ssize_t qeth_dev_card_type_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
+}
+
+static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
+
+static inline const char *qeth_get_bufsize_str(struct qeth_card *card)
+{
+	if (card->qdio.in_buf_size == 16384)
+		return "16k";
+	else if (card->qdio.in_buf_size == 24576)
+		return "24k";
+	else if (card->qdio.in_buf_size == 32768)
+		return "32k";
+	else if (card->qdio.in_buf_size == 40960)
+		return "40k";
+	else
+		return "64k";
+}
+
+static ssize_t qeth_dev_inbuf_size_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n", qeth_get_bufsize_str(card));
+}
+
+static DEVICE_ATTR(inbuf_size, 0444, qeth_dev_inbuf_size_show, NULL);
+
+static ssize_t qeth_dev_portno_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->info.portno);
+}
+
+static ssize_t qeth_dev_portno_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	unsigned int portno;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	portno = simple_strtoul(buf, &tmp, 16);
+	if (portno > QETH_MAX_PORTNO) {
+		PRINT_WARN("portno 0x%X is out of range\n", portno);
+		return -EINVAL;
+	}
+
+	card->info.portno = portno;
+	return count;
+}
+
+static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
+
+static ssize_t qeth_dev_portname_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char portname[9] = {0, };
+
+	if (!card)
+		return -EINVAL;
+
+	if (card->info.portname_required) {
+		memcpy(portname, card->info.portname + 1, 8);
+		EBCASC(portname, 8);
+		return sprintf(buf, "%s\n", portname);
+	} else
+		return sprintf(buf, "no portname required\n");
+}
+
+static ssize_t qeth_dev_portname_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	int i;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	tmp = strsep((char **) &buf, "\n");
+	if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
+		return -EINVAL;
+
+	card->info.portname[0] = strlen(tmp);
+	/* for beauty reasons */
+	for (i = 1; i < 9; i++)
+		card->info.portname[i] = ' ';
+	strcpy(card->info.portname + 1, tmp);
+	ASCEBC(card->info.portname + 1, 8);
+
+	return count;
+}
+
+static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
+		qeth_dev_portname_store);
+
+static ssize_t qeth_dev_prioqing_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	switch (card->qdio.do_prio_queueing) {
+	case QETH_PRIO_Q_ING_PREC:
+		return sprintf(buf, "%s\n", "by precedence");
+	case QETH_PRIO_Q_ING_TOS:
+		return sprintf(buf, "%s\n", "by type of service");
+	default:
+		return sprintf(buf, "always queue %i\n",
+			       card->qdio.default_out_queue);
+	}
+}
+
+static ssize_t qeth_dev_prioqing_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	/* check if 1920 devices are supported ,
+	 * if though we have to permit priority queueing
+	 */
+	if (card->qdio.no_out_queues == 1) {
+		PRINT_WARN("Priority queueing disabled due "
+			   "to hardware limitations!\n");
+		card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+		return -EPERM;
+	}
+
+	tmp = strsep((char **) &buf, "\n");
+	if (!strcmp(tmp, "prio_queueing_prec"))
+		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
+	else if (!strcmp(tmp, "prio_queueing_tos"))
+		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
+	else if (!strcmp(tmp, "no_prio_queueing:0")) {
+		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+		card->qdio.default_out_queue = 0;
+	} else if (!strcmp(tmp, "no_prio_queueing:1")) {
+		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+		card->qdio.default_out_queue = 1;
+	} else if (!strcmp(tmp, "no_prio_queueing:2")) {
+		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+		card->qdio.default_out_queue = 2;
+	} else if (!strcmp(tmp, "no_prio_queueing:3")) {
+		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+		card->qdio.default_out_queue = 3;
+	} else if (!strcmp(tmp, "no_prio_queueing")) {
+		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+		card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
+	} else {
+		PRINT_WARN("Unknown queueing type '%s'\n", tmp);
+		return -EINVAL;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
+		qeth_dev_prioqing_store);
+
+static ssize_t qeth_dev_bufcnt_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
+}
+
+static ssize_t qeth_dev_bufcnt_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	int cnt, old_cnt;
+	int rc;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	old_cnt = card->qdio.in_buf_pool.buf_count;
+	cnt = simple_strtoul(buf, &tmp, 10);
+	cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
+		((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
+	if (old_cnt != cnt) {
+		rc = qeth_realloc_buffer_pool(card, cnt);
+		if (rc)
+			PRINT_WARN("Error (%d) while setting "
+				   "buffer count.\n", rc);
+	}
+	return count;
+}
+
+static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
+		qeth_dev_bufcnt_store);
+
+static ssize_t qeth_dev_recover_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	int i;
+
+	if (!card)
+		return -EINVAL;
+
+	if (card->state != CARD_STATE_UP)
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 1)
+		qeth_schedule_recovery(card);
+
+	return count;
+}
+
+static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
+
+static ssize_t qeth_dev_performance_stats_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
+}
+
+static ssize_t qeth_dev_performance_stats_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	int i;
+
+	if (!card)
+		return -EINVAL;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if ((i == 0) || (i == 1)) {
+		if (i == card->options.performance_stats)
+			return count;
+		card->options.performance_stats = i;
+		if (i == 0)
+			memset(&card->perf_stats, 0,
+				sizeof(struct qeth_perf_stats));
+		card->perf_stats.initial_rx_packets = card->stats.rx_packets;
+		card->perf_stats.initial_tx_packets = card->stats.tx_packets;
+	} else {
+		PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
+		   qeth_dev_performance_stats_store);
+
+static ssize_t qeth_dev_layer2_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
+}
+
+static ssize_t qeth_dev_layer2_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	int i, rc;
+	enum qeth_discipline_id newdis;
+
+	if (!card)
+		return -EINVAL;
+
+	if (((card->state != CARD_STATE_DOWN) &&
+	     (card->state != CARD_STATE_RECOVER)))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	switch (i) {
+	case 0:
+		newdis = QETH_DISCIPLINE_LAYER3;
+		break;
+	case 1:
+		newdis = QETH_DISCIPLINE_LAYER2;
+		break;
+	default:
+		PRINT_WARN("layer2: write 0 or 1 to this file!\n");
+		return -EINVAL;
+	}
+
+	if (card->options.layer2 == newdis) {
+		return count;
+	} else {
+		if (card->discipline.ccwgdriver) {
+			card->discipline.ccwgdriver->remove(card->gdev);
+			qeth_core_free_discipline(card);
+		}
+	}
+
+	rc = qeth_core_load_discipline(card, newdis);
+	if (rc)
+		return rc;
+
+	rc = card->discipline.ccwgdriver->probe(card->gdev);
+	if (rc)
+		return rc;
+	return count;
+}
+
+static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
+		   qeth_dev_layer2_store);
+
+static ssize_t qeth_dev_large_send_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	switch (card->options.large_send) {
+	case QETH_LARGE_SEND_NO:
+		return sprintf(buf, "%s\n", "no");
+	case QETH_LARGE_SEND_EDDP:
+		return sprintf(buf, "%s\n", "EDDP");
+	case QETH_LARGE_SEND_TSO:
+		return sprintf(buf, "%s\n", "TSO");
+	default:
+		return sprintf(buf, "%s\n", "N/A");
+	}
+}
+
+static ssize_t qeth_dev_large_send_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	enum qeth_large_send_types type;
+	int rc = 0;
+	char *tmp;
+
+	if (!card)
+		return -EINVAL;
+	tmp = strsep((char **) &buf, "\n");
+	if (!strcmp(tmp, "no")) {
+		type = QETH_LARGE_SEND_NO;
+	} else if (!strcmp(tmp, "EDDP")) {
+		type = QETH_LARGE_SEND_EDDP;
+	} else if (!strcmp(tmp, "TSO")) {
+		type = QETH_LARGE_SEND_TSO;
+	} else {
+		PRINT_WARN("large_send: invalid mode %s!\n", tmp);
+		return -EINVAL;
+	}
+	if (card->options.large_send == type)
+		return count;
+	rc = qeth_set_large_send(card, type);
+	if (rc)
+		return rc;
+	return count;
+}
+
+static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
+		   qeth_dev_large_send_store);
+
+static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value)
+{
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", value);
+}
+
+static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
+		const char *buf, size_t count, int *value, int max_value)
+{
+	char *tmp;
+	int i;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 10);
+	if (i <= max_value) {
+		*value = i;
+	} else {
+		PRINT_WARN("blkt total time: write values between"
+			   " 0 and %d to this file!\n", max_value);
+		return -EINVAL;
+	}
+	return count;
+}
+
+static ssize_t qeth_dev_blkt_total_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
+}
+
+static ssize_t qeth_dev_blkt_total_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	return qeth_dev_blkt_store(card, buf, count,
+				   &card->info.blkt.time_total, 1000);
+}
+
+
+
+static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
+		   qeth_dev_blkt_total_store);
+
+static ssize_t qeth_dev_blkt_inter_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
+}
+
+static ssize_t qeth_dev_blkt_inter_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	return qeth_dev_blkt_store(card, buf, count,
+				   &card->info.blkt.inter_packet, 100);
+}
+
+static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
+		   qeth_dev_blkt_inter_store);
+
+static ssize_t qeth_dev_blkt_inter_jumbo_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	return qeth_dev_blkt_show(buf, card,
+				  card->info.blkt.inter_packet_jumbo);
+}
+
+static ssize_t qeth_dev_blkt_inter_jumbo_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	return qeth_dev_blkt_store(card, buf, count,
+				   &card->info.blkt.inter_packet_jumbo, 100);
+}
+
+static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
+		   qeth_dev_blkt_inter_jumbo_store);
+
+static struct attribute *qeth_blkt_device_attrs[] = {
+	&dev_attr_total.attr,
+	&dev_attr_inter.attr,
+	&dev_attr_inter_jumbo.attr,
+	NULL,
+};
+
+static struct attribute_group qeth_device_blkt_group = {
+	.name = "blkt",
+	.attrs = qeth_blkt_device_attrs,
+};
+
+static struct attribute *qeth_device_attrs[] = {
+	&dev_attr_state.attr,
+	&dev_attr_chpid.attr,
+	&dev_attr_if_name.attr,
+	&dev_attr_card_type.attr,
+	&dev_attr_inbuf_size.attr,
+	&dev_attr_portno.attr,
+	&dev_attr_portname.attr,
+	&dev_attr_priority_queueing.attr,
+	&dev_attr_buffer_count.attr,
+	&dev_attr_recover.attr,
+	&dev_attr_performance_stats.attr,
+	&dev_attr_layer2.attr,
+	&dev_attr_large_send.attr,
+	NULL,
+};
+
+static struct attribute_group qeth_device_attr_group = {
+	.attrs = qeth_device_attrs,
+};
+
+static struct attribute *qeth_osn_device_attrs[] = {
+	&dev_attr_state.attr,
+	&dev_attr_chpid.attr,
+	&dev_attr_if_name.attr,
+	&dev_attr_card_type.attr,
+	&dev_attr_buffer_count.attr,
+	&dev_attr_recover.attr,
+	NULL,
+};
+
+static struct attribute_group qeth_osn_device_attr_group = {
+	.attrs = qeth_osn_device_attrs,
+};
+
+int qeth_core_create_device_attributes(struct device *dev)
+{
+	int ret;
+	ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group);
+	if (ret)
+		return ret;
+	ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group);
+	if (ret)
+		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+
+	return 0;
+}
+
+void qeth_core_remove_device_attributes(struct device *dev)
+{
+	sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+	sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
+}
+
+int qeth_core_create_osn_attributes(struct device *dev)
+{
+	return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group);
+}
+
+void qeth_core_remove_osn_attributes(struct device *dev)
+{
+	sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
+	return;
+}
diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h
deleted file mode 100644
index 52910c9..0000000
--- a/drivers/s390/net/qeth_eddp.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * linux/drivers/s390/net/qeth_eddp.h
- *
- * Header file for qeth enhanced device driver packing.
- *
- * Copyright 2004 IBM Corporation
- *
- *    Author(s): Thomas Spatzier <tspat@de.ibm.com>
- *
- */
-#ifndef __QETH_EDDP_H__
-#define __QETH_EDDP_H__
-
-struct qeth_eddp_element {
-	u32 flags;
-	u32 length;
-	void *addr;
-};
-
-struct qeth_eddp_context {
-	atomic_t refcnt;
-	enum qeth_large_send_types type;
-	int num_pages;			    /* # of allocated pages */
-	u8 **pages;			    /* pointers to pages */
-	int offset;			    /* offset in ctx during creation */
-	int num_elements;		    /* # of required 'SBALEs' */
-	struct qeth_eddp_element *elements; /* array of 'SBALEs' */
-	int elements_per_skb;		    /* # of 'SBALEs' per skb **/
-};
-
-struct qeth_eddp_context_reference {
-	struct list_head list;
-	struct qeth_eddp_context *ctx;
-};
-
-extern struct qeth_eddp_context *
-qeth_eddp_create_context(struct qeth_card *,struct sk_buff *,
-			 struct qeth_hdr *, unsigned char);
-
-extern void
-qeth_eddp_put_context(struct qeth_eddp_context *);
-
-extern int
-qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,struct qeth_eddp_context *,int);
-
-extern void
-qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
-
-extern int
-qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
-				    struct qeth_eddp_context *);
-/*
- * Data used for fragmenting a IP packet.
- */
-struct qeth_eddp_data {
-	struct qeth_hdr qh;
-	struct ethhdr mac;
-	__be16 vlan[2];
-	union {
-		struct {
-			struct iphdr h;
-			u8 options[40];
-		} ip4;
-		struct {
-			struct ipv6hdr h;
-		} ip6;
-	} nh;
-	u8 nhl;
-	void *nh_in_ctx;	/* address of nh within the ctx */
-	union {
-		struct {
-			struct tcphdr h;
-			u8 options[40];
-		} tcp;
-	} th;
-	u8 thl;
-	void *th_in_ctx;	/* address of th within the ctx */
-	struct sk_buff *skb;
-	int skb_offset;
-	int frag;
-	int frag_offset;
-} __attribute__ ((packed));
-
-#endif /* __QETH_EDDP_H__ */
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
deleted file mode 100644
index 61faf05..0000000
--- a/drivers/s390/net/qeth_fs.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * linux/drivers/s390/net/qeth_fs.h
- *
- * Linux on zSeries OSA Express and HiperSockets support.
- *
- * This header file contains definitions related to sysfs and procfs.
- *
- * Copyright 2000,2003 IBM Corporation
- * Author(s): Thomas Spatzier <tspat@de.ibm.com>
- *
- */
-#ifndef __QETH_FS_H__
-#define __QETH_FS_H__
-
-#ifdef CONFIG_PROC_FS
-extern int
-qeth_create_procfs_entries(void);
-
-extern void
-qeth_remove_procfs_entries(void);
-#else
-static inline int
-qeth_create_procfs_entries(void)
-{
-	return 0;
-}
-
-static inline void
-qeth_remove_procfs_entries(void)
-{
-}
-#endif /* CONFIG_PROC_FS */
-
-extern int
-qeth_create_device_attributes(struct device *dev);
-
-extern void
-qeth_remove_device_attributes(struct device *dev);
-
-extern int
-qeth_create_device_attributes_osn(struct device *dev);
-
-extern void
-qeth_remove_device_attributes_osn(struct device *dev);
-
-extern int
-qeth_create_driver_attributes(void);
-
-extern void
-qeth_remove_driver_attributes(void);
-
-/*
- * utility functions used in qeth_proc.c and qeth_sys.c
- */
-
-static inline const char *
-qeth_get_checksum_str(struct qeth_card *card)
-{
-	if (card->options.checksum_type == SW_CHECKSUMMING)
-		return "sw";
-	else if (card->options.checksum_type == HW_CHECKSUMMING)
-		return "hw";
-	else
-		return "no";
-}
-
-static inline const char *
-qeth_get_prioq_str(struct qeth_card *card, char *buf)
-{
-	if (card->qdio.do_prio_queueing == QETH_NO_PRIO_QUEUEING)
-		sprintf(buf, "always_q_%i", card->qdio.default_out_queue);
-	else
-		strcpy(buf, (card->qdio.do_prio_queueing ==
-					QETH_PRIO_Q_ING_PREC)?
-				"by_prec." : "by_ToS");
-	return buf;
-}
-
-static inline const char *
-qeth_get_bufsize_str(struct qeth_card *card)
-{
-	if (card->qdio.in_buf_size == 16384)
-		return "16k";
-	else if (card->qdio.in_buf_size == 24576)
-		return "24k";
-	else if (card->qdio.in_buf_size == 32768)
-		return "32k";
-	else if (card->qdio.in_buf_size == 40960)
-		return "40k";
-	else
-		return "64k";
-}
-
-static inline const char *
-qeth_get_cardname(struct qeth_card *card)
-{
- 	if (card->info.guestlan) {
- 		switch (card->info.type) {
- 		case QETH_CARD_TYPE_OSAE:
-			return " Guest LAN QDIO";
- 		case QETH_CARD_TYPE_IQD:
-			return " Guest LAN Hiper";
-		default:
-			return " unknown";
- 		}
-	} else {
-		switch (card->info.type) {
-		case QETH_CARD_TYPE_OSAE:
-			return " OSD Express";
-		case QETH_CARD_TYPE_IQD:
-			return " HiperSockets";
-		case QETH_CARD_TYPE_OSN:
-			return " OSN QDIO";
-		default:
-			return " unknown";
-		}
-	}
-	return " n/a";
-}
-
-/* max length to be returned: 14 */
-static inline const char *
-qeth_get_cardname_short(struct qeth_card *card)
-{
-	if (card->info.guestlan){
-		switch (card->info.type){
-		case QETH_CARD_TYPE_OSAE:
-			return "GuestLAN QDIO";
-		case QETH_CARD_TYPE_IQD:
-			return "GuestLAN Hiper";
-		default:
-			return "unknown";
-		}
-	} else {
-		switch (card->info.type) {
-		case QETH_CARD_TYPE_OSAE:
-			switch (card->info.link_type) {
-			case QETH_LINK_TYPE_FAST_ETH:
-				return "OSD_100";
-			case QETH_LINK_TYPE_HSTR:
-				return "HSTR";
-			case QETH_LINK_TYPE_GBIT_ETH:
-				return "OSD_1000";
-			case QETH_LINK_TYPE_10GBIT_ETH:
-				return "OSD_10GIG";
-			case QETH_LINK_TYPE_LANE_ETH100:
-				return "OSD_FE_LANE";
-			case QETH_LINK_TYPE_LANE_TR:
-				return "OSD_TR_LANE";
-			case QETH_LINK_TYPE_LANE_ETH1000:
-				return "OSD_GbE_LANE";
-			case QETH_LINK_TYPE_LANE:
-				return "OSD_ATM_LANE";
-			default:
-				return "OSD_Express";
-			}
-		case QETH_CARD_TYPE_IQD:
-			return "HiperSockets";
-		case QETH_CARD_TYPE_OSN:
-			return "OSN";
-		default:
-			return "unknown";
-		}
-	}
-	return "n/a";
-}
-
-#endif /* __QETH_FS_H__ */
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
new file mode 100644
index 0000000..4417a36
--- /dev/null
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -0,0 +1,1242 @@
+/*
+ *  drivers/s390/net/qeth_l2_main.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
+ *		 Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/ip.h>
+
+#include <asm/s390_rdev.h>
+
+#include "qeth_core.h"
+#include "qeth_core_offl.h"
+
+#define QETH_DBF_TEXT_(name, level, text...) \
+	do { \
+		if (qeth_dbf_passes(qeth_dbf_##name, level)) { \
+			char *dbf_txt_buf = get_cpu_var(qeth_l2_dbf_txt_buf); \
+			sprintf(dbf_txt_buf, text); \
+			debug_text_event(qeth_dbf_##name, level, dbf_txt_buf); \
+			put_cpu_var(qeth_l2_dbf_txt_buf); \
+		} \
+	} while (0)
+
+static DEFINE_PER_CPU(char[256], qeth_l2_dbf_txt_buf);
+
+static int qeth_l2_set_offline(struct ccwgroup_device *);
+static int qeth_l2_stop(struct net_device *);
+static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
+static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *,
+			   enum qeth_ipa_cmds,
+			   int (*reply_cb) (struct qeth_card *,
+					    struct qeth_reply*,
+					    unsigned long));
+static void qeth_l2_set_multicast_list(struct net_device *);
+static int qeth_l2_recover(void *);
+
+static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	struct mii_ioctl_data *mii_data;
+	int rc = 0;
+
+	if (!card)
+		return -ENODEV;
+
+	if ((card->state != CARD_STATE_UP) &&
+		(card->state != CARD_STATE_SOFTSETUP))
+		return -ENODEV;
+
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return -EPERM;
+
+	switch (cmd) {
+	case SIOC_QETH_ADP_SET_SNMP_CONTROL:
+		rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
+		break;
+	case SIOC_QETH_GET_CARD_TYPE:
+		if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
+		    !card->info.guestlan)
+			return 1;
+		return 0;
+		break;
+	case SIOCGMIIPHY:
+		mii_data = if_mii(rq);
+		mii_data->phy_id = 0;
+		break;
+	case SIOCGMIIREG:
+		mii_data = if_mii(rq);
+		if (mii_data->phy_id != 0)
+			rc = -EINVAL;
+		else
+			mii_data->val_out = qeth_mdio_read(dev,
+				mii_data->phy_id, mii_data->reg_num);
+		break;
+	default:
+		rc = -EOPNOTSUPP;
+	}
+	if (rc)
+		QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
+	return rc;
+}
+
+static int qeth_l2_verify_dev(struct net_device *dev)
+{
+	struct qeth_card *card;
+	unsigned long flags;
+	int rc = 0;
+
+	read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
+	list_for_each_entry(card, &qeth_core_card_list.list, list) {
+		if (card->dev == dev) {
+			rc = QETH_REAL_CARD;
+			break;
+		}
+	}
+	read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
+
+	return rc;
+}
+
+static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
+{
+	struct qeth_card *card;
+	struct net_device *ndev;
+	unsigned char *readno;
+	__u16 temp_dev_no, card_dev_no;
+	char *endp;
+	unsigned long flags;
+
+	ndev = NULL;
+	memcpy(&temp_dev_no, read_dev_no, 2);
+	read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
+	list_for_each_entry(card, &qeth_core_card_list.list, list) {
+		readno = CARD_RDEV_ID(card);
+		readno += (strlen(readno) - 4);
+		card_dev_no = simple_strtoul(readno, &endp, 16);
+		if (card_dev_no == temp_dev_no) {
+			ndev = card->dev;
+			break;
+		}
+	}
+	read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
+	return ndev;
+}
+
+static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card,
+				struct qeth_reply *reply,
+				unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+	__u8 *mac;
+
+	QETH_DBF_TEXT(trace, 2, "L2Sgmacb");
+	cmd = (struct qeth_ipa_cmd *) data;
+	mac = &cmd->data.setdelmac.mac[0];
+	/* MAC already registered, needed in couple/uncouple case */
+	if (cmd->hdr.return_code == 0x2005) {
+		PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \
+			  "already existing on %s \n",
+			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+			  QETH_CARD_IFNAME(card));
+		cmd->hdr.return_code = 0;
+	}
+	if (cmd->hdr.return_code)
+		PRINT_ERR("Could not set group MAC " \
+			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
+			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+	return 0;
+}
+
+static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
+{
+	QETH_DBF_TEXT(trace, 2, "L2Sgmac");
+	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
+					  qeth_l2_send_setgroupmac_cb);
+}
+
+static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card,
+				struct qeth_reply *reply,
+				unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+	__u8 *mac;
+
+	QETH_DBF_TEXT(trace, 2, "L2Dgmacb");
+	cmd = (struct qeth_ipa_cmd *) data;
+	mac = &cmd->data.setdelmac.mac[0];
+	if (cmd->hdr.return_code)
+		PRINT_ERR("Could not delete group MAC " \
+			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
+			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+	return 0;
+}
+
+static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
+{
+	QETH_DBF_TEXT(trace, 2, "L2Dgmac");
+	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
+					  qeth_l2_send_delgroupmac_cb);
+}
+
+static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac)
+{
+	struct qeth_mc_mac *mc;
+
+	mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC);
+
+	if (!mc) {
+		PRINT_ERR("no mem vor mc mac address\n");
+		return;
+	}
+
+	memcpy(mc->mc_addr, mac, OSA_ADDR_LEN);
+	mc->mc_addrlen = OSA_ADDR_LEN;
+
+	if (!qeth_l2_send_setgroupmac(card, mac))
+		list_add_tail(&mc->list, &card->mc_list);
+	else
+		kfree(mc);
+}
+
+static void qeth_l2_del_all_mc(struct qeth_card *card)
+{
+	struct qeth_mc_mac *mc, *tmp;
+
+	spin_lock_bh(&card->mclock);
+	list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
+		qeth_l2_send_delgroupmac(card, mc->mc_addr);
+		list_del(&mc->list);
+		kfree(mc);
+	}
+	spin_unlock_bh(&card->mclock);
+}
+
+static void qeth_l2_get_packet_type(struct qeth_card *card,
+			struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+	__u16 hdr_mac;
+
+	if (!memcmp(skb->data + QETH_HEADER_SIZE,
+		    skb->dev->broadcast, 6)) {
+		/* broadcast? */
+		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
+		return;
+	}
+	hdr_mac = *((__u16 *)skb->data);
+	/* tr multicast? */
+	switch (card->info.link_type) {
+	case QETH_LINK_TYPE_HSTR:
+	case QETH_LINK_TYPE_LANE_TR:
+		if ((hdr_mac == QETH_TR_MAC_NC) ||
+		    (hdr_mac == QETH_TR_MAC_C))
+			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
+		else
+			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
+		break;
+		/* eth or so multicast? */
+	default:
+		if ((hdr_mac == QETH_ETH_MAC_V4) ||
+		     (hdr_mac == QETH_ETH_MAC_V6))
+			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
+		else
+			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
+	}
+}
+
+static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+			struct sk_buff *skb, int ipv, int cast_type)
+{
+	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)((skb->data) +
+					QETH_HEADER_SIZE);
+
+	memset(hdr, 0, sizeof(struct qeth_hdr));
+	hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
+
+	/* set byte byte 3 to casting flags */
+	if (cast_type == RTN_MULTICAST)
+		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
+	else if (cast_type == RTN_BROADCAST)
+		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
+	else
+		qeth_l2_get_packet_type(card, hdr, skb);
+
+	hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
+	/* VSWITCH relies on the VLAN
+	 * information to be present in
+	 * the QDIO header */
+	if (veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
+		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_VLAN;
+		hdr->hdr.l2.vlan_id = ntohs(veth->h_vlan_TCI);
+	}
+}
+
+static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
+			struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code) {
+		PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+			  "Continuing\n", cmd->data.setdelvlan.vlan_id,
+			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
+		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+	}
+	return 0;
+}
+
+static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
+				enum qeth_ipa_cmds ipacmd)
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT_(trace, 4, "L2sdv%x", ipacmd);
+	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	cmd->data.setdelvlan.vlan_id = i;
+	return qeth_send_ipa_cmd(card, iob,
+				 qeth_l2_send_setdelvlan_cb, NULL);
+}
+
+static void qeth_l2_process_vlans(struct qeth_card *card, int clear)
+{
+	struct qeth_vlan_vid *id;
+	QETH_DBF_TEXT(trace, 3, "L2prcvln");
+	spin_lock_bh(&card->vlanlock);
+	list_for_each_entry(id, &card->vid_list, list) {
+		if (clear)
+			qeth_l2_send_setdelvlan(card, id->vid,
+				IPA_CMD_DELVLAN);
+		else
+			qeth_l2_send_setdelvlan(card, id->vid,
+				IPA_CMD_SETVLAN);
+	}
+	spin_unlock_bh(&card->vlanlock);
+}
+
+static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	struct qeth_vlan_vid *id;
+
+	QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
+	id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC);
+	if (id) {
+		id->vid = vid;
+		qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
+		spin_lock_bh(&card->vlanlock);
+		list_add_tail(&id->list, &card->vid_list);
+		spin_unlock_bh(&card->vlanlock);
+	} else {
+		PRINT_ERR("no memory for vid\n");
+	}
+}
+
+static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+	struct qeth_vlan_vid *id, *tmpid = NULL;
+	struct qeth_card *card = netdev_priv(dev);
+
+	QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
+	spin_lock_bh(&card->vlanlock);
+	list_for_each_entry(id, &card->vid_list, list) {
+		if (id->vid == vid) {
+			list_del(&id->list);
+			tmpid = id;
+			break;
+		}
+	}
+	spin_unlock_bh(&card->vlanlock);
+	if (tmpid) {
+		qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
+		kfree(tmpid);
+	}
+	qeth_l2_set_multicast_list(card->dev);
+}
+
+static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(setup , 2, "stopcard");
+	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+
+	qeth_set_allowed_threads(card, 0, 1);
+	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
+		return -ERESTARTSYS;
+	if (card->read.state == CH_STATE_UP &&
+	    card->write.state == CH_STATE_UP &&
+	    (card->state == CARD_STATE_UP)) {
+		if (recovery_mode &&
+		    card->info.type != QETH_CARD_TYPE_OSN) {
+			qeth_l2_stop(card->dev);
+		} else {
+			rtnl_lock();
+			dev_close(card->dev);
+			rtnl_unlock();
+		}
+		if (!card->use_hard_stop) {
+			__u8 *mac = &card->dev->dev_addr[0];
+			rc = qeth_l2_send_delmac(card, mac);
+			QETH_DBF_TEXT_(setup, 2, "Lerr%d", rc);
+		}
+		card->state = CARD_STATE_SOFTSETUP;
+	}
+	if (card->state == CARD_STATE_SOFTSETUP) {
+		qeth_l2_process_vlans(card, 1);
+		qeth_l2_del_all_mc(card);
+		qeth_clear_ipacmd_list(card);
+		card->state = CARD_STATE_HARDSETUP;
+	}
+	if (card->state == CARD_STATE_HARDSETUP) {
+		qeth_qdio_clear_card(card, 0);
+		qeth_clear_qdio_buffers(card);
+		qeth_clear_working_pool_list(card);
+		card->state = CARD_STATE_DOWN;
+	}
+	if (card->state == CARD_STATE_DOWN) {
+		qeth_clear_cmd_buffers(&card->read);
+		qeth_clear_cmd_buffers(&card->write);
+	}
+	card->use_hard_stop = 0;
+	return rc;
+}
+
+static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
+			    struct qeth_qdio_buffer *buf, int index)
+{
+	struct qdio_buffer_element *element;
+	struct sk_buff *skb;
+	struct qeth_hdr *hdr;
+	int offset;
+	unsigned int len;
+
+	/* get first element of current buffer */
+	element = (struct qdio_buffer_element *)&buf->buffer->element[0];
+	offset = 0;
+	if (card->options.performance_stats)
+		card->perf_stats.bufs_rec++;
+	while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
+				       &offset, &hdr))) {
+		skb->dev = card->dev;
+		/* is device UP ? */
+		if (!(card->dev->flags & IFF_UP)) {
+			dev_kfree_skb_any(skb);
+			continue;
+		}
+
+		switch (hdr->hdr.l2.id) {
+		case QETH_HEADER_TYPE_LAYER2:
+			skb->pkt_type = PACKET_HOST;
+			skb->protocol = eth_type_trans(skb, skb->dev);
+			if (card->options.checksum_type == NO_CHECKSUMMING)
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			else
+				skb->ip_summed = CHECKSUM_NONE;
+			*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
+			len = skb->len;
+			netif_rx(skb);
+			break;
+		case QETH_HEADER_TYPE_OSN:
+			skb_push(skb, sizeof(struct qeth_hdr));
+			skb_copy_to_linear_data(skb, hdr,
+						sizeof(struct qeth_hdr));
+			len = skb->len;
+			card->osn_info.data_cb(skb);
+			break;
+		default:
+			dev_kfree_skb_any(skb);
+			QETH_DBF_TEXT(trace, 3, "inbunkno");
+			QETH_DBF_HEX(control, 3, hdr, QETH_DBF_CONTROL_LEN);
+			continue;
+		}
+		card->dev->last_rx = jiffies;
+		card->stats.rx_packets++;
+		card->stats.rx_bytes += len;
+	}
+}
+
+static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
+			   enum qeth_ipa_cmds ipacmd,
+			   int (*reply_cb) (struct qeth_card *,
+					    struct qeth_reply*,
+					    unsigned long))
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(trace, 2, "L2sdmac");
+	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
+	memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
+	return qeth_send_ipa_cmd(card, iob, reply_cb, NULL);
+}
+
+static int qeth_l2_send_setmac_cb(struct qeth_card *card,
+			   struct qeth_reply *reply,
+			   unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 2, "L2Smaccb");
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code) {
+		QETH_DBF_TEXT_(trace, 2, "L2er%x", cmd->hdr.return_code);
+		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+		cmd->hdr.return_code = -EIO;
+	} else {
+		card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
+		memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac,
+		       OSA_ADDR_LEN);
+		PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
+			   "successfully registered on device %s\n",
+			   card->dev->dev_addr[0], card->dev->dev_addr[1],
+			   card->dev->dev_addr[2], card->dev->dev_addr[3],
+			   card->dev->dev_addr[4], card->dev->dev_addr[5],
+			   card->dev->name);
+	}
+	return 0;
+}
+
+static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
+{
+	QETH_DBF_TEXT(trace, 2, "L2Setmac");
+	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
+					  qeth_l2_send_setmac_cb);
+}
+
+static int qeth_l2_send_delmac_cb(struct qeth_card *card,
+			   struct qeth_reply *reply,
+			   unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 2, "L2Dmaccb");
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code) {
+		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+		cmd->hdr.return_code = -EIO;
+		return 0;
+	}
+	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+
+	return 0;
+}
+
+static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
+{
+	QETH_DBF_TEXT(trace, 2, "L2Delmac");
+	if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
+		return 0;
+	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
+					  qeth_l2_send_delmac_cb);
+}
+
+static int qeth_l2_request_initial_mac(struct qeth_card *card)
+{
+	int rc = 0;
+	char vendor_pre[] = {0x02, 0x00, 0x00};
+
+	QETH_DBF_TEXT(setup, 2, "doL2init");
+	QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
+
+	rc = qeth_query_setadapterparms(card);
+	if (rc) {
+		PRINT_WARN("could not query adapter parameters on device %s: "
+			   "x%x\n", CARD_BUS_ID(card), rc);
+	}
+
+	if (card->info.guestlan) {
+		rc = qeth_setadpparms_change_macaddr(card);
+		if (rc) {
+			PRINT_WARN("couldn't get MAC address on "
+			   "device %s: x%x\n",
+			   CARD_BUS_ID(card), rc);
+			QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+			return rc;
+		}
+		QETH_DBF_HEX(setup, 2, card->dev->dev_addr, OSA_ADDR_LEN);
+	} else {
+		random_ether_addr(card->dev->dev_addr);
+		memcpy(card->dev->dev_addr, vendor_pre, 3);
+	}
+	return 0;
+}
+
+static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+	struct qeth_card *card = netdev_priv(dev);
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "setmac");
+
+	if (qeth_l2_verify_dev(dev) != QETH_REAL_CARD) {
+		QETH_DBF_TEXT(trace, 3, "setmcINV");
+		return -EOPNOTSUPP;
+	}
+
+	if (card->info.type == QETH_CARD_TYPE_OSN) {
+		PRINT_WARN("Setting MAC address on %s is not supported.\n",
+			   dev->name);
+		QETH_DBF_TEXT(trace, 3, "setmcOSN");
+		return -EOPNOTSUPP;
+	}
+	QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
+	QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
+	rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
+	if (!rc)
+		rc = qeth_l2_send_setmac(card, addr->sa_data);
+	return rc;
+}
+
+static void qeth_l2_set_multicast_list(struct net_device *dev)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	struct dev_mc_list *dm;
+
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return ;
+
+	QETH_DBF_TEXT(trace, 3, "setmulti");
+	qeth_l2_del_all_mc(card);
+	spin_lock_bh(&card->mclock);
+	for (dm = dev->mc_list; dm; dm = dm->next)
+		qeth_l2_add_mc(card, dm->dmi_addr);
+	spin_unlock_bh(&card->mclock);
+	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+		return;
+	qeth_setadp_promisc_mode(card);
+}
+
+static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int rc;
+	struct qeth_hdr *hdr = NULL;
+	int elements = 0;
+	struct qeth_card *card = netdev_priv(dev);
+	struct sk_buff *new_skb = skb;
+	int ipv = qeth_get_ip_version(skb);
+	int cast_type = qeth_get_cast_type(card, skb);
+	struct qeth_qdio_out_q *queue = card->qdio.out_qs
+		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
+	int tx_bytes = skb->len;
+	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
+	struct qeth_eddp_context *ctx = NULL;
+
+	QETH_DBF_TEXT(trace, 6, "l2xmit");
+
+	if ((card->state != CARD_STATE_UP) || !card->lan_online) {
+		card->stats.tx_carrier_errors++;
+		goto tx_drop;
+	}
+
+	if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+	    (skb->protocol == htons(ETH_P_IPV6)))
+		goto tx_drop;
+
+	if (card->options.performance_stats) {
+		card->perf_stats.outbound_cnt++;
+		card->perf_stats.outbound_start_time = qeth_get_micros();
+	}
+	netif_stop_queue(dev);
+
+	if (skb_is_gso(skb))
+		large_send = QETH_LARGE_SEND_EDDP;
+
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		hdr = (struct qeth_hdr *)skb->data;
+	else {
+		new_skb = qeth_prepare_skb(card, skb, &hdr);
+		if (!new_skb)
+			goto tx_drop;
+		qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type);
+	}
+
+	if (large_send == QETH_LARGE_SEND_EDDP) {
+		ctx = qeth_eddp_create_context(card, new_skb, hdr,
+						skb->sk->sk_protocol);
+		if (ctx == NULL) {
+			PRINT_WARN("could not create eddp context\n");
+			goto tx_drop;
+		}
+	} else {
+		elements = qeth_get_elements_no(card, (void *)hdr, new_skb, 0);
+		if (!elements)
+			goto tx_drop;
+	}
+
+	if ((large_send == QETH_LARGE_SEND_NO) &&
+	    (skb->ip_summed == CHECKSUM_PARTIAL))
+		qeth_tx_csum(new_skb);
+
+	if (card->info.type != QETH_CARD_TYPE_IQD)
+		rc = qeth_do_send_packet(card, queue, new_skb, hdr,
+					 elements, ctx);
+	else
+		rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
+					      elements, ctx);
+	if (!rc) {
+		card->stats.tx_packets++;
+		card->stats.tx_bytes += tx_bytes;
+		if (new_skb != skb)
+			dev_kfree_skb_any(skb);
+		if (card->options.performance_stats) {
+			if (large_send != QETH_LARGE_SEND_NO) {
+				card->perf_stats.large_send_bytes += tx_bytes;
+				card->perf_stats.large_send_cnt++;
+			}
+			if (skb_shinfo(new_skb)->nr_frags > 0) {
+				card->perf_stats.sg_skbs_sent++;
+				/* nr_frags + skb->data */
+				card->perf_stats.sg_frags_sent +=
+					skb_shinfo(new_skb)->nr_frags + 1;
+			}
+		}
+
+		if (ctx != NULL) {
+			qeth_eddp_put_context(ctx);
+			dev_kfree_skb_any(new_skb);
+		}
+	} else {
+		if (ctx != NULL)
+			qeth_eddp_put_context(ctx);
+
+		if (rc == -EBUSY) {
+			if (new_skb != skb)
+				dev_kfree_skb_any(new_skb);
+			return NETDEV_TX_BUSY;
+		} else
+			goto tx_drop;
+	}
+
+	netif_wake_queue(dev);
+	if (card->options.performance_stats)
+		card->perf_stats.outbound_time += qeth_get_micros() -
+			card->perf_stats.outbound_start_time;
+	return rc;
+
+tx_drop:
+	card->stats.tx_dropped++;
+	card->stats.tx_errors++;
+	if ((new_skb != skb) && new_skb)
+		dev_kfree_skb_any(new_skb);
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
+			unsigned int status, unsigned int qdio_err,
+			unsigned int siga_err, unsigned int queue,
+			int first_element, int count, unsigned long card_ptr)
+{
+	struct net_device *net_dev;
+	struct qeth_card *card;
+	struct qeth_qdio_buffer *buffer;
+	int index;
+	int i;
+
+	QETH_DBF_TEXT(trace, 6, "qdinput");
+	card = (struct qeth_card *) card_ptr;
+	net_dev = card->dev;
+	if (card->options.performance_stats) {
+		card->perf_stats.inbound_cnt++;
+		card->perf_stats.inbound_start_time = qeth_get_micros();
+	}
+	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
+			QETH_DBF_TEXT(trace, 1, "qdinchk");
+			QETH_DBF_TEXT_(trace, 1, "%s", CARD_BUS_ID(card));
+			QETH_DBF_TEXT_(trace, 1, "%04X%04X", first_element,
+					count);
+			QETH_DBF_TEXT_(trace, 1, "%04X%04X", queue, status);
+			qeth_schedule_recovery(card);
+			return;
+		}
+	}
+	for (i = first_element; i < (first_element + count); ++i) {
+		index = i % QDIO_MAX_BUFFERS_PER_Q;
+		buffer = &card->qdio.in_q->bufs[index];
+		if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
+		      qeth_check_qdio_errors(buffer->buffer,
+					     qdio_err, siga_err, "qinerr")))
+			qeth_l2_process_inbound_buffer(card, buffer, index);
+		/* clear buffer and give back to hardware */
+		qeth_put_buffer_pool_entry(card, buffer->pool_entry);
+		qeth_queue_input_buffer(card, index);
+	}
+	if (card->options.performance_stats)
+		card->perf_stats.inbound_time += qeth_get_micros() -
+			card->perf_stats.inbound_start_time;
+}
+
+static int qeth_l2_open(struct net_device *dev)
+{
+	struct qeth_card *card = netdev_priv(dev);
+
+	QETH_DBF_TEXT(trace, 4, "qethopen");
+	if (card->state != CARD_STATE_SOFTSETUP)
+		return -ENODEV;
+
+	if ((card->info.type != QETH_CARD_TYPE_OSN) &&
+	     (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
+		QETH_DBF_TEXT(trace, 4, "nomacadr");
+		return -EPERM;
+	}
+	card->data.state = CH_STATE_UP;
+	card->state = CARD_STATE_UP;
+	card->dev->flags |= IFF_UP;
+	netif_start_queue(dev);
+
+	if (!card->lan_online && netif_carrier_ok(dev))
+		netif_carrier_off(dev);
+	return 0;
+}
+
+
+static int qeth_l2_stop(struct net_device *dev)
+{
+	struct qeth_card *card = netdev_priv(dev);
+
+	QETH_DBF_TEXT(trace, 4, "qethstop");
+	netif_tx_disable(dev);
+	card->dev->flags &= ~IFF_UP;
+	if (card->state == CARD_STATE_UP)
+		card->state = CARD_STATE_SOFTSETUP;
+	return 0;
+}
+
+static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+
+	INIT_LIST_HEAD(&card->vid_list);
+	INIT_LIST_HEAD(&card->mc_list);
+	card->options.layer2 = 1;
+	card->discipline.input_handler = (qdio_handler_t *)
+		qeth_l2_qdio_input_handler;
+	card->discipline.output_handler = (qdio_handler_t *)
+		qeth_qdio_output_handler;
+	card->discipline.recover = qeth_l2_recover;
+	return 0;
+}
+
+static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
+
+	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+
+	if (cgdev->state == CCWGROUP_ONLINE) {
+		card->use_hard_stop = 1;
+		qeth_l2_set_offline(cgdev);
+	}
+
+	if (card->dev) {
+		unregister_netdev(card->dev);
+		card->dev = NULL;
+	}
+
+	qeth_l2_del_all_mc(card);
+	return;
+}
+
+static struct ethtool_ops qeth_l2_ethtool_ops = {
+	.get_link = ethtool_op_get_link,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_hw_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = ethtool_op_set_tso,
+	.get_strings = qeth_core_get_strings,
+	.get_ethtool_stats = qeth_core_get_ethtool_stats,
+	.get_stats_count = qeth_core_get_stats_count,
+	.get_drvinfo = qeth_core_get_drvinfo,
+};
+
+static struct ethtool_ops qeth_l2_osn_ops = {
+	.get_strings = qeth_core_get_strings,
+	.get_ethtool_stats = qeth_core_get_ethtool_stats,
+	.get_stats_count = qeth_core_get_stats_count,
+	.get_drvinfo = qeth_core_get_drvinfo,
+};
+
+static int qeth_l2_setup_netdev(struct qeth_card *card)
+{
+	switch (card->info.type) {
+	case QETH_CARD_TYPE_OSAE:
+		card->dev = alloc_etherdev(0);
+		break;
+	case QETH_CARD_TYPE_IQD:
+		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
+		break;
+	case QETH_CARD_TYPE_OSN:
+		card->dev = alloc_netdev(0, "osn%d", ether_setup);
+		card->dev->flags |= IFF_NOARP;
+		break;
+	default:
+		card->dev = alloc_etherdev(0);
+	}
+
+	if (!card->dev)
+		return -ENODEV;
+
+	card->dev->priv = card;
+	card->dev->tx_timeout = &qeth_tx_timeout;
+	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
+	card->dev->open = qeth_l2_open;
+	card->dev->stop = qeth_l2_stop;
+	card->dev->hard_start_xmit = qeth_l2_hard_start_xmit;
+	card->dev->do_ioctl = qeth_l2_do_ioctl;
+	card->dev->get_stats = qeth_get_stats;
+	card->dev->change_mtu = qeth_change_mtu;
+	card->dev->set_multicast_list = qeth_l2_set_multicast_list;
+	card->dev->vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid;
+	card->dev->vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid;
+	card->dev->set_mac_address = qeth_l2_set_mac_address;
+	card->dev->mtu = card->info.initial_mtu;
+	if (card->info.type != QETH_CARD_TYPE_OSN)
+		SET_ETHTOOL_OPS(card->dev, &qeth_l2_ethtool_ops);
+	else
+		SET_ETHTOOL_OPS(card->dev, &qeth_l2_osn_ops);
+	card->dev->features |= NETIF_F_HW_VLAN_FILTER;
+	card->info.broadcast_capable = 1;
+	qeth_l2_request_initial_mac(card);
+	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+	return register_netdev(card->dev);
+}
+
+static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	int rc = 0;
+	enum qeth_card_states recover_flag;
+
+	BUG_ON(!card);
+	QETH_DBF_TEXT(setup, 2, "setonlin");
+	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+
+	qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
+	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) {
+		PRINT_WARN("set_online of card %s interrupted by user!\n",
+			   CARD_BUS_ID(card));
+		return -ERESTARTSYS;
+	}
+
+	recover_flag = card->state;
+	rc = ccw_device_set_online(CARD_RDEV(card));
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return -EIO;
+	}
+	rc = ccw_device_set_online(CARD_WDEV(card));
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return -EIO;
+	}
+	rc = ccw_device_set_online(CARD_DDEV(card));
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return -EIO;
+	}
+
+	rc = qeth_core_hardsetup_card(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		goto out_remove;
+	}
+
+	if (!card->dev && qeth_l2_setup_netdev(card))
+		goto out_remove;
+
+	if (card->info.type != QETH_CARD_TYPE_OSN)
+		qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
+
+	card->state = CARD_STATE_HARDSETUP;
+	qeth_print_status_message(card);
+
+	/* softsetup */
+	QETH_DBF_TEXT(setup, 2, "softsetp");
+
+	rc = qeth_send_startlan(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		if (rc == 0xe080) {
+			PRINT_WARN("LAN on card %s if offline! "
+				   "Waiting for STARTLAN from card.\n",
+				   CARD_BUS_ID(card));
+			card->lan_online = 0;
+		}
+		return rc;
+	} else
+		card->lan_online = 1;
+
+	if (card->info.type != QETH_CARD_TYPE_OSN) {
+		qeth_set_large_send(card, card->options.large_send);
+		qeth_l2_process_vlans(card, 0);
+	}
+
+	netif_tx_disable(card->dev);
+
+	rc = qeth_init_qdio_queues(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+		goto out_remove;
+	}
+	card->state = CARD_STATE_SOFTSETUP;
+	netif_carrier_on(card->dev);
+
+	qeth_set_allowed_threads(card, 0xffffffff, 0);
+	if (recover_flag == CARD_STATE_RECOVER) {
+		if (recovery_mode &&
+		    card->info.type != QETH_CARD_TYPE_OSN) {
+			qeth_l2_open(card->dev);
+		} else {
+			rtnl_lock();
+			dev_open(card->dev);
+			rtnl_unlock();
+		}
+		/* this also sets saved unicast addresses */
+		qeth_l2_set_multicast_list(card->dev);
+	}
+	/* let user_space know that device is online */
+	kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
+	return 0;
+out_remove:
+	card->use_hard_stop = 1;
+	qeth_l2_stop_card(card, 0);
+	ccw_device_set_offline(CARD_DDEV(card));
+	ccw_device_set_offline(CARD_WDEV(card));
+	ccw_device_set_offline(CARD_RDEV(card));
+	if (recover_flag == CARD_STATE_RECOVER)
+		card->state = CARD_STATE_RECOVER;
+	else
+		card->state = CARD_STATE_DOWN;
+	return -ENODEV;
+}
+
+static int qeth_l2_set_online(struct ccwgroup_device *gdev)
+{
+	return __qeth_l2_set_online(gdev, 0);
+}
+
+static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
+					int recovery_mode)
+{
+	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
+	int rc = 0, rc2 = 0, rc3 = 0;
+	enum qeth_card_states recover_flag;
+
+	QETH_DBF_TEXT(setup, 3, "setoffl");
+	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+
+	if (card->dev && netif_carrier_ok(card->dev))
+		netif_carrier_off(card->dev);
+	recover_flag = card->state;
+	if (qeth_l2_stop_card(card, recovery_mode) == -ERESTARTSYS) {
+		PRINT_WARN("Stopping card %s interrupted by user!\n",
+			   CARD_BUS_ID(card));
+		return -ERESTARTSYS;
+	}
+	rc  = ccw_device_set_offline(CARD_DDEV(card));
+	rc2 = ccw_device_set_offline(CARD_WDEV(card));
+	rc3 = ccw_device_set_offline(CARD_RDEV(card));
+	if (!rc)
+		rc = (rc2) ? rc2 : rc3;
+	if (rc)
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+	if (recover_flag == CARD_STATE_UP)
+		card->state = CARD_STATE_RECOVER;
+	/* let user_space know that device is offline */
+	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
+	return 0;
+}
+
+static int qeth_l2_set_offline(struct ccwgroup_device *cgdev)
+{
+	return __qeth_l2_set_offline(cgdev, 0);
+}
+
+static int qeth_l2_recover(void *ptr)
+{
+	struct qeth_card *card;
+	int rc = 0;
+
+	card = (struct qeth_card *) ptr;
+	QETH_DBF_TEXT(trace, 2, "recover1");
+	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
+		return 0;
+	QETH_DBF_TEXT(trace, 2, "recover2");
+	PRINT_WARN("Recovery of device %s started ...\n",
+		   CARD_BUS_ID(card));
+	card->use_hard_stop = 1;
+	__qeth_l2_set_offline(card->gdev, 1);
+	rc = __qeth_l2_set_online(card->gdev, 1);
+	/* don't run another scheduled recovery */
+	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
+	if (!rc)
+		PRINT_INFO("Device %s successfully recovered!\n",
+			   CARD_BUS_ID(card));
+	else
+		PRINT_INFO("Device %s could not be recovered!\n",
+			   CARD_BUS_ID(card));
+	return 0;
+}
+
+static int __init qeth_l2_init(void)
+{
+	PRINT_INFO("register layer 2 discipline\n");
+	return 0;
+}
+
+static void __exit qeth_l2_exit(void)
+{
+	PRINT_INFO("unregister layer 2 discipline\n");
+}
+
+static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	qeth_qdio_clear_card(card, 0);
+	qeth_clear_qdio_buffers(card);
+}
+
+struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
+	.probe = qeth_l2_probe_device,
+	.remove = qeth_l2_remove_device,
+	.set_online = qeth_l2_set_online,
+	.set_offline = qeth_l2_set_offline,
+	.shutdown = qeth_l2_shutdown,
+};
+EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver);
+
+static int qeth_osn_send_control_data(struct qeth_card *card, int len,
+			   struct qeth_cmd_buffer *iob)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 5, "osndctrd");
+
+	wait_event(card->wait_q,
+		   atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+	qeth_prepare_control_data(card, len, iob);
+	QETH_DBF_TEXT(trace, 6, "osnoirqp");
+	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+			      (addr_t) iob, 0, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+	if (rc) {
+		PRINT_WARN("qeth_osn_send_control_data: "
+			   "ccw_device_start rc = %i\n", rc);
+		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+		qeth_release_buffer(iob->channel, iob);
+		atomic_set(&card->write.irq_pending, 0);
+		wake_up(&card->wait_q);
+	}
+	return rc;
+}
+
+static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
+			struct qeth_cmd_buffer *iob, int data_len)
+{
+	u16 s1, s2;
+
+	QETH_DBF_TEXT(trace, 4, "osndipa");
+
+	qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+	s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+	s2 = (u16)data_len;
+	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+	return qeth_osn_send_control_data(card, s1, iob);
+}
+
+int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
+{
+	struct qeth_cmd_buffer *iob;
+	struct qeth_card *card;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 2, "osnsdmc");
+	if (!dev)
+		return -ENODEV;
+	card = netdev_priv(dev);
+	if (!card)
+		return -ENODEV;
+	if ((card->state != CARD_STATE_UP) &&
+	    (card->state != CARD_STATE_SOFTSETUP))
+		return -ENODEV;
+	iob = qeth_wait_for_buffer(&card->write);
+	memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+	rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+	return rc;
+}
+EXPORT_SYMBOL(qeth_osn_assist);
+
+int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
+		  int (*assist_cb)(struct net_device *, void *),
+		  int (*data_cb)(struct sk_buff *))
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT(trace, 2, "osnreg");
+	*dev = qeth_l2_netdev_by_devno(read_dev_no);
+	if (*dev == NULL)
+		return -ENODEV;
+	card = netdev_priv(*dev);
+	if (!card)
+		return -ENODEV;
+	if ((assist_cb == NULL) || (data_cb == NULL))
+		return -EINVAL;
+	card->osn_info.assist_cb = assist_cb;
+	card->osn_info.data_cb = data_cb;
+	return 0;
+}
+EXPORT_SYMBOL(qeth_osn_register);
+
+void qeth_osn_deregister(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT(trace, 2, "osndereg");
+	if (!dev)
+		return;
+	card = netdev_priv(dev);
+	if (!card)
+		return;
+	card->osn_info.assist_cb = NULL;
+	card->osn_info.data_cb = NULL;
+	return;
+}
+EXPORT_SYMBOL(qeth_osn_deregister);
+
+module_init(qeth_l2_init);
+module_exit(qeth_l2_exit);
+MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
+MODULE_DESCRIPTION("qeth layer 2 discipline");
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h
new file mode 100644
index 0000000..f639cc3
--- /dev/null
+++ b/drivers/s390/net/qeth_l3.h
@@ -0,0 +1,76 @@
+/*
+ *  drivers/s390/net/qeth_l3.h
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
+ *		 Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#ifndef __QETH_L3_H__
+#define __QETH_L3_H__
+
+#include "qeth_core.h"
+
+#define QETH_DBF_TEXT_(name, level, text...) \
+	do { \
+		if (qeth_dbf_passes(qeth_dbf_##name, level)) { \
+			char *dbf_txt_buf = get_cpu_var(qeth_l3_dbf_txt_buf); \
+			sprintf(dbf_txt_buf, text); \
+			debug_text_event(qeth_dbf_##name, level, dbf_txt_buf); \
+			put_cpu_var(qeth_l3_dbf_txt_buf); \
+		} \
+	} while (0)
+
+DECLARE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
+
+struct qeth_ipaddr {
+	struct list_head entry;
+	enum qeth_ip_types type;
+	enum qeth_ipa_setdelip_flags set_flags;
+	enum qeth_ipa_setdelip_flags del_flags;
+	int is_multicast;
+	int users;
+	enum qeth_prot_versions proto;
+	unsigned char mac[OSA_ADDR_LEN];
+	union {
+		struct {
+			unsigned int addr;
+			unsigned int mask;
+		} a4;
+		struct {
+			struct in6_addr addr;
+			unsigned int pfxlen;
+		} a6;
+	} u;
+};
+
+struct qeth_ipato_entry {
+	struct list_head entry;
+	enum qeth_prot_versions proto;
+	char addr[16];
+	int mask_bits;
+};
+
+
+void qeth_l3_ipaddr4_to_string(const __u8 *, char *);
+int qeth_l3_string_to_ipaddr4(const char *, __u8 *);
+void qeth_l3_ipaddr6_to_string(const __u8 *, char *);
+int qeth_l3_string_to_ipaddr6(const char *, __u8 *);
+void qeth_l3_ipaddr_to_string(enum qeth_prot_versions, const __u8 *, char *);
+int qeth_l3_string_to_ipaddr(const char *, enum qeth_prot_versions, __u8 *);
+int qeth_l3_create_device_attributes(struct device *);
+void qeth_l3_remove_device_attributes(struct device *);
+int qeth_l3_setrouting_v4(struct qeth_card *);
+int qeth_l3_setrouting_v6(struct qeth_card *);
+int qeth_l3_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
+void qeth_l3_del_ipato_entry(struct qeth_card *, enum qeth_prot_versions,
+			u8 *, int);
+int qeth_l3_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
+			const u8 *);
+
+#endif /* __QETH_L3_H__ */
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
new file mode 100644
index 0000000..a856cb4
--- /dev/null
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -0,0 +1,3391 @@
+/*
+ *  drivers/s390/net/qeth_l3_main.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
+ *		 Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/ip.h>
+#include <linux/reboot.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+
+#include <net/ip.h>
+#include <net/arp.h>
+
+#include <asm/s390_rdev.h>
+
+#include "qeth_l3.h"
+#include "qeth_core_offl.h"
+
+DEFINE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
+
+static int qeth_l3_set_offline(struct ccwgroup_device *);
+static int qeth_l3_recover(void *);
+static int qeth_l3_stop(struct net_device *);
+static void qeth_l3_set_multicast_list(struct net_device *);
+static int qeth_l3_neigh_setup(struct net_device *, struct neigh_parms *);
+static int qeth_l3_register_addr_entry(struct qeth_card *,
+		struct qeth_ipaddr *);
+static int qeth_l3_deregister_addr_entry(struct qeth_card *,
+		struct qeth_ipaddr *);
+static int __qeth_l3_set_online(struct ccwgroup_device *, int);
+static int __qeth_l3_set_offline(struct ccwgroup_device *, int);
+
+
+static int qeth_l3_isxdigit(char *buf)
+{
+	while (*buf) {
+		if (!isxdigit(*buf++))
+			return 0;
+	}
+	return 1;
+}
+
+void qeth_l3_ipaddr4_to_string(const __u8 *addr, char *buf)
+{
+	sprintf(buf, "%i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
+}
+
+int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr)
+{
+	int count = 0, rc = 0;
+	int in[4];
+	char c;
+
+	rc = sscanf(buf, "%u.%u.%u.%u%c",
+		    &in[0], &in[1], &in[2], &in[3], &c);
+	if (rc != 4 && (rc != 5 || c != '\n'))
+		return -EINVAL;
+	for (count = 0; count < 4; count++) {
+		if (in[count] > 255)
+			return -EINVAL;
+		addr[count] = in[count];
+	}
+	return 0;
+}
+
+void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf)
+{
+	sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+		     ":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+		     addr[0], addr[1], addr[2], addr[3],
+		     addr[4], addr[5], addr[6], addr[7],
+		     addr[8], addr[9], addr[10], addr[11],
+		     addr[12], addr[13], addr[14], addr[15]);
+}
+
+int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr)
+{
+	const char *end, *end_tmp, *start;
+	__u16 *in;
+	char num[5];
+	int num2, cnt, out, found, save_cnt;
+	unsigned short in_tmp[8] = {0, };
+
+	cnt = out = found = save_cnt = num2 = 0;
+	end = start = buf;
+	in = (__u16 *) addr;
+	memset(in, 0, 16);
+	while (*end) {
+		end = strchr(start, ':');
+		if (end == NULL) {
+			end = buf + strlen(buf);
+			end_tmp = strchr(start, '\n');
+			if (end_tmp != NULL)
+				end = end_tmp;
+			out = 1;
+		}
+		if ((end - start)) {
+			memset(num, 0, 5);
+			if ((end - start) > 4)
+				return -EINVAL;
+			memcpy(num, start, end - start);
+			if (!qeth_l3_isxdigit(num))
+				return -EINVAL;
+			sscanf(start, "%x", &num2);
+			if (found)
+				in_tmp[save_cnt++] = num2;
+			else
+				in[cnt++] = num2;
+			if (out)
+				break;
+		} else {
+			if (found)
+				return -EINVAL;
+			found = 1;
+		}
+		start = ++end;
+	}
+	if (cnt + save_cnt > 8)
+		return -EINVAL;
+	cnt = 7;
+	while (save_cnt)
+		in[cnt--] = in_tmp[--save_cnt];
+	return 0;
+}
+
+void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
+				char *buf)
+{
+	if (proto == QETH_PROT_IPV4)
+		qeth_l3_ipaddr4_to_string(addr, buf);
+	else if (proto == QETH_PROT_IPV6)
+		qeth_l3_ipaddr6_to_string(addr, buf);
+}
+
+int qeth_l3_string_to_ipaddr(const char *buf, enum qeth_prot_versions proto,
+				__u8 *addr)
+{
+	if (proto == QETH_PROT_IPV4)
+		return qeth_l3_string_to_ipaddr4(buf, addr);
+	else if (proto == QETH_PROT_IPV6)
+		return qeth_l3_string_to_ipaddr6(buf, addr);
+	else
+		return -EINVAL;
+}
+
+static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
+{
+	int i, j;
+	u8 octet;
+
+	for (i = 0; i < len; ++i) {
+		octet = addr[i];
+		for (j = 7; j >= 0; --j) {
+			bits[i*8 + j] = octet & 1;
+			octet >>= 1;
+		}
+	}
+}
+
+static int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card,
+						struct qeth_ipaddr *addr)
+{
+	struct qeth_ipato_entry *ipatoe;
+	u8 addr_bits[128] = {0, };
+	u8 ipatoe_bits[128] = {0, };
+	int rc = 0;
+
+	if (!card->ipato.enabled)
+		return 0;
+
+	qeth_l3_convert_addr_to_bits((u8 *) &addr->u, addr_bits,
+				  (addr->proto == QETH_PROT_IPV4)? 4:16);
+	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
+		if (addr->proto != ipatoe->proto)
+			continue;
+		qeth_l3_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
+					  (ipatoe->proto == QETH_PROT_IPV4) ?
+					  4 : 16);
+		if (addr->proto == QETH_PROT_IPV4)
+			rc = !memcmp(addr_bits, ipatoe_bits,
+				     min(32, ipatoe->mask_bits));
+		else
+			rc = !memcmp(addr_bits, ipatoe_bits,
+				     min(128, ipatoe->mask_bits));
+		if (rc)
+			break;
+	}
+	/* invert? */
+	if ((addr->proto == QETH_PROT_IPV4) && card->ipato.invert4)
+		rc = !rc;
+	else if ((addr->proto == QETH_PROT_IPV6) && card->ipato.invert6)
+		rc = !rc;
+
+	return rc;
+}
+
+/*
+ * Add IP to be added to todo list. If there is already an "add todo"
+ * in this list we just incremenent the reference count.
+ * Returns 0 if we  just incremented reference count.
+ */
+static int __qeth_l3_insert_ip_todo(struct qeth_card *card,
+					struct qeth_ipaddr *addr, int add)
+{
+	struct qeth_ipaddr *tmp, *t;
+	int found = 0;
+
+	list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
+		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
+		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
+			return 0;
+		if ((tmp->proto        == QETH_PROT_IPV4)     &&
+		    (addr->proto       == QETH_PROT_IPV4)     &&
+		    (tmp->type         == addr->type)         &&
+		    (tmp->is_multicast == addr->is_multicast) &&
+		    (tmp->u.a4.addr    == addr->u.a4.addr)    &&
+		    (tmp->u.a4.mask    == addr->u.a4.mask)) {
+			found = 1;
+			break;
+		}
+		if ((tmp->proto        == QETH_PROT_IPV6)      &&
+		    (addr->proto       == QETH_PROT_IPV6)      &&
+		    (tmp->type         == addr->type)          &&
+		    (tmp->is_multicast == addr->is_multicast)  &&
+		    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&
+		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+			    sizeof(struct in6_addr)) == 0)) {
+			found = 1;
+			break;
+		}
+	}
+	if (found) {
+		if (addr->users != 0)
+			tmp->users += addr->users;
+		else
+			tmp->users += add ? 1 : -1;
+		if (tmp->users == 0) {
+			list_del(&tmp->entry);
+			kfree(tmp);
+		}
+		return 0;
+	} else {
+		if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)
+			list_add(&addr->entry, card->ip_tbd_list);
+		else {
+			if (addr->users == 0)
+				addr->users += add ? 1 : -1;
+			if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&
+			    qeth_l3_is_addr_covered_by_ipato(card, addr)) {
+				QETH_DBF_TEXT(trace, 2, "tkovaddr");
+				addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
+			}
+			list_add_tail(&addr->entry, card->ip_tbd_list);
+		}
+		return 1;
+	}
+}
+
+static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 4, "delip");
+
+	if (addr->proto == QETH_PROT_IPV4)
+		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+	else {
+		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+	}
+	spin_lock_irqsave(&card->ip_lock, flags);
+	rc = __qeth_l3_insert_ip_todo(card, addr, 0);
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	return rc;
+}
+
+static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 4, "addip");
+	if (addr->proto == QETH_PROT_IPV4)
+		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+	else {
+		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+	}
+	spin_lock_irqsave(&card->ip_lock, flags);
+	rc = __qeth_l3_insert_ip_todo(card, addr, 1);
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	return rc;
+}
+
+
+static struct qeth_ipaddr *qeth_l3_get_addr_buffer(
+				enum qeth_prot_versions prot)
+{
+	struct qeth_ipaddr *addr;
+
+	addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
+	if (addr == NULL) {
+		PRINT_WARN("Not enough memory to add address\n");
+		return NULL;
+	}
+	addr->type = QETH_IP_TYPE_NORMAL;
+	addr->proto = prot;
+	return addr;
+}
+
+static void qeth_l3_delete_mc_addresses(struct qeth_card *card)
+{
+	struct qeth_ipaddr *iptodo;
+	unsigned long flags;
+
+	QETH_DBF_TEXT(trace, 4, "delmc");
+	iptodo = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
+	if (!iptodo) {
+		QETH_DBF_TEXT(trace, 2, "dmcnomem");
+		return;
+	}
+	iptodo->type = QETH_IP_TYPE_DEL_ALL_MC;
+	spin_lock_irqsave(&card->ip_lock, flags);
+	if (!__qeth_l3_insert_ip_todo(card, iptodo, 0))
+		kfree(iptodo);
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+}
+
+/*
+ * Add/remove address to/from card's ip list, i.e. try to add or remove
+ * reference to/from an IP address that is already registered on the card.
+ * Returns:
+ *	0  address was on card and its reference count has been adjusted,
+ *	   but is still > 0, so nothing has to be done
+ *	   also returns 0 if card was not on card and the todo was to delete
+ *	   the address -> there is also nothing to be done
+ *	1  address was not on card and the todo is to add it to the card's ip
+ *	   list
+ *	-1 address was on card and its reference count has been decremented
+ *	   to <= 0 by the todo -> address must be removed from card
+ */
+static int __qeth_l3_ref_ip_on_card(struct qeth_card *card,
+		struct qeth_ipaddr *todo, struct qeth_ipaddr **__addr)
+{
+	struct qeth_ipaddr *addr;
+	int found = 0;
+
+	list_for_each_entry(addr, &card->ip_list, entry) {
+		if ((addr->proto == QETH_PROT_IPV4) &&
+		    (todo->proto == QETH_PROT_IPV4) &&
+		    (addr->type == todo->type) &&
+		    (addr->u.a4.addr == todo->u.a4.addr) &&
+		    (addr->u.a4.mask == todo->u.a4.mask)) {
+			found = 1;
+			break;
+		}
+		if ((addr->proto == QETH_PROT_IPV6) &&
+		    (todo->proto == QETH_PROT_IPV6) &&
+		    (addr->type == todo->type) &&
+		    (addr->u.a6.pfxlen == todo->u.a6.pfxlen) &&
+		    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
+			    sizeof(struct in6_addr)) == 0)) {
+			found = 1;
+			break;
+		}
+	}
+	if (found) {
+		addr->users += todo->users;
+		if (addr->users <= 0) {
+			*__addr = addr;
+			return -1;
+		} else {
+			/* for VIPA and RXIP limit refcount to 1 */
+			if (addr->type != QETH_IP_TYPE_NORMAL)
+				addr->users = 1;
+			return 0;
+		}
+	}
+	if (todo->users > 0) {
+		/* for VIPA and RXIP limit refcount to 1 */
+		if (todo->type != QETH_IP_TYPE_NORMAL)
+			todo->users = 1;
+		return 1;
+	} else
+		return 0;
+}
+
+static void __qeth_l3_delete_all_mc(struct qeth_card *card,
+					unsigned long *flags)
+{
+	struct qeth_ipaddr *addr, *tmp;
+	int rc;
+again:
+	list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
+		if (addr->is_multicast) {
+			list_del(&addr->entry);
+			spin_unlock_irqrestore(&card->ip_lock, *flags);
+			rc = qeth_l3_deregister_addr_entry(card, addr);
+			spin_lock_irqsave(&card->ip_lock, *flags);
+			if (!rc) {
+				kfree(addr);
+				goto again;
+			} else
+				list_add(&addr->entry, &card->ip_list);
+		}
+	}
+}
+
+static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
+{
+	struct list_head *tbd_list;
+	struct qeth_ipaddr *todo, *addr;
+	unsigned long flags;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 2, "sdiplist");
+	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+
+	spin_lock_irqsave(&card->ip_lock, flags);
+	tbd_list = card->ip_tbd_list;
+	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+	if (!card->ip_tbd_list) {
+		QETH_DBF_TEXT(trace, 0, "silnomem");
+		card->ip_tbd_list = tbd_list;
+		spin_unlock_irqrestore(&card->ip_lock, flags);
+		return;
+	} else
+		INIT_LIST_HEAD(card->ip_tbd_list);
+
+	while (!list_empty(tbd_list)) {
+		todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);
+		list_del(&todo->entry);
+		if (todo->type == QETH_IP_TYPE_DEL_ALL_MC) {
+			__qeth_l3_delete_all_mc(card, &flags);
+			kfree(todo);
+			continue;
+		}
+		rc = __qeth_l3_ref_ip_on_card(card, todo, &addr);
+		if (rc == 0) {
+			/* nothing to be done; only adjusted refcount */
+			kfree(todo);
+		} else if (rc == 1) {
+			/* new entry to be added to on-card list */
+			spin_unlock_irqrestore(&card->ip_lock, flags);
+			rc = qeth_l3_register_addr_entry(card, todo);
+			spin_lock_irqsave(&card->ip_lock, flags);
+			if (!rc)
+				list_add_tail(&todo->entry, &card->ip_list);
+			else
+				kfree(todo);
+		} else if (rc == -1) {
+			/* on-card entry to be removed */
+			list_del_init(&addr->entry);
+			spin_unlock_irqrestore(&card->ip_lock, flags);
+			rc = qeth_l3_deregister_addr_entry(card, addr);
+			spin_lock_irqsave(&card->ip_lock, flags);
+			if (!rc)
+				kfree(addr);
+			else
+				list_add_tail(&addr->entry, &card->ip_list);
+			kfree(todo);
+		}
+	}
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	kfree(tbd_list);
+}
+
+static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean,
+					int recover)
+{
+	struct qeth_ipaddr *addr, *tmp;
+	unsigned long flags;
+
+	QETH_DBF_TEXT(trace, 4, "clearip");
+	spin_lock_irqsave(&card->ip_lock, flags);
+	/* clear todo list */
+	list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry) {
+		list_del(&addr->entry);
+		kfree(addr);
+	}
+
+	while (!list_empty(&card->ip_list)) {
+		addr = list_entry(card->ip_list.next,
+				  struct qeth_ipaddr, entry);
+		list_del_init(&addr->entry);
+		if (clean) {
+			spin_unlock_irqrestore(&card->ip_lock, flags);
+			qeth_l3_deregister_addr_entry(card, addr);
+			spin_lock_irqsave(&card->ip_lock, flags);
+		}
+		if (!recover || addr->is_multicast) {
+			kfree(addr);
+			continue;
+		}
+		list_add_tail(&addr->entry, card->ip_tbd_list);
+	}
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+}
+
+static int qeth_l3_address_exists_in_list(struct list_head *list,
+		struct qeth_ipaddr *addr, int same_type)
+{
+	struct qeth_ipaddr *tmp;
+
+	list_for_each_entry(tmp, list, entry) {
+		if ((tmp->proto == QETH_PROT_IPV4) &&
+		    (addr->proto == QETH_PROT_IPV4) &&
+		    ((same_type && (tmp->type == addr->type)) ||
+		    (!same_type && (tmp->type != addr->type))) &&
+		    (tmp->u.a4.addr == addr->u.a4.addr))
+			return 1;
+
+		if ((tmp->proto == QETH_PROT_IPV6) &&
+		    (addr->proto == QETH_PROT_IPV6) &&
+		    ((same_type && (tmp->type == addr->type)) ||
+		    (!same_type && (tmp->type != addr->type))) &&
+		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+			    sizeof(struct in6_addr)) == 0))
+			return 1;
+
+	}
+	return 0;
+}
+
+static int qeth_l3_send_setdelmc(struct qeth_card *card,
+			struct qeth_ipaddr *addr, int ipacmd)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "setdelmc");
+
+	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	memcpy(&cmd->data.setdelipm.mac, addr->mac, OSA_ADDR_LEN);
+	if (addr->proto == QETH_PROT_IPV6)
+		memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
+		       sizeof(struct in6_addr));
+	else
+		memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4);
+
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+
+	return rc;
+}
+
+static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len)
+{
+	int i, j;
+	for (i = 0; i < 16; i++) {
+		j = (len) - (i * 8);
+		if (j >= 8)
+			netmask[i] = 0xff;
+		else if (j > 0)
+			netmask[i] = (u8)(0xFF00 >> j);
+		else
+			netmask[i] = 0;
+	}
+}
+
+static int qeth_l3_send_setdelip(struct qeth_card *card,
+		struct qeth_ipaddr *addr, int ipacmd, unsigned int flags)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+	__u8 netmask[16];
+
+	QETH_DBF_TEXT(trace, 4, "setdelip");
+	QETH_DBF_TEXT_(trace, 4, "flags%02X", flags);
+
+	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	if (addr->proto == QETH_PROT_IPV6) {
+		memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
+		       sizeof(struct in6_addr));
+		qeth_l3_fill_netmask(netmask, addr->u.a6.pfxlen);
+		memcpy(cmd->data.setdelip6.mask, netmask,
+		       sizeof(struct in6_addr));
+		cmd->data.setdelip6.flags = flags;
+	} else {
+		memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
+		memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
+		cmd->data.setdelip4.flags = flags;
+	}
+
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+
+	return rc;
+}
+
+static int qeth_l3_send_setrouting(struct qeth_card *card,
+	enum qeth_routing_types type, enum qeth_prot_versions prot)
+{
+	int rc;
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(trace, 4, "setroutg");
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	cmd->data.setrtg.type = (type);
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+
+	return rc;
+}
+
+static void qeth_l3_correct_routing_type(struct qeth_card *card,
+		enum qeth_routing_types *type, enum qeth_prot_versions prot)
+{
+	if (card->info.type == QETH_CARD_TYPE_IQD) {
+		switch (*type) {
+		case NO_ROUTER:
+		case PRIMARY_CONNECTOR:
+		case SECONDARY_CONNECTOR:
+		case MULTICAST_ROUTER:
+			return;
+		default:
+			goto out_inval;
+		}
+	} else {
+		switch (*type) {
+		case NO_ROUTER:
+		case PRIMARY_ROUTER:
+		case SECONDARY_ROUTER:
+			return;
+		case MULTICAST_ROUTER:
+			if (qeth_is_ipafunc_supported(card, prot,
+						      IPA_OSA_MC_ROUTER))
+				return;
+		default:
+			goto out_inval;
+		}
+	}
+out_inval:
+	PRINT_WARN("Routing type '%s' not supported for interface %s.\n"
+		   "Router status set to 'no router'.\n",
+		   ((*type == PRIMARY_ROUTER)? "primary router" :
+		    (*type == SECONDARY_ROUTER)? "secondary router" :
+		    (*type == PRIMARY_CONNECTOR)? "primary connector" :
+		    (*type == SECONDARY_CONNECTOR)? "secondary connector" :
+		    (*type == MULTICAST_ROUTER)? "multicast router" :
+		    "unknown"),
+		   card->dev->name);
+	*type = NO_ROUTER;
+}
+
+int qeth_l3_setrouting_v4(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "setrtg4");
+
+	qeth_l3_correct_routing_type(card, &card->options.route4.type,
+				  QETH_PROT_IPV4);
+
+	rc = qeth_l3_send_setrouting(card, card->options.route4.type,
+				  QETH_PROT_IPV4);
+	if (rc) {
+		card->options.route4.type = NO_ROUTER;
+		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
+			   "Type set to 'no router'.\n",
+			   rc, QETH_CARD_IFNAME(card));
+	}
+	return rc;
+}
+
+int qeth_l3_setrouting_v6(struct qeth_card *card)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "setrtg6");
+#ifdef CONFIG_QETH_IPV6
+
+	if (!qeth_is_supported(card, IPA_IPV6))
+		return 0;
+	qeth_l3_correct_routing_type(card, &card->options.route6.type,
+				  QETH_PROT_IPV6);
+
+	rc = qeth_l3_send_setrouting(card, card->options.route6.type,
+				  QETH_PROT_IPV6);
+	if (rc) {
+		card->options.route6.type = NO_ROUTER;
+		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
+			   "Type set to 'no router'.\n",
+			   rc, QETH_CARD_IFNAME(card));
+	}
+#endif
+	return rc;
+}
+
+/*
+ * IP address takeover related functions
+ */
+static void qeth_l3_clear_ipato_list(struct qeth_card *card)
+{
+
+	struct qeth_ipato_entry *ipatoe, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->ip_lock, flags);
+	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
+		list_del(&ipatoe->entry);
+		kfree(ipatoe);
+	}
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+}
+
+int qeth_l3_add_ipato_entry(struct qeth_card *card,
+				struct qeth_ipato_entry *new)
+{
+	struct qeth_ipato_entry *ipatoe;
+	unsigned long flags;
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 2, "addipato");
+	spin_lock_irqsave(&card->ip_lock, flags);
+	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
+		if (ipatoe->proto != new->proto)
+			continue;
+		if (!memcmp(ipatoe->addr, new->addr,
+			    (ipatoe->proto == QETH_PROT_IPV4)? 4:16) &&
+		    (ipatoe->mask_bits == new->mask_bits)) {
+			PRINT_WARN("ipato entry already exists!\n");
+			rc = -EEXIST;
+			break;
+		}
+	}
+	if (!rc)
+		list_add_tail(&new->entry, &card->ipato.entries);
+
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	return rc;
+}
+
+void qeth_l3_del_ipato_entry(struct qeth_card *card,
+		enum qeth_prot_versions proto, u8 *addr, int mask_bits)
+{
+	struct qeth_ipato_entry *ipatoe, *tmp;
+	unsigned long flags;
+
+	QETH_DBF_TEXT(trace, 2, "delipato");
+	spin_lock_irqsave(&card->ip_lock, flags);
+	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
+		if (ipatoe->proto != proto)
+			continue;
+		if (!memcmp(ipatoe->addr, addr,
+			    (proto == QETH_PROT_IPV4)? 4:16) &&
+		    (ipatoe->mask_bits == mask_bits)) {
+			list_del(&ipatoe->entry);
+			kfree(ipatoe);
+		}
+	}
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+}
+
+/*
+ * VIPA related functions
+ */
+int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+	      const u8 *addr)
+{
+	struct qeth_ipaddr *ipaddr;
+	unsigned long flags;
+	int rc = 0;
+
+	ipaddr = qeth_l3_get_addr_buffer(proto);
+	if (ipaddr) {
+		if (proto == QETH_PROT_IPV4) {
+			QETH_DBF_TEXT(trace, 2, "addvipa4");
+			memcpy(&ipaddr->u.a4.addr, addr, 4);
+			ipaddr->u.a4.mask = 0;
+		} else if (proto == QETH_PROT_IPV6) {
+			QETH_DBF_TEXT(trace, 2, "addvipa6");
+			memcpy(&ipaddr->u.a6.addr, addr, 16);
+			ipaddr->u.a6.pfxlen = 0;
+		}
+		ipaddr->type = QETH_IP_TYPE_VIPA;
+		ipaddr->set_flags = QETH_IPA_SETIP_VIPA_FLAG;
+		ipaddr->del_flags = QETH_IPA_DELIP_VIPA_FLAG;
+	} else
+		return -ENOMEM;
+	spin_lock_irqsave(&card->ip_lock, flags);
+	if (qeth_l3_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
+	    qeth_l3_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
+		rc = -EEXIST;
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	if (rc) {
+		PRINT_WARN("Cannot add VIPA. Address already exists!\n");
+		return rc;
+	}
+	if (!qeth_l3_add_ip(card, ipaddr))
+		kfree(ipaddr);
+	qeth_l3_set_ip_addr_list(card);
+	return rc;
+}
+
+void qeth_l3_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+	      const u8 *addr)
+{
+	struct qeth_ipaddr *ipaddr;
+
+	ipaddr = qeth_l3_get_addr_buffer(proto);
+	if (ipaddr) {
+		if (proto == QETH_PROT_IPV4) {
+			QETH_DBF_TEXT(trace, 2, "delvipa4");
+			memcpy(&ipaddr->u.a4.addr, addr, 4);
+			ipaddr->u.a4.mask = 0;
+		} else if (proto == QETH_PROT_IPV6) {
+			QETH_DBF_TEXT(trace, 2, "delvipa6");
+			memcpy(&ipaddr->u.a6.addr, addr, 16);
+			ipaddr->u.a6.pfxlen = 0;
+		}
+		ipaddr->type = QETH_IP_TYPE_VIPA;
+	} else
+		return;
+	if (!qeth_l3_delete_ip(card, ipaddr))
+		kfree(ipaddr);
+	qeth_l3_set_ip_addr_list(card);
+}
+
+/*
+ * proxy ARP related functions
+ */
+int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
+	      const u8 *addr)
+{
+	struct qeth_ipaddr *ipaddr;
+	unsigned long flags;
+	int rc = 0;
+
+	ipaddr = qeth_l3_get_addr_buffer(proto);
+	if (ipaddr) {
+		if (proto == QETH_PROT_IPV4) {
+			QETH_DBF_TEXT(trace, 2, "addrxip4");
+			memcpy(&ipaddr->u.a4.addr, addr, 4);
+			ipaddr->u.a4.mask = 0;
+		} else if (proto == QETH_PROT_IPV6) {
+			QETH_DBF_TEXT(trace, 2, "addrxip6");
+			memcpy(&ipaddr->u.a6.addr, addr, 16);
+			ipaddr->u.a6.pfxlen = 0;
+		}
+		ipaddr->type = QETH_IP_TYPE_RXIP;
+		ipaddr->set_flags = QETH_IPA_SETIP_TAKEOVER_FLAG;
+		ipaddr->del_flags = 0;
+	} else
+		return -ENOMEM;
+	spin_lock_irqsave(&card->ip_lock, flags);
+	if (qeth_l3_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
+	    qeth_l3_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
+		rc = -EEXIST;
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	if (rc) {
+		PRINT_WARN("Cannot add RXIP. Address already exists!\n");
+		return rc;
+	}
+	if (!qeth_l3_add_ip(card, ipaddr))
+		kfree(ipaddr);
+	qeth_l3_set_ip_addr_list(card);
+	return 0;
+}
+
+void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
+			const u8 *addr)
+{
+	struct qeth_ipaddr *ipaddr;
+
+	ipaddr = qeth_l3_get_addr_buffer(proto);
+	if (ipaddr) {
+		if (proto == QETH_PROT_IPV4) {
+			QETH_DBF_TEXT(trace, 2, "addrxip4");
+			memcpy(&ipaddr->u.a4.addr, addr, 4);
+			ipaddr->u.a4.mask = 0;
+		} else if (proto == QETH_PROT_IPV6) {
+			QETH_DBF_TEXT(trace, 2, "addrxip6");
+			memcpy(&ipaddr->u.a6.addr, addr, 16);
+			ipaddr->u.a6.pfxlen = 0;
+		}
+		ipaddr->type = QETH_IP_TYPE_RXIP;
+	} else
+		return;
+	if (!qeth_l3_delete_ip(card, ipaddr))
+		kfree(ipaddr);
+	qeth_l3_set_ip_addr_list(card);
+}
+
+static int qeth_l3_register_addr_entry(struct qeth_card *card,
+				struct qeth_ipaddr *addr)
+{
+	char buf[50];
+	int rc = 0;
+	int cnt = 3;
+
+	if (addr->proto == QETH_PROT_IPV4) {
+		QETH_DBF_TEXT(trace, 2, "setaddr4");
+		QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
+	} else if (addr->proto == QETH_PROT_IPV6) {
+		QETH_DBF_TEXT(trace, 2, "setaddr6");
+		QETH_DBF_HEX(trace, 3, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 3, ((char *)&addr->u.a6.addr) + 8, 8);
+	} else {
+		QETH_DBF_TEXT(trace, 2, "setaddr?");
+		QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
+	}
+	do {
+		if (addr->is_multicast)
+			rc =  qeth_l3_send_setdelmc(card, addr, IPA_CMD_SETIPM);
+		else
+			rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_SETIP,
+					addr->set_flags);
+		if (rc)
+			QETH_DBF_TEXT(trace, 2, "failed");
+	} while ((--cnt > 0) && rc);
+	if (rc) {
+		QETH_DBF_TEXT(trace, 2, "FAILED");
+		qeth_l3_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
+		PRINT_WARN("Could not register IP address %s (rc=0x%x/%d)\n",
+			   buf, rc, rc);
+	}
+	return rc;
+}
+
+static int qeth_l3_deregister_addr_entry(struct qeth_card *card,
+						struct qeth_ipaddr *addr)
+{
+	int rc = 0;
+
+	if (addr->proto == QETH_PROT_IPV4) {
+		QETH_DBF_TEXT(trace, 2, "deladdr4");
+		QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
+	} else if (addr->proto == QETH_PROT_IPV6) {
+		QETH_DBF_TEXT(trace, 2, "deladdr6");
+		QETH_DBF_HEX(trace, 3, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 3, ((char *)&addr->u.a6.addr) + 8, 8);
+	} else {
+		QETH_DBF_TEXT(trace, 2, "deladdr?");
+		QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
+	}
+	if (addr->is_multicast)
+		rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_DELIPM);
+	else
+		rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP,
+					addr->del_flags);
+	if (rc) {
+		QETH_DBF_TEXT(trace, 2, "failed");
+		/* TODO: re-activate this warning as soon as we have a
+		 * clean mirco code
+		qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
+		PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
+			   buf, rc);
+		*/
+	}
+
+	return rc;
+}
+
+static inline u8 qeth_l3_get_qeth_hdr_flags4(int cast_type)
+{
+	if (cast_type == RTN_MULTICAST)
+		return QETH_CAST_MULTICAST;
+	if (cast_type == RTN_BROADCAST)
+		return QETH_CAST_BROADCAST;
+	return QETH_CAST_UNICAST;
+}
+
+static inline u8 qeth_l3_get_qeth_hdr_flags6(int cast_type)
+{
+	u8 ct = QETH_HDR_PASSTHRU | QETH_HDR_IPV6;
+	if (cast_type == RTN_MULTICAST)
+		return ct | QETH_CAST_MULTICAST;
+	if (cast_type == RTN_ANYCAST)
+		return ct | QETH_CAST_ANYCAST;
+	if (cast_type == RTN_BROADCAST)
+		return ct | QETH_CAST_BROADCAST;
+	return ct | QETH_CAST_UNICAST;
+}
+
+static int qeth_l3_send_setadp_mode(struct qeth_card *card, __u32 command,
+					__u32 mode)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "adpmode");
+
+	iob = qeth_get_adapter_cmd(card, command,
+				   sizeof(struct qeth_ipacmd_setadpparms));
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	cmd->data.setadapterparms.data.mode = mode;
+	rc = qeth_send_ipa_cmd(card, iob, qeth_default_setadapterparms_cb,
+			       NULL);
+	return rc;
+}
+
+static int qeth_l3_setadapter_hstr(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 4, "adphstr");
+
+	if (qeth_adp_supported(card, IPA_SETADP_SET_BROADCAST_MODE)) {
+		rc = qeth_l3_send_setadp_mode(card,
+					IPA_SETADP_SET_BROADCAST_MODE,
+					card->options.broadcast_mode);
+		if (rc)
+			PRINT_WARN("couldn't set broadcast mode on "
+				   "device %s: x%x\n",
+				   CARD_BUS_ID(card), rc);
+		rc = qeth_l3_send_setadp_mode(card,
+					IPA_SETADP_ALTER_MAC_ADDRESS,
+					card->options.macaddr_mode);
+		if (rc)
+			PRINT_WARN("couldn't set macaddr mode on "
+				   "device %s: x%x\n", CARD_BUS_ID(card), rc);
+		return rc;
+	}
+	if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL)
+		PRINT_WARN("set adapter parameters not available "
+			   "to set broadcast mode, using ALLRINGS "
+			   "on device %s:\n", CARD_BUS_ID(card));
+	if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL)
+		PRINT_WARN("set adapter parameters not available "
+			   "to set macaddr mode, using NONCANONICAL "
+			   "on device %s:\n", CARD_BUS_ID(card));
+	return 0;
+}
+
+static int qeth_l3_setadapter_parms(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(setup, 2, "setadprm");
+
+	if (!qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
+		PRINT_WARN("set adapter parameters not supported "
+			   "on device %s.\n",
+			   CARD_BUS_ID(card));
+		QETH_DBF_TEXT(setup, 2, " notsupp");
+		return 0;
+	}
+	rc = qeth_query_setadapterparms(card);
+	if (rc) {
+		PRINT_WARN("couldn't set adapter parameters on device %s: "
+			   "x%x\n", CARD_BUS_ID(card), rc);
+		return rc;
+	}
+	if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) {
+		rc = qeth_setadpparms_change_macaddr(card);
+		if (rc)
+			PRINT_WARN("couldn't get MAC address on "
+				   "device %s: x%x\n",
+				   CARD_BUS_ID(card), rc);
+	}
+
+	if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+	    (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
+		rc = qeth_l3_setadapter_hstr(card);
+
+	return rc;
+}
+
+static int qeth_l3_default_setassparms_cb(struct qeth_card *card,
+			struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "defadpcb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code == 0) {
+		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+		if (cmd->hdr.prot_version == QETH_PROT_IPV4)
+			card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+		if (cmd->hdr.prot_version == QETH_PROT_IPV6)
+			card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
+	}
+	if (cmd->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
+	    cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+		card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
+		QETH_DBF_TEXT_(trace, 3, "csum:%d", card->info.csum_mask);
+	}
+	return 0;
+}
+
+static struct qeth_cmd_buffer *qeth_l3_get_setassparms_cmd(
+	struct qeth_card *card, enum qeth_ipa_funcs ipa_func, __u16 cmd_code,
+	__u16 len, enum qeth_prot_versions prot)
+{
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "getasscm");
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
+
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	cmd->data.setassparms.hdr.assist_no = ipa_func;
+	cmd->data.setassparms.hdr.length = 8 + len;
+	cmd->data.setassparms.hdr.command_code = cmd_code;
+	cmd->data.setassparms.hdr.return_code = 0;
+	cmd->data.setassparms.hdr.seq_no = 0;
+
+	return iob;
+}
+
+static int qeth_l3_send_setassparms(struct qeth_card *card,
+	struct qeth_cmd_buffer *iob, __u16 len, long data,
+	int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
+		unsigned long),
+	void *reply_param)
+{
+	int rc;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "sendassp");
+
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	if (len <= sizeof(__u32))
+		cmd->data.setassparms.data.flags_32bit = (__u32) data;
+	else   /* (len > sizeof(__u32)) */
+		memcpy(&cmd->data.setassparms.data, (void *) data, len);
+
+	rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
+	return rc;
+}
+
+#ifdef CONFIG_QETH_IPV6
+static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
+		enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(trace, 4, "simassp6");
+	iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
+				       0, QETH_PROT_IPV6);
+	rc = qeth_l3_send_setassparms(card, iob, 0, 0,
+				   qeth_l3_default_setassparms_cb, NULL);
+	return rc;
+}
+#endif
+
+static int qeth_l3_send_simple_setassparms(struct qeth_card *card,
+		enum qeth_ipa_funcs ipa_func, __u16 cmd_code, long data)
+{
+	int rc;
+	int length = 0;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT(trace, 4, "simassp4");
+	if (data)
+		length = sizeof(__u32);
+	iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
+				       length, QETH_PROT_IPV4);
+	rc = qeth_l3_send_setassparms(card, iob, length, data,
+				   qeth_l3_default_setassparms_cb, NULL);
+	return rc;
+}
+
+static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "ipaarp");
+
+	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
+		PRINT_WARN("ARP processing not supported "
+			   "on %s!\n", QETH_CARD_IFNAME(card));
+		return 0;
+	}
+	rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+					IPA_CMD_ASS_START, 0);
+	if (rc) {
+		PRINT_WARN("Could not start ARP processing "
+			   "assist on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+	}
+	return rc;
+}
+
+static int qeth_l3_start_ipa_ip_fragmentation(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "ipaipfrg");
+
+	if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
+		PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
+			   QETH_CARD_IFNAME(card));
+		return  -EOPNOTSUPP;
+	}
+
+	rc = qeth_l3_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
+					  IPA_CMD_ASS_START, 0);
+	if (rc) {
+		PRINT_WARN("Could not start Hardware IP fragmentation "
+			   "assist on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+	} else
+		PRINT_INFO("Hardware IP fragmentation enabled \n");
+	return rc;
+}
+
+static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "stsrcmac");
+
+	if (!card->options.fake_ll)
+		return -EOPNOTSUPP;
+
+	if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
+		PRINT_INFO("Inbound source address not "
+			   "supported on %s\n", QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+
+	rc = qeth_l3_send_simple_setassparms(card, IPA_SOURCE_MAC,
+					  IPA_CMD_ASS_START, 0);
+	if (rc)
+		PRINT_WARN("Could not start inbound source "
+			   "assist on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+	return rc;
+}
+
+static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "strtvlan");
+
+	if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
+		PRINT_WARN("VLAN not supported on %s\n",
+				QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+
+	rc = qeth_l3_send_simple_setassparms(card, IPA_VLAN_PRIO,
+					  IPA_CMD_ASS_START, 0);
+	if (rc) {
+		PRINT_WARN("Could not start vlan "
+			   "assist on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+	} else {
+		PRINT_INFO("VLAN enabled \n");
+	}
+	return rc;
+}
+
+static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "stmcast");
+
+	if (!qeth_is_supported(card, IPA_MULTICASTING)) {
+		PRINT_WARN("Multicast not supported on %s\n",
+			   QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+
+	rc = qeth_l3_send_simple_setassparms(card, IPA_MULTICASTING,
+					  IPA_CMD_ASS_START, 0);
+	if (rc) {
+		PRINT_WARN("Could not start multicast "
+			   "assist on %s: rc=%i\n",
+			   QETH_CARD_IFNAME(card), rc);
+	} else {
+		PRINT_INFO("Multicast enabled\n");
+		card->dev->flags |= IFF_MULTICAST;
+	}
+	return rc;
+}
+
+static int qeth_l3_query_ipassists_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(setup, 2, "qipasscb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
+		card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
+		card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+	} else {
+		card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
+		card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
+	}
+	QETH_DBF_TEXT(setup, 2, "suppenbl");
+	QETH_DBF_TEXT_(setup, 2, "%x", cmd->hdr.ipa_supported);
+	QETH_DBF_TEXT_(setup, 2, "%x", cmd->hdr.ipa_enabled);
+	return 0;
+}
+
+static int qeth_l3_query_ipassists(struct qeth_card *card,
+				enum qeth_prot_versions prot)
+{
+	int rc;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT_(setup, 2, "qipassi%i", prot);
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot);
+	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_query_ipassists_cb, NULL);
+	return rc;
+}
+
+#ifdef CONFIG_QETH_IPV6
+static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "softipv6");
+
+	if (card->info.type == QETH_CARD_TYPE_IQD)
+		goto out;
+
+	rc = qeth_l3_query_ipassists(card, QETH_PROT_IPV6);
+	if (rc) {
+		PRINT_ERR("IPv6 query ipassist failed on %s\n",
+			  QETH_CARD_IFNAME(card));
+		return rc;
+	}
+	rc = qeth_l3_send_simple_setassparms(card, IPA_IPV6,
+					  IPA_CMD_ASS_START, 3);
+	if (rc) {
+		PRINT_WARN("IPv6 start assist (version 4) failed "
+			   "on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+		return rc;
+	}
+	rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_IPV6,
+					       IPA_CMD_ASS_START);
+	if (rc) {
+		PRINT_WARN("IPV6 start assist (version 6) failed  "
+			   "on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+		return rc;
+	}
+	rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
+					       IPA_CMD_ASS_START);
+	if (rc) {
+		PRINT_WARN("Could not enable passthrough "
+			   "on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+		return rc;
+	}
+out:
+	PRINT_INFO("IPV6 enabled \n");
+	return 0;
+}
+#endif
+
+static int qeth_l3_start_ipa_ipv6(struct qeth_card *card)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "strtipv6");
+
+	if (!qeth_is_supported(card, IPA_IPV6)) {
+		PRINT_WARN("IPv6 not supported on %s\n",
+			   QETH_CARD_IFNAME(card));
+		return 0;
+	}
+#ifdef CONFIG_QETH_IPV6
+	rc = qeth_l3_softsetup_ipv6(card);
+#endif
+	return rc ;
+}
+
+static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "stbrdcst");
+	card->info.broadcast_capable = 0;
+	if (!qeth_is_supported(card, IPA_FILTERING)) {
+		PRINT_WARN("Broadcast not supported on %s\n",
+			   QETH_CARD_IFNAME(card));
+		rc = -EOPNOTSUPP;
+		goto out;
+	}
+	rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+					  IPA_CMD_ASS_START, 0);
+	if (rc) {
+		PRINT_WARN("Could not enable broadcasting filtering "
+			   "on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+		goto out;
+	}
+
+	rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+					  IPA_CMD_ASS_CONFIGURE, 1);
+	if (rc) {
+		PRINT_WARN("Could not set up broadcast filtering on %s: 0x%x\n",
+			   QETH_CARD_IFNAME(card), rc);
+		goto out;
+	}
+	card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
+	PRINT_INFO("Broadcast enabled \n");
+	rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+					  IPA_CMD_ASS_ENABLE, 1);
+	if (rc) {
+		PRINT_WARN("Could not set up broadcast echo filtering on "
+			   "%s: 0x%x\n", QETH_CARD_IFNAME(card), rc);
+		goto out;
+	}
+	card->info.broadcast_capable = QETH_BROADCAST_WITHOUT_ECHO;
+out:
+	if (card->info.broadcast_capable)
+		card->dev->flags |= IFF_BROADCAST;
+	else
+		card->dev->flags &= ~IFF_BROADCAST;
+	return rc;
+}
+
+static int qeth_l3_send_checksum_command(struct qeth_card *card)
+{
+	int rc;
+
+	rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+					  IPA_CMD_ASS_START, 0);
+	if (rc) {
+		PRINT_WARN("Starting Inbound HW Checksumming failed on %s: "
+			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
+			   QETH_CARD_IFNAME(card), rc);
+		return rc;
+	}
+	rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+					  IPA_CMD_ASS_ENABLE,
+					  card->info.csum_mask);
+	if (rc) {
+		PRINT_WARN("Enabling Inbound HW Checksumming failed on %s: "
+			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
+			   QETH_CARD_IFNAME(card), rc);
+		return rc;
+	}
+	return 0;
+}
+
+static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 3, "strtcsum");
+
+	if (card->options.checksum_type == NO_CHECKSUMMING) {
+		PRINT_WARN("Using no checksumming on %s.\n",
+			   QETH_CARD_IFNAME(card));
+		return 0;
+	}
+	if (card->options.checksum_type == SW_CHECKSUMMING) {
+		PRINT_WARN("Using SW checksumming on %s.\n",
+			   QETH_CARD_IFNAME(card));
+		return 0;
+	}
+	if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) {
+		PRINT_WARN("Inbound HW Checksumming not "
+			   "supported on %s,\ncontinuing "
+			   "using Inbound SW Checksumming\n",
+			   QETH_CARD_IFNAME(card));
+		card->options.checksum_type = SW_CHECKSUMMING;
+		return 0;
+	}
+	rc = qeth_l3_send_checksum_command(card);
+	if (!rc)
+		PRINT_INFO("HW Checksumming (inbound) enabled \n");
+
+	return rc;
+}
+
+static int qeth_l3_start_ipa_tso(struct qeth_card *card)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "sttso");
+
+	if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
+		PRINT_WARN("Outbound TSO not supported on %s\n",
+			   QETH_CARD_IFNAME(card));
+		rc = -EOPNOTSUPP;
+	} else {
+		rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
+						IPA_CMD_ASS_START, 0);
+		if (rc)
+			PRINT_WARN("Could not start outbound TSO "
+				   "assist on %s: rc=%i\n",
+				   QETH_CARD_IFNAME(card), rc);
+		else
+			PRINT_INFO("Outbound TSO enabled\n");
+	}
+	if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)) {
+		card->options.large_send = QETH_LARGE_SEND_NO;
+		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
+	}
+	return rc;
+}
+
+static int qeth_l3_start_ipassists(struct qeth_card *card)
+{
+	QETH_DBF_TEXT(trace, 3, "strtipas");
+	qeth_l3_start_ipa_arp_processing(card);	/* go on*/
+	qeth_l3_start_ipa_ip_fragmentation(card);	/* go on*/
+	qeth_l3_start_ipa_source_mac(card);	/* go on*/
+	qeth_l3_start_ipa_vlan(card);		/* go on*/
+	qeth_l3_start_ipa_multicast(card);		/* go on*/
+	qeth_l3_start_ipa_ipv6(card);		/* go on*/
+	qeth_l3_start_ipa_broadcast(card);		/* go on*/
+	qeth_l3_start_ipa_checksum(card);		/* go on*/
+	qeth_l3_start_ipa_tso(card);		/* go on*/
+	return 0;
+}
+
+static int qeth_l3_put_unique_id(struct qeth_card *card)
+{
+
+	int rc = 0;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 2, "puniqeid");
+
+	if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
+		UNIQUE_ID_NOT_BY_CARD)
+		return -1;
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
+				     QETH_PROT_IPV6);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
+				card->info.unique_id;
+	memcpy(&cmd->data.create_destroy_addr.unique_id[0],
+	       card->dev->dev_addr, OSA_ADDR_LEN);
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+	return rc;
+}
+
+static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code == 0)
+		memcpy(card->dev->dev_addr,
+			cmd->data.create_destroy_addr.unique_id, ETH_ALEN);
+	else
+		random_ether_addr(card->dev->dev_addr);
+
+	return 0;
+}
+
+static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
+{
+	int rc = 0;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(setup, 2, "hsrmac");
+
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
+				     QETH_PROT_IPV6);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
+			card->info.unique_id;
+
+	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_iqd_read_initial_mac_cb,
+				NULL);
+	return rc;
+}
+
+static int qeth_l3_get_unique_id_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code == 0)
+		card->info.unique_id = *((__u16 *)
+				&cmd->data.create_destroy_addr.unique_id[6]);
+	else {
+		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+					UNIQUE_ID_NOT_BY_CARD;
+		PRINT_WARN("couldn't get a unique id from the card on device "
+			   "%s (result=x%x), using default id. ipv6 "
+			   "autoconfig on other lpars may lead to duplicate "
+			   "ip addresses. please use manually "
+			   "configured ones.\n",
+			   CARD_BUS_ID(card), cmd->hdr.return_code);
+	}
+	return 0;
+}
+
+static int qeth_l3_get_unique_id(struct qeth_card *card)
+{
+	int rc = 0;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(setup, 2, "guniqeid");
+
+	if (!qeth_is_supported(card, IPA_IPV6)) {
+		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+					UNIQUE_ID_NOT_BY_CARD;
+		return 0;
+	}
+
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
+				     QETH_PROT_IPV6);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
+			card->info.unique_id;
+
+	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_get_unique_id_cb, NULL);
+	return rc;
+}
+
+static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac,
+				struct net_device *dev)
+{
+	if (dev->type == ARPHRD_IEEE802_TR)
+		ip_tr_mc_map(ipm, mac);
+	else
+		ip_eth_mc_map(ipm, mac);
+}
+
+static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
+{
+	struct qeth_ipaddr *ipm;
+	struct ip_mc_list *im4;
+	char buf[MAX_ADDR_LEN];
+
+	QETH_DBF_TEXT(trace, 4, "addmc");
+	for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
+		qeth_l3_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev);
+		ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
+		if (!ipm)
+			continue;
+		ipm->u.a4.addr = im4->multiaddr;
+		memcpy(ipm->mac, buf, OSA_ADDR_LEN);
+		ipm->is_multicast = 1;
+		if (!qeth_l3_add_ip(card, ipm))
+			kfree(ipm);
+	}
+}
+
+static void qeth_l3_add_vlan_mc(struct qeth_card *card)
+{
+	struct in_device *in_dev;
+	struct vlan_group *vg;
+	int i;
+
+	QETH_DBF_TEXT(trace, 4, "addmcvl");
+	if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+		return;
+
+	vg = card->vlangrp;
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		struct net_device *netdev = vlan_group_get_device(vg, i);
+		if (netdev == NULL ||
+		    !(netdev->flags & IFF_UP))
+			continue;
+		in_dev = in_dev_get(netdev);
+		if (!in_dev)
+			continue;
+		read_lock(&in_dev->mc_list_lock);
+		qeth_l3_add_mc(card, in_dev);
+		read_unlock(&in_dev->mc_list_lock);
+		in_dev_put(in_dev);
+	}
+}
+
+static void qeth_l3_add_multicast_ipv4(struct qeth_card *card)
+{
+	struct in_device *in4_dev;
+
+	QETH_DBF_TEXT(trace, 4, "chkmcv4");
+	in4_dev = in_dev_get(card->dev);
+	if (in4_dev == NULL)
+		return;
+	read_lock(&in4_dev->mc_list_lock);
+	qeth_l3_add_mc(card, in4_dev);
+	qeth_l3_add_vlan_mc(card);
+	read_unlock(&in4_dev->mc_list_lock);
+	in_dev_put(in4_dev);
+}
+
+#ifdef CONFIG_QETH_IPV6
+static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
+{
+	struct qeth_ipaddr *ipm;
+	struct ifmcaddr6 *im6;
+	char buf[MAX_ADDR_LEN];
+
+	QETH_DBF_TEXT(trace, 4, "addmc6");
+	for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
+		ndisc_mc_map(&im6->mca_addr, buf, in6_dev->dev, 0);
+		ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+		if (!ipm)
+			continue;
+		ipm->is_multicast = 1;
+		memcpy(ipm->mac, buf, OSA_ADDR_LEN);
+		memcpy(&ipm->u.a6.addr, &im6->mca_addr.s6_addr,
+		       sizeof(struct in6_addr));
+		if (!qeth_l3_add_ip(card, ipm))
+			kfree(ipm);
+	}
+}
+
+static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
+{
+	struct inet6_dev *in_dev;
+	struct vlan_group *vg;
+	int i;
+
+	QETH_DBF_TEXT(trace, 4, "admc6vl");
+	if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+		return;
+
+	vg = card->vlangrp;
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		struct net_device *netdev = vlan_group_get_device(vg, i);
+		if (netdev == NULL ||
+		    !(netdev->flags & IFF_UP))
+			continue;
+		in_dev = in6_dev_get(netdev);
+		if (!in_dev)
+			continue;
+		read_lock_bh(&in_dev->lock);
+		qeth_l3_add_mc6(card, in_dev);
+		read_unlock_bh(&in_dev->lock);
+		in6_dev_put(in_dev);
+	}
+}
+
+static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
+{
+	struct inet6_dev *in6_dev;
+
+	QETH_DBF_TEXT(trace, 4, "chkmcv6");
+	if (!qeth_is_supported(card, IPA_IPV6))
+		return ;
+	in6_dev = in6_dev_get(card->dev);
+	if (in6_dev == NULL)
+		return;
+	read_lock_bh(&in6_dev->lock);
+	qeth_l3_add_mc6(card, in6_dev);
+	qeth_l3_add_vlan_mc6(card);
+	read_unlock_bh(&in6_dev->lock);
+	in6_dev_put(in6_dev);
+}
+#endif /* CONFIG_QETH_IPV6 */
+
+static void qeth_l3_free_vlan_addresses4(struct qeth_card *card,
+			unsigned short vid)
+{
+	struct in_device *in_dev;
+	struct in_ifaddr *ifa;
+	struct qeth_ipaddr *addr;
+
+	QETH_DBF_TEXT(trace, 4, "frvaddr4");
+
+	in_dev = in_dev_get(vlan_group_get_device(card->vlangrp, vid));
+	if (!in_dev)
+		return;
+	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
+		addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
+		if (addr) {
+			addr->u.a4.addr = ifa->ifa_address;
+			addr->u.a4.mask = ifa->ifa_mask;
+			addr->type = QETH_IP_TYPE_NORMAL;
+			if (!qeth_l3_delete_ip(card, addr))
+				kfree(addr);
+		}
+	}
+	in_dev_put(in_dev);
+}
+
+static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
+			unsigned short vid)
+{
+#ifdef CONFIG_QETH_IPV6
+	struct inet6_dev *in6_dev;
+	struct inet6_ifaddr *ifa;
+	struct qeth_ipaddr *addr;
+
+	QETH_DBF_TEXT(trace, 4, "frvaddr6");
+
+	in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
+	if (!in6_dev)
+		return;
+	for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next) {
+		addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+		if (addr) {
+			memcpy(&addr->u.a6.addr, &ifa->addr,
+			       sizeof(struct in6_addr));
+			addr->u.a6.pfxlen = ifa->prefix_len;
+			addr->type = QETH_IP_TYPE_NORMAL;
+			if (!qeth_l3_delete_ip(card, addr))
+				kfree(addr);
+		}
+	}
+	in6_dev_put(in6_dev);
+#endif /* CONFIG_QETH_IPV6 */
+}
+
+static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
+			unsigned short vid)
+{
+	if (!card->vlangrp)
+		return;
+	qeth_l3_free_vlan_addresses4(card, vid);
+	qeth_l3_free_vlan_addresses6(card, vid);
+}
+
+static void qeth_l3_vlan_rx_register(struct net_device *dev,
+			struct vlan_group *grp)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	unsigned long flags;
+
+	QETH_DBF_TEXT(trace, 4, "vlanreg");
+	spin_lock_irqsave(&card->vlanlock, flags);
+	card->vlangrp = grp;
+	spin_unlock_irqrestore(&card->vlanlock, flags);
+}
+
+static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+{
+	struct net_device *vlandev;
+	struct qeth_card *card = (struct qeth_card *) dev->priv;
+	struct in_device *in_dev;
+
+	if (card->info.type == QETH_CARD_TYPE_IQD)
+		return;
+
+	vlandev = vlan_group_get_device(card->vlangrp, vid);
+	vlandev->neigh_setup = qeth_l3_neigh_setup;
+
+	in_dev = in_dev_get(vlandev);
+#ifdef CONFIG_SYSCTL
+	neigh_sysctl_unregister(in_dev->arp_parms);
+#endif
+	neigh_parms_release(&arp_tbl, in_dev->arp_parms);
+
+	in_dev->arp_parms = neigh_parms_alloc(vlandev, &arp_tbl);
+#ifdef CONFIG_SYSCTL
+	neigh_sysctl_register(vlandev, in_dev->arp_parms, NET_IPV4,
+			      NET_IPV4_NEIGH, "ipv4", NULL, NULL);
+#endif
+	in_dev_put(in_dev);
+	return;
+}
+
+static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	unsigned long flags;
+
+	QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
+	spin_lock_irqsave(&card->vlanlock, flags);
+	/* unregister IP addresses of vlan device */
+	qeth_l3_free_vlan_addresses(card, vid);
+	vlan_group_set_device(card->vlangrp, vid, NULL);
+	spin_unlock_irqrestore(&card->vlanlock, flags);
+	qeth_l3_set_multicast_list(card->dev);
+}
+
+static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
+			struct sk_buff *skb, struct qeth_hdr *hdr)
+{
+	unsigned short vlan_id = 0;
+	__be16 prot;
+	struct iphdr *ip_hdr;
+	unsigned char tg_addr[MAX_ADDR_LEN];
+
+	if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
+		prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
+			      ETH_P_IP);
+		switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK) {
+		case QETH_CAST_MULTICAST:
+			switch (prot) {
+#ifdef CONFIG_QETH_IPV6
+			case __constant_htons(ETH_P_IPV6):
+				ndisc_mc_map((struct in6_addr *)
+				     skb->data + 24,
+				     tg_addr, card->dev, 0);
+				break;
+#endif
+			case __constant_htons(ETH_P_IP):
+				ip_hdr = (struct iphdr *)skb->data;
+				(card->dev->type == ARPHRD_IEEE802_TR) ?
+				ip_tr_mc_map(ip_hdr->daddr, tg_addr):
+				ip_eth_mc_map(ip_hdr->daddr, tg_addr);
+				break;
+			default:
+				memcpy(tg_addr, card->dev->broadcast,
+					card->dev->addr_len);
+			}
+			card->stats.multicast++;
+			skb->pkt_type = PACKET_MULTICAST;
+			break;
+		case QETH_CAST_BROADCAST:
+			memcpy(tg_addr, card->dev->broadcast,
+				card->dev->addr_len);
+			card->stats.multicast++;
+			skb->pkt_type = PACKET_BROADCAST;
+			break;
+		case QETH_CAST_UNICAST:
+		case QETH_CAST_ANYCAST:
+		case QETH_CAST_NOCAST:
+		default:
+			skb->pkt_type = PACKET_HOST;
+			memcpy(tg_addr, card->dev->dev_addr,
+				card->dev->addr_len);
+		}
+		card->dev->header_ops->create(skb, card->dev, prot, tg_addr,
+					      "FAKELL", card->dev->addr_len);
+	}
+
+#ifdef CONFIG_TR
+	if (card->dev->type == ARPHRD_IEEE802_TR)
+		skb->protocol = tr_type_trans(skb, card->dev);
+	else
+#endif
+		skb->protocol = eth_type_trans(skb, card->dev);
+
+	if (hdr->hdr.l3.ext_flags &
+	    (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
+		vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
+		 hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
+	}
+
+	skb->ip_summed = card->options.checksum_type;
+	if (card->options.checksum_type == HW_CHECKSUMMING) {
+		if ((hdr->hdr.l3.ext_flags &
+		      (QETH_HDR_EXT_CSUM_HDR_REQ |
+		       QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
+		     (QETH_HDR_EXT_CSUM_HDR_REQ |
+		      QETH_HDR_EXT_CSUM_TRANSP_REQ))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb->ip_summed = SW_CHECKSUMMING;
+	}
+
+	return vlan_id;
+}
+
+static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
+			    struct qeth_qdio_buffer *buf, int index)
+{
+	struct qdio_buffer_element *element;
+	struct sk_buff *skb;
+	struct qeth_hdr *hdr;
+	int offset;
+	__u16 vlan_tag = 0;
+	unsigned int len;
+
+	/* get first element of current buffer */
+	element = (struct qdio_buffer_element *)&buf->buffer->element[0];
+	offset = 0;
+	if (card->options.performance_stats)
+		card->perf_stats.bufs_rec++;
+	while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
+				       &offset, &hdr))) {
+		skb->dev = card->dev;
+		/* is device UP ? */
+		if (!(card->dev->flags & IFF_UP)) {
+			dev_kfree_skb_any(skb);
+			continue;
+		}
+
+		switch (hdr->hdr.l3.id) {
+		case QETH_HEADER_TYPE_LAYER3:
+			vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
+			len = skb->len;
+			if (vlan_tag)
+				if (card->vlangrp)
+					vlan_hwaccel_rx(skb, card->vlangrp,
+						vlan_tag);
+				else {
+					dev_kfree_skb_any(skb);
+					continue;
+				}
+			else
+				netif_rx(skb);
+			break;
+		default:
+			dev_kfree_skb_any(skb);
+			QETH_DBF_TEXT(trace, 3, "inbunkno");
+			QETH_DBF_HEX(control, 3, hdr, QETH_DBF_CONTROL_LEN);
+			continue;
+		}
+
+		card->dev->last_rx = jiffies;
+		card->stats.rx_packets++;
+		card->stats.rx_bytes += len;
+	}
+}
+
+static int qeth_l3_verify_vlan_dev(struct net_device *dev,
+			struct qeth_card *card)
+{
+	int rc = 0;
+	struct vlan_group *vg;
+	int i;
+
+	vg = card->vlangrp;
+	if (!vg)
+		return rc;
+
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		if (vlan_group_get_device(vg, i) == dev) {
+			rc = QETH_VLAN_CARD;
+			break;
+		}
+	}
+
+	if (rc && !(netdev_priv(vlan_dev_info(dev)->real_dev) == (void *)card))
+		return 0;
+
+	return rc;
+}
+
+static int qeth_l3_verify_dev(struct net_device *dev)
+{
+	struct qeth_card *card;
+	unsigned long flags;
+	int rc = 0;
+
+	read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
+	list_for_each_entry(card, &qeth_core_card_list.list, list) {
+		if (card->dev == dev) {
+			rc = QETH_REAL_CARD;
+			break;
+		}
+		rc = qeth_l3_verify_vlan_dev(dev, card);
+		if (rc)
+			break;
+	}
+	read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
+
+	return rc;
+}
+
+static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
+{
+	struct qeth_card *card = NULL;
+	int rc;
+
+	rc = qeth_l3_verify_dev(dev);
+	if (rc == QETH_REAL_CARD)
+		card = netdev_priv(dev);
+	else if (rc == QETH_VLAN_CARD)
+		card = netdev_priv(vlan_dev_info(dev)->real_dev);
+	if (card->options.layer2)
+		card = NULL;
+	QETH_DBF_TEXT_(trace, 4, "%d", rc);
+	return card ;
+}
+
+static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
+{
+	int rc = 0;
+
+	QETH_DBF_TEXT(setup, 2, "stopcard");
+	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+
+	qeth_set_allowed_threads(card, 0, 1);
+	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
+		return -ERESTARTSYS;
+	if (card->read.state == CH_STATE_UP &&
+	    card->write.state == CH_STATE_UP &&
+	    (card->state == CARD_STATE_UP)) {
+		if (recovery_mode)
+			qeth_l3_stop(card->dev);
+		if (!card->use_hard_stop) {
+			rc = qeth_send_stoplan(card);
+			if (rc)
+				QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		}
+		card->state = CARD_STATE_SOFTSETUP;
+	}
+	if (card->state == CARD_STATE_SOFTSETUP) {
+		qeth_l3_clear_ip_list(card, !card->use_hard_stop, 1);
+		qeth_clear_ipacmd_list(card);
+		card->state = CARD_STATE_HARDSETUP;
+	}
+	if (card->state == CARD_STATE_HARDSETUP) {
+		if (!card->use_hard_stop &&
+		    (card->info.type != QETH_CARD_TYPE_IQD)) {
+			rc = qeth_l3_put_unique_id(card);
+			if (rc)
+				QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		}
+		qeth_qdio_clear_card(card, 0);
+		qeth_clear_qdio_buffers(card);
+		qeth_clear_working_pool_list(card);
+		card->state = CARD_STATE_DOWN;
+	}
+	if (card->state == CARD_STATE_DOWN) {
+		qeth_clear_cmd_buffers(&card->read);
+		qeth_clear_cmd_buffers(&card->write);
+	}
+	card->use_hard_stop = 0;
+	return rc;
+}
+
+static void qeth_l3_set_multicast_list(struct net_device *dev)
+{
+	struct qeth_card *card = netdev_priv(dev);
+
+	QETH_DBF_TEXT(trace, 3, "setmulti");
+	qeth_l3_delete_mc_addresses(card);
+	qeth_l3_add_multicast_ipv4(card);
+#ifdef CONFIG_QETH_IPV6
+	qeth_l3_add_multicast_ipv6(card);
+#endif
+	qeth_l3_set_ip_addr_list(card);
+	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+		return;
+	qeth_setadp_promisc_mode(card);
+}
+
+static const char *qeth_l3_arp_get_error_cause(int *rc)
+{
+	switch (*rc) {
+	case QETH_IPA_ARP_RC_FAILED:
+		*rc = -EIO;
+		return "operation failed";
+	case QETH_IPA_ARP_RC_NOTSUPP:
+		*rc = -EOPNOTSUPP;
+		return "operation not supported";
+	case QETH_IPA_ARP_RC_OUT_OF_RANGE:
+		*rc = -EINVAL;
+		return "argument out of range";
+	case QETH_IPA_ARP_RC_Q_NOTSUPP:
+		*rc = -EOPNOTSUPP;
+		return "query operation not supported";
+	case QETH_IPA_ARP_RC_Q_NO_DATA:
+		*rc = -ENOENT;
+		return "no query data available";
+	default:
+		return "unknown error";
+	}
+}
+
+static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
+{
+	int tmp;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "arpstnoe");
+
+	/*
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+	 * thus we say EOPNOTSUPP for this ARP function
+	 */
+	if (card->info.guestlan)
+		return -EOPNOTSUPP;
+	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
+		PRINT_WARN("ARP processing not supported "
+			   "on %s!\n", QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+	rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+					  IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
+					  no_entries);
+	if (rc) {
+		tmp = rc;
+		PRINT_WARN("Could not set number of ARP entries on %s: "
+			"%s (0x%x/%d)\n", QETH_CARD_IFNAME(card),
+			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
+	}
+	return rc;
+}
+
+static void qeth_l3_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
+		struct qeth_arp_query_data *qdata, int entry_size,
+		int uentry_size)
+{
+	char *entry_ptr;
+	char *uentry_ptr;
+	int i;
+
+	entry_ptr = (char *)&qdata->data;
+	uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset);
+	for (i = 0; i < qdata->no_entries; ++i) {
+		/* strip off 32 bytes "media specific information" */
+		memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32);
+		entry_ptr += entry_size;
+		uentry_ptr += uentry_size;
+	}
+}
+
+static int qeth_l3_arp_query_cb(struct qeth_card *card,
+		struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_arp_query_data *qdata;
+	struct qeth_arp_query_info *qinfo;
+	int entry_size;
+	int uentry_size;
+	int i;
+
+	QETH_DBF_TEXT(trace, 4, "arpquecb");
+
+	qinfo = (struct qeth_arp_query_info *) reply->param;
+	cmd = (struct qeth_ipa_cmd *) data;
+	if (cmd->hdr.return_code) {
+		QETH_DBF_TEXT_(trace, 4, "qaer1%i", cmd->hdr.return_code);
+		return 0;
+	}
+	if (cmd->data.setassparms.hdr.return_code) {
+		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+		QETH_DBF_TEXT_(trace, 4, "qaer2%i", cmd->hdr.return_code);
+		return 0;
+	}
+	qdata = &cmd->data.setassparms.data.query_arp;
+	switch (qdata->reply_bits) {
+	case 5:
+		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5);
+		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+			uentry_size = sizeof(struct qeth_arp_qi_entry5_short);
+		break;
+	case 7:
+		/* fall through to default */
+	default:
+		/* tr is the same as eth -> entry7 */
+		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7);
+		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+			uentry_size = sizeof(struct qeth_arp_qi_entry7_short);
+		break;
+	}
+	/* check if there is enough room in userspace */
+	if ((qinfo->udata_len - qinfo->udata_offset) <
+			qdata->no_entries * uentry_size){
+		QETH_DBF_TEXT_(trace, 4, "qaer3%i", -ENOMEM);
+		cmd->hdr.return_code = -ENOMEM;
+		PRINT_WARN("query ARP user space buffer is too small for "
+			   "the returned number of ARP entries. "
+			   "Aborting query!\n");
+		goto out_error;
+	}
+	QETH_DBF_TEXT_(trace, 4, "anore%i",
+		       cmd->data.setassparms.hdr.number_of_replies);
+	QETH_DBF_TEXT_(trace, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no);
+	QETH_DBF_TEXT_(trace, 4, "anoen%i", qdata->no_entries);
+
+	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) {
+		/* strip off "media specific information" */
+		qeth_l3_copy_arp_entries_stripped(qinfo, qdata, entry_size,
+					       uentry_size);
+	} else
+		/*copy entries to user buffer*/
+		memcpy(qinfo->udata + qinfo->udata_offset,
+		       (char *)&qdata->data, qdata->no_entries*uentry_size);
+
+	qinfo->no_entries += qdata->no_entries;
+	qinfo->udata_offset += (qdata->no_entries*uentry_size);
+	/* check if all replies received ... */
+	if (cmd->data.setassparms.hdr.seq_no <
+	    cmd->data.setassparms.hdr.number_of_replies)
+		return 1;
+	memcpy(qinfo->udata, &qinfo->no_entries, 4);
+	/* keep STRIP_ENTRIES flag so the user program can distinguish
+	 * stripped entries from normal ones */
+	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+		qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
+	memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2);
+	return 0;
+out_error:
+	i = 0;
+	memcpy(qinfo->udata, &i, 4);
+	return 0;
+}
+
+static int qeth_l3_send_ipa_arp_cmd(struct qeth_card *card,
+		struct qeth_cmd_buffer *iob, int len,
+		int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
+			unsigned long),
+		void *reply_param)
+{
+	QETH_DBF_TEXT(trace, 4, "sendarp");
+
+	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+				      reply_cb, reply_param);
+}
+
+static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
+{
+	struct qeth_cmd_buffer *iob;
+	struct qeth_arp_query_info qinfo = {0, };
+	int tmp;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "arpquery");
+
+	if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
+			       IPA_ARP_PROCESSING)) {
+		PRINT_WARN("ARP processing not supported "
+			   "on %s!\n", QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+	/* get size of userspace buffer and mask_bits -> 6 bytes */
+	if (copy_from_user(&qinfo, udata, 6))
+		return -EFAULT;
+	qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
+	if (!qinfo.udata)
+		return -ENOMEM;
+	qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
+	iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+				       IPA_CMD_ASS_ARP_QUERY_INFO,
+				       sizeof(int), QETH_PROT_IPV4);
+
+	rc = qeth_l3_send_ipa_arp_cmd(card, iob,
+				   QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
+				   qeth_l3_arp_query_cb, (void *)&qinfo);
+	if (rc) {
+		tmp = rc;
+		PRINT_WARN("Error while querying ARP cache on %s: %s "
+			"(0x%x/%d)\n", QETH_CARD_IFNAME(card),
+			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
+		if (copy_to_user(udata, qinfo.udata, 4))
+			rc = -EFAULT;
+	} else {
+		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+			rc = -EFAULT;
+	}
+	kfree(qinfo.udata);
+	return rc;
+}
+
+static int qeth_l3_arp_add_entry(struct qeth_card *card,
+				struct qeth_arp_cache_entry *entry)
+{
+	struct qeth_cmd_buffer *iob;
+	char buf[16];
+	int tmp;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "arpadent");
+
+	/*
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+	 * thus we say EOPNOTSUPP for this ARP function
+	 */
+	if (card->info.guestlan)
+		return -EOPNOTSUPP;
+	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
+		PRINT_WARN("ARP processing not supported "
+			   "on %s!\n", QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+
+	iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+				       IPA_CMD_ASS_ARP_ADD_ENTRY,
+				       sizeof(struct qeth_arp_cache_entry),
+				       QETH_PROT_IPV4);
+	rc = qeth_l3_send_setassparms(card, iob,
+				   sizeof(struct qeth_arp_cache_entry),
+				   (unsigned long) entry,
+				   qeth_l3_default_setassparms_cb, NULL);
+	if (rc) {
+		tmp = rc;
+		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+		PRINT_WARN("Could not add ARP entry for address %s on %s: "
+			   "%s (0x%x/%d)\n",
+			   buf, QETH_CARD_IFNAME(card),
+			   qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
+	}
+	return rc;
+}
+
+static int qeth_l3_arp_remove_entry(struct qeth_card *card,
+				struct qeth_arp_cache_entry *entry)
+{
+	struct qeth_cmd_buffer *iob;
+	char buf[16] = {0, };
+	int tmp;
+	int rc;
+
+	QETH_DBF_TEXT(trace, 3, "arprment");
+
+	/*
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+	 * thus we say EOPNOTSUPP for this ARP function
+	 */
+	if (card->info.guestlan)
+		return -EOPNOTSUPP;
+	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
+		PRINT_WARN("ARP processing not supported "
+			   "on %s!\n", QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+	memcpy(buf, entry, 12);
+	iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+				       IPA_CMD_ASS_ARP_REMOVE_ENTRY,
+				       12,
+				       QETH_PROT_IPV4);
+	rc = qeth_l3_send_setassparms(card, iob,
+				   12, (unsigned long)buf,
+				   qeth_l3_default_setassparms_cb, NULL);
+	if (rc) {
+		tmp = rc;
+		memset(buf, 0, 16);
+		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+		PRINT_WARN("Could not delete ARP entry for address %s on %s: "
+			   "%s (0x%x/%d)\n",
+			   buf, QETH_CARD_IFNAME(card),
+			   qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
+	}
+	return rc;
+}
+
+static int qeth_l3_arp_flush_cache(struct qeth_card *card)
+{
+	int rc;
+	int tmp;
+
+	QETH_DBF_TEXT(trace, 3, "arpflush");
+
+	/*
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+	 * thus we say EOPNOTSUPP for this ARP function
+	*/
+	if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
+		return -EOPNOTSUPP;
+	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
+		PRINT_WARN("ARP processing not supported "
+			   "on %s!\n", QETH_CARD_IFNAME(card));
+		return -EOPNOTSUPP;
+	}
+	rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+					  IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
+	if (rc) {
+		tmp = rc;
+		PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n",
+			QETH_CARD_IFNAME(card),
+			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
+	}
+	return rc;
+}
+
+static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	struct qeth_arp_cache_entry arp_entry;
+	struct mii_ioctl_data *mii_data;
+	int rc = 0;
+
+	if (!card)
+		return -ENODEV;
+
+	if ((card->state != CARD_STATE_UP) &&
+		(card->state != CARD_STATE_SOFTSETUP))
+		return -ENODEV;
+
+	switch (cmd) {
+	case SIOC_QETH_ARP_SET_NO_ENTRIES:
+		if (!capable(CAP_NET_ADMIN)) {
+			rc = -EPERM;
+			break;
+		}
+		rc = qeth_l3_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
+		break;
+	case SIOC_QETH_ARP_QUERY_INFO:
+		if (!capable(CAP_NET_ADMIN)) {
+			rc = -EPERM;
+			break;
+		}
+		rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data);
+		break;
+	case SIOC_QETH_ARP_ADD_ENTRY:
+		if (!capable(CAP_NET_ADMIN)) {
+			rc = -EPERM;
+			break;
+		}
+		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+				   sizeof(struct qeth_arp_cache_entry)))
+			rc = -EFAULT;
+		else
+			rc = qeth_l3_arp_add_entry(card, &arp_entry);
+		break;
+	case SIOC_QETH_ARP_REMOVE_ENTRY:
+		if (!capable(CAP_NET_ADMIN)) {
+			rc = -EPERM;
+			break;
+		}
+		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+				   sizeof(struct qeth_arp_cache_entry)))
+			rc = -EFAULT;
+		else
+			rc = qeth_l3_arp_remove_entry(card, &arp_entry);
+		break;
+	case SIOC_QETH_ARP_FLUSH_CACHE:
+		if (!capable(CAP_NET_ADMIN)) {
+			rc = -EPERM;
+			break;
+		}
+		rc = qeth_l3_arp_flush_cache(card);
+		break;
+	case SIOC_QETH_ADP_SET_SNMP_CONTROL:
+		rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
+		break;
+	case SIOC_QETH_GET_CARD_TYPE:
+		if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
+		    !card->info.guestlan)
+			return 1;
+		return 0;
+		break;
+	case SIOCGMIIPHY:
+		mii_data = if_mii(rq);
+		mii_data->phy_id = 0;
+		break;
+	case SIOCGMIIREG:
+		mii_data = if_mii(rq);
+		if (mii_data->phy_id != 0)
+			rc = -EINVAL;
+		else
+			mii_data->val_out = qeth_mdio_read(dev,
+							mii_data->phy_id,
+							mii_data->reg_num);
+		break;
+	default:
+		rc = -EOPNOTSUPP;
+	}
+	if (rc)
+		QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
+	return rc;
+}
+
+static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+		struct sk_buff *skb, int ipv, int cast_type)
+{
+	QETH_DBF_TEXT(trace, 6, "fillhdr");
+
+	memset(hdr, 0, sizeof(struct qeth_hdr));
+	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
+	hdr->hdr.l3.ext_flags = 0;
+
+	/*
+	 * before we're going to overwrite this location with next hop ip.
+	 * v6 uses passthrough, v4 sets the tag in the QDIO header.
+	 */
+	if (card->vlangrp && vlan_tx_tag_present(skb)) {
+		hdr->hdr.l3.ext_flags = (ipv == 4) ?
+			QETH_HDR_EXT_VLAN_FRAME :
+			QETH_HDR_EXT_INCLUDE_VLAN_TAG;
+		hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
+	}
+
+	hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+	if (ipv == 4) {
+		/* IPv4 */
+		hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type);
+		memset(hdr->hdr.l3.dest_addr, 0, 12);
+		if ((skb->dst) && (skb->dst->neighbour)) {
+			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
+			    *((u32 *) skb->dst->neighbour->primary_key);
+		} else {
+			/* fill in destination address used in ip header */
+			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
+							ip_hdr(skb)->daddr;
+		}
+	} else if (ipv == 6) {
+		/* IPv6 */
+		hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type);
+		if (card->info.type == QETH_CARD_TYPE_IQD)
+			hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU;
+		if ((skb->dst) && (skb->dst->neighbour)) {
+			memcpy(hdr->hdr.l3.dest_addr,
+			       skb->dst->neighbour->primary_key, 16);
+		} else {
+			/* fill in destination address used in ip header */
+			memcpy(hdr->hdr.l3.dest_addr,
+			       &ipv6_hdr(skb)->daddr, 16);
+		}
+	} else {
+		/* passthrough */
+		if ((skb->dev->type == ARPHRD_IEEE802_TR) &&
+			!memcmp(skb->data + sizeof(struct qeth_hdr) +
+			sizeof(__u16), skb->dev->broadcast, 6)) {
+			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+						QETH_HDR_PASSTHRU;
+		} else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
+			    skb->dev->broadcast, 6)) {
+			/* broadcast? */
+			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+						QETH_HDR_PASSTHRU;
+		} else {
+			hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
+				QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
+				QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
+		}
+	}
+}
+
+static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int rc;
+	u16 *tag;
+	struct qeth_hdr *hdr = NULL;
+	int elements_needed = 0;
+	struct qeth_card *card = netdev_priv(dev);
+	struct sk_buff *new_skb = NULL;
+	int ipv = qeth_get_ip_version(skb);
+	int cast_type = qeth_get_cast_type(card, skb);
+	struct qeth_qdio_out_q *queue = card->qdio.out_qs
+		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
+	int tx_bytes = skb->len;
+	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
+	struct qeth_eddp_context *ctx = NULL;
+
+	QETH_DBF_TEXT(trace, 6, "l3xmit");
+
+	if ((card->info.type == QETH_CARD_TYPE_IQD) &&
+	    (skb->protocol != htons(ETH_P_IPV6)) &&
+	    (skb->protocol != htons(ETH_P_IP)))
+			goto tx_drop;
+
+	if ((card->state != CARD_STATE_UP) || !card->lan_online) {
+		card->stats.tx_carrier_errors++;
+		goto tx_drop;
+	}
+
+	if ((cast_type == RTN_BROADCAST) &&
+	    (card->info.broadcast_capable == 0))
+		goto tx_drop;
+
+	if (card->options.performance_stats) {
+		card->perf_stats.outbound_cnt++;
+		card->perf_stats.outbound_start_time = qeth_get_micros();
+	}
+
+	/* create a clone with writeable headroom */
+	new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso) +
+					VLAN_HLEN);
+	if (!new_skb)
+		goto tx_drop;
+
+	if (card->info.type == QETH_CARD_TYPE_IQD) {
+		skb_pull(new_skb, ETH_HLEN);
+	} else {
+		if (new_skb->protocol == htons(ETH_P_IP)) {
+			if (card->dev->type == ARPHRD_IEEE802_TR)
+				skb_pull(new_skb, TR_HLEN);
+			else
+				skb_pull(new_skb, ETH_HLEN);
+		}
+
+		if (new_skb->protocol == ETH_P_IPV6 && card->vlangrp &&
+				vlan_tx_tag_present(new_skb)) {
+			skb_push(new_skb, VLAN_HLEN);
+			skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
+			skb_copy_to_linear_data_offset(new_skb, 4,
+				new_skb->data + 8, 4);
+			skb_copy_to_linear_data_offset(new_skb, 8,
+				new_skb->data + 12, 4);
+			tag = (u16 *)(new_skb->data + 12);
+			*tag = __constant_htons(ETH_P_8021Q);
+			*(tag + 1) = htons(vlan_tx_tag_get(new_skb));
+			VLAN_TX_SKB_CB(new_skb)->magic = 0;
+		}
+	}
+
+	netif_stop_queue(dev);
+
+	if (skb_is_gso(new_skb))
+		large_send = card->options.large_send;
+
+	/* fix hardware limitation: as long as we do not have sbal
+	 * chaining we can not send long frag lists so we temporary
+	 * switch to EDDP
+	 */
+	if ((large_send == QETH_LARGE_SEND_TSO) &&
+		((skb_shinfo(new_skb)->nr_frags + 2) > 16))
+		large_send = QETH_LARGE_SEND_EDDP;
+
+	if ((large_send == QETH_LARGE_SEND_TSO) &&
+	    (cast_type == RTN_UNSPEC)) {
+		hdr = (struct qeth_hdr *)skb_push(new_skb,
+						sizeof(struct qeth_hdr_tso));
+		memset(hdr, 0, sizeof(struct qeth_hdr_tso));
+		qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
+		qeth_tso_fill_header(card, hdr, new_skb);
+		elements_needed++;
+	} else {
+		hdr = (struct qeth_hdr *)skb_push(new_skb,
+						sizeof(struct qeth_hdr));
+		qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
+	}
+
+	if (large_send == QETH_LARGE_SEND_EDDP) {
+		/* new_skb is not owned by a socket so we use skb to get
+		 * the protocol
+		 */
+		ctx = qeth_eddp_create_context(card, new_skb, hdr,
+						skb->sk->sk_protocol);
+		if (ctx == NULL) {
+			PRINT_WARN("could not create eddp context\n");
+			goto tx_drop;
+		}
+	} else {
+		int elems = qeth_get_elements_no(card, (void *)hdr, new_skb,
+						 elements_needed);
+		if (!elems)
+			goto tx_drop;
+		elements_needed += elems;
+	}
+
+	if ((large_send == QETH_LARGE_SEND_NO) &&
+	    (new_skb->ip_summed == CHECKSUM_PARTIAL))
+		qeth_tx_csum(new_skb);
+
+	if (card->info.type != QETH_CARD_TYPE_IQD)
+		rc = qeth_do_send_packet(card, queue, new_skb, hdr,
+					 elements_needed, ctx);
+	else
+		rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
+					      elements_needed, ctx);
+
+	if (!rc) {
+		card->stats.tx_packets++;
+		card->stats.tx_bytes += tx_bytes;
+		if (new_skb != skb)
+			dev_kfree_skb_any(skb);
+		if (card->options.performance_stats) {
+			if (large_send != QETH_LARGE_SEND_NO) {
+				card->perf_stats.large_send_bytes += tx_bytes;
+				card->perf_stats.large_send_cnt++;
+			}
+			if (skb_shinfo(new_skb)->nr_frags > 0) {
+				card->perf_stats.sg_skbs_sent++;
+				/* nr_frags + skb->data */
+				card->perf_stats.sg_frags_sent +=
+					skb_shinfo(new_skb)->nr_frags + 1;
+			}
+		}
+
+		if (ctx != NULL) {
+			qeth_eddp_put_context(ctx);
+			dev_kfree_skb_any(new_skb);
+		}
+	} else {
+		if (ctx != NULL)
+			qeth_eddp_put_context(ctx);
+
+		if (rc == -EBUSY) {
+			if (new_skb != skb)
+				dev_kfree_skb_any(new_skb);
+			return NETDEV_TX_BUSY;
+		} else
+			goto tx_drop;
+	}
+
+	netif_wake_queue(dev);
+	if (card->options.performance_stats)
+		card->perf_stats.outbound_time += qeth_get_micros() -
+			card->perf_stats.outbound_start_time;
+	return rc;
+
+tx_drop:
+	card->stats.tx_dropped++;
+	card->stats.tx_errors++;
+	if ((new_skb != skb) && new_skb)
+		dev_kfree_skb_any(new_skb);
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static int qeth_l3_open(struct net_device *dev)
+{
+	struct qeth_card *card = netdev_priv(dev);
+
+	QETH_DBF_TEXT(trace, 4, "qethopen");
+	if (card->state != CARD_STATE_SOFTSETUP)
+		return -ENODEV;
+	card->data.state = CH_STATE_UP;
+	card->state = CARD_STATE_UP;
+	card->dev->flags |= IFF_UP;
+	netif_start_queue(dev);
+
+	if (!card->lan_online && netif_carrier_ok(dev))
+		netif_carrier_off(dev);
+	return 0;
+}
+
+static int qeth_l3_stop(struct net_device *dev)
+{
+	struct qeth_card *card = netdev_priv(dev);
+
+	QETH_DBF_TEXT(trace, 4, "qethstop");
+	netif_tx_disable(dev);
+	card->dev->flags &= ~IFF_UP;
+	if (card->state == CARD_STATE_UP)
+		card->state = CARD_STATE_SOFTSETUP;
+	return 0;
+}
+
+static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev)
+{
+	struct qeth_card *card = netdev_priv(dev);
+
+	return (card->options.checksum_type == HW_CHECKSUMMING);
+}
+
+static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct qeth_card *card = netdev_priv(dev);
+	enum qeth_card_states old_state;
+	enum qeth_checksum_types csum_type;
+
+	if ((card->state != CARD_STATE_UP) &&
+	    (card->state != CARD_STATE_DOWN))
+		return -EPERM;
+
+	if (data)
+		csum_type = HW_CHECKSUMMING;
+	else
+		csum_type = SW_CHECKSUMMING;
+
+	if (card->options.checksum_type != csum_type) {
+		old_state = card->state;
+		if (card->state == CARD_STATE_UP)
+			__qeth_l3_set_offline(card->gdev, 1);
+		card->options.checksum_type = csum_type;
+		if (old_state == CARD_STATE_UP)
+			__qeth_l3_set_online(card->gdev, 1);
+	}
+	return 0;
+}
+
+static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
+{
+	struct qeth_card *card = netdev_priv(dev);
+
+	if (data) {
+		if (card->options.large_send == QETH_LARGE_SEND_NO) {
+			if (card->info.type == QETH_CARD_TYPE_IQD)
+				card->options.large_send = QETH_LARGE_SEND_EDDP;
+			else
+				card->options.large_send = QETH_LARGE_SEND_TSO;
+			dev->features |= NETIF_F_TSO;
+		}
+	} else {
+		dev->features &= ~NETIF_F_TSO;
+		card->options.large_send = QETH_LARGE_SEND_NO;
+	}
+	return 0;
+}
+
+static struct ethtool_ops qeth_l3_ethtool_ops = {
+	.get_link = ethtool_op_get_link,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_hw_csum,
+	.get_rx_csum = qeth_l3_ethtool_get_rx_csum,
+	.set_rx_csum = qeth_l3_ethtool_set_rx_csum,
+	.get_sg      = ethtool_op_get_sg,
+	.set_sg      = ethtool_op_set_sg,
+	.get_tso     = ethtool_op_get_tso,
+	.set_tso     = qeth_l3_ethtool_set_tso,
+	.get_strings = qeth_core_get_strings,
+	.get_ethtool_stats = qeth_core_get_ethtool_stats,
+	.get_stats_count = qeth_core_get_stats_count,
+	.get_drvinfo = qeth_core_get_drvinfo,
+};
+
+/*
+ * we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting
+ * NOARP on the netdevice is no option because it also turns off neighbor
+ * solicitation. For IPv4 we install a neighbor_setup function. We don't want
+ * arp resolution but we want the hard header (packet socket will work
+ * e.g. tcpdump)
+ */
+static int qeth_l3_neigh_setup_noarp(struct neighbour *n)
+{
+	n->nud_state = NUD_NOARP;
+	memcpy(n->ha, "FAKELL", 6);
+	n->output = n->ops->connected_output;
+	return 0;
+}
+
+static int
+qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
+{
+	if (np->tbl->family == AF_INET)
+		np->neigh_setup = qeth_l3_neigh_setup_noarp;
+
+	return 0;
+}
+
+static int qeth_l3_setup_netdev(struct qeth_card *card)
+{
+	if (card->info.type == QETH_CARD_TYPE_OSAE) {
+		if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
+		    (card->info.link_type == QETH_LINK_TYPE_HSTR)) {
+#ifdef CONFIG_TR
+			card->dev = alloc_trdev(0);
+#endif
+			if (!card->dev)
+				return -ENODEV;
+		} else {
+			card->dev = alloc_etherdev(0);
+			if (!card->dev)
+				return -ENODEV;
+			card->dev->neigh_setup = qeth_l3_neigh_setup;
+
+			/*IPv6 address autoconfiguration stuff*/
+			qeth_l3_get_unique_id(card);
+			if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
+				card->dev->dev_id = card->info.unique_id &
+							 0xffff;
+		}
+	} else if (card->info.type == QETH_CARD_TYPE_IQD) {
+		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
+		if (!card->dev)
+			return -ENODEV;
+		card->dev->flags |= IFF_NOARP;
+		qeth_l3_iqd_read_initial_mac(card);
+	} else
+		return -ENODEV;
+
+	card->dev->hard_start_xmit = qeth_l3_hard_start_xmit;
+	card->dev->priv = card;
+	card->dev->tx_timeout = &qeth_tx_timeout;
+	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
+	card->dev->open = qeth_l3_open;
+	card->dev->stop = qeth_l3_stop;
+	card->dev->do_ioctl = qeth_l3_do_ioctl;
+	card->dev->get_stats = qeth_get_stats;
+	card->dev->change_mtu = qeth_change_mtu;
+	card->dev->set_multicast_list = qeth_l3_set_multicast_list;
+	card->dev->vlan_rx_register = qeth_l3_vlan_rx_register;
+	card->dev->vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid;
+	card->dev->vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid;
+	card->dev->mtu = card->info.initial_mtu;
+	SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
+	card->dev->features |=	NETIF_F_HW_VLAN_TX |
+				NETIF_F_HW_VLAN_RX |
+				NETIF_F_HW_VLAN_FILTER;
+
+	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+	return register_netdev(card->dev);
+}
+
+static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
+		unsigned int status, unsigned int qdio_err,
+		unsigned int siga_err, unsigned int queue, int first_element,
+		int count, unsigned long card_ptr)
+{
+	struct net_device *net_dev;
+	struct qeth_card *card;
+	struct qeth_qdio_buffer *buffer;
+	int index;
+	int i;
+
+	QETH_DBF_TEXT(trace, 6, "qdinput");
+	card = (struct qeth_card *) card_ptr;
+	net_dev = card->dev;
+	if (card->options.performance_stats) {
+		card->perf_stats.inbound_cnt++;
+		card->perf_stats.inbound_start_time = qeth_get_micros();
+	}
+	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
+			QETH_DBF_TEXT(trace, 1, "qdinchk");
+			QETH_DBF_TEXT_(trace, 1, "%s", CARD_BUS_ID(card));
+			QETH_DBF_TEXT_(trace, 1, "%04X%04X",
+					first_element, count);
+			QETH_DBF_TEXT_(trace, 1, "%04X%04X", queue, status);
+			qeth_schedule_recovery(card);
+			return;
+		}
+	}
+	for (i = first_element; i < (first_element + count); ++i) {
+		index = i % QDIO_MAX_BUFFERS_PER_Q;
+		buffer = &card->qdio.in_q->bufs[index];
+		if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
+		      qeth_check_qdio_errors(buffer->buffer,
+					     qdio_err, siga_err, "qinerr")))
+			qeth_l3_process_inbound_buffer(card, buffer, index);
+		/* clear buffer and give back to hardware */
+		qeth_put_buffer_pool_entry(card, buffer->pool_entry);
+		qeth_queue_input_buffer(card, index);
+	}
+	if (card->options.performance_stats)
+		card->perf_stats.inbound_time += qeth_get_micros() -
+			card->perf_stats.inbound_start_time;
+}
+
+static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+
+	qeth_l3_create_device_attributes(&gdev->dev);
+	card->options.layer2 = 0;
+	card->discipline.input_handler = (qdio_handler_t *)
+		qeth_l3_qdio_input_handler;
+	card->discipline.output_handler = (qdio_handler_t *)
+		qeth_qdio_output_handler;
+	card->discipline.recover = qeth_l3_recover;
+	return 0;
+}
+
+static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
+
+	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+
+	if (cgdev->state == CCWGROUP_ONLINE) {
+		card->use_hard_stop = 1;
+		qeth_l3_set_offline(cgdev);
+	}
+
+	if (card->dev) {
+		unregister_netdev(card->dev);
+		card->dev = NULL;
+	}
+
+	qeth_l3_remove_device_attributes(&cgdev->dev);
+	qeth_l3_clear_ip_list(card, 0, 0);
+	qeth_l3_clear_ipato_list(card);
+	return;
+}
+
+static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	int rc = 0;
+	enum qeth_card_states recover_flag;
+
+	BUG_ON(!card);
+	QETH_DBF_TEXT(setup, 2, "setonlin");
+	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+
+	qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
+	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) {
+		PRINT_WARN("set_online of card %s interrupted by user!\n",
+			   CARD_BUS_ID(card));
+		return -ERESTARTSYS;
+	}
+
+	recover_flag = card->state;
+	rc = ccw_device_set_online(CARD_RDEV(card));
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return -EIO;
+	}
+	rc = ccw_device_set_online(CARD_WDEV(card));
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return -EIO;
+	}
+	rc = ccw_device_set_online(CARD_DDEV(card));
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		return -EIO;
+	}
+
+	rc = qeth_core_hardsetup_card(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+		goto out_remove;
+	}
+
+	qeth_l3_query_ipassists(card, QETH_PROT_IPV4);
+
+	if (!card->dev && qeth_l3_setup_netdev(card))
+		goto out_remove;
+
+	card->state = CARD_STATE_HARDSETUP;
+	qeth_print_status_message(card);
+
+	/* softsetup */
+	QETH_DBF_TEXT(setup, 2, "softsetp");
+
+	rc = qeth_send_startlan(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+		if (rc == 0xe080) {
+			PRINT_WARN("LAN on card %s if offline! "
+				   "Waiting for STARTLAN from card.\n",
+				   CARD_BUS_ID(card));
+			card->lan_online = 0;
+		}
+		return rc;
+	} else
+		card->lan_online = 1;
+	qeth_set_large_send(card, card->options.large_send);
+
+	rc = qeth_l3_setadapter_parms(card);
+	if (rc)
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+	rc = qeth_l3_start_ipassists(card);
+	if (rc)
+		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+	rc = qeth_l3_setrouting_v4(card);
+	if (rc)
+		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+	rc = qeth_l3_setrouting_v6(card);
+	if (rc)
+		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+	netif_tx_disable(card->dev);
+
+	rc = qeth_init_qdio_queues(card);
+	if (rc) {
+		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+		goto out_remove;
+	}
+	card->state = CARD_STATE_SOFTSETUP;
+	netif_carrier_on(card->dev);
+
+	qeth_set_allowed_threads(card, 0xffffffff, 0);
+	if ((recover_flag == CARD_STATE_RECOVER) && recovery_mode) {
+			qeth_l3_open(card->dev);
+			qeth_l3_set_multicast_list(card->dev);
+	}
+	/* let user_space know that device is online */
+	kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
+	return 0;
+out_remove:
+	card->use_hard_stop = 1;
+	qeth_l3_stop_card(card, 0);
+	ccw_device_set_offline(CARD_DDEV(card));
+	ccw_device_set_offline(CARD_WDEV(card));
+	ccw_device_set_offline(CARD_RDEV(card));
+	if (recover_flag == CARD_STATE_RECOVER)
+		card->state = CARD_STATE_RECOVER;
+	else
+		card->state = CARD_STATE_DOWN;
+	return -ENODEV;
+}
+
+static int qeth_l3_set_online(struct ccwgroup_device *gdev)
+{
+	return __qeth_l3_set_online(gdev, 0);
+}
+
+static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
+			int recovery_mode)
+{
+	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
+	int rc = 0, rc2 = 0, rc3 = 0;
+	enum qeth_card_states recover_flag;
+
+	QETH_DBF_TEXT(setup, 3, "setoffl");
+	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+
+	if (card->dev && netif_carrier_ok(card->dev))
+		netif_carrier_off(card->dev);
+	recover_flag = card->state;
+	if (qeth_l3_stop_card(card, recovery_mode) == -ERESTARTSYS) {
+		PRINT_WARN("Stopping card %s interrupted by user!\n",
+			   CARD_BUS_ID(card));
+		return -ERESTARTSYS;
+	}
+	rc  = ccw_device_set_offline(CARD_DDEV(card));
+	rc2 = ccw_device_set_offline(CARD_WDEV(card));
+	rc3 = ccw_device_set_offline(CARD_RDEV(card));
+	if (!rc)
+		rc = (rc2) ? rc2 : rc3;
+	if (rc)
+		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+	if (recover_flag == CARD_STATE_UP)
+		card->state = CARD_STATE_RECOVER;
+	/* let user_space know that device is offline */
+	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
+	return 0;
+}
+
+static int qeth_l3_set_offline(struct ccwgroup_device *cgdev)
+{
+	return __qeth_l3_set_offline(cgdev, 0);
+}
+
+static int qeth_l3_recover(void *ptr)
+{
+	struct qeth_card *card;
+	int rc = 0;
+
+	card = (struct qeth_card *) ptr;
+	QETH_DBF_TEXT(trace, 2, "recover1");
+	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
+		return 0;
+	QETH_DBF_TEXT(trace, 2, "recover2");
+	PRINT_WARN("Recovery of device %s started ...\n",
+		   CARD_BUS_ID(card));
+	card->use_hard_stop = 1;
+	__qeth_l3_set_offline(card->gdev, 1);
+	rc = __qeth_l3_set_online(card->gdev, 1);
+	/* don't run another scheduled recovery */
+	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
+	if (!rc)
+		PRINT_INFO("Device %s successfully recovered!\n",
+			   CARD_BUS_ID(card));
+	else
+		PRINT_INFO("Device %s could not be recovered!\n",
+			   CARD_BUS_ID(card));
+	return 0;
+}
+
+static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	qeth_l3_clear_ip_list(card, 0, 0);
+	qeth_qdio_clear_card(card, 0);
+	qeth_clear_qdio_buffers(card);
+}
+
+struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
+	.probe = qeth_l3_probe_device,
+	.remove = qeth_l3_remove_device,
+	.set_online = qeth_l3_set_online,
+	.set_offline = qeth_l3_set_offline,
+	.shutdown = qeth_l3_shutdown,
+};
+EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver);
+
+static int qeth_l3_ip_event(struct notifier_block *this,
+			    unsigned long event, void *ptr)
+{
+	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+	struct net_device *dev = (struct net_device *)ifa->ifa_dev->dev;
+	struct qeth_ipaddr *addr;
+	struct qeth_card *card;
+
+	if (dev->nd_net != &init_net)
+		return NOTIFY_DONE;
+
+	QETH_DBF_TEXT(trace, 3, "ipevent");
+	card = qeth_l3_get_card_from_dev(dev);
+	if (!card)
+		return NOTIFY_DONE;
+
+	addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
+	if (addr != NULL) {
+		addr->u.a4.addr = ifa->ifa_address;
+		addr->u.a4.mask = ifa->ifa_mask;
+		addr->type = QETH_IP_TYPE_NORMAL;
+	} else
+		goto out;
+
+	switch (event) {
+	case NETDEV_UP:
+		if (!qeth_l3_add_ip(card, addr))
+			kfree(addr);
+		break;
+	case NETDEV_DOWN:
+		if (!qeth_l3_delete_ip(card, addr))
+			kfree(addr);
+		break;
+	default:
+		break;
+	}
+	qeth_l3_set_ip_addr_list(card);
+out:
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block qeth_l3_ip_notifier = {
+	qeth_l3_ip_event,
+	NULL,
+};
+
+#ifdef CONFIG_QETH_IPV6
+/**
+ * IPv6 event handler
+ */
+static int qeth_l3_ip6_event(struct notifier_block *this,
+			     unsigned long event, void *ptr)
+{
+	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
+	struct net_device *dev = (struct net_device *)ifa->idev->dev;
+	struct qeth_ipaddr *addr;
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT(trace, 3, "ip6event");
+
+	card = qeth_l3_get_card_from_dev(dev);
+	if (!card)
+		return NOTIFY_DONE;
+	if (!qeth_is_supported(card, IPA_IPV6))
+		return NOTIFY_DONE;
+
+	addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+	if (addr != NULL) {
+		memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr));
+		addr->u.a6.pfxlen = ifa->prefix_len;
+		addr->type = QETH_IP_TYPE_NORMAL;
+	} else
+		goto out;
+
+	switch (event) {
+	case NETDEV_UP:
+		if (!qeth_l3_add_ip(card, addr))
+			kfree(addr);
+		break;
+	case NETDEV_DOWN:
+		if (!qeth_l3_delete_ip(card, addr))
+			kfree(addr);
+		break;
+	default:
+		break;
+	}
+	qeth_l3_set_ip_addr_list(card);
+out:
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block qeth_l3_ip6_notifier = {
+	qeth_l3_ip6_event,
+	NULL,
+};
+#endif
+
+static int qeth_l3_register_notifiers(void)
+{
+	int rc;
+
+	QETH_DBF_TEXT(trace, 5, "regnotif");
+	rc = register_inetaddr_notifier(&qeth_l3_ip_notifier);
+	if (rc)
+		return rc;
+#ifdef CONFIG_QETH_IPV6
+	rc = register_inet6addr_notifier(&qeth_l3_ip6_notifier);
+	if (rc) {
+		unregister_inetaddr_notifier(&qeth_l3_ip_notifier);
+		return rc;
+	}
+#else
+	PRINT_WARN("layer 3 discipline no IPv6 support\n");
+#endif
+	return 0;
+}
+
+static void qeth_l3_unregister_notifiers(void)
+{
+
+	QETH_DBF_TEXT(trace, 5, "unregnot");
+	BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
+#ifdef CONFIG_QETH_IPV6
+	BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
+#endif /* QETH_IPV6 */
+}
+
+static int __init qeth_l3_init(void)
+{
+	int rc = 0;
+
+	PRINT_INFO("register layer 3 discipline\n");
+	rc = qeth_l3_register_notifiers();
+	return rc;
+}
+
+static void __exit qeth_l3_exit(void)
+{
+	qeth_l3_unregister_notifiers();
+	PRINT_INFO("unregister layer 3 discipline\n");
+}
+
+module_init(qeth_l3_init);
+module_exit(qeth_l3_exit);
+MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
+MODULE_DESCRIPTION("qeth layer 3 discipline");
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
new file mode 100644
index 0000000..08f51fd
--- /dev/null
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -0,0 +1,1051 @@
+/*
+ *  drivers/s390/net/qeth_l3_sys.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
+ *		 Frank Pavlic <fpavlic@de.ibm.com>,
+ *		 Thomas Spatzier <tspat@de.ibm.com>,
+ *		 Frank Blaschka <frank.blaschka@de.ibm.com>
+ */
+
+#include "qeth_l3.h"
+
+#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
+
+static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
+{
+	if (card->options.checksum_type == SW_CHECKSUMMING)
+		return "sw";
+	else if (card->options.checksum_type == HW_CHECKSUMMING)
+		return "hw";
+	else
+		return "no";
+}
+
+static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
+			struct qeth_routing_info *route, char *buf)
+{
+	switch (route->type) {
+	case PRIMARY_ROUTER:
+		return sprintf(buf, "%s\n", "primary router");
+	case SECONDARY_ROUTER:
+		return sprintf(buf, "%s\n", "secondary router");
+	case MULTICAST_ROUTER:
+		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+			return sprintf(buf, "%s\n", "multicast router+");
+		else
+			return sprintf(buf, "%s\n", "multicast router");
+	case PRIMARY_CONNECTOR:
+		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+			return sprintf(buf, "%s\n", "primary connector+");
+		else
+			return sprintf(buf, "%s\n", "primary connector");
+	case SECONDARY_CONNECTOR:
+		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+			return sprintf(buf, "%s\n", "secondary connector+");
+		else
+			return sprintf(buf, "%s\n", "secondary connector");
+	default:
+		return sprintf(buf, "%s\n", "no");
+	}
+}
+
+static ssize_t qeth_l3_dev_route4_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_route_show(card, &card->options.route4, buf);
+}
+
+static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
+		struct qeth_routing_info *route, enum qeth_prot_versions prot,
+		const char *buf, size_t count)
+{
+	enum qeth_routing_types old_route_type = route->type;
+	char *tmp;
+	int rc;
+
+	tmp = strsep((char **) &buf, "\n");
+
+	if (!strcmp(tmp, "no_router")) {
+		route->type = NO_ROUTER;
+	} else if (!strcmp(tmp, "primary_connector")) {
+		route->type = PRIMARY_CONNECTOR;
+	} else if (!strcmp(tmp, "secondary_connector")) {
+		route->type = SECONDARY_CONNECTOR;
+	} else if (!strcmp(tmp, "primary_router")) {
+		route->type = PRIMARY_ROUTER;
+	} else if (!strcmp(tmp, "secondary_router")) {
+		route->type = SECONDARY_ROUTER;
+	} else if (!strcmp(tmp, "multicast_router")) {
+		route->type = MULTICAST_ROUTER;
+	} else {
+		PRINT_WARN("Invalid routing type '%s'.\n", tmp);
+		return -EINVAL;
+	}
+	if (((card->state == CARD_STATE_SOFTSETUP) ||
+	     (card->state == CARD_STATE_UP)) &&
+	    (old_route_type != route->type)) {
+		if (prot == QETH_PROT_IPV4)
+			rc = qeth_l3_setrouting_v4(card);
+		else if (prot == QETH_PROT_IPV6)
+			rc = qeth_l3_setrouting_v6(card);
+	}
+	return count;
+}
+
+static ssize_t qeth_l3_dev_route4_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_route_store(card, &card->options.route4,
+				QETH_PROT_IPV4, buf, count);
+}
+
+static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
+			qeth_l3_dev_route4_store);
+
+static ssize_t qeth_l3_dev_route6_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	if (!qeth_is_supported(card, IPA_IPV6))
+		return sprintf(buf, "%s\n", "n/a");
+
+	return qeth_l3_dev_route_show(card, &card->options.route6, buf);
+}
+
+static ssize_t qeth_l3_dev_route6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	if (!qeth_is_supported(card, IPA_IPV6)) {
+		PRINT_WARN("IPv6 not supported for interface %s.\n"
+			   "Routing status no changed.\n",
+			   QETH_CARD_IFNAME(card));
+		return -ENOTSUPP;
+	}
+
+	return qeth_l3_dev_route_store(card, &card->options.route6,
+				QETH_PROT_IPV6, buf, count);
+}
+
+static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
+			qeth_l3_dev_route6_store);
+
+static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
+}
+
+static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	int i;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if ((i == 0) || (i == 1))
+		card->options.fake_broadcast = i;
+	else {
+		PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
+		   qeth_l3_dev_fake_broadcast_store);
+
+static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
+		return sprintf(buf, "n/a\n");
+
+	return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
+				     QETH_TR_BROADCAST_ALLRINGS)?
+		       "all rings":"local");
+}
+
+static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
+		PRINT_WARN("Device is not a tokenring device!\n");
+		return -EINVAL;
+	}
+
+	tmp = strsep((char **) &buf, "\n");
+
+	if (!strcmp(tmp, "local")) {
+		card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
+		return count;
+	} else if (!strcmp(tmp, "all_rings")) {
+		card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
+		return count;
+	} else {
+		PRINT_WARN("broadcast_mode: invalid mode %s!\n",
+			   tmp);
+		return -EINVAL;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
+		   qeth_l3_dev_broadcast_mode_store);
+
+static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
+		return sprintf(buf, "n/a\n");
+
+	return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
+				     QETH_TR_MACADDR_CANONICAL)? 1:0);
+}
+
+static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+	int i;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
+		PRINT_WARN("Device is not a tokenring device!\n");
+		return -EINVAL;
+	}
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if ((i == 0) || (i == 1))
+		card->options.macaddr_mode = i?
+			QETH_TR_MACADDR_CANONICAL :
+			QETH_TR_MACADDR_NONCANONICAL;
+	else {
+		PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
+		   qeth_l3_dev_canonical_macaddr_store);
+
+static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s checksumming\n",
+			qeth_l3_get_checksum_str(card));
+}
+
+static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	tmp = strsep((char **) &buf, "\n");
+	if (!strcmp(tmp, "sw_checksumming"))
+		card->options.checksum_type = SW_CHECKSUMMING;
+	else if (!strcmp(tmp, "hw_checksumming"))
+		card->options.checksum_type = HW_CHECKSUMMING;
+	else if (!strcmp(tmp, "no_checksumming"))
+		card->options.checksum_type = NO_CHECKSUMMING;
+	else {
+		PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
+		return -EINVAL;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
+		qeth_l3_dev_checksum_store);
+
+static struct attribute *qeth_l3_device_attrs[] = {
+	&dev_attr_route4.attr,
+	&dev_attr_route6.attr,
+	&dev_attr_fake_broadcast.attr,
+	&dev_attr_broadcast_mode.attr,
+	&dev_attr_canonical_macaddr.attr,
+	&dev_attr_checksumming.attr,
+	NULL,
+};
+
+static struct attribute_group qeth_l3_device_attr_group = {
+	.attrs = qeth_l3_device_attrs,
+};
+
+static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
+}
+
+static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+
+	if (!card)
+		return -EINVAL;
+
+	if ((card->state != CARD_STATE_DOWN) &&
+	    (card->state != CARD_STATE_RECOVER))
+		return -EPERM;
+
+	tmp = strsep((char **) &buf, "\n");
+	if (!strcmp(tmp, "toggle")) {
+		card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
+	} else if (!strcmp(tmp, "1")) {
+		card->ipato.enabled = 1;
+	} else if (!strcmp(tmp, "0")) {
+		card->ipato.enabled = 0;
+	} else {
+		PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
+			   "this file\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
+			qeth_l3_dev_ipato_enable_show,
+			qeth_l3_dev_ipato_enable_store);
+
+static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
+}
+
+static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+
+	if (!card)
+		return -EINVAL;
+
+	tmp = strsep((char **) &buf, "\n");
+	if (!strcmp(tmp, "toggle")) {
+		card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
+	} else if (!strcmp(tmp, "1")) {
+		card->ipato.invert4 = 1;
+	} else if (!strcmp(tmp, "0")) {
+		card->ipato.invert4 = 0;
+	} else {
+		PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
+			   "this file\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
+			qeth_l3_dev_ipato_invert4_show,
+			qeth_l3_dev_ipato_invert4_store);
+
+static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
+			enum qeth_prot_versions proto)
+{
+	struct qeth_ipato_entry *ipatoe;
+	unsigned long flags;
+	char addr_str[40];
+	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+	int i = 0;
+
+	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+	/* add strlen for "/<mask>\n" */
+	entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
+	spin_lock_irqsave(&card->ip_lock, flags);
+	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
+		if (ipatoe->proto != proto)
+			continue;
+		/* String must not be longer than PAGE_SIZE. So we check if
+		 * string length gets near PAGE_SIZE. Then we can savely display
+		 * the next IPv6 address (worst case, compared to IPv4) */
+		if ((PAGE_SIZE - i) <= entry_len)
+			break;
+		qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
+		i += snprintf(buf + i, PAGE_SIZE - i,
+			      "%s/%i\n", addr_str, ipatoe->mask_bits);
+	}
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+
+	return i;
+}
+
+static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
+}
+
+static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
+		  u8 *addr, int *mask_bits)
+{
+	const char *start, *end;
+	char *tmp;
+	char buffer[40] = {0, };
+
+	start = buf;
+	/* get address string */
+	end = strchr(start, '/');
+	if (!end || (end - start >= 40)) {
+		PRINT_WARN("Invalid format for ipato_addx/delx. "
+			   "Use <ip addr>/<mask bits>\n");
+		return -EINVAL;
+	}
+	strncpy(buffer, start, end - start);
+	if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
+		PRINT_WARN("Invalid IP address format!\n");
+		return -EINVAL;
+	}
+	start = end + 1;
+	*mask_bits = simple_strtoul(start, &tmp, 10);
+	if (!strlen(start) ||
+	    (tmp == start) ||
+	    (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
+		PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
+			 struct qeth_card *card, enum qeth_prot_versions proto)
+{
+	struct qeth_ipato_entry *ipatoe;
+	u8 addr[16];
+	int mask_bits;
+	int rc;
+
+	rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
+	if (rc)
+		return rc;
+
+	ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
+	if (!ipatoe) {
+		PRINT_WARN("No memory to allocate ipato entry\n");
+		return -ENOMEM;
+	}
+	ipatoe->proto = proto;
+	memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
+	ipatoe->mask_bits = mask_bits;
+
+	rc = qeth_l3_add_ipato_entry(card, ipatoe);
+	if (rc) {
+		kfree(ipatoe);
+		return rc;
+	}
+
+	return count;
+}
+
+static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
+}
+
+static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
+			qeth_l3_dev_ipato_add4_show,
+			qeth_l3_dev_ipato_add4_store);
+
+static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
+			 struct qeth_card *card, enum qeth_prot_versions proto)
+{
+	u8 addr[16];
+	int mask_bits;
+	int rc;
+
+	rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
+	if (rc)
+		return rc;
+
+	qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
+
+	return count;
+}
+
+static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
+}
+
+static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
+			qeth_l3_dev_ipato_del4_store);
+
+static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
+}
+
+static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	char *tmp;
+
+	if (!card)
+		return -EINVAL;
+
+	tmp = strsep((char **) &buf, "\n");
+	if (!strcmp(tmp, "toggle")) {
+		card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
+	} else if (!strcmp(tmp, "1")) {
+		card->ipato.invert6 = 1;
+	} else if (!strcmp(tmp, "0")) {
+		card->ipato.invert6 = 0;
+	} else {
+		PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
+			   "this file\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
+			qeth_l3_dev_ipato_invert6_show,
+			qeth_l3_dev_ipato_invert6_store);
+
+
+static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
+}
+
+static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
+}
+
+static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
+			qeth_l3_dev_ipato_add6_show,
+			qeth_l3_dev_ipato_add6_store);
+
+static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
+}
+
+static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
+			qeth_l3_dev_ipato_del6_store);
+
+static struct attribute *qeth_ipato_device_attrs[] = {
+	&dev_attr_ipato_enable.attr,
+	&dev_attr_ipato_invert4.attr,
+	&dev_attr_ipato_add4.attr,
+	&dev_attr_ipato_del4.attr,
+	&dev_attr_ipato_invert6.attr,
+	&dev_attr_ipato_add6.attr,
+	&dev_attr_ipato_del6.attr,
+	NULL,
+};
+
+static struct attribute_group qeth_device_ipato_group = {
+	.name = "ipa_takeover",
+	.attrs = qeth_ipato_device_attrs,
+};
+
+static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
+			enum qeth_prot_versions proto)
+{
+	struct qeth_ipaddr *ipaddr;
+	char addr_str[40];
+	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+	unsigned long flags;
+	int i = 0;
+
+	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+	entry_len += 2; /* \n + terminator */
+	spin_lock_irqsave(&card->ip_lock, flags);
+	list_for_each_entry(ipaddr, &card->ip_list, entry) {
+		if (ipaddr->proto != proto)
+			continue;
+		if (ipaddr->type != QETH_IP_TYPE_VIPA)
+			continue;
+		/* String must not be longer than PAGE_SIZE. So we check if
+		 * string length gets near PAGE_SIZE. Then we can savely display
+		 * the next IPv6 address (worst case, compared to IPv4) */
+		if ((PAGE_SIZE - i) <= entry_len)
+			break;
+		qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
+			addr_str);
+		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
+	}
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+
+	return i;
+}
+
+static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
+}
+
+static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
+		 u8 *addr)
+{
+	if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
+		PRINT_WARN("Invalid IP address format!\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
+			struct qeth_card *card, enum qeth_prot_versions proto)
+{
+	u8 addr[16] = {0, };
+	int rc;
+
+	rc = qeth_l3_parse_vipae(buf, proto, addr);
+	if (rc)
+		return rc;
+
+	rc = qeth_l3_add_vipa(card, proto, addr);
+	if (rc)
+		return rc;
+
+	return count;
+}
+
+static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
+}
+
+static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
+			qeth_l3_dev_vipa_add4_show,
+			qeth_l3_dev_vipa_add4_store);
+
+static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
+			 struct qeth_card *card, enum qeth_prot_versions proto)
+{
+	u8 addr[16];
+	int rc;
+
+	rc = qeth_l3_parse_vipae(buf, proto, addr);
+	if (rc)
+		return rc;
+
+	qeth_l3_del_vipa(card, proto, addr);
+
+	return count;
+}
+
+static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
+}
+
+static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
+			qeth_l3_dev_vipa_del4_store);
+
+static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
+}
+
+static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
+}
+
+static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
+			qeth_l3_dev_vipa_add6_show,
+			qeth_l3_dev_vipa_add6_store);
+
+static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
+}
+
+static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
+			qeth_l3_dev_vipa_del6_store);
+
+static struct attribute *qeth_vipa_device_attrs[] = {
+	&dev_attr_vipa_add4.attr,
+	&dev_attr_vipa_del4.attr,
+	&dev_attr_vipa_add6.attr,
+	&dev_attr_vipa_del6.attr,
+	NULL,
+};
+
+static struct attribute_group qeth_device_vipa_group = {
+	.name = "vipa",
+	.attrs = qeth_vipa_device_attrs,
+};
+
+static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
+		       enum qeth_prot_versions proto)
+{
+	struct qeth_ipaddr *ipaddr;
+	char addr_str[40];
+	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+	unsigned long flags;
+	int i = 0;
+
+	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+	entry_len += 2; /* \n + terminator */
+	spin_lock_irqsave(&card->ip_lock, flags);
+	list_for_each_entry(ipaddr, &card->ip_list, entry) {
+		if (ipaddr->proto != proto)
+			continue;
+		if (ipaddr->type != QETH_IP_TYPE_RXIP)
+			continue;
+		/* String must not be longer than PAGE_SIZE. So we check if
+		 * string length gets near PAGE_SIZE. Then we can savely display
+		 * the next IPv6 address (worst case, compared to IPv4) */
+		if ((PAGE_SIZE - i) <= entry_len)
+			break;
+		qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
+			addr_str);
+		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
+	}
+	spin_unlock_irqrestore(&card->ip_lock, flags);
+	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+
+	return i;
+}
+
+static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
+}
+
+static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
+		 u8 *addr)
+{
+	if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
+		PRINT_WARN("Invalid IP address format!\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
+			struct qeth_card *card, enum qeth_prot_versions proto)
+{
+	u8 addr[16] = {0, };
+	int rc;
+
+	rc = qeth_l3_parse_rxipe(buf, proto, addr);
+	if (rc)
+		return rc;
+
+	rc = qeth_l3_add_rxip(card, proto, addr);
+	if (rc)
+		return rc;
+
+	return count;
+}
+
+static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
+}
+
+static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
+			qeth_l3_dev_rxip_add4_show,
+			qeth_l3_dev_rxip_add4_store);
+
+static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
+			struct qeth_card *card, enum qeth_prot_versions proto)
+{
+	u8 addr[16];
+	int rc;
+
+	rc = qeth_l3_parse_rxipe(buf, proto, addr);
+	if (rc)
+		return rc;
+
+	qeth_l3_del_rxip(card, proto, addr);
+
+	return count;
+}
+
+static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
+}
+
+static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
+			qeth_l3_dev_rxip_del4_store);
+
+static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
+}
+
+static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
+}
+
+static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
+			qeth_l3_dev_rxip_add6_show,
+			qeth_l3_dev_rxip_add6_store);
+
+static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+
+	if (!card)
+		return -EINVAL;
+
+	return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
+}
+
+static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
+			qeth_l3_dev_rxip_del6_store);
+
+static struct attribute *qeth_rxip_device_attrs[] = {
+	&dev_attr_rxip_add4.attr,
+	&dev_attr_rxip_del4.attr,
+	&dev_attr_rxip_add6.attr,
+	&dev_attr_rxip_del6.attr,
+	NULL,
+};
+
+static struct attribute_group qeth_device_rxip_group = {
+	.name = "rxip",
+	.attrs = qeth_rxip_device_attrs,
+};
+
+int qeth_l3_create_device_attributes(struct device *dev)
+{
+	int ret;
+
+	ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
+	if (ret) {
+		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
+		return ret;
+	}
+
+	ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
+	if (ret) {
+		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
+		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+		return ret;
+	}
+
+	ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
+	if (ret) {
+		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
+		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+		return ret;
+	}
+	return 0;
+}
+
+void qeth_l3_remove_device_attributes(struct device *dev)
+{
+	sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
+	sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+	sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+	sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
+}
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
deleted file mode 100644
index d063e9e..0000000
--- a/drivers/s390/net/qeth_main.c
+++ /dev/null
@@ -1,8959 +0,0 @@
-/*
- * linux/drivers/s390/net/qeth_main.c
- *
- * Linux on zSeries OSA Express and HiperSockets support
- *
- * Copyright 2000,2003 IBM Corporation
- *
- *    Author(s): Original Code written by
- *			  Utz Bacher (utz.bacher@de.ibm.com)
- *		 Rewritten by
- *			  Frank Pavlic (fpavlic@de.ibm.com) and
- *		 	  Thomas Spatzier <tspat@de.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/ip.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/tcp.h>
-#include <linux/icmp.h>
-#include <linux/skbuff.h>
-#include <linux/in.h>
-#include <linux/igmp.h>
-#include <linux/init.h>
-#include <linux/reboot.h>
-#include <linux/mii.h>
-#include <linux/rcupdate.h>
-#include <linux/ethtool.h>
-
-#include <net/arp.h>
-#include <net/ip.h>
-#include <net/route.h>
-
-#include <asm/ebcdic.h>
-#include <asm/io.h>
-#include <asm/qeth.h>
-#include <asm/timex.h>
-#include <asm/semaphore.h>
-#include <asm/uaccess.h>
-#include <asm/s390_rdev.h>
-
-#include "qeth.h"
-#include "qeth_mpc.h"
-#include "qeth_fs.h"
-#include "qeth_eddp.h"
-#include "qeth_tso.h"
-
-static const char *version = "qeth S/390 OSA-Express driver";
-
-/**
- * Debug Facility Stuff
- */
-static debug_info_t *qeth_dbf_setup = NULL;
-static debug_info_t *qeth_dbf_data = NULL;
-static debug_info_t *qeth_dbf_misc = NULL;
-static debug_info_t *qeth_dbf_control = NULL;
-debug_info_t *qeth_dbf_trace = NULL;
-static debug_info_t *qeth_dbf_sense = NULL;
-static debug_info_t *qeth_dbf_qerr = NULL;
-
-DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf);
-
-static struct lock_class_key qdio_out_skb_queue_key;
-
-/**
- * some more definitions and declarations
- */
-static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
-
-/* list of our cards */
-struct qeth_card_list_struct qeth_card_list;
-/*process list want to be notified*/
-spinlock_t qeth_notify_lock;
-struct list_head qeth_notify_list;
-
-static void qeth_send_control_data_cb(struct qeth_channel *,
-				      struct qeth_cmd_buffer *);
-
-/**
- * here we go with function implementation
- */
-static void
-qeth_init_qdio_info(struct qeth_card *card);
-
-static int
-qeth_init_qdio_queues(struct qeth_card *card);
-
-static int
-qeth_alloc_qdio_buffers(struct qeth_card *card);
-
-static void
-qeth_free_qdio_buffers(struct qeth_card *);
-
-static void
-qeth_clear_qdio_buffers(struct qeth_card *);
-
-static void
-qeth_clear_ip_list(struct qeth_card *, int, int);
-
-static void
-qeth_clear_ipacmd_list(struct qeth_card *);
-
-static int
-qeth_qdio_clear_card(struct qeth_card *, int);
-
-static void
-qeth_clear_working_pool_list(struct qeth_card *);
-
-static void
-qeth_clear_cmd_buffers(struct qeth_channel *);
-
-static int
-qeth_stop(struct net_device *);
-
-static void
-qeth_clear_ipato_list(struct qeth_card *);
-
-static int
-qeth_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
-
-static void
-qeth_irq_tasklet(unsigned long);
-
-static int
-qeth_set_online(struct ccwgroup_device *);
-
-static int
-__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode);
-
-static struct qeth_ipaddr *
-qeth_get_addr_buffer(enum qeth_prot_versions);
-
-static void
-qeth_set_multicast_list(struct net_device *);
-
-static void
-qeth_setadp_promisc_mode(struct qeth_card *);
-
-static int
-qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr);
-
-static void
-qeth_notify_processes(void)
-{
-	/*notify all  registered processes */
-	struct qeth_notify_list_struct *n_entry;
-
-	QETH_DBF_TEXT(trace,3,"procnoti");
-	spin_lock(&qeth_notify_lock);
-	list_for_each_entry(n_entry, &qeth_notify_list, list) {
-		send_sig(n_entry->signum, n_entry->task, 1);
-	}
-	spin_unlock(&qeth_notify_lock);
-
-}
-int
-qeth_notifier_unregister(struct task_struct *p)
-{
-	struct qeth_notify_list_struct *n_entry, *tmp;
-
-	QETH_DBF_TEXT(trace, 2, "notunreg");
-	spin_lock(&qeth_notify_lock);
-	list_for_each_entry_safe(n_entry, tmp, &qeth_notify_list, list) {
-		if (n_entry->task == p) {
-			list_del(&n_entry->list);
-			kfree(n_entry);
-			goto out;
-		}
-	}
-out:
-	spin_unlock(&qeth_notify_lock);
-	return 0;
-}
-int
-qeth_notifier_register(struct task_struct *p, int signum)
-{
-	struct qeth_notify_list_struct *n_entry;
-
-	/*check first if entry already exists*/
-	spin_lock(&qeth_notify_lock);
-	list_for_each_entry(n_entry, &qeth_notify_list, list) {
-		if (n_entry->task == p) {
-			n_entry->signum = signum;
-			spin_unlock(&qeth_notify_lock);
-			return 0;
-		}
-	}
-	spin_unlock(&qeth_notify_lock);
-
-	n_entry = (struct qeth_notify_list_struct *)
-		kmalloc(sizeof(struct qeth_notify_list_struct),GFP_KERNEL);
-	if (!n_entry)
-		return -ENOMEM;
-	n_entry->task = p;
-	n_entry->signum = signum;
-	spin_lock(&qeth_notify_lock);
-	list_add(&n_entry->list,&qeth_notify_list);
-	spin_unlock(&qeth_notify_lock);
-	return 0;
-}
-
-
-/**
- * free channel command buffers
- */
-static void
-qeth_clean_channel(struct qeth_channel *channel)
-{
-	int cnt;
-
-	QETH_DBF_TEXT(setup, 2, "freech");
-	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
-		kfree(channel->iob[cnt].data);
-}
-
-/**
- * free card
- */
-static void
-qeth_free_card(struct qeth_card *card)
-{
-
-	QETH_DBF_TEXT(setup, 2, "freecrd");
-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
-	qeth_clean_channel(&card->read);
-	qeth_clean_channel(&card->write);
-	if (card->dev)
-		free_netdev(card->dev);
-	qeth_clear_ip_list(card, 0, 0);
-	qeth_clear_ipato_list(card);
-	kfree(card->ip_tbd_list);
-	qeth_free_qdio_buffers(card);
-	kfree(card);
-}
-
-/**
- * alloc memory for command buffer per channel
- */
-static int
-qeth_setup_channel(struct qeth_channel *channel)
-{
-	int cnt;
-
-	QETH_DBF_TEXT(setup, 2, "setupch");
-	for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
-		channel->iob[cnt].data = (char *)
-			kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
-		if (channel->iob[cnt].data == NULL)
-			break;
-		channel->iob[cnt].state = BUF_STATE_FREE;
-		channel->iob[cnt].channel = channel;
-		channel->iob[cnt].callback = qeth_send_control_data_cb;
-		channel->iob[cnt].rc = 0;
-	}
-	if (cnt < QETH_CMD_BUFFER_NO) {
-		while (cnt-- > 0)
-			kfree(channel->iob[cnt].data);
-		return -ENOMEM;
-	}
-	channel->buf_no = 0;
-	channel->io_buf_no = 0;
-	atomic_set(&channel->irq_pending, 0);
-	spin_lock_init(&channel->iob_lock);
-
-	init_waitqueue_head(&channel->wait_q);
-	channel->irq_tasklet.data = (unsigned long) channel;
-	channel->irq_tasklet.func = qeth_irq_tasklet;
-	return 0;
-}
-
-/**
- * alloc memory for card structure
- */
-static struct qeth_card *
-qeth_alloc_card(void)
-{
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(setup, 2, "alloccrd");
-	card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
-	if (!card)
-		return NULL;
-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
-	if (qeth_setup_channel(&card->read)) {
-		kfree(card);
-		return NULL;
-	}
-	if (qeth_setup_channel(&card->write)) {
-		qeth_clean_channel(&card->read);
-		kfree(card);
-		return NULL;
-	}
-	return card;
-}
-
-static long
-__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
-		       struct irb *irb)
-{
-	if (!IS_ERR(irb))
-		return 0;
-
-	switch (PTR_ERR(irb)) {
-	case -EIO:
-		PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
-		QETH_DBF_TEXT(trace, 2, "ckirberr");
-		QETH_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
-		break;
-	case -ETIMEDOUT:
-		PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
-		QETH_DBF_TEXT(trace, 2, "ckirberr");
-		QETH_DBF_TEXT_(trace, 2, "  rc%d", -ETIMEDOUT);
-		if (intparm == QETH_RCD_PARM) {
-			struct qeth_card *card = CARD_FROM_CDEV(cdev);
-
-			if (card && (card->data.ccwdev == cdev)) {
-				card->data.state = CH_STATE_DOWN;
-				wake_up(&card->wait_q);
-			}
-		}
-		break;
-	default:
-		PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
-			   cdev->dev.bus_id);
-		QETH_DBF_TEXT(trace, 2, "ckirberr");
-		QETH_DBF_TEXT(trace, 2, "  rc???");
-	}
-	return PTR_ERR(irb);
-}
-
-static int
-qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
-{
-	int dstat,cstat;
-	char *sense;
-
-	sense = (char *) irb->ecw;
-	cstat = irb->scsw.cstat;
-	dstat = irb->scsw.dstat;
-
-	if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
-		     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
-		     SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
-		QETH_DBF_TEXT(trace,2, "CGENCHK");
-		PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
-			   cdev->dev.bus_id, dstat, cstat);
-		HEXDUMP16(WARN, "irb: ", irb);
-		HEXDUMP16(WARN, "irb: ", ((char *) irb) + 32);
-		return 1;
-	}
-
-	if (dstat & DEV_STAT_UNIT_CHECK) {
-		if (sense[SENSE_RESETTING_EVENT_BYTE] &
-		    SENSE_RESETTING_EVENT_FLAG) {
-			QETH_DBF_TEXT(trace,2,"REVIND");
-			return 1;
-		}
-		if (sense[SENSE_COMMAND_REJECT_BYTE] &
-		    SENSE_COMMAND_REJECT_FLAG) {
-			QETH_DBF_TEXT(trace,2,"CMDREJi");
-			return 0;
-		}
-		if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
-			QETH_DBF_TEXT(trace,2,"AFFE");
-			return 1;
-		}
-		if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
-			QETH_DBF_TEXT(trace,2,"ZEROSEN");
-			return 0;
-		}
-		QETH_DBF_TEXT(trace,2,"DGENCHK");
-			return 1;
-	}
-	return 0;
-}
-static int qeth_issue_next_read(struct qeth_card *);
-
-/**
- * interrupt handler
- */
-static void
-qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
-{
-	int rc;
-	int cstat,dstat;
-	struct qeth_cmd_buffer *buffer;
-	struct qeth_channel *channel;
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(trace,5,"irq");
-
-	if (__qeth_check_irb_error(cdev, intparm, irb))
-		return;
-	cstat = irb->scsw.cstat;
-	dstat = irb->scsw.dstat;
-
-	card = CARD_FROM_CDEV(cdev);
-	if (!card)
-		return;
-
-	if (card->read.ccwdev == cdev){
-		channel = &card->read;
-		QETH_DBF_TEXT(trace,5,"read");
-	} else if (card->write.ccwdev == cdev) {
-		channel = &card->write;
-		QETH_DBF_TEXT(trace,5,"write");
-	} else {
-		channel = &card->data;
-		QETH_DBF_TEXT(trace,5,"data");
-	}
-	atomic_set(&channel->irq_pending, 0);
-
-	if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
-		channel->state = CH_STATE_STOPPED;
-
-	if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
-		channel->state = CH_STATE_HALTED;
-
-	/*let's wake up immediately on data channel*/
-	if ((channel == &card->data) && (intparm != 0) &&
-	    (intparm != QETH_RCD_PARM))
-		goto out;
-
-	if (intparm == QETH_CLEAR_CHANNEL_PARM) {
-		QETH_DBF_TEXT(trace, 6, "clrchpar");
-		/* we don't have to handle this further */
-		intparm = 0;
-	}
-	if (intparm == QETH_HALT_CHANNEL_PARM) {
-		QETH_DBF_TEXT(trace, 6, "hltchpar");
-		/* we don't have to handle this further */
-		intparm = 0;
-	}
-	if ((dstat & DEV_STAT_UNIT_EXCEP) ||
-	    (dstat & DEV_STAT_UNIT_CHECK) ||
-	    (cstat)) {
-		if (irb->esw.esw0.erw.cons) {
-			/* TODO: we should make this s390dbf */
-			PRINT_WARN("sense data available on channel %s.\n",
-				   CHANNEL_ID(channel));
-			PRINT_WARN(" cstat 0x%X\n dstat 0x%X\n", cstat, dstat);
-			HEXDUMP16(WARN,"irb: ",irb);
-			HEXDUMP16(WARN,"sense data: ",irb->ecw);
-		}
-		if (intparm == QETH_RCD_PARM) {
-			channel->state = CH_STATE_DOWN;
-			goto out;
-		}
-		rc = qeth_get_problem(cdev,irb);
-		if (rc) {
-			qeth_schedule_recovery(card);
-			goto out;
-		}
-	}
-
-	if (intparm == QETH_RCD_PARM) {
-		channel->state = CH_STATE_RCD_DONE;
-		goto out;
-	}
-	if (intparm) {
-		buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
-		buffer->state = BUF_STATE_PROCESSED;
-	}
-	if (channel == &card->data)
-		return;
-
-	if (channel == &card->read &&
-	    channel->state == CH_STATE_UP)
-		qeth_issue_next_read(card);
-
-	qeth_irq_tasklet((unsigned long)channel);
-	return;
-out:
-	wake_up(&card->wait_q);
-}
-
-/**
- * tasklet function scheduled from irq handler
- */
-static void
-qeth_irq_tasklet(unsigned long data)
-{
-	struct qeth_card *card;
-	struct qeth_channel *channel;
-	struct qeth_cmd_buffer *iob;
-	__u8 index;
-
-	QETH_DBF_TEXT(trace,5,"irqtlet");
-	channel = (struct qeth_channel *) data;
-	iob = channel->iob;
-	index = channel->buf_no;
-	card = CARD_FROM_CDEV(channel->ccwdev);
-	while (iob[index].state == BUF_STATE_PROCESSED) {
-		if (iob[index].callback !=NULL) {
-			iob[index].callback(channel,iob + index);
-		}
-		index = (index + 1) % QETH_CMD_BUFFER_NO;
-	}
-	channel->buf_no = index;
-	wake_up(&card->wait_q);
-}
-
-static int qeth_stop_card(struct qeth_card *, int);
-
-static int
-__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
-{
-	struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
-	int rc = 0, rc2 = 0, rc3 = 0;
-	enum qeth_card_states recover_flag;
-
-	QETH_DBF_TEXT(setup, 3, "setoffl");
-	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
-
-	if (card->dev && netif_carrier_ok(card->dev))
-		netif_carrier_off(card->dev);
-	recover_flag = card->state;
-	if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
-		PRINT_WARN("Stopping card %s interrupted by user!\n",
-			   CARD_BUS_ID(card));
-		return -ERESTARTSYS;
-	}
-	rc  = ccw_device_set_offline(CARD_DDEV(card));
-	rc2 = ccw_device_set_offline(CARD_WDEV(card));
-	rc3 = ccw_device_set_offline(CARD_RDEV(card));
-	if (!rc)
-		rc = (rc2) ? rc2 : rc3;
-	if (rc)
-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-	if (recover_flag == CARD_STATE_UP)
-		card->state = CARD_STATE_RECOVER;
-	qeth_notify_processes();
-	return 0;
-}
-
-static int
-qeth_set_offline(struct ccwgroup_device *cgdev)
-{
-	return  __qeth_set_offline(cgdev, 0);
-}
-
-static int
-qeth_threads_running(struct qeth_card *card, unsigned long threads);
-
-
-static void
-qeth_remove_device(struct ccwgroup_device *cgdev)
-{
-	struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
-	unsigned long flags;
-
-	QETH_DBF_TEXT(setup, 3, "rmdev");
-	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
-
-	if (!card)
-		return;
-
-	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
-
-	if (cgdev->state == CCWGROUP_ONLINE){
-		card->use_hard_stop = 1;
-		qeth_set_offline(cgdev);
-	}
-	/* remove form our internal list */
-	write_lock_irqsave(&qeth_card_list.rwlock, flags);
-	list_del(&card->list);
-	write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
-	if (card->dev)
-		unregister_netdev(card->dev);
-	qeth_remove_device_attributes(&cgdev->dev);
-	qeth_free_card(card);
-	cgdev->dev.driver_data = NULL;
-	put_device(&cgdev->dev);
-}
-
-static int
-qeth_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
-static int
-qeth_deregister_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
-
-/**
- * Add/remove address to/from card's ip list, i.e. try to add or remove
- * reference to/from an IP address that is already registered on the card.
- * Returns:
- * 	0  address was on card and its reference count has been adjusted,
- * 	   but is still > 0, so nothing has to be done
- * 	   also returns 0 if card was not on card and the todo was to delete
- * 	   the address -> there is also nothing to be done
- * 	1  address was not on card and the todo is to add it to the card's ip
- * 	   list
- * 	-1 address was on card and its reference count has been decremented
- * 	   to <= 0 by the todo -> address must be removed from card
- */
-static int
-__qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
-		      struct qeth_ipaddr **__addr)
-{
-	struct qeth_ipaddr *addr;
-	int found = 0;
-
-	list_for_each_entry(addr, &card->ip_list, entry) {
-		if (card->options.layer2) {
-			if ((addr->type == todo->type) &&
-			    (memcmp(&addr->mac, &todo->mac,
-				    OSA_ADDR_LEN) == 0)) {
-				found = 1;
-				break;
-			}
-			continue;
-		}
-		if ((addr->proto     == QETH_PROT_IPV4)  &&
-		    (todo->proto     == QETH_PROT_IPV4)  &&
-		    (addr->type      == todo->type)      &&
-		    (addr->u.a4.addr == todo->u.a4.addr) &&
-		    (addr->u.a4.mask == todo->u.a4.mask)) {
-			found = 1;
-			break;
-		}
-		if ((addr->proto       == QETH_PROT_IPV6)     &&
-		    (todo->proto       == QETH_PROT_IPV6)     &&
-		    (addr->type        == todo->type)         &&
-		    (addr->u.a6.pfxlen == todo->u.a6.pfxlen)  &&
-		    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
-			    sizeof(struct in6_addr)) == 0)) {
-			found = 1;
-			break;
-		}
-	}
-	if (found) {
-		addr->users += todo->users;
-		if (addr->users <= 0){
-			*__addr = addr;
-			return -1;
-		} else {
-			/* for VIPA and RXIP limit refcount to 1 */
-			if (addr->type != QETH_IP_TYPE_NORMAL)
-				addr->users = 1;
-			return 0;
-		}
-	}
-	if (todo->users > 0) {
-		/* for VIPA and RXIP limit refcount to 1 */
-		if (todo->type != QETH_IP_TYPE_NORMAL)
-			todo->users = 1;
-		return 1;
-	} else
-		return 0;
-}
-
-static int
-__qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
-		              int same_type)
-{
-	struct qeth_ipaddr *tmp;
-
-	list_for_each_entry(tmp, list, entry) {
-		if ((tmp->proto     == QETH_PROT_IPV4)            &&
-		    (addr->proto    == QETH_PROT_IPV4)            &&
-		    ((same_type && (tmp->type == addr->type)) ||
-		     (!same_type && (tmp->type != addr->type))  ) &&
-		    (tmp->u.a4.addr == addr->u.a4.addr)             ){
-			return 1;
-		}
-		if ((tmp->proto  == QETH_PROT_IPV6)               &&
-		    (addr->proto == QETH_PROT_IPV6)               &&
-		    ((same_type && (tmp->type == addr->type)) ||
-		     (!same_type && (tmp->type != addr->type))  ) &&
-		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
-			    sizeof(struct in6_addr)) == 0)          ) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * Add IP to be added to todo list. If there is already an "add todo"
- * in this list we just incremenent the reference count.
- * Returns 0 if we  just incremented reference count.
- */
-static int
-__qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
-{
-	struct qeth_ipaddr *tmp, *t;
-	int found = 0;
-
-	list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
-		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
-		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
-			return 0;
-		if (card->options.layer2) {
-			if ((tmp->type	== addr->type)	&&
-			    (tmp->is_multicast == addr->is_multicast) &&
-			    (memcmp(&tmp->mac, &addr->mac,
-				    OSA_ADDR_LEN) == 0)) {
-				found = 1;
-				break;
-			}
-			continue;
-		}
-		if ((tmp->proto        == QETH_PROT_IPV4)     &&
-		    (addr->proto       == QETH_PROT_IPV4)     &&
-		    (tmp->type         == addr->type)         &&
-		    (tmp->is_multicast == addr->is_multicast) &&
-		    (tmp->u.a4.addr    == addr->u.a4.addr)    &&
-		    (tmp->u.a4.mask    == addr->u.a4.mask)) {
-			found = 1;
-			break;
-		}
-		if ((tmp->proto        == QETH_PROT_IPV6)      &&
-		    (addr->proto       == QETH_PROT_IPV6)      &&
-		    (tmp->type         == addr->type)          &&
-		    (tmp->is_multicast == addr->is_multicast)  &&
-		    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&
-		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
-			    sizeof(struct in6_addr)) == 0)) {
-			found = 1;
-			break;
-		}
-	}
-	if (found){
-		if (addr->users != 0)
-			tmp->users += addr->users;
-		else
-			tmp->users += add? 1:-1;
-		if (tmp->users == 0) {
-			list_del(&tmp->entry);
-			kfree(tmp);
-		}
-		return 0;
-	} else {
-		if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)
-			list_add(&addr->entry, card->ip_tbd_list);
-		else {
-			if (addr->users == 0)
-				addr->users += add? 1:-1;
-			if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&
-			    qeth_is_addr_covered_by_ipato(card, addr)){
-				QETH_DBF_TEXT(trace, 2, "tkovaddr");
-				addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
-			}
-			list_add_tail(&addr->entry, card->ip_tbd_list);
-		}
-		return 1;
-	}
-}
-
-/**
- * Remove IP address from list
- */
-static int
-qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace, 4, "delip");
-
-	if (card->options.layer2)
-		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
-	else if (addr->proto == QETH_PROT_IPV4)
-		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
-	else {
-		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
-		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
-	}
-	spin_lock_irqsave(&card->ip_lock, flags);
-	rc = __qeth_insert_ip_todo(card, addr, 0);
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	return rc;
-}
-
-static int
-qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace, 4, "addip");
-	if (card->options.layer2)
-		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
-	else if (addr->proto == QETH_PROT_IPV4)
-		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
-	else {
-		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
-		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
-	}
-	spin_lock_irqsave(&card->ip_lock, flags);
-	rc = __qeth_insert_ip_todo(card, addr, 1);
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	return rc;
-}
-
-static void
-__qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
-{
-	struct qeth_ipaddr *addr, *tmp;
-	int rc;
-again:
-	list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
-		if (addr->is_multicast) {
-			list_del(&addr->entry);
-			spin_unlock_irqrestore(&card->ip_lock, *flags);
-			rc = qeth_deregister_addr_entry(card, addr);
-			spin_lock_irqsave(&card->ip_lock, *flags);
-			if (!rc) {
-				kfree(addr);
-				goto again;
-			} else
-				list_add(&addr->entry, &card->ip_list);
-		}
-	}
-}
-
-static void
-qeth_set_ip_addr_list(struct qeth_card *card)
-{
-	struct list_head *tbd_list;
-	struct qeth_ipaddr *todo, *addr;
-	unsigned long flags;
-	int rc;
-
-	QETH_DBF_TEXT(trace, 2, "sdiplist");
-	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
-
-	spin_lock_irqsave(&card->ip_lock, flags);
-	tbd_list = card->ip_tbd_list;
-	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
-	if (!card->ip_tbd_list) {
-		QETH_DBF_TEXT(trace, 0, "silnomem");
-		card->ip_tbd_list = tbd_list;
-		spin_unlock_irqrestore(&card->ip_lock, flags);
-		return;
-	} else
-		INIT_LIST_HEAD(card->ip_tbd_list);
-
-	while (!list_empty(tbd_list)){
-		todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);
-		list_del(&todo->entry);
-		if (todo->type == QETH_IP_TYPE_DEL_ALL_MC){
-			__qeth_delete_all_mc(card, &flags);
-			kfree(todo);
-			continue;
-		}
-		rc = __qeth_ref_ip_on_card(card, todo, &addr);
-		if (rc == 0) {
-			/* nothing to be done; only adjusted refcount */
-			kfree(todo);
-		} else if (rc == 1) {
-			/* new entry to be added to on-card list */
-			spin_unlock_irqrestore(&card->ip_lock, flags);
-			rc = qeth_register_addr_entry(card, todo);
-			spin_lock_irqsave(&card->ip_lock, flags);
-			if (!rc)
-				list_add_tail(&todo->entry, &card->ip_list);
-			else
-				kfree(todo);
-		} else if (rc == -1) {
-			/* on-card entry to be removed */
-			list_del_init(&addr->entry);
-			spin_unlock_irqrestore(&card->ip_lock, flags);
-			rc = qeth_deregister_addr_entry(card, addr);
-			spin_lock_irqsave(&card->ip_lock, flags);
-			if (!rc)
-				kfree(addr);
-			else
-				list_add_tail(&addr->entry, &card->ip_list);
-			kfree(todo);
-		}
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	kfree(tbd_list);
-}
-
-static void qeth_delete_mc_addresses(struct qeth_card *);
-static void qeth_add_multicast_ipv4(struct qeth_card *);
-static void qeth_layer2_add_multicast(struct qeth_card *);
-#ifdef CONFIG_QETH_IPV6
-static void qeth_add_multicast_ipv6(struct qeth_card *);
-#endif
-
-static int
-qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->thread_mask_lock, flags);
-	if ( !(card->thread_allowed_mask & thread) ||
-	      (card->thread_start_mask & thread) ) {
-		spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-		return -EPERM;
-	}
-	card->thread_start_mask |= thread;
-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-	return 0;
-}
-
-static void
-qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->thread_mask_lock, flags);
-	card->thread_start_mask &= ~thread;
-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-	wake_up(&card->wait_q);
-}
-
-static void
-qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->thread_mask_lock, flags);
-	card->thread_running_mask &= ~thread;
-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-	wake_up(&card->wait_q);
-}
-
-static int
-__qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	spin_lock_irqsave(&card->thread_mask_lock, flags);
-	if (card->thread_start_mask & thread){
-		if ((card->thread_allowed_mask & thread) &&
-		    !(card->thread_running_mask & thread)){
-			rc = 1;
-			card->thread_start_mask &= ~thread;
-			card->thread_running_mask |= thread;
-		} else
-			rc = -EPERM;
-	}
-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-	return rc;
-}
-
-static int
-qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
-{
-	int rc = 0;
-
-	wait_event(card->wait_q,
-		   (rc = __qeth_do_run_thread(card, thread)) >= 0);
-	return rc;
-}
-
-static int
-qeth_recover(void *ptr)
-{
-	struct qeth_card *card;
-	int rc = 0;
-
-	card = (struct qeth_card *) ptr;
-	daemonize("qeth_recover");
-	QETH_DBF_TEXT(trace,2,"recover1");
-	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
-	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
-		return 0;
-	QETH_DBF_TEXT(trace,2,"recover2");
-	PRINT_WARN("Recovery of device %s started ...\n",
-		   CARD_BUS_ID(card));
-	card->use_hard_stop = 1;
-	__qeth_set_offline(card->gdev,1);
-	rc = __qeth_set_online(card->gdev,1);
-	/* don't run another scheduled recovery */
-	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
-	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
-	if (!rc)
-		PRINT_INFO("Device %s successfully recovered!\n",
-			   CARD_BUS_ID(card));
-	else
-		PRINT_INFO("Device %s could not be recovered!\n",
-			   CARD_BUS_ID(card));
-	return 0;
-}
-
-void
-qeth_schedule_recovery(struct qeth_card *card)
-{
-	QETH_DBF_TEXT(trace,2,"startrec");
-	if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
-}
-
-static int
-qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	spin_lock_irqsave(&card->thread_mask_lock, flags);
-	QETH_DBF_TEXT_(trace, 4, "  %02x%02x%02x",
-			(u8) card->thread_start_mask,
-			(u8) card->thread_allowed_mask,
-			(u8) card->thread_running_mask);
-	rc = (card->thread_start_mask & thread);
-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-	return rc;
-}
-
-static void
-qeth_start_kernel_thread(struct work_struct *work)
-{
-	struct qeth_card *card = container_of(work, struct qeth_card, kernel_thread_starter);
-	QETH_DBF_TEXT(trace , 2, "strthrd");
-
-	if (card->read.state != CH_STATE_UP &&
-	    card->write.state != CH_STATE_UP)
-		return;
-	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
-		kernel_thread(qeth_recover, (void *) card, SIGCHLD);
-}
-
-
-static void
-qeth_set_intial_options(struct qeth_card *card)
-{
-	card->options.route4.type = NO_ROUTER;
-#ifdef CONFIG_QETH_IPV6
-	card->options.route6.type = NO_ROUTER;
-#endif /* QETH_IPV6 */
-	card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
-	card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
-	card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
-	card->options.fake_broadcast = 0;
-	card->options.add_hhlen = DEFAULT_ADD_HHLEN;
-	card->options.fake_ll = 0;
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		card->options.layer2 = 1;
-	else
-		card->options.layer2 = 0;
-	card->options.performance_stats = 0;
-	card->options.rx_sg_cb = QETH_RX_SG_CB;
-}
-
-/**
- * initialize channels ,card and all state machines
- */
-static int
-qeth_setup_card(struct qeth_card *card)
-{
-
-	QETH_DBF_TEXT(setup, 2, "setupcrd");
-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
-
-	card->read.state  = CH_STATE_DOWN;
-	card->write.state = CH_STATE_DOWN;
-	card->data.state  = CH_STATE_DOWN;
-	card->state = CARD_STATE_DOWN;
-	card->lan_online = 0;
-	card->use_hard_stop = 0;
-	card->dev = NULL;
-#ifdef CONFIG_QETH_VLAN
-	spin_lock_init(&card->vlanlock);
-	card->vlangrp = NULL;
-#endif
-	spin_lock_init(&card->lock);
-	spin_lock_init(&card->ip_lock);
-	spin_lock_init(&card->thread_mask_lock);
-	card->thread_start_mask = 0;
-	card->thread_allowed_mask = 0;
-	card->thread_running_mask = 0;
-	INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
-	INIT_LIST_HEAD(&card->ip_list);
-	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
-	if (!card->ip_tbd_list) {
-		QETH_DBF_TEXT(setup, 0, "iptbdnom");
-		return -ENOMEM;
-	}
-	INIT_LIST_HEAD(card->ip_tbd_list);
-	INIT_LIST_HEAD(&card->cmd_waiter_list);
-	init_waitqueue_head(&card->wait_q);
-	/* intial options */
-	qeth_set_intial_options(card);
-	/* IP address takeover */
-	INIT_LIST_HEAD(&card->ipato.entries);
-	card->ipato.enabled = 0;
-	card->ipato.invert4 = 0;
-	card->ipato.invert6 = 0;
-	/* init QDIO stuff */
-	qeth_init_qdio_info(card);
-	return 0;
-}
-
-static int
-is_1920_device (struct qeth_card *card)
-{
-	int single_queue = 0;
-	struct ccw_device *ccwdev;
-	struct channelPath_dsc {
-		u8 flags;
-		u8 lsn;
-		u8 desc;
-		u8 chpid;
-		u8 swla;
-		u8 zeroes;
-		u8 chla;
-		u8 chpp;
-	} *chp_dsc;
-
-	QETH_DBF_TEXT(setup, 2, "chk_1920");
-
-	ccwdev = card->data.ccwdev;
-	chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
-	if (chp_dsc != NULL) {
-		/* CHPP field bit 6 == 1 -> single queue */
-		single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
-		kfree(chp_dsc);
-	}
-	QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);
-	return single_queue;
-}
-
-static int
-qeth_determine_card_type(struct qeth_card *card)
-{
-	int i = 0;
-
-	QETH_DBF_TEXT(setup, 2, "detcdtyp");
-
-	card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
-	card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
-	while (known_devices[i][4]) {
-		if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
-		    (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
-			card->info.type = known_devices[i][4];
-			card->qdio.no_out_queues = known_devices[i][8];
-			card->info.is_multicast_different = known_devices[i][9];
-			if (is_1920_device(card)) {
-				PRINT_INFO("Priority Queueing not able "
-					   "due to hardware limitations!\n");
-				card->qdio.no_out_queues = 1;
-				card->qdio.default_out_queue = 0;
-			}
-			return 0;
-		}
-		i++;
-	}
-	card->info.type = QETH_CARD_TYPE_UNKNOWN;
-	PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
-	return -ENOENT;
-}
-
-static int
-qeth_probe_device(struct ccwgroup_device *gdev)
-{
-	struct qeth_card *card;
-	struct device *dev;
-	unsigned long flags;
-	int rc;
-
-	QETH_DBF_TEXT(setup, 2, "probedev");
-
-	dev = &gdev->dev;
-	if (!get_device(dev))
-		return -ENODEV;
-
-	QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
-
-	card = qeth_alloc_card();
-	if (!card) {
-		put_device(dev);
-		QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);
-		return -ENOMEM;
-	}
-	card->read.ccwdev  = gdev->cdev[0];
-	card->write.ccwdev = gdev->cdev[1];
-	card->data.ccwdev  = gdev->cdev[2];
-	gdev->dev.driver_data = card;
-	card->gdev = gdev;
-	gdev->cdev[0]->handler = qeth_irq;
-	gdev->cdev[1]->handler = qeth_irq;
-	gdev->cdev[2]->handler = qeth_irq;
-
-	if ((rc = qeth_determine_card_type(card))){
-		PRINT_WARN("%s: not a valid card type\n", __func__);
-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-		put_device(dev);
-		qeth_free_card(card);
-		return rc;
-	}
-	if ((rc = qeth_setup_card(card))){
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		put_device(dev);
-		qeth_free_card(card);
-		return rc;
-	}
-	rc = qeth_create_device_attributes(dev);
-	if (rc) {
-		put_device(dev);
-		qeth_free_card(card);
-		return rc;
-	}
-	/* insert into our internal list */
-	write_lock_irqsave(&qeth_card_list.rwlock, flags);
-	list_add_tail(&card->list, &qeth_card_list.list);
-	write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
-	return rc;
-}
-
-
-static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
-			       int *length)
-{
-	struct ciw *ciw;
-	char *rcd_buf;
-	int ret;
-	struct qeth_channel *channel = &card->data;
-	unsigned long flags;
-
-	/*
-	 * scan for RCD command in extended SenseID data
-	 */
-	ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
-	if (!ciw || ciw->cmd == 0)
-		return -EOPNOTSUPP;
-	rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
-	if (!rcd_buf)
-		return -ENOMEM;
-
-	channel->ccw.cmd_code = ciw->cmd;
-	channel->ccw.cda = (__u32) __pa (rcd_buf);
-	channel->ccw.count = ciw->count;
-	channel->ccw.flags = CCW_FLAG_SLI;
-	channel->state = CH_STATE_RCD;
-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
-				       QETH_RCD_PARM, LPM_ANYPATH, 0,
-				       QETH_RCD_TIMEOUT);
-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
-	if (!ret)
-		wait_event(card->wait_q,
-			   (channel->state == CH_STATE_RCD_DONE ||
-			    channel->state == CH_STATE_DOWN));
-	if (channel->state == CH_STATE_DOWN)
-		ret = -EIO;
-	else
-		channel->state = CH_STATE_DOWN;
-	if (ret) {
-		kfree(rcd_buf);
-		*buffer = NULL;
-		*length = 0;
-	} else {
-		*length = ciw->count;
-		*buffer = rcd_buf;
-	}
-	return ret;
-}
-
-static int
-qeth_get_unitaddr(struct qeth_card *card)
-{
- 	int length;
-	char *prcd;
-	int rc;
-
-	QETH_DBF_TEXT(setup, 2, "getunit");
-	rc = qeth_read_conf_data(card, (void **) &prcd, &length);
-	if (rc) {
-		PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
-			  CARD_DDEV_ID(card), rc);
-		return rc;
-	}
-	card->info.chpid = prcd[30];
-	card->info.unit_addr2 = prcd[31];
-	card->info.cula = prcd[63];
-	card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
-			       (prcd[0x11] == _ascebc['M']));
-	kfree(prcd);
-	return 0;
-}
-
-static void
-qeth_init_tokens(struct qeth_card *card)
-{
-	card->token.issuer_rm_w = 0x00010103UL;
-	card->token.cm_filter_w = 0x00010108UL;
-	card->token.cm_connection_w = 0x0001010aUL;
-	card->token.ulp_filter_w = 0x0001010bUL;
-	card->token.ulp_connection_w = 0x0001010dUL;
-}
-
-static inline __u16
-raw_devno_from_bus_id(char *id)
-{
-        id += (strlen(id) - 4);
-        return (__u16) simple_strtoul(id, &id, 16);
-}
-/**
- * setup channel
- */
-static void
-qeth_setup_ccw(struct qeth_channel *channel,unsigned char *iob, __u32 len)
-{
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(trace, 4, "setupccw");
-	card = CARD_FROM_CDEV(channel->ccwdev);
-	if (channel == &card->read)
-		memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
-	else
-		memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
-	channel->ccw.count = len;
-	channel->ccw.cda = (__u32) __pa(iob);
-}
-
-/**
- * get free buffer for ccws (IDX activation, lancmds,ipassists...)
- */
-static struct qeth_cmd_buffer *
-__qeth_get_buffer(struct qeth_channel *channel)
-{
-	__u8 index;
-
-	QETH_DBF_TEXT(trace, 6, "getbuff");
-	index = channel->io_buf_no;
-	do {
-		if (channel->iob[index].state == BUF_STATE_FREE) {
-			channel->iob[index].state = BUF_STATE_LOCKED;
-			channel->io_buf_no = (channel->io_buf_no + 1) %
-				QETH_CMD_BUFFER_NO;
-			memset(channel->iob[index].data, 0, QETH_BUFSIZE);
-			return channel->iob + index;
-		}
-		index = (index + 1) % QETH_CMD_BUFFER_NO;
-	} while(index != channel->io_buf_no);
-
-	return NULL;
-}
-
-/**
- * release command buffer
- */
-static void
-qeth_release_buffer(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
-{
-	unsigned long flags;
-
-	QETH_DBF_TEXT(trace, 6, "relbuff");
-	spin_lock_irqsave(&channel->iob_lock, flags);
-	memset(iob->data, 0, QETH_BUFSIZE);
-	iob->state = BUF_STATE_FREE;
-	iob->callback = qeth_send_control_data_cb;
-	iob->rc = 0;
-	spin_unlock_irqrestore(&channel->iob_lock, flags);
-}
-
-static struct qeth_cmd_buffer *
-qeth_get_buffer(struct qeth_channel *channel)
-{
-	struct qeth_cmd_buffer *buffer = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&channel->iob_lock, flags);
-	buffer = __qeth_get_buffer(channel);
-	spin_unlock_irqrestore(&channel->iob_lock, flags);
-	return buffer;
-}
-
-static struct qeth_cmd_buffer *
-qeth_wait_for_buffer(struct qeth_channel *channel)
-{
-	struct qeth_cmd_buffer *buffer;
-	wait_event(channel->wait_q,
-		   ((buffer = qeth_get_buffer(channel)) != NULL));
-	return buffer;
-}
-
-static void
-qeth_clear_cmd_buffers(struct qeth_channel *channel)
-{
-	int cnt;
-
-	for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++)
-		qeth_release_buffer(channel,&channel->iob[cnt]);
-	channel->buf_no = 0;
-	channel->io_buf_no = 0;
-}
-
-/**
- * start IDX for read and write channel
- */
-static int
-qeth_idx_activate_get_answer(struct qeth_channel *channel,
-			      void (*idx_reply_cb)(struct qeth_channel *,
-						   struct qeth_cmd_buffer *))
-{
-	struct qeth_cmd_buffer *iob;
-	unsigned long flags;
-	int rc;
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(setup, 2, "idxanswr");
-	card = CARD_FROM_CDEV(channel->ccwdev);
-	iob = qeth_get_buffer(channel);
-	iob->callback = idx_reply_cb;
-	memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
-	channel->ccw.count = QETH_BUFSIZE;
-	channel->ccw.cda = (__u32) __pa(iob->data);
-
-	wait_event(card->wait_q,
-		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
-	QETH_DBF_TEXT(setup, 6, "noirqpnd");
-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_start(channel->ccwdev,
-			      &channel->ccw,(addr_t) iob, 0, 0);
-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
-
-	if (rc) {
-		PRINT_ERR("qeth: Error2 in activating channel rc=%d\n",rc);
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		atomic_set(&channel->irq_pending, 0);
-		wake_up(&card->wait_q);
-		return rc;
-	}
-	rc = wait_event_interruptible_timeout(card->wait_q,
-			 channel->state == CH_STATE_UP, QETH_TIMEOUT);
-	if (rc == -ERESTARTSYS)
-		return rc;
-	if (channel->state != CH_STATE_UP){
-		rc = -ETIME;
-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-		qeth_clear_cmd_buffers(channel);
-	} else
-		rc = 0;
-	return rc;
-}
-
-static int
-qeth_idx_activate_channel(struct qeth_channel *channel,
-			   void (*idx_reply_cb)(struct qeth_channel *,
-						struct qeth_cmd_buffer *))
-{
-	struct qeth_card *card;
-	struct qeth_cmd_buffer *iob;
-	unsigned long flags;
-	__u16 temp;
-	int rc;
-
-	card = CARD_FROM_CDEV(channel->ccwdev);
-
-	QETH_DBF_TEXT(setup, 2, "idxactch");
-
-	iob = qeth_get_buffer(channel);
-	iob->callback = idx_reply_cb;
-	memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
-	channel->ccw.count = IDX_ACTIVATE_SIZE;
-	channel->ccw.cda = (__u32) __pa(iob->data);
-	if (channel == &card->write) {
-		memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
-		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
-		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
-		card->seqno.trans_hdr++;
-	} else {
-		memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
-		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
-		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
-	}
-	memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
-	       &card->token.issuer_rm_w,QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),
-	       &card->info.func_level,sizeof(__u16));
-	temp = raw_devno_from_bus_id(CARD_DDEV_ID(card));
-	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);
-	temp = (card->info.cula << 8) + card->info.unit_addr2;
-	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
-
-	wait_event(card->wait_q,
-		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
-	QETH_DBF_TEXT(setup, 6, "noirqpnd");
-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_start(channel->ccwdev,
-			      &channel->ccw,(addr_t) iob, 0, 0);
-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
-
-	if (rc) {
-		PRINT_ERR("qeth: Error1 in activating channel. rc=%d\n",rc);
-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-		atomic_set(&channel->irq_pending, 0);
-		wake_up(&card->wait_q);
-		return rc;
-	}
-	rc = wait_event_interruptible_timeout(card->wait_q,
-			channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);
-	if (rc == -ERESTARTSYS)
-		return rc;
-	if (channel->state != CH_STATE_ACTIVATING) {
-		PRINT_WARN("qeth: IDX activate timed out!\n");
-		QETH_DBF_TEXT_(setup, 2, "2err%d", -ETIME);
-		qeth_clear_cmd_buffers(channel);
-		return -ETIME;
-	}
-	return qeth_idx_activate_get_answer(channel,idx_reply_cb);
-}
-
-static int
-qeth_peer_func_level(int level)
-{
-	if ((level & 0xff) == 8)
-		return (level & 0xff) + 0x400;
-	if (((level >> 8) & 3) == 1)
-		return (level & 0xff) + 0x200;
-	return level;
-}
-
-static void
-qeth_idx_write_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
-{
-	struct qeth_card *card;
-	__u16 temp;
-
-	QETH_DBF_TEXT(setup ,2, "idxwrcb");
-
-	if (channel->state == CH_STATE_DOWN) {
-		channel->state = CH_STATE_ACTIVATING;
-		goto out;
-	}
-	card = CARD_FROM_CDEV(channel->ccwdev);
-
-	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
-		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
-			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
-				"adapter exclusively used by another host\n",
-				CARD_WDEV_ID(card));
-		else
-			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
-				"negative reply\n", CARD_WDEV_ID(card));
-		goto out;
-	}
-	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
-	if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
-		PRINT_WARN("IDX_ACTIVATE on write channel device %s: "
-			"function level mismatch "
-			"(sent: 0x%x, received: 0x%x)\n",
-			CARD_WDEV_ID(card), card->info.func_level, temp);
-		goto out;
-	}
-	channel->state = CH_STATE_UP;
-out:
-	qeth_release_buffer(channel, iob);
-}
-
-static int
-qeth_check_idx_response(unsigned char *buffer)
-{
-	if (!buffer)
-		return 0;
-
-	QETH_DBF_HEX(control, 2, buffer, QETH_DBF_CONTROL_LEN);
-	if ((buffer[2] & 0xc0) == 0xc0) {
-		PRINT_WARN("received an IDX TERMINATE "
-			   "with cause code 0x%02x%s\n",
-			   buffer[4],
-			   ((buffer[4] == 0x22) ?
-			    " -- try another portname" : ""));
-		QETH_DBF_TEXT(trace, 2, "ckidxres");
-		QETH_DBF_TEXT(trace, 2, " idxterm");
-		QETH_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
-		return -EIO;
-	}
-	return 0;
-}
-
-static void
-qeth_idx_read_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
-{
-	struct qeth_card *card;
-	__u16 temp;
-
-	QETH_DBF_TEXT(setup , 2, "idxrdcb");
-	if (channel->state == CH_STATE_DOWN) {
-		channel->state = CH_STATE_ACTIVATING;
-		goto out;
-	}
-
-	card = CARD_FROM_CDEV(channel->ccwdev);
-	if (qeth_check_idx_response(iob->data)) {
-			goto out;
-	}
-	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
-		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
-			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
-				"adapter exclusively used by another host\n",
-				CARD_RDEV_ID(card));
-		else
-			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
-				"negative reply\n", CARD_RDEV_ID(card));
-		goto out;
-	}
-
-/**
- * temporary fix for microcode bug
- * to revert it,replace OR by AND
- */
-	if ( (!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
-	     (card->info.type == QETH_CARD_TYPE_OSAE) )
-		card->info.portname_required = 1;
-
-	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
-	if (temp != qeth_peer_func_level(card->info.func_level)) {
-		PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
-			"level mismatch (sent: 0x%x, received: 0x%x)\n",
-			CARD_RDEV_ID(card), card->info.func_level, temp);
-		goto out;
-	}
-	memcpy(&card->token.issuer_rm_r,
-	       QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
-	       QETH_MPC_TOKEN_LENGTH);
-	memcpy(&card->info.mcl_level[0],
-	       QETH_IDX_REPLY_LEVEL(iob->data), QETH_MCL_LENGTH);
-	channel->state = CH_STATE_UP;
-out:
-	qeth_release_buffer(channel,iob);
-}
-
-static int
-qeth_issue_next_read(struct qeth_card *card)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(trace,5,"issnxrd");
-	if (card->read.state != CH_STATE_UP)
-		return -EIO;
-	iob = qeth_get_buffer(&card->read);
-	if (!iob) {
-		PRINT_WARN("issue_next_read failed: no iob available!\n");
-		return -ENOMEM;
-	}
-	qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
-	QETH_DBF_TEXT(trace, 6, "noirqpnd");
-	rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
-			      (addr_t) iob, 0, 0);
-	if (rc) {
-		PRINT_ERR("Error in starting next read ccw! rc=%i\n", rc);
-		atomic_set(&card->read.irq_pending, 0);
-		qeth_schedule_recovery(card);
-		wake_up(&card->wait_q);
-	}
-	return rc;
-}
-
-static struct qeth_reply *
-qeth_alloc_reply(struct qeth_card *card)
-{
-	struct qeth_reply *reply;
-
-	reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
-	if (reply){
-		atomic_set(&reply->refcnt, 1);
-		atomic_set(&reply->received, 0);
-		reply->card = card;
-	};
-	return reply;
-}
-
-static void
-qeth_get_reply(struct qeth_reply *reply)
-{
-	WARN_ON(atomic_read(&reply->refcnt) <= 0);
-	atomic_inc(&reply->refcnt);
-}
-
-static void
-qeth_put_reply(struct qeth_reply *reply)
-{
-	WARN_ON(atomic_read(&reply->refcnt) <= 0);
-	if (atomic_dec_and_test(&reply->refcnt))
-		kfree(reply);
-}
-
-static void
-qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, struct qeth_card *card)
-{
-	int rc;
-	int com;
-	char * ipa_name;
-
-	com = cmd->hdr.command;
-	rc  = cmd->hdr.return_code;
-	ipa_name = qeth_get_ipa_cmd_name(com);
-
-	PRINT_ERR("%s(x%X) for %s returned x%X \"%s\"\n", ipa_name, com,
-		   QETH_CARD_IFNAME(card), rc, qeth_get_ipa_msg(rc));
-}
-
-static struct qeth_ipa_cmd *
-qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
-{
-	struct qeth_ipa_cmd *cmd = NULL;
-
-	QETH_DBF_TEXT(trace,5,"chkipad");
-	if (IS_IPA(iob->data)){
-		cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
-		if (IS_IPA_REPLY(cmd)) {
-			if (cmd->hdr.return_code)
-				qeth_issue_ipa_msg(cmd, card);
-			return cmd;
-		}
-		else {
-			switch (cmd->hdr.command) {
-			case IPA_CMD_STOPLAN:
-				PRINT_WARN("Link failure on %s (CHPID 0x%X) - "
-					   "there is a network problem or "
-					   "someone pulled the cable or "
-					   "disabled the port.\n",
-					   QETH_CARD_IFNAME(card),
-					   card->info.chpid);
-				card->lan_online = 0;
-				if (card->dev && netif_carrier_ok(card->dev))
-					netif_carrier_off(card->dev);
-				return NULL;
-			case IPA_CMD_STARTLAN:
-				PRINT_INFO("Link reestablished on %s "
-					   "(CHPID 0x%X). Scheduling "
-					   "IP address reset.\n",
-					   QETH_CARD_IFNAME(card),
-					   card->info.chpid);
-				netif_carrier_on(card->dev);
-				qeth_schedule_recovery(card);
-				return NULL;
-			case IPA_CMD_MODCCID:
-				return cmd;
-			case IPA_CMD_REGISTER_LOCAL_ADDR:
-				QETH_DBF_TEXT(trace,3, "irla");
-				break;
-			case IPA_CMD_UNREGISTER_LOCAL_ADDR:
-				QETH_DBF_TEXT(trace,3, "urla");
-				break;
-			default:
-				PRINT_WARN("Received data is IPA "
-					   "but not a reply!\n");
-				break;
-			}
-		}
-	}
-	return cmd;
-}
-
-/**
- * wake all waiting ipa commands
- */
-static void
-qeth_clear_ipacmd_list(struct qeth_card *card)
-{
-	struct qeth_reply *reply, *r;
-	unsigned long flags;
-
-	QETH_DBF_TEXT(trace, 4, "clipalst");
-
-	spin_lock_irqsave(&card->lock, flags);
-	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
-		qeth_get_reply(reply);
-		reply->rc = -EIO;
-		atomic_inc(&reply->received);
-		list_del_init(&reply->list);
-		wake_up(&reply->wait_q);
-		qeth_put_reply(reply);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static void
-qeth_send_control_data_cb(struct qeth_channel *channel,
-			  struct qeth_cmd_buffer *iob)
-{
-	struct qeth_card *card;
-	struct qeth_reply *reply, *r;
-	struct qeth_ipa_cmd *cmd;
-	unsigned long flags;
-	int keep_reply;
-
-	QETH_DBF_TEXT(trace,4,"sndctlcb");
-
-	card = CARD_FROM_CDEV(channel->ccwdev);
-	if (qeth_check_idx_response(iob->data)) {
-		qeth_clear_ipacmd_list(card);
-		qeth_schedule_recovery(card);
-		goto out;
-	}
-
-	cmd = qeth_check_ipa_data(card, iob);
-	if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
-		goto out;
-	/*in case of OSN : check if cmd is set */
-	if (card->info.type == QETH_CARD_TYPE_OSN &&
-	    cmd &&
-	    cmd->hdr.command != IPA_CMD_STARTLAN &&
-	    card->osn_info.assist_cb != NULL) {
-		card->osn_info.assist_cb(card->dev, cmd);
-		goto out;
-	}
-
-	spin_lock_irqsave(&card->lock, flags);
-	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
-		if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
-		    ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
-			qeth_get_reply(reply);
-			list_del_init(&reply->list);
-			spin_unlock_irqrestore(&card->lock, flags);
-			keep_reply = 0;
-			if (reply->callback != NULL) {
-				if (cmd) {
-					reply->offset = (__u16)((char*)cmd -
-								(char *)iob->data);
-					keep_reply = reply->callback(card,
-							reply,
-							(unsigned long)cmd);
-				} else
-					keep_reply = reply->callback(card,
-							reply,
-							(unsigned long)iob);
-			}
-			if (cmd)
-				reply->rc = (u16) cmd->hdr.return_code;
-			else if (iob->rc)
-				reply->rc = iob->rc;
-			if (keep_reply) {
-				spin_lock_irqsave(&card->lock, flags);
-				list_add_tail(&reply->list,
-					      &card->cmd_waiter_list);
-				spin_unlock_irqrestore(&card->lock, flags);
-			} else {
-				atomic_inc(&reply->received);
-				wake_up(&reply->wait_q);
-			}
-			qeth_put_reply(reply);
-			goto out;
-		}
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-out:
-	memcpy(&card->seqno.pdu_hdr_ack,
-		QETH_PDU_HEADER_SEQ_NO(iob->data),
-		QETH_SEQ_NO_LENGTH);
-	qeth_release_buffer(channel,iob);
-}
-
-static void
-qeth_prepare_control_data(struct qeth_card *card, int len,
-			  struct qeth_cmd_buffer *iob)
-{
-	qeth_setup_ccw(&card->write,iob->data,len);
-	iob->callback = qeth_release_buffer;
-
-	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
-	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
-	card->seqno.trans_hdr++;
-	memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
-	       &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
-	card->seqno.pdu_hdr++;
-	memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
-	       &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
-	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
-}
-
-static int
-qeth_send_control_data(struct qeth_card *card, int len,
-		       struct qeth_cmd_buffer *iob,
-		       int (*reply_cb)
-		       (struct qeth_card *, struct qeth_reply*, unsigned long),
-		       void *reply_param)
-
-{
-	int rc;
-	unsigned long flags;
-	struct qeth_reply *reply = NULL;
-	unsigned long timeout;
-
-	QETH_DBF_TEXT(trace, 2, "sendctl");
-
-	reply = qeth_alloc_reply(card);
-	if (!reply) {
-		PRINT_WARN("Could no alloc qeth_reply!\n");
-		return -ENOMEM;
-	}
-	reply->callback = reply_cb;
-	reply->param = reply_param;
-	if (card->state == CARD_STATE_DOWN)
-		reply->seqno = QETH_IDX_COMMAND_SEQNO;
-	else
-		reply->seqno = card->seqno.ipa++;
-	init_waitqueue_head(&reply->wait_q);
-	spin_lock_irqsave(&card->lock, flags);
-	list_add_tail(&reply->list, &card->cmd_waiter_list);
-	spin_unlock_irqrestore(&card->lock, flags);
-	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
-
-	while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
-	qeth_prepare_control_data(card, len, iob);
-
-	if (IS_IPA(iob->data))
-		timeout = jiffies + QETH_IPA_TIMEOUT;
-	else
-		timeout = jiffies + QETH_TIMEOUT;
-
-	QETH_DBF_TEXT(trace, 6, "noirqpnd");
-	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
-	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
-			      (addr_t) iob, 0, 0);
-	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
-	if (rc){
-		PRINT_WARN("qeth_send_control_data: "
-			   "ccw_device_start rc = %i\n", rc);
-		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
-		spin_lock_irqsave(&card->lock, flags);
-		list_del_init(&reply->list);
-		qeth_put_reply(reply);
-		spin_unlock_irqrestore(&card->lock, flags);
-		qeth_release_buffer(iob->channel, iob);
-		atomic_set(&card->write.irq_pending, 0);
-		wake_up(&card->wait_q);
-		return rc;
-	}
-	while (!atomic_read(&reply->received)) {
-		if (time_after(jiffies, timeout)) {
-			spin_lock_irqsave(&reply->card->lock, flags);
-			list_del_init(&reply->list);
-			spin_unlock_irqrestore(&reply->card->lock, flags);
-			reply->rc = -ETIME;
-			atomic_inc(&reply->received);
-			wake_up(&reply->wait_q);
-		}
-		cpu_relax();
-	};
-	rc = reply->rc;
-	qeth_put_reply(reply);
-	return rc;
-}
-
-static int
-qeth_osn_send_control_data(struct qeth_card *card, int len,
-			   struct qeth_cmd_buffer *iob)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace, 5, "osndctrd");
-
-	wait_event(card->wait_q,
-		   atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
-	qeth_prepare_control_data(card, len, iob);
-	QETH_DBF_TEXT(trace, 6, "osnoirqp");
-	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
-	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
-			      (addr_t) iob, 0, 0);
-	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
-	if (rc){
-		PRINT_WARN("qeth_osn_send_control_data: "
-			   "ccw_device_start rc = %i\n", rc);
-		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
-		qeth_release_buffer(iob->channel, iob);
-		atomic_set(&card->write.irq_pending, 0);
-		wake_up(&card->wait_q);
-	}
-	return rc;
-}
-
-static inline void
-qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-		     char prot_type)
-{
-	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
-	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-}
-
-static int
-qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-		      int data_len)
-{
-	u16 s1, s2;
-
-	QETH_DBF_TEXT(trace,4,"osndipa");
-
-	qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
-	s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
-	s2 = (u16)data_len;
-	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
-	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
-	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
-	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
-	return qeth_osn_send_control_data(card, s1, iob);
-}
-
-static int
-qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-		  int (*reply_cb)
-		  (struct qeth_card *,struct qeth_reply*, unsigned long),
-		  void *reply_param)
-{
-	int rc;
-	char prot_type;
-
-	QETH_DBF_TEXT(trace,4,"sendipa");
-
-	if (card->options.layer2)
-		if (card->info.type == QETH_CARD_TYPE_OSN)
-			prot_type = QETH_PROT_OSN2;
-		else
-			prot_type = QETH_PROT_LAYER2;
-	else
-		prot_type = QETH_PROT_TCPIP;
-	qeth_prepare_ipa_cmd(card,iob,prot_type);
-	rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
-				    reply_cb, reply_param);
-	return rc;
-}
-
-
-static int
-qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
-		  unsigned long data)
-{
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(setup, 2, "cmenblcb");
-
-	iob = (struct qeth_cmd_buffer *) data;
-	memcpy(&card->token.cm_filter_r,
-	       QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
-	       QETH_MPC_TOKEN_LENGTH);
-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
-	return 0;
-}
-
-static int
-qeth_cm_enable(struct qeth_card *card)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(setup,2,"cmenable");
-
-	iob = qeth_wait_for_buffer(&card->write);
-	memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
-	memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
-	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
-	       &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
-
-	rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
-				    qeth_cm_enable_cb, NULL);
-	return rc;
-}
-
-static int
-qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
-		 unsigned long data)
-{
-
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(setup, 2, "cmsetpcb");
-
-	iob = (struct qeth_cmd_buffer *) data;
-	memcpy(&card->token.cm_connection_r,
-	       QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
-	       QETH_MPC_TOKEN_LENGTH);
-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
-	return 0;
-}
-
-static int
-qeth_cm_setup(struct qeth_card *card)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(setup,2,"cmsetup");
-
-	iob = qeth_wait_for_buffer(&card->write);
-	memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
-	memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
-	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
-	       &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
-	       &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
-	rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
-				    qeth_cm_setup_cb, NULL);
-	return rc;
-
-}
-
-static int
-qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
-		   unsigned long data)
-{
-
-	__u16 mtu, framesize;
-	__u16 len;
-	__u8 link_type;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(setup, 2, "ulpenacb");
-
-	iob = (struct qeth_cmd_buffer *) data;
-	memcpy(&card->token.ulp_filter_r,
-	       QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
-	       QETH_MPC_TOKEN_LENGTH);
-	if (qeth_get_mtu_out_of_mpc(card->info.type)) {
-		memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
-		mtu = qeth_get_mtu_outof_framesize(framesize);
-		if (!mtu) {
-			iob->rc = -EINVAL;
-			QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
-			return 0;
-		}
-		card->info.max_mtu = mtu;
-		card->info.initial_mtu = mtu;
-		card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
-	} else {
-		card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
-		card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
-		card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
-	}
-
-	memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
-	if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
-		memcpy(&link_type,
-		       QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
-		card->info.link_type = link_type;
-	} else
-		card->info.link_type = 0;
-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
-	return 0;
-}
-
-static int
-qeth_ulp_enable(struct qeth_card *card)
-{
-	int rc;
-	char prot_type;
-	struct qeth_cmd_buffer *iob;
-
-	/*FIXME: trace view callbacks*/
-	QETH_DBF_TEXT(setup,2,"ulpenabl");
-
-	iob = qeth_wait_for_buffer(&card->write);
-	memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
-
-	*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
-		(__u8) card->info.portno;
-	if (card->options.layer2)
-		if (card->info.type == QETH_CARD_TYPE_OSN)
-			prot_type = QETH_PROT_OSN2;
-		else
-			prot_type = QETH_PROT_LAYER2;
-	else
-		prot_type = QETH_PROT_TCPIP;
-
-	memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data),&prot_type,1);
-	memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
-	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
-	       &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
-	       card->info.portname, 9);
-	rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
-				    qeth_ulp_enable_cb, NULL);
-	return rc;
-
-}
-
-static int
-qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
-		  unsigned long data)
-{
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(setup, 2, "ulpstpcb");
-
-	iob = (struct qeth_cmd_buffer *) data;
-	memcpy(&card->token.ulp_connection_r,
-	       QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
-	       QETH_MPC_TOKEN_LENGTH);
-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
-	return 0;
-}
-
-static int
-qeth_ulp_setup(struct qeth_card *card)
-{
-	int rc;
-	__u16 temp;
-	struct qeth_cmd_buffer *iob;
-	struct ccw_dev_id dev_id;
-
-	QETH_DBF_TEXT(setup,2,"ulpsetup");
-
-	iob = qeth_wait_for_buffer(&card->write);
-	memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
-
-	memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
-	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
-	       &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
-	       &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
-
-	ccw_device_get_id(CARD_DDEV(card), &dev_id);
-	memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
-	temp = (card->info.cula << 8) + card->info.unit_addr2;
-	memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
-	rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
-				    qeth_ulp_setup_cb, NULL);
-	return rc;
-}
-
-static inline int
-qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
-		       unsigned int siga_error, const char *dbftext)
-{
-	if (qdio_error || siga_error) {
-		QETH_DBF_TEXT(trace, 2, dbftext);
-		QETH_DBF_TEXT(qerr, 2, dbftext);
-		QETH_DBF_TEXT_(qerr, 2, " F15=%02X",
-			       buf->element[15].flags & 0xff);
-		QETH_DBF_TEXT_(qerr, 2, " F14=%02X",
-			       buf->element[14].flags & 0xff);
-		QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error);
-		QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error);
-		return 1;
-	}
-	return 0;
-}
-
-static struct sk_buff *
-qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
-{
-	struct sk_buff* skb;
-	int add_len;
-
-	add_len = 0;
-	if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
-		add_len = sizeof(struct qeth_hdr);
-#ifdef CONFIG_QETH_VLAN
-	else
-		add_len = VLAN_HLEN;
-#endif
-	skb = dev_alloc_skb(length + add_len);
-	if (skb && add_len)
-		skb_reserve(skb, add_len);
-	return skb;
-}
-
-static inline int
-qeth_create_skb_frag(struct qdio_buffer_element *element,
-		     struct sk_buff **pskb,
-		     int offset, int *pfrag, int data_len)
-{
-	struct page *page = virt_to_page(element->addr);
-	if (*pfrag == 0) {
-		/* the upper protocol layers assume that there is data in the
-		 * skb itself. Copy a small amount (64 bytes) to make them
-		 * happy. */
-		*pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
-		if (!(*pskb))
-			return -ENOMEM;
-		skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
-		if (data_len <= 64) {
-			memcpy(skb_put(*pskb, data_len), element->addr + offset,
-				data_len);
-		} else {
-			get_page(page);
-			memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
-			skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
-				data_len - 64);
-			(*pskb)->data_len += data_len - 64;
-			(*pskb)->len	  += data_len - 64;
-			(*pskb)->truesize += data_len - 64;
-		}
-	} else {
-		get_page(page);
-		skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
-		(*pskb)->data_len += data_len;
-		(*pskb)->len	  += data_len;
-		(*pskb)->truesize += data_len;
-	}
-	(*pfrag)++;
-	return 0;
-}
-
-static inline struct qeth_buffer_pool_entry *
-qeth_find_free_buffer_pool_entry(struct qeth_card *card)
-{
-	struct list_head *plh;
-	struct qeth_buffer_pool_entry *entry;
-	int i, free;
-	struct page *page;
-
-	if (list_empty(&card->qdio.in_buf_pool.entry_list))
-		return NULL;
-
-	list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
-		entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
-		free = 1;
-		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
-			if (page_count(virt_to_page(entry->elements[i])) > 1) {
-				free = 0;
-				break;
-			}
-		}
-		if (free) {
-			list_del_init(&entry->list);
-			return entry;
-		}
-	}
-
-	/* no free buffer in pool so take first one and swap pages */
-	entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
-			struct qeth_buffer_pool_entry, list);
-	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
-		if (page_count(virt_to_page(entry->elements[i])) > 1) {
-			page = alloc_page(GFP_ATOMIC|GFP_DMA);
-			if (!page) {
-				return NULL;
-			} else {
-				free_page((unsigned long)entry->elements[i]);
-				entry->elements[i] = page_address(page);
-				if (card->options.performance_stats)
-					card->perf_stats.sg_alloc_page_rx++;
-			}
-		}
-	}
-	list_del_init(&entry->list);
-	return entry;
-}
-
-static struct sk_buff *
-qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
-		  struct qdio_buffer_element **__element, int *__offset,
-		  struct qeth_hdr **hdr)
-{
-	struct qdio_buffer_element *element = *__element;
-	int offset = *__offset;
-	struct sk_buff *skb = NULL;
-	int skb_len;
-	void *data_ptr;
-	int data_len;
-	int use_rx_sg = 0;
-	int frag = 0;
-
-	QETH_DBF_TEXT(trace,6,"nextskb");
-	/* qeth_hdr must not cross element boundaries */
-	if (element->length < offset + sizeof(struct qeth_hdr)){
-		if (qeth_is_last_sbale(element))
-			return NULL;
-		element++;
-		offset = 0;
-		if (element->length < sizeof(struct qeth_hdr))
-			return NULL;
-	}
-	*hdr = element->addr + offset;
-
-	offset += sizeof(struct qeth_hdr);
-	if (card->options.layer2)
-		if (card->info.type == QETH_CARD_TYPE_OSN)
-			skb_len = (*hdr)->hdr.osn.pdu_length;
-		else
-			skb_len = (*hdr)->hdr.l2.pkt_length;
-	else
-		skb_len = (*hdr)->hdr.l3.length;
-
-	if (!skb_len)
-		return NULL;
-	if ((skb_len >= card->options.rx_sg_cb) &&
-	    (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
-	    (!atomic_read(&card->force_alloc_skb))) {
-		use_rx_sg = 1;
-	} else {
-		if (card->options.fake_ll) {
-			if (card->dev->type == ARPHRD_IEEE802_TR) {
-				if (!(skb = qeth_get_skb(skb_len +
-						QETH_FAKE_LL_LEN_TR, *hdr)))
-					goto no_mem;
-				skb_reserve(skb, QETH_FAKE_LL_LEN_TR);
-			} else {
-				if (!(skb = qeth_get_skb(skb_len +
-						QETH_FAKE_LL_LEN_ETH, *hdr)))
-					goto no_mem;
-				skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
-			}
-		} else {
-			skb = qeth_get_skb(skb_len, *hdr);
-			if (!skb)
-				goto no_mem;
-		}
-	}
-
-	data_ptr = element->addr + offset;
-	while (skb_len) {
-		data_len = min(skb_len, (int)(element->length - offset));
-		if (data_len) {
-			if (use_rx_sg) {
-				if (qeth_create_skb_frag(element, &skb, offset,
-				    &frag, data_len))
-					goto no_mem;
-			} else {
-				memcpy(skb_put(skb, data_len), data_ptr,
-					data_len);
-			}
-		}
-		skb_len -= data_len;
-		if (skb_len){
-			if (qeth_is_last_sbale(element)){
-				QETH_DBF_TEXT(trace,4,"unexeob");
-				QETH_DBF_TEXT_(trace,4,"%s",CARD_BUS_ID(card));
-				QETH_DBF_TEXT(qerr,2,"unexeob");
-				QETH_DBF_TEXT_(qerr,2,"%s",CARD_BUS_ID(card));
-				QETH_DBF_HEX(misc,4,buffer,sizeof(*buffer));
-				dev_kfree_skb_any(skb);
-				card->stats.rx_errors++;
-				return NULL;
-			}
-			element++;
-			offset = 0;
-			data_ptr = element->addr;
-		} else {
-			offset += data_len;
-		}
-	}
-	*__element = element;
-	*__offset = offset;
-	if (use_rx_sg && card->options.performance_stats) {
-		card->perf_stats.sg_skbs_rx++;
-		card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
-	}
-	return skb;
-no_mem:
-	if (net_ratelimit()){
-		PRINT_WARN("No memory for packet received on %s.\n",
-			   QETH_CARD_IFNAME(card));
-		QETH_DBF_TEXT(trace,2,"noskbmem");
-		QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
-	}
-	card->stats.rx_dropped++;
-	return NULL;
-}
-
-static __be16
-qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
-	struct qeth_card *card;
-	struct ethhdr *eth;
-
-	QETH_DBF_TEXT(trace,6,"typtrans");
-
-	card = (struct qeth_card *)dev->priv;
-#ifdef CONFIG_TR
-	if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-	    (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
-	 	return tr_type_trans(skb,dev);
-#endif /* CONFIG_TR */
-	skb_reset_mac_header(skb);
-	skb_pull(skb, ETH_HLEN );
-	eth = eth_hdr(skb);
-
-	if (*eth->h_dest & 1) {
-		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
-			skb->pkt_type = PACKET_BROADCAST;
-		else
-			skb->pkt_type = PACKET_MULTICAST;
-	} else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
-		skb->pkt_type = PACKET_OTHERHOST;
-
-	if (ntohs(eth->h_proto) >= 1536)
-		return eth->h_proto;
-	if (*(unsigned short *) (skb->data) == 0xFFFF)
-		return htons(ETH_P_802_3);
-	return htons(ETH_P_802_2);
-}
-
-static void
-qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
-			 struct qeth_hdr *hdr)
-{
-	struct trh_hdr *fake_hdr;
-	struct trllc *fake_llc;
-	struct iphdr *ip_hdr;
-
-	QETH_DBF_TEXT(trace,5,"skbfktr");
-	skb_set_mac_header(skb, (int)-QETH_FAKE_LL_LEN_TR);
-	/* this is a fake ethernet header */
-	fake_hdr = tr_hdr(skb);
-
-	/* the destination MAC address */
-	switch (skb->pkt_type){
-	case PACKET_MULTICAST:
-		switch (skb->protocol){
-#ifdef CONFIG_QETH_IPV6
-		case __constant_htons(ETH_P_IPV6):
-			ndisc_mc_map((struct in6_addr *)
-				     skb->data + QETH_FAKE_LL_V6_ADDR_POS,
-				     fake_hdr->daddr, card->dev, 0);
-			break;
-#endif /* CONFIG_QETH_IPV6 */
-		case __constant_htons(ETH_P_IP):
-			ip_hdr = (struct iphdr *)skb->data;
-			ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr);
-			break;
-		default:
-			memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
-		}
-		break;
-	case PACKET_BROADCAST:
-		memset(fake_hdr->daddr, 0xff, TR_ALEN);
-		break;
-	default:
-		memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
-	}
-	/* the source MAC address */
-	if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
-		memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN);
-	else
-		memset(fake_hdr->saddr, 0, TR_ALEN);
-	fake_hdr->rcf=0;
-	fake_llc = (struct trllc*)&(fake_hdr->rcf);
-	fake_llc->dsap = EXTENDED_SAP;
-	fake_llc->ssap = EXTENDED_SAP;
-	fake_llc->llc  = UI_CMD;
-	fake_llc->protid[0] = 0;
-	fake_llc->protid[1] = 0;
-	fake_llc->protid[2] = 0;
-	fake_llc->ethertype = ETH_P_IP;
-}
-
-static void
-qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
-			 struct qeth_hdr *hdr)
-{
-	struct ethhdr *fake_hdr;
-	struct iphdr *ip_hdr;
-
-	QETH_DBF_TEXT(trace,5,"skbfketh");
-	skb_set_mac_header(skb, -QETH_FAKE_LL_LEN_ETH);
-	/* this is a fake ethernet header */
-	fake_hdr = eth_hdr(skb);
-
-	/* the destination MAC address */
-	switch (skb->pkt_type){
-	case PACKET_MULTICAST:
-		switch (skb->protocol){
-#ifdef CONFIG_QETH_IPV6
-		case __constant_htons(ETH_P_IPV6):
-			ndisc_mc_map((struct in6_addr *)
-				     skb->data + QETH_FAKE_LL_V6_ADDR_POS,
-				     fake_hdr->h_dest, card->dev, 0);
-			break;
-#endif /* CONFIG_QETH_IPV6 */
-		case __constant_htons(ETH_P_IP):
-			ip_hdr = (struct iphdr *)skb->data;
-			ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
-			break;
-		default:
-			memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
-		}
-		break;
-	case PACKET_BROADCAST:
-		memset(fake_hdr->h_dest, 0xff, ETH_ALEN);
-		break;
-	default:
-		memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
-	}
-	/* the source MAC address */
-	if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
-		memcpy(fake_hdr->h_source, &hdr->hdr.l3.dest_addr[2], ETH_ALEN);
-	else
-		memset(fake_hdr->h_source, 0, ETH_ALEN);
-	/* the protocol */
-	fake_hdr->h_proto = skb->protocol;
-}
-
-static inline void
-qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
-			struct qeth_hdr *hdr)
-{
-	if (card->dev->type == ARPHRD_IEEE802_TR)
-		qeth_rebuild_skb_fake_ll_tr(card, skb, hdr);
-	else
-		qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
-}
-
-static inline void
-qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
-			struct qeth_hdr *hdr)
-{
-	skb->pkt_type = PACKET_HOST;
-	skb->protocol = qeth_type_trans(skb, skb->dev);
-	if (card->options.checksum_type == NO_CHECKSUMMING)
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	else
-		skb->ip_summed = CHECKSUM_NONE;
-	*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
-}
-
-static __u16
-qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
-		 struct qeth_hdr *hdr)
-{
-	unsigned short vlan_id = 0;
-#ifdef CONFIG_QETH_IPV6
-	if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) {
-		skb->pkt_type = PACKET_HOST;
-		skb->protocol = qeth_type_trans(skb, card->dev);
-		return 0;
-	}
-#endif /* CONFIG_QETH_IPV6 */
-	skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
-			      ETH_P_IP);
-	switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK){
-	case QETH_CAST_UNICAST:
-		skb->pkt_type = PACKET_HOST;
-		break;
-	case QETH_CAST_MULTICAST:
-		skb->pkt_type = PACKET_MULTICAST;
-		card->stats.multicast++;
-		break;
-	case QETH_CAST_BROADCAST:
-		skb->pkt_type = PACKET_BROADCAST;
-		card->stats.multicast++;
-		break;
-	case QETH_CAST_ANYCAST:
-	case QETH_CAST_NOCAST:
-	default:
-		skb->pkt_type = PACKET_HOST;
-	}
-
-	if (hdr->hdr.l3.ext_flags &
-	    (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
-		vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
-			hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
-	}
-
-	if (card->options.fake_ll)
-		qeth_rebuild_skb_fake_ll(card, skb, hdr);
-	else
-		skb_reset_mac_header(skb);
-	skb->ip_summed = card->options.checksum_type;
-	if (card->options.checksum_type == HW_CHECKSUMMING){
-		if ( (hdr->hdr.l3.ext_flags &
-		      (QETH_HDR_EXT_CSUM_HDR_REQ |
-		       QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
-		     (QETH_HDR_EXT_CSUM_HDR_REQ |
-		      QETH_HDR_EXT_CSUM_TRANSP_REQ) )
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else
-			skb->ip_summed = SW_CHECKSUMMING;
-	}
-	return vlan_id;
-}
-
-static void
-qeth_process_inbound_buffer(struct qeth_card *card,
-			    struct qeth_qdio_buffer *buf, int index)
-{
-	struct qdio_buffer_element *element;
-	struct sk_buff *skb;
-	struct qeth_hdr *hdr;
-	int offset;
-	int rxrc;
-	__u16 vlan_tag = 0;
-
-	/* get first element of current buffer */
-	element = (struct qdio_buffer_element *)&buf->buffer->element[0];
-	offset = 0;
-	if (card->options.performance_stats)
-		card->perf_stats.bufs_rec++;
-	while((skb = qeth_get_next_skb(card, buf->buffer, &element,
-				       &offset, &hdr))) {
-		skb->dev = card->dev;
-		if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
-			qeth_layer2_rebuild_skb(card, skb, hdr);
-		else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
-			vlan_tag = qeth_rebuild_skb(card, skb, hdr);
-		else if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN) {
-			skb_push(skb, sizeof(struct qeth_hdr));
-			skb_copy_to_linear_data(skb, hdr,
-						sizeof(struct qeth_hdr));
-		} else { /* unknown header type */
-			dev_kfree_skb_any(skb);
-			QETH_DBF_TEXT(trace, 3, "inbunkno");
-			QETH_DBF_HEX(control, 3, hdr, QETH_DBF_CONTROL_LEN);
-			continue;
-		}
-		/* is device UP ? */
-		if (!(card->dev->flags & IFF_UP)){
-			dev_kfree_skb_any(skb);
-			continue;
-		}
-		if (card->info.type == QETH_CARD_TYPE_OSN)
-			rxrc = card->osn_info.data_cb(skb);
-		else
-#ifdef CONFIG_QETH_VLAN
-		if (vlan_tag)
-			if (card->vlangrp)
-				vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
-			else {
-				dev_kfree_skb_any(skb);
-				continue;
-			}
-		else
-#endif
-			rxrc = netif_rx(skb);
-		card->dev->last_rx = jiffies;
-		card->stats.rx_packets++;
-		card->stats.rx_bytes += skb->len;
-	}
-}
-
-static int
-qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
-{
-	struct qeth_buffer_pool_entry *pool_entry;
-	int i;
-
-	pool_entry = qeth_find_free_buffer_pool_entry(card);
-	if (!pool_entry)
-		return 1;
-	/*
-	 * since the buffer is accessed only from the input_tasklet
-	 * there shouldn't be a need to synchronize; also, since we use
-	 * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run  out off
-	 * buffers
-	 */
-	BUG_ON(!pool_entry);
-
-	buf->pool_entry = pool_entry;
-	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
-		buf->buffer->element[i].length = PAGE_SIZE;
-		buf->buffer->element[i].addr =  pool_entry->elements[i];
-		if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
-			buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
-		else
-			buf->buffer->element[i].flags = 0;
-	}
-	buf->state = QETH_QDIO_BUF_EMPTY;
-	return 0;
-}
-
-static void
-qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
-			 struct qeth_qdio_out_buffer *buf)
-{
-	int i;
-	struct sk_buff *skb;
-
-	/* is PCI flag set on buffer? */
-	if (buf->buffer->element[0].flags & 0x40)
-		atomic_dec(&queue->set_pci_flags_count);
-
-	while ((skb = skb_dequeue(&buf->skb_list))){
-		atomic_dec(&skb->users);
-		dev_kfree_skb_any(skb);
-	}
-	qeth_eddp_buf_release_contexts(buf);
-	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i){
-		buf->buffer->element[i].length = 0;
-		buf->buffer->element[i].addr = NULL;
-		buf->buffer->element[i].flags = 0;
-	}
-	buf->next_element_to_fill = 0;
-	atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
-}
-
-static void
-qeth_queue_input_buffer(struct qeth_card *card, int index)
-{
-	struct qeth_qdio_q *queue = card->qdio.in_q;
-	int count;
-	int i;
-	int rc;
-	int newcount = 0;
-
-	QETH_DBF_TEXT(trace,6,"queinbuf");
-	count = (index < queue->next_buf_to_init)?
-		card->qdio.in_buf_pool.buf_count -
-		(queue->next_buf_to_init - index) :
-		card->qdio.in_buf_pool.buf_count -
-		(queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
-	/* only requeue at a certain threshold to avoid SIGAs */
-	if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
-		for (i = queue->next_buf_to_init;
-		     i < queue->next_buf_to_init + count; ++i) {
-			if (qeth_init_input_buffer(card,
-				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
-				break;
-			} else {
-				newcount++;
-			}
-		}
-
-		if (newcount < count) {
-			/* we are in memory shortage so we switch back to
-			   traditional skb allocation and drop packages */
-			if (!atomic_read(&card->force_alloc_skb) &&
-			    net_ratelimit())
-				PRINT_WARN("Switch to alloc skb\n");
-			atomic_set(&card->force_alloc_skb, 3);
-			count = newcount;
-		} else {
-			if ((atomic_read(&card->force_alloc_skb) == 1) &&
-			    net_ratelimit())
-				PRINT_WARN("Switch to sg\n");
-			atomic_add_unless(&card->force_alloc_skb, -1, 0);
-		}
-
-		/*
-		 * according to old code it should be avoided to requeue all
-		 * 128 buffers in order to benefit from PCI avoidance.
-		 * this function keeps at least one buffer (the buffer at
-		 * 'index') un-requeued -> this buffer is the first buffer that
-		 * will be requeued the next time
-		 */
-		if (card->options.performance_stats) {
-			card->perf_stats.inbound_do_qdio_cnt++;
-			card->perf_stats.inbound_do_qdio_start_time =
-				qeth_get_micros();
-		}
-		rc = do_QDIO(CARD_DDEV(card),
-			     QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
-			     0, queue->next_buf_to_init, count, NULL);
-		if (card->options.performance_stats)
-			card->perf_stats.inbound_do_qdio_time +=
-				qeth_get_micros() -
-				card->perf_stats.inbound_do_qdio_start_time;
-		if (rc){
-			PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
-				   "return %i (device %s).\n",
-				   rc, CARD_DDEV_ID(card));
-			QETH_DBF_TEXT(trace,2,"qinberr");
-			QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
-		}
-		queue->next_buf_to_init = (queue->next_buf_to_init + count) %
-					  QDIO_MAX_BUFFERS_PER_Q;
-	}
-}
-
-static inline void
-qeth_put_buffer_pool_entry(struct qeth_card *card,
-			   struct qeth_buffer_pool_entry *entry)
-{
-	QETH_DBF_TEXT(trace, 6, "ptbfplen");
-	list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
-}
-
-static void
-qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
-		        unsigned int qdio_err, unsigned int siga_err,
-			unsigned int queue, int first_element, int count,
-			unsigned long card_ptr)
-{
-	struct net_device *net_dev;
-	struct qeth_card *card;
-	struct qeth_qdio_buffer *buffer;
-	int index;
-	int i;
-
-	QETH_DBF_TEXT(trace, 6, "qdinput");
-	card = (struct qeth_card *) card_ptr;
-	net_dev = card->dev;
-	if (card->options.performance_stats) {
-		card->perf_stats.inbound_cnt++;
-		card->perf_stats.inbound_start_time = qeth_get_micros();
-	}
-	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
-		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
-			QETH_DBF_TEXT(trace, 1,"qdinchk");
-			QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
-			QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count);
-			QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status);
-			qeth_schedule_recovery(card);
-			return;
-		}
-	}
-	for (i = first_element; i < (first_element + count); ++i) {
-		index = i % QDIO_MAX_BUFFERS_PER_Q;
-		buffer = &card->qdio.in_q->bufs[index];
-		if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
-		      qeth_check_qdio_errors(buffer->buffer,
-					     qdio_err, siga_err,"qinerr")))
-			qeth_process_inbound_buffer(card, buffer, index);
-		/* clear buffer and give back to hardware */
-		qeth_put_buffer_pool_entry(card, buffer->pool_entry);
-		qeth_queue_input_buffer(card, index);
-	}
-	if (card->options.performance_stats)
-		card->perf_stats.inbound_time += qeth_get_micros() -
-			card->perf_stats.inbound_start_time;
-}
-
-static int
-qeth_handle_send_error(struct qeth_card *card,
-		       struct qeth_qdio_out_buffer *buffer,
-		       unsigned int qdio_err, unsigned int siga_err)
-{
-	int sbalf15 = buffer->buffer->element[15].flags & 0xff;
-	int cc = siga_err & 3;
-
-	QETH_DBF_TEXT(trace, 6, "hdsnderr");
-	qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
-	switch (cc) {
-	case 0:
-		if (qdio_err){
-			QETH_DBF_TEXT(trace, 1,"lnkfail");
-			QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
-			QETH_DBF_TEXT_(trace,1,"%04x %02x",
-				       (u16)qdio_err, (u8)sbalf15);
-			return QETH_SEND_ERROR_LINK_FAILURE;
-		}
-		return QETH_SEND_ERROR_NONE;
-	case 2:
-		if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
-			QETH_DBF_TEXT(trace, 1, "SIGAcc2B");
-			QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
-			return QETH_SEND_ERROR_KICK_IT;
-		}
-		if ((sbalf15 >= 15) && (sbalf15 <= 31))
-			return QETH_SEND_ERROR_RETRY;
-		return QETH_SEND_ERROR_LINK_FAILURE;
-		/* look at qdio_error and sbalf 15 */
-	case 1:
-		QETH_DBF_TEXT(trace, 1, "SIGAcc1");
-		QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
-		return QETH_SEND_ERROR_LINK_FAILURE;
-	case 3:
-	default:
-		QETH_DBF_TEXT(trace, 1, "SIGAcc3");
-		QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
-		return QETH_SEND_ERROR_KICK_IT;
-	}
-}
-
-void
-qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
-		   int index, int count)
-{
-	struct qeth_qdio_out_buffer *buf;
-	int rc;
-	int i;
-	unsigned int qdio_flags;
-
-	QETH_DBF_TEXT(trace, 6, "flushbuf");
-
-	for (i = index; i < index + count; ++i) {
-		buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
-		buf->buffer->element[buf->next_element_to_fill - 1].flags |=
-				SBAL_FLAGS_LAST_ENTRY;
-
-		if (queue->card->info.type == QETH_CARD_TYPE_IQD)
-			continue;
-
-		if (!queue->do_pack){
-			if ((atomic_read(&queue->used_buffers) >=
-		    		(QETH_HIGH_WATERMARK_PACK -
-				 QETH_WATERMARK_PACK_FUZZ)) &&
-		    	    !atomic_read(&queue->set_pci_flags_count)){
-				/* it's likely that we'll go to packing
-				 * mode soon */
-				atomic_inc(&queue->set_pci_flags_count);
-				buf->buffer->element[0].flags |= 0x40;
-			}
-		} else {
-			if (!atomic_read(&queue->set_pci_flags_count)){
-				/*
-				 * there's no outstanding PCI any more, so we
-				 * have to request a PCI to be sure that the PCI
-				 * will wake at some time in the future then we
-				 * can flush packed buffers that might still be
-				 * hanging around, which can happen if no
-				 * further send was requested by the stack
-				 */
-				atomic_inc(&queue->set_pci_flags_count);
-				buf->buffer->element[0].flags |= 0x40;
-			}
-		}
-	}
-
-	queue->card->dev->trans_start = jiffies;
-	if (queue->card->options.performance_stats) {
-		queue->card->perf_stats.outbound_do_qdio_cnt++;
-		queue->card->perf_stats.outbound_do_qdio_start_time =
-			qeth_get_micros();
-	}
-	qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
-	if (under_int)
-		qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
-	if (atomic_read(&queue->set_pci_flags_count))
-		qdio_flags |= QDIO_FLAG_PCI_OUT;
-	rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
-		     queue->queue_no, index, count, NULL);
-	if (queue->card->options.performance_stats)
-		queue->card->perf_stats.outbound_do_qdio_time +=
-			qeth_get_micros() -
-			queue->card->perf_stats.outbound_do_qdio_start_time;
-	if (rc){
-		QETH_DBF_TEXT(trace, 2, "flushbuf");
-		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
-		QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
-		queue->card->stats.tx_errors += count;
-		/* this must not happen under normal circumstances. if it
-		 * happens something is really wrong -> recover */
-		qeth_schedule_recovery(queue->card);
-		return;
-	}
-	atomic_add(count, &queue->used_buffers);
-	if (queue->card->options.performance_stats)
-		queue->card->perf_stats.bufs_sent += count;
-}
-
-/*
- * Switched to packing state if the number of used buffers on a queue
- * reaches a certain limit.
- */
-static void
-qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
-{
-	if (!queue->do_pack) {
-		if (atomic_read(&queue->used_buffers)
-		    >= QETH_HIGH_WATERMARK_PACK){
-			/* switch non-PACKING -> PACKING */
-			QETH_DBF_TEXT(trace, 6, "np->pack");
-			if (queue->card->options.performance_stats)
-				queue->card->perf_stats.sc_dp_p++;
-			queue->do_pack = 1;
-		}
-	}
-}
-
-/*
- * Switches from packing to non-packing mode. If there is a packing
- * buffer on the queue this buffer will be prepared to be flushed.
- * In that case 1 is returned to inform the caller. If no buffer
- * has to be flushed, zero is returned.
- */
-static int
-qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
-{
-	struct qeth_qdio_out_buffer *buffer;
-	int flush_count = 0;
-
-	if (queue->do_pack) {
-		if (atomic_read(&queue->used_buffers)
-		    <= QETH_LOW_WATERMARK_PACK) {
-			/* switch PACKING -> non-PACKING */
-			QETH_DBF_TEXT(trace, 6, "pack->np");
-			if (queue->card->options.performance_stats)
-				queue->card->perf_stats.sc_p_dp++;
-			queue->do_pack = 0;
-			/* flush packing buffers */
-			buffer = &queue->bufs[queue->next_buf_to_fill];
-			if ((atomic_read(&buffer->state) ==
-						QETH_QDIO_BUF_EMPTY) &&
-			    (buffer->next_element_to_fill > 0)) {
-				atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
-				flush_count++;
-				queue->next_buf_to_fill =
-					(queue->next_buf_to_fill + 1) %
-					QDIO_MAX_BUFFERS_PER_Q;
-			}
-		}
-	}
-	return flush_count;
-}
-
-/*
- * Called to flush a packing buffer if no more pci flags are on the queue.
- * Checks if there is a packing buffer and prepares it to be flushed.
- * In that case returns 1, otherwise zero.
- */
-static int
-qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
-{
-	struct qeth_qdio_out_buffer *buffer;
-
-	buffer = &queue->bufs[queue->next_buf_to_fill];
-	if((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
-	   (buffer->next_element_to_fill > 0)){
-		/* it's a packing buffer */
-		atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
-		queue->next_buf_to_fill =
-			(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
-		return 1;
-	}
-	return 0;
-}
-
-static void
-qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
-{
-	int index;
-	int flush_cnt = 0;
-	int q_was_packing = 0;
-
-	/*
-	 * check if weed have to switch to non-packing mode or if
-	 * we have to get a pci flag out on the queue
-	 */
-	if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) ||
-	    !atomic_read(&queue->set_pci_flags_count)){
-		if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) ==
-				QETH_OUT_Q_UNLOCKED) {
-			/*
-			 * If we get in here, there was no action in
-			 * do_send_packet. So, we check if there is a
-			 * packing buffer to be flushed here.
-			 */
-			netif_stop_queue(queue->card->dev);
-			index = queue->next_buf_to_fill;
-			q_was_packing = queue->do_pack;
-			flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
-			if (!flush_cnt &&
-			    !atomic_read(&queue->set_pci_flags_count))
-				flush_cnt +=
-					qeth_flush_buffers_on_no_pci(queue);
-			if (queue->card->options.performance_stats &&
-			    q_was_packing)
-				queue->card->perf_stats.bufs_sent_pack +=
-					flush_cnt;
-			if (flush_cnt)
-				qeth_flush_buffers(queue, 1, index, flush_cnt);
-			atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
-		}
-	}
-}
-
-static void
-qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
-		        unsigned int qdio_error, unsigned int siga_error,
-			unsigned int __queue, int first_element, int count,
-			unsigned long card_ptr)
-{
-	struct qeth_card *card        = (struct qeth_card *) card_ptr;
-	struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
-	struct qeth_qdio_out_buffer *buffer;
-	int i;
-
-	QETH_DBF_TEXT(trace, 6, "qdouhdl");
-	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
-		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
-			QETH_DBF_TEXT(trace, 2, "achkcond");
-			QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
-			QETH_DBF_TEXT_(trace, 2, "%08x", status);
-			netif_stop_queue(card->dev);
-			qeth_schedule_recovery(card);
-			return;
-		}
-	}
-	if (card->options.performance_stats) {
-		card->perf_stats.outbound_handler_cnt++;
-		card->perf_stats.outbound_handler_start_time =
-			qeth_get_micros();
-	}
-	for(i = first_element; i < (first_element + count); ++i){
-		buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
-		/*we only handle the KICK_IT error by doing a recovery */
-		if (qeth_handle_send_error(card, buffer,
-					   qdio_error, siga_error)
-				== QETH_SEND_ERROR_KICK_IT){
-			netif_stop_queue(card->dev);
-			qeth_schedule_recovery(card);
-			return;
-		}
-		qeth_clear_output_buffer(queue, buffer);
-	}
-	atomic_sub(count, &queue->used_buffers);
-	/* check if we need to do something on this outbound queue */
-	if (card->info.type != QETH_CARD_TYPE_IQD)
-		qeth_check_outbound_queue(queue);
-
-	netif_wake_queue(queue->card->dev);
-	if (card->options.performance_stats)
-		card->perf_stats.outbound_handler_time += qeth_get_micros() -
-			card->perf_stats.outbound_handler_start_time;
-}
-
-static void
-qeth_create_qib_param_field(struct qeth_card *card, char *param_field)
-{
-
-	param_field[0] = _ascebc['P'];
-	param_field[1] = _ascebc['C'];
-	param_field[2] = _ascebc['I'];
-	param_field[3] = _ascebc['T'];
-	*((unsigned int *) (&param_field[4])) = QETH_PCI_THRESHOLD_A(card);
-	*((unsigned int *) (&param_field[8])) = QETH_PCI_THRESHOLD_B(card);
-	*((unsigned int *) (&param_field[12])) = QETH_PCI_TIMER_VALUE(card);
-}
-
-static void
-qeth_create_qib_param_field_blkt(struct qeth_card *card, char *param_field)
-{
-	param_field[16] = _ascebc['B'];
-        param_field[17] = _ascebc['L'];
-        param_field[18] = _ascebc['K'];
-        param_field[19] = _ascebc['T'];
-        *((unsigned int *) (&param_field[20])) = card->info.blkt.time_total;
-        *((unsigned int *) (&param_field[24])) = card->info.blkt.inter_packet;
-        *((unsigned int *) (&param_field[28])) = card->info.blkt.inter_packet_jumbo;
-}
-
-static void
-qeth_initialize_working_pool_list(struct qeth_card *card)
-{
-	struct qeth_buffer_pool_entry *entry;
-
-	QETH_DBF_TEXT(trace,5,"inwrklst");
-
-	list_for_each_entry(entry,
-			    &card->qdio.init_pool.entry_list, init_list) {
-		qeth_put_buffer_pool_entry(card,entry);
-	}
-}
-
-static void
-qeth_clear_working_pool_list(struct qeth_card *card)
-{
-	struct qeth_buffer_pool_entry *pool_entry, *tmp;
-
-	QETH_DBF_TEXT(trace,5,"clwrklst");
-	list_for_each_entry_safe(pool_entry, tmp,
-			    &card->qdio.in_buf_pool.entry_list, list){
-			list_del(&pool_entry->list);
-	}
-}
-
-static void
-qeth_free_buffer_pool(struct qeth_card *card)
-{
-	struct qeth_buffer_pool_entry *pool_entry, *tmp;
-	int i=0;
-	QETH_DBF_TEXT(trace,5,"freepool");
-	list_for_each_entry_safe(pool_entry, tmp,
-				 &card->qdio.init_pool.entry_list, init_list){
-		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
-			free_page((unsigned long)pool_entry->elements[i]);
-		list_del(&pool_entry->init_list);
-		kfree(pool_entry);
-	}
-}
-
-static int
-qeth_alloc_buffer_pool(struct qeth_card *card)
-{
-	struct qeth_buffer_pool_entry *pool_entry;
-	void *ptr;
-	int i, j;
-
-	QETH_DBF_TEXT(trace,5,"alocpool");
-	for (i = 0; i < card->qdio.init_pool.buf_count; ++i){
-	 	pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
-		if (!pool_entry){
-			qeth_free_buffer_pool(card);
-			return -ENOMEM;
-		}
-		for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){
-			ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA);
-			if (!ptr) {
-				while (j > 0)
-					free_page((unsigned long)
-						  pool_entry->elements[--j]);
-				kfree(pool_entry);
-				qeth_free_buffer_pool(card);
-				return -ENOMEM;
-			}
-			pool_entry->elements[j] = ptr;
-		}
-		list_add(&pool_entry->init_list,
-			 &card->qdio.init_pool.entry_list);
-	}
-	return 0;
-}
-
-int
-qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
-{
-	QETH_DBF_TEXT(trace, 2, "realcbp");
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	/* TODO: steel/add buffers from/to a running card's buffer pool (?) */
-	qeth_clear_working_pool_list(card);
-	qeth_free_buffer_pool(card);
-	card->qdio.in_buf_pool.buf_count = bufcnt;
-	card->qdio.init_pool.buf_count = bufcnt;
-	return qeth_alloc_buffer_pool(card);
-}
-
-static int
-qeth_alloc_qdio_buffers(struct qeth_card *card)
-{
-	int i, j;
-
-	QETH_DBF_TEXT(setup, 2, "allcqdbf");
-
-	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
-		QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
-		return 0;
-
-	card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
-				  GFP_KERNEL|GFP_DMA);
-	if (!card->qdio.in_q)
-		goto out_nomem;
-	QETH_DBF_TEXT(setup, 2, "inq");
-	QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *));
-	memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
-	/* give inbound qeth_qdio_buffers their qdio_buffers */
-	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
-		card->qdio.in_q->bufs[i].buffer =
-			&card->qdio.in_q->qdio_bufs[i];
-	/* inbound buffer pool */
-	if (qeth_alloc_buffer_pool(card))
-		goto out_freeinq;
-	/* outbound */
-	card->qdio.out_qs =
-		kmalloc(card->qdio.no_out_queues *
-			sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
-	if (!card->qdio.out_qs)
-		goto out_freepool;
-	for (i = 0; i < card->qdio.no_out_queues; ++i) {
-		card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
-					       GFP_KERNEL|GFP_DMA);
-		if (!card->qdio.out_qs[i])
-			goto out_freeoutq;
-		QETH_DBF_TEXT_(setup, 2, "outq %i", i);
-		QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *));
-		memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
-		card->qdio.out_qs[i]->queue_no = i;
-		/* give outbound qeth_qdio_buffers their qdio_buffers */
-		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
-			card->qdio.out_qs[i]->bufs[j].buffer =
-				&card->qdio.out_qs[i]->qdio_bufs[j];
-			skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
-					    skb_list);
-			lockdep_set_class(
-				&card->qdio.out_qs[i]->bufs[j].skb_list.lock,
-				&qdio_out_skb_queue_key);
-			INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
-		}
-	}
-	return 0;
-
-out_freeoutq:
-	while (i > 0)
-		kfree(card->qdio.out_qs[--i]);
-	kfree(card->qdio.out_qs);
-	card->qdio.out_qs = NULL;
-out_freepool:
-	qeth_free_buffer_pool(card);
-out_freeinq:
-	kfree(card->qdio.in_q);
-	card->qdio.in_q = NULL;
-out_nomem:
-	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
-	return -ENOMEM;
-}
-
-static void
-qeth_free_qdio_buffers(struct qeth_card *card)
-{
-	int i, j;
-
-	QETH_DBF_TEXT(trace, 2, "freeqdbf");
-	if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
-		QETH_QDIO_UNINITIALIZED)
-		return;
-	kfree(card->qdio.in_q);
-	card->qdio.in_q = NULL;
-	/* inbound buffer pool */
-	qeth_free_buffer_pool(card);
-	/* free outbound qdio_qs */
-	if (card->qdio.out_qs) {
-		for (i = 0; i < card->qdio.no_out_queues; ++i) {
-			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
-				qeth_clear_output_buffer(card->qdio.out_qs[i],
-						&card->qdio.out_qs[i]->bufs[j]);
-			kfree(card->qdio.out_qs[i]);
-		}
-		kfree(card->qdio.out_qs);
-		card->qdio.out_qs = NULL;
-	}
-}
-
-static void
-qeth_clear_qdio_buffers(struct qeth_card *card)
-{
-	int i, j;
-
-	QETH_DBF_TEXT(trace, 2, "clearqdbf");
-	/* clear outbound buffers to free skbs */
-	for (i = 0; i < card->qdio.no_out_queues; ++i)
-		if (card->qdio.out_qs && card->qdio.out_qs[i]) {
-			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
-				qeth_clear_output_buffer(card->qdio.out_qs[i],
-						&card->qdio.out_qs[i]->bufs[j]);
-		}
-}
-
-static void
-qeth_init_qdio_info(struct qeth_card *card)
-{
-	QETH_DBF_TEXT(setup, 4, "intqdinf");
-	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
-	/* inbound */
-	card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
-	card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
-	card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
-	INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
-	INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
-}
-
-static int
-qeth_init_qdio_queues(struct qeth_card *card)
-{
-	int i, j;
-	int rc;
-
-	QETH_DBF_TEXT(setup, 2, "initqdqs");
-
-	/* inbound queue */
-	memset(card->qdio.in_q->qdio_bufs, 0,
-	       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
-	qeth_initialize_working_pool_list(card);
-	/*give only as many buffers to hardware as we have buffer pool entries*/
-	for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
-		qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
-	card->qdio.in_q->next_buf_to_init = card->qdio.in_buf_pool.buf_count - 1;
-	rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
-		     card->qdio.in_buf_pool.buf_count - 1, NULL);
-	if (rc) {
-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-		return rc;
-	}
-	rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
-	if (rc) {
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		return rc;
-	}
-	/* outbound queue */
-	for (i = 0; i < card->qdio.no_out_queues; ++i){
-		memset(card->qdio.out_qs[i]->qdio_bufs, 0,
-		       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
-		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
-			qeth_clear_output_buffer(card->qdio.out_qs[i],
-					&card->qdio.out_qs[i]->bufs[j]);
-		}
-		card->qdio.out_qs[i]->card = card;
-		card->qdio.out_qs[i]->next_buf_to_fill = 0;
-		card->qdio.out_qs[i]->do_pack = 0;
-		atomic_set(&card->qdio.out_qs[i]->used_buffers,0);
-		atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
-		atomic_set(&card->qdio.out_qs[i]->state,
-			   QETH_OUT_Q_UNLOCKED);
-	}
-	return 0;
-}
-
-static int
-qeth_qdio_establish(struct qeth_card *card)
-{
-	struct qdio_initialize init_data;
-	char *qib_param_field;
-	struct qdio_buffer **in_sbal_ptrs;
-	struct qdio_buffer **out_sbal_ptrs;
-	int i, j, k;
-	int rc = 0;
-
-	QETH_DBF_TEXT(setup, 2, "qdioest");
-
-	qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
-			      GFP_KERNEL);
- 	if (!qib_param_field)
-		return -ENOMEM;
-
-	qeth_create_qib_param_field(card, qib_param_field);
-	qeth_create_qib_param_field_blkt(card, qib_param_field);
-
-	in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
-			       GFP_KERNEL);
-	if (!in_sbal_ptrs) {
-		kfree(qib_param_field);
-		return -ENOMEM;
-	}
-	for(i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
-		in_sbal_ptrs[i] = (struct qdio_buffer *)
-			virt_to_phys(card->qdio.in_q->bufs[i].buffer);
-
-	out_sbal_ptrs =
-		kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
-			sizeof(void *), GFP_KERNEL);
-	if (!out_sbal_ptrs) {
-		kfree(in_sbal_ptrs);
-		kfree(qib_param_field);
-		return -ENOMEM;
-	}
-	for(i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
-		for(j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k){
-			out_sbal_ptrs[k] = (struct qdio_buffer *)
-				virt_to_phys(card->qdio.out_qs[i]->
-					     bufs[j].buffer);
-		}
-
-	memset(&init_data, 0, sizeof(struct qdio_initialize));
-	init_data.cdev                   = CARD_DDEV(card);
-	init_data.q_format               = qeth_get_qdio_q_format(card);
-	init_data.qib_param_field_format = 0;
-	init_data.qib_param_field        = qib_param_field;
-	init_data.min_input_threshold    = QETH_MIN_INPUT_THRESHOLD;
-	init_data.max_input_threshold    = QETH_MAX_INPUT_THRESHOLD;
-	init_data.min_output_threshold   = QETH_MIN_OUTPUT_THRESHOLD;
-	init_data.max_output_threshold   = QETH_MAX_OUTPUT_THRESHOLD;
-	init_data.no_input_qs            = 1;
-	init_data.no_output_qs           = card->qdio.no_out_queues;
-	init_data.input_handler          = (qdio_handler_t *)
-					   qeth_qdio_input_handler;
-	init_data.output_handler         = (qdio_handler_t *)
-					   qeth_qdio_output_handler;
-	init_data.int_parm               = (unsigned long) card;
-	init_data.flags                  = QDIO_INBOUND_0COPY_SBALS |
-					   QDIO_OUTBOUND_0COPY_SBALS |
-					   QDIO_USE_OUTBOUND_PCIS;
-	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
-	init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
-
-	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
-		QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED)
-		if ((rc = qdio_initialize(&init_data)))
-			atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
-
-	kfree(out_sbal_ptrs);
-	kfree(in_sbal_ptrs);
-	kfree(qib_param_field);
-	return rc;
-}
-
-static int
-qeth_qdio_activate(struct qeth_card *card)
-{
-	QETH_DBF_TEXT(setup,3,"qdioact");
-	return qdio_activate(CARD_DDEV(card), 0);
-}
-
-static int
-qeth_clear_channel(struct qeth_channel *channel)
-{
-	unsigned long flags;
-	struct qeth_card *card;
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"clearch");
-	card = CARD_FROM_CDEV(channel->ccwdev);
-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
-
-	if (rc)
-		return rc;
-	rc = wait_event_interruptible_timeout(card->wait_q,
-			channel->state==CH_STATE_STOPPED, QETH_TIMEOUT);
-	if (rc == -ERESTARTSYS)
-		return rc;
-	if (channel->state != CH_STATE_STOPPED)
-		return -ETIME;
-	channel->state = CH_STATE_DOWN;
-	return 0;
-}
-
-static int
-qeth_halt_channel(struct qeth_channel *channel)
-{
-	unsigned long flags;
-	struct qeth_card *card;
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"haltch");
-	card = CARD_FROM_CDEV(channel->ccwdev);
-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
-
-	if (rc)
-		return rc;
-	rc = wait_event_interruptible_timeout(card->wait_q,
-			channel->state==CH_STATE_HALTED, QETH_TIMEOUT);
-	if (rc == -ERESTARTSYS)
-		return rc;
-	if (channel->state != CH_STATE_HALTED)
-		return -ETIME;
-	return 0;
-}
-
-static int
-qeth_halt_channels(struct qeth_card *card)
-{
-	int rc1 = 0, rc2=0, rc3 = 0;
-
-	QETH_DBF_TEXT(trace,3,"haltchs");
-	rc1 = qeth_halt_channel(&card->read);
-	rc2 = qeth_halt_channel(&card->write);
-	rc3 = qeth_halt_channel(&card->data);
-	if (rc1)
-		return rc1;
-	if (rc2)
-		return rc2;
-	return rc3;
-}
-static int
-qeth_clear_channels(struct qeth_card *card)
-{
-	int rc1 = 0, rc2=0, rc3 = 0;
-
-	QETH_DBF_TEXT(trace,3,"clearchs");
-	rc1 = qeth_clear_channel(&card->read);
-	rc2 = qeth_clear_channel(&card->write);
-	rc3 = qeth_clear_channel(&card->data);
-	if (rc1)
-		return rc1;
-	if (rc2)
-		return rc2;
-	return rc3;
-}
-
-static int
-qeth_clear_halt_card(struct qeth_card *card, int halt)
-{
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace,3,"clhacrd");
-	QETH_DBF_HEX(trace, 3, &card, sizeof(void *));
-
-	if (halt)
-		rc = qeth_halt_channels(card);
-	if (rc)
-		return rc;
-	return qeth_clear_channels(card);
-}
-
-static int
-qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
-{
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace,3,"qdioclr");
-	switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED,
-		QETH_QDIO_CLEANING)) {
-	case QETH_QDIO_ESTABLISHED:
-		if ((rc = qdio_cleanup(CARD_DDEV(card),
-				(card->info.type == QETH_CARD_TYPE_IQD) ?
-				QDIO_FLAG_CLEANUP_USING_HALT :
-				QDIO_FLAG_CLEANUP_USING_CLEAR)))
-			QETH_DBF_TEXT_(trace, 3, "1err%d", rc);
-		atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
-		break;
-	case QETH_QDIO_CLEANING:
-		return rc;
-	default:
-		break;
-	}
-	if ((rc = qeth_clear_halt_card(card, use_halt)))
-		QETH_DBF_TEXT_(trace, 3, "2err%d", rc);
-	card->state = CARD_STATE_DOWN;
-	return rc;
-}
-
-static int
-qeth_dm_act(struct qeth_card *card)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(setup,2,"dmact");
-
-	iob = qeth_wait_for_buffer(&card->write);
-	memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
-
-	memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
-	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
-	memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-	rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
-	return rc;
-}
-
-static int
-qeth_mpc_initialize(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(setup,2,"mpcinit");
-
-	if ((rc = qeth_issue_next_read(card))){
-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-		return rc;
-	}
-	if ((rc = qeth_cm_enable(card))){
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		goto out_qdio;
-	}
-	if ((rc = qeth_cm_setup(card))){
-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-		goto out_qdio;
-	}
-	if ((rc = qeth_ulp_enable(card))){
-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
-		goto out_qdio;
-	}
-	if ((rc = qeth_ulp_setup(card))){
-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-		goto out_qdio;
-	}
-	if ((rc = qeth_alloc_qdio_buffers(card))){
-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-		goto out_qdio;
-	}
-	if ((rc = qeth_qdio_establish(card))){
-		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
-		qeth_free_qdio_buffers(card);
-		goto out_qdio;
-	}
- 	if ((rc = qeth_qdio_activate(card))){
-		QETH_DBF_TEXT_(setup, 2, "7err%d", rc);
-		goto out_qdio;
-	}
-	if ((rc = qeth_dm_act(card))){
-		QETH_DBF_TEXT_(setup, 2, "8err%d", rc);
-		goto out_qdio;
-	}
-
-	return 0;
-out_qdio:
-	qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
-	return rc;
-}
-
-static struct net_device *
-qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
-{
-	struct net_device *dev = NULL;
-
-	switch (type) {
-	case QETH_CARD_TYPE_OSAE:
-		switch (linktype) {
-		case QETH_LINK_TYPE_LANE_TR:
-		case QETH_LINK_TYPE_HSTR:
-#ifdef CONFIG_TR
-			dev = alloc_trdev(0);
-#endif /* CONFIG_TR */
-			break;
-		default:
-			dev = alloc_etherdev(0);
-		}
-		break;
-	case QETH_CARD_TYPE_IQD:
-		dev = alloc_netdev(0, "hsi%d", ether_setup);
-		break;
-	case QETH_CARD_TYPE_OSN:
-		dev = alloc_netdev(0, "osn%d", ether_setup);
-		break;
-	default:
-		dev = alloc_etherdev(0);
-	}
-	return dev;
-}
-
-/*hard_header fake function; used in case fake_ll is set */
-static int
-qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
-		 unsigned short type, const void *daddr, const void *saddr,
-		 unsigned len)
-{
-	if(dev->type == ARPHRD_IEEE802_TR){
-		struct trh_hdr *hdr;
-        	hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR);
-		memcpy(hdr->saddr, dev->dev_addr, TR_ALEN);
-        	memcpy(hdr->daddr, "FAKELL", TR_ALEN);
-		return QETH_FAKE_LL_LEN_TR;
-
-	} else {
-		struct ethhdr *hdr;
-        	hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH);
-		memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
-        	memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
-        	if (type != ETH_P_802_3)
-                	hdr->h_proto = htons(type);
-        	else
-                	hdr->h_proto = htons(len);
-		return QETH_FAKE_LL_LEN_ETH;
-
-	}
-}
-
-static const struct header_ops qeth_fake_ops = {
-	.create	= qeth_fake_header,
-	.parse  = qeth_hard_header_parse,
-};
-
-static int
-qeth_send_packet(struct qeth_card *, struct sk_buff *);
-
-static int
-qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	int rc;
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(trace, 6, "hrdstxmi");
-	card = (struct qeth_card *)dev->priv;
-	if (skb==NULL) {
-		card->stats.tx_dropped++;
-		card->stats.tx_errors++;
-		/* return OK; otherwise ksoftirqd goes to 100% */
-		return NETDEV_TX_OK;
-	}
-	if ((card->state != CARD_STATE_UP) || !card->lan_online) {
-		card->stats.tx_dropped++;
-		card->stats.tx_errors++;
-		card->stats.tx_carrier_errors++;
-		dev_kfree_skb_any(skb);
-		/* return OK; otherwise ksoftirqd goes to 100% */
-		return NETDEV_TX_OK;
-	}
-	if (card->options.performance_stats) {
-		card->perf_stats.outbound_cnt++;
-		card->perf_stats.outbound_start_time = qeth_get_micros();
-	}
-	netif_stop_queue(dev);
-	if ((rc = qeth_send_packet(card, skb))) {
-		if (rc == -EBUSY) {
-			return NETDEV_TX_BUSY;
-		} else {
-			card->stats.tx_errors++;
-			card->stats.tx_dropped++;
-			dev_kfree_skb_any(skb);
-			/*set to OK; otherwise ksoftirqd goes to 100% */
-			rc = NETDEV_TX_OK;
-		}
-	}
-	netif_wake_queue(dev);
-	if (card->options.performance_stats)
-		card->perf_stats.outbound_time += qeth_get_micros() -
-			card->perf_stats.outbound_start_time;
-	return rc;
-}
-
-static int
-qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card)
-{
-	int rc = 0;
-#ifdef CONFIG_QETH_VLAN
-	struct vlan_group *vg;
-	int i;
-
-	if (!(vg = card->vlangrp))
-		return rc;
-
-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++){
-		if (vlan_group_get_device(vg, i) == dev){
-			rc = QETH_VLAN_CARD;
-			break;
-		}
-	}
-	if (rc && !(vlan_dev_info(dev)->real_dev->priv == (void *)card))
-		return 0;
-
-#endif
-	return rc;
-}
-
-static int
-qeth_verify_dev(struct net_device *dev)
-{
-	struct qeth_card *card;
-	unsigned long flags;
-	int rc = 0;
-
-	read_lock_irqsave(&qeth_card_list.rwlock, flags);
-	list_for_each_entry(card, &qeth_card_list.list, list){
-		if (card->dev == dev){
-			rc = QETH_REAL_CARD;
-			break;
-		}
-		rc = qeth_verify_vlan_dev(dev, card);
-		if (rc)
-			break;
-	}
-	read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
-
-	return rc;
-}
-
-static struct qeth_card *
-qeth_get_card_from_dev(struct net_device *dev)
-{
-	struct qeth_card *card = NULL;
-	int rc;
-
-	rc = qeth_verify_dev(dev);
-	if (rc == QETH_REAL_CARD)
-		card = (struct qeth_card *)dev->priv;
-	else if (rc == QETH_VLAN_CARD)
-		card = (struct qeth_card *)
-			vlan_dev_info(dev)->real_dev->priv;
-
-	QETH_DBF_TEXT_(trace, 4, "%d", rc);
-	return card ;
-}
-
-static void
-qeth_tx_timeout(struct net_device *dev)
-{
-	struct qeth_card *card;
-
-	card = (struct qeth_card *) dev->priv;
-	card->stats.tx_errors++;
-	qeth_schedule_recovery(card);
-}
-
-static int
-qeth_open(struct net_device *dev)
-{
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(trace, 4, "qethopen");
-
-	card = (struct qeth_card *) dev->priv;
-
-	if (card->state != CARD_STATE_SOFTSETUP)
-		return -ENODEV;
-
-	if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
-	     (card->options.layer2) &&
-	     (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
-		QETH_DBF_TEXT(trace,4,"nomacadr");
-		return -EPERM;
-	}
-	card->data.state = CH_STATE_UP;
-	card->state = CARD_STATE_UP;
-	card->dev->flags |= IFF_UP;
-	netif_start_queue(dev);
-
-	if (!card->lan_online && netif_carrier_ok(dev))
-		netif_carrier_off(dev);
-	return 0;
-}
-
-static int
-qeth_stop(struct net_device *dev)
-{
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(trace, 4, "qethstop");
-
-	card = (struct qeth_card *) dev->priv;
-
-	netif_tx_disable(dev);
-	card->dev->flags &= ~IFF_UP;
-	if (card->state == CARD_STATE_UP)
-		card->state = CARD_STATE_SOFTSETUP;
-	return 0;
-}
-
-static int
-qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
-{
-	int cast_type = RTN_UNSPEC;
-
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		return cast_type;
-
-	if (skb->dst && skb->dst->neighbour){
-		cast_type = skb->dst->neighbour->type;
-		if ((cast_type == RTN_BROADCAST) ||
-		    (cast_type == RTN_MULTICAST) ||
-		    (cast_type == RTN_ANYCAST))
-			return cast_type;
-		else
-			return RTN_UNSPEC;
-	}
-	/* try something else */
-	if (skb->protocol == ETH_P_IPV6)
-		return (skb_network_header(skb)[24] == 0xff) ?
-				RTN_MULTICAST : 0;
-	else if (skb->protocol == ETH_P_IP)
-		return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
-				RTN_MULTICAST : 0;
-	/* ... */
-	if (!memcmp(skb->data, skb->dev->broadcast, 6))
-		return RTN_BROADCAST;
-	else {
-		u16 hdr_mac;
-
-	        hdr_mac = *((u16 *)skb->data);
-	        /* tr multicast? */
-	        switch (card->info.link_type) {
-	        case QETH_LINK_TYPE_HSTR:
-	        case QETH_LINK_TYPE_LANE_TR:
-	        	if ((hdr_mac == QETH_TR_MAC_NC) ||
-			    (hdr_mac == QETH_TR_MAC_C))
-				return RTN_MULTICAST;
-			break;
-	        /* eth or so multicast? */
-                default:
-                      	if ((hdr_mac == QETH_ETH_MAC_V4) ||
-			    (hdr_mac == QETH_ETH_MAC_V6))
-			        return RTN_MULTICAST;
-	        }
-        }
-	return cast_type;
-}
-
-static int
-qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
-		        int ipv, int cast_type)
-{
-	if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
-		return card->qdio.default_out_queue;
-	switch (card->qdio.no_out_queues) {
-	case 4:
-		if (cast_type && card->info.is_multicast_different)
-			return card->info.is_multicast_different &
-				(card->qdio.no_out_queues - 1);
-		if (card->qdio.do_prio_queueing && (ipv == 4)) {
-			const u8 tos = ip_hdr(skb)->tos;
-
-			if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_TOS){
-				if (tos & IP_TOS_NOTIMPORTANT)
-					return 3;
-				if (tos & IP_TOS_HIGHRELIABILITY)
-					return 2;
-				if (tos & IP_TOS_HIGHTHROUGHPUT)
-					return 1;
-				if (tos & IP_TOS_LOWDELAY)
-					return 0;
-			}
-			if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_PREC)
-				return 3 - (tos >> 6);
-		} else if (card->qdio.do_prio_queueing && (ipv == 6)) {
-			/* TODO: IPv6!!! */
-		}
-		return card->qdio.default_out_queue;
-	case 1: /* fallthrough for single-out-queue 1920-device */
-	default:
-		return card->qdio.default_out_queue;
-	}
-}
-
-static inline int
-qeth_get_ip_version(struct sk_buff *skb)
-{
-	switch (skb->protocol) {
-	case ETH_P_IPV6:
-		return 6;
-	case ETH_P_IP:
-		return 4;
-	default:
-		return 0;
-	}
-}
-
-static struct qeth_hdr *
-__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
-{
-#ifdef CONFIG_QETH_VLAN
-	u16 *tag;
-	if (card->vlangrp && vlan_tx_tag_present(skb) &&
-	    ((ipv == 6) || card->options.layer2) ) {
-		/*
-		 * Move the mac addresses (6 bytes src, 6 bytes dest)
-		 * to the beginning of the new header.  We are using three
-		 * memcpys instead of one memmove to save cycles.
-		 */
-		skb_push(skb, VLAN_HLEN);
-		skb_copy_to_linear_data(skb, skb->data + 4, 4);
-		skb_copy_to_linear_data_offset(skb, 4, skb->data + 8, 4);
-		skb_copy_to_linear_data_offset(skb, 8, skb->data + 12, 4);
-		tag = (u16 *)(skb->data + 12);
-		/*
-		 * first two bytes  = ETH_P_8021Q (0x8100)
-		 * second two bytes = VLANID
-		 */
-		*tag = __constant_htons(ETH_P_8021Q);
-		*(tag + 1) = htons(vlan_tx_tag_get(skb));
-	}
-#endif
-	return ((struct qeth_hdr *)
-		qeth_push_skb(card, skb, sizeof(struct qeth_hdr)));
-}
-
-static void
-__qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
-{
-	if (orig_skb != new_skb)
-		dev_kfree_skb_any(new_skb);
-}
-
-static struct sk_buff *
-qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
-		 struct qeth_hdr **hdr, int ipv)
-{
-	struct sk_buff *new_skb, *new_skb2;
-	
-	QETH_DBF_TEXT(trace, 6, "prepskb");
-	new_skb = skb;
-	new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
-	if (!new_skb)
-		return NULL;
-	new_skb2 = qeth_realloc_headroom(card, new_skb,
-					 sizeof(struct qeth_hdr));
-	if (!new_skb2) {
-		__qeth_free_new_skb(skb, new_skb);
-		return NULL;
-	}
-	if (new_skb != skb)
-		__qeth_free_new_skb(new_skb2, new_skb);
-	new_skb = new_skb2;
-	*hdr = __qeth_prepare_skb(card, new_skb, ipv);
-	if (*hdr == NULL) {
-		__qeth_free_new_skb(skb, new_skb);
-		return NULL;
-	}
-	return new_skb;
-}
-
-static inline u8
-qeth_get_qeth_hdr_flags4(int cast_type)
-{
-	if (cast_type == RTN_MULTICAST)
-		return QETH_CAST_MULTICAST;
-	if (cast_type == RTN_BROADCAST)
-		return QETH_CAST_BROADCAST;
-	return QETH_CAST_UNICAST;
-}
-
-static inline u8
-qeth_get_qeth_hdr_flags6(int cast_type)
-{
-	u8 ct = QETH_HDR_PASSTHRU | QETH_HDR_IPV6;
-	if (cast_type == RTN_MULTICAST)
-		return ct | QETH_CAST_MULTICAST;
-	if (cast_type == RTN_ANYCAST)
-		return ct | QETH_CAST_ANYCAST;
-	if (cast_type == RTN_BROADCAST)
-		return ct | QETH_CAST_BROADCAST;
-	return ct | QETH_CAST_UNICAST;
-}
-
-static void
-qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
-			    struct sk_buff *skb)
-{
-	__u16 hdr_mac;
-
-	if (!memcmp(skb->data+QETH_HEADER_SIZE,
-		    skb->dev->broadcast,6)) { /* broadcast? */
-		*(__u32 *)hdr->hdr.l2.flags |=
-			 QETH_LAYER2_FLAG_BROADCAST << 8;
-		return;
-	}
-	hdr_mac=*((__u16*)skb->data);
-	/* tr multicast? */
-	switch (card->info.link_type) {
-	case QETH_LINK_TYPE_HSTR:
-	case QETH_LINK_TYPE_LANE_TR:
-		if ((hdr_mac == QETH_TR_MAC_NC) ||
-		    (hdr_mac == QETH_TR_MAC_C) )
-			*(__u32 *)hdr->hdr.l2.flags |=
-				QETH_LAYER2_FLAG_MULTICAST << 8;
-		else
-			*(__u32 *)hdr->hdr.l2.flags |=
-				QETH_LAYER2_FLAG_UNICAST << 8;
-		break;
-		/* eth or so multicast? */
-	default:
-		if ( (hdr_mac==QETH_ETH_MAC_V4) ||
-		     (hdr_mac==QETH_ETH_MAC_V6) )
-			*(__u32 *)hdr->hdr.l2.flags |=
-				QETH_LAYER2_FLAG_MULTICAST << 8;
-		else
-			*(__u32 *)hdr->hdr.l2.flags |=
-				QETH_LAYER2_FLAG_UNICAST << 8;
-	}
-}
-
-static void
-qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
-			struct sk_buff *skb, int cast_type)
-{
-	memset(hdr, 0, sizeof(struct qeth_hdr));
-	hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
-
-	/* set byte 0 to "0x02" and byte 3 to casting flags */
-	if (cast_type==RTN_MULTICAST)
-		*(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_MULTICAST << 8;
-	else if (cast_type==RTN_BROADCAST)
-		*(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_BROADCAST << 8;
-	 else
-		qeth_layer2_get_packet_type(card, hdr, skb);
-
-	hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
-#ifdef CONFIG_QETH_VLAN
-	/* VSWITCH relies on the VLAN
-	 * information to be present in
-	 * the QDIO header */
-	if ((card->vlangrp != NULL) &&
-	    vlan_tx_tag_present(skb)) {
-		*(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_VLAN << 8;
-		hdr->hdr.l2.vlan_id = vlan_tx_tag_get(skb);
-	}
-#endif
-}
-
-void
-qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
-		struct sk_buff *skb, int ipv, int cast_type)
-{
-	QETH_DBF_TEXT(trace, 6, "fillhdr");
-
-	memset(hdr, 0, sizeof(struct qeth_hdr));
-	if (card->options.layer2) {
-		qeth_layer2_fill_header(card, hdr, skb, cast_type);
-		return;
-	}
-	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
-	hdr->hdr.l3.ext_flags = 0;
-#ifdef CONFIG_QETH_VLAN
-	/*
-	 * before we're going to overwrite this location with next hop ip.
-	 * v6 uses passthrough, v4 sets the tag in the QDIO header.
-	 */
-	if (card->vlangrp && vlan_tx_tag_present(skb)) {
-		hdr->hdr.l3.ext_flags = (ipv == 4) ?
-			QETH_HDR_EXT_VLAN_FRAME :
-			QETH_HDR_EXT_INCLUDE_VLAN_TAG;
-		hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
-	}
-#endif /* CONFIG_QETH_VLAN */
-	hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
-	if (ipv == 4) {	 /* IPv4 */
-		hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags4(cast_type);
-		memset(hdr->hdr.l3.dest_addr, 0, 12);
-		if ((skb->dst) && (skb->dst->neighbour)) {
-			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
-			    *((u32 *) skb->dst->neighbour->primary_key);
-		} else {
-			/* fill in destination address used in ip header */
-			*((u32 *)(&hdr->hdr.l3.dest_addr[12])) =
-							   ip_hdr(skb)->daddr;
-		}
-	} else if (ipv == 6) { /* IPv6 or passthru */
-		hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags6(cast_type);
-		if ((skb->dst) && (skb->dst->neighbour)) {
-			memcpy(hdr->hdr.l3.dest_addr,
-			       skb->dst->neighbour->primary_key, 16);
-		} else {
-			/* fill in destination address used in ip header */
-			memcpy(hdr->hdr.l3.dest_addr,
-			       &ipv6_hdr(skb)->daddr, 16);
-		}
-	} else { /* passthrough */
-                if((skb->dev->type == ARPHRD_IEEE802_TR) &&
-		    !memcmp(skb->data + sizeof(struct qeth_hdr) +
-		    sizeof(__u16), skb->dev->broadcast, 6)) {
-			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
-						QETH_HDR_PASSTHRU;
-		} else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
-			    skb->dev->broadcast, 6)) {   /* broadcast? */
-			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
-						QETH_HDR_PASSTHRU;
-		} else {
- 			hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
- 				QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
- 				QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
-		}
-	}
-}
-
-static void
-__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
-		   int is_tso, int *next_element_to_fill)
-{
-	int length = skb->len;
-	int length_here;
-	int element;
-	char *data;
-	int first_lap ;
-
-	element = *next_element_to_fill;
-	data = skb->data;
-	first_lap = (is_tso == 0 ? 1 : 0);
-
-	while (length > 0) {
-		/* length_here is the remaining amount of data in this page */
-		length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
-		if (length < length_here)
-			length_here = length;
-
-		buffer->element[element].addr = data;
-		buffer->element[element].length = length_here;
-		length -= length_here;
-		if (!length) {
-			if (first_lap)
-				buffer->element[element].flags = 0;
-			else
-				buffer->element[element].flags =
-				    SBAL_FLAGS_LAST_FRAG;
-		} else {
-			if (first_lap)
-				buffer->element[element].flags =
-				    SBAL_FLAGS_FIRST_FRAG;
-			else
-				buffer->element[element].flags =
-				    SBAL_FLAGS_MIDDLE_FRAG;
-		}
-		data += length_here;
-		element++;
-		first_lap = 0;
-	}
-	*next_element_to_fill = element;
-}
-
-static int
-qeth_fill_buffer(struct qeth_qdio_out_q *queue,
-		 struct qeth_qdio_out_buffer *buf,
-		 struct sk_buff *skb)
-{
-	struct qdio_buffer *buffer;
-	struct qeth_hdr_tso *hdr;
-	int flush_cnt = 0, hdr_len, large_send = 0;
-
-	QETH_DBF_TEXT(trace, 6, "qdfillbf");
-
-	buffer = buf->buffer;
-	atomic_inc(&skb->users);
-	skb_queue_tail(&buf->skb_list, skb);
-
-	hdr  = (struct qeth_hdr_tso *) skb->data;
-	/*check first on TSO ....*/
-	if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
-		int element = buf->next_element_to_fill;
-
-		hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
-		/*fill first buffer entry only with header information */
-		buffer->element[element].addr = skb->data;
-		buffer->element[element].length = hdr_len;
-		buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
-		buf->next_element_to_fill++;
-		skb->data += hdr_len;
-		skb->len  -= hdr_len;
-		large_send = 1;
-	}
-	if (skb_shinfo(skb)->nr_frags == 0)
-		__qeth_fill_buffer(skb, buffer, large_send,
-				   (int *)&buf->next_element_to_fill);
-	else
-		__qeth_fill_buffer_frag(skb, buffer, large_send,
-					(int *)&buf->next_element_to_fill);
-
-	if (!queue->do_pack) {
-		QETH_DBF_TEXT(trace, 6, "fillbfnp");
-		/* set state to PRIMED -> will be flushed */
-		atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
-		flush_cnt = 1;
-	} else {
-		QETH_DBF_TEXT(trace, 6, "fillbfpa");
-		if (queue->card->options.performance_stats)
-			queue->card->perf_stats.skbs_sent_pack++;
-		if (buf->next_element_to_fill >=
-				QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
-			/*
-			 * packed buffer if full -> set state PRIMED
-			 * -> will be flushed
-			 */
-			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
-			flush_cnt = 1;
-		}
-	}
-	return flush_cnt;
-}
-
-static int
-qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
-			 struct sk_buff *skb, struct qeth_hdr *hdr,
-			 int elements_needed,
-			 struct qeth_eddp_context *ctx)
-{
-	struct qeth_qdio_out_buffer *buffer;
-	int buffers_needed = 0;
-	int flush_cnt = 0;
-	int index;
-
-	QETH_DBF_TEXT(trace, 6, "dosndpfa");
-
-	/* spin until we get the queue ... */
-	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
-			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
-	/* ... now we've got the queue */
-	index = queue->next_buf_to_fill;
-	buffer = &queue->bufs[queue->next_buf_to_fill];
-	/*
-	 * check if buffer is empty to make sure that we do not 'overtake'
-	 * ourselves and try to fill a buffer that is already primed
-	 */
-	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) 
-		goto out;
-	if (ctx == NULL)
-		queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
-					  QDIO_MAX_BUFFERS_PER_Q;
-	else {
-		buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx);
-		if (buffers_needed < 0) 
-			goto out;
-		queue->next_buf_to_fill =
-			(queue->next_buf_to_fill + buffers_needed) %
-			QDIO_MAX_BUFFERS_PER_Q;
-	}
-	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
-	if (ctx == NULL) {
-		qeth_fill_buffer(queue, buffer, skb);
-		qeth_flush_buffers(queue, 0, index, 1);
-	} else {
-		flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
-		WARN_ON(buffers_needed != flush_cnt);
-		qeth_flush_buffers(queue, 0, index, flush_cnt);
-	}
-	return 0;
-out:
-	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
-	return -EBUSY;
-}
-
-static int
-qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
-		    struct sk_buff *skb, struct qeth_hdr *hdr,
-		    int elements_needed, struct qeth_eddp_context *ctx)
-{
-	struct qeth_qdio_out_buffer *buffer;
-	int start_index;
-	int flush_count = 0;
-	int do_pack = 0;
-	int tmp;
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace, 6, "dosndpkt");
-
-	/* spin until we get the queue ... */
-	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
-			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
-	start_index = queue->next_buf_to_fill;
-	buffer = &queue->bufs[queue->next_buf_to_fill];
-	/*
-	 * check if buffer is empty to make sure that we do not 'overtake'
-	 * ourselves and try to fill a buffer that is already primed
-	 */
-	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
-		atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
-		return -EBUSY;
-	}
-	/* check if we need to switch packing state of this queue */
-	qeth_switch_to_packing_if_needed(queue);
-	if (queue->do_pack){
-		do_pack = 1;
-		if (ctx == NULL) {
-			/* does packet fit in current buffer? */
-			if((QETH_MAX_BUFFER_ELEMENTS(card) -
-			    buffer->next_element_to_fill) < elements_needed){
-				/* ... no -> set state PRIMED */
-				atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
-				flush_count++;
-				queue->next_buf_to_fill =
-					(queue->next_buf_to_fill + 1) %
-					QDIO_MAX_BUFFERS_PER_Q;
-				buffer = &queue->bufs[queue->next_buf_to_fill];
-				/* we did a step forward, so check buffer state
-				 * again */
-				if (atomic_read(&buffer->state) !=
-						QETH_QDIO_BUF_EMPTY){
-					qeth_flush_buffers(queue, 0, start_index, flush_count);
-					atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
-					return -EBUSY;
-				}
-			}
-		} else {
-			/* check if we have enough elements (including following
-			 * free buffers) to handle eddp context */
-			if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){
-				if (net_ratelimit())
-					PRINT_WARN("eddp tx_dropped 1\n");
-				rc = -EBUSY;
-				goto out;
-			}
-		}
-	}
-	if (ctx == NULL)
-		tmp = qeth_fill_buffer(queue, buffer, skb);
-	else {
-		tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill);
-		if (tmp < 0) {
-			printk("eddp tx_dropped 2\n");
-			rc = - EBUSY;
-			goto out;
-		}
-	}
-	queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
-				  QDIO_MAX_BUFFERS_PER_Q;
-	flush_count += tmp;
-out:
-	if (flush_count)
-		qeth_flush_buffers(queue, 0, start_index, flush_count);
-	else if (!atomic_read(&queue->set_pci_flags_count))
-		atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
-	/*
-	 * queue->state will go from LOCKED -> UNLOCKED or from
-	 * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
-	 * (switch packing state or flush buffer to get another pci flag out).
-	 * In that case we will enter this loop
-	 */
-	while (atomic_dec_return(&queue->state)){
-		flush_count = 0;
-		start_index = queue->next_buf_to_fill;
-		/* check if we can go back to non-packing state */
-		flush_count += qeth_switch_to_nonpacking_if_needed(queue);
-		/*
-		 * check if we need to flush a packing buffer to get a pci
-		 * flag out on the queue
-		 */
-		if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
-			flush_count += qeth_flush_buffers_on_no_pci(queue);
-		if (flush_count)
-			qeth_flush_buffers(queue, 0, start_index, flush_count);
-	}
-	/* at this point the queue is UNLOCKED again */
-	if (queue->card->options.performance_stats && do_pack)
-		queue->card->perf_stats.bufs_sent_pack += flush_count;
-
-	return rc;
-}
-
-static int
-qeth_get_elements_no(struct qeth_card *card, void *hdr,
-		     struct sk_buff *skb, int elems)
-{
-	int elements_needed = 0;
-
-        if (skb_shinfo(skb)->nr_frags > 0) 
-                elements_needed = (skb_shinfo(skb)->nr_frags + 1);
-        if (elements_needed == 0)
-                elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
-                                        + skb->len) >> PAGE_SHIFT);
-	if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
-                PRINT_ERR("Invalid size of IP packet "
-			  "(Number=%d / Length=%d). Discarded.\n",
-                          (elements_needed+elems), skb->len);
-                return 0;
-        }
-        return elements_needed;
-}
-
-static void qeth_tx_csum(struct sk_buff *skb)
-{
-	int tlen;
-
-	if (skb->protocol == htons(ETH_P_IP)) {
-		tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
-		switch (ip_hdr(skb)->protocol) {
-		case IPPROTO_TCP:
-			tcp_hdr(skb)->check = 0;
-			tcp_hdr(skb)->check = csum_tcpudp_magic(
-				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
-				tlen, ip_hdr(skb)->protocol,
-				skb_checksum(skb, skb_transport_offset(skb),
-					tlen, 0));
-			break;
-		case IPPROTO_UDP:
-			udp_hdr(skb)->check = 0;
-			udp_hdr(skb)->check = csum_tcpudp_magic(
-				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
-				tlen, ip_hdr(skb)->protocol,
-				skb_checksum(skb, skb_transport_offset(skb),
-					tlen, 0));
-			break;
-		}
-	} else if (skb->protocol == htons(ETH_P_IPV6)) {
-		switch (ipv6_hdr(skb)->nexthdr) {
-		case IPPROTO_TCP:
-			tcp_hdr(skb)->check = 0;
-			tcp_hdr(skb)->check = csum_ipv6_magic(
-				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
-				ipv6_hdr(skb)->payload_len,
-				ipv6_hdr(skb)->nexthdr,
-				skb_checksum(skb, skb_transport_offset(skb),
-					ipv6_hdr(skb)->payload_len, 0));
-			break;
-		case IPPROTO_UDP:
-			udp_hdr(skb)->check = 0;
-			udp_hdr(skb)->check = csum_ipv6_magic(
-				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
-				ipv6_hdr(skb)->payload_len,
-				ipv6_hdr(skb)->nexthdr,
-				skb_checksum(skb, skb_transport_offset(skb),
-					ipv6_hdr(skb)->payload_len, 0));
-			break;
-		}
-	}
-}
-
-static int
-qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
-{
-	int ipv = 0;
-	int cast_type;
-	struct qeth_qdio_out_q *queue;
-	struct qeth_hdr *hdr = NULL;
-	int elements_needed = 0;
-	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
-	struct qeth_eddp_context *ctx = NULL;
-	int tx_bytes = skb->len;
-	unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
-	unsigned short tso_size = skb_shinfo(skb)->gso_size;
-	struct sk_buff *new_skb, *new_skb2;
-	int rc;
-
-	QETH_DBF_TEXT(trace, 6, "sendpkt");
-
-	new_skb = skb;
-	if ((card->info.type == QETH_CARD_TYPE_OSN) &&
-	    (skb->protocol == htons(ETH_P_IPV6)))
-		return -EPERM;
-	cast_type = qeth_get_cast_type(card, skb);
-	if ((cast_type == RTN_BROADCAST) &&
-	    (card->info.broadcast_capable == 0))
-		return -EPERM;
-	queue = card->qdio.out_qs
-		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
-	if (!card->options.layer2) {
-		ipv = qeth_get_ip_version(skb);
-		if ((card->dev->header_ops == &qeth_fake_ops) && ipv) {
-			new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
-			if (!new_skb)
-				return -ENOMEM;
-			if(card->dev->type == ARPHRD_IEEE802_TR){
-				skb_pull(new_skb, QETH_FAKE_LL_LEN_TR);
-			} else {
-				skb_pull(new_skb, QETH_FAKE_LL_LEN_ETH);
-			}
-		}
-	}
-	if (skb_is_gso(skb))
-		large_send = card->options.large_send;
-	/* check on OSN device*/
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		hdr = (struct qeth_hdr *)new_skb->data;
-	/*are we able to do TSO ? */
-	if ((large_send == QETH_LARGE_SEND_TSO) &&
-	    (cast_type == RTN_UNSPEC)) {
-		rc = qeth_tso_prepare_packet(card, new_skb, ipv, cast_type);
-		if (rc) {
-			__qeth_free_new_skb(skb, new_skb);
-			return rc;
-		}
-		elements_needed++;
-	} else if (card->info.type != QETH_CARD_TYPE_OSN) {
-		new_skb2 = qeth_prepare_skb(card, new_skb, &hdr, ipv);
-		if (!new_skb2) {
-			__qeth_free_new_skb(skb, new_skb);
-			return -EINVAL;
-		}
-		if (new_skb != skb)
-			__qeth_free_new_skb(new_skb2, new_skb);
-		new_skb = new_skb2;
-		qeth_fill_header(card, hdr, new_skb, ipv, cast_type);
-	}
-	if (large_send == QETH_LARGE_SEND_EDDP) {
-		ctx = qeth_eddp_create_context(card, new_skb, hdr,
-					       skb->sk->sk_protocol);
-		if (ctx == NULL) {
-			__qeth_free_new_skb(skb, new_skb);
-			PRINT_WARN("could not create eddp context\n");
-			return -EINVAL;
-		}
-	} else {
-		int elems = qeth_get_elements_no(card,(void*) hdr, new_skb,
-						 elements_needed);
-		if (!elems) {
-			__qeth_free_new_skb(skb, new_skb);
-			return -EINVAL;
-		}
-		elements_needed += elems;
-	}
-
-	if ((large_send == QETH_LARGE_SEND_NO) &&
-	    (skb->ip_summed == CHECKSUM_PARTIAL))
-		qeth_tx_csum(new_skb);
-
-	if (card->info.type != QETH_CARD_TYPE_IQD)
-		rc = qeth_do_send_packet(card, queue, new_skb, hdr,
-					 elements_needed, ctx);
-	else {
-		if ((!card->options.layer2) &&
-		    (ipv == 0)) {
-			__qeth_free_new_skb(skb, new_skb);
-			return -EPERM;
-		}
-		rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
-					      elements_needed, ctx);
-	}
-	if (!rc) {
-		card->stats.tx_packets++;
-		card->stats.tx_bytes += tx_bytes;
-		if (new_skb != skb)
-			dev_kfree_skb_any(skb);
-		if (card->options.performance_stats) {
-			if (tso_size &&
-			    !(large_send == QETH_LARGE_SEND_NO)) {
-				card->perf_stats.large_send_bytes += tx_bytes;
-				card->perf_stats.large_send_cnt++;
-			}
-			if (nr_frags > 0) {
-				card->perf_stats.sg_skbs_sent++;
-				/* nr_frags + skb->data */
-				card->perf_stats.sg_frags_sent +=
-					nr_frags + 1;
-			}
-		}
-	} else {
-		card->stats.tx_dropped++;
-		__qeth_free_new_skb(skb, new_skb);
-	}
-	if (ctx != NULL) {
-		/* drop creator's reference */
-		qeth_eddp_put_context(ctx);
-		/* free skb; it's not referenced by a buffer */
-		if (!rc)
-		       dev_kfree_skb_any(new_skb);
-	}
-	return rc;
-}
-
-static int
-qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
-{
-	struct qeth_card *card = (struct qeth_card *) dev->priv;
-	int rc = 0;
-
-	switch(regnum){
-	case MII_BMCR: /* Basic mode control register */
-		rc = BMCR_FULLDPLX;
-		if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
-		    (card->info.link_type != QETH_LINK_TYPE_OSN) &&
-		    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
-			rc |= BMCR_SPEED100;
-		break;
-	case MII_BMSR: /* Basic mode status register */
-		rc = BMSR_ERCAP | BMSR_ANEGCOMPLETE | BMSR_LSTATUS |
-		     BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL |
-		     BMSR_100BASE4;
-		break;
-	case MII_PHYSID1: /* PHYS ID 1 */
-		rc = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 8) |
-		     dev->dev_addr[2];
-		rc = (rc >> 5) & 0xFFFF;
-		break;
-	case MII_PHYSID2: /* PHYS ID 2 */
-		rc = (dev->dev_addr[2] << 10) & 0xFFFF;
-		break;
-	case MII_ADVERTISE: /* Advertisement control reg */
-		rc = ADVERTISE_ALL;
-		break;
-	case MII_LPA: /* Link partner ability reg */
-		rc = LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL |
-		     LPA_100BASE4 | LPA_LPACK;
-		break;
-	case MII_EXPANSION: /* Expansion register */
-		break;
-	case MII_DCOUNTER: /* disconnect counter */
-		break;
-	case MII_FCSCOUNTER: /* false carrier counter */
-		break;
-	case MII_NWAYTEST: /* N-way auto-neg test register */
-		break;
-	case MII_RERRCOUNTER: /* rx error counter */
-		rc = card->stats.rx_errors;
-		break;
-	case MII_SREVISION: /* silicon revision */
-		break;
-	case MII_RESV1: /* reserved 1 */
-		break;
-	case MII_LBRERROR: /* loopback, rx, bypass error */
-		break;
-	case MII_PHYADDR: /* physical address */
-		break;
-	case MII_RESV2: /* reserved 2 */
-		break;
-	case MII_TPISTATUS: /* TPI status for 10mbps */
-		break;
-	case MII_NCONFIG: /* network interface config */
-		break;
-	default:
-		break;
-	}
-	return rc;
-}
-
-
-static const char *
-qeth_arp_get_error_cause(int *rc)
-{
-	switch (*rc) {
-	case QETH_IPA_ARP_RC_FAILED:
-		*rc = -EIO;
-		return "operation failed";
-	case QETH_IPA_ARP_RC_NOTSUPP:
-		*rc = -EOPNOTSUPP;
-		return "operation not supported";
-	case QETH_IPA_ARP_RC_OUT_OF_RANGE:
-		*rc = -EINVAL;
-		return "argument out of range";
-	case QETH_IPA_ARP_RC_Q_NOTSUPP:
-		*rc = -EOPNOTSUPP;
-		return "query operation not supported";
-	case QETH_IPA_ARP_RC_Q_NO_DATA:
-		*rc = -ENOENT;
-		return "no query data available";
-	default:
-		return "unknown error";
-	}
-}
-
-static int
-qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs,
-			     __u16, long);
-
-static int
-qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
-{
-	int tmp;
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"arpstnoe");
-
-	/*
-	 * currently GuestLAN only supports the ARP assist function
-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
-	 * thus we say EOPNOTSUPP for this ARP function
-	 */
-	if (card->info.guestlan)
-		return -EOPNOTSUPP;
-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
-		PRINT_WARN("ARP processing not supported "
-			   "on %s!\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
-					  IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
-					  no_entries);
-	if (rc) {
-		tmp = rc;
-		PRINT_WARN("Could not set number of ARP entries on %s: "
-			   "%s (0x%x/%d)\n",
-			   QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
-			   tmp, tmp);
-	}
-	return rc;
-}
-
-static void
-qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
-		               struct qeth_arp_query_data *qdata,
-			       int entry_size, int uentry_size)
-{
-	char *entry_ptr;
-	char *uentry_ptr;
-	int i;
-
-	entry_ptr = (char *)&qdata->data;
-	uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset);
-	for (i = 0; i < qdata->no_entries; ++i){
-		/* strip off 32 bytes "media specific information" */
-		memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32);
-		entry_ptr += entry_size;
-		uentry_ptr += uentry_size;
-	}
-}
-
-static int
-qeth_arp_query_cb(struct qeth_card *card, struct qeth_reply *reply,
-		  unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_arp_query_data *qdata;
-	struct qeth_arp_query_info *qinfo;
-	int entry_size;
-	int uentry_size;
-	int i;
-
-	QETH_DBF_TEXT(trace,4,"arpquecb");
-
-	qinfo = (struct qeth_arp_query_info *) reply->param;
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->hdr.return_code) {
-		QETH_DBF_TEXT_(trace,4,"qaer1%i", cmd->hdr.return_code);
-		return 0;
-	}
-	if (cmd->data.setassparms.hdr.return_code) {
-		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
-		QETH_DBF_TEXT_(trace,4,"qaer2%i", cmd->hdr.return_code);
-		return 0;
-	}
-	qdata = &cmd->data.setassparms.data.query_arp;
-	switch(qdata->reply_bits){
-	case 5:
-		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5);
-		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
-			uentry_size = sizeof(struct qeth_arp_qi_entry5_short);
-		break;
-	case 7:
-		/* fall through to default */
-	default:
-		/* tr is the same as eth -> entry7 */
-		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7);
-		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
-			uentry_size = sizeof(struct qeth_arp_qi_entry7_short);
-		break;
-	}
-	/* check if there is enough room in userspace */
-	if ((qinfo->udata_len - qinfo->udata_offset) <
-			qdata->no_entries * uentry_size){
-		QETH_DBF_TEXT_(trace, 4, "qaer3%i", -ENOMEM);
-		cmd->hdr.return_code = -ENOMEM;
-		PRINT_WARN("query ARP user space buffer is too small for "
-			   "the returned number of ARP entries. "
-			   "Aborting query!\n");
-		goto out_error;
-	}
-	QETH_DBF_TEXT_(trace, 4, "anore%i",
-		       cmd->data.setassparms.hdr.number_of_replies);
-	QETH_DBF_TEXT_(trace, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no);
-	QETH_DBF_TEXT_(trace, 4, "anoen%i", qdata->no_entries);
-
-	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) {
-		/* strip off "media specific information" */
-		qeth_copy_arp_entries_stripped(qinfo, qdata, entry_size,
-					       uentry_size);
-	} else
-		/*copy entries to user buffer*/
-		memcpy(qinfo->udata + qinfo->udata_offset,
-		       (char *)&qdata->data, qdata->no_entries*uentry_size);
-
-	qinfo->no_entries += qdata->no_entries;
-	qinfo->udata_offset += (qdata->no_entries*uentry_size);
-	/* check if all replies received ... */
-	if (cmd->data.setassparms.hdr.seq_no <
-	    cmd->data.setassparms.hdr.number_of_replies)
-		return 1;
-	memcpy(qinfo->udata, &qinfo->no_entries, 4);
-	/* keep STRIP_ENTRIES flag so the user program can distinguish
-	 * stripped entries from normal ones */
-	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
-		qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
-	memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET,&qdata->reply_bits,2);
-	return 0;
-out_error:
-	i = 0;
-	memcpy(qinfo->udata, &i, 4);
-	return 0;
-}
-
-static int
-qeth_send_ipa_arp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-		      int len, int (*reply_cb)(struct qeth_card *,
-					       struct qeth_reply *,
-					       unsigned long),
-		      void *reply_param)
-{
-	QETH_DBF_TEXT(trace,4,"sendarp");
-
-	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
-				      reply_cb, reply_param);
-}
-
-static int
-qeth_send_ipa_snmp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-		      int len, int (*reply_cb)(struct qeth_card *,
-					       struct qeth_reply *,
-					       unsigned long),
-		      void *reply_param)
-{
-	u16 s1, s2;
-
-	QETH_DBF_TEXT(trace,4,"sendsnmp");
-
-	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-	/* adjust PDU length fields in IPA_PDU_HEADER */
-	s1 = (u32) IPA_PDU_HEADER_SIZE + len;
-	s2 = (u32) len;
-	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
-	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
-	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
-	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
-	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
-				      reply_cb, reply_param);
-}
-
-static struct qeth_cmd_buffer *
-qeth_get_setassparms_cmd(struct qeth_card *, enum qeth_ipa_funcs,
-			 __u16, __u16, enum qeth_prot_versions);
-static int
-qeth_arp_query(struct qeth_card *card, char __user *udata)
-{
-	struct qeth_cmd_buffer *iob;
-	struct qeth_arp_query_info qinfo = {0, };
-	int tmp;
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"arpquery");
-
-	if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
-			       IPA_ARP_PROCESSING)) {
-		PRINT_WARN("ARP processing not supported "
-			   "on %s!\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-	/* get size of userspace buffer and mask_bits -> 6 bytes */
-	if (copy_from_user(&qinfo, udata, 6))
-		return -EFAULT;
-	if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL)))
-		return -ENOMEM;
-	qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
-	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
-				       IPA_CMD_ASS_ARP_QUERY_INFO,
-				       sizeof(int),QETH_PROT_IPV4);
-
-	rc = qeth_send_ipa_arp_cmd(card, iob,
-				   QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
-				   qeth_arp_query_cb, (void *)&qinfo);
-	if (rc) {
-		tmp = rc;
-		PRINT_WARN("Error while querying ARP cache on %s: %s "
-			   "(0x%x/%d)\n",
-			   QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
-			   tmp, tmp);
-		if (copy_to_user(udata, qinfo.udata, 4))
-			rc = -EFAULT;
-	} else {
-		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
-			rc = -EFAULT;
-	}
-	kfree(qinfo.udata);
-	return rc;
-}
-
-/**
- * SNMP command callback
- */
-static int
-qeth_snmp_command_cb(struct qeth_card *card, struct qeth_reply *reply,
-		     unsigned long sdata)
-{
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_arp_query_info *qinfo;
-	struct qeth_snmp_cmd *snmp;
-	unsigned char *data;
-	__u16 data_len;
-
-	QETH_DBF_TEXT(trace,3,"snpcmdcb");
-
-	cmd = (struct qeth_ipa_cmd *) sdata;
-	data = (unsigned char *)((char *)cmd - reply->offset);
-	qinfo = (struct qeth_arp_query_info *) reply->param;
-	snmp = &cmd->data.setadapterparms.data.snmp;
-
-	if (cmd->hdr.return_code) {
-		QETH_DBF_TEXT_(trace,4,"scer1%i", cmd->hdr.return_code);
-		return 0;
-	}
-	if (cmd->data.setadapterparms.hdr.return_code) {
-		cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
-		QETH_DBF_TEXT_(trace,4,"scer2%i", cmd->hdr.return_code);
-		return 0;
-	}
-	data_len = *((__u16*)QETH_IPA_PDU_LEN_PDU1(data));
-	if (cmd->data.setadapterparms.hdr.seq_no == 1)
-		data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
-	else
-		data_len -= (__u16)((char*)&snmp->request - (char *)cmd);
-
-	/* check if there is enough room in userspace */
-	if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
-		QETH_DBF_TEXT_(trace, 4, "scer3%i", -ENOMEM);
-		cmd->hdr.return_code = -ENOMEM;
-		return 0;
-	}
-	QETH_DBF_TEXT_(trace, 4, "snore%i",
-		       cmd->data.setadapterparms.hdr.used_total);
-	QETH_DBF_TEXT_(trace, 4, "sseqn%i", cmd->data.setadapterparms.hdr.seq_no);
-	/*copy entries to user buffer*/
-	if (cmd->data.setadapterparms.hdr.seq_no == 1) {
-		memcpy(qinfo->udata + qinfo->udata_offset,
-		       (char *)snmp,
-		       data_len + offsetof(struct qeth_snmp_cmd,data));
-		qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
-	} else {
-		memcpy(qinfo->udata + qinfo->udata_offset,
-		       (char *)&snmp->request, data_len);
-	}
-	qinfo->udata_offset += data_len;
-	/* check if all replies received ... */
-		QETH_DBF_TEXT_(trace, 4, "srtot%i",
-			       cmd->data.setadapterparms.hdr.used_total);
-		QETH_DBF_TEXT_(trace, 4, "srseq%i",
-			       cmd->data.setadapterparms.hdr.seq_no);
-	if (cmd->data.setadapterparms.hdr.seq_no <
-	    cmd->data.setadapterparms.hdr.used_total)
-		return 1;
-	return 0;
-}
-
-static struct qeth_cmd_buffer *
-qeth_get_ipacmd_buffer(struct qeth_card *, enum qeth_ipa_cmds,
-		       enum qeth_prot_versions );
-
-static struct qeth_cmd_buffer *
-qeth_get_adapter_cmd(struct qeth_card *card, __u32 command, __u32 cmdlen)
-{
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	iob = qeth_get_ipacmd_buffer(card,IPA_CMD_SETADAPTERPARMS,
-				     QETH_PROT_IPV4);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
-	cmd->data.setadapterparms.hdr.command_code = command;
-	cmd->data.setadapterparms.hdr.used_total = 1;
-	cmd->data.setadapterparms.hdr.seq_no = 1;
-
-	return iob;
-}
-
-/**
- * function to send SNMP commands to OSA-E card
- */
-static int
-qeth_snmp_command(struct qeth_card *card, char __user *udata)
-{
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_snmp_ureq *ureq;
-	int req_len;
-	struct qeth_arp_query_info qinfo = {0, };
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace,3,"snmpcmd");
-
-	if (card->info.guestlan)
-		return -EOPNOTSUPP;
-
-	if ((!qeth_adp_supported(card,IPA_SETADP_SET_SNMP_CONTROL)) &&
-	    (!card->options.layer2) ) {
-		PRINT_WARN("SNMP Query MIBS not supported "
-			   "on %s!\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-	/* skip 4 bytes (data_len struct member) to get req_len */
-	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
-		return -EFAULT;
-	ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
-	if (!ureq) {
-		QETH_DBF_TEXT(trace, 2, "snmpnome");
-		return -ENOMEM;
-	}
-	if (copy_from_user(ureq, udata,
-			req_len+sizeof(struct qeth_snmp_ureq_hdr))){
-		kfree(ureq);
-		return -EFAULT;
-	}
-	qinfo.udata_len = ureq->hdr.data_len;
-	if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))){
-		kfree(ureq);
-		return -ENOMEM;
-	}
-	qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
-
-	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
-				   QETH_SNMP_SETADP_CMDLENGTH + req_len);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
-	rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
-				    qeth_snmp_command_cb, (void *)&qinfo);
-	if (rc)
-		PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
-			   QETH_CARD_IFNAME(card), rc);
-	else {
-		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
-			rc = -EFAULT;
-	}
-
-	kfree(ureq);
-	kfree(qinfo.udata);
-	return rc;
-}
-
-static int
-qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
-			    unsigned long);
-
-static int
-qeth_default_setadapterparms_cb(struct qeth_card *card,
-                                struct qeth_reply *reply,
-                                unsigned long data);
-static int
-qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
-		      __u16, long,
-		      int (*reply_cb)
-		      (struct qeth_card *, struct qeth_reply *, unsigned long),
-		      void *reply_param);
-
-static int
-qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
-{
-	struct qeth_cmd_buffer *iob;
-	char buf[16];
-	int tmp;
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"arpadent");
-
-	/*
-	 * currently GuestLAN only supports the ARP assist function
-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
-	 * thus we say EOPNOTSUPP for this ARP function
-	 */
-	if (card->info.guestlan)
-		return -EOPNOTSUPP;
-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
-		PRINT_WARN("ARP processing not supported "
-			   "on %s!\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-
-	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
-				       IPA_CMD_ASS_ARP_ADD_ENTRY,
-				       sizeof(struct qeth_arp_cache_entry),
-				       QETH_PROT_IPV4);
-	rc = qeth_send_setassparms(card, iob,
-				   sizeof(struct qeth_arp_cache_entry),
-				   (unsigned long) entry,
-				   qeth_default_setassparms_cb, NULL);
-	if (rc) {
-		tmp = rc;
-		qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
-		PRINT_WARN("Could not add ARP entry for address %s on %s: "
-			   "%s (0x%x/%d)\n",
-			   buf, QETH_CARD_IFNAME(card),
-			   qeth_arp_get_error_cause(&rc), tmp, tmp);
-	}
-	return rc;
-}
-
-static int
-qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
-{
-	struct qeth_cmd_buffer *iob;
-	char buf[16] = {0, };
-	int tmp;
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"arprment");
-
-	/*
-	 * currently GuestLAN only supports the ARP assist function
-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
-	 * thus we say EOPNOTSUPP for this ARP function
-	 */
-	if (card->info.guestlan)
-		return -EOPNOTSUPP;
-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
-		PRINT_WARN("ARP processing not supported "
-			   "on %s!\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-	memcpy(buf, entry, 12);
-	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
-				       IPA_CMD_ASS_ARP_REMOVE_ENTRY,
-				       12,
-				       QETH_PROT_IPV4);
-	rc = qeth_send_setassparms(card, iob,
-				   12, (unsigned long)buf,
-				   qeth_default_setassparms_cb, NULL);
-	if (rc) {
-		tmp = rc;
-		memset(buf, 0, 16);
-		qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
-		PRINT_WARN("Could not delete ARP entry for address %s on %s: "
-			   "%s (0x%x/%d)\n",
-			   buf, QETH_CARD_IFNAME(card),
-			   qeth_arp_get_error_cause(&rc), tmp, tmp);
-	}
-	return rc;
-}
-
-static int
-qeth_arp_flush_cache(struct qeth_card *card)
-{
-	int rc;
-	int tmp;
-
-	QETH_DBF_TEXT(trace,3,"arpflush");
-
-	/*
-	 * currently GuestLAN only supports the ARP assist function
-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
-	 * thus we say EOPNOTSUPP for this ARP function
-	*/
-	if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
-		return -EOPNOTSUPP;
-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
-		PRINT_WARN("ARP processing not supported "
-			   "on %s!\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
-					  IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
-	if (rc){
-		tmp = rc;
-		PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n",
-			   QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
-			   tmp, tmp);
-	}
-	return rc;
-}
-
-static int
-qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct qeth_card *card = (struct qeth_card *)dev->priv;
-	struct qeth_arp_cache_entry arp_entry;
-	struct mii_ioctl_data *mii_data;
-	int rc = 0;
-
-	if (!card)
-		return -ENODEV;
-
-	if ((card->state != CARD_STATE_UP) &&
-            (card->state != CARD_STATE_SOFTSETUP))
-		return -ENODEV;
-
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		return -EPERM;
-
-	switch (cmd){
-	case SIOC_QETH_ARP_SET_NO_ENTRIES:
-		if ( !capable(CAP_NET_ADMIN) ||
-		     (card->options.layer2) ) {
-			rc = -EPERM;
-			break;
-		}
-		rc = qeth_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
-		break;
-	case SIOC_QETH_ARP_QUERY_INFO:
-		if ( !capable(CAP_NET_ADMIN) ||
-		     (card->options.layer2) ) {
-			rc = -EPERM;
-			break;
-		}
-		rc = qeth_arp_query(card, rq->ifr_ifru.ifru_data);
-		break;
-	case SIOC_QETH_ARP_ADD_ENTRY:
-		if ( !capable(CAP_NET_ADMIN) ||
-		     (card->options.layer2) ) {
-			rc = -EPERM;
-			break;
-		}
-		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
-				   sizeof(struct qeth_arp_cache_entry)))
-			rc = -EFAULT;
-		else
-			rc = qeth_arp_add_entry(card, &arp_entry);
-		break;
-	case SIOC_QETH_ARP_REMOVE_ENTRY:
-		if ( !capable(CAP_NET_ADMIN) ||
-		     (card->options.layer2) ) {
-			rc = -EPERM;
-			break;
-		}
-		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
-				   sizeof(struct qeth_arp_cache_entry)))
-			rc = -EFAULT;
-		else
-			rc = qeth_arp_remove_entry(card, &arp_entry);
-		break;
-	case SIOC_QETH_ARP_FLUSH_CACHE:
-		if ( !capable(CAP_NET_ADMIN) ||
-		     (card->options.layer2) ) {
-			rc = -EPERM;
-			break;
-		}
-		rc = qeth_arp_flush_cache(card);
-		break;
-	case SIOC_QETH_ADP_SET_SNMP_CONTROL:
-		rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
-		break;
-	case SIOC_QETH_GET_CARD_TYPE:
-		if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
-		    !card->info.guestlan)
-			return 1;
-		return 0;
-		break;
-	case SIOCGMIIPHY:
-		mii_data = if_mii(rq);
-		mii_data->phy_id = 0;
-		break;
-	case SIOCGMIIREG:
-		mii_data = if_mii(rq);
-		if (mii_data->phy_id != 0)
-			rc = -EINVAL;
-		else
-			mii_data->val_out = qeth_mdio_read(dev,mii_data->phy_id,
-							   mii_data->reg_num);
-		break;
-	default:
-		rc = -EOPNOTSUPP;
-	}
-	if (rc)
-		QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
-	return rc;
-}
-
-static struct net_device_stats *
-qeth_get_stats(struct net_device *dev)
-{
-	struct qeth_card *card;
-
-	card = (struct qeth_card *) (dev->priv);
-
-	QETH_DBF_TEXT(trace,5,"getstat");
-
-	return &card->stats;
-}
-
-static int
-qeth_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct qeth_card *card;
-	char dbf_text[15];
-
-	card = (struct qeth_card *) (dev->priv);
-
-	QETH_DBF_TEXT(trace,4,"chgmtu");
-	sprintf(dbf_text, "%8x", new_mtu);
-	QETH_DBF_TEXT(trace,4,dbf_text);
-
-	if (new_mtu < 64)
-		return -EINVAL;
-	if (new_mtu > 65535)
-		return -EINVAL;
-	if ((!qeth_is_supported(card,IPA_IP_FRAGMENTATION)) &&
-	    (!qeth_mtu_is_valid(card, new_mtu)))
-		return -EINVAL;
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-#ifdef CONFIG_QETH_VLAN
-static void
-qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct qeth_card *card;
-	unsigned long flags;
-
-	QETH_DBF_TEXT(trace,4,"vlanreg");
-
-	card = (struct qeth_card *) dev->priv;
-	spin_lock_irqsave(&card->vlanlock, flags);
-	card->vlangrp = grp;
-	spin_unlock_irqrestore(&card->vlanlock, flags);
-}
-
-static void
-qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
-		      unsigned short vid)
-{
-	int i;
-	struct sk_buff *skb;
-	struct sk_buff_head tmp_list;
-
-	skb_queue_head_init(&tmp_list);
-	lockdep_set_class(&tmp_list.lock, &qdio_out_skb_queue_key);
-	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
-		while ((skb = skb_dequeue(&buf->skb_list))){
-			if (vlan_tx_tag_present(skb) &&
-			    (vlan_tx_tag_get(skb) == vid)) {
-				atomic_dec(&skb->users);
-				dev_kfree_skb(skb);
-			} else
-				skb_queue_tail(&tmp_list, skb);
-		}
-	}
-	while ((skb = skb_dequeue(&tmp_list)))
-		skb_queue_tail(&buf->skb_list, skb);
-}
-
-static void
-qeth_free_vlan_skbs(struct qeth_card *card, unsigned short vid)
-{
-	int i, j;
-
-	QETH_DBF_TEXT(trace, 4, "frvlskbs");
-	for (i = 0; i < card->qdio.no_out_queues; ++i){
-		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
-			qeth_free_vlan_buffer(card, &card->qdio.
-					      out_qs[i]->bufs[j], vid);
-	}
-}
-
-static void
-qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
-{
-	struct in_device *in_dev;
-	struct in_ifaddr *ifa;
-	struct qeth_ipaddr *addr;
-
-	QETH_DBF_TEXT(trace, 4, "frvaddr4");
-
-	rcu_read_lock();
-	in_dev = __in_dev_get_rcu(vlan_group_get_device(card->vlangrp, vid));
-	if (!in_dev)
-		goto out;
-	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
-		addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
-		if (addr){
-			addr->u.a4.addr = ifa->ifa_address;
-			addr->u.a4.mask = ifa->ifa_mask;
-			addr->type = QETH_IP_TYPE_NORMAL;
-			if (!qeth_delete_ip(card, addr))
-				kfree(addr);
-		}
-	}
-out:
-	rcu_read_unlock();
-}
-
-static void
-qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
-{
-#ifdef CONFIG_QETH_IPV6
-	struct inet6_dev *in6_dev;
-	struct inet6_ifaddr *ifa;
-	struct qeth_ipaddr *addr;
-
-	QETH_DBF_TEXT(trace, 4, "frvaddr6");
-
-	in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
-	if (!in6_dev)
-		return;
-	for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next){
-		addr = qeth_get_addr_buffer(QETH_PROT_IPV6);
-		if (addr){
-			memcpy(&addr->u.a6.addr, &ifa->addr,
-			       sizeof(struct in6_addr));
-			addr->u.a6.pfxlen = ifa->prefix_len;
-			addr->type = QETH_IP_TYPE_NORMAL;
-			if (!qeth_delete_ip(card, addr))
-				kfree(addr);
-		}
-	}
-	in6_dev_put(in6_dev);
-#endif /* CONFIG_QETH_IPV6 */
-}
-
-static void
-qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
-{
-	if (card->options.layer2 || !card->vlangrp)
-		return;
-	qeth_free_vlan_addresses4(card, vid);
-	qeth_free_vlan_addresses6(card, vid);
-}
-
-static int
-qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
-                               struct qeth_reply *reply,
-                               unsigned long data)
-{
-        struct qeth_ipa_cmd *cmd;
-
-        QETH_DBF_TEXT(trace, 2, "L2sdvcb");
-        cmd = (struct qeth_ipa_cmd *) data;
-        if (cmd->hdr.return_code) {
-		PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
-			  "Continuing\n",cmd->data.setdelvlan.vlan_id,
-			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
-		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
-		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
-		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
-	}
-        return 0;
-}
-
-static int
-qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
-			    enum qeth_ipa_cmds ipacmd)
-{
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT_(trace, 4, "L2sdv%x",ipacmd);
-	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-        cmd->data.setdelvlan.vlan_id = i;
-	return qeth_send_ipa_cmd(card, iob,
-				 qeth_layer2_send_setdelvlan_cb, NULL);
-}
-
-static void
-qeth_layer2_process_vlans(struct qeth_card *card, int clear)
-{
-        unsigned short  i;
-
-	QETH_DBF_TEXT(trace, 3, "L2prcvln");
-
-	if (!card->vlangrp)
-		return;
-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-		if (vlan_group_get_device(card->vlangrp, i) == NULL)
-			continue;
-		if (clear)
-			qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
-		else
-			qeth_layer2_send_setdelvlan(card, i, IPA_CMD_SETVLAN);
-        }
-}
-
-/*add_vid is layer 2 used only ....*/
-static void
-qeth_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
-{
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
-
-	card = (struct qeth_card *) dev->priv;
-	if (!card->options.layer2)
-		return;
-	qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
-}
-
-/*... kill_vid used for both modes*/
-static void
-qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct qeth_card *card;
-	unsigned long flags;
-
-	QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
-
-	card = (struct qeth_card *) dev->priv;
-	/* free all skbs for the vlan device */
-	qeth_free_vlan_skbs(card, vid);
-	spin_lock_irqsave(&card->vlanlock, flags);
-	/* unregister IP addresses of vlan device */
-	qeth_free_vlan_addresses(card, vid);
-	vlan_group_set_device(card->vlangrp, vid, NULL);
-	spin_unlock_irqrestore(&card->vlanlock, flags);
-	if (card->options.layer2)
-		qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
-	qeth_set_multicast_list(card->dev);
-}
-#endif
-/**
- * Examine hardware response to SET_PROMISC_MODE
- */
-static int
-qeth_setadp_promisc_mode_cb(struct qeth_card *card,
-			    struct qeth_reply *reply,
-			    unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_ipacmd_setadpparms *setparms;
-
-	QETH_DBF_TEXT(trace,4,"prmadpcb");
-
-	cmd = (struct qeth_ipa_cmd *) data;
-	setparms = &(cmd->data.setadapterparms);
-
-        qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
-	if (cmd->hdr.return_code) {
-		QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
-		setparms->data.mode = SET_PROMISC_MODE_OFF;
-	}
-	card->info.promisc_mode = setparms->data.mode;
-	return 0;
-}
-/*
- * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
- */
-static void
-qeth_setadp_promisc_mode(struct qeth_card *card)
-{
-	enum qeth_ipa_promisc_modes mode;
-	struct net_device *dev = card->dev;
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace, 4, "setprom");
-
-	if (((dev->flags & IFF_PROMISC) &&
-	     (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
-	    (!(dev->flags & IFF_PROMISC) &&
-	     (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
-		return;
-	mode = SET_PROMISC_MODE_OFF;
-	if (dev->flags & IFF_PROMISC)
-		mode = SET_PROMISC_MODE_ON;
-	QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
-
-	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
-			sizeof(struct qeth_ipacmd_setadpparms));
-	cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
-	cmd->data.setadapterparms.data.mode = mode;
-	qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
-}
-
-/**
- * set multicast address on card
- */
-static void
-qeth_set_multicast_list(struct net_device *dev)
-{
-	struct qeth_card *card = (struct qeth_card *) dev->priv;
-
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		return ;
-
-	QETH_DBF_TEXT(trace, 3, "setmulti");
-	qeth_delete_mc_addresses(card);
-	if (card->options.layer2) {
-		qeth_layer2_add_multicast(card);
-		goto out;
-	}
-	qeth_add_multicast_ipv4(card);
-#ifdef CONFIG_QETH_IPV6
-	qeth_add_multicast_ipv6(card);
-#endif
-out:
-	qeth_set_ip_addr_list(card);
-	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
-		return;
-	qeth_setadp_promisc_mode(card);
-}
-
-static int
-qeth_neigh_setup(struct net_device *dev, struct neigh_parms *np)
-{
-	return 0;
-}
-
-static void
-qeth_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
-{
-	if (dev->type == ARPHRD_IEEE802_TR)
-		ip_tr_mc_map(ipm, mac);
-	else
-		ip_eth_mc_map(ipm, mac);
-}
-
-static struct qeth_ipaddr *
-qeth_get_addr_buffer(enum qeth_prot_versions prot)
-{
-	struct qeth_ipaddr *addr;
-
-	addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
-	if (addr == NULL) {
-		PRINT_WARN("Not enough memory to add address\n");
-		return NULL;
-	}
-	addr->type = QETH_IP_TYPE_NORMAL;
-	addr->proto = prot;
-	return addr;
-}
-
-int
-qeth_osn_assist(struct net_device *dev,
-		void *data,
-		int data_len)
-{
-	struct qeth_cmd_buffer *iob;
-	struct qeth_card *card;
-	int rc;
-
-	QETH_DBF_TEXT(trace, 2, "osnsdmc");
-	if (!dev)
-		return -ENODEV;
-	card = (struct qeth_card *)dev->priv;
-	if (!card)
-		return -ENODEV;
-	if ((card->state != CARD_STATE_UP) &&
-	    (card->state != CARD_STATE_SOFTSETUP))
-		return -ENODEV;
-	iob = qeth_wait_for_buffer(&card->write);
-	memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
-	rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
-	return rc;
-}
-
-static struct net_device *
-qeth_netdev_by_devno(unsigned char *read_dev_no)
-{
-	struct qeth_card *card;
-	struct net_device *ndev;
-	unsigned char *readno;
-	__u16 temp_dev_no, card_dev_no;
-	char *endp;
-	unsigned long flags;
-
-	ndev = NULL;
-	memcpy(&temp_dev_no, read_dev_no, 2);
-	read_lock_irqsave(&qeth_card_list.rwlock, flags);
-	list_for_each_entry(card, &qeth_card_list.list, list) {
-		readno = CARD_RDEV_ID(card);
-		readno += (strlen(readno) - 4);
-		card_dev_no = simple_strtoul(readno, &endp, 16);
-		if (card_dev_no == temp_dev_no) {
-			ndev = card->dev;
-			break;
-		}
-	}
-	read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
-	return ndev;
-}
-
-int
-qeth_osn_register(unsigned char *read_dev_no,
-		  struct net_device **dev,
-		  int (*assist_cb)(struct net_device *, void *),
-		  int (*data_cb)(struct sk_buff *))
-{
-	struct qeth_card * card;
-
-	QETH_DBF_TEXT(trace, 2, "osnreg");
-	*dev = qeth_netdev_by_devno(read_dev_no);
-	if (*dev == NULL)
-		return -ENODEV;
-	card = (struct qeth_card *)(*dev)->priv;
-	if (!card)
-		return -ENODEV;
-	if ((assist_cb == NULL) || (data_cb == NULL))
-		return -EINVAL;
-	card->osn_info.assist_cb = assist_cb;
-	card->osn_info.data_cb = data_cb;
-	return 0;
-}
-
-void
-qeth_osn_deregister(struct net_device * dev)
-{
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(trace, 2, "osndereg");
-	if (!dev)
-		return;
-	card = (struct qeth_card *)dev->priv;
-	if (!card)
-		return;
-	card->osn_info.assist_cb = NULL;
-	card->osn_info.data_cb = NULL;
-	return;
-}
-
-static void
-qeth_delete_mc_addresses(struct qeth_card *card)
-{
-	struct qeth_ipaddr *iptodo;
-	unsigned long flags;
-
-	QETH_DBF_TEXT(trace,4,"delmc");
-	iptodo = qeth_get_addr_buffer(QETH_PROT_IPV4);
-	if (!iptodo) {
-		QETH_DBF_TEXT(trace, 2, "dmcnomem");
-		return;
-	}
-	iptodo->type = QETH_IP_TYPE_DEL_ALL_MC;
-	spin_lock_irqsave(&card->ip_lock, flags);
-	if (!__qeth_insert_ip_todo(card, iptodo, 0))
-		kfree(iptodo);
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-}
-
-static void
-qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev)
-{
-	struct qeth_ipaddr *ipm;
-	struct ip_mc_list *im4;
-	char buf[MAX_ADDR_LEN];
-
-	QETH_DBF_TEXT(trace,4,"addmc");
-	for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
-		qeth_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev);
-		ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
-		if (!ipm)
-			continue;
-		ipm->u.a4.addr = im4->multiaddr;
-		memcpy(ipm->mac,buf,OSA_ADDR_LEN);
-		ipm->is_multicast = 1;
-		if (!qeth_add_ip(card,ipm))
-			kfree(ipm);
-	}
-}
-
-static inline void
-qeth_add_vlan_mc(struct qeth_card *card)
-{
-#ifdef CONFIG_QETH_VLAN
-	struct in_device *in_dev;
-	struct vlan_group *vg;
-	int i;
-
-	QETH_DBF_TEXT(trace,4,"addmcvl");
-	if ( ((card->options.layer2 == 0) &&
-	      (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
-	     (card->vlangrp == NULL) )
-		return ;
-
-	vg = card->vlangrp;
-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-		struct net_device *netdev = vlan_group_get_device(vg, i);
-		if (netdev == NULL ||
-		    !(netdev->flags & IFF_UP))
-			continue;
-		in_dev = in_dev_get(netdev);
-		if (!in_dev)
-			continue;
-		read_lock(&in_dev->mc_list_lock);
-		qeth_add_mc(card,in_dev);
-		read_unlock(&in_dev->mc_list_lock);
-		in_dev_put(in_dev);
-	}
-#endif
-}
-
-static void
-qeth_add_multicast_ipv4(struct qeth_card *card)
-{
-	struct in_device *in4_dev;
-
-	QETH_DBF_TEXT(trace,4,"chkmcv4");
-	in4_dev = in_dev_get(card->dev);
-	if (in4_dev == NULL)
-		return;
-	read_lock(&in4_dev->mc_list_lock);
-	qeth_add_mc(card, in4_dev);
-	qeth_add_vlan_mc(card);
-	read_unlock(&in4_dev->mc_list_lock);
-	in_dev_put(in4_dev);
-}
-
-static void
-qeth_layer2_add_multicast(struct qeth_card *card)
-{
-	struct qeth_ipaddr *ipm;
-	struct dev_mc_list *dm;
-
-	QETH_DBF_TEXT(trace,4,"L2addmc");
-	for (dm = card->dev->mc_list; dm; dm = dm->next) {
-		ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
-		if (!ipm)
-			continue;
-		memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
-		ipm->is_multicast = 1;
-		if (!qeth_add_ip(card, ipm))
-			kfree(ipm);
-	}
-}
-
-#ifdef CONFIG_QETH_IPV6
-static void
-qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
-{
-	struct qeth_ipaddr *ipm;
-	struct ifmcaddr6 *im6;
-	char buf[MAX_ADDR_LEN];
-
-	QETH_DBF_TEXT(trace,4,"addmc6");
-	for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
-		ndisc_mc_map(&im6->mca_addr, buf, in6_dev->dev, 0);
-		ipm = qeth_get_addr_buffer(QETH_PROT_IPV6);
-		if (!ipm)
-			continue;
-		ipm->is_multicast = 1;
-		memcpy(ipm->mac,buf,OSA_ADDR_LEN);
-		memcpy(&ipm->u.a6.addr,&im6->mca_addr.s6_addr,
-		       sizeof(struct in6_addr));
-		if (!qeth_add_ip(card,ipm))
-			kfree(ipm);
-	}
-}
-
-static inline void
-qeth_add_vlan_mc6(struct qeth_card *card)
-{
-#ifdef CONFIG_QETH_VLAN
-	struct inet6_dev *in_dev;
-	struct vlan_group *vg;
-	int i;
-
-	QETH_DBF_TEXT(trace,4,"admc6vl");
-	if ( ((card->options.layer2 == 0) &&
-	      (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
-	     (card->vlangrp == NULL))
-		return ;
-
-	vg = card->vlangrp;
-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-		struct net_device *netdev = vlan_group_get_device(vg, i);
-		if (netdev == NULL ||
-		    !(netdev->flags & IFF_UP))
-			continue;
-		in_dev = in6_dev_get(netdev);
-		if (!in_dev)
-			continue;
-		read_lock_bh(&in_dev->lock);
-		qeth_add_mc6(card,in_dev);
-		read_unlock_bh(&in_dev->lock);
-		in6_dev_put(in_dev);
-	}
-#endif /* CONFIG_QETH_VLAN */
-}
-
-static void
-qeth_add_multicast_ipv6(struct qeth_card *card)
-{
-	struct inet6_dev *in6_dev;
-
-	QETH_DBF_TEXT(trace,4,"chkmcv6");
-	if (!qeth_is_supported(card, IPA_IPV6))
-		return ;
-	in6_dev = in6_dev_get(card->dev);
-	if (in6_dev == NULL)
-		return;
-	read_lock_bh(&in6_dev->lock);
-	qeth_add_mc6(card, in6_dev);
-	qeth_add_vlan_mc6(card);
-	read_unlock_bh(&in6_dev->lock);
-	in6_dev_put(in6_dev);
-}
-#endif /* CONFIG_QETH_IPV6 */
-
-static int
-qeth_layer2_send_setdelmac(struct qeth_card *card, __u8 *mac,
-			   enum qeth_ipa_cmds ipacmd,
-			   int (*reply_cb) (struct qeth_card *,
-					    struct qeth_reply*,
-					    unsigned long))
-{
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(trace, 2, "L2sdmac");
-	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-        cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
-        memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
-	return qeth_send_ipa_cmd(card, iob, reply_cb, NULL);
-}
-
-static int
-qeth_layer2_send_setgroupmac_cb(struct qeth_card *card,
-				struct qeth_reply *reply,
-				unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-	__u8 *mac;
-
-	QETH_DBF_TEXT(trace, 2, "L2Sgmacb");
-	cmd = (struct qeth_ipa_cmd *) data;
-	mac = &cmd->data.setdelmac.mac[0];
-	/* MAC already registered, needed in couple/uncouple case */
-	if (cmd->hdr.return_code == 0x2005) {
-		PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \
-			  "already existing on %s \n",
-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-			  QETH_CARD_IFNAME(card));
-		cmd->hdr.return_code = 0;
-	}
-	if (cmd->hdr.return_code)
-		PRINT_ERR("Could not set group MAC " \
-			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-			  QETH_CARD_IFNAME(card),cmd->hdr.return_code);
-	return 0;
-}
-
-static int
-qeth_layer2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
-{
-	QETH_DBF_TEXT(trace, 2, "L2Sgmac");
-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
-					  qeth_layer2_send_setgroupmac_cb);
-}
-
-static int
-qeth_layer2_send_delgroupmac_cb(struct qeth_card *card,
-				struct qeth_reply *reply,
-				unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-	__u8 *mac;
-
-	QETH_DBF_TEXT(trace, 2, "L2Dgmacb");
-	cmd = (struct qeth_ipa_cmd *) data;
-	mac = &cmd->data.setdelmac.mac[0];
-	if (cmd->hdr.return_code)
-		PRINT_ERR("Could not delete group MAC " \
-			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
-	return 0;
-}
-
-static int
-qeth_layer2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
-{
-	QETH_DBF_TEXT(trace, 2, "L2Dgmac");
-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
-					  qeth_layer2_send_delgroupmac_cb);
-}
-
-static int
-qeth_layer2_send_setmac_cb(struct qeth_card *card,
-			   struct qeth_reply *reply,
-			   unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace, 2, "L2Smaccb");
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->hdr.return_code) {
-		QETH_DBF_TEXT_(trace, 2, "L2er%x", cmd->hdr.return_code);
-		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
-		cmd->hdr.return_code = -EIO;
-	} else {
-		card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
-		memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac,
-		       OSA_ADDR_LEN);
-		PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
-			   "successfully registered on device %s\n",
-			   card->dev->dev_addr[0], card->dev->dev_addr[1],
-			   card->dev->dev_addr[2], card->dev->dev_addr[3],
-			   card->dev->dev_addr[4], card->dev->dev_addr[5],
-			   card->dev->name);
-	}
-	return 0;
-}
-
-static int
-qeth_layer2_send_setmac(struct qeth_card *card, __u8 *mac)
-{
-	QETH_DBF_TEXT(trace, 2, "L2Setmac");
-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
-					  qeth_layer2_send_setmac_cb);
-}
-
-static int
-qeth_layer2_send_delmac_cb(struct qeth_card *card,
-			   struct qeth_reply *reply,
-			   unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace, 2, "L2Dmaccb");
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->hdr.return_code) {
-		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
-		cmd->hdr.return_code = -EIO;
-		return 0;
-	}
-	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
-
-	return 0;
-}
-static int
-qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac)
-{
-	QETH_DBF_TEXT(trace, 2, "L2Delmac");
-	if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
-		return 0;
-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
-					  qeth_layer2_send_delmac_cb);
-}
-
-static int
-qeth_layer2_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-	struct qeth_card *card;
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace, 3, "setmac");
-
-	if (qeth_verify_dev(dev) != QETH_REAL_CARD) {
-		QETH_DBF_TEXT(trace, 3, "setmcINV");
-		return -EOPNOTSUPP;
-	}
-	card = (struct qeth_card *) dev->priv;
-
-	if (!card->options.layer2) {
-		PRINT_WARN("Setting MAC address on %s is not supported "
-			   "in Layer 3 mode.\n", dev->name);
-		QETH_DBF_TEXT(trace, 3, "setmcLY3");
-		return -EOPNOTSUPP;
-	}
-	if (card->info.type == QETH_CARD_TYPE_OSN) {
-		PRINT_WARN("Setting MAC address on %s is not supported.\n",
-			   dev->name);
-		QETH_DBF_TEXT(trace, 3, "setmcOSN");
-		return -EOPNOTSUPP;
-	}
-	QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
-	QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
-	rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
-	if (!rc)
-		rc = qeth_layer2_send_setmac(card, addr->sa_data);
-	return rc;
-}
-
-static void
-qeth_fill_ipacmd_header(struct qeth_card *card, struct qeth_ipa_cmd *cmd,
-			__u8 command, enum qeth_prot_versions prot)
-{
-	memset(cmd, 0, sizeof (struct qeth_ipa_cmd));
-	cmd->hdr.command = command;
-	cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
-	cmd->hdr.seqno = card->seqno.ipa;
-	cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
-	cmd->hdr.rel_adapter_no = (__u8) card->info.portno;
-	if (card->options.layer2)
-		cmd->hdr.prim_version_no = 2;
-	else
-		cmd->hdr.prim_version_no = 1;
-	cmd->hdr.param_count = 1;
-	cmd->hdr.prot_version = prot;
-	cmd->hdr.ipa_supported = 0;
-	cmd->hdr.ipa_enabled = 0;
-}
-
-static struct qeth_cmd_buffer *
-qeth_get_ipacmd_buffer(struct qeth_card *card, enum qeth_ipa_cmds ipacmd,
-		       enum qeth_prot_versions prot)
-{
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	iob = qeth_wait_for_buffer(&card->write);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
-
-	return iob;
-}
-
-static int
-qeth_send_setdelmc(struct qeth_card *card, struct qeth_ipaddr *addr, int ipacmd)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"setdelmc");
-
-	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	memcpy(&cmd->data.setdelipm.mac,addr->mac, OSA_ADDR_LEN);
-	if (addr->proto == QETH_PROT_IPV6)
-		memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
-		       sizeof(struct in6_addr));
-	else
-		memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr,4);
-
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
-	return rc;
-}
-static void
-qeth_fill_netmask(u8 *netmask, unsigned int len)
-{
-	int i,j;
-	for (i=0;i<16;i++) {
-		j=(len)-(i*8);
-		if (j >= 8)
-			netmask[i] = 0xff;
-		else if (j > 0)
-			netmask[i] = (u8)(0xFF00>>j);
-		else
-			netmask[i] = 0;
-	}
-}
-
-static int
-qeth_send_setdelip(struct qeth_card *card, struct qeth_ipaddr *addr,
-		   int ipacmd, unsigned int flags)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-	__u8 netmask[16];
-
-	QETH_DBF_TEXT(trace,4,"setdelip");
-	QETH_DBF_TEXT_(trace,4,"flags%02X", flags);
-
-	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	if (addr->proto == QETH_PROT_IPV6) {
-		memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
-		       sizeof(struct in6_addr));
-		qeth_fill_netmask(netmask,addr->u.a6.pfxlen);
-		memcpy(cmd->data.setdelip6.mask, netmask,
-		       sizeof(struct in6_addr));
-		cmd->data.setdelip6.flags = flags;
-	} else {
-		memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
-		memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
-		cmd->data.setdelip4.flags = flags;
-	}
-
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
-	return rc;
-}
-
-static int
-qeth_layer2_register_addr_entry(struct qeth_card *card,
-				struct qeth_ipaddr *addr)
-{
-	if (!addr->is_multicast)
-		return 0;
-	QETH_DBF_TEXT(trace, 2, "setgmac");
-	QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN);
-	return qeth_layer2_send_setgroupmac(card, &addr->mac[0]);
-}
-
-static int
-qeth_layer2_deregister_addr_entry(struct qeth_card *card,
-				  struct qeth_ipaddr *addr)
-{
-	if (!addr->is_multicast)
-		return 0;
-	QETH_DBF_TEXT(trace, 2, "delgmac");
-	QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN);
-	return qeth_layer2_send_delgroupmac(card, &addr->mac[0]);
-}
-
-static int
-qeth_layer3_register_addr_entry(struct qeth_card *card,
-				struct qeth_ipaddr *addr)
-{
-	char buf[50];
-	int rc;
-	int cnt = 3;
-
-	if (addr->proto == QETH_PROT_IPV4) {
-		QETH_DBF_TEXT(trace, 2,"setaddr4");
-		QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
-	} else if (addr->proto == QETH_PROT_IPV6) {
-		QETH_DBF_TEXT(trace, 2, "setaddr6");
-		QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
-		QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
-	} else {
-		QETH_DBF_TEXT(trace, 2, "setaddr?");
-		QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
-	}
-	do {
-		if (addr->is_multicast)
-			rc =  qeth_send_setdelmc(card, addr, IPA_CMD_SETIPM);
-		else
-			rc = qeth_send_setdelip(card, addr, IPA_CMD_SETIP,
-					addr->set_flags);
-		if (rc)
-			QETH_DBF_TEXT(trace, 2, "failed");
-	} while ((--cnt > 0) && rc);
-	if (rc){
-		QETH_DBF_TEXT(trace, 2, "FAILED");
-		qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
-		PRINT_WARN("Could not register IP address %s (rc=0x%x/%d)\n",
-			   buf, rc, rc);
-	}
-	return rc;
-}
-
-static int
-qeth_layer3_deregister_addr_entry(struct qeth_card *card,
-				  struct qeth_ipaddr *addr)
-{
-	//char buf[50];
-	int rc;
-
-	if (addr->proto == QETH_PROT_IPV4) {
-		QETH_DBF_TEXT(trace, 2,"deladdr4");
-		QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
-	} else if (addr->proto == QETH_PROT_IPV6) {
-		QETH_DBF_TEXT(trace, 2, "deladdr6");
-		QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
-		QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
-	} else {
-		QETH_DBF_TEXT(trace, 2, "deladdr?");
-		QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
-	}
-	if (addr->is_multicast)
-		rc = qeth_send_setdelmc(card, addr, IPA_CMD_DELIPM);
-	else
-		rc = qeth_send_setdelip(card, addr, IPA_CMD_DELIP,
-					addr->del_flags);
-	if (rc) {
-		QETH_DBF_TEXT(trace, 2, "failed");
-		/* TODO: re-activate this warning as soon as we have a
-		 * clean mirco code
-		qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
-		PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
-			   buf, rc);
-		*/
-	}
-	return rc;
-}
-
-static int
-qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
-{
-	if (card->options.layer2)
-		return qeth_layer2_register_addr_entry(card, addr);
-
-	return qeth_layer3_register_addr_entry(card, addr);
-}
-
-static int
-qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
-{
-	if (card->options.layer2)
-		return qeth_layer2_deregister_addr_entry(card, addr);
-
-	return qeth_layer3_deregister_addr_entry(card, addr);
-}
-
-static u32
-qeth_ethtool_get_tx_csum(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int
-qeth_ethtool_set_tx_csum(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= NETIF_F_HW_CSUM;
-	else
-		dev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-
-static u32
-qeth_ethtool_get_rx_csum(struct net_device *dev)
-{
-	struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-	return (card->options.checksum_type == HW_CHECKSUMMING);
-}
-
-static int
-qeth_ethtool_set_rx_csum(struct net_device *dev, u32 data)
-{
-	struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-	if (data)
-		card->options.checksum_type = HW_CHECKSUMMING;
-	else
-		card->options.checksum_type = SW_CHECKSUMMING;
-	return 0;
-}
-
-static u32
-qeth_ethtool_get_sg(struct net_device *dev)
-{
-	struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-	return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
-		(dev->features & NETIF_F_SG));
-}
-
-static int
-qeth_ethtool_set_sg(struct net_device *dev, u32 data)
-{
-	struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-	if (data) {
-		if (card->options.large_send != QETH_LARGE_SEND_NO)
-			dev->features |= NETIF_F_SG;
-		else {
-			dev->features &= ~NETIF_F_SG;
-			return -EINVAL;
-		}
-	} else
-		dev->features &= ~NETIF_F_SG;
-	return 0;
-}
-
-static u32
-qeth_ethtool_get_tso(struct net_device *dev)
-{
-	struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-	return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
-		(dev->features & NETIF_F_TSO));
-}
-
-static int
-qeth_ethtool_set_tso(struct net_device *dev, u32 data)
-{
-	struct qeth_card *card = (struct qeth_card *)dev->priv;
-
-	if (data) {
-		if (card->options.large_send != QETH_LARGE_SEND_NO)
-			dev->features |= NETIF_F_TSO;
-		else {
-			dev->features &= ~NETIF_F_TSO;
-			return -EINVAL;
-		}
-	} else
-		dev->features &= ~NETIF_F_TSO;
-	return 0;
-}
-
-static struct ethtool_ops qeth_ethtool_ops = {
-	.get_tx_csum = qeth_ethtool_get_tx_csum,
-	.set_tx_csum = qeth_ethtool_set_tx_csum,
-	.get_rx_csum = qeth_ethtool_get_rx_csum,
-	.set_rx_csum = qeth_ethtool_set_rx_csum,
-	.get_sg      = qeth_ethtool_get_sg,
-	.set_sg      = qeth_ethtool_set_sg,
-	.get_tso     = qeth_ethtool_get_tso,
-	.set_tso     = qeth_ethtool_set_tso,
-};
-
-static int
-qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr)
-{
-	const struct qeth_card *card;
-	const struct ethhdr *eth;
-	struct net_device *dev = skb->dev;
-
-	if (dev->type != ARPHRD_IEEE802_TR)
-		return 0;
-
-	card = qeth_get_card_from_dev(dev);
-	if (card->options.layer2)
-		goto haveheader;
-#ifdef CONFIG_QETH_IPV6
-	/* cause of the manipulated arp constructor and the ARP
-	   flag for OSAE devices we have some nasty exceptions */
-	if (card->info.type == QETH_CARD_TYPE_OSAE) {
-		if (!card->options.fake_ll) {
-			if ((skb->pkt_type==PACKET_OUTGOING) &&
-			    (skb->protocol==ETH_P_IPV6))
-				goto haveheader;
-			else
-				return 0;
-		} else {
-			if ((skb->pkt_type==PACKET_OUTGOING) &&
-			    (skb->protocol==ETH_P_IP))
-				return 0;
-			else
-				goto haveheader;
-		}
-	}
-#endif
-	if (!card->options.fake_ll)
-		return 0;
-haveheader:
-	eth = eth_hdr(skb);
-	memcpy(haddr, eth->h_source, ETH_ALEN);
-	return ETH_ALEN;
-}
-
-static const struct header_ops qeth_null_ops = {
-	.parse = qeth_hard_header_parse,
-};
-
-static int
-qeth_netdev_init(struct net_device *dev)
-{
-	struct qeth_card *card;
-
-	card = (struct qeth_card *) dev->priv;
-
-	QETH_DBF_TEXT(trace,3,"initdev");
-
-	dev->tx_timeout = &qeth_tx_timeout;
-	dev->watchdog_timeo = QETH_TX_TIMEOUT;
-	dev->open = qeth_open;
-	dev->stop = qeth_stop;
-	dev->hard_start_xmit = qeth_hard_start_xmit;
-	dev->do_ioctl = qeth_do_ioctl;
-	dev->get_stats = qeth_get_stats;
-	dev->change_mtu = qeth_change_mtu;
-	dev->neigh_setup = qeth_neigh_setup;
-	dev->set_multicast_list = qeth_set_multicast_list;
-#ifdef CONFIG_QETH_VLAN
-	dev->vlan_rx_register = qeth_vlan_rx_register;
-	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
-	dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
-#endif
-	if (qeth_get_netdev_flags(card) & IFF_NOARP)
-		dev->header_ops = &qeth_null_ops;
-
-#ifdef CONFIG_QETH_IPV6
-	/*IPv6 address autoconfiguration stuff*/
-	if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
-		card->dev->dev_id = card->info.unique_id & 0xffff;
-#endif
-	if (card->options.fake_ll &&
-		(qeth_get_netdev_flags(card) & IFF_NOARP))
-			dev->header_ops = &qeth_fake_ops;
-
-	dev->set_mac_address = qeth_layer2_set_mac_address;
-	dev->flags |= qeth_get_netdev_flags(card);
-	if ((card->options.fake_broadcast) ||
-	    (card->info.broadcast_capable))
-		dev->flags |= IFF_BROADCAST;
-	dev->hard_header_len =
-			qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
-	dev->addr_len = OSA_ADDR_LEN;
-	dev->mtu = card->info.initial_mtu;
-	if (card->info.type != QETH_CARD_TYPE_OSN)
-		SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
-	return 0;
-}
-
-static void
-qeth_init_func_level(struct qeth_card *card)
-{
-	if (card->ipato.enabled) {
-		if (card->info.type == QETH_CARD_TYPE_IQD)
-				card->info.func_level =
-					QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
-		else
-				card->info.func_level =
-					QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
-	} else {
-		if (card->info.type == QETH_CARD_TYPE_IQD)
-		/*FIXME:why do we have same values for  dis and ena for osae??? */
-			card->info.func_level =
-				QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
-		else
-			card->info.func_level =
-				QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
-	}
-}
-
-/**
- * hardsetup card, initialize MPC and QDIO stuff
- */
-static int
-qeth_hardsetup_card(struct qeth_card *card)
-{
-	int retries = 3;
-	int rc;
-
-	QETH_DBF_TEXT(setup, 2, "hrdsetup");
-
-	atomic_set(&card->force_alloc_skb, 0);
-retry:
-	if (retries < 3){
-		PRINT_WARN("Retrying to do IDX activates.\n");
-		ccw_device_set_offline(CARD_DDEV(card));
-		ccw_device_set_offline(CARD_WDEV(card));
-		ccw_device_set_offline(CARD_RDEV(card));
-		ccw_device_set_online(CARD_RDEV(card));
-		ccw_device_set_online(CARD_WDEV(card));
-		ccw_device_set_online(CARD_DDEV(card));
-	}
-	rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
-	if (rc == -ERESTARTSYS) {
-		QETH_DBF_TEXT(setup, 2, "break1");
-		return rc;
-	} else if (rc) {
-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-		if (--retries < 0)
-			goto out;
-		else
-			goto retry;
-	}
-	if ((rc = qeth_get_unitaddr(card))){
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		return rc;
-	}
-	qeth_init_tokens(card);
-	qeth_init_func_level(card);
-	rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
-	if (rc == -ERESTARTSYS) {
-		QETH_DBF_TEXT(setup, 2, "break2");
-		return rc;
-	} else if (rc) {
-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-		if (--retries < 0)
-			goto out;
-		else
-			goto retry;
-	}
-	rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb);
-	if (rc == -ERESTARTSYS) {
-		QETH_DBF_TEXT(setup, 2, "break3");
-		return rc;
-	} else if (rc) {
-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
-		if (--retries < 0)
-			goto out;
-		else
-			goto retry;
-	}
-	if ((rc = qeth_mpc_initialize(card))){
-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-		goto out;
-	}
-	/*network device will be recovered*/
-	if (card->dev) {
-		card->dev->header_ops = card->orig_header_ops;
-		if (card->options.fake_ll &&
-		    (qeth_get_netdev_flags(card) & IFF_NOARP))
-			card->dev->header_ops = &qeth_fake_ops;
-		return 0;
-	}
-	/* at first set_online allocate netdev */
-	card->dev = qeth_get_netdevice(card->info.type,
-				       card->info.link_type);
-	if (!card->dev){
-		qeth_qdio_clear_card(card, card->info.type !=
-				     QETH_CARD_TYPE_IQD);
-		rc = -ENODEV;
-		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
-		goto out;
-	}
-	card->dev->priv = card;
-	card->orig_header_ops = card->dev->header_ops;
-	card->dev->type = qeth_get_arphdr_type(card->info.type,
-					       card->info.link_type);
-	card->dev->init = qeth_netdev_init;
-	return 0;
-out:
-	PRINT_ERR("Initialization in hardsetup failed! rc=%d\n", rc);
-	return rc;
-}
-
-static int
-qeth_default_setassparms_cb(struct qeth_card *card, struct qeth_reply *reply,
-			    unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"defadpcb");
-
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->hdr.return_code == 0){
-		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
-		if (cmd->hdr.prot_version == QETH_PROT_IPV4)
-			card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
-#ifdef CONFIG_QETH_IPV6
-		if (cmd->hdr.prot_version == QETH_PROT_IPV6)
-			card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
-#endif
-	}
-	if (cmd->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
-	    cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
-		card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
-		QETH_DBF_TEXT_(trace, 3, "csum:%d", card->info.csum_mask);
-	}
-	return 0;
-}
-
-static int
-qeth_default_setadapterparms_cb(struct qeth_card *card,
-				struct qeth_reply *reply,
-				unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"defadpcb");
-
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->hdr.return_code == 0)
-		cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
-	return 0;
-}
-
-
-
-static int
-qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
-			      unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,3,"quyadpcb");
-
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
-		card->info.link_type =
-		      cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
-	card->options.adp.supported_funcs =
-		cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
-	return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
-}
-
-static int
-qeth_query_setadapterparms(struct qeth_card *card)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(trace,3,"queryadp");
-	iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_COMMANDS_SUPPORTED,
-				   sizeof(struct qeth_ipacmd_setadpparms));
-	rc = qeth_send_ipa_cmd(card, iob, qeth_query_setadapterparms_cb, NULL);
-	return rc;
-}
-
-static int
-qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
-				   struct qeth_reply *reply,
-				   unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"chgmaccb");
-
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (!card->options.layer2 ||
-	    !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
-		memcpy(card->dev->dev_addr,
-		       &cmd->data.setadapterparms.data.change_addr.addr,
-		       OSA_ADDR_LEN);
-		card->info.mac_bits |= QETH_LAYER2_MAC_READ;
-	}
-	qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
-	return 0;
-}
-
-static int
-qeth_setadpparms_change_macaddr(struct qeth_card *card)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"chgmac");
-
-	iob = qeth_get_adapter_cmd(card,IPA_SETADP_ALTER_MAC_ADDRESS,
-				   sizeof(struct qeth_ipacmd_setadpparms));
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
-	cmd->data.setadapterparms.data.change_addr.addr_size = OSA_ADDR_LEN;
-	memcpy(&cmd->data.setadapterparms.data.change_addr.addr,
-	       card->dev->dev_addr, OSA_ADDR_LEN);
-	rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_change_macaddr_cb,
-			       NULL);
-	return rc;
-}
-
-static int
-qeth_send_setadp_mode(struct qeth_card *card, __u32 command, __u32 mode)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"adpmode");
-
-	iob = qeth_get_adapter_cmd(card, command,
-				   sizeof(struct qeth_ipacmd_setadpparms));
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	cmd->data.setadapterparms.data.mode = mode;
-	rc = qeth_send_ipa_cmd(card, iob, qeth_default_setadapterparms_cb,
-			       NULL);
-	return rc;
-}
-
-static int
-qeth_setadapter_hstr(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,4,"adphstr");
-
-	if (qeth_adp_supported(card,IPA_SETADP_SET_BROADCAST_MODE)) {
-		rc = qeth_send_setadp_mode(card, IPA_SETADP_SET_BROADCAST_MODE,
-					   card->options.broadcast_mode);
-		if (rc)
-			PRINT_WARN("couldn't set broadcast mode on "
-				   "device %s: x%x\n",
-				   CARD_BUS_ID(card), rc);
-		rc = qeth_send_setadp_mode(card, IPA_SETADP_ALTER_MAC_ADDRESS,
-					   card->options.macaddr_mode);
-		if (rc)
-			PRINT_WARN("couldn't set macaddr mode on "
-				   "device %s: x%x\n", CARD_BUS_ID(card), rc);
-		return rc;
-	}
-	if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL)
-		PRINT_WARN("set adapter parameters not available "
-			   "to set broadcast mode, using ALLRINGS "
-			   "on device %s:\n", CARD_BUS_ID(card));
-	if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL)
-		PRINT_WARN("set adapter parameters not available "
-			   "to set macaddr mode, using NONCANONICAL "
-			   "on device %s:\n", CARD_BUS_ID(card));
-	return 0;
-}
-
-static int
-qeth_setadapter_parms(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(setup, 2, "setadprm");
-
-	if (!qeth_is_supported(card, IPA_SETADAPTERPARMS)){
-		PRINT_WARN("set adapter parameters not supported "
-			   "on device %s.\n",
-			   CARD_BUS_ID(card));
-		QETH_DBF_TEXT(setup, 2, " notsupp");
-		return 0;
-	}
-	rc = qeth_query_setadapterparms(card);
-	if (rc) {
-		PRINT_WARN("couldn't set adapter parameters on device %s: "
-			   "x%x\n", CARD_BUS_ID(card), rc);
-		return rc;
-	}
-	if (qeth_adp_supported(card,IPA_SETADP_ALTER_MAC_ADDRESS)) {
-		rc = qeth_setadpparms_change_macaddr(card);
-		if (rc)
-			PRINT_WARN("couldn't get MAC address on "
-				   "device %s: x%x\n",
-				   CARD_BUS_ID(card), rc);
-	}
-
-	if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-	    (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
-		rc = qeth_setadapter_hstr(card);
-
-	return rc;
-}
-
-static int
-qeth_layer2_initialize(struct qeth_card *card)
-{
-        int rc = 0;
-
-
-        QETH_DBF_TEXT(setup, 2, "doL2init");
-        QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
-
-	rc = qeth_query_setadapterparms(card);
-	if (rc) {
-		PRINT_WARN("could not query adapter parameters on device %s: "
-			   "x%x\n", CARD_BUS_ID(card), rc);
-	}
-
-	rc = qeth_setadpparms_change_macaddr(card);
-	if (rc) {
-		PRINT_WARN("couldn't get MAC address on "
-			   "device %s: x%x\n",
-			   CARD_BUS_ID(card), rc);
-		QETH_DBF_TEXT_(setup, 2,"1err%d",rc);
-		return rc;
-        }
-	QETH_DBF_HEX(setup,2, card->dev->dev_addr, OSA_ADDR_LEN);
-
-	rc = qeth_layer2_send_setmac(card, &card->dev->dev_addr[0]);
-        if (rc)
-		QETH_DBF_TEXT_(setup, 2,"2err%d",rc);
-        return 0;
-}
-
-
-static int
-qeth_send_startstoplan(struct qeth_card *card, enum qeth_ipa_cmds ipacmd,
-		       enum qeth_prot_versions prot)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	iob = qeth_get_ipacmd_buffer(card,ipacmd,prot);
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
-	return rc;
-}
-
-static int
-qeth_send_startlan(struct qeth_card *card, enum qeth_prot_versions prot)
-{
-	int rc;
-
-	QETH_DBF_TEXT_(setup, 2, "strtlan%i", prot);
-
-	rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, prot);
-	return rc;
-}
-
-static int
-qeth_send_stoplan(struct qeth_card *card)
-{
-	int rc = 0;
-
-	/*
-	 * TODO: according to the IPA format document page 14,
-	 * TCP/IP (we!) never issue a STOPLAN
-	 * is this right ?!?
-	 */
-	QETH_DBF_TEXT(trace, 2, "stoplan");
-
-	rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, QETH_PROT_IPV4);
-	return rc;
-}
-
-static int
-qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply,
-			unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(setup, 2, "qipasscb");
-
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
-		card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
-		card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
-		/* Disable IPV6 support hard coded for Hipersockets */
-		if(card->info.type == QETH_CARD_TYPE_IQD)
-			card->options.ipa4.supported_funcs &= ~IPA_IPV6;
-	} else {
-#ifdef CONFIG_QETH_IPV6
-		card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
-		card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
-#endif
-	}
-	QETH_DBF_TEXT(setup, 2, "suppenbl");
-	QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_supported);
-	QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_enabled);
-	return 0;
-}
-
-static int
-qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT_(setup, 2, "qipassi%i", prot);
-	if (card->options.layer2) {
-		QETH_DBF_TEXT(setup, 2, "noprmly2");
-		return -EPERM;
-	}
-
-	iob = qeth_get_ipacmd_buffer(card,IPA_CMD_QIPASSIST,prot);
-	rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL);
-	return rc;
-}
-
-static struct qeth_cmd_buffer *
-qeth_get_setassparms_cmd(struct qeth_card *card, enum qeth_ipa_funcs ipa_func,
-			 __u16 cmd_code, __u16 len,
-			 enum qeth_prot_versions prot)
-{
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"getasscm");
-	iob = qeth_get_ipacmd_buffer(card,IPA_CMD_SETASSPARMS,prot);
-
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	cmd->data.setassparms.hdr.assist_no = ipa_func;
-	cmd->data.setassparms.hdr.length = 8 + len;
-	cmd->data.setassparms.hdr.command_code = cmd_code;
-	cmd->data.setassparms.hdr.return_code = 0;
-	cmd->data.setassparms.hdr.seq_no = 0;
-
-	return iob;
-}
-
-static int
-qeth_send_setassparms(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-		      __u16 len, long data,
-		      int (*reply_cb)
-		      (struct qeth_card *,struct qeth_reply *,unsigned long),
-		      void *reply_param)
-{
-	int rc;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,4,"sendassp");
-
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	if (len <= sizeof(__u32))
-		cmd->data.setassparms.data.flags_32bit = (__u32) data;
-	else   /* (len > sizeof(__u32)) */
-		memcpy(&cmd->data.setassparms.data, (void *) data, len);
-
-	rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
-	return rc;
-}
-
-#ifdef CONFIG_QETH_IPV6
-static int
-qeth_send_simple_setassparms_ipv6(struct qeth_card *card,
-				  enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
-
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(trace,4,"simassp6");
-	iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
-				       0, QETH_PROT_IPV6);
-	rc = qeth_send_setassparms(card, iob, 0, 0,
-				   qeth_default_setassparms_cb, NULL);
-	return rc;
-}
-#endif
-
-static int
-qeth_send_simple_setassparms(struct qeth_card *card,
-			     enum qeth_ipa_funcs ipa_func,
-			     __u16 cmd_code, long data)
-{
-	int rc;
-	int length = 0;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(trace,4,"simassp4");
-	if (data)
-		length = sizeof(__u32);
-	iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
-				       length, QETH_PROT_IPV4);
-	rc = qeth_send_setassparms(card, iob, length, data,
-				   qeth_default_setassparms_cb, NULL);
-	return rc;
-}
-
-static int
-qeth_start_ipa_arp_processing(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"ipaarp");
-
-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
-		PRINT_WARN("ARP processing not supported "
-			   "on %s!\n", QETH_CARD_IFNAME(card));
-		return 0;
-	}
-	rc = qeth_send_simple_setassparms(card,IPA_ARP_PROCESSING,
-					  IPA_CMD_ASS_START, 0);
-	if (rc) {
-		PRINT_WARN("Could not start ARP processing "
-			   "assist on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-	}
-	return rc;
-}
-
-static int
-qeth_start_ipa_ip_fragmentation(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"ipaipfrg");
-
-	if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
-		PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
-			   QETH_CARD_IFNAME(card));
-		return  -EOPNOTSUPP;
-	}
-
-	rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
-					  IPA_CMD_ASS_START, 0);
-	if (rc) {
-		PRINT_WARN("Could not start Hardware IP fragmentation "
-			   "assist on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-	} else
-		PRINT_INFO("Hardware IP fragmentation enabled \n");
-	return rc;
-}
-
-static int
-qeth_start_ipa_source_mac(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"stsrcmac");
-
-	if (!card->options.fake_ll)
-		return -EOPNOTSUPP;
-
-	if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
-		PRINT_INFO("Inbound source address not "
-			   "supported on %s\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-
-	rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
-					  IPA_CMD_ASS_START, 0);
-	if (rc)
-		PRINT_WARN("Could not start inbound source "
-			   "assist on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-	return rc;
-}
-
-static int
-qeth_start_ipa_vlan(struct qeth_card *card)
-{
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace,3,"strtvlan");
-
-#ifdef CONFIG_QETH_VLAN
-	if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
-		PRINT_WARN("VLAN not supported on %s\n", QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-
-	rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
-					  IPA_CMD_ASS_START,0);
-	if (rc) {
-		PRINT_WARN("Could not start vlan "
-			   "assist on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-	} else {
-		PRINT_INFO("VLAN enabled \n");
-		card->dev->features |=
-			NETIF_F_HW_VLAN_FILTER |
-			NETIF_F_HW_VLAN_TX |
-			NETIF_F_HW_VLAN_RX;
-	}
-#endif /* QETH_VLAN */
-	return rc;
-}
-
-static int
-qeth_start_ipa_multicast(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"stmcast");
-
-	if (!qeth_is_supported(card, IPA_MULTICASTING)) {
-		PRINT_WARN("Multicast not supported on %s\n",
-			   QETH_CARD_IFNAME(card));
-		return -EOPNOTSUPP;
-	}
-
-	rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
-					  IPA_CMD_ASS_START,0);
-	if (rc) {
-		PRINT_WARN("Could not start multicast "
-			   "assist on %s: rc=%i\n",
-			   QETH_CARD_IFNAME(card), rc);
-	} else {
-		PRINT_INFO("Multicast enabled\n");
-		card->dev->flags |= IFF_MULTICAST;
-	}
-	return rc;
-}
-
-#ifdef CONFIG_QETH_IPV6
-static int
-qeth_softsetup_ipv6(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"softipv6");
-
-	rc = qeth_send_startlan(card, QETH_PROT_IPV6);
-	if (rc) {
-		PRINT_ERR("IPv6 startlan failed on %s\n",
-			  QETH_CARD_IFNAME(card));
-		return rc;
-	}
-	rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
-	if (rc) {
-		PRINT_ERR("IPv6 query ipassist failed on %s\n",
-			  QETH_CARD_IFNAME(card));
-		return rc;
-	}
-	rc = qeth_send_simple_setassparms(card, IPA_IPV6,
-					  IPA_CMD_ASS_START, 3);
-	if (rc) {
-		PRINT_WARN("IPv6 start assist (version 4) failed "
-			   "on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-		return rc;
-	}
-	rc = qeth_send_simple_setassparms_ipv6(card, IPA_IPV6,
-					       IPA_CMD_ASS_START);
-	if (rc) {
-		PRINT_WARN("IPV6 start assist (version 6) failed  "
-			   "on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-		return rc;
-	}
-	rc = qeth_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
-					       IPA_CMD_ASS_START);
-	if (rc) {
-		PRINT_WARN("Could not enable passthrough "
-			   "on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-		return rc;
-	}
-	PRINT_INFO("IPV6 enabled \n");
-	return 0;
-}
-
-#endif
-
-static int
-qeth_start_ipa_ipv6(struct qeth_card *card)
-{
-	int rc = 0;
-#ifdef CONFIG_QETH_IPV6
-	QETH_DBF_TEXT(trace,3,"strtipv6");
-
-	if (!qeth_is_supported(card, IPA_IPV6)) {
-		PRINT_WARN("IPv6 not supported on %s\n",
-			   QETH_CARD_IFNAME(card));
-		return 0;
-	}
-	rc = qeth_softsetup_ipv6(card);
-#endif
-	return rc ;
-}
-
-static int
-qeth_start_ipa_broadcast(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"stbrdcst");
-	card->info.broadcast_capable = 0;
-	if (!qeth_is_supported(card, IPA_FILTERING)) {
-		PRINT_WARN("Broadcast not supported on %s\n",
-			   QETH_CARD_IFNAME(card));
-		rc = -EOPNOTSUPP;
-		goto out;
-	}
-	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
-					  IPA_CMD_ASS_START, 0);
-	if (rc) {
-		PRINT_WARN("Could not enable broadcasting filtering "
-			   "on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-		goto out;
-	}
-
-	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
-					  IPA_CMD_ASS_CONFIGURE, 1);
-	if (rc) {
-		PRINT_WARN("Could not set up broadcast filtering on %s: 0x%x\n",
-			   QETH_CARD_IFNAME(card), rc);
-		goto out;
-	}
-	card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
-	PRINT_INFO("Broadcast enabled \n");
-	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
-					  IPA_CMD_ASS_ENABLE, 1);
-	if (rc) {
-		PRINT_WARN("Could not set up broadcast echo filtering on "
-			   "%s: 0x%x\n", QETH_CARD_IFNAME(card), rc);
-		goto out;
-	}
-	card->info.broadcast_capable = QETH_BROADCAST_WITHOUT_ECHO;
-out:
-	if (card->info.broadcast_capable)
-		card->dev->flags |= IFF_BROADCAST;
-	else
-		card->dev->flags &= ~IFF_BROADCAST;
-	return rc;
-}
-
-static int
-qeth_send_checksum_command(struct qeth_card *card)
-{
-	int rc;
-
-	rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
-					  IPA_CMD_ASS_START, 0);
-	if (rc) {
-		PRINT_WARN("Starting Inbound HW Checksumming failed on %s: "
-			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
-			   QETH_CARD_IFNAME(card), rc);
-		return rc;
-	}
-	rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
-					  IPA_CMD_ASS_ENABLE,
-					  card->info.csum_mask);
-	if (rc) {
-		PRINT_WARN("Enabling Inbound HW Checksumming failed on %s: "
-			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
-			   QETH_CARD_IFNAME(card), rc);
-		return rc;
-	}
-	return 0;
-}
-
-static int
-qeth_start_ipa_checksum(struct qeth_card *card)
-{
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace,3,"strtcsum");
-
-	if (card->options.checksum_type == NO_CHECKSUMMING) {
-		PRINT_WARN("Using no checksumming on %s.\n",
-			   QETH_CARD_IFNAME(card));
-		return 0;
-	}
-	if (card->options.checksum_type == SW_CHECKSUMMING) {
-		PRINT_WARN("Using SW checksumming on %s.\n",
-			   QETH_CARD_IFNAME(card));
-		return 0;
-	}
-	if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) {
-		PRINT_WARN("Inbound HW Checksumming not "
-			   "supported on %s,\ncontinuing "
-			   "using Inbound SW Checksumming\n",
-			   QETH_CARD_IFNAME(card));
-		card->options.checksum_type = SW_CHECKSUMMING;
-		return 0;
-	}
-	rc = qeth_send_checksum_command(card);
-	if (!rc) {
-		PRINT_INFO("HW Checksumming (inbound) enabled \n");
-	}
-	return rc;
-}
-
-static int
-qeth_start_ipa_tso(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"sttso");
-
-	if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
-		PRINT_WARN("Outbound TSO not supported on %s\n",
-			   QETH_CARD_IFNAME(card));
-		rc = -EOPNOTSUPP;
-	} else {
-		rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
-						  IPA_CMD_ASS_START,0);
-		if (rc)
-			PRINT_WARN("Could not start outbound TSO "
-				   "assist on %s: rc=%i\n",
-				   QETH_CARD_IFNAME(card), rc);
-		else
-			PRINT_INFO("Outbound TSO enabled\n");
-	}
-	if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)){
-		card->options.large_send = QETH_LARGE_SEND_NO;
-		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
-						NETIF_F_HW_CSUM);
-	}
-	return rc;
-}
-
-static int
-qeth_start_ipassists(struct qeth_card *card)
-{
-	QETH_DBF_TEXT(trace,3,"strtipas");
-	qeth_start_ipa_arp_processing(card);	/* go on*/
-	qeth_start_ipa_ip_fragmentation(card); 	/* go on*/
-	qeth_start_ipa_source_mac(card);	/* go on*/
-	qeth_start_ipa_vlan(card);		/* go on*/
-	qeth_start_ipa_multicast(card);		/* go on*/
-	qeth_start_ipa_ipv6(card);		/* go on*/
-	qeth_start_ipa_broadcast(card);		/* go on*/
-	qeth_start_ipa_checksum(card);		/* go on*/
-	qeth_start_ipa_tso(card);		/* go on*/
-	return 0;
-}
-
-static int
-qeth_send_setrouting(struct qeth_card *card, enum qeth_routing_types type,
-		     enum qeth_prot_versions prot)
-{
-	int rc;
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(trace,4,"setroutg");
-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	cmd->data.setrtg.type = (type);
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
-	return rc;
-
-}
-
-static void
-qeth_correct_routing_type(struct qeth_card *card, enum qeth_routing_types *type,
-			enum qeth_prot_versions prot)
-{
-	if (card->info.type == QETH_CARD_TYPE_IQD) {
-		switch (*type) {
-		case NO_ROUTER:
-		case PRIMARY_CONNECTOR:
-		case SECONDARY_CONNECTOR:
-		case MULTICAST_ROUTER:
-			return;
-		default:
-			goto out_inval;
-		}
-	} else {
-		switch (*type) {
-		case NO_ROUTER:
-		case PRIMARY_ROUTER:
-		case SECONDARY_ROUTER:
-			return;
-		case MULTICAST_ROUTER:
-			if (qeth_is_ipafunc_supported(card, prot,
-						      IPA_OSA_MC_ROUTER))
-				return;
-		default:
-			goto out_inval;
-		}
-	}
-out_inval:
-	PRINT_WARN("Routing type '%s' not supported for interface %s.\n"
-		   "Router status set to 'no router'.\n",
-		   ((*type == PRIMARY_ROUTER)? "primary router" :
-		    (*type == SECONDARY_ROUTER)? "secondary router" :
-		    (*type == PRIMARY_CONNECTOR)? "primary connector" :
-		    (*type == SECONDARY_CONNECTOR)? "secondary connector" :
-		    (*type == MULTICAST_ROUTER)? "multicast router" :
-		    "unknown"),
-		   card->dev->name);
-	*type = NO_ROUTER;
-}
-
-int
-qeth_setrouting_v4(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(trace,3,"setrtg4");
-
-	qeth_correct_routing_type(card, &card->options.route4.type,
-				  QETH_PROT_IPV4);
-
-	rc = qeth_send_setrouting(card, card->options.route4.type,
-				  QETH_PROT_IPV4);
-	if (rc) {
- 		card->options.route4.type = NO_ROUTER;
-		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
-			   "Type set to 'no router'.\n",
-			   rc, QETH_CARD_IFNAME(card));
-	}
-	return rc;
-}
-
-int
-qeth_setrouting_v6(struct qeth_card *card)
-{
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace,3,"setrtg6");
-#ifdef CONFIG_QETH_IPV6
-
-	if (!qeth_is_supported(card, IPA_IPV6))
-		return 0;
-	qeth_correct_routing_type(card, &card->options.route6.type,
-				  QETH_PROT_IPV6);
-
-	rc = qeth_send_setrouting(card, card->options.route6.type,
-				  QETH_PROT_IPV6);
-	if (rc) {
-	 	card->options.route6.type = NO_ROUTER;
-		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
-			   "Type set to 'no router'.\n",
-			   rc, QETH_CARD_IFNAME(card));
-	}
-#endif
-	return rc;
-}
-
-int
-qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
-{
-	int rc = 0;
-
-	if (card->dev == NULL) {
-		card->options.large_send = type;
-		return 0;
-	}
-	if (card->state == CARD_STATE_UP)
-		netif_tx_disable(card->dev);
-	card->options.large_send = type;
-	switch (card->options.large_send) {
-	case QETH_LARGE_SEND_EDDP:
-		card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
-					NETIF_F_HW_CSUM;
-		break;
-	case QETH_LARGE_SEND_TSO:
-		if (qeth_is_supported(card, IPA_OUTBOUND_TSO)){
-			card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
-						NETIF_F_HW_CSUM;
-		} else {
-			PRINT_WARN("TSO not supported on %s. "
-				   "large_send set to 'no'.\n",
-				   card->dev->name);
-			card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
-						NETIF_F_HW_CSUM);
-			card->options.large_send = QETH_LARGE_SEND_NO;
-			rc = -EOPNOTSUPP;
-		}
-		break;
-	default: /* includes QETH_LARGE_SEND_NO */
-		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
-					NETIF_F_HW_CSUM);
-		break;
-	}
-	if (card->state == CARD_STATE_UP)
-		netif_wake_queue(card->dev);
-	return rc;
-}
-
-/*
- * softsetup card: init IPA stuff
- */
-static int
-qeth_softsetup_card(struct qeth_card *card)
-{
-	int rc;
-
-	QETH_DBF_TEXT(setup, 2, "softsetp");
-
-	if ((rc = qeth_send_startlan(card, QETH_PROT_IPV4))){
-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-		if (rc == 0xe080){
-			PRINT_WARN("LAN on card %s if offline! "
-				   "Waiting for STARTLAN from card.\n",
-				   CARD_BUS_ID(card));
-			card->lan_online = 0;
-		}
-		return rc;
-	} else
-		card->lan_online = 1;
-	if (card->info.type==QETH_CARD_TYPE_OSN)
-		goto out;
-	qeth_set_large_send(card, card->options.large_send);
-	if (card->options.layer2) {
-		card->dev->features |=
-			NETIF_F_HW_VLAN_FILTER |
-			NETIF_F_HW_VLAN_TX |
-			NETIF_F_HW_VLAN_RX;
-		card->dev->flags|=IFF_MULTICAST|IFF_BROADCAST;
-		card->info.broadcast_capable=1;
-		if ((rc = qeth_layer2_initialize(card))) {
-			QETH_DBF_TEXT_(setup, 2, "L2err%d", rc);
-			return rc;
-		}
-#ifdef CONFIG_QETH_VLAN
-		qeth_layer2_process_vlans(card, 0);
-#endif
-		goto out;
-	}
-	if ((rc = qeth_setadapter_parms(card)))
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-	if ((rc = qeth_start_ipassists(card)))
-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-	if ((rc = qeth_setrouting_v4(card)))
-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
-	if ((rc = qeth_setrouting_v6(card)))
-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-out:
-	netif_tx_disable(card->dev);
-	return 0;
-}
-
-#ifdef CONFIG_QETH_IPV6
-static int
-qeth_get_unique_id_cb(struct qeth_card *card, struct qeth_reply *reply,
-		      unsigned long data)
-{
-	struct qeth_ipa_cmd *cmd;
-
-	cmd = (struct qeth_ipa_cmd *) data;
-	if (cmd->hdr.return_code == 0)
-		card->info.unique_id = *((__u16 *)
-				&cmd->data.create_destroy_addr.unique_id[6]);
-	else {
-		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
-					UNIQUE_ID_NOT_BY_CARD;
-		PRINT_WARN("couldn't get a unique id from the card on device "
-			   "%s (result=x%x), using default id. ipv6 "
-			   "autoconfig on other lpars may lead to duplicate "
-			   "ip addresses. please use manually "
-			   "configured ones.\n",
-			   CARD_BUS_ID(card), cmd->hdr.return_code);
-	}
-	return 0;
-}
-#endif
-
-static int
-qeth_put_unique_id(struct qeth_card *card)
-{
-
-	int rc = 0;
-#ifdef CONFIG_QETH_IPV6
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(trace,2,"puniqeid");
-
-	if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
-	    	UNIQUE_ID_NOT_BY_CARD)
-		return -1;
-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
-				     QETH_PROT_IPV6);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
-		            card->info.unique_id;
-	memcpy(&cmd->data.create_destroy_addr.unique_id[0],
-	       card->dev->dev_addr, OSA_ADDR_LEN);
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-#else
-	card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
-				UNIQUE_ID_NOT_BY_CARD;
-#endif
-	return rc;
-}
-
-/**
- * Clear IP List
- */
-static void
-qeth_clear_ip_list(struct qeth_card *card, int clean, int recover)
-{
-	struct qeth_ipaddr *addr, *tmp;
-	unsigned long flags;
-
-	QETH_DBF_TEXT(trace,4,"clearip");
-	spin_lock_irqsave(&card->ip_lock, flags);
-	/* clear todo list */
-	list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry){
-		list_del(&addr->entry);
-		kfree(addr);
-	}
-
-	while (!list_empty(&card->ip_list)) {
-		addr = list_entry(card->ip_list.next,
-				  struct qeth_ipaddr, entry);
-		list_del_init(&addr->entry);
-		if (clean) {
-			spin_unlock_irqrestore(&card->ip_lock, flags);
-			qeth_deregister_addr_entry(card, addr);
-			spin_lock_irqsave(&card->ip_lock, flags);
-		}
-		if (!recover || addr->is_multicast) {
-			kfree(addr);
-			continue;
-		}
-		list_add_tail(&addr->entry, card->ip_tbd_list);
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-}
-
-static void
-qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
-			 int clear_start_mask)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->thread_mask_lock, flags);
-	card->thread_allowed_mask = threads;
-	if (clear_start_mask)
-		card->thread_start_mask &= threads;
-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-	wake_up(&card->wait_q);
-}
-
-static int
-qeth_threads_running(struct qeth_card *card, unsigned long threads)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	spin_lock_irqsave(&card->thread_mask_lock, flags);
-	rc = (card->thread_running_mask & threads);
-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-	return rc;
-}
-
-static int
-qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
-{
-	return wait_event_interruptible(card->wait_q,
-			qeth_threads_running(card, threads) == 0);
-}
-
-static int
-qeth_stop_card(struct qeth_card *card, int recovery_mode)
-{
-	int rc = 0;
-
-	QETH_DBF_TEXT(setup ,2,"stopcard");
-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
-
-	qeth_set_allowed_threads(card, 0, 1);
-	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
-		return -ERESTARTSYS;
-	if (card->read.state == CH_STATE_UP &&
-	    card->write.state == CH_STATE_UP &&
-	    (card->state == CARD_STATE_UP)) {
-		if (recovery_mode &&
-		    card->info.type != QETH_CARD_TYPE_OSN) {
-			qeth_stop(card->dev);
-		} else {
-			rtnl_lock();
-			dev_close(card->dev);
-			rtnl_unlock();
-		}
-		if (!card->use_hard_stop) {
-			__u8 *mac = &card->dev->dev_addr[0];
-			rc = qeth_layer2_send_delmac(card, mac);
-			QETH_DBF_TEXT_(setup, 2, "Lerr%d", rc);
-			if ((rc = qeth_send_stoplan(card)))
-				QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-		}
-		card->state = CARD_STATE_SOFTSETUP;
-	}
-	if (card->state == CARD_STATE_SOFTSETUP) {
-#ifdef CONFIG_QETH_VLAN
-		if (card->options.layer2)
-			qeth_layer2_process_vlans(card, 1);
-#endif
-		qeth_clear_ip_list(card, !card->use_hard_stop, 1);
-		qeth_clear_ipacmd_list(card);
-		card->state = CARD_STATE_HARDSETUP;
-	}
-	if (card->state == CARD_STATE_HARDSETUP) {
-		if ((!card->use_hard_stop) &&
-		    (!card->options.layer2))
-			if ((rc = qeth_put_unique_id(card)))
-				QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		qeth_qdio_clear_card(card, 0);
-		qeth_clear_qdio_buffers(card);
-		qeth_clear_working_pool_list(card);
-		card->state = CARD_STATE_DOWN;
-	}
-	if (card->state == CARD_STATE_DOWN) {
-		qeth_clear_cmd_buffers(&card->read);
-		qeth_clear_cmd_buffers(&card->write);
-	}
-	card->use_hard_stop = 0;
-	return rc;
-}
-
-
-static int
-qeth_get_unique_id(struct qeth_card *card)
-{
-	int rc = 0;
-#ifdef CONFIG_QETH_IPV6
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_DBF_TEXT(setup, 2, "guniqeid");
-
-	if (!qeth_is_supported(card,IPA_IPV6)) {
-		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
-					UNIQUE_ID_NOT_BY_CARD;
-		return 0;
-	}
-
-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
-				     QETH_PROT_IPV6);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
-		            card->info.unique_id;
-
-	rc = qeth_send_ipa_cmd(card, iob, qeth_get_unique_id_cb, NULL);
-#else
-	card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
-				UNIQUE_ID_NOT_BY_CARD;
-#endif
-	return rc;
-}
-static void
-qeth_print_status_with_portname(struct qeth_card *card)
-{
-	char dbf_text[15];
-	int i;
-
-	sprintf(dbf_text, "%s", card->info.portname + 1);
-	for (i = 0; i < 8; i++)
-		dbf_text[i] =
-			(char) _ebcasc[(__u8) dbf_text[i]];
-	dbf_text[8] = 0;
-	printk("qeth: Device %s/%s/%s is a%s card%s%s%s\n"
-	       "with link type %s (portname: %s)\n",
-	       CARD_RDEV_ID(card),
-	       CARD_WDEV_ID(card),
-	       CARD_DDEV_ID(card),
-	       qeth_get_cardname(card),
-	       (card->info.mcl_level[0]) ? " (level: " : "",
-	       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
-	       (card->info.mcl_level[0]) ? ")" : "",
-	       qeth_get_cardname_short(card),
-	       dbf_text);
-
-}
-
-static void
-qeth_print_status_no_portname(struct qeth_card *card)
-{
-	if (card->info.portname[0])
-		printk("qeth: Device %s/%s/%s is a%s "
-		       "card%s%s%s\nwith link type %s "
-		       "(no portname needed by interface).\n",
-		       CARD_RDEV_ID(card),
-		       CARD_WDEV_ID(card),
-		       CARD_DDEV_ID(card),
-		       qeth_get_cardname(card),
-		       (card->info.mcl_level[0]) ? " (level: " : "",
-		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
-		       (card->info.mcl_level[0]) ? ")" : "",
-		       qeth_get_cardname_short(card));
-	else
-		printk("qeth: Device %s/%s/%s is a%s "
-		       "card%s%s%s\nwith link type %s.\n",
-		       CARD_RDEV_ID(card),
-		       CARD_WDEV_ID(card),
-		       CARD_DDEV_ID(card),
-		       qeth_get_cardname(card),
-		       (card->info.mcl_level[0]) ? " (level: " : "",
-		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
-		       (card->info.mcl_level[0]) ? ")" : "",
-		       qeth_get_cardname_short(card));
-}
-
-static void
-qeth_print_status_message(struct qeth_card *card)
-{
-	switch (card->info.type) {
-	case QETH_CARD_TYPE_OSAE:
-		/* VM will use a non-zero first character
-		 * to indicate a HiperSockets like reporting
-		 * of the level OSA sets the first character to zero
-		 * */
-		if (!card->info.mcl_level[0]) {
-			sprintf(card->info.mcl_level,"%02x%02x",
-				card->info.mcl_level[2],
-				card->info.mcl_level[3]);
-
-			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
-			break;
-		}
-		/* fallthrough */
-	case QETH_CARD_TYPE_IQD:
-		if (card->info.guestlan) {
-			card->info.mcl_level[0] = (char) _ebcasc[(__u8)
-				card->info.mcl_level[0]];
-			card->info.mcl_level[1] = (char) _ebcasc[(__u8)
-				card->info.mcl_level[1]];
-			card->info.mcl_level[2] = (char) _ebcasc[(__u8)
-				card->info.mcl_level[2]];
-			card->info.mcl_level[3] = (char) _ebcasc[(__u8)
-				card->info.mcl_level[3]];
-			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
-		}
-		break;
-	default:
-		memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
-	}
-	if (card->info.portname_required)
-		qeth_print_status_with_portname(card);
-	else
-		qeth_print_status_no_portname(card);
-}
-
-static int
-qeth_register_netdev(struct qeth_card *card)
-{
-	QETH_DBF_TEXT(setup, 3, "regnetd");
-	if (card->dev->reg_state != NETREG_UNINITIALIZED)
-		return 0;
-	/* sysfs magic */
-	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
-	return register_netdev(card->dev);
-}
-
-static void
-qeth_start_again(struct qeth_card *card, int recovery_mode)
-{
-	QETH_DBF_TEXT(setup ,2, "startag");
-
-	if (recovery_mode &&
-	    card->info.type != QETH_CARD_TYPE_OSN) {
-		qeth_open(card->dev);
-	} else {
-		rtnl_lock();
-		dev_open(card->dev);
-		rtnl_unlock();
-	}
-	/* this also sets saved unicast addresses */
-	qeth_set_multicast_list(card->dev);
-}
-
-
-/* Layer 2 specific stuff */
-#define IGNORE_PARAM_EQ(option,value,reset_value,msg) \
-        if (card->options.option == value) { \
-                PRINT_ERR("%s not supported with layer 2 " \
-                          "functionality, ignoring option on read" \
-			  "channel device %s .\n",msg,CARD_RDEV_ID(card)); \
-                card->options.option = reset_value; \
-        }
-#define IGNORE_PARAM_NEQ(option,value,reset_value,msg) \
-        if (card->options.option != value) { \
-                PRINT_ERR("%s not supported with layer 2 " \
-                          "functionality, ignoring option on read" \
-			  "channel device %s .\n",msg,CARD_RDEV_ID(card)); \
-                card->options.option = reset_value; \
-        }
-
-
-static void qeth_make_parameters_consistent(struct qeth_card *card)
-{
-
-	if (card->options.layer2 == 0)
-		return;
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		return;
-	if (card->info.type == QETH_CARD_TYPE_IQD) {
-       		PRINT_ERR("Device %s does not support layer 2 functionality." \
-	               	  " Ignoring layer2 option.\n",CARD_BUS_ID(card));
-       		card->options.layer2 = 0;
-		return;
-	}
-       	IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
-               	         "Routing options are");
-#ifdef CONFIG_QETH_IPV6
-       	IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
-               	         "Routing options are");
-#endif
-       	IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
-                       	QETH_CHECKSUM_DEFAULT,
-               	        "Checksumming options are");
-       	IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
-                       	 QETH_TR_BROADCAST_ALLRINGS,
-               	         "Broadcast mode options are");
-       	IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
-                       	 QETH_TR_MACADDR_NONCANONICAL,
-               	         "Canonical MAC addr options are");
-       	IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
-			 "Broadcast faking options are");
-       	IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
-       	                 DEFAULT_ADD_HHLEN,"Option add_hhlen is");
-        IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
-}
-
-
-static int
-__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
-{
-	struct qeth_card *card = gdev->dev.driver_data;
-	int rc = 0;
-	enum qeth_card_states recover_flag;
-
-	BUG_ON(!card);
-	QETH_DBF_TEXT(setup ,2, "setonlin");
-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
-
-	qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
-	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)){
-		PRINT_WARN("set_online of card %s interrupted by user!\n",
-			   CARD_BUS_ID(card));
-		return -ERESTARTSYS;
-	}
-
-	recover_flag = card->state;
-	if ((rc = ccw_device_set_online(CARD_RDEV(card))) ||
-	    (rc = ccw_device_set_online(CARD_WDEV(card))) ||
-	    (rc = ccw_device_set_online(CARD_DDEV(card)))){
-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-		return -EIO;
-	}
-
-	qeth_make_parameters_consistent(card);
-
-	if ((rc = qeth_hardsetup_card(card))){
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		goto out_remove;
-	}
-	card->state = CARD_STATE_HARDSETUP;
-
-	if (!(rc = qeth_query_ipassists(card,QETH_PROT_IPV4)))
-		rc = qeth_get_unique_id(card);
-
-	if (rc && card->options.layer2 == 0) {
-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-		goto out_remove;
-	}
-	qeth_print_status_message(card);
-	if ((rc = qeth_register_netdev(card))){
-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
-		goto out_remove;
-	}
-	if ((rc = qeth_softsetup_card(card))){
-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-		goto out_remove;
-	}
-
-	if ((rc = qeth_init_qdio_queues(card))){
-		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
-		goto out_remove;
-	}
-	card->state = CARD_STATE_SOFTSETUP;
-	netif_carrier_on(card->dev);
-
-	qeth_set_allowed_threads(card, 0xffffffff, 0);
-	if (recover_flag == CARD_STATE_RECOVER)
-		qeth_start_again(card, recovery_mode);
-	qeth_notify_processes();
-	return 0;
-out_remove:
-	card->use_hard_stop = 1;
-	qeth_stop_card(card, 0);
-	ccw_device_set_offline(CARD_DDEV(card));
-	ccw_device_set_offline(CARD_WDEV(card));
-	ccw_device_set_offline(CARD_RDEV(card));
-	if (recover_flag == CARD_STATE_RECOVER)
-		card->state = CARD_STATE_RECOVER;
-	else
-		card->state = CARD_STATE_DOWN;
-	return -ENODEV;
-}
-
-static int
-qeth_set_online(struct ccwgroup_device *gdev)
-{
-	return __qeth_set_online(gdev, 0);
-}
-
-static struct ccw_device_id qeth_ids[] = {
-	{CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
-	{CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
-	{CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
-	{},
-};
-MODULE_DEVICE_TABLE(ccw, qeth_ids);
-
-struct device *qeth_root_dev = NULL;
-
-struct ccwgroup_driver qeth_ccwgroup_driver = {
-	.owner = THIS_MODULE,
-	.name = "qeth",
-	.driver_id = 0xD8C5E3C8,
-	.probe = qeth_probe_device,
-	.remove = qeth_remove_device,
-	.set_online = qeth_set_online,
-	.set_offline = qeth_set_offline,
-};
-
-struct ccw_driver qeth_ccw_driver = {
-	.name = "qeth",
-	.ids = qeth_ids,
-	.probe = ccwgroup_probe_ccwdev,
-	.remove = ccwgroup_remove_ccwdev,
-};
-
-
-static void
-qeth_unregister_dbf_views(void)
-{
-	if (qeth_dbf_setup)
-		debug_unregister(qeth_dbf_setup);
-	if (qeth_dbf_qerr)
-		debug_unregister(qeth_dbf_qerr);
-	if (qeth_dbf_sense)
-		debug_unregister(qeth_dbf_sense);
-	if (qeth_dbf_misc)
-		debug_unregister(qeth_dbf_misc);
-	if (qeth_dbf_data)
-		debug_unregister(qeth_dbf_data);
-	if (qeth_dbf_control)
-		debug_unregister(qeth_dbf_control);
-	if (qeth_dbf_trace)
-		debug_unregister(qeth_dbf_trace);
-}
-static int
-qeth_register_dbf_views(void)
-{
-	qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
-					QETH_DBF_SETUP_PAGES,
-					QETH_DBF_SETUP_NR_AREAS,
-					QETH_DBF_SETUP_LEN);
-	qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
-				       QETH_DBF_MISC_PAGES,
-				       QETH_DBF_MISC_NR_AREAS,
-				       QETH_DBF_MISC_LEN);
-	qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
-				       QETH_DBF_DATA_PAGES,
-				       QETH_DBF_DATA_NR_AREAS,
-				       QETH_DBF_DATA_LEN);
-	qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
-					  QETH_DBF_CONTROL_PAGES,
-					  QETH_DBF_CONTROL_NR_AREAS,
-					  QETH_DBF_CONTROL_LEN);
-	qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
-					QETH_DBF_SENSE_PAGES,
-					QETH_DBF_SENSE_NR_AREAS,
-					QETH_DBF_SENSE_LEN);
-	qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
-				       QETH_DBF_QERR_PAGES,
-				       QETH_DBF_QERR_NR_AREAS,
-				       QETH_DBF_QERR_LEN);
-	qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
-					QETH_DBF_TRACE_PAGES,
-					QETH_DBF_TRACE_NR_AREAS,
-					QETH_DBF_TRACE_LEN);
-
-	if ((qeth_dbf_setup == NULL) || (qeth_dbf_misc == NULL)    ||
-	    (qeth_dbf_data == NULL)  || (qeth_dbf_control == NULL) ||
-	    (qeth_dbf_sense == NULL) || (qeth_dbf_qerr == NULL)    ||
-	    (qeth_dbf_trace == NULL)) {
-		qeth_unregister_dbf_views();
-		return -ENOMEM;
-	}
-	debug_register_view(qeth_dbf_setup, &debug_hex_ascii_view);
-	debug_set_level(qeth_dbf_setup, QETH_DBF_SETUP_LEVEL);
-
-	debug_register_view(qeth_dbf_misc, &debug_hex_ascii_view);
-	debug_set_level(qeth_dbf_misc, QETH_DBF_MISC_LEVEL);
-
-	debug_register_view(qeth_dbf_data, &debug_hex_ascii_view);
-	debug_set_level(qeth_dbf_data, QETH_DBF_DATA_LEVEL);
-
-	debug_register_view(qeth_dbf_control, &debug_hex_ascii_view);
-	debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL);
-
-	debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view);
-	debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL);
-
-	debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view);
-	debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL);
-
-	debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view);
-	debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL);
-
-	return 0;
-}
-
-#ifdef CONFIG_QETH_IPV6
-extern struct neigh_table arp_tbl;
-static struct neigh_ops *arp_direct_ops;
-static int (*qeth_old_arp_constructor) (struct neighbour *);
-
-static struct neigh_ops arp_direct_ops_template = {
-	.family = AF_INET,
-	.solicit = NULL,
-	.error_report = NULL,
-	.output = dev_queue_xmit,
-	.connected_output = dev_queue_xmit,
-	.hh_output = dev_queue_xmit,
-	.queue_xmit = dev_queue_xmit
-};
-
-static int
-qeth_arp_constructor(struct neighbour *neigh)
-{
-	struct net_device *dev = neigh->dev;
-	struct in_device *in_dev;
-	struct neigh_parms *parms;
-	struct qeth_card *card;
-
-	card = qeth_get_card_from_dev(dev);
-	if (card == NULL)
-		goto out;
-	if((card->options.layer2) ||
-	   (card->dev->header_ops == &qeth_fake_ops))
-		goto out;
-
-	rcu_read_lock();
-	in_dev = __in_dev_get_rcu(dev);
-	if (in_dev == NULL) {
-		rcu_read_unlock();
-		return -EINVAL;
-	}
-
-	parms = in_dev->arp_parms;
-	__neigh_parms_put(neigh->parms);
-	neigh->parms = neigh_parms_clone(parms);
-	rcu_read_unlock();
-
-	neigh->type = inet_addr_type(&init_net, *(__be32 *) neigh->primary_key);
-	neigh->nud_state = NUD_NOARP;
-	neigh->ops = arp_direct_ops;
-	neigh->output = neigh->ops->queue_xmit;
-	return 0;
-out:
-	return qeth_old_arp_constructor(neigh);
-}
-#endif  /*CONFIG_QETH_IPV6*/
-
-/*
- * IP address takeover related functions
- */
-static void
-qeth_clear_ipato_list(struct qeth_card *card)
-{
-	struct qeth_ipato_entry *ipatoe, *tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->ip_lock, flags);
-	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
-		list_del(&ipatoe->entry);
-		kfree(ipatoe);
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-}
-
-int
-qeth_add_ipato_entry(struct qeth_card *card, struct qeth_ipato_entry *new)
-{
-	struct qeth_ipato_entry *ipatoe;
-	unsigned long flags;
-	int rc = 0;
-
-	QETH_DBF_TEXT(trace, 2, "addipato");
-	spin_lock_irqsave(&card->ip_lock, flags);
-	list_for_each_entry(ipatoe, &card->ipato.entries, entry){
-		if (ipatoe->proto != new->proto)
-			continue;
-		if (!memcmp(ipatoe->addr, new->addr,
-			    (ipatoe->proto == QETH_PROT_IPV4)? 4:16) &&
-		    (ipatoe->mask_bits == new->mask_bits)){
-			PRINT_WARN("ipato entry already exists!\n");
-			rc = -EEXIST;
-			break;
-		}
-	}
-	if (!rc) {
-		list_add_tail(&new->entry, &card->ipato.entries);
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	return rc;
-}
-
-void
-qeth_del_ipato_entry(struct qeth_card *card, enum qeth_prot_versions proto,
-		     u8 *addr, int mask_bits)
-{
-	struct qeth_ipato_entry *ipatoe, *tmp;
-	unsigned long flags;
-
-	QETH_DBF_TEXT(trace, 2, "delipato");
-	spin_lock_irqsave(&card->ip_lock, flags);
-	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry){
-		if (ipatoe->proto != proto)
-			continue;
-		if (!memcmp(ipatoe->addr, addr,
-			    (proto == QETH_PROT_IPV4)? 4:16) &&
-		    (ipatoe->mask_bits == mask_bits)){
-			list_del(&ipatoe->entry);
-			kfree(ipatoe);
-		}
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-}
-
-static void
-qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
-{
-	int i, j;
-	u8 octet;
-
-	for (i = 0; i < len; ++i){
-		octet = addr[i];
-		for (j = 7; j >= 0; --j){
-			bits[i*8 + j] = octet & 1;
-			octet >>= 1;
-		}
-	}
-}
-
-static int
-qeth_is_addr_covered_by_ipato(struct qeth_card *card, struct qeth_ipaddr *addr)
-{
-	struct qeth_ipato_entry *ipatoe;
-	u8 addr_bits[128] = {0, };
-	u8 ipatoe_bits[128] = {0, };
-	int rc = 0;
-
-	if (!card->ipato.enabled)
-		return 0;
-
-	qeth_convert_addr_to_bits((u8 *) &addr->u, addr_bits,
-				  (addr->proto == QETH_PROT_IPV4)? 4:16);
-	list_for_each_entry(ipatoe, &card->ipato.entries, entry){
-		if (addr->proto != ipatoe->proto)
-			continue;
-		qeth_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
-					  (ipatoe->proto==QETH_PROT_IPV4) ?
-					  4:16);
-		if (addr->proto == QETH_PROT_IPV4)
-			rc = !memcmp(addr_bits, ipatoe_bits,
-				     min(32, ipatoe->mask_bits));
-		else
-			rc = !memcmp(addr_bits, ipatoe_bits,
-				     min(128, ipatoe->mask_bits));
-		if (rc)
-			break;
-	}
-	/* invert? */
-	if ((addr->proto == QETH_PROT_IPV4) && card->ipato.invert4)
-		rc = !rc;
-	else if ((addr->proto == QETH_PROT_IPV6) && card->ipato.invert6)
-		rc = !rc;
-
-	return rc;
-}
-
-/*
- * VIPA related functions
- */
-int
-qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
-	      const u8 *addr)
-{
-	struct qeth_ipaddr *ipaddr;
-	unsigned long flags;
-	int rc = 0;
-
-	ipaddr = qeth_get_addr_buffer(proto);
-	if (ipaddr){
-		if (proto == QETH_PROT_IPV4){
-			QETH_DBF_TEXT(trace, 2, "addvipa4");
-			memcpy(&ipaddr->u.a4.addr, addr, 4);
-			ipaddr->u.a4.mask = 0;
-#ifdef CONFIG_QETH_IPV6
-		} else if (proto == QETH_PROT_IPV6){
-			QETH_DBF_TEXT(trace, 2, "addvipa6");
-			memcpy(&ipaddr->u.a6.addr, addr, 16);
-			ipaddr->u.a6.pfxlen = 0;
-#endif
-		}
-		ipaddr->type = QETH_IP_TYPE_VIPA;
-		ipaddr->set_flags = QETH_IPA_SETIP_VIPA_FLAG;
-		ipaddr->del_flags = QETH_IPA_DELIP_VIPA_FLAG;
-	} else
-		return -ENOMEM;
-	spin_lock_irqsave(&card->ip_lock, flags);
-	if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
-	    __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
-		rc = -EEXIST;
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	if (rc){
-		PRINT_WARN("Cannot add VIPA. Address already exists!\n");
-		return rc;
-	}
-	if (!qeth_add_ip(card, ipaddr))
-		kfree(ipaddr);
-	qeth_set_ip_addr_list(card);
-	return rc;
-}
-
-void
-qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
-	      const u8 *addr)
-{
-	struct qeth_ipaddr *ipaddr;
-
-	ipaddr = qeth_get_addr_buffer(proto);
-	if (ipaddr){
-		if (proto == QETH_PROT_IPV4){
-			QETH_DBF_TEXT(trace, 2, "delvipa4");
-			memcpy(&ipaddr->u.a4.addr, addr, 4);
-			ipaddr->u.a4.mask = 0;
-#ifdef CONFIG_QETH_IPV6
-		} else if (proto == QETH_PROT_IPV6){
-			QETH_DBF_TEXT(trace, 2, "delvipa6");
-			memcpy(&ipaddr->u.a6.addr, addr, 16);
-			ipaddr->u.a6.pfxlen = 0;
-#endif
-		}
-		ipaddr->type = QETH_IP_TYPE_VIPA;
-	} else
-		return;
-	if (!qeth_delete_ip(card, ipaddr))
-		kfree(ipaddr);
-	qeth_set_ip_addr_list(card);
-}
-
-/*
- * proxy ARP related functions
- */
-int
-qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
-	      const u8 *addr)
-{
-	struct qeth_ipaddr *ipaddr;
-	unsigned long flags;
-	int rc = 0;
-
-	ipaddr = qeth_get_addr_buffer(proto);
-	if (ipaddr){
-		if (proto == QETH_PROT_IPV4){
-			QETH_DBF_TEXT(trace, 2, "addrxip4");
-			memcpy(&ipaddr->u.a4.addr, addr, 4);
-			ipaddr->u.a4.mask = 0;
-#ifdef CONFIG_QETH_IPV6
-		} else if (proto == QETH_PROT_IPV6){
-			QETH_DBF_TEXT(trace, 2, "addrxip6");
-			memcpy(&ipaddr->u.a6.addr, addr, 16);
-			ipaddr->u.a6.pfxlen = 0;
-#endif
-		}
-		ipaddr->type = QETH_IP_TYPE_RXIP;
-		ipaddr->set_flags = QETH_IPA_SETIP_TAKEOVER_FLAG;
-		ipaddr->del_flags = 0;
-	} else
-		return -ENOMEM;
-	spin_lock_irqsave(&card->ip_lock, flags);
-	if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
-	    __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
-		rc = -EEXIST;
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	if (rc){
-		PRINT_WARN("Cannot add RXIP. Address already exists!\n");
-		return rc;
-	}
-	if (!qeth_add_ip(card, ipaddr))
-		kfree(ipaddr);
-	qeth_set_ip_addr_list(card);
-	return 0;
-}
-
-void
-qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
-	      const u8 *addr)
-{
-	struct qeth_ipaddr *ipaddr;
-
-	ipaddr = qeth_get_addr_buffer(proto);
-	if (ipaddr){
-		if (proto == QETH_PROT_IPV4){
-			QETH_DBF_TEXT(trace, 2, "addrxip4");
-			memcpy(&ipaddr->u.a4.addr, addr, 4);
-			ipaddr->u.a4.mask = 0;
-#ifdef CONFIG_QETH_IPV6
-		} else if (proto == QETH_PROT_IPV6){
-			QETH_DBF_TEXT(trace, 2, "addrxip6");
-			memcpy(&ipaddr->u.a6.addr, addr, 16);
-			ipaddr->u.a6.pfxlen = 0;
-#endif
-		}
-		ipaddr->type = QETH_IP_TYPE_RXIP;
-	} else
-		return;
-	if (!qeth_delete_ip(card, ipaddr))
-		kfree(ipaddr);
-	qeth_set_ip_addr_list(card);
-}
-
-/**
- * IP event handler
- */
-static int
-qeth_ip_event(struct notifier_block *this,
-	      unsigned long event,void *ptr)
-{
-	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
-	struct net_device *dev =(struct net_device *) ifa->ifa_dev->dev;
-	struct qeth_ipaddr *addr;
-	struct qeth_card *card;
-
-	if (dev->nd_net != &init_net)
-		return NOTIFY_DONE;
-
-	QETH_DBF_TEXT(trace,3,"ipevent");
-	card = qeth_get_card_from_dev(dev);
-	if (!card)
-		return NOTIFY_DONE;
-	if (card->options.layer2)
-		return NOTIFY_DONE;
-
-	addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
-	if (addr != NULL) {
-		addr->u.a4.addr = ifa->ifa_address;
-		addr->u.a4.mask = ifa->ifa_mask;
-		addr->type = QETH_IP_TYPE_NORMAL;
-	} else
-		goto out;
-
-	switch(event) {
-	case NETDEV_UP:
-		if (!qeth_add_ip(card, addr))
-			kfree(addr);
-		break;
-	case NETDEV_DOWN:
-		if (!qeth_delete_ip(card, addr))
-			kfree(addr);
-		break;
-	default:
-		break;
-	}
-	qeth_set_ip_addr_list(card);
-out:
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block qeth_ip_notifier = {
-	qeth_ip_event,
-	NULL,
-};
-
-#ifdef CONFIG_QETH_IPV6
-/**
- * IPv6 event handler
- */
-static int
-qeth_ip6_event(struct notifier_block *this,
-	      unsigned long event,void *ptr)
-{
-
-	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
-	struct net_device *dev = (struct net_device *)ifa->idev->dev;
-	struct qeth_ipaddr *addr;
-	struct qeth_card *card;
-
-	QETH_DBF_TEXT(trace,3,"ip6event");
-
-	card = qeth_get_card_from_dev(dev);
-	if (!card)
-		return NOTIFY_DONE;
-	if (!qeth_is_supported(card, IPA_IPV6))
-		return NOTIFY_DONE;
-
-	addr = qeth_get_addr_buffer(QETH_PROT_IPV6);
-	if (addr != NULL) {
-		memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr));
-		addr->u.a6.pfxlen = ifa->prefix_len;
-		addr->type = QETH_IP_TYPE_NORMAL;
-	} else
-		goto out;
-
-	switch(event) {
-	case NETDEV_UP:
-		if (!qeth_add_ip(card, addr))
-			kfree(addr);
-		break;
-	case NETDEV_DOWN:
-		if (!qeth_delete_ip(card, addr))
-			kfree(addr);
-		break;
-	default:
-		break;
-	}
-	qeth_set_ip_addr_list(card);
-out:
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block qeth_ip6_notifier = {
-	qeth_ip6_event,
-	NULL,
-};
-#endif
-
-static int
-__qeth_reboot_event_card(struct device *dev, void *data)
-{
-	struct qeth_card *card;
-
-	card = (struct qeth_card *) dev->driver_data;
-	qeth_clear_ip_list(card, 0, 0);
-	qeth_qdio_clear_card(card, 0);
-	qeth_clear_qdio_buffers(card);
-	return 0;
-}
-
-static int
-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
-	int ret;
-
-	ret = driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
-				     __qeth_reboot_event_card);
-	return ret ? NOTIFY_BAD : NOTIFY_DONE;
-}
-
-
-static struct notifier_block qeth_reboot_notifier = {
-	qeth_reboot_event,
-	NULL,
-};
-
-static int
-qeth_register_notifiers(void)
-{
-        int r;
-
-	QETH_DBF_TEXT(trace,5,"regnotif");
-	if ((r = register_reboot_notifier(&qeth_reboot_notifier)))
-		return r;
-	if ((r = register_inetaddr_notifier(&qeth_ip_notifier)))
-		goto out_reboot;
-#ifdef CONFIG_QETH_IPV6
-	if ((r = register_inet6addr_notifier(&qeth_ip6_notifier)))
-		goto out_ipv4;
-#endif
-	return 0;
-
-#ifdef CONFIG_QETH_IPV6
-out_ipv4:
-	unregister_inetaddr_notifier(&qeth_ip_notifier);
-#endif
-out_reboot:
-	unregister_reboot_notifier(&qeth_reboot_notifier);
-	return r;
-}
-
-/**
- * unregister all event notifiers
- */
-static void
-qeth_unregister_notifiers(void)
-{
-
-	QETH_DBF_TEXT(trace,5,"unregnot");
-	BUG_ON(unregister_reboot_notifier(&qeth_reboot_notifier));
-	BUG_ON(unregister_inetaddr_notifier(&qeth_ip_notifier));
-#ifdef CONFIG_QETH_IPV6
-	BUG_ON(unregister_inet6addr_notifier(&qeth_ip6_notifier));
-#endif /* QETH_IPV6 */
-
-}
-
-#ifdef CONFIG_QETH_IPV6
-static int
-qeth_ipv6_init(void)
-{
-	qeth_old_arp_constructor = arp_tbl.constructor;
-	write_lock_bh(&arp_tbl.lock);
-	arp_tbl.constructor = qeth_arp_constructor;
-	write_unlock_bh(&arp_tbl.lock);
-
-	arp_direct_ops = (struct neigh_ops*)
-		kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
-	if (!arp_direct_ops)
-		return -ENOMEM;
-
-	memcpy(arp_direct_ops, &arp_direct_ops_template,
-	       sizeof(struct neigh_ops));
-
-	return 0;
-}
-
-static void
-qeth_ipv6_uninit(void)
-{
-	write_lock_bh(&arp_tbl.lock);
-	arp_tbl.constructor = qeth_old_arp_constructor;
-	write_unlock_bh(&arp_tbl.lock);
-	kfree(arp_direct_ops);
-}
-#endif /* CONFIG_QETH_IPV6 */
-
-static void
-qeth_sysfs_unregister(void)
-{
-	s390_root_dev_unregister(qeth_root_dev);
-	qeth_remove_driver_attributes();
-	ccw_driver_unregister(&qeth_ccw_driver);
-	ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
-}
-
-/**
- * register qeth at sysfs
- */
-static int
-qeth_sysfs_register(void)
-{
-	int rc;
-
-	rc = ccwgroup_driver_register(&qeth_ccwgroup_driver);
-	if (rc)
-		goto out;
-
-	rc = ccw_driver_register(&qeth_ccw_driver);
-	if (rc)
-		goto out_ccw_driver;
-
-	rc = qeth_create_driver_attributes();
-	if (rc)
-		goto out_qeth_attr;
-
-	qeth_root_dev = s390_root_dev_register("qeth");
-	rc = IS_ERR(qeth_root_dev) ? PTR_ERR(qeth_root_dev) : 0;
-	if (!rc)
-		goto out;
-
-	qeth_remove_driver_attributes();
-out_qeth_attr:
-	ccw_driver_unregister(&qeth_ccw_driver);
-out_ccw_driver:
-	ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
-out:
-	return rc;
-}
-
-/***
- * init function
- */
-static int __init
-qeth_init(void)
-{
-	int rc;
-
-	PRINT_INFO("loading %s\n", version);
-
-	INIT_LIST_HEAD(&qeth_card_list.list);
-	INIT_LIST_HEAD(&qeth_notify_list);
-	spin_lock_init(&qeth_notify_lock);
-	rwlock_init(&qeth_card_list.rwlock);
-
-	rc = qeth_register_dbf_views();
-	if (rc)
-		goto out_err;
-
-	rc = qeth_sysfs_register();
-	if (rc)
-		goto out_dbf;
-
-#ifdef CONFIG_QETH_IPV6
-	rc = qeth_ipv6_init();
-	if (rc) {
-		PRINT_ERR("Out of memory during ipv6 init code = %d\n", rc);
-		goto out_sysfs;
-	}
-#endif /* QETH_IPV6 */
-	rc = qeth_register_notifiers();
-	if (rc)
-		goto out_ipv6;
-	rc = qeth_create_procfs_entries();
-	if (rc)
-		goto out_notifiers;
-
-	return rc;
-
-out_notifiers:
-	qeth_unregister_notifiers();
-out_ipv6:
-#ifdef CONFIG_QETH_IPV6
-	qeth_ipv6_uninit();
-out_sysfs:
-#endif /* QETH_IPV6 */
-	qeth_sysfs_unregister();
-out_dbf:
-	qeth_unregister_dbf_views();
-out_err:
-	PRINT_ERR("Initialization failed with code %d\n", rc);
-	return rc;
-}
-
-static void
-__exit qeth_exit(void)
-{
-	struct qeth_card *card, *tmp;
-	unsigned long flags;
-
-	QETH_DBF_TEXT(trace,1, "cleanup.");
-
-	/*
-	 * Weed would not need to clean up our devices here, because the
-	 * common device layer calls qeth_remove_device for each device
-	 * as soon as we unregister our driver (done in qeth_sysfs_unregister).
-	 * But we do cleanup here so we can do a "soft" shutdown of our cards.
-	 * qeth_remove_device called by the common device layer would otherwise
-	 * do a "hard" shutdown (card->use_hard_stop is set to one in
-	 * qeth_remove_device).
-	 */
-again:
-	read_lock_irqsave(&qeth_card_list.rwlock, flags);
-	list_for_each_entry_safe(card, tmp, &qeth_card_list.list, list){
-		read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
-		qeth_set_offline(card->gdev);
-		qeth_remove_device(card->gdev);
-		goto again;
-	}
-	read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
-#ifdef CONFIG_QETH_IPV6
-	qeth_ipv6_uninit();
-#endif
-	qeth_unregister_notifiers();
-	qeth_remove_procfs_entries();
-	qeth_sysfs_unregister();
-	qeth_unregister_dbf_views();
-	printk("qeth: removed\n");
-}
-
-EXPORT_SYMBOL(qeth_osn_register);
-EXPORT_SYMBOL(qeth_osn_deregister);
-EXPORT_SYMBOL(qeth_osn_assist);
-module_init(qeth_init);
-module_exit(qeth_exit);
-MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
-MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
-		                      "Copyright 2000,2003 IBM Corporation\n");
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
deleted file mode 100644
index f29a4bc..0000000
--- a/drivers/s390/net/qeth_mpc.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * linux/drivers/s390/net/qeth_mpc.c
- *
- * Linux on zSeries OSA Express and HiperSockets support
- *
- * Copyright 2000,2003 IBM Corporation
- * Author(s): Frank Pavlic <fpavlic@de.ibm.com>
- * 	      Thomas Spatzier <tspat@de.ibm.com>
- *
- */
-#include <asm/cio.h>
-#include "qeth_mpc.h"
-
-unsigned char IDX_ACTIVATE_READ[]={
-	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
-	0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x00,0xc8,0xc1,
-	0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
-	0x00,0x00
-};
-
-unsigned char IDX_ACTIVATE_WRITE[]={
-	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
-	0x15,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
-	0xff,0xff,0x00,0x00, 0x00,0x00,0xc8,0xc1,
-	0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
-	0x00,0x00
-};
-
-unsigned char CM_ENABLE[]={
-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x01,
-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x63,
-	0x10,0x00,0x00,0x01,
-	0x00,0x00,0x00,0x00,
-	0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x23,
-	0x00,0x00,0x23,0x05, 0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
-	0x01,0x00,0x00,0x23, 0x00,0x00,0x00,0x40,
-	0x00,0x0c,0x41,0x02, 0x00,0x17,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x00,0x0b,0x04,0x01,
-	0x7e,0x04,0x05,0x00, 0x01,0x01,0x0f,
-	0x00,
-	0x0c,0x04,0x02,0xff, 0xff,0xff,0xff,0xff,
-	0xff,0xff,0xff
-};
-
-unsigned char CM_SETUP[]={
-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x02,
-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x64,
-	0x10,0x00,0x00,0x01,
-	0x00,0x00,0x00,0x00,
-	0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x24,
-	0x00,0x00,0x24,0x05, 0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
-	0x01,0x00,0x00,0x24, 0x00,0x00,0x00,0x40,
-	0x00,0x0c,0x41,0x04, 0x00,0x18,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x00,0x09,0x04,0x04,
-	0x05,0x00,0x01,0x01, 0x11,
-	0x00,0x09,0x04,
-	0x05,0x05,0x00,0x00, 0x00,0x00,
-	0x00,0x06,
-	0x04,0x06,0xc8,0x00
-};
-
-unsigned char ULP_ENABLE[]={
-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x03,
-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6b,
-	0x10,0x00,0x00,0x01,
-	0x00,0x00,0x00,0x00,
-	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x01,
-	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x2b,
-	0x00,0x00,0x2b,0x05, 0x20,0x01,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
-	0x01,0x00,0x00,0x2b, 0x00,0x00,0x00,0x40,
-	0x00,0x0c,0x41,0x02, 0x00,0x1f,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x00,0x0b,0x04,0x01,
-	0x03,0x04,0x05,0x00, 0x01,0x01,0x12,
-	0x00,
-	0x14,0x04,0x0a,0x00, 0x20,0x00,0x00,0xff,
-	0xff,0x00,0x08,0xc8, 0xe8,0xc4,0xf1,0xc7,
-	0xf1,0x00,0x00
-};
-
-unsigned char ULP_SETUP[]={
-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x04,
-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6c,
-	0x10,0x00,0x00,0x01,
-	0x00,0x00,0x00,0x00,
-	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x02,
-	0x00,0x00,0x00,0x01, 0x00,0x24,0x00,0x2c,
-	0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
-	0x01,0x00,0x00,0x2c, 0x00,0x00,0x00,0x40,
-	0x00,0x0c,0x41,0x04, 0x00,0x20,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x00,0x09,0x04,0x04,
-	0x05,0x00,0x01,0x01, 0x14,
-	0x00,0x09,0x04,
-	0x05,0x05,0x30,0x01, 0x00,0x00,
-	0x00,0x06,
-	0x04,0x06,0x40,0x00,
-	0x00,0x08,0x04,0x0b,
-	0x00,0x00,0x00,0x00
-};
-
-unsigned char DM_ACT[]={
-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x05,
-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x55,
-	0x10,0x00,0x00,0x01,
-	0x00,0x00,0x00,0x00,
-	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x03,
-	0x00,0x00,0x00,0x02, 0x00,0x24,0x00,0x15,
-	0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
-	0x01,0x00,0x00,0x15, 0x00,0x00,0x00,0x40,
-	0x00,0x0c,0x43,0x60, 0x00,0x09,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x00,0x09,0x04,0x04,
-	0x05,0x40,0x01,0x01, 0x00
-};
-
-unsigned char IPA_PDU_HEADER[]={
-	0x00,0xe0,0x00,0x00, 0x77,0x77,0x77,0x77,
-	0x00,0x00,0x00,0x14, 0x00,0x00,
-		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))/256,
-		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))%256,
-	0x10,0x00,0x00,0x01, 0x00,0x00,0x00,0x00,
-	0xc1,0x03,0x00,0x01, 0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00, 0x00,0x24,
-		sizeof(struct qeth_ipa_cmd)/256,
-		sizeof(struct qeth_ipa_cmd)%256,
-	0x00,
-		sizeof(struct qeth_ipa_cmd)/256,
-		sizeof(struct qeth_ipa_cmd)%256,
-	0x05,
-	0x77,0x77,0x77,0x77,
-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
-	0x01,0x00,
-		sizeof(struct qeth_ipa_cmd)/256,
-		sizeof(struct qeth_ipa_cmd)%256,
-	0x00,0x00,0x00,0x40,
-};
-
-unsigned char WRITE_CCW[]={
-	0x01,CCW_FLAG_SLI,0,0,
-	0,0,0,0
-};
-
-unsigned char READ_CCW[]={
-	0x02,CCW_FLAG_SLI,0,0,
-	0,0,0,0
-};
-
-
-struct ipa_rc_msg {
-	enum qeth_ipa_return_codes rc;
-	char *msg;
-};
-
-static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
-	{IPA_RC_SUCCESS,		"success"},
-	{IPA_RC_NOTSUPP,		"Command not supported"},
-	{IPA_RC_IP_TABLE_FULL,		"Add Addr IP Table Full - ipv6"},
-	{IPA_RC_UNKNOWN_ERROR,		"IPA command failed - reason unknown"},
-	{IPA_RC_UNSUPPORTED_COMMAND,	"Command not supported"},
-	{IPA_RC_DUP_IPV6_REMOTE,"ipv6 address already registered remote"},
-	{IPA_RC_DUP_IPV6_HOME,		"ipv6 address already registered"},
-	{IPA_RC_UNREGISTERED_ADDR,	"Address not registered"},
-	{IPA_RC_NO_ID_AVAILABLE,	"No identifiers available"},
-	{IPA_RC_ID_NOT_FOUND,		"Identifier not found"},
-	{IPA_RC_INVALID_IP_VERSION,	"IP version incorrect"},
-	{IPA_RC_LAN_FRAME_MISMATCH,	"LAN and frame mismatch"},
-	{IPA_RC_L2_UNSUPPORTED_CMD,	"Unsupported layer 2 command"},
-	{IPA_RC_L2_DUP_MAC,		"Duplicate MAC address"},
-	{IPA_RC_L2_ADDR_TABLE_FULL,	"Layer2 address table full"},
-	{IPA_RC_L2_DUP_LAYER3_MAC,	"Duplicate with layer 3 MAC"},
-	{IPA_RC_L2_GMAC_NOT_FOUND,	"GMAC not found"},
-	{IPA_RC_L2_MAC_NOT_FOUND,	"L2 mac address not found"},
-	{IPA_RC_L2_INVALID_VLAN_ID,	"L2 invalid vlan id"},
-	{IPA_RC_L2_DUP_VLAN_ID,		"L2 duplicate vlan id"},
-	{IPA_RC_L2_VLAN_ID_NOT_FOUND,	"L2 vlan id not found"},
-	{IPA_RC_DATA_MISMATCH,		"Data field mismatch (v4/v6 mixed)"},
-	{IPA_RC_INVALID_MTU_SIZE,	"Invalid MTU size"},
-	{IPA_RC_INVALID_LANTYPE,	"Invalid LAN type"},
-	{IPA_RC_INVALID_LANNUM,		"Invalid LAN num"},
-	{IPA_RC_DUPLICATE_IP_ADDRESS,	"Address already registered"},
-	{IPA_RC_IP_ADDR_TABLE_FULL,	"IP address table full"},
-	{IPA_RC_LAN_PORT_STATE_ERROR,	"LAN port state error"},
-	{IPA_RC_SETIP_NO_STARTLAN,	"Setip no startlan received"},
-	{IPA_RC_SETIP_ALREADY_RECEIVED,	"Setip already received"},
-	{IPA_RC_IP_ADDR_ALREADY_USED,	"IP address already in use on LAN"},
-	{IPA_RC_MULTICAST_FULL,		"No task available, multicast full"},
-	{IPA_RC_SETIP_INVALID_VERSION,	"SETIP invalid IP version"},
-	{IPA_RC_UNSUPPORTED_SUBCMD,	"Unsupported assist subcommand"},
-	{IPA_RC_ARP_ASSIST_NO_ENABLE,	"Only partial success, no enable"},
-	{IPA_RC_PRIMARY_ALREADY_DEFINED,"Primary already defined"},
-	{IPA_RC_SECOND_ALREADY_DEFINED,	"Secondary already defined"},
-	{IPA_RC_INVALID_SETRTG_INDICATOR,"Invalid SETRTG indicator"},
-	{IPA_RC_MC_ADDR_ALREADY_DEFINED,"Multicast address already defined"},
-	{IPA_RC_LAN_OFFLINE,		"STRTLAN_LAN_DISABLED - LAN offline"},
-	{IPA_RC_INVALID_IP_VERSION2,	"Invalid IP version"},
-	{IPA_RC_FFFF,			"Unknown Error"}
-};
-
-
-
-char *
-qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
-{
-	int x = 0;
-	qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
-			sizeof(struct ipa_rc_msg) - 1].rc = rc;
-	while(qeth_ipa_rc_msg[x].rc != rc)
-		x++;
-	return qeth_ipa_rc_msg[x].msg;
-}
-
-
-struct ipa_cmd_names {
-	enum qeth_ipa_cmds cmd;
-	char *name;
-};
-
-static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
-	{IPA_CMD_STARTLAN,	"startlan"},
-	{IPA_CMD_STOPLAN,	"stoplan"},
-	{IPA_CMD_SETVMAC,	"setvmac"},
-	{IPA_CMD_DELVMAC,	"delvmca"},
-	{IPA_CMD_SETGMAC,	"setgmac"},
-	{IPA_CMD_DELGMAC,	"delgmac"},
-	{IPA_CMD_SETVLAN,	"setvlan"},
-	{IPA_CMD_DELVLAN,	"delvlan"},
-	{IPA_CMD_SETCCID,	"setccid"},
-	{IPA_CMD_DELCCID,	"delccid"},
-	{IPA_CMD_MODCCID,	"setip"},
-	{IPA_CMD_SETIP,		"setip"},
-	{IPA_CMD_QIPASSIST,	"qipassist"},
-	{IPA_CMD_SETASSPARMS,	"setassparms"},
-	{IPA_CMD_SETIPM,	"setipm"},
-	{IPA_CMD_DELIPM,	"delipm"},
-	{IPA_CMD_SETRTG,	"setrtg"},
-	{IPA_CMD_DELIP,		"delip"},
-	{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
-	{IPA_CMD_SET_DIAG_ASS,	"set_diag_ass"},
-	{IPA_CMD_CREATE_ADDR,	"create_addr"},
-	{IPA_CMD_DESTROY_ADDR,	"destroy_addr"},
-	{IPA_CMD_REGISTER_LOCAL_ADDR,	"register_local_addr"},
-	{IPA_CMD_UNREGISTER_LOCAL_ADDR,	"unregister_local_addr"},
-	{IPA_CMD_UNKNOWN,	"unknown"},
-};
-
-char *
-qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
-{
-	int x = 0;
-	qeth_ipa_cmd_names[
-		sizeof(qeth_ipa_cmd_names)/
-			sizeof(struct ipa_cmd_names)-1].cmd = cmd;
-	while(qeth_ipa_cmd_names[x].cmd != cmd)
-		x++;
-	return qeth_ipa_cmd_names[x].name;
-}
-
-
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
deleted file mode 100644
index 46ecd03..0000000
--- a/drivers/s390/net/qeth_proc.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- *
- * linux/drivers/s390/net/qeth_fs.c
- *
- * Linux on zSeries OSA Express and HiperSockets support
- * This file contains code related to procfs.
- *
- * Copyright 2000,2003 IBM Corporation
- *
- * Author(s): Thomas Spatzier <tspat@de.ibm.com>
- *
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/list.h>
-#include <linux/rwsem.h>
-
-#include "qeth.h"
-#include "qeth_mpc.h"
-#include "qeth_fs.h"
-
-/***** /proc/qeth *****/
-#define QETH_PROCFILE_NAME "qeth"
-static struct proc_dir_entry *qeth_procfile;
-
-static int
-qeth_procfile_seq_match(struct device *dev, void *data)
-{
-	return(dev ? 1 : 0);
-}
-
-static void *
-qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
-{
-	struct device *dev = NULL;
-	loff_t nr = 0;
-
-	if (*offset == 0)
-		return SEQ_START_TOKEN;
-	while (1) {
-		dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
-					 NULL, qeth_procfile_seq_match);
-		if (++nr == *offset)
-			break;
-		put_device(dev);
-	}
-	return dev;
-}
-
-static void
-qeth_procfile_seq_stop(struct seq_file *s, void* it)
-{
-}
-
-static void *
-qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
-{
-	struct device *prev, *next;
-
-	if (it == SEQ_START_TOKEN)
-		prev = NULL;
-	else
-		prev = (struct device *) it;
-	next = driver_find_device(&qeth_ccwgroup_driver.driver,
-				  prev, NULL, qeth_procfile_seq_match);
-	(*offset)++;
-	return (void *) next;
-}
-
-static inline const char *
-qeth_get_router_str(struct qeth_card *card, int ipv)
-{
-	enum qeth_routing_types routing_type = NO_ROUTER;
-
-	if (ipv == 4) {
-		routing_type = card->options.route4.type;
-	} else {
-#ifdef CONFIG_QETH_IPV6
-		routing_type = card->options.route6.type;
-#else
-		return "n/a";
-#endif /* CONFIG_QETH_IPV6 */
-	}
-
-	switch (routing_type){
-	case PRIMARY_ROUTER:
-		return "pri";
-	case SECONDARY_ROUTER:
-		return "sec";
-	case MULTICAST_ROUTER:
-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
-			return "mc+";
-		return "mc";
-	case PRIMARY_CONNECTOR:
-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
-			return "p+c";
-		return "p.c";
-	case SECONDARY_CONNECTOR:
-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
-			return "s+c";
-		return "s.c";
-	default:   /* NO_ROUTER */
-		return "no";
-	}
-}
-
-static int
-qeth_procfile_seq_show(struct seq_file *s, void *it)
-{
-	struct device *device;
-	struct qeth_card *card;
-	char tmp[12]; /* for qeth_get_prioq_str */
-
-	if (it == SEQ_START_TOKEN){
-		seq_printf(s, "devices                    CHPID interface  "
-		              "cardtype       port chksum prio-q'ing rtr4 "
-			      "rtr6 fsz   cnt\n");
-		seq_printf(s, "-------------------------- ----- ---------- "
-			      "-------------- ---- ------ ---------- ---- "
-			      "---- ----- -----\n");
-	} else {
-		device = (struct device *) it;
-		card = device->driver_data;
-		seq_printf(s, "%s/%s/%s x%02X   %-10s %-14s %-4i ",
-				CARD_RDEV_ID(card),
-				CARD_WDEV_ID(card),
-				CARD_DDEV_ID(card),
-				card->info.chpid,
-				QETH_CARD_IFNAME(card),
-				qeth_get_cardname_short(card),
-				card->info.portno);
-		if (card->lan_online)
-			seq_printf(s, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
-					qeth_get_checksum_str(card),
-					qeth_get_prioq_str(card, tmp),
-					qeth_get_router_str(card, 4),
-					qeth_get_router_str(card, 6),
-					qeth_get_bufsize_str(card),
-					card->qdio.in_buf_pool.buf_count);
-		else
-			seq_printf(s, "  +++ LAN OFFLINE +++\n");
-		put_device(device);
-	}
-	return 0;
-}
-
-static const struct seq_operations qeth_procfile_seq_ops = {
-	.start = qeth_procfile_seq_start,
-	.stop  = qeth_procfile_seq_stop,
-	.next  = qeth_procfile_seq_next,
-	.show  = qeth_procfile_seq_show,
-};
-
-static int
-qeth_procfile_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &qeth_procfile_seq_ops);
-}
-
-static const struct file_operations qeth_procfile_fops = {
-	.owner   = THIS_MODULE,
-	.open    = qeth_procfile_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
-
-/***** /proc/qeth_perf *****/
-#define QETH_PERF_PROCFILE_NAME "qeth_perf"
-static struct proc_dir_entry *qeth_perf_procfile;
-
-static int
-qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
-{
-	struct device *device;
-	struct qeth_card *card;
-
-
-	if (it == SEQ_START_TOKEN)
-		return 0;
-
-	device = (struct device *) it;
-	card = device->driver_data;
-	seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
-			CARD_RDEV_ID(card),
-			CARD_WDEV_ID(card),
-			CARD_DDEV_ID(card),
-			QETH_CARD_IFNAME(card)
-		  );
-	if (!card->options.performance_stats)
-		seq_printf(s, "Performance statistics are deactivated.\n");
-	seq_printf(s, "  Skb's/buffers received                 : %lu/%u\n"
-		      "  Skb's/buffers sent                     : %lu/%u\n\n",
-		        card->stats.rx_packets -
-				card->perf_stats.initial_rx_packets,
-			card->perf_stats.bufs_rec,
-		        card->stats.tx_packets -
-				card->perf_stats.initial_tx_packets,
-			card->perf_stats.bufs_sent
-		  );
-	seq_printf(s, "  Skb's/buffers sent without packing     : %lu/%u\n"
-		      "  Skb's/buffers sent with packing        : %u/%u\n\n",
-		   card->stats.tx_packets - card->perf_stats.initial_tx_packets
-					  - card->perf_stats.skbs_sent_pack,
-		   card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
-		   card->perf_stats.skbs_sent_pack,
-		   card->perf_stats.bufs_sent_pack
-		  );
-	seq_printf(s, "  Skbs sent in SG mode                   : %u\n"
-		      "  Skb fragments sent in SG mode          : %u\n\n",
-		      card->perf_stats.sg_skbs_sent,
-		      card->perf_stats.sg_frags_sent);
-	seq_printf(s, "  Skbs received in SG mode               : %u\n"
-		      "  Skb fragments received in SG mode      : %u\n"
-		      "  Page allocations for rx SG mode        : %u\n\n",
-		      card->perf_stats.sg_skbs_rx,
-		      card->perf_stats.sg_frags_rx,
-		      card->perf_stats.sg_alloc_page_rx);
-	seq_printf(s, "  large_send tx (in Kbytes)              : %u\n"
-		      "  large_send count                       : %u\n\n",
-		      card->perf_stats.large_send_bytes >> 10,
-		      card->perf_stats.large_send_cnt);
-	seq_printf(s, "  Packing state changes no pkg.->packing : %u/%u\n"
-		      "  Watermarks L/H                         : %i/%i\n"
-		      "  Current buffer usage (outbound q's)    : "
-		      "%i/%i/%i/%i\n\n",
-		        card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
-			QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
-			atomic_read(&card->qdio.out_qs[0]->used_buffers),
-			(card->qdio.no_out_queues > 1)?
-				atomic_read(&card->qdio.out_qs[1]->used_buffers)
-				: 0,
-			(card->qdio.no_out_queues > 2)?
-				atomic_read(&card->qdio.out_qs[2]->used_buffers)
-				: 0,
-			(card->qdio.no_out_queues > 3)?
-				atomic_read(&card->qdio.out_qs[3]->used_buffers)
-				: 0
-		  );
-	seq_printf(s, "  Inbound handler time (in us)           : %u\n"
-		      "  Inbound handler count                  : %u\n"
-		      "  Inbound do_QDIO time (in us)           : %u\n"
-		      "  Inbound do_QDIO count                  : %u\n\n"
-		      "  Outbound handler time (in us)          : %u\n"
-		      "  Outbound handler count                 : %u\n\n"
-		      "  Outbound time (in us, incl QDIO)       : %u\n"
-		      "  Outbound count                         : %u\n"
-		      "  Outbound do_QDIO time (in us)          : %u\n"
-		      "  Outbound do_QDIO count                 : %u\n\n",
-		        card->perf_stats.inbound_time,
-			card->perf_stats.inbound_cnt,
-		        card->perf_stats.inbound_do_qdio_time,
-			card->perf_stats.inbound_do_qdio_cnt,
-			card->perf_stats.outbound_handler_time,
-			card->perf_stats.outbound_handler_cnt,
-			card->perf_stats.outbound_time,
-			card->perf_stats.outbound_cnt,
-		        card->perf_stats.outbound_do_qdio_time,
-			card->perf_stats.outbound_do_qdio_cnt
-		  );
-	put_device(device);
-	return 0;
-}
-
-static const struct seq_operations qeth_perf_procfile_seq_ops = {
-	.start = qeth_procfile_seq_start,
-	.stop  = qeth_procfile_seq_stop,
-	.next  = qeth_procfile_seq_next,
-	.show  = qeth_perf_procfile_seq_show,
-};
-
-static int
-qeth_perf_procfile_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &qeth_perf_procfile_seq_ops);
-}
-
-static const struct file_operations qeth_perf_procfile_fops = {
-	.owner   = THIS_MODULE,
-	.open    = qeth_perf_procfile_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
-
-int __init
-qeth_create_procfs_entries(void)
-{
-	qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
-					   S_IFREG | 0444, NULL);
-	if (qeth_procfile)
-		qeth_procfile->proc_fops = &qeth_procfile_fops;
-
-	qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
-					   S_IFREG | 0444, NULL);
-	if (qeth_perf_procfile)
-		qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
-
-	if (qeth_procfile &&
-	    qeth_perf_procfile)
-		return 0;
-	else
-		return -ENOMEM;
-}
-
-void __exit
-qeth_remove_procfs_entries(void)
-{
-	if (qeth_procfile)
-		remove_proc_entry(QETH_PROCFILE_NAME, NULL);
-	if (qeth_perf_procfile)
-		remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
-}
-
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
deleted file mode 100644
index 2cc3f3a..0000000
--- a/drivers/s390/net/qeth_sys.c
+++ /dev/null
@@ -1,1858 +0,0 @@
-/*
- *
- * linux/drivers/s390/net/qeth_sys.c
- *
- * Linux on zSeries OSA Express and HiperSockets support
- * This file contains code related to sysfs.
- *
- * Copyright 2000,2003 IBM Corporation
- *
- * Author(s): Thomas Spatzier <tspat@de.ibm.com>
- * 	      Frank Pavlic <fpavlic@de.ibm.com>
- *
- */
-#include <linux/list.h>
-#include <linux/rwsem.h>
-
-#include <asm/ebcdic.h>
-
-#include "qeth.h"
-#include "qeth_mpc.h"
-#include "qeth_fs.h"
-
-/*****************************************************************************/
-/*                                                                           */
-/*          /sys-fs stuff UNDER DEVELOPMENT !!!                              */
-/*                                                                           */
-/*****************************************************************************/
-//low/high watermark
-
-static ssize_t
-qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-	if (!card)
-		return -EINVAL;
-
-	switch (card->state) {
-	case CARD_STATE_DOWN:
-		return sprintf(buf, "DOWN\n");
-	case CARD_STATE_HARDSETUP:
-		return sprintf(buf, "HARDSETUP\n");
-	case CARD_STATE_SOFTSETUP:
-		return sprintf(buf, "SOFTSETUP\n");
-	case CARD_STATE_UP:
-		if (card->lan_online)
-		return sprintf(buf, "UP (LAN ONLINE)\n");
-		else
-			return sprintf(buf, "UP (LAN OFFLINE)\n");
-	case CARD_STATE_RECOVER:
-		return sprintf(buf, "RECOVER\n");
-	default:
-		return sprintf(buf, "UNKNOWN\n");
-	}
-}
-
-static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
-
-static ssize_t
-qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%02X\n", card->info.chpid);
-}
-
-static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
-
-static ssize_t
-qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-	if (!card)
-		return -EINVAL;
-	return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
-}
-
-static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
-
-static ssize_t
-qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
-}
-
-static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
-
-static ssize_t
-qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", card->info.portno);
-}
-
-static ssize_t
-qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	unsigned int portno;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	portno = simple_strtoul(buf, &tmp, 16);
-	if (portno > MAX_PORTNO){
-		PRINT_WARN("portno 0x%X is out of range\n", portno);
-		return -EINVAL;
-	}
-
-	card->info.portno = portno;
-	return count;
-}
-
-static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
-
-static ssize_t
-qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-	char portname[9] = {0, };
-
-	if (!card)
-		return -EINVAL;
-
-	if (card->info.portname_required) {
-		memcpy(portname, card->info.portname + 1, 8);
-		EBCASC(portname, 8);
-		return sprintf(buf, "%s\n", portname);
-	} else
-		return sprintf(buf, "no portname required\n");
-}
-
-static ssize_t
-qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	tmp = strsep((char **) &buf, "\n");
-	if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
-		return -EINVAL;
-
-	card->info.portname[0] = strlen(tmp);
-	/* for beauty reasons */
-	for (i = 1; i < 9; i++)
-		card->info.portname[i] = ' ';
-	strcpy(card->info.portname + 1, tmp);
-	ASCEBC(card->info.portname + 1, 8);
-
-	return count;
-}
-
-static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
-		qeth_dev_portname_store);
-
-static ssize_t
-qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card));
-}
-
-static ssize_t
-qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	tmp = strsep((char **) &buf, "\n");
-	if (!strcmp(tmp, "sw_checksumming"))
-		card->options.checksum_type = SW_CHECKSUMMING;
-	else if (!strcmp(tmp, "hw_checksumming"))
-		card->options.checksum_type = HW_CHECKSUMMING;
-	else if (!strcmp(tmp, "no_checksumming"))
-		card->options.checksum_type = NO_CHECKSUMMING;
-	else {
-		PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
-		return -EINVAL;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
-		qeth_dev_checksum_store);
-
-static ssize_t
-qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	switch (card->qdio.do_prio_queueing) {
-	case QETH_PRIO_Q_ING_PREC:
-		return sprintf(buf, "%s\n", "by precedence");
-	case QETH_PRIO_Q_ING_TOS:
-		return sprintf(buf, "%s\n", "by type of service");
-	default:
-		return sprintf(buf, "always queue %i\n",
-			       card->qdio.default_out_queue);
-	}
-}
-
-static ssize_t
-qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	/* check if 1920 devices are supported ,
-	 * if though we have to permit priority queueing
-	 */
-	if (card->qdio.no_out_queues == 1) {
-		PRINT_WARN("Priority queueing disabled due "
-			   "to hardware limitations!\n");
-		card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
-		return -EPERM;
-	}
-
-	tmp = strsep((char **) &buf, "\n");
-	if (!strcmp(tmp, "prio_queueing_prec"))
-		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
-	else if (!strcmp(tmp, "prio_queueing_tos"))
-		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
-	else if (!strcmp(tmp, "no_prio_queueing:0")) {
-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
-		card->qdio.default_out_queue = 0;
-	} else if (!strcmp(tmp, "no_prio_queueing:1")) {
-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
-		card->qdio.default_out_queue = 1;
-	} else if (!strcmp(tmp, "no_prio_queueing:2")) {
-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
-		card->qdio.default_out_queue = 2;
-	} else if (!strcmp(tmp, "no_prio_queueing:3")) {
-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
-		card->qdio.default_out_queue = 3;
-	} else if (!strcmp(tmp, "no_prio_queueing")) {
-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
-		card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
-	} else {
-		PRINT_WARN("Unknown queueing type '%s'\n", tmp);
-		return -EINVAL;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
-		qeth_dev_prioqing_store);
-
-static ssize_t
-qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
-}
-
-static ssize_t
-qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int cnt, old_cnt;
-	int rc;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	old_cnt = card->qdio.in_buf_pool.buf_count;
-	cnt = simple_strtoul(buf, &tmp, 10);
-	cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
-		((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
-	if (old_cnt != cnt) {
-		if ((rc = qeth_realloc_buffer_pool(card, cnt)))
-			PRINT_WARN("Error (%d) while setting "
-				   "buffer count.\n", rc);
-	}
-	return count;
-}
-
-static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
-		qeth_dev_bufcnt_store);
-
-static ssize_t
-qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
-		    char *buf)
-{
-	switch (route->type) {
-	case PRIMARY_ROUTER:
-		return sprintf(buf, "%s\n", "primary router");
-	case SECONDARY_ROUTER:
-		return sprintf(buf, "%s\n", "secondary router");
-	case MULTICAST_ROUTER:
-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
-			return sprintf(buf, "%s\n", "multicast router+");
-		else
-			return sprintf(buf, "%s\n", "multicast router");
-	case PRIMARY_CONNECTOR:
-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
-			return sprintf(buf, "%s\n", "primary connector+");
-		else
-			return sprintf(buf, "%s\n", "primary connector");
-	case SECONDARY_CONNECTOR:
-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
-			return sprintf(buf, "%s\n", "secondary connector+");
-		else
-			return sprintf(buf, "%s\n", "secondary connector");
-	default:
-		return sprintf(buf, "%s\n", "no");
-	}
-}
-
-static ssize_t
-qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_route_show(card, &card->options.route4, buf);
-}
-
-static ssize_t
-qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
-		enum qeth_prot_versions prot, const char *buf, size_t count)
-{
-	enum qeth_routing_types old_route_type = route->type;
-	char *tmp;
-	int rc;
-
-	tmp = strsep((char **) &buf, "\n");
-
-	if (!strcmp(tmp, "no_router")){
-		route->type = NO_ROUTER;
-	} else if (!strcmp(tmp, "primary_connector")) {
-		route->type = PRIMARY_CONNECTOR;
-	} else if (!strcmp(tmp, "secondary_connector")) {
-		route->type = SECONDARY_CONNECTOR;
-	} else if (!strcmp(tmp, "primary_router")) {
-		route->type = PRIMARY_ROUTER;
-	} else if (!strcmp(tmp, "secondary_router")) {
-		route->type = SECONDARY_ROUTER;
-	} else if (!strcmp(tmp, "multicast_router")) {
-		route->type = MULTICAST_ROUTER;
-	} else {
-		PRINT_WARN("Invalid routing type '%s'.\n", tmp);
-		return -EINVAL;
-	}
-	if (((card->state == CARD_STATE_SOFTSETUP) ||
-	     (card->state == CARD_STATE_UP)) &&
-	    (old_route_type != route->type)){
-		if (prot == QETH_PROT_IPV4)
-			rc = qeth_setrouting_v4(card);
-		else if (prot == QETH_PROT_IPV6)
-			rc = qeth_setrouting_v6(card);
-	}
-	return count;
-}
-
-static ssize_t
-qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_route_store(card, &card->options.route4,
-			            QETH_PROT_IPV4, buf, count);
-}
-
-static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store);
-
-#ifdef CONFIG_QETH_IPV6
-static ssize_t
-qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (!qeth_is_supported(card, IPA_IPV6))
-		return sprintf(buf, "%s\n", "n/a");
-
-	return qeth_dev_route_show(card, &card->options.route6, buf);
-}
-
-static ssize_t
-qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (!qeth_is_supported(card, IPA_IPV6)){
-		PRINT_WARN("IPv6 not supported for interface %s.\n"
-			   "Routing status no changed.\n",
-			   QETH_CARD_IFNAME(card));
-		return -ENOTSUPP;
-	}
-
-	return qeth_dev_route_store(card, &card->options.route6,
-			            QETH_PROT_IPV6, buf, count);
-}
-
-static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store);
-#endif
-
-static ssize_t
-qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", card->options.add_hhlen);
-}
-
-static ssize_t
-qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	i = simple_strtoul(buf, &tmp, 10);
-	if ((i < 0) || (i > MAX_ADD_HHLEN)) {
-		PRINT_WARN("add_hhlen out of range\n");
-		return -EINVAL;
-	}
-	card->options.add_hhlen = i;
-
-	return count;
-}
-
-static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show,
-		   qeth_dev_add_hhlen_store);
-
-static ssize_t
-qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", card->options.fake_ll? 1:0);
-}
-
-static ssize_t
-qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	i = simple_strtoul(buf, &tmp, 16);
-	if ((i != 0) && (i != 1)) {
-		PRINT_WARN("fake_ll: write 0 or 1 to this file!\n");
-		return -EINVAL;
-	}
-	card->options.fake_ll = i;
-	return count;
-}
-
-static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show,
-		   qeth_dev_fake_ll_store);
-
-static ssize_t
-qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
-}
-
-static ssize_t
-qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	i = simple_strtoul(buf, &tmp, 16);
-	if ((i == 0) || (i == 1))
-		card->options.fake_broadcast = i;
-	else {
-		PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show,
-		   qeth_dev_fake_broadcast_store);
-
-static ssize_t
-qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	if (card->state != CARD_STATE_UP)
-		return -EPERM;
-
-	i = simple_strtoul(buf, &tmp, 16);
-	if (i == 1)
-		qeth_schedule_recovery(card);
-
-	return count;
-}
-
-static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
-
-static ssize_t
-qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
-		return sprintf(buf, "n/a\n");
-
-	return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
-				     QETH_TR_BROADCAST_ALLRINGS)?
-		       "all rings":"local");
-}
-
-static ssize_t
-qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
-		PRINT_WARN("Device is not a tokenring device!\n");
-		return -EINVAL;
-	}
-
-	tmp = strsep((char **) &buf, "\n");
-
-	if (!strcmp(tmp, "local")){
-		card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
-		return count;
-	} else if (!strcmp(tmp, "all_rings")) {
-		card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
-		return count;
-	} else {
-		PRINT_WARN("broadcast_mode: invalid mode %s!\n",
-			   tmp);
-		return -EINVAL;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
-		   qeth_dev_broadcast_mode_store);
-
-static ssize_t
-qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
-		return sprintf(buf, "n/a\n");
-
-	return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
-				     QETH_TR_MACADDR_CANONICAL)? 1:0);
-}
-
-static ssize_t
-qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
-				  size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
-		PRINT_WARN("Device is not a tokenring device!\n");
-		return -EINVAL;
-	}
-
-	i = simple_strtoul(buf, &tmp, 16);
-	if ((i == 0) || (i == 1))
-		card->options.macaddr_mode = i?
-			QETH_TR_MACADDR_CANONICAL :
-			QETH_TR_MACADDR_NONCANONICAL;
-	else {
-		PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
-		   qeth_dev_canonical_macaddr_store);
-
-static ssize_t
-qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
-}
-
-static ssize_t
-qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-	if (card->info.type == QETH_CARD_TYPE_IQD) {
-                PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
-                return -EPERM;
-        }
-
-	if (((card->state != CARD_STATE_DOWN) &&
-	     (card->state != CARD_STATE_RECOVER)))
-		return -EPERM;
-
-	i = simple_strtoul(buf, &tmp, 16);
-	if ((i == 0) || (i == 1))
-		card->options.layer2 = i;
-	else {
-		PRINT_WARN("layer2: write 0 or 1 to this file!\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
-		   qeth_dev_layer2_store);
-
-static ssize_t
-qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
-}
-
-static ssize_t
-qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	i = simple_strtoul(buf, &tmp, 16);
-	if ((i == 0) || (i == 1)) {
-		if (i == card->options.performance_stats)
-			return count;
-		card->options.performance_stats = i;
-		if (i == 0)
-			memset(&card->perf_stats, 0,
-				sizeof(struct qeth_perf_stats));
-		card->perf_stats.initial_rx_packets = card->stats.rx_packets;
-		card->perf_stats.initial_tx_packets = card->stats.tx_packets;
-	} else {
-		PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
-		   qeth_dev_performance_stats_store);
-
-static ssize_t
-qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	switch (card->options.large_send) {
-	case QETH_LARGE_SEND_NO:
-		return sprintf(buf, "%s\n", "no");
-	case QETH_LARGE_SEND_EDDP:
-		return sprintf(buf, "%s\n", "EDDP");
-	case QETH_LARGE_SEND_TSO:
-		return sprintf(buf, "%s\n", "TSO");
-	default:
-		return sprintf(buf, "%s\n", "N/A");
-	}
-}
-
-static ssize_t
-qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	enum qeth_large_send_types type;
-	int rc = 0;
-	char *tmp;
-
-	if (!card)
-		return -EINVAL;
-	tmp = strsep((char **) &buf, "\n");
-	if (!strcmp(tmp, "no")){
-		type = QETH_LARGE_SEND_NO;
-	} else if (!strcmp(tmp, "EDDP")) {
-		type = QETH_LARGE_SEND_EDDP;
-	} else if (!strcmp(tmp, "TSO")) {
-		type = QETH_LARGE_SEND_TSO;
-	} else {
-		PRINT_WARN("large_send: invalid mode %s!\n", tmp);
-		return -EINVAL;
-	}
-	if (card->options.large_send == type)
-		return count;
-	if ((rc = qeth_set_large_send(card, type)))
-		return rc;
-	return count;
-}
-
-static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
-		   qeth_dev_large_send_store);
-
-static ssize_t
-qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value )
-{
-
-	if (!card)
-		return -EINVAL;
-
-	return sprintf(buf, "%i\n", value);
-}
-
-static ssize_t
-qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
-			  int *value, int max_value)
-{
-	char *tmp;
-	int i;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	i = simple_strtoul(buf, &tmp, 10);
-	if (i <= max_value) {
-		*value = i;
-	} else {
-		PRINT_WARN("blkt total time: write values between"
-			   " 0 and %d to this file!\n", max_value);
-		return -EINVAL;
-	}
-	return count;
-}
-
-static ssize_t
-qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
-}
-
-
-static ssize_t
-qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	return qeth_dev_blkt_store(card, buf, count,
-				   &card->info.blkt.time_total,1000);
-}
-
-
-
-static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
-		   qeth_dev_blkt_total_store);
-
-static ssize_t
-qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
-}
-
-
-static ssize_t
-qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	return qeth_dev_blkt_store(card, buf, count,
-				   &card->info.blkt.inter_packet,100);
-}
-
-static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
-		   qeth_dev_blkt_inter_store);
-
-static ssize_t
-qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	return qeth_dev_blkt_show(buf, card,
-				  card->info.blkt.inter_packet_jumbo);
-}
-
-
-static ssize_t
-qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	return qeth_dev_blkt_store(card, buf, count,
-				   &card->info.blkt.inter_packet_jumbo,100);
-}
-
-static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
-		   qeth_dev_blkt_inter_jumbo_store);
-
-static struct device_attribute * qeth_blkt_device_attrs[] = {
-	&dev_attr_total,
-	&dev_attr_inter,
-	&dev_attr_inter_jumbo,
-	NULL,
-};
-
-static struct attribute_group qeth_device_blkt_group = {
-	.name = "blkt",
-	.attrs = (struct attribute **)qeth_blkt_device_attrs,
-};
-
-static struct device_attribute * qeth_device_attrs[] = {
-	&dev_attr_state,
-	&dev_attr_chpid,
-	&dev_attr_if_name,
-	&dev_attr_card_type,
-	&dev_attr_portno,
-	&dev_attr_portname,
-	&dev_attr_checksumming,
-	&dev_attr_priority_queueing,
-	&dev_attr_buffer_count,
-	&dev_attr_route4,
-#ifdef CONFIG_QETH_IPV6
-	&dev_attr_route6,
-#endif
-	&dev_attr_add_hhlen,
-	&dev_attr_fake_ll,
-	&dev_attr_fake_broadcast,
-	&dev_attr_recover,
-	&dev_attr_broadcast_mode,
-	&dev_attr_canonical_macaddr,
-	&dev_attr_layer2,
-	&dev_attr_large_send,
-	&dev_attr_performance_stats,
-	NULL,
-};
-
-static struct attribute_group qeth_device_attr_group = {
-	.attrs = (struct attribute **)qeth_device_attrs,
-};
-
-static struct device_attribute * qeth_osn_device_attrs[] = {
-	&dev_attr_state,
-	&dev_attr_chpid,
-	&dev_attr_if_name,
-	&dev_attr_card_type,
-	&dev_attr_buffer_count,
-	&dev_attr_recover,
-	NULL,
-};
-
-static struct attribute_group qeth_osn_device_attr_group = {
-	.attrs = (struct attribute **)qeth_osn_device_attrs,
-};
-
-#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)			     \
-struct device_attribute dev_attr_##_id = {				     \
-	.attr = {.name=__stringify(_name), .mode=_mode, },\
-	.show	= _show,						     \
-	.store	= _store,						     \
-};
-
-static int
-qeth_check_layer2(struct qeth_card *card)
-{
-	if (card->options.layer2)
-		return -EPERM;
-	return 0;
-}
-
-
-static ssize_t
-qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-	return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
-}
-
-static ssize_t
-qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-
-	if (!card)
-		return -EINVAL;
-
-	if ((card->state != CARD_STATE_DOWN) &&
-	    (card->state != CARD_STATE_RECOVER))
-		return -EPERM;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	tmp = strsep((char **) &buf, "\n");
-	if (!strcmp(tmp, "toggle")){
-		card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
-	} else if (!strcmp(tmp, "1")){
-		card->ipato.enabled = 1;
-	} else if (!strcmp(tmp, "0")){
-		card->ipato.enabled = 0;
-	} else {
-		PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
-			   "this file\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
-			qeth_dev_ipato_enable_show,
-			qeth_dev_ipato_enable_store);
-
-static ssize_t
-qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
-}
-
-static ssize_t
-qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-
-	if (!card)
-		return -EINVAL;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	tmp = strsep((char **) &buf, "\n");
-	if (!strcmp(tmp, "toggle")){
-		card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
-	} else if (!strcmp(tmp, "1")){
-		card->ipato.invert4 = 1;
-	} else if (!strcmp(tmp, "0")){
-		card->ipato.invert4 = 0;
-	} else {
-		PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
-			   "this file\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
-			qeth_dev_ipato_invert4_show,
-			qeth_dev_ipato_invert4_store);
-
-static ssize_t
-qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
-			enum qeth_prot_versions proto)
-{
-	struct qeth_ipato_entry *ipatoe;
-	unsigned long flags;
-	char addr_str[40];
-	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
-	int i = 0;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
-	/* add strlen for "/<mask>\n" */
-	entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
-	spin_lock_irqsave(&card->ip_lock, flags);
-	list_for_each_entry(ipatoe, &card->ipato.entries, entry){
-		if (ipatoe->proto != proto)
-			continue;
-		/* String must not be longer than PAGE_SIZE. So we check if
-		 * string length gets near PAGE_SIZE. Then we can savely display
-		 * the next IPv6 address (worst case, compared to IPv4) */
-		if ((PAGE_SIZE - i) <= entry_len)
-			break;
-		qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
-		i += snprintf(buf + i, PAGE_SIZE - i,
-			      "%s/%i\n", addr_str, ipatoe->mask_bits);
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
-
-	return i;
-}
-
-static ssize_t
-qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
-}
-
-static int
-qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
-		  u8 *addr, int *mask_bits)
-{
-	const char *start, *end;
-	char *tmp;
-	char buffer[40] = {0, };
-
-	start = buf;
-	/* get address string */
-	end = strchr(start, '/');
-	if (!end || (end - start >= 40)){
-		PRINT_WARN("Invalid format for ipato_addx/delx. "
-			   "Use <ip addr>/<mask bits>\n");
-		return -EINVAL;
-	}
-	strncpy(buffer, start, end - start);
-	if (qeth_string_to_ipaddr(buffer, proto, addr)){
-		PRINT_WARN("Invalid IP address format!\n");
-		return -EINVAL;
-	}
-	start = end + 1;
-	*mask_bits = simple_strtoul(start, &tmp, 10);
-	if (!strlen(start) ||
-	    (tmp == start) ||
-	    (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
-		PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static ssize_t
-qeth_dev_ipato_add_store(const char *buf, size_t count,
-			 struct qeth_card *card, enum qeth_prot_versions proto)
-{
-	struct qeth_ipato_entry *ipatoe;
-	u8 addr[16];
-	int mask_bits;
-	int rc;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-	if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
-		return rc;
-
-	if (!(ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){
-		PRINT_WARN("No memory to allocate ipato entry\n");
-		return -ENOMEM;
-	}
-	ipatoe->proto = proto;
-	memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
-	ipatoe->mask_bits = mask_bits;
-
-	if ((rc = qeth_add_ipato_entry(card, ipatoe))){
-		kfree(ipatoe);
-		return rc;
-	}
-
-	return count;
-}
-
-static ssize_t
-qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
-}
-
-static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
-			qeth_dev_ipato_add4_show,
-			qeth_dev_ipato_add4_store);
-
-static ssize_t
-qeth_dev_ipato_del_store(const char *buf, size_t count,
-			 struct qeth_card *card, enum qeth_prot_versions proto)
-{
-	u8 addr[16];
-	int mask_bits;
-	int rc;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-	if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
-		return rc;
-
-	qeth_del_ipato_entry(card, proto, addr, mask_bits);
-
-	return count;
-}
-
-static ssize_t
-qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
-}
-
-static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
-			qeth_dev_ipato_del4_store);
-
-#ifdef CONFIG_QETH_IPV6
-static ssize_t
-qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
-}
-
-static ssize_t
-qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-	char *tmp;
-
-	if (!card)
-		return -EINVAL;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	tmp = strsep((char **) &buf, "\n");
-	if (!strcmp(tmp, "toggle")){
-		card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
-	} else if (!strcmp(tmp, "1")){
-		card->ipato.invert6 = 1;
-	} else if (!strcmp(tmp, "0")){
-		card->ipato.invert6 = 0;
-	} else {
-		PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
-			   "this file\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
-			qeth_dev_ipato_invert6_show,
-			qeth_dev_ipato_invert6_store);
-
-
-static ssize_t
-qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
-}
-
-static ssize_t
-qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
-}
-
-static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
-			qeth_dev_ipato_add6_show,
-			qeth_dev_ipato_add6_store);
-
-static ssize_t
-qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
-}
-
-static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
-			qeth_dev_ipato_del6_store);
-#endif /* CONFIG_QETH_IPV6 */
-
-static struct device_attribute * qeth_ipato_device_attrs[] = {
-	&dev_attr_ipato_enable,
-	&dev_attr_ipato_invert4,
-	&dev_attr_ipato_add4,
-	&dev_attr_ipato_del4,
-#ifdef CONFIG_QETH_IPV6
-	&dev_attr_ipato_invert6,
-	&dev_attr_ipato_add6,
-	&dev_attr_ipato_del6,
-#endif
-	NULL,
-};
-
-static struct attribute_group qeth_device_ipato_group = {
-	.name = "ipa_takeover",
-	.attrs = (struct attribute **)qeth_ipato_device_attrs,
-};
-
-static ssize_t
-qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
-			enum qeth_prot_versions proto)
-{
-	struct qeth_ipaddr *ipaddr;
-	char addr_str[40];
-	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
-	unsigned long flags;
-	int i = 0;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
-	entry_len += 2; /* \n + terminator */
-	spin_lock_irqsave(&card->ip_lock, flags);
-	list_for_each_entry(ipaddr, &card->ip_list, entry){
-		if (ipaddr->proto != proto)
-			continue;
-		if (ipaddr->type != QETH_IP_TYPE_VIPA)
-			continue;
-		/* String must not be longer than PAGE_SIZE. So we check if
-		 * string length gets near PAGE_SIZE. Then we can savely display
-		 * the next IPv6 address (worst case, compared to IPv4) */
-		if ((PAGE_SIZE - i) <= entry_len)
-			break;
-		qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
-		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
-
-	return i;
-}
-
-static ssize_t
-qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
-}
-
-static int
-qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
-		 u8 *addr)
-{
-	if (qeth_string_to_ipaddr(buf, proto, addr)){
-		PRINT_WARN("Invalid IP address format!\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static ssize_t
-qeth_dev_vipa_add_store(const char *buf, size_t count,
-			 struct qeth_card *card, enum qeth_prot_versions proto)
-{
-	u8 addr[16] = {0, };
-	int rc;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-	if ((rc = qeth_parse_vipae(buf, proto, addr)))
-		return rc;
-
-	if ((rc = qeth_add_vipa(card, proto, addr)))
-		return rc;
-
-	return count;
-}
-
-static ssize_t
-qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
-}
-
-static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
-			qeth_dev_vipa_add4_show,
-			qeth_dev_vipa_add4_store);
-
-static ssize_t
-qeth_dev_vipa_del_store(const char *buf, size_t count,
-			 struct qeth_card *card, enum qeth_prot_versions proto)
-{
-	u8 addr[16];
-	int rc;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-	if ((rc = qeth_parse_vipae(buf, proto, addr)))
-		return rc;
-
-	qeth_del_vipa(card, proto, addr);
-
-	return count;
-}
-
-static ssize_t
-qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
-}
-
-static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
-			qeth_dev_vipa_del4_store);
-
-#ifdef CONFIG_QETH_IPV6
-static ssize_t
-qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
-}
-
-static ssize_t
-qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
-}
-
-static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
-			qeth_dev_vipa_add6_show,
-			qeth_dev_vipa_add6_store);
-
-static ssize_t
-qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
-}
-
-static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
-			qeth_dev_vipa_del6_store);
-#endif /* CONFIG_QETH_IPV6 */
-
-static struct device_attribute * qeth_vipa_device_attrs[] = {
-	&dev_attr_vipa_add4,
-	&dev_attr_vipa_del4,
-#ifdef CONFIG_QETH_IPV6
-	&dev_attr_vipa_add6,
-	&dev_attr_vipa_del6,
-#endif
-	NULL,
-};
-
-static struct attribute_group qeth_device_vipa_group = {
-	.name = "vipa",
-	.attrs = (struct attribute **)qeth_vipa_device_attrs,
-};
-
-static ssize_t
-qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
-		       enum qeth_prot_versions proto)
-{
-	struct qeth_ipaddr *ipaddr;
-	char addr_str[40];
-	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
-	unsigned long flags;
-	int i = 0;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-
-	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
-	entry_len += 2; /* \n + terminator */
-	spin_lock_irqsave(&card->ip_lock, flags);
-	list_for_each_entry(ipaddr, &card->ip_list, entry){
-		if (ipaddr->proto != proto)
-			continue;
-		if (ipaddr->type != QETH_IP_TYPE_RXIP)
-			continue;
-		/* String must not be longer than PAGE_SIZE. So we check if
-		 * string length gets near PAGE_SIZE. Then we can savely display
-		 * the next IPv6 address (worst case, compared to IPv4) */
-		if ((PAGE_SIZE - i) <= entry_len)
-			break;
-		qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
-		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
-	}
-	spin_unlock_irqrestore(&card->ip_lock, flags);
-	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
-
-	return i;
-}
-
-static ssize_t
-qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
-}
-
-static int
-qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
-		 u8 *addr)
-{
-	if (qeth_string_to_ipaddr(buf, proto, addr)){
-		PRINT_WARN("Invalid IP address format!\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static ssize_t
-qeth_dev_rxip_add_store(const char *buf, size_t count,
-			struct qeth_card *card, enum qeth_prot_versions proto)
-{
-	u8 addr[16] = {0, };
-	int rc;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-	if ((rc = qeth_parse_rxipe(buf, proto, addr)))
-		return rc;
-
-	if ((rc = qeth_add_rxip(card, proto, addr)))
-		return rc;
-
-	return count;
-}
-
-static ssize_t
-qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
-}
-
-static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
-			qeth_dev_rxip_add4_show,
-			qeth_dev_rxip_add4_store);
-
-static ssize_t
-qeth_dev_rxip_del_store(const char *buf, size_t count,
-			struct qeth_card *card, enum qeth_prot_versions proto)
-{
-	u8 addr[16];
-	int rc;
-
-	if (qeth_check_layer2(card))
-		return -EPERM;
-	if ((rc = qeth_parse_rxipe(buf, proto, addr)))
-		return rc;
-
-	qeth_del_rxip(card, proto, addr);
-
-	return count;
-}
-
-static ssize_t
-qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
-}
-
-static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
-			qeth_dev_rxip_del4_store);
-
-#ifdef CONFIG_QETH_IPV6
-static ssize_t
-qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
-}
-
-static ssize_t
-qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
-}
-
-static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
-			qeth_dev_rxip_add6_show,
-			qeth_dev_rxip_add6_store);
-
-static ssize_t
-qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (!card)
-		return -EINVAL;
-
-	return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
-}
-
-static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
-			qeth_dev_rxip_del6_store);
-#endif /* CONFIG_QETH_IPV6 */
-
-static struct device_attribute * qeth_rxip_device_attrs[] = {
-	&dev_attr_rxip_add4,
-	&dev_attr_rxip_del4,
-#ifdef CONFIG_QETH_IPV6
-	&dev_attr_rxip_add6,
-	&dev_attr_rxip_del6,
-#endif
-	NULL,
-};
-
-static struct attribute_group qeth_device_rxip_group = {
-	.name = "rxip",
-	.attrs = (struct attribute **)qeth_rxip_device_attrs,
-};
-
-int
-qeth_create_device_attributes(struct device *dev)
-{
-	int ret;
-	struct qeth_card *card = dev->driver_data;
-
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		return sysfs_create_group(&dev->kobj,
-					  &qeth_osn_device_attr_group);
-
-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
-		return ret;
-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-		return ret;
-	}
-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group))){
-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
-		return ret;
-	}
-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group))){
-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
-		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
-		return ret;
-	}
-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))){
-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
-		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
-		sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
-		return ret;
-	}
-	return 0;
-}
-
-void
-qeth_remove_device_attributes(struct device *dev)
-{
-	struct qeth_card *card = dev->driver_data;
-
-	if (card->info.type == QETH_CARD_TYPE_OSN) {
-		sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
-		return;
-	}
-	sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-	sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
-	sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
-	sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
-	sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
-}
-
-/**********************/
-/* DRIVER ATTRIBUTES  */
-/**********************/
-static ssize_t
-qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
-			size_t count)
-{
-	const char *start, *end;
-	char bus_ids[3][BUS_ID_SIZE], *argv[3];
-	int i;
-	int err;
-
-	start = buf;
-	for (i = 0; i < 3; i++) {
-		static const char delim[] = { ',', ',', '\n' };
-		int len;
-
-		if (!(end = strchr(start, delim[i])))
-			return -EINVAL;
-		len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
-		strncpy(bus_ids[i], start, len);
-		bus_ids[i][len] = '\0';
-		start = end + 1;
-		argv[i] = bus_ids[i];
-	}
-	err = ccwgroup_create(qeth_root_dev, qeth_ccwgroup_driver.driver_id,
-			&qeth_ccw_driver, 3, argv);
-	if (err)
-		return err;
-	else
-		return count;
-}
-
-
-static DRIVER_ATTR(group, 0200, NULL, qeth_driver_group_store);
-
-static ssize_t
-qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
-				size_t count)
-{
-	int rc;
-	int signum;
-	char *tmp, *tmp2;
-
-	tmp = strsep((char **) &buf, "\n");
-	if (!strncmp(tmp, "unregister", 10)){
-		if ((rc = qeth_notifier_unregister(current)))
-			return rc;
-		return count;
-	}
-
-	signum = simple_strtoul(tmp, &tmp2, 10);
-	if ((signum < 0) || (signum > 32)){
-		PRINT_WARN("Signal number %d is out of range\n", signum);
-		return -EINVAL;
-	}
-	if ((rc = qeth_notifier_register(current, signum)))
-		return rc;
-
-	return count;
-}
-
-static DRIVER_ATTR(notifier_register, 0200, NULL,
-		   qeth_driver_notifier_register_store);
-
-int
-qeth_create_driver_attributes(void)
-{
-	int rc;
-
-	if ((rc = driver_create_file(&qeth_ccwgroup_driver.driver,
-				     &driver_attr_group)))
-		return rc;
-	return driver_create_file(&qeth_ccwgroup_driver.driver,
-				  &driver_attr_notifier_register);
-}
-
-void
-qeth_remove_driver_attributes(void)
-{
-	driver_remove_file(&qeth_ccwgroup_driver.driver,
-			&driver_attr_group);
-	driver_remove_file(&qeth_ccwgroup_driver.driver,
-			&driver_attr_notifier_register);
-}
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
deleted file mode 100644
index c20e923..0000000
--- a/drivers/s390/net/qeth_tso.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * linux/drivers/s390/net/qeth_tso.h
- *
- * Header file for qeth TCP Segmentation Offload support.
- *
- * Copyright 2004 IBM Corporation
- *
- *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>
- *
- */
-#ifndef __QETH_TSO_H__
-#define __QETH_TSO_H__
-
-#include <linux/skbuff.h>
-#include <linux/tcp.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <net/ip6_checksum.h>
-#include "qeth.h"
-#include "qeth_mpc.h"
-
-
-static inline struct qeth_hdr_tso *
-qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
-{
-	QETH_DBF_TEXT(trace, 5, "tsoprsk");
-	return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso));
-}
-
-/**
- * fill header for a TSO packet
- */
-static inline void
-qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
-{
-	struct qeth_hdr_tso *hdr;
-	struct tcphdr *tcph;
-	struct iphdr *iph;
-
-	QETH_DBF_TEXT(trace, 5, "tsofhdr");
-
-	hdr  = (struct qeth_hdr_tso *) skb->data;
-	iph  = ip_hdr(skb);
-	tcph = tcp_hdr(skb);
-	/*fix header to TSO values ...*/
-	hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
-	/*set values which are fix for the first approach ...*/
-	hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
-	hdr->ext.imb_hdr_no  = 1;
-	hdr->ext.hdr_type    = 1;
-	hdr->ext.hdr_version = 1;
-	hdr->ext.hdr_len     = 28;
-	/*insert non-fix values */
-	hdr->ext.mss = skb_shinfo(skb)->gso_size;
-	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
-	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
-				       sizeof(struct qeth_hdr_tso));
-}
-
-/**
- * change some header values as requested by hardware
- */
-static inline void
-qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
-{
-	struct iphdr *iph    = ip_hdr(skb);
-	struct ipv6hdr *ip6h = ipv6_hdr(skb);
-	struct tcphdr *tcph  = tcp_hdr(skb);
-
-	tcph->check = 0;
-	if (skb->protocol == ETH_P_IPV6) {
-		ip6h->payload_len = 0;
-		tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
-					       0, IPPROTO_TCP, 0);
-		return;
-	}
-	/*OSA want us to set these values ...*/
-	tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-					 0, IPPROTO_TCP, 0);
-	iph->tot_len = 0;
-	iph->check = 0;
-}
-
-static inline int
-qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
-			int ipv, int cast_type)
-{
-	struct qeth_hdr_tso *hdr;
-
-	QETH_DBF_TEXT(trace, 5, "tsoprep");
-
-	hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
-	if (hdr == NULL) {
-		QETH_DBF_TEXT(trace, 4, "tsoperr");
-		return -ENOMEM;
-	}
-	memset(hdr, 0, sizeof(struct qeth_hdr_tso));
-	/*fill first 32 bytes of  qdio header as used
-	 *FIXME: TSO has two struct members
-	 * with different names but same size
-	 * */
-	qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
-	qeth_tso_fill_header(card, skb);
-	qeth_tso_set_tcpip_header(card, skb);
-	return 0;
-}
-
-static inline void
-__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
-			int is_tso, int *next_element_to_fill)
-{
-	struct skb_frag_struct *frag;
-	int fragno;
-	unsigned long addr;
-	int element, cnt, dlen;
-
-	fragno = skb_shinfo(skb)->nr_frags;
-	element = *next_element_to_fill;
-	dlen = 0;
-
-	if (is_tso)
-		buffer->element[element].flags =
-			SBAL_FLAGS_MIDDLE_FRAG;
-	else
-		buffer->element[element].flags =
-			SBAL_FLAGS_FIRST_FRAG;
-	if ( (dlen = (skb->len - skb->data_len)) ) {
-		buffer->element[element].addr = skb->data;
-		buffer->element[element].length = dlen;
-		element++;
-	}
-	for (cnt = 0; cnt < fragno; cnt++) {
-		frag = &skb_shinfo(skb)->frags[cnt];
-		addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
-			frag->page_offset;
-		buffer->element[element].addr = (char *)addr;
-		buffer->element[element].length = frag->size;
-		if (cnt < (fragno - 1))
-			buffer->element[element].flags =
-				SBAL_FLAGS_MIDDLE_FRAG;
-		else
-			buffer->element[element].flags =
-				SBAL_FLAGS_LAST_FRAG;
-		element++;
-	}
-	*next_element_to_fill = element;
-}
-#endif /* __QETH_TSO_H__ */
diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
new file mode 100644
index 0000000..8e0556b
--- /dev/null
+++ b/include/linux/smc91x.h
@@ -0,0 +1,13 @@
+#ifndef __SMC91X_H__
+#define __SMC91X_H__
+
+#define SMC91X_USE_8BIT (1 << 0)
+#define SMC91X_USE_16BIT (1 << 1)
+#define SMC91X_USE_32BIT (1 << 2)
+
+struct smc91x_platdata {
+	unsigned long flags;
+	unsigned long irq_flags; /* IRQF_... */
+};
+
+#endif /* __SMC91X_H__ */