Index: oldkernel/linux/Documentation/Configure.help
diff -u linux/Documentation/Configure.help:1.2 linux/Documentation/Configure.help:1.3
--- linux/Documentation/Configure.help:1.2	Thu Jun  1 14:51:28 2000
+++ linux/Documentation/Configure.help	Thu Jun  1 14:57:34 2000
@@ -6090,6 +6090,36 @@
   Documentation/networking/net-modules.txt. The module will be called
   3c509.o. 
 
+3c90x series "Cyclone/Hurricane/Tornado" support
+CONFIG_BC90X
+  If you have one or more of the following 3Com EtherLink PCI network
+  adapters, say Y and read README file distributed in the package.
+
+    EtherLink 10/100 PCI Adapters
+	3c905B-TX     EtherLink 10/100 PCI with Remote Wake Up
+	3c905B-T4     EtherLink 10/100 PCI T4
+	3c905B-COMBO  EtherLink 10/100 PCI COMBO
+	3c905C-TXM    EtherLink 10/100 PCI For Complete PC Management
+
+    EtherLink Server 10/100 PCI Adapters
+	3c980-TX     EtherLink Server 10/100 PCI
+	3c980C-TX    EtherLink Server 10/100 PCI
+
+    EtherLink 100 PCI Adapters
+	3c905B-FX     EtherLink 100 PCI Fibert
+
+    EtherLink 10 PCI Adapters
+	3c900B-TPO    EtherLink 10 PCI TPO
+	3c900B-TPC    EtherLink 10 PCI TPC
+	3c900B-COMBO  EtherLink 10 PCI COMBO
+	3c900B-FL     EtherLink 10 PCI Fiber
+
+
+  If you want to compile this as a module ( = code which can be 
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt as well as
+  Documentation/networking/3c90x.txt.
+
 3c590 series (592/595/597) "Vortex" support
 CONFIG_VORTEX
   If you have a 3Com "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597)
Index: oldkernel/linux/Documentation/networking/3c90x.txt
diff -u /dev/null linux/Documentation/networking/3c90x.txt:1.1
--- /dev/null	Mon Jul 31 21:12:12 2000
+++ linux/Documentation/networking/3c90x.txt	Thu Jun  1 14:57:34 2000
@@ -0,0 +1,345 @@
+File: README
+                             
+                             3Com (R) Corporation
+             EtherLink 10/100 PCI (3C90x) Network Interface Card 
+                              Driver for Linux
+
+
+This file describes the 3C90x network interface card (NIC) driver for Linux.  
+It includes the following topics:
+
+    * Supported NICs
+    * Supported Platforms and Distributions
+    * Loading the Driver Module
+    * Building the Driver
+    * Configuring the Driver 
+    * Support Information
+    * Additional Information
+      
+    CAUTION:  3Com has not yet verified functionality of the 3C90x 
+    driver on platforms, architectures, or configurations other than 
+    those specified in this file. Although it may operate correctly 
+    on other configurations, users are encouraged to exercise caution  
+    when using the driver with other configurations.
+                  
+    DISCLAIMER:  3Com makes no warranties or guarantees, expressly, 
+    implied, or otherwise.  Usage of this driver is solely at the 
+    risk of the user.
+                
+
+* Supported NICs
+----------------
+
+The 3C90x NIC driver for Linux supports the following EtherLink NICs:
+
+    EtherLink 10/100 PCI NICs
+    3C905C Family and 3C920 ASICs EtherLink 10/100 PCI including
+    the -TX and -TX-M
+    3C905B Family and 3C918 ASICs EtherLink 10/100 PCI including
+    the -TX -TX-M and -TX-NM
+    3C905B-COMBO  EtherLink 10/100 PCI COMBO
+    3C905B-T4     EtherLink 10/100 PCI T4
+
+    EtherLink Server 10/100 PCI NICs
+    3C980C-TX    EtherLink Server 10/100 PCI
+    3C980B-TX    EtherLink Server 10/100 PCI
+    3C980-TX     EtherLink Server 10/100 PCI
+	
+    EtherLink 100 PCI NIC
+    3C905B-FX     EtherLink 100 PCI Fiber
+
+    EtherLink 10 PCI NICs
+    3C900B-TPO    EtherLink 10 PCI TPO
+    3C900B-TPC    EtherLink 10 PCI TPC
+    3C900B-COMBO  EtherLink 10 PCI COMBO
+    3C900B-FL     EtherLink 10 PCI Fiber
+
+    The 3c590/3c592/3c595/3c597 and 3C905 Families are supported
+    with the 3c59x driver from Donald Becker.
+
+* Supported Platforms and Distributions
+---------------------------------------
+
+    The 3C90x driver for Linux has been tested with the following
+    commercial Linux distributions, using the i386 architecture:
+
+    RedHat 5.2
+      Kernel version 2.0.36	(i386)
+
+    RedHat 6.0
+      Kernel version 2.2.5-15	(i386)	
+      Kernel version 2.2.5-22	(i386)
+    
+    NOTE:  The driver has been tested on both SMP and UP machines.
+            
+
+* Loading the Driver Module
+---------------------------
+
+    To load the 3C90x driver module on a RedHat 5.2 or 6.0 system, 
+    place an "alias" in the file named /etc/conf.modules.  
+    
+    The alias instructs the kernel module loader to use the 
+    3C90x driver module for a specific Linux Ethernet interface.  
+    When the system attempts to use this Ethernet interface, it 
+    causes the kernel module loader to load the 3c90x driver
+    into the system automatically, and initialize it for use.
+    
+    The alias listed below associates the Ethernet device "eth0" with
+    the 3c90x driver module.  If you have one of the EtherLink NICs
+    that is supported by the driver, place the following line in the
+    /etc/conf.modules file:
+
+	    alias eth0 3c90x 
+
+    To enable additional supported EtherLink NICs, create additional 
+    aliases, such as:
+
+	    alias eth1 3c90x 
+	    alias eth2 3c90x 
+
+
+  Using 3c90x and 3c59x drivers
+  ------------------------------
+    The 3C90x driver for Linux supports the "B" and "C" models of the 
+    EtherLink 3C90x NIC family (see the supported NICs listed above).  
+    
+    Support for older 3C900 and 3C59x NICs, as well as many current 
+    3Com NICs, is provided by the 3C59x driver in Linux.  
+    
+    Because both of these drivers support many of the same models of NICs, 
+    3Com recommends using the 3C90x driver module for the most recent NICs 
+    (those listed above), and the 3c59x driver for those older NICs 
+    not supported by the 3c90x driver.
+    
+    Both the 3C90x and 3C59x driver modules can be used at the same time.
+    However, to make sure that the 3C90x driver is used with the 
+    appropriate NIC, configure your system to load the 3C90x driver first.
+    This allows the 3C90x driver to attach itself to all of the NICs that 
+    it supports.  Once this is complete, the 3C59x driver can be loaded 
+    and used by your system for any remaining 3Com NICs that are not 
+    supported by the 3C90x driver.
+    
+    To accomplish this driver module loading order, it is important to
+    understand how both the 3C90x and 3C59x drivers scan the PCI slots 
+    for the presence of a suitable NIC, how the kernel module loading 
+    system works, and how the "eth0," "eth1," "eth2," etc. device names 
+    are assigned.
+    
+    Both of the 3C90x and 3C59x drivers attempt to locate all of the 
+    PCI network devices they support.  If the 3C90x driver first locates
+    three supported network devices, they will be named eth0, eth1, and
+    eth2.  If, subsequently, the 3C59x driver finds two devices, they 
+    will be named eth3 and eth4. (Note that the ethN devices names are 
+    assigned in a first-found order; this may not be what is requested 
+    in the /etc/conf.modules file.)
+
+    Both drivers scan for devices in PCI slot number order, beginning at 
+    slot 0, and scanning to slot 255.  Unfortunately, there is no 
+    standard for how PCI slots are numbered relative to their location 
+    in a PC; each PC vendor determines the numbering order of PCI slots.  
+    This means that the slots in which you have placed your NICs affects 
+    the order in which the NICs are "found" by the driver.  The 
+    device named eth0 will be the first device found and successfully 
+    scanned by the driver; eth1 will be the second Ethernet device; 
+    eth2 the third, and so on.  
+       
+    To ensure that the 3C90x driver module is the first to detect all
+    supported NICs, place an "alias eth0 3c90x" alias in 
+    /etc/conf.modules. 
+
+    Remember: ALL supported devices found by either the 3C90x or 3C59x 
+    driver will be used by that driver.  There is currently no way to 
+    control specific NIC-to-driver assignments.
+
+
+* Building the Driver
+---------------------
+    The 3C90x driver can be built either as a kernel loadable module, or 
+    it can be compiled directly into the kernel.
+
+    Building a loadable module:
+    ---------------------------
+    To build the 3c90x driver as a loadable module, compile the 3c90x.c
+    source file with the following command:
+
+    gcc -c 3c90x.c -O2 -Wall -Wstrict-prototypes -fomit-frame-pointer \
+	       -fno-strength-reduce -pipe -m486 -malign-loops=2 \
+	       -malign-jumps=2 -malign-functions=2 -DCPU=486 \
+	       -DMODULE -D__KERNEL__
+
+    Additionally, you can modify this compile line by:
+    + Adding -DMODVERSIONS to the command line if your kernel was built 
+      with symbol versioning (RedHat, etc.)
+    + Adding -D__SMP__ to the command line for SMP support
+        
+    
+    To install a loadable module, enter the following command:
+    
+    insmod 3c90x.o
+
+    
+    Building the driver into the base kernel:
+    ----------------------------------------
+    To build the 3C90x driver into the base kernel, run the patch utility
+    to alter the original kernel source to include the 3C90x driver 
+    source, and then re-run the kernel configuration process.
+	
+    Note: It is assumed that the user understands how to configure and
+    build the Linux kernel, a process which is beyond the scope of this
+    document and not described here.
+	
+    Included with the 3C90x distribution tar file are two patch input files
+    named "patch-2.2.5" and "patch-2.0.36".  These are used to patch your
+    original kernel source.  Use the patch file that matches the version 
+    of your kernel source.
+	
+    CAUTION:  The following process MODIFIES your original kernel source	
+    code.  It is highly recommended that you backup your kernel source 
+    code if you are concerned about these modifications.
+	
+    To build the 3C90x driver into the base kernel:
+	
+    1.  Run the following command to patch your kernel source code
+        and replace the <kernel_src_root> with the root of your
+	    kernel source code:
+	  
+	    % patch -d <kernel_src_root> -p0 < <patchfile>
+	    
+	    NOTE:  <patchfile> is the name of the patch file (patch-2.2.5 or
+	    patch-2.0.36) that is appropriate for your kernel.  Both
+	    patch files are included with the driver:
+	  		
+        Use patch-2.2.5 for kernel versions 2.2.5-15 and 2.2.5-22.
+        Use patch-2.0.36 for kernel version 2.0.36-0.7.
+	
+        The root of your kernel source code may be /usr/src/linux.	    
+	    
+    2. After the patch has been applied successfully, reconfigure,
+       rebuild and reinstall your kernel.
+	
+       The patch applied to your kernel source updates the appropriate
+       files such that the "make config" process understands the new  
+       3c90x driver.  Be sure to configure 3Com networking, and specifically
+       support for the 3c90x driver.
+
+
+
+* Configuring the Driver 
+------------------------
+
+    The 3C90x driver supports the following options, which can be 
+    supplied as command line arguments to the insmod command or in the 
+    /etc/conf.modules file.  Unless otherwise stated, all settings take 
+    the form of:
+    	
+    <option>=value [,value...]
+	
+    NOTE:  If you use the conf.modules file to load the driver at
+    boot time, include the word "option" when configuring the driver.
+    For example:  option full_duplex=0
+	
+    If you use command line insmod, do not include the word "option"
+    when configuring the driver.  For example:  insmod 3c90x full_duplex=0
+		
+                                                                              		
+  OPTION: media_select
+    Selects the media type of the NIC.  Note: Invalid combinations of
+    media_select and full_duplex are ignored by the driver.
+
+    0  NONE			[ Default ]
+    1  10BASE_TX
+    2  10AUI
+    3  10BASE_2
+    4  100BASE_TX
+    5  100BASE_FX
+    6  10BASE_FL
+    7  AUTO_SELECT
+
+
+  OPTION: full_duplex
+    Allows overriding of the default duplex setting for the hardware.  
+    Note: Invalid combinations of media_select and full_duplex are ignored 
+    by the driver.
+
+    -  Hardware default	[ Default ]
+    0  Disabled
+    1  Enabled
+	
+
+  OPTION: flowcontrol
+    Sets flow control for the NIC.  Flow control for multiple NICs
+    can be set using commas (for example, flowcontrol=0,1,1,0).
+
+    1  Enabled		[ Default ]
+    0  Disabled
+
+ 
+  OPTION: switchdelay
+    Delays the driver initialization by three seconds to allow 
+    slower switches to respond to the NIC initialization.
+
+    0  Disabled		[ Default ]
+    1  Enabled
+
+
+
+  OPTION: downpoll
+    Sets the poll rate for the DPD, the rate at which the current DPD is 
+    polled for a new DPD to be processed when the next DPD pointer is 
+    empty, or to determine the timer expiration when a packet download 
+    is delayed. The only values that are allowed are 8 and 64.
+
+    8   2.56 microseconds	[ Default ]
+    64  20.48 microseconds
+
+
+ 
+   OPTION: debug
+    Enables debugging messages for particular sub-systems of the driver.  
+    The values below represent flag bits, which can be added together 
+    to enable debugging messages for the particular sub-systems.  In 
+    general, this option is useful to programmers only;  therefore, 
+    debugging output is only available when the driver is compiled with
+    DEBUG defined.
+
+     0x00  No debugging output	[ Default]
+     0x01  Initialization code messages
+     0x02  Function call entry/exit messages
+     0x04  Ioctl messages
+     0x08  Statistics messages
+     0x10  Send path messages
+     0x20  Receive path messages
+     0x40  Interrupt path messages
+
+
+* Support Information
+---------------------
+
+    E-mail: linux_drivers@3com.com
+
+    Europe: European_Technical_Support@3Com.com
+    APR   : apr_technical_support@3com.com
+    LAT   : Linux_drivers@3Com.com
+
+    - Source/binary name/location
+      (http://support.3com.com/infodeli/tools/nic/linuxdownload.htm )
+
+
+* Additional Information
+------------------------
+
+    - Linux network driver site:
+	  http://cesdis.gsfc.nasa.gov/linux/drivers
+
+    - Detailed instructions for building a driver:
+	  http://cesdis.gsfc.nasa.gov/linux/misc/modules.html
+	
+    /usr/src/linux/Documentation
+	  
+	  
+
+3Com and EtherLink are registered trademarks of 3Com Corporation.
+
+
+                 <README.TXT - Release Notes v1.1)
Index: oldkernel/linux/drivers/net/3c90x.c
diff -u /dev/null linux/drivers/net/3c90x.c:1.1
--- /dev/null	Mon Jul 31 21:12:13 2000
+++ linux/drivers/net/3c90x.c	Thu Jun  1 14:57:34 2000
@@ -0,0 +1,6876 @@
+#include "3c90x.h"
+
+#ifndef NOSTATIC
+static
+#endif
+char *version = 
+	"3Com 3c90x Version 1.0.0c 1999 <linux_drivers@3com.com>\n";
+
+/*
+   3Com EtherLink 10/100 PCI (3C90x) Linux Network Driver, Copyright (c) 1999
+   3Com Corporation. All rights reserved.
+   3Com Linux Network Driver software is distributed as is, without any warranty
+   of any kind, either express or implied as further specified in the GNU Public
+   License. This software may be used and distributed according to the terms of
+   the GNU Public License, located in the file LICENSE.
+
+   3Com and EtherLink are registered trademarks of 3Com Corporation. Linux is a
+   registered trademarks of Linus Torvalds. 
+
+
+   Credit
+   ------
+   Special thanks goes to Donald Becker for providing the skeleton driver outline
+   used in this driver, and for the hard work he has put into the 3c59x EtherLink
+   The 3Com 3c90x driver works in cooperatioon with his 3c59x driver.
+
+   skeleton.c: A network driver out line for Linux.
+   Copyright 1993 Uninted States Government as represented by the Director, National
+   Security Agency.
+
+   Donald Becker may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O Center of
+   Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight
+   Center, Greenbelt MD 20771
+   http://cesdis.gsfc.nasa.gov/linux/
+
+
+   This is 3Com's EtherLink PCI driver for Linux.  It provides support for the
+   3c90x and 3c980 network adapters listed here:
+
+    EtherLink 10/100 PCI NICs
+    3C905C Family and 3C920 ASICs EtherLink 10/100 PCI including
+    the -TX and -TX-M
+    3C905B Family and 3C918 ASICs EtherLink 10/100 PCI including
+    the -TX -TX-M and -TX-NM
+    3C905B-COMBO  EtherLink 10/100 PCI COMBO
+    3C905B-T4     EtherLink 10/100 PCI T4
+
+    EtherLink Server 10/100 PCI NICs
+    3C980C-TX    EtherLink Server 10/100 PCI
+    3C980B-TX    EtherLink Server 10/100 PCI
+    3C980-TX     EtherLink Server 10/100 PCI
+	
+    EtherLink 100 PCI NIC
+    3C905B-FX     EtherLink 100 PCI Fiber
+
+    EtherLink 10 PCI NICs
+    3C900B-TPO    EtherLink 10 PCI TPO
+    3C900B-TPC    EtherLink 10 PCI TPC
+    3C900B-COMBO  EtherLink 10 PCI COMBO
+    3C900B-FL     EtherLink 10 PCI Fiber
+
+    Email:	linux_drivers@3com.com
+    URL:	http://support.3com.com/infodeli/tools/nic/linuxdownload.htm
+
+
+    Compile command :
+
+       gcc -c 3c90x.c -O2 -Wall -Wstrict-prototypes -fomit-frame-pointer \
+           -fno-strength-reduce -pipe -m486 -malign-loops=2 \
+	   -malign-jumps=2 -malign-functions=2 -DCPU=486 -DMODULE -D__KERNEL__
+
+        + Add -D__SMP__ to the command line for SMP support
+        + Add -DMODVERSIONS to the command line if your kernel was built with
+          symbol versioning (RedHat, etc.)
+
+
+  
+    c-indent-level: 4
+    c-basic-offset: 4
+    tab-width: 8
+ */
+
+
+
+#include <linux/string.h>
+
+#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
+
+MODULE_AUTHOR("3Com Corporation <linux_drivers@3com.com>");
+MODULE_DESCRIPTION("EtherLink PCI Driver");
+
+#ifdef DEBUG
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_PARM(switchdelay, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(downpoll, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(flowcontrol, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(media_select, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+
+#endif // MODULE && LINUX_VERSION_CODE
+
+char kernel_version [] = UTS_RELEASE;
+
+static const INT MTU = 1500;
+PCHAR ProductName = "3Com EtherLink PCI NIC\n";
+
+static ULONG tc90x_Index = 0;
+
+#ifndef NOSTATIC
+static 
+#endif
+UCHAR BroadcastAddr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+
+PDEVICE RootNICDevice = NULL;
+
+#ifdef MODULE
+
+/*++
+
+Routine Name:
+
+    init_module
+
+Routine Description:
+
+    This routine finds the adapter using the Linux calls 
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	-ENODEV if no adapter found
+	noAdapterFound if adapter(s) found
+
+--*/
+
+INT
+init_module(VOID)
+{
+	NIC_STATUS nicStatus;
+	DBGPRINT_INIT((KERN_CRIT "init_module: IN\n"));
+
+	nicStatus = tc90xbc_ScanDevices(0);
+
+	if (NIC_STATUS_SUCCESS == nicStatus) {
+
+		DBGPRINT_FUNCTION((KERN_CRIT "init_module: OUT\n"));
+		printk(version);
+		return 0;
+
+	}
+	DBGPRINT_ERROR((KERN_CRIT "Scan Devices failed\n"));
+	DBGPRINT_FUNCTION((KERN_CRIT "init_module: OUT\n"));
+	return -ENODEV; 
+
+}
+
+#else
+
+/*++
+
+Routine Name:
+
+    tc90xbc_probe
+
+Routine Description:
+
+    This routine finds the adapter using the Linux calls 
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	-ENODEV if no adapter found
+	noAdapterFound if adapter(s) found
+
+--*/
+
+INT 
+tc90xbc_probe(
+	IN PDEVICE Device
+	)
+{
+	static int scanned = 0;
+	NIC_STATUS nicStatus;
+
+	DBGPRINT_INIT((KERN_CRIT "tc90xbc_probe: IN\n"));
+
+	if(scanned++)
+		return -ENODEV;
+	printk(KERN_INFO "%s", version);
+
+	nicStatus = tc90xbc_ScanDevices(Device);
+	
+	if (NIC_STATUS_SUCCESS == nicStatus) {
+		
+		DBGPRINT_FUNCTION((
+			KERN_CRIT"NICScanDevices: OUT-success\n"));
+		return 0;
+	}
+	else {
+
+		DBGPRINT_ERROR((
+			KERN_CRIT "NICScanDevices returned error\n"));
+		return -ENODEV;
+	}			
+}
+
+#endif  
+
+
+NIC_STATUS
+tc90xbc_ScanDevices(
+	IN PDEVICE Device
+	)
+{
+	PNIC_INFORMATION pAdapter = NULL;
+	INT ioBaseAddress;
+	USHORT pciCommand, vendorId, deviceId;
+	INT interruptVector, noAdapterFound = 0;
+	UCHAR pciBus, pciDeviceFunction;
+	static INT pciIndex = 0;
+	UCHAR cacheLineSize, revisionId;
+	USHORT powerManagementControl;
+
+	DBGPRINT_INIT((KERN_CRIT "tc90xbc_ScanDevices: IN\n"));
+
+	for (; pciIndex < 0xff; pciIndex++) {
+
+		if (pcibios_find_class(
+			PCI_CLASS_NETWORK_ETHERNET << 8,
+			pciIndex,
+			&pciBus,
+			&pciDeviceFunction
+			) != PCIBIOS_SUCCESSFUL) 
+			break;
+
+		pcibios_read_config_word(
+			pciBus,
+			pciDeviceFunction,
+			PCI_VENDOR_ID,
+			&vendorId);
+
+		if (vendorId != NIC_VENDOR_ID)
+			continue;
+
+		pcibios_read_config_word(
+			pciBus,
+			pciDeviceFunction,
+			PCI_DEVICE_ID,
+			&deviceId);
+
+		switch (deviceId) {
+
+			case NIC_PCI_DEVICE_ID_9055:
+				DBGPRINT_INIT(("10/100 Base-TX NIC found\n"));
+				break;
+
+			case NIC_PCI_DEVICE_ID_9058:
+				DBGPRINT_INIT(("10/100 COMBO Deluxe board found\n"));
+				break;
+	
+			case NIC_PCI_DEVICE_ID_9004:
+				DBGPRINT_INIT(("10Base-T TPO NIC found\n"));
+				break;
+
+			case NIC_PCI_DEVICE_ID_9005:
+				DBGPRINT_INIT(("10Base-T/10Base-2/AUI Combo found\n"));
+
+			case NIC_PCI_DEVICE_ID_9006:
+				DBGPRINT_INIT(("10Base-T/10Base-2/TPC found\n"));
+				break;
+
+			case NIC_PCI_DEVICE_ID_900A:
+				DBGPRINT_INIT(("10Base-FL NIC found\n"));
+				break;
+
+			case NIC_PCI_DEVICE_ID_905A:
+				DBGPRINT_INIT(("100Base-Fx NIC found\n"));
+				break;
+					
+			case NIC_PCI_DEVICE_ID_9200:
+				DBGPRINT_INIT(("Tornado NIC found\n"));
+				break;
+
+			case NIC_PCI_DEVICE_ID_9800:
+				DBGPRINT_INIT(("10/100 Base-TX NIC(Python-H) found\n"));
+				break;
+
+
+			case NIC_PCI_DEVICE_ID_9805:
+				DBGPRINT_INIT(("10/100 Base-TX NIC(Python-T) found\n"));
+				break;
+
+			default:				
+				DBGPRINT_INIT(("UnSupported NIC found\n"));
+				continue;
+		}			
+		//
+		// Initialize the ether device.
+		//
+		Device = init_etherdev(Device, 0);
+		DBGPRINT_INIT((
+			KERN_CRIT "3Com device %s\n",Device->name));
+		Device->priv = kmalloc(sizeof(NIC_INFORMATION), GFP_KERNEL);
+		memset(Device->priv, 0, sizeof(NIC_INFORMATION));
+		pAdapter = (PNIC_INFORMATION)Device->priv;
+		pAdapter->Device = Device;
+		//
+		// Save the NIC index.
+		//
+		pAdapter->Index = tc90x_Index++;
+
+		pcibios_read_config_word(
+			pciBus,
+			pciDeviceFunction,
+			PCI_COMMAND,
+			&pciCommand);
+
+		if (!(pciCommand & PCI_COMMAND_MASTER)) {
+
+			DBGPRINT_INIT(("Enabling Bus Matering\n"));
+			pciCommand |= PCI_COMMAND_MASTER;
+		}
+		else {
+			DBGPRINT_INIT(("Bus Mastering enabled by BIOS\n"));			
+		}
+	{
+
+#if LINUX_VERSION_CODE >= 0x20155
+			struct pci_dev *pdev = pci_find_slot(
+							pciBus,
+							pciDeviceFunction
+							);
+			ioBaseAddress = pdev->base_address[0];
+			interruptVector = pdev->irq;
+#else
+			u32 pciIoAddress;
+			u8 pciIrqLine;	
+
+			pcibios_read_config_byte(
+				pciBus,
+				pciDeviceFunction,
+				PCI_INTERRUPT_LINE,
+				&pciIrqLine);
+
+			pcibios_read_config_dword(
+				pciBus,
+				pciDeviceFunction,
+				PCI_BASE_ADDRESS_0,
+				&pciIoAddress);
+
+			ioBaseAddress = pciIoAddress;
+			interruptVector = pciIrqLine;
+#endif
+		}
+		ioBaseAddress &= ~1;
+		//
+		//Check that IO range is free. 
+		//
+		if (check_region(ioBaseAddress, 0x40)) {
+
+			DBGPRINT_ERROR(("NICScan: check_region failed\n"));
+			continue;
+		}
+		DBGPRINT_INIT(("Irq = %x , IoAddress = %x\n",
+					interruptVector,
+					ioBaseAddress));
+
+		pcibios_read_config_byte(
+			pciBus,
+			pciDeviceFunction,
+			PCI_REVISION_ID,
+			&revisionId);
+
+		pcibios_read_config_byte(
+			pciBus,
+			pciDeviceFunction,
+			PCI_CACHE_LINE_SIZE,
+			&cacheLineSize);
+
+		powerManagementControl = PCI_PME_STATUS | 
+					 PCI_POWER_STATE_D0;
+
+		
+		pcibios_write_config_word(
+			pciBus,
+			pciDeviceFunction,
+			PCI_POWER_CONTROL,
+			powerManagementControl);
+
+		pcibios_write_config_dword(
+			pciBus,
+			pciDeviceFunction,
+			PCI_BASE_ADDRESS_0,
+			ioBaseAddress);
+
+		pcibios_write_config_byte(
+			pciBus,
+			pciDeviceFunction,
+			PCI_INTERRUPT_LINE,
+			interruptVector);
+
+		pcibios_write_config_byte(
+			pciBus,
+			pciDeviceFunction,
+			PCI_CACHE_LINE_SIZE,
+			cacheLineSize);
+
+		pcibios_write_config_word(
+			pciBus,
+			pciDeviceFunction,
+			PCI_COMMAND,
+			pciCommand);
+		
+		pAdapter->Hardware.CacheLineSize = cacheLineSize * 4;
+		
+		if ((pAdapter->Hardware.CacheLineSize % 0x10) ||
+		    (!pAdapter->Hardware.CacheLineSize)) {
+
+			DBGPRINT_ERROR((
+				"tc90xbc_Scan: Cacheline size wrong\n"));
+
+			pAdapter->Hardware.CacheLineSize = 0x20;
+		}
+		//
+		// Save the variables in adapter structure
+		//
+		pAdapter->IoBaseAddress = ioBaseAddress;
+		pAdapter->PCI.IoBaseAddress = ioBaseAddress;
+		pAdapter->PCI.InterruptVector = interruptVector;
+
+		pAdapter->Hardware.RevisionId = revisionId;
+		pAdapter->Hardware.DeviceId = deviceId;
+		//
+		// Fill the device structure
+		//
+		if (tc90x_FillDeviceStructure(pAdapter) != NIC_STATUS_SUCCESS) {
+
+			DBGPRINT_ERROR((
+				KERN_CRIT "FillDeviceStructure failed\n"));			
+			tc90x_FreeAdapterResources(pAdapter);
+			continue;
+		}
+
+    		if (tc90x_ReadCommandLineChanges(pAdapter) != 
+		    NIC_STATUS_SUCCESS) {
+
+			DBGPRINT_ERROR((
+				KERN_CRIT "ReadCommandLineChanges failed\n"
+				));
+			tc90x_FreeAdapterResources(pAdapter);
+			continue;
+		}
+		//
+		// Allocate Shared memory
+		//
+		if (tc90x_AllocateSharedMemory(pAdapter) != NIC_STATUS_SUCCESS) {
+
+			DBGPRINT_ERROR((
+				"tc90x_AllocateSharedMemory failed\n"
+				));
+			tc90x_FreeAdapterResources(pAdapter);
+			continue;
+		}
+		//
+		// Reserve the io range.
+		//
+		request_region(
+			Device->base_addr,
+			0x80,
+			ProductName);
+
+		pAdapter->ResourcesReserved |= NIC_IO_PORT_REGISTERED;
+		//
+		// Set the root device and the next device.
+		//
+		((PNIC_INFORMATION)(Device->priv))->NextDevice = RootNICDevice;
+		((PNIC_INFORMATION)(Device->priv))->Device = Device;
+		RootNICDevice = Device;
+
+		Device = 0;
+		noAdapterFound++;
+	}
+
+
+	DBGPRINT_FUNCTION((KERN_CRIT "tc90xbc_ScanDevices: OUT\n"));
+	
+	if (noAdapterFound) {
+
+		DBGPRINT_INITIALIZE(("NoAdapter = %x\n", noAdapterFound));
+		return NIC_STATUS_SUCCESS;
+	}
+	else
+		return NIC_STATUS_FAILURE;
+}
+
+
+
+/*++
+
+Routine Name:
+
+    tc90x_FillDeviceStructure
+
+Routine Description:
+
+    This routine fills the device structure 
+
+Arguments:
+
+	Device - Pointer to the device structure.
+	IoBaseAddress - IoBase address for the adapter.
+	Irq - Irq of the adapter.
+	
+
+Return Value:
+
+	-ENODEV if no adapter found
+	noAdapterFound if adapter(s) found
+
+--*/
+
+NIC_STATUS 
+tc90x_FillDeviceStructure(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+
+	PNIC_INFORMATION pAdapter = Adapter;
+	PDEVICE device = pAdapter->Device;
+
+	DBGPRINT_INIT(("FillDeviceStructure: IN\n"));
+	device->base_addr = pAdapter->PCI.IoBaseAddress;
+	device->irq = pAdapter->PCI.InterruptVector;
+	device->mtu = MTU;
+	//
+	// Set the routine addresses
+	//
+	device->open = &NICOpen;
+	device->hard_start_xmit  = &NICSendPacket;
+	device->stop = &NICClose;
+	device->get_stats = &NICGetStatistics;
+	device->do_ioctl = &NICIoctl;
+#ifdef NEW_MULTICAST
+	device->set_multicast_list = &NICSetReceiveMode;
+#else
+	device->set_multicast_list = &NICSetMulticastList;
+#endif
+	DBGPRINT_INIT(("FillDeviceStructure: OUT\n"));
+	return NIC_STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Name:
+
+    NICOpen
+
+Routine Description:
+
+    This routine opens the interface. 
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	0 if SUCCESS
+	-ENODEV if FAILURE
+
+--*/
+
+
+INT
+NICOpen(
+	IN PDEVICE Device
+	)
+
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
+	
+	DBGPRINT_FUNCTION(("New NICOpen: IN\n"));
+
+#if LINUX_VERSION_CODE >= 0x20200
+	pAdapter->SpinLock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+#endif
+	//
+	// Register IOBase and Irq with the OS
+	//
+	if (tc90x_RegisterAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
+
+		DBGPRINT_ERROR(("NICOpen: RegisterAdapter failed\n"));
+		DBGPRINT_FUNCTION(("NICOpen: Out with ERROR\n"));
+		tc90x_FreeAdapterResources(pAdapter);
+		return -ENODEV;
+	}
+
+	if (tc90x_GetAdapterProperties(pAdapter) != NIC_STATUS_SUCCESS) {
+
+		DBGPRINT_ERROR(("NICOpen: GetAdapterProperties failed\n"));
+		DBGPRINT_FUNCTION(("NICOpen: Out with ERROR\n"));
+		tc90x_FreeAdapterResources(pAdapter);
+		return -ENODEV;
+	}	
+
+	if (tc90x_BasicInitializeAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
+
+		DBGPRINT_ERROR(("NICOpen: BasicInitializeAdapter failed\n"));
+		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
+		tc90x_FreeAdapterResources(pAdapter);
+		return -ENODEV;
+	}
+
+	if (tc90x_TestAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
+
+		DBGPRINT_ERROR(("NICOpen: TestAdapter failed\n"));
+		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
+		tc90x_FreeAdapterResources(pAdapter);
+		return -ENODEV;
+	}
+
+	if (tc90x_SetupMedia(Device) != NIC_STATUS_SUCCESS) {
+
+		DBGPRINT_ERROR(("NICOpen: SetupMedia failed\n"));
+		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
+		tc90x_FreeAdapterResources(pAdapter);
+		return -ENODEV;
+	}
+
+	if (tc90x_SoftwareWork(pAdapter) != NIC_STATUS_SUCCESS) {
+
+		DBGPRINT_ERROR((
+			"NICOpen: EnableSoftwareWork failed\n"));
+		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));	
+		tc90x_FreeAdapterResources(pAdapter);
+		return -ENODEV;
+	}
+
+	if (tc90x_StartAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
+
+		DBGPRINT_ERROR(("NICOpen: StartAdapter failed\n"));
+		DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
+		tc90x_FreeAdapterResources(pAdapter);
+		return -ENODEV;
+	}
+
+	Device->tbusy = 0;
+	Device->interrupt = 0;
+	Device->start = 1;
+	//
+	// Initialize the timer.
+	//
+	pAdapter->Resources.TimerInterval = 100;
+	init_timer(&pAdapter->Resources.Timer);
+	pAdapter->Resources.Timer.expires = RUN_AT(HZ/10);
+	pAdapter->Resources.Timer.data = (ULONG)Device;
+	pAdapter->Resources.Timer.function = &NICTimer;
+	add_timer(&pAdapter->Resources.Timer);
+	//
+	// Initialize task queue for hosterr task, just in case
+	//
+	pAdapter->Resources.hostErr_task.routine = ReStartAdapter;
+	pAdapter->Resources.hostErr_task.data = (void *)&pAdapter;
+	pAdapter->Resources.hostErr_task.sync = 0;
+	//
+	// Timer has been registered.
+	//
+	pAdapter->ResourcesReserved |= NIC_TIMER_REGISTERED;
+
+	MOD_INC_USE_COUNT;
+
+	DBGPRINT_FUNCTION(("NICOpen:  OUT with SUCCESS\n"));
+	return	0;
+
+}
+
+/*++
+
+Routine Name:
+
+    NICClose
+
+Routine Description:
+
+    This routine closes the interface. 
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	-ENODEV if no adapter found
+	noAdapterFound if adapter(s) found
+
+--*/
+INT
+NICClose(
+	IN PDEVICE Device
+	)
+{
+
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
+	PDEVICE device = pAdapter->Device;
+	ULONG count;
+	USHORT mediaStatus;
+
+	DBGPRINT_FUNCTION(("NICClose: IN\n"));
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_lock(&pAdapter->SpinLock);
+#endif
+	DBGPRINT_FUNCTION(("NICClose:one \n"));
+
+	Device->start = 0;
+	Device->tbusy = 1;
+	//
+	// Disable transmit and receive.
+	//
+	NIC_COMMAND(pAdapter, COMMAND_TX_DISABLE);
+	NIC_COMMAND(pAdapter, COMMAND_RX_DISABLE);
+	//
+	// Wait for the transmit in progress to go off.
+	//
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW |  REGISTER_WINDOW_4);
+	
+	count = jiffies + HZ;
+	do {
+        	mediaStatus = NIC_READ_PORT_USHORT(
+                            	pAdapter,
+                            	MEDIA_STATUS_REGISTER);
+       		NIC_DELAY(10);
+    	} while ( (mediaStatus & MEDIA_STATUS_TX_IN_PROGRESS) &&
+			  (count > jiffies) );
+
+	if (count < jiffies) {
+        	//
+        	// Adapter is not responding, lets reset the transmitter 
+        	// and receiver.
+        	//
+        	DBGPRINT_ERROR(("NICClose: Adapter is not responding\n"));
+    	}
+
+	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
+	//delay 2 microseconds here or not???
+
+	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+	// delay 2 microseconds here or not???
+    	//
+	// Mask and acknowledge all interrupts.
+	//
+	NIC_MASK_ALL_INTERRUPT(pAdapter);
+	NIC_ACKNOWLEDGE_ALL_INTERRUPT(pAdapter);
+	
+	tc90x_CleanupSendLogic(Device);
+	//
+	// Unregister the interrupt handler. 
+	//
+	DBGPRINT_FUNCTION(("NICClose:eight \n"));
+
+	if (pAdapter->ResourcesReserved & NIC_INTERRUPT_REGISTERED) {
+
+		DBGPRINT_INITIALIZE(("Releasing interrupt\n"));
+		free_irq(device->irq, device);
+		pAdapter->ResourcesReserved &= ~NIC_INTERRUPT_REGISTERED;
+	}
+	//
+	// Unregister the timer handler. 
+	//
+	if (pAdapter->ResourcesReserved & NIC_TIMER_REGISTERED) {
+
+		DBGPRINT_INITIALIZE((KERN_CRIT "Releasing Timer\n"));
+		if (del_timer(&pAdapter->Resources.Timer)) {
+			//
+			// Timer has already been queued.
+			//
+			//DBGPRINT_ERROR(("Timer already queued\n"));
+		}
+		pAdapter->ResourcesReserved &= ~NIC_TIMER_REGISTERED;
+	}
+
+	MOD_DEC_USE_COUNT;
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_unlock(&pAdapter->SpinLock);
+#endif
+
+	DBGPRINT_FUNCTION(("NICClose: OUT\n"));
+	return 0;
+}
+
+
+/*++
+
+Routine Name:
+
+    cleanup_module
+
+Routine Description:
+
+    This routine releases the resources. 
+
+Arguments:
+
+	None
+
+Return Value:
+
+	None
+
+--*/
+
+#ifdef MODULE
+
+VOID
+cleanup_module(
+	VOID
+	)
+{
+	PDEVICE nextDevice;
+	PNIC_INFORMATION pAdapter;
+
+	DBGPRINT_FUNCTION(("cleanup_module: IN\n"));
+
+	while (RootNICDevice) {
+
+		nextDevice = ((PNIC_INFORMATION)
+			      (RootNICDevice->priv))->NextDevice;
+		
+		unregister_netdev(RootNICDevice);
+		pAdapter = (PNIC_INFORMATION)RootNICDevice->priv;
+		tc90x_FreeAdapterResources(pAdapter);
+		kfree(RootNICDevice);
+		kfree(pAdapter);
+		RootNICDevice = nextDevice;
+	}
+
+	DBGPRINT_FUNCTION(("cleanup_module: OUT\n"));
+}
+#endif
+
+
+
+
+
+
+/*++
+
+Routine Name: 
+
+	MainAutoSelectionRoutine
+
+Routine Description:
+
+	If autoselection is set, determine the connector and link speed
+	by trying the various transceiver types.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	IN USHORT Options
+
+Return Value:
+
+	VOID
+
+--*/
+
+VOID 
+tc90x_MainAutoSelectionRoutine(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT Options
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	CONNECTOR_TYPE NotUsed;
+	USHORT index;
+
+	DBGPRINT_FUNCTION(("MainAutoSelectionRoutine: IN \n"));
+
+	pAdapter->Hardware.Connector = CONNECTOR_UNKNOWN;   
+
+	//
+	// Try 100MB Connectors
+	//
+	if ((Options & MEDIA_OPTIONS_100BASETX_AVAILABLE) ||
+   	    (Options & MEDIA_OPTIONS_10BASET_AVAILABLE) ||
+    	    (Options & MEDIA_OPTIONS_MII_AVAILABLE)) {
+	       	  
+    		//
+	    	// For 10Base-T and 100Base-TX, select autonegotiation
+	    	// instead of autoselect before calling trymii
+    		//
+	    	if ((Options & MEDIA_OPTIONS_100BASETX_AVAILABLE) ||
+    	    	    (Options & MEDIA_OPTIONS_10BASET_AVAILABLE)) {
+
+			pAdapter->Hardware.Connector = 
+					CONNECTOR_AUTONEGOTIATION;
+    		} 
+    		else {
+        	
+			pAdapter->Hardware.Connector = CONNECTOR_MII;
+    		}
+
+		DBGPRINT_INITIALIZE(("Trying MII\n"));
+	   
+		if (!tc90x_TryMII(pAdapter, pAdapter->Hardware.Connector)) {
+	       
+			pAdapter->Hardware.Connector = CONNECTOR_UNKNOWN;
+	   	} 
+	}
+
+	//
+	// Transceiver available is 100Base-FX
+	//
+	if ((Options & MEDIA_OPTIONS_100BASEFX_AVAILABLE) &&
+		(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {
+			
+		DBGPRINT_INITIALIZE(("Trying 100BFX\n"));
+	   		
+		if (tc90x_TryLinkBeat(pAdapter, CONNECTOR_100BASEFX)) {
+			
+			pAdapter->Hardware.Connector = CONNECTOR_100BASEFX;
+			pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
+   		}
+	}
+
+	//
+	// Transceiver available is 10AUI
+	//
+   	if ((Options & MEDIA_OPTIONS_10AUI_AVAILABLE) &&
+		(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {
+			
+		DBGPRINT_INITIALIZE(("Trying 10AUI\n"));
+
+		tc90x_SetupConnector(pAdapter, CONNECTOR_10AUI, &NotUsed);
+
+		//
+		// Try to loopback packet
+		//
+		for (index = 0; index < 3; index++) {
+	
+			if (TestPacket(pAdapter)) {
+
+				pAdapter->Hardware.Connector = CONNECTOR_10AUI;
+				pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
+	
+				DBGPRINT_INITIALIZE(("Found AUI\n"));
+				break;
+			}
+		}
+
+		if (index == 3) {
+
+			DBGPRINT_INITIALIZE(("Unable to find AUI\n"));
+ 		}
+	}
+
+	//
+	// Transceiver available is 10Base-2
+	//
+	if ((Options & MEDIA_OPTIONS_10BASE2_AVAILABLE) &&
+		(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {
+			
+		DBGPRINT_INITIALIZE(("Trying 10BASEB2\n"));
+	   	
+		// Set up the connector
+
+		tc90x_SetupConnector(pAdapter, CONNECTOR_10BASE2, &NotUsed);
+		//
+		// Try to loopback packet
+		//
+		for (index = 0; index < 3; index++) {
+	
+			if (TestPacket(pAdapter)) {
+
+				pAdapter->Hardware.Connector = CONNECTOR_10BASE2;
+				pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
+	
+				DBGPRINT_INITIALIZE(("Found 10Base2 \n"));
+				break;
+			}
+		}
+
+		if (index == 3) {
+
+			DBGPRINT_INITIALIZE(("Unable to find 10Base2\n"));
+		}
+	
+		//
+		// Disable DC converter
+		//
+		NIC_COMMAND(pAdapter, COMMAND_DISABLE_DC_CONVERTER);
+
+		//
+		// Check if DC convertor has been disabled
+		//
+		tc90x_CheckDCConverter(pAdapter, FALSE);
+	}
+	
+	//
+	// Nothing left to try!
+	//
+	if (pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN) {
+		
+		pAdapter->Hardware.Connector = pAdapter->Hardware.ConfigConnector;
+		pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
+		DBGPRINT_INITIALIZE(("AutoSelection failed. Using default.\n"));
+		DBGPRINT_INITIALIZE(("Connector: %x\n",pAdapter->Hardware.Connector));
+		pAdapter->Hardware.LinkLost = TRUE;
+
+	}
+
+	tc90x_SetupConnector(
+		pAdapter, 
+		pAdapter->Hardware.Connector, 
+		&NotUsed
+		);
+
+	DBGPRINT_FUNCTION(("MainAutoSelectionRoutine: OUT \n"));
+}
+
+
+
+/*++
+
+Routine Name:
+	
+	tc90x_CheckDCConverter
+		
+Routine Description:
+
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	IN BOOLEAN EnabledState
+
+Return Value:
+
+    BOOLEAN
+
+--*/
+
+BOOLEAN 
+tc90x_CheckDCConverter (
+	IN PNIC_INFORMATION Adapter,
+	IN BOOLEAN EnabledState
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT MediaStatus = 0;
+	ULONG count;
+
+	NIC_COMMAND(
+		pAdapter, 
+        COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+
+	count = jiffies + (30*HZ/1000);
+	do {		
+		NIC_DELAY(1000);	
+		MediaStatus = NIC_READ_PORT_USHORT(
+				pAdapter, 
+				MEDIA_STATUS_REGISTER);
+	
+	} while ( (
+			((EnabledState) && !(MediaStatus & MEDIA_STATUS_DC_CONVERTER_ENABLED) ) ||
+			((!EnabledState) && (MediaStatus & MEDIA_STATUS_DC_CONVERTER_ENABLED)) 	
+		  )  &&
+		  (count > jiffies )
+		);
+
+	if (count < jiffies) {
+		DBGPRINT_ERROR(("ConfigureDCConverter: Timeout setting DC Converter \n"));
+		pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+		return FALSE;
+	}	
+	return TRUE;
+}
+
+
+/*++
+
+Routine Name:
+	
+	tc90x_SetupConnector
+		
+Routine Description:
+
+	Setup new transceiver type in InternalConfig. Determine whether to 
+	set JabberGuardEnable, enableSQEStats and linkBeatEnable in MediaStatus.
+	Determine if the coax transceiver also needs to be enabled/disabled.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+ 	IN CONNECTOR_TYPE NewConnector
+  	OUT PCONNECTOR_TYPE OldConnector 
+
+Return Value:
+
+	VOID
+
+--*/
+
+VOID
+tc90x_SetupConnector(    
+	IN PNIC_INFORMATION Adapter,
+ 	IN CONNECTOR_TYPE NewConnector,
+  	OUT PCONNECTOR_TYPE OldConnector 
+  	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+    	ULONG InternalConfig = 0;
+    	USHORT MediaStatus = 0;
+	
+	NIC_COMMAND(
+		pAdapter, 
+        	COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	InternalConfig = NIC_READ_PORT_ULONG(
+				pAdapter, 
+				INTERNAL_CONFIG_REGISTER);
+	//
+	// Save old choice
+	//
+	*OldConnector = 
+		(InternalConfig & INTERNAL_CONFIG_TRANSCEIVER_MASK) >> 20;
+   	//
+	// Clear transceiver type and change to new transceiver type
+	//
+   	InternalConfig = InternalConfig & (~INTERNAL_CONFIG_TRANSCEIVER_MASK);
+   	InternalConfig |= (NewConnector << 20);
+	NIC_WRITE_PORT_ULONG(
+		pAdapter, 
+		INTERNAL_CONFIG_REGISTER, 
+		InternalConfig);
+    	//
+    	// Determine whether to set enableSQEStats and linkBeatEnable 
+    	// Automatically set JabberGuardEnable in MediaStatus register.	
+		//
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	MediaStatus = NIC_READ_PORT_USHORT(
+					pAdapter, 
+					MEDIA_STATUS_REGISTER);
+
+	MediaStatus &= ~(
+		MEDIA_STATUS_SQE_STATISTICS_ENABLE |
+		MEDIA_STATUS_LINK_BEAT_ENABLE |
+		MEDIA_STATUS_JABBER_GUARD_ENABLE);
+
+	MediaStatus |= MEDIA_STATUS_JABBER_GUARD_ENABLE;
+
+    	if (NewConnector == CONNECTOR_10AUI) {
+	
+		MediaStatus |= MEDIA_STATUS_SQE_STATISTICS_ENABLE;
+	}
+
+   	 if (NewConnector == CONNECTOR_AUTONEGOTIATION) {
+		
+		MediaStatus |= MEDIA_STATUS_LINK_BEAT_ENABLE;
+	}
+	else {
+		if ((NewConnector == CONNECTOR_10BASET) ||
+			(NewConnector == CONNECTOR_100BASETX) ||
+			(NewConnector == CONNECTOR_100BASEFX)) {
+	
+			if (!pAdapter->Hardware.LinkBeatDisable)
+				MediaStatus |= MEDIA_STATUS_LINK_BEAT_ENABLE;
+    		}
+	}
+
+	NIC_WRITE_PORT_USHORT(pAdapter,	MEDIA_STATUS_REGISTER, MediaStatus);
+
+   	DBGPRINT_INITIALIZE((
+		"tc90x_SetupConnector: MediaStatus = %x \n",MediaStatus));
+	//
+	// If configured for coax we must start the internal transceiver. 
+	// If not, we stop it (in case the configuration changed across a
+	// warm boot).  
+	//
+    	if (NewConnector == CONNECTOR_10BASE2) {
+		
+		NIC_COMMAND(pAdapter, COMMAND_ENABLE_DC_CONVERTER);
+		//
+		// Check if DC convertor has been enabled
+		//
+		tc90x_CheckDCConverter(pAdapter, TRUE);
+	}
+	else {
+		
+		NIC_COMMAND(pAdapter, COMMAND_DISABLE_DC_CONVERTER);
+		//
+		// Check if DC convertor has been disabled
+		//
+		tc90x_CheckDCConverter(pAdapter, FALSE);
+	}
+}
+
+
+/*++
+
+Routine Name: 
+
+	tc90x_TryMII
+
+Routine Description:
+
+    Used to detect if 10Base-T, 100Base-TX, or external MII is available. 
+
+Arguments:
+
+    IN pAdapter pAdapter - Pointer to the adapter structure
+    IN CONNECTOR_TYPE newconnector
+
+Return Value:
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+tc90x_TryMII(    
+	IN PNIC_INFORMATION Adapter,
+  	IN CONNECTOR_TYPE NewConnector 
+  	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+
+ 	BOOLEAN Handles100Mbit = FALSE;
+	CONNECTOR_TYPE NotUsed;
+	BOOLEAN PhyResponding;
+    USHORT PhyControl;
+	ULONG DelayCount;
+    USHORT PhyStatus;
+        
+	DBGPRINT_FUNCTION(("tc90x_TryMII: IN \n"));
+    //
+    // First see if there's anything connected to the MII
+   	//
+    if (!FindMIIPhy(pAdapter)) {
+
+		DBGPRINT_ERROR(("tc90x_TryMII: FindMIIPhy failed \n"));
+		pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+		return FALSE;
+
+	}
+    //
+    // Nowhere is it written that the register must be latched, and since
+    // reset is the last bit out, the contents might not be valid.  read
+    // it one more time.
+    //
+    PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_CONTROL, &PhyControl);
+    if (!PhyResponding) {
+		
+		DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (1) \n"));
+		pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+		return FALSE;
+
+	}
+    //
+    // Now we can read the status and try to figure out what's out there.
+    //
+    PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyStatus);
+    if (!PhyResponding) {
+		
+		DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (2) \n"));
+		pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+		return FALSE;
+
+	}
+    
+	if ((PhyStatus & MII_STATUS_AUTO) && 
+	    (PhyStatus & MII_STATUS_EXTENDED)) {
+    //
+    //  If it is capable of auto negotiation, see if it has i
+	// been done already.  If not, re-initiate autoselect.  
+	// Otherwise accept the results.
+    //
+		DBGPRINT_INITIALIZE(("MII Capable of Autonegotiation\n")); 
+
+		if (!((PhyControl & MII_CONTROL_ENABLE_AUTO) &&
+			(PhyStatus & MII_STATUS_AUTO_DONE))) {
+
+	    	DBGPRINT_INITIALIZE(("Re-Initiating autonegotiation...\n"));	
+	   		tc90x_SetupConnector(
+				pAdapter, 
+				CONNECTOR_AUTONEGOTIATION, 
+				&NotUsed);
+		    
+	  	  	PhyControl |= 
+			(MII_CONTROL_START_AUTO | MII_CONTROL_ENABLE_AUTO);
+	    		WriteMIIPhy(pAdapter, MII_PHY_CONTROL, PhyControl);
+
+		DelayCount = jiffies + 4*HZ;
+		do {
+				NIC_DELAY(1000);
+				PhyResponding = ReadMIIPhy(
+							pAdapter, 
+							MII_PHY_STATUS, 
+							&PhyStatus);
+				if (!PhyResponding) {				
+					DBGPRINT_ERROR(("tc90x_TryMII: Phy !responding (4) \n"));
+					pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+					return FALSE;
+				}
+
+		} while ( (!(PhyStatus & MII_STATUS_AUTO_DONE)) &&
+				  (DelayCount > jiffies ) );
+
+		if ( DelayCount < jiffies )
+		{	DBGPRINT_ERROR(("tc90x_TryMII: Autonegotiation not done (2) \n"));
+			return FALSE;
+		}
+
+		} //end if
+	    
+		Handles100Mbit = FALSE;
+	    
+	    PhyResponding = ReadMIIPhy(
+					pAdapter, 
+					MII_PHY_STATUS, 
+					&PhyStatus);
+		    
+		if (!PhyResponding) {
+			pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+
+			DBGPRINT_ERROR(("TryMII: Phy not responding (5) \n")); 
+			return FALSE;
+
+		}
+	    
+		if (PhyStatus & MII_STATUS_LINK_UP) {			
+			if (!GetLinkSpeed(pAdapter, &Handles100Mbit)) {
+	
+				DBGPRINT_ERROR(("TryMII: Unknown link speed \n"));
+				pAdapter->Hardware.Status = 
+						HARDWARE_STATUS_FAILURE;
+				return FALSE;
+			
+			}
+			if (Handles100Mbit) { 
+				
+				DBGPRINT_INITIALIZE(("TryMII: Link speed set to 100\n"));
+		    		pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
+			} 
+			else {
+			
+				DBGPRINT_INITIALIZE(("TryMII: Link speed set to 10\n"));
+		    		pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
+			}			
+			return TRUE;
+   	 	}
+		else {
+			//
+			// Assume 10Mbit if no link
+			//
+			if (PhyStatus & MII_STATUS_100MB_MASK) {
+				DBGPRINT_INITIALIZE((
+				"TryMII: Link speed defaulted to 100 \n"));
+				pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;		
+			}
+			else {
+				DBGPRINT_INITIALIZE((
+				"TryMII: Link speed defaulted to 10 \n"));
+				pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
+			
+			}
+			return TRUE;
+    	} 		  
+    }		
+	return FALSE;
+}
+
+
+/*++
+
+Routine Name:
+	
+	tc90x_TryLinkBeat
+
+Routine Description:
+
+	Download a self-directed packet. If successful, 100BASE-FX is available.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	IN CONNECTOR_TYPE NewConnector
+
+Return Value:
+
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+tc90x_TryLinkBeat(   
+	IN PNIC_INFORMATION Adapter,
+	IN CONNECTOR_TYPE NewConnector
+	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT MediaStatus = 0;
+	BOOLEAN retval = FALSE;
+  	CONNECTOR_TYPE NotUsed;
+	ULONG TimeOutCount;
+   	DBGPRINT_FUNCTION(("tc90x_TryLinkBeat: IN \n"));
+	//
+    	// Go quiet for 1.5 seconds to get any N-Way hub into a receptive 
+	// state to sense the new link speed.  We go quiet by switching over
+	// to 10BT and disabling Linkbeat.
+	//
+	pAdapter->Hardware.LinkBeatDisable = TRUE;
+    	tc90x_SetupConnector(pAdapter, CONNECTOR_10BASET, &NotUsed);
+	//
+	// Delay 1.5 seconds
+	//
+	TimeOutCount = jiffies + (15*HZ/10);	
+	while(TimeOutCount > jiffies);
+
+    	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
+    	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+    	//
+    	// Set up for TP transceiver
+    	//
+    	tc90x_SetupConnector(pAdapter, NewConnector, &NotUsed);
+	// delay 5 milliseconds
+	TimeOutCount = jiffies + 1;//make it 10ms
+	while(TimeOutCount > jiffies);
+	//
+    	// We need to send a test packet to clear the
+   	// the Partition if for some reason it's partitioned
+    	// (i.e., we were testing 100mb before.)
+    	// Download a 20 byte packet into the TxFIFO, from us, to us
+   	//
+    	if (!DownloadSelfDirected(pAdapter)) {
+		return FALSE;
+	}
+	//
+	// Acknowledge the down complete
+	//
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_ACKNOWLEDGE_INTERRUPT + INTSTATUS_DOWN_COMPLETE);
+ 	//
+    	// Check MediaStatus for linkbeat indication
+    	//
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	MediaStatus = NIC_READ_PORT_USHORT(pAdapter, MEDIA_STATUS_REGISTER);
+
+    	if (MediaStatus & MEDIA_STATUS_LINK_DETECT) {		
+		retval = TRUE;
+	}
+
+	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
+    	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+
+	DBGPRINT_INITIALIZE(("tc90x_TryLinkBeat: OUT with success\n"));
+    	return retval;
+}
+
+/*++
+Routine Name:
+
+	DownloadSelfDirected
+
+Routine Description:
+
+    Download a 20 byte packet into the TxFIFO, from us, to us.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+
+Return Value:
+
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+DownloadSelfDirected(  
+	IN PNIC_INFORMATION Adapter
+	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	PDPD_LIST_ENTRY dpdVirtual;
+	ULONG PacketBufPhysAddr;
+    UCHAR *PacketBuffer;
+	ULONG DownListPointer;
+    PUCHAR pbuffer;
+	ULONG index;
+	//
+	// Set allocated buffer for transmit
+	//
+	PacketBuffer = (PUCHAR)pAdapter->TestBufferVirtual[0];
+	PacketBufPhysAddr = pAdapter->TestBufferPhysical[0];
+	//
+    // Fill data in the buffer
+	//
+	pbuffer = pAdapter->StationAddress;
+	memcpy(PacketBuffer, pbuffer, 6);	// destination is me 
+	memcpy(PacketBuffer + 6, pbuffer, 6);	// source is me 
+	*(ULONG *)(PacketBuffer + 12) = 0;		 
+	*(ULONG *)(PacketBuffer + 16) = 0;		 
+	//
+	// Create a single DPD  
+	//
+	dpdVirtual = (PDPD_LIST_ENTRY)pAdapter->TestDPDVirtual[0];
+
+	dpdVirtual->DownNextPointer = 0;
+	dpdVirtual->FrameStartHeader = 20 | FSH_ROUND_UP_DEFEAT;
+	dpdVirtual->SGList[0].Address = PacketBufPhysAddr;
+	dpdVirtual->SGList[0].Count = 20 | 0x80000000;
+	//
+	// Download DPD
+	//
+	NIC_COMMAND_WAIT(pAdapter, COMMAND_DOWN_STALL);
+	
+	NIC_WRITE_PORT_ULONG(
+		pAdapter, 
+		DOWN_LIST_POINTER_REGISTER, 
+		dpdVirtual->DPDPhysicalAddress);
+
+	NIC_COMMAND(pAdapter, COMMAND_DOWN_UNSTALL);
+	//
+	// Check if the DPD is done with
+    //
+	index = jiffies + (3*HZ);
+	do {
+		NIC_DELAY(100);   
+		DownListPointer = NIC_READ_PORT_ULONG(
+					pAdapter,
+					DOWN_LIST_POINTER_REGISTER);
+	} while ( (DownListPointer == dpdVirtual->DPDPhysicalAddress) &&
+			  (index > jiffies ) );
+
+    if (index < jiffies) {
+		DBGPRINT_ERROR(("DownloadSelfDirected: DPD not finished\n"));
+		pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+		return FALSE;
+	}
+	return TRUE;
+}
+
+BOOLEAN
+CheckTransmitInProgress(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT MediaStatus = 0;
+	ULONG index;
+
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	index = jiffies + HZ;
+	do {
+		MediaStatus = NIC_READ_PORT_USHORT(
+					pAdapter, 
+					MEDIA_STATUS_REGISTER);
+		NIC_DELAY(10);
+	} while ( (MediaStatus & MEDIA_STATUS_TX_IN_PROGRESS) && 
+			  (index > jiffies) );
+
+	if (index < jiffies) { 
+		pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
+		DBGPRINT_ERROR((
+			"CheckTransmitInProgress: Transmit still in progress\n"));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+	
+/*++
+
+Routine Name:
+
+	TestPacket
+
+Routine Description:
+
+    This function is called by TryLoopback to determine if a packet can 
+	successfully be loopbacked for 10Base-2 and AUI.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+    
+Return Value:
+	
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+TestPacket(    
+	IN PNIC_INFORMATION Adapter
+	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+    	BOOLEAN ReturnValue = FALSE;
+	USHORT MacControl = 0;
+	ULONG PacketStatus = 0;
+	ULONG UpListPointer;
+    	ULONG index;
+		
+
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	MacControl = NIC_READ_PORT_USHORT(
+					pAdapter, 
+					MAC_CONTROL_REGISTER);
+	//
+    // Enable full duplex
+    //
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		MAC_CONTROL_REGISTER, 
+		(USHORT)(MacControl | MAC_CONTROL_FULL_DUPLEX_ENABLE));
+	//
+    // Write UpListPointer to UpListPointer register and unstall
+    //
+	NIC_COMMAND_WAIT(pAdapter, COMMAND_UP_STALL);
+    
+	NIC_WRITE_PORT_ULONG(
+		pAdapter, 
+		UP_LIST_POINTER_REGISTER, 
+		pAdapter->HeadUPDVirtual->UPDPhysicalAddress);
+
+	NIC_COMMAND(pAdapter, COMMAND_UP_UNSTALL);
+
+	//
+    // Enable receive and transmit and setup our packet filter
+    //
+    	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_ENABLE);
+    	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_ENABLE);
+    	NIC_COMMAND_WAIT(pAdapter, COMMAND_SET_RX_FILTER + 
+			 RX_FILTER_INDIVIDUAL);
+
+	//
+	// Create single DPD and download 
+	//
+	if (!DownloadSelfDirected(pAdapter)) {
+
+		return FALSE;
+	}
+	//
+	// Check if transmit is still in progress 
+	//
+	if (!CheckTransmitInProgress(pAdapter))
+		return FALSE;
+   	//
+    // Reset the transmitter to get rid of any TxStatus we haven't seen yet
+   	//
+	NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
+	//
+   	// Check UpListPtr to see if it has changed to see if upload complete
+	//
+	index = jiffies + HZ;
+	do {
+		NIC_DELAY(100);  
+		UpListPointer = NIC_READ_PORT_ULONG(
+						pAdapter,
+						UP_LIST_POINTER_REGISTER);
+	} while ( (UpListPointer == pAdapter->HeadUPDVirtual->UPDPhysicalAddress) &&
+			  (index > jiffies) );
+
+	if (index < jiffies) { 
+		DBGPRINT_ERROR(("TestPacket: UPD not finished\n"));
+		return FALSE;
+	}
+    //
+    // Check RxStatus.  If we've got a packet without any errors, this
+    // connector is okay.
+   	//
+    	PacketStatus = pAdapter->HeadUPDVirtual->UpPacketStatus;
+   
+	if (!(PacketStatus & UP_PACKET_STATUS_ERROR) && 
+    		(PacketStatus & UP_PACKET_STATUS_COMPLETE)) {
+		
+		ReturnValue = TRUE;		// Received a good packet
+	}
+    	//
+    	// The following cleans up after the test we just ran
+    	//
+    	NIC_WRITE_PORT_ULONG(pAdapter, UP_LIST_POINTER_REGISTER, 0);
+    	NIC_WRITE_PORT_ULONG(pAdapter, DOWN_LIST_POINTER_REGISTER, 0);
+    	pAdapter->HeadUPDVirtual->UpPacketStatus = 0;
+    	//
+    	// Reset the receiver to wipe anything we haven't seen yet
+    	//
+    	NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+    	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_ACKNOWLEDGE_INTERRUPT +	
+		INTSTATUS_ACKNOWLEDGE_ALL);
+
+	//
+    // Get out of loopback mode
+    //
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	MacControl = NIC_READ_PORT_USHORT(pAdapter, MAC_CONTROL_REGISTER);
+	
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		MAC_CONTROL_REGISTER, 
+		(USHORT)(MacControl & ~MAC_CONTROL_FULL_DUPLEX_ENABLE));
+
+    	return ReturnValue;
+}
+
+
+/*++
+
+Routine Name: 
+
+	GetLinkSpeed
+
+Routine Description:
+
+	Determine from the MII AutoNegotiationAdvertisement and
+	AutoNegotiationPartnerAbility registers whether the 
+	current linkspeed is 10Mbits or 100Mbits.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter,
+	OUT PBOOLEAN handles100Mbitptr 
+
+Return Value:
+
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+GetLinkSpeed(  
+	IN PNIC_INFORMATION Adapter,
+	OUT PBOOLEAN handles100Mbitptr 
+	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+  	BOOLEAN PhyResponding;
+	USHORT PhyAnlpar;
+    	USHORT PhyAner;
+    	USHORT PhyAnar;
+      
+    	PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_ANER, &PhyAner);
+    	if (!PhyResponding)
+		return FALSE;
+  
+    	PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_ANLPAR, &PhyAnlpar);
+    	if (!PhyResponding)
+		return FALSE;
+
+    	PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_ANAR, &PhyAnar);
+    	if (!PhyResponding)
+		return FALSE;
+
+    	if ((PhyAnar & MII_ANAR_100TXFD) && 
+	    (PhyAnlpar & MII_ANLPAR_100TXFD)) {
+
+		pAdapter->Hardware.MIIPhyUsed = MII_100TXFD;
+		*handles100Mbitptr = TRUE;
+		pAdapter->Hardware.FullDuplexEnable = TRUE;
+
+	} 
+    	else if ((PhyAnar & MII_ANAR_100TX) && (PhyAnlpar & MII_ANLPAR_100TX)) {
+		pAdapter->Hardware.MIIPhyUsed = MII_100TX ;
+		*handles100Mbitptr = TRUE;
+		pAdapter->Hardware.FullDuplexEnable = FALSE;
+    	} 
+    	else if ((PhyAnar & MII_ANAR_10TFD) && (PhyAnlpar & MII_ANLPAR_10TFD)) {
+		pAdapter->Hardware.MIIPhyUsed = MII_10TFD ;
+		pAdapter->Hardware.FullDuplexEnable = TRUE;
+    		*handles100Mbitptr = FALSE;
+	} 
+    	else if ((PhyAnar & MII_ANAR_10T) && (PhyAnlpar & MII_ANLPAR_10T)) {
+		pAdapter->Hardware.MIIPhyUsed = MII_10T ;
+		pAdapter->Hardware.FullDuplexEnable = FALSE;
+		*handles100Mbitptr = FALSE;	
+    	} 
+	else {
+		return FALSE;
+	}
+    	return TRUE;
+
+}
+
+
+
+
+
+
+/*++
+
+Routine Name:
+
+    tc90x_FreeAdapterResources.
+
+Routine Description:
+
+    This routine frees up the adapter resources.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+    None
+
+--*/
+
+VOID
+tc90x_FreeAdapterResources(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	PDEVICE device = pAdapter->Device;
+	PUPD_LIST_ENTRY currentUPDVirtual = pAdapter->HeadUPDVirtual;
+	
+	
+	DBGPRINT_FUNCTION(("FreeAdapterResources: IN\n"));
+
+	if (pAdapter->ResourcesReserved & NIC_INTERRUPT_REGISTERED) {
+
+		DBGPRINT_INITIALIZE(("Releasing interrupt\n"));
+		free_irq(device->irq, device);
+		pAdapter->ResourcesReserved &= ~NIC_INTERRUPT_REGISTERED;
+
+	}
+
+	if (pAdapter->ResourcesReserved & NIC_TIMER_REGISTERED) {
+
+		DBGPRINT_INITIALIZE((KERN_CRIT "Releasing Timer\n"));
+		if (del_timer(&pAdapter->Resources.Timer)) {
+		
+			//
+			// Timer has already been queued.
+			//
+			DBGPRINT_ERROR(("Timer already queued\n"));
+
+		}
+		pAdapter->ResourcesReserved &= ~NIC_TIMER_REGISTERED;
+	}
+
+	if (pAdapter->ResourcesReserved & NIC_SHARED_MEMORY_ALLOCATED) {
+
+		DBGPRINT_INITIALIZE((KERN_CRIT "Releasing memory\n"));
+
+		currentUPDVirtual = pAdapter->HeadUPDVirtual;
+		//
+		// Release the SKBs allocated
+		//
+		while (1) {
+
+			if (currentUPDVirtual->SocketBuffer) 
+#if LINUX_VERSION_CODE >= 0x20200
+				dev_kfree_skb(
+					currentUPDVirtual->SocketBuffer
+					);
+#else
+				dev_kfree_skb(
+					currentUPDVirtual->SocketBuffer,
+					GFP_ATOMIC
+					);
+
+#endif
+			currentUPDVirtual = currentUPDVirtual->Next;
+			if (currentUPDVirtual == pAdapter->HeadUPDVirtual)
+					break;	
+		}
+
+		kfree(pAdapter->Resources.SharedMemoryVirtual);
+		pAdapter->ResourcesReserved &= ~NIC_SHARED_MEMORY_ALLOCATED;
+	}
+
+
+	if (pAdapter->ResourcesReserved & NIC_IO_PORT_REGISTERED) {
+
+		DBGPRINT_INITIALIZE((KERN_CRIT "Releasing IO port region\n"));
+		release_region(device->base_addr, 0x80);
+		pAdapter->ResourcesReserved &= ~NIC_IO_PORT_REGISTERED;
+	}	
+	DBGPRINT_FUNCTION(("FreeAdapterResources: OUT\n"));
+}
+
+
+/*++
+
+RoutineName:
+
+    tc90x_RegisterAdapter.
+
+Routine Description:
+
+    This routine registers the adapter resources with Linux.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+    NIC_STATUS_SUCCESS if the adapter resources could be registered.
+    NIC_STATUS_FAILURE if the adapter resources could not be registered.
+
+--*/
+
+NIC_STATUS
+tc90x_RegisterAdapter(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	PDEVICE device = pAdapter->Device;
+
+	DBGPRINT_FUNCTION(("RegisterAdapter: IN\n"));
+	//
+	// Use the now-standard shared IRQ implementation.
+	//
+	DBGPRINT_INITIALIZE(("SA_SHIRQ  registering IRQ %x\n", device->irq));
+	if (request_irq(
+		device->irq, 
+		&NICInterrupt, 
+		SA_SHIRQ, 
+		device->name, 
+		device)) {
+		
+		DBGPRINT_ERROR(("RegisterAdapter: IRQ registration failed\n"));
+		return NIC_STATUS_FAILURE;
+
+	}
+
+	pAdapter->ResourcesReserved|= NIC_INTERRUPT_REGISTERED; 
+
+	DBGPRINT_FUNCTION(("RegisterAdapter: OUT\n"));
+	return NIC_STATUS_SUCCESS;
+}
+
+/*++
+
+Routine Name:
+
+    tc90x_GetAdapterProperties.
+
+Routine Description:
+
+    This routine sets up the adapter.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+    NIC_STATUS_SUCCESS if the adapter could be set up successfully.
+    NIC_STATUS_FAILURE if the adpater could not be set up successfully.
+
+--*/
+
+NIC_STATUS
+tc90x_GetAdapterProperties(
+	IN PNIC_INFORMATION Adapter
+    	)
+
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	PDEVICE device = pAdapter->Device;
+
+	NIC_STATUS nicStatus;
+	USHORT eepromValue;
+	USHORT intStatus;
+	COMPATABILITY_WORD compatability;
+	SOFTWARE_INFORMATION_1 information1;
+	SOFTWARE_INFORMATION_2 information2;
+	CAPABILITIES_WORD capabilities;
+	UCHAR value, index;
+
+	DBGPRINT_FUNCTION(("GetAdapterProperties: IN \n"));
+    //
+    // Check the ASIC type. Udp checksum should not be used in
+    // pre-Tornado cards-  JRR
+    //
+
+    if ((pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_9055) ||
+        (pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_9004) ||
+        (pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_9005) ||
+        (pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_9006) ||
+        (pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_9058) ||
+        (pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_900A) ||
+        (pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_905A) || 
+	(pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_9800)) { 
+
+        pAdapter->Hardware.BitsInHashFilter = 0x40;
+    }
+    else {
+
+        pAdapter->Hardware.BitsInHashFilter = 0x100;
+        pAdapter->Hardware.UDPChecksumErrDone = TRUE;
+    }
+
+	pAdapter->Hardware.Status = HARDWARE_STATUS_WORKING;
+	pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
+
+	//
+	// Make sure we can see the adapter.  Set up for window 7, and make
+	// sure the window number gets reflected in status. 
+	//
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_7);
+
+	intStatus = NIC_READ_PORT_USHORT(
+			pAdapter, 
+			INTSTATUS_COMMAND_REGISTER);
+
+	DBGPRINT_INITIALIZE(("intStatus =%x\n", intStatus));
+	DBGPRINT_INITIALIZE(("ioBase =%x\n", (INT)pAdapter->IoBaseAddress));
+
+	if ((intStatus & REGISTER_WINDOW_MASK) != 
+	    (REGISTER_WINDOW_7 << 13)) {
+
+		DBGPRINT_ERROR(("SetupAdapter: Window selection failure\n"));
+		DBGPRINT_INITIALIZE(("SetupAdapter: Out with error\n"));
+	    	return NIC_STATUS_FAILURE;
+    	}
+	//
+	// ----------------- Read the compatability level ----------
+	//
+
+	nicStatus = tc90x_ReadEEPROM(
+                        pAdapter,
+                        EEPROM_COMPATABILITY_WORD,
+                        (PUSHORT)&compatability);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+	        DBGPRINT_INITIALIZE((
+            		"GetAdapterProperties: compatability read failed\n"));
+        	return NIC_STATUS_FAILURE;
+    	}
+	//
+	// Check the Failure level.
+	//
+
+	if (compatability.FailureLevel > EEPROM_COMPATABILITY_LEVEL) {
+
+       		DBGPRINT_ERROR((
+	        	"GetAdapterProperties: Incompatible level\n"));
+	        DBGPRINT_INITIALIZE((
+	        	"GetAdapterProperties: Out with error\n"));
+	        return NIC_STATUS_FAILURE;
+	}
+	//
+	// Check the warning level.
+	//
+
+	if (compatability.WarningLevel > EEPROM_COMPATABILITY_LEVEL) {
+
+        	DBGPRINT_ERROR((
+            		"GetAdapterProperties: Wrong down compatability level\n"
+			));
+    	}
+    //
+	// ----------------- Read the software information 1 -------
+	//
+	nicStatus = tc90x_ReadEEPROM(
+                        pAdapter,
+                        EEPROM_SOFTWARE_INFORMATION_1,
+                        (PUSHORT)&information1);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_INITIALIZE((
+			"GetAdapterProperties: EEPROM s/w info1 read failed\n"));
+        	return NIC_STATUS_FAILURE;
+
+    	}
+	if (information1.LinkBeatDisable) {
+
+        	DBGPRINT_INITIALIZE(("s/w information1 - Link beat disable\n"));
+	        pAdapter->Hardware.LinkBeatDisable = TRUE;
+
+    	}
+	if (pAdapter->Hardware.DuplexCommandOverride == FALSE) {
+		if (information1.FullDuplexMode) {
+
+			DBGPRINT_INITIALIZE(("s/w information1 - Full duplex enable\n"));
+			pAdapter->Hardware.FullDuplexEnable = TRUE;
+		}
+		else {
+			DBGPRINT_INITIALIZE(("s/w information 1 - Full duplex disabled\n"));
+	        pAdapter->Hardware.FullDuplexEnable = FALSE;
+		}
+	}
+
+	switch (information1.OptimizeFor) {
+
+        case EEPROM_OPTIMIZE_FOR_THROUGHPUT:
+
+			DBGPRINT_INITIALIZE(("sw info1 - optimize throughput\n"));
+			pAdapter->Hardware.OptimizeForThroughput = TRUE;
+			break;
+
+		case EEPROM_OPTIMIZE_FOR_CPU:
+
+			DBGPRINT_INITIALIZE(("s/w info1 - optimize CPU\n"));
+			pAdapter->Hardware.OptimizeForCPU = TRUE;
+			break;
+
+		case EEPROM_OPTIMIZE_NORMAL:
+
+			DBGPRINT_INITIALIZE(("s/w info1 - optimize Normal\n"));
+			pAdapter->Hardware.OptimizeNormal = TRUE;
+			break;
+
+	        default:
+            		DBGPRINT_ERROR((
+	               	"GetAdapterProperties: Wrong optimization level\n"));
+            		return NIC_STATUS_FAILURE;
+			break;
+
+	}
+
+	// ----------------- Read the capabilities information -----
+	//
+	nicStatus = tc90x_ReadEEPROM(
+                        pAdapter,
+                        EEPROM_CAPABILITIES_WORD,
+                        (PUSHORT)&capabilities
+                        );
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_INITIALIZE((
+	        "GetAdapterProprties: EEPROM s/w capabilities read failed\n"));
+
+        	return NIC_STATUS_FAILURE;
+    	}
+
+	if (capabilities.SupportsPowerManagement) {
+
+        	DBGPRINT_INITIALIZE(("Adapter supports power management\n"));
+	        pAdapter->Hardware.SupportsPowerManagement = TRUE;
+	}
+	//
+	// ----------------- Read the software information 2 -------
+	//
+
+	nicStatus = tc90x_ReadEEPROM(
+                        pAdapter,
+                        EEPROM_SOFTWARE_INFORMATION_2,
+                        (PUSHORT)&information2);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+	        	"GetAdapterProperties: ReadEEPROM , SWINFO2 failed\n"));
+	        DBGPRINT_INITIALIZE((
+            		"GetAdapterProperties: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+
+    	}
+
+	if (information2.BroadcastRxErrDone){
+
+        	DBGPRINT_INITIALIZE(("Adapter has BroadcastRxErrDone\n"));
+	        pAdapter->Hardware.BroadcastErrDone = TRUE;
+    	}
+
+	if (information2.MWIErrDone) {
+
+        	DBGPRINT_INITIALIZE(("Adapter has MWIErrDone\n"));
+	        pAdapter->Hardware.MWIErrDone = TRUE;
+    	}
+
+	if (information2.WOLConnectorPresent){
+
+        	DBGPRINT_INITIALIZE(("WOL is connected\n"));
+	        pAdapter->Hardware.WOLConnectorPresent = TRUE;
+    	}
+
+	if (information2.AutoResetToD0) {
+
+        	DBGPRINT_INITIALIZE(("Auto reset to D0 bit on\n"));
+	        pAdapter->Hardware.AutoResetToD0 = TRUE;
+    	}
+	//
+	// ----------------- Read the OEM station address ----------
+	//
+
+	nicStatus = tc90x_ReadEEPROM( 
+                        pAdapter,
+                        EEPROM_OEM_NODE_ADDRESS_WORD_0,
+                        &eepromValue);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+			"GetAdapterProperties: EEPROM read word 0 failed\n"));
+	        DBGPRINT_INITIALIZE((
+            		"GetAdapterProperties: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+
+    	}
+
+	pAdapter->PermanentAddress[0] = HIBYTE(eepromValue);
+	pAdapter->PermanentAddress[1] = LOBYTE(eepromValue);
+
+	nicStatus = tc90x_ReadEEPROM( 
+                        pAdapter,
+                        EEPROM_OEM_NODE_ADDRESS_WORD_1,
+                        &eepromValue);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+			"GetAdapterProperties: EEPROM read word 1 failed\n"));
+	        DBGPRINT_INITIALIZE((
+            		"GetAdapterProperties: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+
+    	}
+
+	pAdapter->PermanentAddress[2] = HIBYTE(eepromValue);
+	pAdapter->PermanentAddress[3] = LOBYTE(eepromValue);
+            
+	nicStatus = tc90x_ReadEEPROM( 
+                        pAdapter,
+                        EEPROM_OEM_NODE_ADDRESS_WORD_2,
+                        &eepromValue);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+	        	"GetAdapterProperties: EEPROM read word 2 failed\n"));
+			DBGPRINT_INITIALIZE((
+			"GetAdapterProperties: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+
+    	}
+
+	pAdapter->PermanentAddress[4] = HIBYTE(eepromValue);
+ 	pAdapter->PermanentAddress[5] = LOBYTE(eepromValue);
+
+   	//
+	// If the station address has not been overriden, fill the permanent
+	// address into it.
+   	//
+
+	value = pAdapter->StationAddress[0] |
+		pAdapter->StationAddress[1] |
+		pAdapter->StationAddress[2] |
+		pAdapter->StationAddress[3] |
+           	pAdapter->StationAddress[4] |
+           	pAdapter->StationAddress[5];
+
+  	//
+	// If the station address has not been overriden, set this value
+	// in the station address.
+    	//
+
+	if (!value) { 
+
+		for (index=0; index < 6; index++) 
+			pAdapter->StationAddress[index] =
+				pAdapter->PermanentAddress[index];
+
+		
+    	}
+
+	for (index=0; index < 6; index++) 
+		device->dev_addr[index] = pAdapter->StationAddress[index];
+
+	DBGPRINT_FUNCTION(("GetAdapterProperties: OUT \n"));
+	return NIC_STATUS_SUCCESS;
+
+}
+
+
+/*++
+
+Routine Name:
+
+    tc90x_BasicInitializeAdapter.
+
+Routine Description:
+
+    This routine does the basic initialize of the adapter. It does
+    not set the media specific stuff.
+
+Arguments:
+
+    MiniportAdapterContext - Pointer to the adapter structure.
+
+Return Value:
+
+    NIC_STATUS_SUCCESS if the initialization succeeds.
+    NIC_STATUS_FAILUTE if the initialization fails.
+
+--*/
+
+NIC_STATUS
+tc90x_BasicInitializeAdapter(
+	IN PNIC_INFORMATION Adapter
+	)
+
+{
+
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT stationTemp, macControl;
+	NIC_STATUS nicStatus;
+
+	DBGPRINT_FUNCTION(("BasicInitializeAdapter: In\n"));
+	//
+	// ----------------- Tx Engine handling --------------------
+	//
+
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_DISABLE);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+	            	"BasicInitializeAdapter: COMMAND_TX_DISABLE failed\n"));
+	        DBGPRINT_FUNCTION((
+            		"BasicInitializeAdapter: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+    
+    	}
+
+#ifdef SERR_NEEDED
+    // Down stall the adapter and wait for 100 milliseconds for
+    // any pending PCI retry to be over.
+    NIC_COMMAND_WAIT(pAdapter, COMMAND_DOWN_STALL);
+#endif
+
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+			"BasicInitializeAdapter: COMMAND_TX_RESET failed\n"));
+	        DBGPRINT_FUNCTION((
+			"GetAdapterProperties: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+    	}
+    //
+	// ----------------- Rx engine handling --------------------
+	//
+
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_DISABLE);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+			"BasicInitializeAdapter: Rx disable failed\n"));
+	        DBGPRINT_FUNCTION((
+            		"BasicInitializeAdapter: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+    }
+
+#ifdef SERR_NEEDED
+    // Up stall the adapter and wait for 100 milliseconds for
+    // any pending PCI retry to be over.
+    NIC_COMMAND_WAIT(pAdapter, COMMAND_UP_STALL);
+#endif
+
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+			"BasicInitializeAdapter: Rx reset failed\n"
+			));
+		DBGPRINT_FUNCTION((
+	            	"BasicInitializeAdapter: Out with error\n"
+			));
+        	return NIC_STATUS_FAILURE;
+    	}
+	//
+	// Take care of the interrupts.
+	//
+	NIC_ACKNOWLEDGE_ALL_INTERRUPT(pAdapter);
+	NIC_COMMAND(pAdapter, COMMAND_STATISTICS_DISABLE);
+
+    	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_6);
+	//
+	// Clear the statistics from the hardware.
+	//
+	NIC_READ_PORT_UCHAR(pAdapter, CARRIER_LOST_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, SQE_ERRORS_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, MULTIPLE_COLLISIONS_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, SINGLE_COLLISIONS_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, LATE_COLLISIONS_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, RX_OVERRUNS_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, FRAMES_TRANSMITTED_OK_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, FRAMES_RECEIVED_OK_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, FRAMES_DEFERRED_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, UPPER_FRAMES_OK_REGISTER);
+	NIC_READ_PORT_USHORT(pAdapter, BYTES_RECEIVED_OK_REGISTER);
+	NIC_READ_PORT_USHORT(pAdapter, BYTES_TRANSMITTED_OK_REGISTER);
+
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	NIC_READ_PORT_UCHAR(pAdapter, BAD_SSD_REGISTER);
+	NIC_READ_PORT_UCHAR(pAdapter, UPPER_BYTES_OK_REGISTER);
+	//
+	// Program the station address.
+	//
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_2);
+
+	stationTemp = pAdapter->StationAddress[1] << 8;
+	stationTemp |= pAdapter->StationAddress[0];
+
+	NIC_WRITE_PORT_USHORT(
+        	pAdapter,
+		STATION_ADDRESS_LOW_REGISTER,
+		stationTemp);
+
+	stationTemp = pAdapter->StationAddress[3] << 8;
+	stationTemp |= pAdapter->StationAddress[2];
+
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		STATION_ADDRESS_MID_REGISTER,
+		stationTemp);
+
+	stationTemp = pAdapter->StationAddress[5] << 8;
+	stationTemp |= pAdapter->StationAddress[4];
+
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		STATION_ADDRESS_HIGH_REGISTER,
+		stationTemp);
+
+	NIC_WRITE_PORT_USHORT(pAdapter, 0x6, 0);
+	NIC_WRITE_PORT_USHORT(pAdapter, 0x8, 0);
+	NIC_WRITE_PORT_USHORT(pAdapter, 0xA, 0);
+	NIC_COMMAND(pAdapter, COMMAND_STATISTICS_ENABLE);
+	//
+	// Clear the mac control register.
+	//
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	macControl = NIC_READ_PORT_USHORT(pAdapter, MAC_CONTROL_REGISTER);
+	macControl &= 0x1;
+	NIC_WRITE_PORT_USHORT(pAdapter, MAC_CONTROL_REGISTER, macControl);
+
+	DBGPRINT_FUNCTION((
+        	"BasicInitializeAdapter: Out with success\n"));
+
+	return NIC_STATUS_SUCCESS;
+
+}
+
+/*++
+
+Routine Name:
+
+	tc90x_AllocateSharedMemory.
+
+Routine Description:
+
+	This routine allocates the shared memory
+
+Arguments:
+
+	Device - Pointer to the device structure
+
+Return Value:
+
+	NIC_STATUS_SUCCESS if memory allocations succeeds
+	NIC_STATUS_FAILURE if memory allocation fails
+
+--*/
+
+NIC_STATUS
+tc90x_AllocateSharedMemory(
+	IN PNIC_INFORMATION Adapter
+    	)
+{
+	PNIC_INFORMATION pAdapter = Adapter; 
+	PDEVICE device = pAdapter->Device;
+
+	ULONG updMemoryForOne, totalUPDMemory;
+	ULONG dpdMemoryForOne, totalDPDMemory;
+
+	ULONG rxMemoryForOne;
+
+	ULONG cacheLineSize, count, alignment;
+
+    ULONG memoryBaseVirtual, memoryBasePhysical;
+	ULONG updMemoryVirtualStart, updMemoryPhysicalStart;
+	ULONG dpdMemoryVirtualStart, dpdMemoryPhysicalStart;
+
+    ULONG currentUPDPhysical, previousUPDPhysical;
+	ULONG firstUPDPhysical = 0;
+
+    PUPD_LIST_ENTRY currentUPDVirtual = NULL;
+	PUPD_LIST_ENTRY firstUPDVirtual = NULL;
+	PUPD_LIST_ENTRY previousUPDVirtual = NULL;
+
+	PUCHAR dataPointer;
+
+	PDPD_LIST_ENTRY currentDPDVirtual = NULL;
+	PDPD_LIST_ENTRY headDPDVirtual = NULL;
+	PDPD_LIST_ENTRY previousDPDVirtual = NULL;
+	ULONG currentDPDPhysical = 0;
+
+    	ULONG testMemoryVirtualStart, testMemoryPhysicalStart;
+	ULONG totalTestMemory;
+
+	DBGPRINT_FUNCTION(("tc90x_AllocateSharedMemory: In\n"));
+
+	cacheLineSize = pAdapter->Hardware.CacheLineSize;
+	//
+	// UPD structure memory requirement.
+	//
+	updMemoryForOne = sizeof(UPD_LIST_ENTRY) + cacheLineSize;
+	totalUPDMemory = pAdapter->Resources.ReceiveCount * updMemoryForOne;
+	//
+	// Receive buffer requirement.
+	//
+	rxMemoryForOne = ETHERNET_MAXIMUM_FRAME_SIZE + cacheLineSize;
+	//
+	// DPD structure memory requirement.
+	//
+	dpdMemoryForOne = sizeof(DPD_LIST_ENTRY) + cacheLineSize;
+	totalDPDMemory = pAdapter->Resources.SendCount * dpdMemoryForOne;
+	//
+	// Calculate the test memory required.
+	//	
+	totalTestMemory =  MAXIMUM_TEST_BUFFERS *
+			  (dpdMemoryForOne + rxMemoryForOne);
+
+	pAdapter->Resources.SharedMemorySize	= totalUPDMemory + 
+                                                  totalDPDMemory +
+												totalTestMemory;
+	//
+	// Allocate the memory
+	//
+	pAdapter->Resources.SharedMemoryVirtual =
+			(PUCHAR) kmalloc(
+					pAdapter->Resources.SharedMemorySize,
+					GFP_KERNEL);
+
+	pAdapter->ResourcesReserved |= NIC_SHARED_MEMORY_ALLOCATED;
+    //
+	// Zero out the memory.
+	//
+	memset(
+		pAdapter->Resources.SharedMemoryVirtual, 
+		0, 
+		pAdapter->Resources.SharedMemorySize);
+    //
+	// -------------- Carve out the regions ---------------
+	//
+	memoryBaseVirtual = (ULONG)pAdapter->Resources.SharedMemoryVirtual;
+	memoryBasePhysical = virt_to_bus(
+				pAdapter->Resources.SharedMemoryVirtual);
+
+	DBGPRINT_INITIALIZE(("memoryBaseVirtual = %x, memoryBasePhysical =%x\n",
+			(INT)memoryBaseVirtual,
+			(INT)memoryBasePhysical));
+	//
+	// Virtual addresses of the regions.
+	//
+	updMemoryVirtualStart = memoryBaseVirtual;
+	dpdMemoryVirtualStart = updMemoryVirtualStart + totalUPDMemory;
+    testMemoryVirtualStart = dpdMemoryVirtualStart + totalDPDMemory;
+	//
+	// Physical addresses of the regions.
+	//
+	updMemoryPhysicalStart = memoryBasePhysical;
+	dpdMemoryPhysicalStart = updMemoryPhysicalStart + totalUPDMemory;
+    testMemoryPhysicalStart = dpdMemoryPhysicalStart + totalDPDMemory;
+	//
+	// -------------- Make the receive structures -------------- 
+	//
+	for (count = 0; count < pAdapter->Resources.ReceiveCount; count++) {
+
+        	currentUPDPhysical = updMemoryPhysicalStart + 
+                             	     count * updMemoryForOne;
+
+        	alignment = cacheLineSize - 
+			    (currentUPDPhysical % cacheLineSize );
+		currentUPDPhysical += alignment;
+
+        	currentUPDVirtual = (PUPD_LIST_ENTRY)(
+                            	    updMemoryVirtualStart + 
+                            	    alignment +
+				    count * updMemoryForOne );
+        //
+		// Store the physical address of this UPD in the UPD itself.
+		//
+		currentUPDVirtual->UPDPhysicalAddress = currentUPDPhysical;
+
+        	if (0 == count) {
+			//
+			// Store the virtual and physical address of the 
+			// first UPD.
+            		firstUPDVirtual = currentUPDVirtual;
+			firstUPDPhysical = currentUPDPhysical;
+
+        	}
+		else {
+			//
+			// Put the links in the UPDs.
+			//
+			previousUPDVirtual->Next = currentUPDVirtual;
+			previousUPDVirtual->UpNextPointer = currentUPDPhysical;
+			currentUPDVirtual->Previous = previousUPDVirtual;
+
+        	}
+		//
+		// Allocate the skb per UPD
+		//
+		currentUPDVirtual->SocketBuffer = 
+					DEV_ALLOC_SKB(
+						ETHERNET_MAXIMUM_FRAME_SIZE +
+						2);
+        //
+		// Make the current UPD as the previous one.
+		//
+		if (currentUPDVirtual->SocketBuffer == 0) {
+
+			DBGPRINT_ERROR((
+				"Socket buffer allocation failed\n"));
+			return NIC_STATUS_FAILURE;
+		}
+		else {
+			
+			currentUPDVirtual->SocketBuffer->dev = device;
+			//
+			// Align IP on 16 byte boundaries
+			//
+			skb_reserve(
+				currentUPDVirtual->SocketBuffer,
+				2);
+
+			dataPointer = skb_put(
+					currentUPDVirtual->SocketBuffer,
+					ETHERNET_MAXIMUM_FRAME_SIZE );
+		}
+		
+		currentUPDVirtual->RxBufferVirtual = dataPointer;
+        	currentUPDVirtual->SGList[0].Address = virt_to_bus(dataPointer);
+		currentUPDVirtual->SGList[0].Count = 
+				ETHERNET_MAXIMUM_FRAME_SIZE | 0x80000000;
+
+		previousUPDVirtual = currentUPDVirtual;
+		previousUPDPhysical = currentUPDPhysical;
+
+    	}
+	//
+	// Link the first and last UPDs.
+	//
+
+	currentUPDVirtual->Next = firstUPDVirtual;
+	currentUPDVirtual->UpNextPointer = firstUPDPhysical;
+	firstUPDVirtual->Previous = currentUPDVirtual;
+	//
+	// Save the address of the first UPD in the adapter structure.
+	//
+	pAdapter->HeadUPDVirtual = firstUPDVirtual;
+
+	//
+	// --------------- Carve out DPD structures -----------------
+	//
+
+	for (count=0; count < pAdapter->Resources.SendCount; count++) {
+
+		currentDPDPhysical = dpdMemoryPhysicalStart + 
+                             	     count * dpdMemoryForOne;
+
+		alignment = cacheLineSize - 
+			    (currentDPDPhysical % cacheLineSize);
+		currentDPDPhysical += alignment;
+
+		currentDPDVirtual = (PDPD_LIST_ENTRY)(
+                                    dpdMemoryVirtualStart +
+                                    count * dpdMemoryForOne +
+                                    alignment);
+		//
+		// Save the physical address of this DPD in the DPD itself.
+		//                                        
+		currentDPDVirtual->DPDPhysicalAddress = currentDPDPhysical;
+
+        	if (0 == count) {
+
+			headDPDVirtual = currentDPDVirtual;
+
+        	}
+		else {
+
+			previousDPDVirtual->Next = currentDPDVirtual;
+			currentDPDVirtual->Previous = previousDPDVirtual;
+		}
+        	previousDPDVirtual = currentDPDVirtual;
+    	}
+
+	//
+	// Link head and tail.
+	//
+	headDPDVirtual->Previous = currentDPDVirtual;
+	currentDPDVirtual->Next = headDPDVirtual;
+	//
+	// Point head and tail to this DPD.
+	//
+	pAdapter->HeadDPDVirtual = headDPDVirtual;
+	pAdapter->TailDPDVirtual = headDPDVirtual;
+
+	//
+	// -------------- Test DPD and test buffer -----------------
+	//
+
+	for ( count = 0; count < MAXIMUM_TEST_BUFFERS; count++ ) {
+
+		alignment = cacheLineSize - 
+			    (testMemoryPhysicalStart % cacheLineSize);
+		pAdapter->TestDPDVirtual[count] = testMemoryVirtualStart + 
+						  alignment;
+		pAdapter->TestDPDPhysical[count] = testMemoryPhysicalStart + 
+						   alignment;
+
+		testMemoryVirtualStart += dpdMemoryForOne;
+		testMemoryPhysicalStart += dpdMemoryForOne;
+
+		alignment = cacheLineSize - 
+			    (testMemoryPhysicalStart % cacheLineSize);
+
+		pAdapter->TestBufferVirtual[count] = 
+				testMemoryVirtualStart + alignment;
+		pAdapter->TestBufferPhysical[count] = 
+				testMemoryPhysicalStart + alignment;
+		//
+		// Save the physical address of the DPD, in the DPD.
+		//
+		((PDPD_LIST_ENTRY)
+		(pAdapter->TestDPDVirtual[count]))->DPDPhysicalAddress =
+		                        pAdapter->TestDPDPhysical[count];
+
+		testMemoryVirtualStart += rxMemoryForOne;
+		testMemoryPhysicalStart += rxMemoryForOne;
+
+	}
+
+	DBGPRINT_FUNCTION(("tc90x_AllocateSharedMemory: Out\n"));
+	return NIC_STATUS_SUCCESS;
+}
+
+/*++
+
+Routine Name:
+
+    TestAdapter.
+
+Routine Description:
+
+    This routine tests the functionality of the adapter.
+
+Arguments:
+
+    MiniportAdapterContext - Pointer to the adapter structure.
+
+Return Value:
+
+    NIC_STATUS_SUCCESS if the adapter is functioning properly.
+    NIC_STATUS_FAILURE if the adapter is not functioning properly.
+
+--*/
+
+NIC_STATUS
+tc90x_TestAdapter(
+	IN PNIC_INFORMATION Adapter
+    	)
+
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	NIC_STATUS nicStatus;
+	PDPD_LIST_ENTRY dpdVirtual;
+	PUPD_LIST_ENTRY updVirtual;
+	PUCHAR sourceBufferVirtual, destinationBufferVirtual;
+	ULONG sourceBufferPhysical;
+	ULONG  count;
+	USHORT networkDiagnosticsValue;
+	ULONG portValue;
+
+	DBGPRINT_FUNCTION(("TestAdapter: IN \n"));
+	//
+	// Select the network diagnostics window.
+	//
+	NIC_COMMAND( 
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	//
+	// Read the network diagnostics register.
+	//
+	networkDiagnosticsValue = NIC_READ_PORT_USHORT(
+					pAdapter,
+					NETWORK_DIAGNOSTICS_REGISTER);
+	//
+	// Enable loop back on the adapter.
+	//
+
+	networkDiagnosticsValue |= BIT_12;
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		NETWORK_DIAGNOSTICS_REGISTER,
+		networkDiagnosticsValue);
+
+	NIC_COMMAND(pAdapter, COMMAND_TX_ENABLE);
+	NIC_COMMAND(pAdapter, COMMAND_RX_ENABLE);
+	//
+	// Write the address to the UpListPointer register.
+	//
+
+	NIC_WRITE_PORT_ULONG(
+		pAdapter,
+		UP_LIST_POINTER_REGISTER,
+		pAdapter->HeadUPDVirtual->UPDPhysicalAddress);
+
+	NIC_COMMAND(pAdapter, COMMAND_UP_UNSTALL);
+	//
+	// Use the buffer in the second UPD to make the packet.
+	//
+    sourceBufferVirtual = (PUCHAR)pAdapter->TestBufferVirtual[0];
+	sourceBufferPhysical = pAdapter->TestBufferPhysical[0];
+    
+	for (count=0; count < ETHERNET_MAXIMUM_FRAME_SIZE; count++) {
+
+        *sourceBufferVirtual++ = (UCHAR)count;
+    }
+    
+	dpdVirtual = (PDPD_LIST_ENTRY)pAdapter->TestDPDVirtual[0];
+	dpdVirtual->FrameStartHeader = ETHERNET_MAXIMUM_FRAME_SIZE; 
+	dpdVirtual->DownNextPointer = 0;
+	dpdVirtual->SGList[0].Address = sourceBufferPhysical;
+	dpdVirtual->SGList[0].Count = ETHERNET_MAXIMUM_FRAME_SIZE |
+                                  	0x80000000;
+
+	NIC_COMMAND_WAIT(pAdapter, COMMAND_DOWN_STALL);
+	//
+	// Write the down list pointer register.
+	//
+	NIC_WRITE_PORT_ULONG(
+		pAdapter,
+		DOWN_LIST_POINTER_REGISTER,
+		dpdVirtual->DPDPhysicalAddress);
+
+	NIC_COMMAND(pAdapter, COMMAND_DOWN_UNSTALL);
+	//
+	// Check that packet has been picked up by the hardware.
+	//
+	count = jiffies + HZ;
+	do {
+        portValue = NIC_READ_PORT_ULONG(
+ 					pAdapter,
+					DOWN_LIST_POINTER_REGISTER);
+        NIC_DELAY(10);
+	} while ( (portValue == dpdVirtual->DPDPhysicalAddress) &&
+		      ( count > jiffies) );
+
+	if (count < jiffies) {
+        DBGPRINT_ERROR(("TestAdapter: Packet not picked up the hardware\n"));
+		DBGPRINT_INITIALIZE(("TestAdapter: Out with error\n"));
+       	return NIC_STATUS_FAILURE;
+	}
+	//
+	// Check the upload information.
+	//
+	count = jiffies + HZ;
+	do {
+        portValue = NIC_READ_PORT_ULONG(
+							pAdapter,
+							UP_LIST_POINTER_REGISTER);
+		NIC_DELAY(10);
+	} while ( (portValue = pAdapter->HeadUPDVirtual->UPDPhysicalAddress) &&
+			  (count > jiffies) );
+
+	if (count < jiffies) {
+        DBGPRINT_ERROR(("TestAdapter: Packet not uploaded by adapter\n"));
+		DBGPRINT_INITIALIZE(("TestAdapter: Out with error\n"));
+        return NIC_STATUS_FAILURE;
+	}
+	//
+	// Check the contents of the packet.
+	//
+	updVirtual = pAdapter->HeadUPDVirtual;
+	destinationBufferVirtual = (PUCHAR)updVirtual->RxBufferVirtual;
+
+	for (count=0; count < ETHERNET_MAXIMUM_FRAME_SIZE; count++) {
+
+        	if (*(destinationBufferVirtual + count) != (UCHAR)count) 
+            		break;
+	}
+            
+	if (ETHERNET_MAXIMUM_FRAME_SIZE != count) {
+
+        DBGPRINT_ERROR((
+                	"TestAdapter: Receive buffer contents not ok\n"));
+		DBGPRINT_INITIALIZE(("TestAdapter: Out with error\n"));
+        return NIC_STATUS_FAILURE;
+
+	}
+
+	pAdapter->HeadUPDVirtual->UpPacketStatus = 0;
+
+	NIC_WRITE_PORT_ULONG(pAdapter, UP_LIST_POINTER_REGISTER, 0);
+	NIC_ACKNOWLEDGE_ALL_INTERRUPT(pAdapter);
+	//
+	// Issue transmit and receive reset here.
+	//
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        DBGPRINT_ERROR(("TestAdapter: Transmit reset failed\n"));
+		DBGPRINT_INITIALIZE(("TestAdapter: Out with error\n"));
+        return NIC_STATUS_FAILURE;
+
+    	}
+
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR(("TestAdapter: Receiver reset failed\n"));
+	        DBGPRINT_INITIALIZE(("TestAdapter: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+        
+    	}       
+	//
+	// Clear the loop back bit in network diagnostics.
+	//
+	networkDiagnosticsValue &= ~BIT_12;
+
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		NETWORK_DIAGNOSTICS_REGISTER,
+		networkDiagnosticsValue);
+
+	DBGPRINT_FUNCTION(("TestAdapter: Out with success\n"));
+	return NIC_STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Name:
+
+    StartAdapter.
+
+Routine Description:
+
+    This routine starts the adapter.
+
+Arguments:
+
+    MiniportAdapterContext - Pointer to the adapter structure.
+
+Return Value:
+
+    None.
+
+--*/
+
+NIC_STATUS
+tc90x_StartAdapter(
+	IN PNIC_INFORMATION Adapter
+    	)
+{
+
+	PNIC_INFORMATION pAdapter = Adapter;
+	NIC_STATUS nicStatus;
+	PDPD_LIST_ENTRY headDPDVirtual;
+	USHORT diagnostics;
+	ULONG dmaControl;
+	ULONG TimeOutCount;
+	DBGPRINT_FUNCTION(("StartAdapter: In\n"));
+
+
+	//
+	// Enable upper bytes counting in diagnostics register.
+	//
+
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	diagnostics = NIC_READ_PORT_USHORT(
+			pAdapter,
+            NETWORK_DIAGNOSTICS_REGISTER);
+
+	diagnostics |= NETWORK_DIAGNOSTICS_UPPER_BYTES_ENABLE;
+
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		NETWORK_DIAGNOSTICS_REGISTER,
+		diagnostics);
+	//
+	// Enable counter speed in DMA control.
+	//
+	dmaControl = NIC_READ_PORT_ULONG(
+			pAdapter,
+            DMA_CONTROL_REGISTER);
+
+	if (100000000 == pAdapter->Hardware.LinkSpeed)
+        	dmaControl |= DMA_CONTROL_COUNTER_SPEED;
+
+	NIC_WRITE_PORT_ULONG(
+		pAdapter,
+		DMA_CONTROL_REGISTER,
+		dmaControl);        
+	//
+	// ------------ Give download structures to the adapter -----
+	//
+	// Stall the download engine.
+	//
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_DOWN_STALL);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR(("StartAdapter: down stall failed\n"));
+        	DBGPRINT_INITIALIZE(("StartAdapter: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+
+    	}
+    //
+	// Use the head DPD to mark it as dummy.
+	//
+	headDPDVirtual = pAdapter->HeadDPDVirtual;
+	headDPDVirtual->FrameStartHeader = FSH_DPD_EMPTY;
+	//
+	// Now move head and tail to next one. 
+	//
+	pAdapter->HeadDPDVirtual = headDPDVirtual->Next;
+	pAdapter->TailDPDVirtual = headDPDVirtual->Next;
+	//
+	// Write the first DPD address to the hardware.
+	//
+	NIC_WRITE_PORT_ULONG(
+		pAdapter,
+		DOWN_LIST_POINTER_REGISTER,
+		headDPDVirtual->DPDPhysicalAddress);
+	//
+	// Enable down polling on the hardware.
+	//
+	NIC_WRITE_PORT_UCHAR(
+		pAdapter,
+		DOWN_POLL_REGISTER,
+		(UCHAR)pAdapter->Resources.DownPollRate);
+	//
+	// Unstall the download engine.
+	//
+	NIC_COMMAND(pAdapter, COMMAND_DOWN_UNSTALL);
+	//
+	// ------------ Give upload structures to the adapter -------
+	//
+    //
+	// Stall the upload engine.
+	//
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_UP_STALL);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR(("StartAdapter: up stall failed\n"));
+        	DBGPRINT_INITIALIZE(("StartAdapter: Out with error\n"));
+        	return NIC_STATUS_FAILURE;
+    	}
+	//
+	// Give the address of the first UPD to the adapter.
+	//
+
+	NIC_WRITE_PORT_ULONG(
+		pAdapter,
+		UP_LIST_POINTER_REGISTER,
+		pAdapter->HeadUPDVirtual->UPDPhysicalAddress);
+	//
+	// Write the up poll register.
+	//
+	NIC_WRITE_PORT_UCHAR(
+		pAdapter,
+		UP_POLL_REGISTER,
+            	8);
+	//
+	// Unstall the download engine.
+	//
+	NIC_COMMAND(pAdapter, COMMAND_UP_UNSTALL);
+	//
+	// Enable the statistics back.
+	//
+	NIC_COMMAND(pAdapter, COMMAND_STATISTICS_ENABLE);
+	//
+	// Acknowledge any pending interrupts.
+	//
+	NIC_ACKNOWLEDGE_ALL_INTERRUPT(pAdapter);
+	//
+	// Enable indication for all interrupts.
+	//
+	NIC_ENABLE_ALL_INTERRUPT_INDICATION(pAdapter);
+	//
+	// Enable all interrupts to the host.
+	//
+	NIC_UNMASK_ALL_INTERRUPT(pAdapter);
+	//
+	// Enable the transmit and receive engines.
+	//
+	NIC_COMMAND(pAdapter, COMMAND_RX_ENABLE);
+	NIC_COMMAND(pAdapter, COMMAND_TX_ENABLE);
+	//
+	// Delay three seconds, only some switches need this,
+	// default is no delay, user can enable this delay in command line
+	//
+	if(pAdapter->DelayStart == TRUE) {
+		TimeOutCount = jiffies + (3*HZ);
+		while(TimeOutCount > jiffies);
+	}
+
+	DBGPRINT_FUNCTION(("StartAdapter: Out\n"));
+	return NIC_STATUS_SUCCESS;
+}
+
+/*++
+
+Routine Name:
+
+    ReStartAdapter.
+
+Routine Description:
+
+    This routine starts the adapter.
+
+Arguments:
+
+    MiniportAdapterContext - Pointer to the adapter structure.
+
+Return Value:
+
+    None.
+
+--*/
+
+VOID
+ReStartAdapter(
+	//IN PNIC_INFORMATION Adapter
+	PVOID Adapter
+    	)
+{
+	
+	PNIC_INFORMATION pAdapter = Adapter;	
+	ULONG internalConfig = pAdapter->keepForGlobalReset;
+	ULONG TimeOutCount;
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "ReStartAdapter after global reset: IN\n"));
+	//
+	// Delay for 1 second, might not be that long since
+	// some has been comsumed with task queue 
+	TimeOutCount = jiffies + HZ;
+	while(TimeOutCount > jiffies);
+	//
+	// Mask all the interrupts.
+	//
+	NIC_MASK_ALL_INTERRUPT(pAdapter);
+	//
+	// Enable indication for all interrupts.
+	//
+	NIC_ENABLE_ALL_INTERRUPT_INDICATION(pAdapter);	
+	//
+	// Write the internal config back.
+	//
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	NIC_WRITE_PORT_ULONG(
+		pAdapter,
+		INTERNAL_CONFIG_REGISTER,
+		internalConfig);
+	//
+    // Set the adapter for operation
+    //
+	if (tc90x_GetAdapterProperties(pAdapter) != NIC_STATUS_SUCCESS)
+		DBGPRINT_INTERRUPT((KERN_CRIT "GetAdapterProperties failed\n"));	
+
+	if (tc90x_BasicInitializeAdapter(pAdapter) != NIC_STATUS_SUCCESS)
+		DBGPRINT_INTERRUPT((KERN_CRIT "BasicInitialize failed\n"));
+
+	if (tc90x_SetupMedia(pAdapter->Device) != NIC_STATUS_SUCCESS)
+		DBGPRINT_INTERRUPT((KERN_CRIT "SetupMedia failed\n"));
+	
+	if (tc90x_SoftwareWork(pAdapter) != NIC_STATUS_SUCCESS)
+		DBGPRINT_INTERRUPT((KERN_CRIT "SoftwareWork failed\n"));
+	//
+	// Countdown timer is cleared by reset. So write it back.
+	//
+	tc90x_SetCountDownTimer(pAdapter);
+	
+	pAdapter->DelayStart = FALSE; // no need to delay for switch here
+
+	if (tc90x_StartAdapter(pAdapter) != NIC_STATUS_SUCCESS)
+		DBGPRINT_INTERRUPT((KERN_CRIT "ReStartAdapter: StartAdapter failed\n"));
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "ReStartAdapter after global reset: OUT\n"));
+
+	return;
+}
+
+
+UCHAR firstTime = 0;
+
+/*++
+
+Routine Name:
+
+    NICSendPacket
+
+Routine Description:
+
+    This routine sends the packet 
+
+Arguments:
+
+	SocketBuffer - Pointer to the socket buffer
+	Device - Pointer to the device structure
+
+Return Value:
+
+	0 if packet could be sent
+	1 if packet could not be sent
+
+--*/
+
+INT
+NICSendPacket(
+	IN PSKB SocketBuffer,
+	IN PDEVICE Device
+	)
+{	
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
+	PDPD_LIST_ENTRY dpdVirtual;
+	ULONG packetLength;
+
+#if LINUX_VERSION_CODE < 0x20200
+	PDEVICE device = pAdapter->Device;
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20200
+	ULONG flags;
+#endif
+
+	if (test_and_set_bit(0, (void*)&Device->tbusy) != 0) {
+		DBGPRINT_SEND(("NICSendPacket: Device is busy\n")); 
+		return 1;
+	}
+	
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_lock_irqsave(&pAdapter->SpinLock, flags);
+#endif
+
+    if (pAdapter->TailDPDVirtual->Next == pAdapter->HeadDPDVirtual) {
+
+	//printk( KERN_CRIT "NICSendPackets: Out with resources: \n");
+	pAdapter->DPDRingFull = TRUE;
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_unlock_irqrestore(&pAdapter->SpinLock, flags);
+#endif
+        return 1;
+    }
+	//
+	// Get the free DPD from the DPD ring.
+	//
+	dpdVirtual = pAdapter->TailDPDVirtual;
+	//
+	// Zero out the frame start header.
+	//
+	dpdVirtual->FrameStartHeader = 0;
+
+	dpdVirtual->SGList[0].Address = virt_to_bus(
+						SocketBuffer->data);
+	packetLength = SocketBuffer->len;
+	dpdVirtual->SGList[0].Count = packetLength | 0x80000000;
+    	dpdVirtual->FrameStartHeader |= (ULONG)(FSH_ROUND_UP_DEFEAT); 
+    	dpdVirtual->SocketBuffer = SocketBuffer;
+	dpdVirtual->PacketLength = SocketBuffer->len;
+	dpdVirtual->DownNextPointer = 0;
+
+
+#if LINUX_VERSION_CODE < 0x20200
+	disable_irq(device->irq);
+#endif
+
+	pAdapter->BytesInDPDQueue += packetLength;
+    	pAdapter->TailDPDVirtual->Previous->DownNextPointer = 
+                               dpdVirtual->DPDPhysicalAddress;
+	pAdapter->TailDPDVirtual = dpdVirtual->Next;
+    	tc90x_SetCountDownTimer(pAdapter);
+
+#if LINUX_VERSION_CODE < 0x20200
+	enable_irq(device->irq);
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_unlock_irqrestore(&pAdapter->SpinLock, flags);
+#endif
+	clear_bit(0, (void*)&Device->tbusy);
+	//
+	// Set the transmission time.
+	//
+	Device->trans_start = jiffies;
+	return 0;
+}
+
+
+/*++
+
+Routine Name:
+
+	tc90x_TxCompleteEvent.
+
+Routine Description:
+
+	This routine handles the Tx complete event.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	None
+
+--*/
+
+VOID
+tc90x_TxCompleteEvent(
+	IN PNIC_INFORMATION Adapter
+	)
+
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+
+    UCHAR txStatus;
+		
+    DBGPRINT_ERROR((KERN_CRIT "TxCompleteEvent: IN\n"));
+
+    LOG_LABEL(pAdapter, "TCE>");
+
+	txStatus = NIC_READ_PORT_UCHAR(pAdapter, TX_STATUS_REGISTER);
+	NIC_WRITE_PORT_UCHAR(pAdapter, TX_STATUS_REGISTER, txStatus);
+
+	if (txStatus & TX_STATUS_HWERROR) {
+        //
+		// Transmit HWError recovery.
+		//
+		DBGPRINT_SEND(("TxCompleteEvent: TxHWError\n"));
+        pAdapter->Statistics.TxHWErrors++;		
+		if (tc90x_ResetAndEnableTransmitter(pAdapter) != 
+		    NIC_STATUS_SUCCESS) {
+
+			DBGPRINT_ERROR(("TxCompleteEvent: TxReset failed\n"));
+            pAdapter->Hardware.Status = HARDWARE_STATUS_HUNG;
+            return;
+
+        }
+
+    	}
+	else if (txStatus & TX_STATUS_JABBER) {
+
+        	DBGPRINT_ERROR(("TxCompleteEvent: Jabber\n"));
+        	pAdapter->Statistics.TxJabberError++;
+
+        	if (tc90x_ResetAndEnableTransmitter(pAdapter) != 
+		    NIC_STATUS_SUCCESS) {
+
+            	DBGPRINT_ERROR(("TxCompleteEvent: TxReset failed\n"));
+            	pAdapter->Hardware.Status = HARDWARE_STATUS_HUNG;
+            	return;
+        	}
+    }
+    else if (txStatus & TX_STATUS_MAXIMUM_COLLISION) {
+
+        	DBGPRINT_ERROR(("TxCompleteEvent: Maximum collision\n"));
+        	pAdapter->Statistics.TxMaximumCollisions++;
+        	NIC_COMMAND(pAdapter, COMMAND_TX_ENABLE);
+    	}
+	else {
+
+        if (txStatus != 0 ) {
+
+            DBGPRINT_ERROR((
+			KERN_CRIT "TxCompleteEvent: Unknown error\n"));
+            pAdapter->Statistics.TxUnknownError++;
+            NIC_COMMAND(pAdapter, COMMAND_TX_ENABLE);
+        }
+    }
+    	DBGPRINT_ERROR((KERN_CRIT "TxCompleteEvent: OUT\n"));
+}
+
+
+/*++
+
+Routine Name:
+
+	tc90x_ResetAndEnableTransmitter
+
+Routine Description:
+
+	This routine resets the transmitter.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	NIC_STATUS_SUCCESS if reset is successful.
+	NIC_STATUS_FAILURE if reset failed. 
+
+--*/
+
+
+NIC_STATUS
+tc90x_ResetAndEnableTransmitter(
+	IN PNIC_INFORMATION Adapter
+    	)
+
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT mediaStatus;
+	ULONG TimeOutCount,count, dmaControl;
+	NIC_STATUS nicStatus;
+
+	NIC_COMMAND(pAdapter, COMMAND_TX_DISABLE);
+	//
+	// Wait for the transmit to go quiet.
+	//
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	count = jiffies + HZ;
+	do {
+        mediaStatus = NIC_READ_PORT_USHORT(
+ 						pAdapter,
+                        MEDIA_STATUS_REGISTER);
+        NIC_DELAY(10);
+    } while ( (mediaStatus & MEDIA_STATUS_TX_IN_PROGRESS) &&
+			  (count > jiffies) );
+
+   	if (count < jiffies) {
+        DBGPRINT_ERROR((
+            		"tc90x_ResetAndEnableTransmitter: media status is hung\n"));
+        return NIC_STATUS_FAILURE;
+    }
+	
+#ifdef SERR_NEEDED
+    //
+    // Issue down stall and delay 100 miliseconds for PCI retries to be over
+    //
+    NIC_COMMAND_WAIT(pAdapter, COMMAND_DOWN_STALL);
+    TimeOutCount = jiffies + HZ/10;
+    while(TimeOutCount > jiffies);
+#endif
+    //
+    // Wait for download engine to stop
+    //
+	count = jiffies + HZ;
+	do {
+        dmaControl = NIC_READ_PORT_ULONG(
+                            	pAdapter, 
+				DMA_CONTROL_REGISTER);
+        NIC_DELAY(10);
+    } while ( (dmaControl & DMA_CONTROL_DOWN_IN_PROGRESS) &&
+			  (count > jiffies) );
+
+	if (count < jiffies) {
+        DBGPRINT_ERROR((
+           	"tc90x_ResetAndEnableTransmitter: DMAControl hung\n"));
+        return NIC_STATUS_FAILURE;
+    }
+
+	nicStatus = NIC_COMMAND_WAIT(
+                      pAdapter, 
+                      COMMAND_TX_RESET | 
+                      TX_RESET_MASK_DOWN_RESET );
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        DBGPRINT_ERROR((
+            "tc90x_ResetAndEnableTransmitter: Tx reset failed\n"));
+        return NIC_STATUS_FAILURE;
+
+    }
+
+	NIC_COMMAND(pAdapter, COMMAND_TX_ENABLE);
+
+	return NIC_STATUS_SUCCESS;
+}
+
+
+
+/*++
+
+Routine Name:
+
+	tc90x_CleanupSendLogic
+
+Routine Description:
+
+	This routines cleans the send logic.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	None
+
+--*/
+
+VOID
+tc90x_CleanupSendLogic(
+	IN PDEVICE Device
+    )
+
+{
+    PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
+    PDPD_LIST_ENTRY headDPDVirtual;
+
+    DBGPRINT_SEND(("tc90x_CleanupSendLogic: IN\n"));
+    //
+    // Now clean up the DPD ring.
+    //
+    headDPDVirtual = pAdapter->HeadDPDVirtual;
+    //
+    // This is to take care of hardware raise condition.
+    //
+    pAdapter->TailDPDVirtual->FrameStartHeader = 0;
+
+    while (1) {
+
+        if (headDPDVirtual == pAdapter->TailDPDVirtual)
+            break;
+        //
+        // Complete all the packets.
+        //
+        pAdapter->BytesInDPDQueue -= headDPDVirtual->PacketLength;
+
+		DEV_FREE_SKB(headDPDVirtual->SocketBuffer);
+
+		headDPDVirtual->SocketBuffer = NULL;
+        headDPDVirtual->FrameStartHeader = 0;
+
+        headDPDVirtual = headDPDVirtual->Next;
+    }
+    //
+    // Update the head to point to this DPD now.
+    //
+    pAdapter->HeadDPDVirtual = headDPDVirtual;
+    //
+    // Initialize all DPDs.
+    //
+    headDPDVirtual = pAdapter->HeadDPDVirtual;
+
+    while (1) {
+
+        headDPDVirtual->DownNextPointer = 0;
+        headDPDVirtual->SocketBuffer = NULL;
+        headDPDVirtual->FrameStartHeader = 0;
+        headDPDVirtual = headDPDVirtual->Next;
+        if (headDPDVirtual == pAdapter->HeadDPDVirtual)
+            break;
+    }
+
+    DBGPRINT_SEND(("tc90x_CleanupSendLogic: OUT\n"));
+}
+
+
+
+
+
+/*++
+
+Routine Name:
+
+	tc90x_UpCompleteEvent
+
+Routine Description:
+
+	This routine handles the receive event.
+
+Arguments:
+
+	Adapter - Pointer to the adapter structure
+
+Return Value:
+
+	None
+
+--*/
+
+VOID
+tc90x_UpCompleteEvent(
+	IN PNIC_INFORMATION Adapter
+    	)
+
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	PDEVICE device = pAdapter->Device;
+	PUPD_LIST_ENTRY currentUPDVirtual = pAdapter->HeadUPDVirtual;
+
+	PSKB socketBuffer;
+
+	ULONG upPacketStatus;
+	ULONG frameLength;
+	PUCHAR dataPointer;
+	PETH_ADDR EthAddr;
+
+	DBGPRINT_RECEIVE(("UpCompleteEvent: IN \n"));
+	LOG_LABEL(pAdapter, "UCE>");
+
+
+	while (1) {	
+		//
+		// If done with all UPDs break.
+		//
+		upPacketStatus = currentUPDVirtual->UpPacketStatus;
+
+		if (!(upPacketStatus & UP_PACKET_STATUS_COMPLETE)) {
+                	break;
+            	}
+            	//
+            	// Get the frame length from the UPD.
+            	//
+            	frameLength = currentUPDVirtual->UpPacketStatus & 0x1FFF; 
+            	//
+            	// Check if there is any error bit set.
+            	//
+            	if (upPacketStatus & UP_PACKET_STATUS_ERROR) {
+					
+                	if ((frameLength < ETHERNET_MINIMUM_FRAME_SIZE) ||
+                    	    (upPacketStatus & UP_PACKET_STATUS_OVERRUN) ||
+                    	    (upPacketStatus & UP_PACKET_STATUS_ALIGNMENT_ERROR) ||
+                    	    (upPacketStatus & UP_PACKET_STATUS_CRC_ERROR) ||
+                    	    (upPacketStatus & UP_PACKET_STATUS_OVERSIZE_FRAME)) { 
+
+					if (upPacketStatus & UP_PACKET_STATUS_RUNT_FRAME) {
+                        DBGPRINT_ERROR(("UpCompleteEvent: Runt\n"));
+	                    LOG_LABEL(pAdapter, "RUNT");
+					}                    
+					if (upPacketStatus & UP_PACKET_STATUS_ALIGNMENT_ERROR) {
+                        LOG_LABEL(pAdapter, "ALGN");
+						DBGPRINT_ERROR(("UpCompleteEvent: Alignment\n"));
+                        pAdapter->Statistics.RxAlignmentError++;
+
+					}
+                    if (upPacketStatus & UP_PACKET_STATUS_CRC_ERROR) {
+                        LOG_LABEL(pAdapter, "CRC ");
+		                DBGPRINT_ERROR(("UpCompleteEvent: Crc\n"));
+                        pAdapter->Statistics.RxBadCRCError++;
+
+                    }
+                    if (upPacketStatus & UP_PACKET_STATUS_OVERSIZE_FRAME){
+                        LOG_LABEL(pAdapter, "OVSZ");
+                        DBGPRINT_ERROR(("UpCompleteEvent: Oversize\n"));
+                        pAdapter->Statistics.RxOversizeError++;
+
+                    }
+                    		//
+                    		// Discard this packet and move on.
+                    		//
+                    		currentUPDVirtual->UpPacketStatus = 0;
+                    		currentUPDVirtual = currentUPDVirtual->Next;
+                    		continue;
+                	}
+	                else {
+		                        		
+			//
+			// Check for Multicast
+			//
+			EthAddr = (PETH_ADDR)(&(currentUPDVirtual->SGList[0].Address));
+			if( (EthAddr->Addr[0] & ETH_MULTICAST_BIT) &&
+				!(COMPARE_MACS(EthAddr, BroadcastAddr)) )
+				pAdapter->Statistics.Rx_MulticastPkts++;
+
+                    pAdapter->Statistics.RxFramesOk++; 
+		    pAdapter->Statistics.RxBytesOk += frameLength;
+
+                }
+        }
+		//
+		// Try to allocate SKB
+		//
+		socketBuffer = DEV_ALLOC_SKB(
+					ETHERNET_MAXIMUM_FRAME_SIZE + 2 +
+					pAdapter->Hardware.CacheLineSize);
+
+		if (socketBuffer != 0) {
+			
+			socketBuffer->dev = device;
+			//
+			// Align IP on 16 byte boundaries
+			//
+			skb_reserve(socketBuffer, 2);
+
+			dataPointer = skb_put(
+					socketBuffer,
+					ETHERNET_MAXIMUM_FRAME_SIZE );
+
+        	currentUPDVirtual->SGList[0].Address = 
+								virt_to_bus(dataPointer);
+
+			currentUPDVirtual->SGList[0].Count = 
+					ETHERNET_MAXIMUM_FRAME_SIZE | 0x80000000;
+
+			currentUPDVirtual->RxBufferVirtual = dataPointer;
+			//
+			// Check for Multicast
+			//
+			/*EthAddr = (PETH_ADDR)(&dataPointer);
+			if( (EthAddr->Addr[0] & ETH_MULTICAST_BIT) &&
+				!(COMPARE_MACS(EthAddr, BroadcastAddr)) )
+				pAdapter->Statistics.Rx_MulticastPkts++;
+			*/
+			currentUPDVirtual->SocketBuffer->protocol = 
+				eth_type_trans(
+					currentUPDVirtual->SocketBuffer,
+					device);
+			
+			SetRxTcpIpChecksumOffloadFlagsInSocketBuffer(
+				pAdapter,
+				currentUPDVirtual->SocketBuffer,
+				currentUPDVirtual->UpPacketStatus);
+
+			netif_rx(currentUPDVirtual->SocketBuffer);
+			device->last_rx = jiffies;
+			currentUPDVirtual->SocketBuffer = socketBuffer;
+
+		}
+		else {
+
+			printk( KERN_CRIT "SKB allocation failed\n");
+			DBGPRINT_ERROR((
+				"UpCompleteEvent: SKB allocation failed\n"));
+
+		}
+            currentUPDVirtual->UpPacketStatus = 0;
+        	currentUPDVirtual = currentUPDVirtual->Next;
+    }
+    	pAdapter->HeadUPDVirtual = currentUPDVirtual;
+
+    	DBGPRINT_RECEIVE(("UpCompleteEvent: OUT \n"));
+    	LOG_LABEL(pAdapter, "UCE<");
+
+}
+
+
+/*++
+
+Routine Name:
+
+	tc90x_ResetAndEnableReceiver.
+
+Routine Description:
+
+	This routine resets the receiver.
+
+Arguments:
+
+	Adapter - Pointer to the adapter structure
+
+Return Value:
+
+    	NIC_STATUS_SUCCESS if reset succeeds.
+
+--*/
+
+NIC_STATUS
+tc90x_ResetAndEnableReceiver(
+	IN PNIC_INFORMATION Adapter
+    	)
+
+{
+
+    PNIC_INFORMATION pAdapter = Adapter;
+
+    NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_DISABLE);
+    NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+    NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_ENABLE);
+
+    return NIC_STATUS_SUCCESS;
+
+}
+
+
+
+
+/*++
+
+Routine Name:
+
+    NICIoctl
+
+Routine Description:
+
+    This routine is IOCTL handler.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	-ENODEV if no adapter found
+	noAdapterFound if adapter(s) found
+
+--*/
+
+INT NICIoctl( IN PDEVICE Device,
+					 IN PIFREQ Request,
+					 IN INT command )
+{	
+	BOOLEAN PhyResponding;
+	long ioaddr;
+	u16 *data;
+	USHORT phy;
+	PNIC_INFORMATION pAdapter;
+
+	DBGPRINT_IOCTL(("NICIoctl: IN\n"));
+	
+	pAdapter = (PNIC_INFORMATION)Device->priv;
+	ioaddr = Device->base_addr;
+	data = (u16 *)&Request->ifr_data;
+	phy = pAdapter->Hardware.phys;
+
+	switch(command) {
+
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		data[0] = phy;
+		/* Fall Through */
+
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		
+		PhyResponding = ReadMIIPhy(pAdapter, data[0], (PUSHORT)&data[3]);
+		if (!PhyResponding)
+			DBGPRINT_ERROR(("IOCTL-ReadPhy: Phy not responding"));
+		return 0;
+
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!suser())
+			return -EPERM;
+		WriteMIIPhy(pAdapter, data[0], data[2]); 
+		return 0;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+/*++
+
+Routine Name:
+
+	NICSetReceiveMode
+
+Routine Description:
+
+	This routine sets receive mode 
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	-ENODEV if no adapter found
+	noAdapterFound if adapter(s) found
+
+--*/
+
+VOID
+NICSetReceiveMode(
+	IN PDEVICE Device
+	)
+{
+
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
+	ULONG count, hardwareReceiveFilter = 0;
+	UCHAR flowControlAddress[ETHERNET_ADDRESS_SIZE];
+	UCHAR broadcastAddress[ETHERNET_ADDRESS_SIZE];
+	UCHAR address[ETHERNET_ADDRESS_SIZE];
+	ULONG numberMulticast, bitsInHashFilter, index;
+	PDEV_MC_LIST multicastList; 
+
+
+	DBGPRINT_FUNCTION(("NICSetReceiveMode: In\n"));
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_lock(&pAdapter->SpinLock);
+#endif
+
+	bitsInHashFilter = pAdapter->Hardware.BitsInHashFilter;
+	//
+	// Check if Promiscuous mode to be enabled.
+	//
+	if (Device->flags & IFF_PROMISC) {
+
+		DBGPRINT_INITIALIZE(("IFF_PROMISC mode \n"));
+		hardwareReceiveFilter |= RX_FILTER_PROMISCUOUS;
+	}
+	else if (Device->flags & IFF_ALLMULTI) {
+		//
+		// Check if ALL_MULTI mode to be enabled.
+		//
+		DBGPRINT_INITIALIZE(("IFF_ALLMULTI\n"));
+		hardwareReceiveFilter |= RX_FILTER_INDIVIDUAL;
+		hardwareReceiveFilter |= RX_FILTER_BROADCAST;
+		hardwareReceiveFilter |= RX_FILTER_ALL_MULTICAST;
+	}
+	else  if (Device->flags & IFF_MULTICAST) {
+		//
+		// Check if hash multicast to be enabled.
+		//
+		DBGPRINT_INITIALIZE(("IFF_MULTICAST\n"));
+		hardwareReceiveFilter |= RX_FILTER_INDIVIDUAL;
+		hardwareReceiveFilter |= RX_FILTER_BROADCAST;
+		hardwareReceiveFilter |= RX_FILTER_MULTICAST_HASH;
+	}
+	else {
+		//
+		// OS does not want to enable multicast.
+		//
+		DBGPRINT_INITIALIZE((
+			"Setting filter individual and broadcast\n"));
+		hardwareReceiveFilter |= RX_FILTER_INDIVIDUAL;
+		hardwareReceiveFilter |= RX_FILTER_BROADCAST;
+	}
+	//
+	// Write the Rx filter
+	//
+	NIC_COMMAND(
+		pAdapter,
+		(USHORT)(COMMAND_SET_RX_FILTER | hardwareReceiveFilter));
+	//
+	// Clear the hash filter.
+	//
+	for (count=0; count < bitsInHashFilter; count++) {
+
+		NIC_COMMAND(
+			pAdapter,
+			(USHORT)(COMMAND_SET_HASH_FILTER_BIT | count));
+	}
+	//
+	// Set the hash filter.
+	//
+	numberMulticast = Device->mc_count;
+	multicastList = Device->mc_list;
+
+	DBGPRINT_INITIALIZE(("mcCount = %x\n", (INT)numberMulticast));
+
+	for (count=0; count < numberMulticast; count++) {
+
+		DBGPRINT_INITIALIZE(("Multicast = ")); 
+
+		for (index=0; index < 6; index++)  {
+			address[index] = multicastList->dmi_addr[index];
+			DBGPRINT_INITIALIZE(("%x", address[index]));
+		}
+
+		DBGPRINT_INITIALIZE(("\n"));
+
+		NIC_COMMAND(
+			pAdapter,
+			(USHORT)
+			(COMMAND_SET_HASH_FILTER_BIT |
+			 0x400 |
+		 	tc90x_HashAddress(address)));
+
+		multicastList = multicastList->next;
+	}
+	//
+	// If receive filter is not promiscuos or multicast, enable
+	// hash multicast for receiving the flow control packets and
+	// for the broadcast.
+	//
+	if (!((hardwareReceiveFilter & RX_FILTER_PROMISCUOUS) ||
+	      (hardwareReceiveFilter & RX_FILTER_ALL_MULTICAST))) {
+	 
+		hardwareReceiveFilter |= RX_FILTER_MULTICAST_HASH;
+		//
+		// Set the flow control enable
+		//
+	    	if (pAdapter->Hardware.FlowControlEnable && 
+   	    	    pAdapter->Hardware.FlowControlSupported &&
+	    	    pAdapter->Hardware.FullDuplexEnable) {
+
+			DBGPRINT_INITIALIZE(("Setting flow control bit\n"));
+			//
+			// Set the flow control address bit
+			//
+			flowControlAddress[0] = NIC_FLOW_CONTROL_ADDRESS_0;
+			flowControlAddress[1] = NIC_FLOW_CONTROL_ADDRESS_1;
+   			flowControlAddress[2] = NIC_FLOW_CONTROL_ADDRESS_2;
+			flowControlAddress[3] = NIC_FLOW_CONTROL_ADDRESS_3;
+			flowControlAddress[4] = NIC_FLOW_CONTROL_ADDRESS_4;
+			flowControlAddress[5] = NIC_FLOW_CONTROL_ADDRESS_5;
+	
+			NIC_COMMAND(
+				pAdapter,
+				(USHORT)(COMMAND_SET_HASH_FILTER_BIT | 
+				0x0400 |
+				tc90x_HashAddress(flowControlAddress)));
+		}
+		//
+		// If there is a broadcast error, write value for broadcast.
+		//
+		if (FALSE == pAdapter->Hardware.BroadcastErrDone) {
+
+			DBGPRINT_INITIALIZE(("Broadcast Err Done\n"));
+			for (count=0; count < ETHERNET_ADDRESS_SIZE; count++) 
+				broadcastAddress[count] = 0xff;
+	
+			NIC_COMMAND(
+				pAdapter,
+				(USHORT)
+				(COMMAND_SET_HASH_FILTER_BIT |
+				 0x400 |
+				tc90x_HashAddress(broadcastAddress)) );
+		}
+	}
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_unlock(&pAdapter->SpinLock);
+#endif
+
+	DBGPRINT_FUNCTION(("NICSetReceiveMode: Out\n"));
+}
+
+
+/*++
+
+Routine Name:
+
+    NICGetStatistics
+
+Routine Description:
+
+    This routine gets the statistics. 
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	-ENODEV if no adapter found
+	noAdapterFound if adapter(s) found
+
+--*/
+
+PENET_STATISTICS
+NICGetStatistics(
+	IN PDEVICE Device
+	)
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
+	PNIC_STATISTICS statistics = &pAdapter->Statistics;
+	PENET_STATISTICS enetStatistics = &pAdapter->EnetStatistics;
+	ULONG flags;
+
+	if(Device->start) {
+	save_flags(flags);
+	cli();
+
+	enetStatistics->rx_packets	= statistics->RxFramesOk;
+	enetStatistics->tx_packets	= statistics->TxFramesOk;
+
+#if LINUX_VERSION_CODE > 0x20024
+	enetStatistics->rx_bytes	= statistics->RxBytesOk;
+	enetStatistics->tx_bytes	= statistics->TxBytesOk;
+#endif
+
+	enetStatistics->rx_errors	= statistics->RxBadCRCError +
+					  statistics->RxOverruns +
+					  statistics->RxAlignmentError + statistics->RxOversizeError;
+					
+	enetStatistics->tx_errors	= statistics->TxHWErrors +	
+					  statistics->TxMaximumCollisions +
+				 	  statistics->TxJabberError +
+					  statistics->TxUnknownError;
+
+	enetStatistics->rx_dropped	= statistics->RxOverruns;
+	enetStatistics->multicast	= statistics->Rx_MulticastPkts;
+	enetStatistics->collisions	= statistics->TxMaximumCollisions;
+	enetStatistics->rx_over_errors	= statistics->RxOversizeError;
+	enetStatistics->rx_crc_errors	= statistics->RxBadCRCError;
+	enetStatistics->rx_frame_errors = statistics->RxAlignmentError;
+	enetStatistics->rx_fifo_errors = statistics->RxOverruns;
+	enetStatistics->tx_aborted_errors = statistics->TxUnknownError; 
+	enetStatistics->tx_carrier_errors = statistics->TxCarrierLost;
+	enetStatistics->tx_heartbeat_errors = statistics->TxSQEErrors;
+
+	enetStatistics->rx_missed_errors = 0;
+	enetStatistics->tx_dropped	= 0;
+	enetStatistics->rx_length_errors= 0;
+	enetStatistics->tx_fifo_errors 	= 0;
+	enetStatistics->tx_window_errors = 0;
+
+	restore_flags(flags);
+	}
+
+	return enetStatistics;
+}
+
+
+/*++
+
+Routine Name:
+
+	tc90x_HashAddress.
+
+Routine Description:
+
+	This routine returns a bit corresponding to the hash address.
+
+Arguments:
+
+	MulticastAddress - Mutlicast address to be hashed.
+
+Return Value:
+
+	Hash Value 
+
+--*/
+
+USHORT
+tc90x_HashAddress(
+	IN PUCHAR Address
+    	)
+{
+
+	ULONG crc, carry, count, bit;
+	UCHAR thisByte;
+	//
+	// Intialize CRC.
+	//
+	crc = 0xffffffff;
+
+	for (count = 0; count < 6; count++) {
+        thisByte = Address[count];
+        for ( bit = 0; bit < 8; bit++) {
+            	carry = ((crc & 0x80000000) ? 1 : 0) ^ 
+							(thisByte & 0x01);
+            	crc <<= 1;
+            	thisByte >>= 1;
+            	if (carry)
+                	crc  = (crc ^ 0x04c11db6) | carry;
+        }
+
+    }
+    return (USHORT)(crc & 0x000003FF) ;
+}
+
+/*++
+
+Routine Name:
+
+	tc90x_SetMulticastAddresses.
+
+Routine Description:
+
+ 	This routine sets up the multicast list on the adapter.
+
+Arguments:
+
+	Device - Pointer to the device structure
+
+Return Value:
+
+    	NIC_STATUS_SUCCESS if the addresses could be set.
+    	NIC_STATUS_FAILURE if the addresses could not be set.
+
+--*/
+
+NIC_STATUS
+tc90x_SetMulticastAddresses(
+	IN PNIC_INFORMATION Adapter
+    	)
+{
+    PNIC_INFORMATION pAdapter = Adapter; 
+    UCHAR FlowControlAddress[ETHERNET_ADDRESS_SIZE];
+
+    DBGPRINT_IOCTL(("SetMulticastAddresses: IN\n"));
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_lock(&pAdapter->SpinLock);
+#endif
+	//
+	// Clear all bits in the hash filter, then write all multicast bits back
+	//
+	tc90x_InitializeHashFilter(pAdapter);
+   
+    	if ((pAdapter->Hardware.FlowControlEnable && 
+	    pAdapter->Hardware.FlowControlSupported) &&
+	    (pAdapter->Hardware.FullDuplexEnable)) {
+		//
+		// Set the flow control address bit
+		//
+		FlowControlAddress[0] = NIC_FLOW_CONTROL_ADDRESS_0;
+		FlowControlAddress[1] = NIC_FLOW_CONTROL_ADDRESS_1;
+   		FlowControlAddress[2] = NIC_FLOW_CONTROL_ADDRESS_2;
+		FlowControlAddress[3] = NIC_FLOW_CONTROL_ADDRESS_3;
+		FlowControlAddress[4] = NIC_FLOW_CONTROL_ADDRESS_4;
+		FlowControlAddress[5] = NIC_FLOW_CONTROL_ADDRESS_5;
+
+		NIC_COMMAND(
+			pAdapter,
+			(USHORT)(COMMAND_SET_HASH_FILTER_BIT | 
+			0x0400 |
+			tc90x_HashAddress(FlowControlAddress)) );
+	}
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_unlock(&pAdapter->SpinLock);
+#endif
+
+    DBGPRINT_IOCTL(("SetMulticastAddresses: OUT\n"));
+
+	return NIC_STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Name:
+	
+	InitializeHashFilter
+
+Routine Description:
+	
+	Clear all bits in hash filter and setup the multicast address bit.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+
+Return Value:
+
+	VOID
+
+--*/
+
+VOID
+tc90x_InitializeHashFilter(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+
+	PNIC_INFORMATION pAdapter= Adapter;
+	PDEVICE device = pAdapter->Device;
+	ULONG count;
+    ULONG bitsInHashFilter;
+	ULONG numberMulticast;
+	PDEV_MC_LIST multicastList; 
+	UCHAR address[ETHERNET_ADDRESS_SIZE];
+	ULONG index;
+	//
+	// Clear all bits in the hash filter, then write all multicast bits back
+	//
+	bitsInHashFilter = pAdapter->Hardware.BitsInHashFilter;
+
+    for (count = 0; count < bitsInHashFilter; count++ ) {
+		
+		NIC_COMMAND(
+				pAdapter, 
+				(USHORT)(COMMAND_SET_HASH_FILTER_BIT | count));
+	}
+
+	numberMulticast = device->mc_count;
+	multicastList = device->mc_list;
+
+	DBGPRINT_INITIALIZE(("mcCount = %x\n", (INT)numberMulticast));
+
+	for (count=0; count < numberMulticast; count++) {
+
+		DBGPRINT_INITIALIZE(("Multicast = ")); 
+
+		for (index=0; index < 6; index++)  {
+			address[index] = multicastList->dmi_addr[index];
+			DBGPRINT_INITIALIZE(("%x", address[index]));
+
+		}
+		DBGPRINT_INITIALIZE(("\n"));
+
+		NIC_COMMAND(
+			pAdapter,
+			(USHORT)
+			(COMMAND_SET_HASH_FILTER_BIT |
+			 0x400 |
+		 	tc90x_HashAddress(address)) );
+
+		multicastList = multicastList->next;
+	}
+}
+
+
+
+/*++
+
+Routine Name:
+
+    tc90x_SetupMedia.
+
+Routine Description:
+
+	This routine checks whether autoselection is specified.  If it
+	does, it calls MainAutoSelectionRoutine else for non-autoselect
+	case, calls ProgramMII.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+    NIC_STATUS_SUCCESS if the media could be set up.
+
+--*/
+
+NIC_STATUS
+tc90x_SetupMedia( 
+	IN PDEVICE Device
+    )
+
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv; 
+	USHORT OptionAvailable = 0;
+	ULONG InternalConfig = 0;
+	USHORT InternalConfig0 = 0;
+	USHORT InternalConfig1 = 0;
+	NIC_STATUS nicStatus;
+	USHORT MacControl = 0;
+	CONNECTOR_TYPE NotUsed;
+
+	DBGPRINT_FUNCTION(("SetupMedia: In\n"));
+	
+	pAdapter->Hardware.AutoSelect = FALSE;
+	pAdapter->Hardware.ConfigConnector = CONNECTOR_UNKNOWN;
+	pAdapter->Hardware.Connector = CONNECTOR_UNKNOWN;
+	//
+	// Assumption made here for Cyclone, Hurricane, and Tornado
+	// adapters have the same fixed PHY address.  For other PHY
+	// address values, this needs to be changed.
+	//
+	pAdapter->Hardware.phys = MII_PHY_ADDRESS;
+	pAdapter->Hardware.MIIReadCommand = MII_PHY_ADDRESS | 0x6000;
+	pAdapter->Hardware.MIIWriteCommand = MII_PHY_ADDRESS | 0x5002; 
+
+    // If this is a 10mb Lightning card, assume that the 10FL bit is
+    // set in the media options register
+    //
+	if (pAdapter->Hardware.DeviceId == NIC_PCI_DEVICE_ID_900A) {
+	    
+		DBGPRINT_INITIALIZE((
+			"SetupMedia: 10BaseFL force Media Option \n"));
+		OptionAvailable = MEDIA_OPTIONS_10BASEFL_AVAILABLE;
+	}
+	else {
+		//
+		// Read the MEDIA OPTIONS to see what connectors are available
+		//
+		NIC_COMMAND(
+			pAdapter, 
+		    COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+	 
+		OptionAvailable = NIC_READ_PORT_USHORT(
+							pAdapter,
+							MEDIA_OPTIONS_REGISTER);
+	}
+ 	//
+	// Read the internal config through EEPROM since reset
+	// invalidates the normal register value.
+    //
+	nicStatus = tc90x_ReadEEPROM(
+						pAdapter,
+                    	EEPROM_INTERNAL_CONFIG_WORD_0,
+                    	(PUSHORT)&InternalConfig0);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+        DBGPRINT_ERROR((
+            	"SetupMedia: InternalConfig 0 read failed\n"));
+        
+        return NIC_STATUS_FAILURE;
+    }
+
+	nicStatus = tc90x_ReadEEPROM(
+                        pAdapter,
+                        EEPROM_INTERNAL_CONFIG_WORD_1,
+                        (PUSHORT)&InternalConfig1);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+
+        DBGPRINT_ERROR((
+            "SetupMedia: InternalConfig 1 read failed\n"));
+        
+        return NIC_STATUS_FAILURE;
+    }
+
+	InternalConfig = InternalConfig0 | (InternalConfig1 <<16);
+
+	DBGPRINT_INITIALIZE((
+		"SetupMedia: InternalConfig %x\n", (INT)InternalConfig));
+
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	NIC_WRITE_PORT_ULONG(
+		pAdapter,
+		INTERNAL_CONFIG_REGISTER,
+		InternalConfig);
+ 	//
+	// Get the connector to use if not already overriden.
+	//
+	if (pAdapter->Hardware.ConfigConnector == CONNECTOR_UNKNOWN) {
+
+		pAdapter->Hardware.ConfigConnector = 
+		(InternalConfig & INTERNAL_CONFIG_TRANSCEIVER_MASK) >> 20;
+		
+		pAdapter->Hardware.Connector = 
+				pAdapter->Hardware.ConfigConnector;
+
+		if (InternalConfig & INTERNAL_CONFIG_AUTO_SELECT)
+			pAdapter->Hardware.AutoSelect = TRUE;
+
+		ProcessMediaOverrides(pAdapter, OptionAvailable);
+    }
+	//
+	// If auto selection of connector was specified, do it now...
+	//
+	if (pAdapter->Hardware.AutoSelect) {
+	
+		DBGPRINT_INITIALIZE(("SetupMedia: Autoselect set\n"));	
+		NIC_COMMAND(pAdapter, COMMAND_STATISTICS_DISABLE);      
+		tc90x_MainAutoSelectionRoutine(pAdapter, OptionAvailable);
+	}
+    else {
+	    //
+	    // MII connector needs to be initialized and the data rates
+	    // set up even in the non-autoselect case
+	    //
+		DBGPRINT_INITIALIZE(("SetupMedia: Adapter in forced-mode\n"));
+	
+		if ((pAdapter->Hardware.Connector == CONNECTOR_MII) ||
+		    (pAdapter->Hardware.Connector == 
+		     CONNECTOR_AUTONEGOTIATION)) {
+	    
+			ProgramMII(pAdapter, CONNECTOR_MII);
+	    }
+		else {
+			
+			if ((pAdapter->Hardware.Connector == 
+			     CONNECTOR_100BASEFX) ||
+			     (pAdapter->Hardware.Connector == 
+			     CONNECTOR_100BASETX)) {
+		    
+				pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;			
+			}
+			else {			
+				pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;			
+			}
+	    }	
+	    tc90x_SetupConnector(
+			pAdapter, 
+			pAdapter->Hardware.Connector, 
+			&NotUsed);
+	}
+	//      
+	// Set full duplex
+	//
+    if (pAdapter->Hardware.FullDuplexEnable) {
+
+		NIC_COMMAND(
+		    pAdapter, 
+			COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+		if (pAdapter->Hardware.FlowControlSupported) {
+
+			DBGPRINT_INITIALIZE((
+				"SetupMedia: Flow Control support is on! \n"));
+
+			MacControl = NIC_READ_PORT_USHORT(
+					pAdapter,
+					MAC_CONTROL_REGISTER);
+	
+			NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				MAC_CONTROL_REGISTER, 
+				(USHORT)(MAC_CONTROL_FLOW_CONTROL_ENABLE | 
+					 MacControl));
+		
+			pAdapter->Hardware.FlowControlEnable = TRUE;
+			
+			tc90x_SetMulticastAddresses(pAdapter);
+
+			NIC_COMMAND(
+				pAdapter, 
+				COMMAND_SELECT_REGISTER_WINDOW | 
+				REGISTER_WINDOW_3);
+		}
+
+		MacControl = NIC_READ_PORT_USHORT(
+				pAdapter,
+				MAC_CONTROL_REGISTER);
+
+		NIC_WRITE_PORT_USHORT(
+			pAdapter,
+			MAC_CONTROL_REGISTER, 
+			(USHORT)(MAC_CONTROL_FULL_DUPLEX_ENABLE | 
+				 MacControl));
+
+		if (tc90x_ResetAndEnableTransmitter(pAdapter) != 
+		    NIC_STATUS_SUCCESS) { 
+			DBGPRINT_INITIALIZE((
+				"SetupMedia: Reset transmitter failed\n"));
+
+			DBGPRINT_FUNCTION(("SetupMedia: Out with error\n"));
+	   		return NIC_STATUS_FAILURE;
+
+		}
+
+		if (tc90x_ResetAndEnableReceiver(pAdapter) != 
+		    NIC_STATUS_SUCCESS) {
+
+			DBGPRINT_INITIALIZE((
+				"SetupMedia: Reset receiver failed\n"));
+
+			DBGPRINT_FUNCTION((
+				"SetupMedia: Out with error\n"));
+			return NIC_STATUS_FAILURE;
+		}		
+	}
+    //
+    // This is for advertisement of flow control.  We only need to
+    // call this if the adapter is using flow control, in Autoselect
+    // mode and not a Tornado board.
+    //
+	if ((pAdapter->Hardware.AutoSelect && 
+	     pAdapter->Hardware.FlowControlEnable) &&
+	     (pAdapter->Hardware.DeviceId != NIC_PCI_DEVICE_ID_9200) &&
+	     (pAdapter->Hardware.DeviceId != NIC_PCI_DEVICE_ID_9805)) {
+		
+		tc90x_FlowControl(pAdapter);
+	}
+
+    DBGPRINT_FUNCTION(("SetupMedia: Out\n"));
+    return NIC_STATUS_SUCCESS;
+}
+ 
+/*++
+
+Routine Name:
+	
+	ProcessMediaOverrides
+
+Routine Description:
+
+	Change the connector and duplex if values are present in command line.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	IN USHORT OptionAvailable
+
+Return Value:
+	
+	VOID
+
+--*/
+
+VOID
+ProcessMediaOverrides(
+	IN PNIC_INFORMATION Adapter, 
+	IN USHORT OptionAvailable
+	)
+{
+	PNIC_INFORMATION pAdapter= Adapter; 
+	ULONG InternalConfig = 0;
+
+	switch (pAdapter->Hardware.MediaOverride) {
+		
+		case MEDIA_AUTO_SELECT:
+			
+			NIC_COMMAND(
+				pAdapter, 
+				COMMAND_SELECT_REGISTER_WINDOW | 
+				REGISTER_WINDOW_3);
+
+			InternalConfig = NIC_READ_PORT_ULONG(
+						pAdapter,
+						INTERNAL_CONFIG_REGISTER);
+
+			InternalConfig |= INTERNAL_CONFIG_AUTO_SELECT;
+
+			NIC_WRITE_PORT_ULONG(
+				pAdapter,
+				INTERNAL_CONFIG_REGISTER,
+				InternalConfig);
+		
+			pAdapter->Hardware.AutoSelect = TRUE;
+			break;
+
+	    case MEDIA_10BASE_TX:
+			
+			if (OptionAvailable & MEDIA_OPTIONS_10BASET_AVAILABLE) {
+			    
+				pAdapter->Hardware.Connector = 
+							CONNECTOR_10BASET;
+				pAdapter->Hardware.AutoSelect = FALSE;
+			}
+			break;
+
+		case MEDIA_10AUI:
+			
+			if (OptionAvailable & MEDIA_OPTIONS_10AUI_AVAILABLE) {
+
+				pAdapter->Hardware.Connector = CONNECTOR_10AUI;
+				pAdapter->Hardware.AutoSelect = FALSE;
+			}
+			break;
+
+		case MEDIA_10BASE_2:
+			
+			if (OptionAvailable & MEDIA_OPTIONS_10BASE2_AVAILABLE) {
+	
+				pAdapter->Hardware.Connector = 
+							CONNECTOR_10BASE2;
+				pAdapter->Hardware.AutoSelect = FALSE;
+			}
+			break;
+
+		case MEDIA_100BASE_TX:
+			
+			if (OptionAvailable & 
+			    MEDIA_OPTIONS_100BASETX_AVAILABLE) {
+			   
+				pAdapter->Hardware.Connector = 
+							CONNECTOR_100BASETX;
+				pAdapter->Hardware.AutoSelect = FALSE;
+			}
+			break;
+
+		case MEDIA_100BASE_FX:
+
+			if (OptionAvailable & 
+			    MEDIA_OPTIONS_100BASEFX_AVAILABLE) {
+				
+				pAdapter->Hardware.Connector = 
+							CONNECTOR_100BASEFX;
+				pAdapter->Hardware.AutoSelect = FALSE;
+			}
+			break;
+
+		case MEDIA_10BASE_FL:
+
+			if (OptionAvailable & 
+			    MEDIA_OPTIONS_10BASEFL_AVAILABLE) {
+
+				pAdapter->Hardware.Connector = CONNECTOR_10AUI;
+				pAdapter->Hardware.AutoSelect = FALSE;
+
+			}
+			break;
+
+	    case MEDIA_NONE:			
+			break;
+	}
+}
+
+/*++
+
+Routine Name:
+	
+	TickMediaHandler
+
+Routine Description:
+
+	Adjust linkspeed and duplex in tick handler 
+	
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+
+Return Value:
+	
+	VOID
+
+--*/
+
+VOID
+tc90x_TickMediaHandler(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+
+	if ((pAdapter->Hardware.Connector == CONNECTOR_AUTONEGOTIATION) ||
+	    (pAdapter->Hardware.Connector == CONNECTOR_10BASET) ||
+	    (pAdapter->Hardware.Connector == CONNECTOR_100BASETX)) {
+		//
+		// TP case
+		//
+		CheckTPLinkState(pAdapter);
+	}
+	else if (pAdapter->Hardware.Connector == CONNECTOR_100BASEFX) {
+		//
+		// FX case
+		//
+		CheckFXLinkState(pAdapter);
+ 	}
+}
+
+
+/*++
+
+Routine Name:
+	
+	CheckTPLinkState
+
+Routine Description:
+
+	Determine whether to notify the operating system if link is lost 
+	or restored. For autonegotiation case, made adjustments to duplex
+	and speed if necessary.
+	
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+
+Return Value:
+	
+	VOID
+
+--*/
+
+VOID
+CheckTPLinkState(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	BOOLEAN handles100Mbit = FALSE;
+	USHORT PhyStatus = 0;
+	BOOLEAN OldFullDuplex;
+	ULONG OldLinkSpeed;
+
+	if (ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyStatus)) {
+
+		if (!(PhyStatus & MII_STATUS_LINK_UP)) {					
+			//
+			// If OS doesn't know link was lost, go       
+			// ahead and notify
+			//
+			if (!pAdapter->Hardware.LinkLost) {
+		
+				IndicateToOSLinkStateChange(pAdapter);
+			}
+	}
+	else {  	
+		//
+		// If OS doesn't know link was restored, go
+		// ahead and notify
+		//
+		if (pAdapter->Hardware.LinkLost) {
+
+				IndicateToOSLinkStateChange(pAdapter);
+			}
+			if (((PhyStatus & MII_STATUS_AUTO) && 
+				(PhyStatus & MII_STATUS_EXTENDED)) &&
+				(pAdapter->Hardware.Connector == CONNECTOR_AUTONEGOTIATION)) {
+
+				OldLinkSpeed = pAdapter->Hardware.LinkSpeed;
+				OldFullDuplex = pAdapter->Hardware.FullDuplexEnable;
+				//
+				// Capable of autonegotiation 
+				//
+				if (GetLinkSpeed(pAdapter, &handles100Mbit)) {
+
+					if (handles100Mbit)
+						pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
+					else
+						pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
+					//
+					// Set up for new speed if speed changed. Set 
+					// counterSpeed bit in DmaCtrl register.
+					//
+					if (pAdapter->Hardware.LinkSpeed != OldLinkSpeed)
+						tc90x_SetupNewSpeed(pAdapter);
+					//
+					// Set up for new duplex mode if duplex changed.
+					//
+					if (pAdapter->Hardware.FullDuplexEnable != OldFullDuplex)
+						tc90x_SetupNewDuplex(pAdapter);						
+				} 
+				else {
+					DBGPRINT_INITIALIZE(("Failed to get link speed\n"));
+				}
+			}		                                     
+		}	
+	}
+}
+
+/*++
+
+Routine Name:
+	
+	CheckFXLinkState
+
+Routine Description:
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+
+Return Value:
+	
+	VOID
+
+--*/
+
+VOID
+CheckFXLinkState(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT MediaStatus = 0;
+
+	NIC_COMMAND(
+		pAdapter, 
+    	COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	MediaStatus = NIC_READ_PORT_USHORT(pAdapter,MEDIA_STATUS_REGISTER);
+
+    	if (!(MediaStatus & MEDIA_STATUS_LINK_DETECT)) {
+
+		if (!pAdapter->Hardware.LinkLost) {
+		
+			IndicateToOSLinkStateChange(pAdapter);
+		}
+		else {
+			if (pAdapter->Hardware.LinkLost) {
+		
+				IndicateToOSLinkStateChange(pAdapter);
+			}
+		}
+	}
+}
+
+/*++
+
+Routine Name:
+	
+	tc90x_SetupNewDuplex
+
+Routine Description:
+	
+	Setup new duplex in MacControl register.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+
+  
+Return Value:
+
+	NIC_STATUS
+
+--*/
+NIC_STATUS
+tc90x_SetupNewDuplex(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT MacControl = 0;
+	USHORT MediaStatus = 0;
+	ULONG count;
+    NIC_STATUS nicStatus;
+
+	NIC_COMMAND(pAdapter, COMMAND_RX_DISABLE);
+	NIC_COMMAND(pAdapter, COMMAND_TX_DISABLE);
+    
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+	//
+	// Wait for transmit to go quiet
+	//
+	count = jiffies + HZ;
+	do {
+		MediaStatus = NIC_READ_PORT_USHORT(
+						pAdapter, 
+						MEDIA_STATUS_REGISTER);
+		NIC_DELAY(10);         
+	} while ( (MediaStatus & MEDIA_STATUS_TX_IN_PROGRESS) &&
+			  (count > jiffies) );
+
+	if (count < jiffies) {
+	    pAdapter->Hardware.Status = HARDWARE_STATUS_HUNG;
+		DBGPRINT_ERROR((
+			"tc90x_SetupNewDuplex: Packet not picked up by hardware"));
+		return NIC_STATUS_FAILURE;
+	}
+	//
+	// Wait for receive to go quiet
+	//
+	count = jiffies + HZ;
+	do {
+		MediaStatus = NIC_READ_PORT_USHORT(
+					pAdapter, 
+					MEDIA_STATUS_REGISTER);
+		NIC_DELAY(10);         
+	} while ( (MediaStatus &  MEDIA_STATUS_CARRIER_SENSE) && 
+			  (count > jiffies) );
+
+	if (count < jiffies) {
+	    pAdapter->Hardware.Status = HARDWARE_STATUS_HUNG;
+		DBGPRINT_ERROR((
+			"tc90x_SetupNewDuplex: Packet not uploaded by hardware"));
+		return NIC_STATUS_FAILURE;
+	}
+
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	MacControl = NIC_READ_PORT_USHORT(pAdapter, MAC_CONTROL_REGISTER);
+				
+	if (pAdapter->Hardware.FullDuplexEnable) {
+		//
+		// Set Full duplex in MacControl register
+		//							
+		MacControl |= MAC_CONTROL_FULL_DUPLEX_ENABLE;                      
+		DBGPRINT_INITIALIZE(("Changed link to full duplex\n"));			
+		//
+		// Since we're switching to full duplex, enable flow control.
+		//                                                                      			      
+		if (pAdapter->Hardware.FlowControlSupported) {                                                          
+	
+			MacControl |=  MAC_CONTROL_FLOW_CONTROL_ENABLE;
+			pAdapter->Hardware.FlowControlEnable = TRUE;
+		
+			tc90x_SetMulticastAddresses(pAdapter);
+		}
+	}
+    	else {
+	
+		//
+		// Set Half duplex in MacControl register
+		//
+		MacControl &= ~MAC_CONTROL_FULL_DUPLEX_ENABLE;                            
+		DBGPRINT_INITIALIZE(("Changed link to half duplex\n"));
+					
+		//
+		// Since we're switching to half duplex, disable flow control
+		//                                    
+		if (pAdapter->Hardware.FlowControlEnable &&
+			pAdapter->Hardware.FlowControlSupported) {
+		
+			MacControl &= ~ MAC_CONTROL_FLOW_CONTROL_ENABLE;
+			pAdapter->Hardware.FlowControlEnable = FALSE;                   
+			tc90x_SetMulticastAddresses(pAdapter);	
+		}         
+	}
+	     
+	NIC_WRITE_PORT_USHORT(
+		pAdapter, 
+		MAC_CONTROL_REGISTER, 
+		MacControl);
+		
+	NIC_DELAY(20);
+	
+	// issue Tx/Rx Reset after setting duplex
+
+	nicStatus = RxResetAndWork(Adapter);
+
+	if (nicStatus != NIC_STATUS_SUCCESS)
+        DBGPRINT_ERROR(("SetupnewDuplex: RxResetAndWork failed\n"));
+
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
+
+	if (nicStatus != NIC_STATUS_SUCCESS)
+        DBGPRINT_ERROR(("SetupnewDuplex: Tx reset failed\n"));
+
+	NIC_COMMAND(pAdapter, COMMAND_RX_ENABLE);
+	NIC_COMMAND(pAdapter, COMMAND_TX_ENABLE);
+
+	return NIC_STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Name:
+	
+	tc90x_SetupNewSpeed
+
+Routine Description:
+	
+	Sets the counter speed in the DMA control register. Clear bit
+	for 10Mbps or set the bit for 100Mbps.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	
+Return Value:
+
+	VOID
+
+--*/
+
+VOID
+tc90x_SetupNewSpeed(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	ULONG DmaControl = 0;
+					
+	DmaControl = NIC_READ_PORT_ULONG(
+					pAdapter, 
+					DMA_CONTROL_REGISTER);
+
+    if (pAdapter->Hardware.LinkSpeed == LINK_SPEED_100) {                                    
+
+		DmaControl |= DMA_CONTROL_COUNTER_SPEED;
+    }
+    else {
+		
+		DmaControl &= ~DMA_CONTROL_COUNTER_SPEED;
+    }
+				
+	NIC_WRITE_PORT_ULONG(
+		pAdapter, 
+		DMA_CONTROL_REGISTER, 
+		DmaControl);
+	  
+	DBGPRINT_INITIALIZE(("Changed link speed to %ld bps\n",
+		pAdapter->Hardware.LinkSpeed));
+}
+
+
+/*++
+
+Routine Name:
+	
+	IndicateToOSLinkStateChange
+
+Routine Description:
+	
+	Notify to NDI wrapper the change in link state.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+
+Return Value:
+
+	VOID
+
+--*/
+
+VOID
+IndicateToOSLinkStateChange(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+
+	if (!pAdapter->Hardware.LinkLost) { 
+
+		DBGPRINT_ERROR((KERN_CRIT "Link Lost...\n"));
+		pAdapter->Hardware.LinkLost = TRUE;
+		if ((pAdapter->Device)->flags & IFF_UP)
+			(pAdapter->Device)->flags &= ~(IFF_UP|IFF_RUNNING);
+	}
+    else {		
+			
+		DBGPRINT_ERROR((KERN_CRIT "Link Regained...\n"));
+		pAdapter->Hardware.LinkLost = FALSE;
+		(pAdapter->Device)->flags |= (IFF_UP|IFF_RUNNING);		
+	}					
+}
+
+
+
+
+
+
+/*++
+
+Routine Name:
+
+	NICInterrupt
+
+Routine Description:
+
+	This routine handles the interrupt.
+
+Arguments:
+
+	Irq
+	DeviceId
+	Registers
+
+Return Value:
+
+	None
+
+--*/
+
+VOID
+NICInterrupt IRQ(
+	INT Irq,
+	PVOID DeviceId,
+	PTREGS Registers
+	)
+
+{		
+	//
+	// Use the now-standard shared IRQ implementation. 
+	//
+	PDEVICE Device = DeviceId;
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
+	USHORT intStatus = 0;
+    	UCHAR loopCount = 2;
+	BOOLEAN countDownTimerEventCalled = FALSE;
+
+//	#if LINUX_VERSION_CODE >= 0x20200
+//		spin_lock(&pAdapter->SpinLock);
+//	#endif
+
+// SMP - Becker's fix
+#if defined(__i386__)
+
+	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+	if (test_and_set_bit(0, (void*)&Device->interrupt)) {		
+		DBGPRINT_ERROR(("NICInterrupt: %s simultaneous entry of an interrupt handler.\n",
+			            Device->name));
+		/* Avoid halting machine. */
+		Device->interrupt = 0;
+
+//	#if LINUX_VERSION_CODE >= 0x20200
+//		spin_unlock(&pAdapter->SpinLock);
+//	#endif
+		return ;
+	}
+#else
+	if (Device->interrupt) {
+		DBGPRINT_ERROR(("NICInterrupt: %s Re-enter the interrupt handler.\n", Device->name));
+		return;
+	}
+
+	Device->interrupt = 1;
+
+#endif
+
+// end fix
+
+	Device->interrupt = 1;
+
+	intStatus = NIC_READ_PORT_UCHAR(
+                        pAdapter,
+                        INTSTATUS_COMMAND_REGISTER);
+
+	if (!(intStatus & INTSTATUS_INTERRUPT_LATCH)) {			
+		
+//#if LINUX_VERSION_CODE >= 0x20200
+//		spin_unlock(&pAdapter->SpinLock);
+//#endif
+		Device->interrupt = 0;
+		return;
+	}
+	else {
+		//
+		// Mask all the interrupts.
+		//
+		NIC_MASK_ALL_INTERRUPT(pAdapter);
+
+        	NIC_COMMAND(
+                	pAdapter, 
+			COMMAND_ACKNOWLEDGE_INTERRUPT | 
+			ACKNOWLEDGE_INTERRUPT_LATCH);
+	}
+    	while (loopCount--) {
+        //
+		// Read the interrupt status register.
+		//
+		intStatus = NIC_READ_PORT_USHORT(
+                            	pAdapter,
+				INTSTATUS_COMMAND_REGISTER);
+
+        	intStatus &= INTSTATUS_INTERRUPT_MASK;
+
+	        if (!intStatus) break;
+
+        	if (intStatus & INTSTATUS_HOST_ERROR) {
+
+				printk( KERN_CRIT "HostError ");
+				DBGPRINT_ERROR((
+				"NICInterrupt: HostError event happened.\n"));
+				tc90x_HostErrorEvent(pAdapter);
+        	}
+        
+	        if (intStatus & INTSTATUS_UPDATE_STATISTICS)  {
+			//
+			// This interrupt will be cleared by reading 
+			// statistics.
+			//
+            	tc90x_UpdateStatisticsEvent(pAdapter);
+        	}
+
+		if (intStatus & INTSTATUS_UP_COMPLETE) { 
+
+			NIC_COMMAND(
+				pAdapter,
+				COMMAND_ACKNOWLEDGE_INTERRUPT |
+				ACKNOWLEDGE_UP_COMPLETE);
+
+			tc90x_UpCompleteEvent(pAdapter);
+        	}
+
+		if (intStatus & INTSTATUS_INTERRUPT_REQUESTED) {
+
+			NIC_COMMAND(
+				pAdapter,
+				COMMAND_ACKNOWLEDGE_INTERRUPT | 
+				ACKNOWLEDGE_INTERRUPT_REQUESTED);
+
+			tc90x_CountDownTimerEvent(pAdapter);
+			countDownTimerEventCalled = TRUE;
+        	}
+
+
+		if (intStatus & INTSTATUS_TX_COMPLETE)  {
+
+			tc90x_TxCompleteEvent(pAdapter);
+        	}
+
+        	if ((intStatus & INTSTATUS_RX_COMPLETE) ||
+		    (intStatus & INTSTATUS_LINK_EVENT) ||
+		    (intStatus & INTSTATUS_DOWN_COMPLETE)) {
+
+			DBGPRINT_ERROR((
+				"NICInterrupt: Unknown interrupt\n"));
+			DBGPRINT_ERROR((
+				"NICInterrupt: IntStatus =%x\n", intStatus));
+        	}
+
+        	if (FALSE == countDownTimerEventCalled) {
+
+				tc90x_CountDownTimerEvent(pAdapter);
+				countDownTimerEventCalled = TRUE;
+        	}
+
+    	}
+
+        NIC_UNMASK_ALL_INTERRUPT(pAdapter);
+
+// Becker's fix?
+#if defined(__i386__)
+	clear_bit(0, (void*)&Device->interrupt);
+#else
+	Device->interrupt = 0;
+#endif
+
+//#if LINUX_VERSION_CODE >= 0x20200
+//	spin_unlock(&pAdapter->SpinLock);
+//#endif
+	return;
+}
+
+
+/*++
+
+Routine Name:
+
+	tc90x_HostErrorEvent.
+
+Routine Description:
+
+	This routine handles the host error.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+	None
+
+--*/
+
+VOID
+tc90x_HostErrorEvent(IN PNIC_INFORMATION Adapter)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	TASKQ	HostErrTask;
+
+	HostErrTask = pAdapter->Resources.hostErr_task;
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "tc90x_HostErrorEvent: IN \n"));
+	//
+	// Read the internal config.
+	//
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+	pAdapter->keepForGlobalReset = NIC_READ_PORT_ULONG(
+								pAdapter, 
+								INTERNAL_CONFIG_REGISTER);
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "Adapter does global reset and restart \n"));
+	//
+	// Issue Global reset. I will mask the updown reset so that 
+	// I don't have to set the UpPoll, DownPoll, UpListPointer
+	// and DownListPointer.
+	//
+	NIC_COMMAND_WAIT(
+		pAdapter,
+		COMMAND_GLOBAL_RESET |
+		GLOBAL_RESET_MASK_TP_AUI_RESET |
+		GLOBAL_RESET_MASK_ENDEC_RESET |
+		GLOBAL_RESET_MASK_AISM_RESET |
+		GLOBAL_RESET_MASK_SMB_RESET |
+		GLOBAL_RESET_MASK_VCO_RESET |
+		GLOBAL_RESET_MASK_UP_DOWN_RESET
+		);
+
+	// run task in contex of a process so that we can sleep at start
+
+	queue_task(&HostErrTask, &tq_scheduler);
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "tc90x_HostErrorEvent: OUT\n"));
+
+	return;
+}	
+
+
+/*++
+
+Routine Name:
+
+	tc90x_UpdateStatisticsEvent.
+
+Routine Description:
+
+	This routine handles the update statistics interrupt.
+
+Arguments:
+
+	Device - Pointer to the device structure.
+
+Return Value:
+
+    None
+
+--*/
+
+VOID
+tc90x_UpdateStatisticsEvent(
+	IN PNIC_INFORMATION Adapter
+    	)
+
+{
+
+	PNIC_INFORMATION pAdapter = Adapter;
+	PNIC_STATISTICS statistics = &pAdapter->Statistics;
+	USHORT rxPackets, txPackets, highPackets;
+	USHORT rxBytes, txBytes, highBytes;
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "tc90x_UpdateStatisticsEvent: IN\n"));
+	//
+	// Change the window.
+	//
+	NIC_COMMAND(
+        	pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_6);
+
+	statistics->TxSQEErrors += NIC_READ_PORT_UCHAR(
+                               pAdapter,
+                               SQE_ERRORS_REGISTER);
+
+	statistics->TxMultipleCollisions += NIC_READ_PORT_UCHAR(
+                                        pAdapter,
+                                        MULTIPLE_COLLISIONS_REGISTER);
+
+	statistics->TxSingleCollisions += NIC_READ_PORT_UCHAR(
+                                      pAdapter,
+                                      SINGLE_COLLISIONS_REGISTER);
+
+	statistics->RxOverruns += NIC_READ_PORT_UCHAR(
+                              pAdapter,
+                              RX_OVERRUNS_REGISTER);
+
+	statistics->TxCarrierLost += NIC_READ_PORT_UCHAR(
+                                 pAdapter,
+                                 CARRIER_LOST_REGISTER);
+
+	statistics->TxLateCollisions += NIC_READ_PORT_UCHAR(
+                                    pAdapter,
+                                    LATE_COLLISIONS_REGISTER);
+
+	statistics->TxFramesDeferred += NIC_READ_PORT_UCHAR(
+                                    pAdapter,
+                                    FRAMES_DEFERRED_REGISTER);
+	rxPackets = NIC_READ_PORT_UCHAR(
+                        pAdapter, 
+                        FRAMES_RECEIVED_OK_REGISTER);
+
+	txPackets = NIC_READ_PORT_UCHAR(
+                        pAdapter,
+                        FRAMES_TRANSMITTED_OK_REGISTER);
+
+	highPackets = NIC_READ_PORT_UCHAR(
+						pAdapter,
+                        UPPER_FRAMES_OK_REGISTER);
+
+	rxPackets += ((highPackets & 0x03) << 8);
+	txPackets += ((highPackets & 0x30) << 4);
+
+	if (pAdapter->Hardware.SQEDisable) 
+        statistics->TxSQEErrors += txPackets;
+
+	statistics->RxFramesOk += rxPackets;
+	statistics->TxFramesOk += txPackets;
+
+	rxBytes = NIC_READ_PORT_USHORT(
+                    pAdapter,
+                    BYTES_RECEIVED_OK_REGISTER);
+
+	txBytes = NIC_READ_PORT_USHORT(
+                    pAdapter,
+                    BYTES_TRANSMITTED_OK_REGISTER);
+
+	NIC_COMMAND(
+            pAdapter,
+            COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	highBytes = NIC_READ_PORT_UCHAR(
+                        pAdapter,
+                        UPPER_BYTES_OK_REGISTER);
+
+	rxBytes += ((highBytes & 0x0F) << 8);
+	txBytes += ((highBytes & 0xF0) << 4);
+
+	statistics->RxBytesOk += rxBytes;
+	statistics->TxBytesOk += txBytes;
+
+	statistics->RxBadSSD += NIC_READ_PORT_UCHAR(
+                                    pAdapter,
+                                    BAD_SSD_REGISTER);
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "tc90x_UpdateStatisticsEvent: OUT\n"));
+}
+
+/*++
+
+Routine Name:
+
+	tc90x_CountDownTimerEvent.
+
+Routine Description:
+
+	This routine handles the interrupt requested event.
+
+Arguments:
+
+	Device - Pointer to the device structure
+
+Return Value:
+
+	None
+
+--*/
+
+VOID
+tc90x_CountDownTimerEvent(
+	IN PNIC_INFORMATION Adapter
+    	)
+
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	PDPD_LIST_ENTRY headDPDVirtual;
+	PDEVICE device = pAdapter->Device;
+
+	DBGPRINT_INTERRUPT((KERN_CRIT "tc90x_CountDownTimerEvent: IN\n"));
+
+    headDPDVirtual = pAdapter->HeadDPDVirtual;
+	//
+	// This clears the FSH_DPD_EMPTY and a raise condition of
+	// hardware.
+	//
+	pAdapter->TailDPDVirtual->FrameStartHeader = 0;
+
+	while (1) {
+
+        if (!(headDPDVirtual->FrameStartHeader & FSH_DOWN_COMPLETE))
+            		break;
+			ASSERT(headDPDVirtual->Packet != NULL);
+
+			DEV_FREE_SKB(headDPDVirtual->SocketBuffer);
+
+			headDPDVirtual->SocketBuffer = NULL;
+			//
+			// Clear the down complete bit in the frame start header.
+			//
+			headDPDVirtual->FrameStartHeader = 0;
+
+        	pAdapter->BytesInDPDQueue -= headDPDVirtual->PacketLength;
+        	headDPDVirtual = headDPDVirtual->Next;
+	        ASSERT(pAdapter->HeadDPDVirtual != NULL);
+    	}
+
+	pAdapter->HeadDPDVirtual = headDPDVirtual;
+
+	if (pAdapter->BytesInDPDQueue) 
+        	tc90x_SetCountDownTimer(pAdapter);
+	//
+	// If the device is busy, run the bottom half.
+	//
+	if (device->tbusy && (TRUE == pAdapter->DPDRingFull)) {
+
+		//DBGPRINT_ERROR(( KERN_CRIT "CountdownTimer: mark_bh\n"));
+		pAdapter->DPDRingFull = FALSE;
+		clear_bit(0, (void*)&device->tbusy);
+		mark_bh(NET_BH);
+	}
+
+    DBGPRINT_INTERRUPT((KERN_CRIT "tc90x_CountDownTimerEvent: OUT\n"));
+}
+
+
+
+
+/*++
+
+Routine Name:
+
+	NICTimer
+
+Routine Description:
+
+	This is the tick handler.
+
+Arguments:
+
+Return Value:
+
+    None.
+
+--*/
+
+
+
+
+VOID
+NICTimer(
+	IN ULONG Data
+	)
+{
+	PDEVICE device =  (PDEVICE)Data;
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)device->priv;
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_lock(&pAdapter->SpinLock);
+#endif
+    pAdapter->InTimer = TRUE;
+
+	disable_irq(device->irq);
+	
+	if ((pAdapter->Statistics.UpdateInterval += 
+             pAdapter->Resources.TimerInterval) > 1000) {
+
+        	pAdapter->Statistics.UpdateInterval = 0;
+        	tc90x_UpdateStatisticsEvent(pAdapter);
+   	}
+	//
+	// Check every five seconds for media changed speed or duplex
+	//
+	if ((pAdapter->Hardware.UpdateInterval += 
+        	pAdapter->Resources.TimerInterval) > 5000) {
+
+        	pAdapter->Hardware.UpdateInterval = 0;
+        	tc90x_TickMediaHandler(pAdapter);
+    }
+
+	enable_irq(device->irq);
+	pAdapter->Resources.Timer.expires = RUN_AT(HZ/10);
+	add_timer(&pAdapter->Resources.Timer);
+
+    pAdapter->InTimer = FALSE;
+
+#if LINUX_VERSION_CODE >= 0x20200
+	spin_unlock(&pAdapter->SpinLock);
+#endif
+}
+
+
+
+
+
+/*++
+
+Routine Name: 
+
+	FindMIIPhy
+
+Routine Description:
+   
+	Search for any PHY that is not known.
+
+Arguments:
+
+	Adapter - Pointer to the adapter structure.
+
+Return Value:
+
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+FindMIIPhy( 
+	IN PNIC_INFORMATION Adapter
+	) 
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Adapter; 
+ 	USHORT MediaOptions = 0;
+	USHORT PhyManagement = 0;
+	UCHAR index;
+	//
+	// Read the MEDIA OPTIONS to see what connectors are available
+	//
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
+
+    	MediaOptions = NIC_READ_PORT_USHORT(pAdapter,MEDIA_OPTIONS_REGISTER);
+
+	if ((MediaOptions & MEDIA_OPTIONS_MII_AVAILABLE) || 
+    	    (MediaOptions & MEDIA_OPTIONS_100BASET4_AVAILABLE) ) {
+		//
+    	// Drop everything, so we are not driving the data, and run the
+    	// clock through 32 cycles in case the PHY is trying to tell us
+    	// something. Then read the data line, since the PHY's pull-up
+    	// will read as a 1 if it's present.
+    	//
+		NIC_COMMAND(
+			pAdapter,
+			COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+		NIC_WRITE_PORT_USHORT(pAdapter,PHYSICAL_MANAGEMENT_REGISTER,0);
+	
+		for (index = 0; index < 32; index++) {
+			
+			NIC_DELAY(1);
+			
+			NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER,
+				PHY_CLOCK);
+
+			NIC_DELAY(1);
+			
+			NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER, 
+				0);
+		}
+		
+		PhyManagement = NIC_READ_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER);
+
+		if ( PhyManagement & PHY_DATA1) {
+	       	
+			return TRUE;
+		} 
+		else {
+	       		return FALSE;
+		}
+    } 
+    	return TRUE;
+}
+
+
+
+/*++
+
+Routine Name: 
+
+	SendMIIPhyPreamble
+
+Routine Description:
+   
+	Establishes the synchronization for each MII transaction. This
+	is done by sending thirty-two "1" bits.
+
+Arguments:
+
+	Adapter - Pointer to the adapter structure.
+
+Return Value:
+	
+	VOID
+
+--*/
+
+VOID
+SendMIIPhyPreamble(    
+	IN PNIC_INFORMATION Adapter
+	) 
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Adapter; 
+    UCHAR index;
+    //
+    // Set up and send the preamble, a sequence of 32 "1" bits
+	//
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		PHYSICAL_MANAGEMENT_REGISTER, 
+		PHY_WRITE);
+
+    	for (index = 0; index < 32; index++) {
+		
+		NIC_WRITE_PORT_USHORT(
+			pAdapter,
+			PHYSICAL_MANAGEMENT_REGISTER, 
+			PHY_WRITE | PHY_DATA1
+			);
+		
+		NIC_WRITE_PORT_USHORT(
+			pAdapter,
+			PHYSICAL_MANAGEMENT_REGISTER, 
+			PHY_WRITE | PHY_DATA1 | PHY_CLOCK);
+		
+		NIC_DELAY(1);
+	
+		NIC_WRITE_PORT_USHORT(
+			pAdapter,
+			PHYSICAL_MANAGEMENT_REGISTER, 
+			PHY_WRITE);
+		
+		NIC_DELAY(1);  
+	}
+}
+
+
+/*++
+
+Routine Name: 
+	
+	WriteMIIPhy
+
+Routine Description:
+
+  Writes to a particular MII PHY register given the proper offset.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	IN USHORT RegAddr
+	IN USHORT Output
+
+Return Value:
+	
+	VOID
+
+--*/
+
+VOID
+WriteMIIPhy(   
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT RegAddr,
+	IN USHORT Output 
+	)
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Adapter;
+   	ULONG index,index2;
+    USHORT writecmd[2];
+
+	writecmd[0] = pAdapter->Hardware.MIIWriteCommand;
+	writecmd[1] = 0;
+ 
+	SendMIIPhyPreamble(pAdapter);
+    //
+    // Bits 2..6 of the command word specify the register.
+    //
+    writecmd[0] |= (RegAddr & 0x1F) << 2;
+    writecmd[1] = Output;
+
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+    	for (index2 = 0; index2 < 2; index2++) {
+
+		for (index = 0x8000; index; index >>= 1) {
+	    
+			if (writecmd[index2] & index) {
+
+				NIC_WRITE_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER, 
+					PHY_WRITE | PHY_DATA1);
+
+	       			NIC_WRITE_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER,
+	       				PHY_WRITE | PHY_DATA1 | PHY_CLOCK);
+			} 
+	    	else {
+
+			 	NIC_WRITE_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER,
+					PHY_WRITE);
+
+	       			NIC_WRITE_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER,
+					PHY_WRITE | PHY_CLOCK);
+	    		}
+			NIC_DELAY(1);
+			
+			NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER,
+				PHY_WRITE);
+
+			NIC_DELAY(1);
+		}
+    	}
+    	//
+    	// OK now give it a couple of clocks with nobody driving.
+    	//
+    	NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER,
+				0);
+
+    	for (index = 0; index < 2; index++) {
+	  	
+			NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER, 
+				PHY_CLOCK);
+
+			NIC_DELAY(1);
+		
+			NIC_WRITE_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER,
+					0);
+		
+			NIC_DELAY(1);
+    	}
+}
+
+
+/*++
+
+Routine Name: 
+
+	ReadMIIPhy
+
+Routine Description:
+	
+	Reads a particular MII PHY register given the proper offset.
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	IN USHORT RegisterAddress
+	OUT PUSHORT pInput
+	
+Return Value:
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+ReadMIIPhy(    
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT RegisterAddress,
+	OUT PUSHORT pInput 
+	) 
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Adapter;
+	USHORT PhyManagement = 0;
+    	USHORT ReadCommand;
+    	ULONG index;
+
+    	ReadCommand = pAdapter->Hardware.MIIReadCommand;
+	
+    	SendMIIPhyPreamble(pAdapter);
+    	//
+    	// Bits 2..6 of the command word specify the register.
+    	//
+    	ReadCommand |= (RegisterAddress & 0x1F) << 2;
+  
+    	for (index = 0x8000; index > 2; index >>= 1) {
+
+		NIC_COMMAND(
+			pAdapter,
+			COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+		if (ReadCommand & index) {
+
+			NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER, 
+				PHY_WRITE | PHY_DATA1);
+
+			NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER, 
+				PHY_WRITE | PHY_DATA1 | PHY_CLOCK);
+		}
+		else {
+		     	NIC_WRITE_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER,
+					PHY_WRITE);
+
+				NIC_WRITE_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER,
+					PHY_WRITE | PHY_CLOCK);
+		}
+		NIC_DELAY(1);
+
+		NIC_WRITE_PORT_USHORT(
+			pAdapter,
+			PHYSICAL_MANAGEMENT_REGISTER,
+			PHY_WRITE);
+		
+		NIC_DELAY(1);
+    	}
+   	//
+    // Now run one clock with nobody driving.
+    //
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		PHYSICAL_MANAGEMENT_REGISTER, 
+		0);
+
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		PHYSICAL_MANAGEMENT_REGISTER,
+		PHY_CLOCK);
+
+	NIC_DELAY(1);
+	
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		PHYSICAL_MANAGEMENT_REGISTER,
+		0);
+	
+	NIC_DELAY(1);
+	//
+    // Now run one clock, expecting the PHY to be driving a 0 on the data
+    // line.  If we read a 1, it has to be just his pull-up, and he's not
+    // responding.
+    //
+    	PhyManagement = NIC_READ_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER);
+
+    	if (PhyManagement & PHY_DATA1) {
+			return FALSE;
+    	}
+    	//
+    	// We think we are in sync.  Now we read 16 bits of data from the PHY.
+    	//
+    	for (index = 0x8000; index; index >>= 1) {
+		//
+		// Shift input up one to make room
+		//
+		NIC_COMMAND(
+			pAdapter,
+			COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+	  	NIC_WRITE_PORT_USHORT(
+			pAdapter,
+			PHYSICAL_MANAGEMENT_REGISTER, 
+			PHY_CLOCK);
+
+		NIC_DELAY(1);
+		
+		NIC_WRITE_PORT_USHORT(
+			pAdapter,
+			PHYSICAL_MANAGEMENT_REGISTER,
+			0);
+		
+		NIC_DELAY(1);
+	
+		PhyManagement = NIC_READ_PORT_USHORT(
+					pAdapter,
+					PHYSICAL_MANAGEMENT_REGISTER);
+
+		if (PhyManagement & PHY_DATA1)
+	    		*pInput |= index;
+		else
+	    		*pInput &= ~index;
+	}
+    //
+    // OK now give it a couple of clocks with nobody driving.
+    //
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		PHYSICAL_MANAGEMENT_REGISTER,
+		0);
+
+    for (index = 0; index < 2; index++) {
+		
+		NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER,
+				PHY_CLOCK);
+
+		NIC_DELAY(1);
+		
+		NIC_WRITE_PORT_USHORT(
+				pAdapter,
+				PHYSICAL_MANAGEMENT_REGISTER, 
+				0);
+			
+		NIC_DELAY(1);
+	}
+    	return TRUE;
+}
+
+
+/*++
+
+Routine Name: 
+
+	MIIMediaOverride
+
+Routine Description:
+
+	MII values need to be updated based on what was set in the 
+	registry.
+  
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+	IN USHORT PhyModes
+	OUT PUSHORT MiiType
+
+Return Value:
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+MIIMediaOverride(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT PhyModes,
+	OUT PUSHORT MiiType
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	
+	switch(pAdapter->Hardware.MediaOverride) {
+
+		case MEDIA_10BASE_TX:
+
+			if (( PhyModes & MII_STATUS_10TFD ) &&
+				( pAdapter->Hardware.FullDuplexEnable == TRUE )) 
+				*MiiType = MIISELECT_10BT;
+	    
+			else if ( PhyModes & MII_STATUS_10T ) 
+				*MiiType = MIISELECT_10BT;
+  	
+			else 
+				return FALSE;
+		
+			break;
+
+		case MEDIA_100BASE_TX:
+
+			if (( PhyModes & MII_STATUS_100TXFD ) &&  
+				( pAdapter->Hardware.FullDuplexEnable == TRUE )) 
+				*MiiType = MIISELECT_100BTX;
+	    			
+			else if ( PhyModes & MII_STATUS_100TX ) 
+				*MiiType = MIISELECT_100BTX;
+
+			else 
+				return FALSE;
+			
+			break;
+	}
+	
+	return TRUE;
+}
+
+
+/*++
+
+Routine Name: 
+
+	ProgramMII
+
+Routine Description:
+	
+	Setup the necessary MII registers with values either 
+	read from the EEPROM or from command line
+
+Arguments:
+
+	IN PNIC_INFORMATION Adapter
+  	IN CONNECTOR_TYPE NewConnector 
+
+Return Value:
+	BOOLEAN
+
+--*/
+
+BOOLEAN
+ProgramMII(   
+	IN PNIC_INFORMATION Adapter,
+  	IN CONNECTOR_TYPE NewConnector 
+  	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	BOOLEAN PhyResponding;
+ 	USHORT PhyControl;
+    	USHORT PhyStatus;
+	NIC_STATUS status;
+    	USHORT MiiType=0, PhyModes;
+	ULONG TimeOutCount;
+    //
+    // First see if there's anything connected to the MII
+    //
+    if (!FindMIIPhy(pAdapter))
+		return FALSE;						 
+    // Nowhere is it written that the register must be latched, and since
+    // reset is the last bit out, the contents might not be valid.  read
+    // it one more time.
+    //
+    PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_CONTROL, &PhyControl);
+    //
+    // Now we can read the status and try to figure out what's out there.
+    //
+    PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyStatus);
+    if (!PhyResponding)
+		return FALSE;  	
+	//
+    // Reads the miiSelect field in EEPROM. Program MII as the default.
+   	//
+    status = tc90x_ReadEEPROM(
+				pAdapter,	
+				EEPROM_SOFTWARE_INFORMATION_3, 
+				&MiiType);				  	  
+	//                                                     
+	// If an override is present AND the transceiver type is available    
+	// on the card, that type will be used.  
+	//
+	PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyModes);
+    	if (!PhyResponding)
+			return FALSE;
+
+	PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_CONTROL, &PhyControl);
+    	if (!PhyResponding)
+			return FALSE;
+
+	if (!MIIMediaOverride(pAdapter, PhyModes, &MiiType))
+		return FALSE;
+  	//
+  	// If full duplex selected, set it in PhyControl. 
+	//
+    	if (pAdapter->Hardware.FullDuplexEnable) 
+			PhyControl |= MII_CONTROL_FULL_DUPLEX;
+    	else   
+       		PhyControl &= ~MII_CONTROL_FULL_DUPLEX;
+    
+    	PhyControl &= ~MII_CONTROL_ENABLE_AUTO;
+
+    	if (((MiiType & MIITXTYPE_MASK) == MIISELECT_100BTX) ||
+	    ((MiiType & MIITXTYPE_MASK) == MIISELECT_100BTX_ANE)) {
+		
+		PhyControl |= MII_CONTROL_100MB;
+		WriteMIIPhy(pAdapter, MII_PHY_CONTROL, PhyControl);
+		//delay 600 milliseconds
+		TimeOutCount = jiffies + (6*HZ/10);
+		while(TimeOutCount > jiffies);	
+		pAdapter->Hardware.LinkSpeed = 100000000L;
+		DBGPRINT_INITIALIZE(("ProgramMII() Set to 100M\n")); 
+		return TRUE;
+
+    	}
+    	else if (((MiiType & MIITXTYPE_MASK ) == MIISELECT_10BT) ||
+		 ((MiiType & MIITXTYPE_MASK ) == MIISELECT_10BT_ANE)) {
+	
+		PhyControl &= ~MII_CONTROL_100MB;
+		WriteMIIPhy(pAdapter, MII_PHY_CONTROL, PhyControl);
+		//delay 600 milliseconds
+		TimeOutCount = jiffies + (6*HZ/10);
+		while(TimeOutCount > jiffies);	
+		pAdapter->Hardware.LinkSpeed = 10000000L;
+		DBGPRINT_INITIALIZE(("ProgramMII() Set to 10M\n")); 
+		return TRUE;
+    	}
+
+    	PhyControl &= ~MII_CONTROL_100MB;
+    	WriteMIIPhy(pAdapter, MII_PHY_CONTROL, PhyControl);
+	//delay 600 milliseconds
+	TimeOutCount = jiffies + (6*HZ/10);
+	while(TimeOutCount > jiffies);	
+	pAdapter->Hardware.LinkSpeed = 10000000L;
+	DBGPRINT_INITIALIZE(("ProgramMII() Defaults to 10M\n")); 
+    return FALSE;
+}
+
+
+
+
+
+
+/*++
+
+Routine Name :
+
+	tc90x_CheckIfEEPROMBusy
+
+Routine Description:
+
+	This routine checks if the EEPROM is busy
+
+Arguments:
+
+	PDEVICE - Pointer to the device structure
+
+Return Value:
+	
+	NIC_STATUS_SUCCESS
+	NIC_STATUS_FAILURE
+
+--*/
+
+NIC_STATUS
+tc90x_CheckIfEEPROMBusy(
+	IN PNIC_INFORMATION Adapter
+	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT command = 0;
+	ULONG count;
+
+	count = jiffies + HZ;
+	do {
+		command = NIC_READ_PORT_USHORT(
+				pAdapter, 
+				EEPROM_COMMAND_REGISTER);
+ 		NIC_DELAY(10);
+	} while ( (command & EEPROM_BUSY_BIT) &&  (count > jiffies) );
+
+	if (count < jiffies) {
+		DBGPRINT_ERROR(("tc90x_CheckIfEEPROMBusy: command timeout"));
+   		return NIC_STATUS_FAILURE;
+	}
+	return NIC_STATUS_SUCCESS; 
+}
+
+/*++
+
+Routine Name:
+
+	tc90x_ReadEEPROM
+
+Routine Description:
+
+	This routine reads from the EEPROM
+
+Arguments:
+
+	PDEVICE - Pointer to the device structure
+	EEPROMAddress - EEPROM register to read
+	Contents - Buffer where contents of the location are returned 
+
+Return Value:
+    
+	NIC_STATUS_SUCCESS
+	NIC_STATUS_FAILURE
+
+--*/
+
+NIC_STATUS
+tc90x_ReadEEPROM(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT EEPROMAddress,
+	OUT PUSHORT Contents
+	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT lowerOffset = 0;
+	USHORT upperOffset = 0;
+
+	if (EEPROMAddress > 0x003F) {
+	
+		lowerOffset = EEPROMAddress & 0x003F;
+		upperOffset = (EEPROMAddress & 0x03C0) << 2;
+		EEPROMAddress = upperOffset | lowerOffset;
+	}
+
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_0);
+	//
+	// Check if EEPROM is busy
+	//
+	if (tc90x_CheckIfEEPROMBusy(pAdapter) != NIC_STATUS_SUCCESS) {
+
+   		DBGPRINT_ERROR(("tc90x_ReadEEPROM: EEPROM is busy\n"));
+		return NIC_STATUS_FAILURE;
+
+	}
+	//
+	// Issue the read eeprom data command
+	//
+	NIC_WRITE_PORT_USHORT(
+		pAdapter, 
+		EEPROM_COMMAND_REGISTER, 
+		(USHORT)(EEPROM_COMMAND_READ + (USHORT)EEPROMAddress));
+	//
+	// Check if EEPROM is busy
+	//
+	if (tc90x_CheckIfEEPROMBusy(pAdapter) != NIC_STATUS_SUCCESS) {
+
+        	DBGPRINT_ERROR((
+			"tc90x_ReadEEPROM: EEPROM is busy after command.\n"));
+
+		return NIC_STATUS_FAILURE;
+	}
+	//
+	// Save value read from eeprom
+	//
+	*Contents = NIC_READ_PORT_USHORT(
+			pAdapter, 
+			EEPROM_DATA_REGISTER);
+
+	return NIC_STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Name :
+
+	WriteEEPROM
+
+Routine Description:
+
+	This routine writes to the EEPROM
+
+Arguments:
+
+	PDEVICE - Pointer to the device structure
+	EEPROMAddress - EEPROM register to write
+	Data - Data to write
+ 
+Return Value:
+	
+	NIC_STATUS_SUCCESS
+	NIC_STATUS_FAILURE
+    
+--*/
+
+NIC_STATUS
+tc90x_WriteEEPROM(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT EEPROMAddress,
+	IN USHORT Data
+	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT lowerOffset = 0;
+	USHORT upperOffset = 0;
+	USHORT saveAddress;
+
+	saveAddress = EEPROMAddress;
+
+	if (EEPROMAddress > 0x003F) {
+	
+		lowerOffset = EEPROMAddress & 0x003F;
+		upperOffset = (EEPROMAddress & 0x03C0) << 2;
+		EEPROMAddress = upperOffset | lowerOffset;
+	}
+
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_0);
+
+	//
+	// Issue erase register command prior to writing
+	//
+	NIC_WRITE_PORT_USHORT(
+		pAdapter, 
+		EEPROM_COMMAND_REGISTER, 
+		(USHORT)EEPROM_WRITE_ENABLE);
+	
+	if (tc90x_CheckIfEEPROMBusy(pAdapter) != NIC_STATUS_SUCCESS){
+
+	        DBGPRINT_ERROR((
+			"WriteEEPROM: Write enable, EEPROM is busy\n"));
+
+		return NIC_STATUS_FAILURE;
+	}
+	
+	NIC_WRITE_PORT_USHORT(
+		pAdapter, 
+		EEPROM_COMMAND_REGISTER,
+		(USHORT)(EEPROM_ERASE_REGISTER + (USHORT)EEPROMAddress));
+
+	if (tc90x_CheckIfEEPROMBusy(pAdapter) != NIC_STATUS_SUCCESS){
+
+	        DBGPRINT_ERROR((
+			"WriteEEPROM: Erase Register, EEPROM is busy\n"));
+
+		return NIC_STATUS_FAILURE;
+	}	
+	//
+	// Load data to be written to the eeprom
+	//
+ 	NIC_WRITE_PORT_USHORT(pAdapter,	EEPROM_DATA_REGISTER, Data);
+
+//	DBGPRINT_INITIALIZE((
+//		"WriteEeprom: Writing value %x at %x \n" ,Data, saveAddress));
+	
+	if (tc90x_CheckIfEEPROMBusy(pAdapter) != NIC_STATUS_SUCCESS){
+
+	        DBGPRINT_ERROR((
+			"WriteEEPROM: Write data, EEPROM is busy\n"
+			));
+		return NIC_STATUS_FAILURE;
+    	}
+	
+
+	//
+	// Issue the write eeprom data command 
+	//
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		EEPROM_COMMAND_REGISTER,
+		(USHORT)EEPROM_WRITE_ENABLE);
+	
+	if (tc90x_CheckIfEEPROMBusy(pAdapter) != NIC_STATUS_SUCCESS){
+
+        	DBGPRINT_ERROR(("WriteEEPROM: EEPROM is busy\n"));
+		return NIC_STATUS_FAILURE;
+    	}
+   	 	
+	NIC_WRITE_PORT_USHORT(
+		pAdapter, 
+		EEPROM_COMMAND_REGISTER, 
+		(USHORT)(EEPROM_WRITE_REGISTER + (USHORT)EEPROMAddress));
+	
+	if (tc90x_CheckIfEEPROMBusy(pAdapter) != NIC_STATUS_SUCCESS){
+
+	        DBGPRINT_ERROR((
+			"WriteEEPROM: Write register, EEPROM is busy\n"));
+		return NIC_STATUS_FAILURE;
+    	}
+	return NIC_STATUS_SUCCESS;
+}
+
+
+
+/*++
+
+Routine Name :
+
+	CalculateEEPROMChecksum1
+
+Routine Description:
+
+	Calculates the EEPROM checksum #1 from offset 0 to 0x1F.
+
+Arguments:
+
+	PDEVICE - Pointer to the device structure
+ 
+Return Value:
+
+	Checksum #1 value
+
+--*/
+
+USHORT
+tc90x_CalculateEEPROMChecksum1(  
+	IN PNIC_INFORMATION Adapter
+    	) 
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	NIC_STATUS status;
+	USHORT checksum=0;
+  	USHORT value=0;
+	UCHAR index;
+
+	DBGPRINT_FUNCTION(("CalculateChecksum1: IN \n"));
+
+	NIC_COMMAND(
+		pAdapter,
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_0);
+
+	for (index = EEPROM_NODE_ADDRESS_WORD_0; 
+	     index < EEPROM_CHECKSUM_1; 
+	     index++) {
+
+		status = tc90x_ReadEEPROM(pAdapter, index, &value);
+		
+		if (status == NIC_STATUS_FAILURE) {
+
+			DBGPRINT_ERROR((
+				"CalculateEEPROMChecksum1: Read failure\n"));
+			
+			return NIC_STATUS_FAILURE;
+		}
+
+		checksum ^= (USHORT)LOBYTE(value);			 
+		checksum ^= (USHORT)HIBYTE(value);			 
+	}
+
+	DBGPRINT_FUNCTION(("CalculateChecksum1: OUT \n"));
+
+	return((USHORT)checksum);
+}
+
+
+
+
+
+NIC_STATUS 
+tc90x_SoftwareWork(
+	IN PNIC_INFORMATION Adapter
+	)
+
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	USHORT SoftwareInformation2 = 0;
+	ULONG DmaControl = 0;
+	USHORT NetDiag = 0;
+	USHORT Contents = 0;
+
+	DBGPRINT_FUNCTION(("SoftwareWork: IN\n"));
+	// Additional work#1
+
+	tc90x_ReadEEPROM(
+		pAdapter, 
+		EEPROM_SOFTWARE_INFORMATION_2, 
+		&Contents);
+
+	if (!(Contents & ENABLE_MWI_WORK)) {
+		
+		DmaControl = NIC_READ_PORT_ULONG(
+				pAdapter, 
+				DMA_CONTROL_REGISTER);
+       	
+		NIC_WRITE_PORT_ULONG(
+			pAdapter, 
+			DMA_CONTROL_REGISTER, 
+			(ULONG)(DMA_CONTROL_DEFEAT_MWI | DmaControl));
+	}
+
+	// Additional work#2
+
+	NIC_COMMAND(
+		pAdapter, 
+		COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
+
+    NetDiag = NIC_READ_PORT_USHORT(pAdapter, NETWORK_DIAGNOSTICS_REGISTER);
+    
+	if ((((NetDiag & NETWORK_DIAGNOSTICS_ASIC_REVISION) >> 4) == 1) &&
+       	    (((NetDiag & NETWORK_DIAGNOSTICS_ASIC_REVISION_LOW) >> 1) < 4)) {
+
+		pAdapter->Hardware.HurricaneEarlyRevision = TRUE;
+		DBGPRINT_INITIALIZE(("Hurricane Early board\n"));
+       	tc90x_HurricaneEarlyRevision(pAdapter);
+    }
+
+	SoftwareInformation2 = 0;
+	((PSOFTWARE_INFORMATION_2)&SoftwareInformation2)->D3Work = 1;
+
+	if (Contents & SoftwareInformation2) {
+		DBGPRINT_INITIALIZE(("Enable D3 work \n"));
+		pAdapter->Hardware.D3Work = TRUE;
+	}
+
+	
+	// Additional work#3
+
+	pAdapter->Hardware.DontSleep = FALSE;
+	
+	SoftwareInformation2 = 0;
+	((PSOFTWARE_INFORMATION_2)
+	&SoftwareInformation2)->WOLConnectorPresent = 1;
+
+	((PSOFTWARE_INFORMATION_2)&SoftwareInformation2)->AutoResetToD0 = 1;
+
+	DBGPRINT_INITIALIZE(("SoftwareInfo2 : %x\n", SoftwareInformation2));
+    
+	if (!(Contents & SoftwareInformation2)) {
+		DBGPRINT_INITIALIZE(("Don't sleep is TRUE \n"));
+		pAdapter->Hardware.DontSleep = TRUE;
+	}
+
+	DBGPRINT_FUNCTION(("SoftwareWork: OUT\n"));
+	return NIC_STATUS_SUCCESS;
+}
+
+VOID
+tc90x_FlowControl(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Adapter; 
+	BOOLEAN PhyResponding;
+	USHORT PhyAnar;
+	USHORT PhyControl;
+	PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_ANAR, &PhyAnar);
+	PhyAnar |= MII_ANAR_FLOWCONTROL;
+	WriteMIIPhy(pAdapter, MII_PHY_ANAR, PhyAnar);
+
+	PhyResponding = ReadMIIPhy(pAdapter, MII_PHY_CONTROL, &PhyControl);
+	PhyControl |= MII_CONTROL_START_AUTO;
+	WriteMIIPhy(pAdapter, MII_PHY_CONTROL, PhyControl);
+}
+
+VOID
+tc90x_HurricaneEarlyRevision(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	BOOLEAN PhyResponding;
+	USHORT PhyRegisterValue;
+
+    PhyResponding = ReadMIIPhy(
+				pAdapter, 
+				MII_PHY_REGISTER_24, 
+				&PhyRegisterValue);
+
+	if (!PhyResponding)
+		DBGPRINT_ERROR(("CaneRev-ReadMIIPhy: Phy not responding\n"));
+
+    PhyRegisterValue |= MII_PHY_REGISTER_24_PVCIRC;
+    
+	WriteMIIPhy(
+		pAdapter,
+		MII_PHY_REGISTER_24,
+		PhyRegisterValue);
+}
+
+NIC_STATUS
+RxResetAndWork(IN PNIC_INFORMATION Adapter)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	NIC_STATUS nicStatus;
+
+	nicStatus = NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
+
+	if (nicStatus != NIC_STATUS_SUCCESS) {
+		DBGPRINT_ERROR(("RxResetAndWork: Rx reset failed\n"));
+		return NIC_STATUS_FAILURE;
+	}
+	// not all work needed after Rx reset. Refine later
+	if (tc90x_SoftwareWork(pAdapter) != NIC_STATUS_SUCCESS) {
+		DBGPRINT_ERROR(("RxResetAndWork: SoftwareWork failed\n"));
+		return NIC_STATUS_FAILURE;
+	}
+	return NIC_STATUS_SUCCESS;
+}
+
+
+
+
+#define MAX_UNITS 8
+
+#ifdef DEBUG
+static ULONG debug = DEBUG_ERROR;
+#endif
+
+static INT switchdelay[] = {0, 0, 0, 0, 0, 0, 0, 0};
+static USHORT media_select[MAX_UNITS] = {MEDIA_NONE, };
+static INT flowcontrol[MAX_UNITS] = {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1};
+static INT downpoll[MAX_UNITS] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static INT full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+static ULONG tc90x_SendCount[] = { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 };
+static ULONG tc90x_ReceiveCount[] = { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 };
+
+NIC_STATUS
+tc90x_ReadCommandLineChanges(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	INT index = pAdapter->Index;
+	USHORT	mediatype;
+
+	DBGPRINT_INIT(("ReadCommandLineChanges: IN index=%x\n",index));
+
+	if (tc90x_SendCount[index] < NIC_MINIMUM_SEND_COUNT ||
+	    tc90x_SendCount[index] > NIC_MAXIMUM_SEND_COUNT) {
+
+		DBGPRINT_ERROR(("ProcessOverride: Using default value\n"));
+		pAdapter->Resources.SendCount = NIC_DEFAULT_SEND_COUNT; 
+	}
+	else  {
+		DBGPRINT_INITIALIZE(("SendCount = %x\n",(INT)tc90x_SendCount[index]));
+		pAdapter->Resources.SendCount = tc90x_SendCount[index];
+	}
+	
+	if (tc90x_ReceiveCount[index] < NIC_MINIMUM_RECEIVE_COUNT ||
+	    tc90x_ReceiveCount[index] > NIC_MAXIMUM_RECEIVE_COUNT) {
+
+		DBGPRINT_ERROR(("ReadCommandLineChanges: Using default receive\n"));
+		pAdapter->Resources.ReceiveCount = NIC_DEFAULT_RECEIVE_COUNT; 
+
+	}
+	else  {
+		pAdapter->Resources.ReceiveCount = tc90x_ReceiveCount[index];	
+	}
+	
+	DBGPRINT_INITIALIZE((
+		"ReceiveCount=%x\n", (INT)pAdapter->Resources.ReceiveCount));
+
+	if ( (index < MAX_UNITS)  && (flowcontrol[index] <= 0) ){
+
+		DBGPRINT_INITIALIZE(("User disables FlowControl\n"));
+		pAdapter->Hardware.FlowControlSupported = FALSE;
+		pAdapter->Hardware.FlowControlEnable = FALSE;
+	}
+	else {
+
+		DBGPRINT_INITIALIZE(("FlowControl is enabled by default\n"));
+		pAdapter->Hardware.FlowControlSupported = TRUE;
+		pAdapter->Hardware.FlowControlEnable = TRUE ;
+	}
+
+	if ( (index < MAX_UNITS)  && (downpoll[index] == 0x40) ){
+	
+		DBGPRINT_INITIALIZE(("DownPollRate is 64\n"));
+		pAdapter->Resources.DownPollRate = 0x40;
+	}
+	else {
+
+		DBGPRINT_INITIALIZE(("DownPollRate is 8 by default\n"));
+		pAdapter->Resources.DownPollRate = 0x8;
+	}
+
+	if ( (index < MAX_UNITS)  && (switchdelay[index] > 0) ){
+	
+		DBGPRINT_INITIALIZE(("User enables delay for switch\n"));
+		pAdapter->DelayStart = TRUE;
+	} 
+	else
+		pAdapter->DelayStart = FALSE;
+
+
+		/* Possible media selections:
+
+		MEDIA_NONE		0
+		MEDIA_10BASE_TX			1
+		MEDIA_10AUI				2
+		MEDIA_10BASE_2			3
+		MEDIA_100BASE_TX		4
+		MEDIA_100BASE_FX		5
+		MEDIA_10BASE_FL			6
+		MEDIA_AUTO_SELECT		7
+		*/
+
+		if ((pAdapter->Device)->mem_start)
+			mediatype = (pAdapter->Device)->mem_start;
+		else if (index < MAX_UNITS)
+			mediatype = media_select[index];
+		else
+			mediatype = MEDIA_NONE;
+
+		if ( (index < MAX_UNITS)  && (mediatype > 0) && (mediatype <= 7) )
+		{
+			pAdapter->Hardware.MediaOverride = mediatype;			
+			DBGPRINT_INITIALIZE(("User selects Media = %i\n", mediatype));
+		}
+		else
+			pAdapter->Hardware.MediaOverride = MEDIA_NONE;
+
+		if (pAdapter->Hardware.MediaOverride != MEDIA_AUTO_SELECT) {
+
+			if ( (index < MAX_UNITS)  &&  (full_duplex[index] > 0) )
+			{
+				DBGPRINT_INITIALIZE(("NotAutoSelect: User enables full duplex\n"));			
+				if ( (pAdapter->Hardware.MediaOverride != MEDIA_10AUI) &&
+					(pAdapter->Hardware.MediaOverride != MEDIA_10BASE_2) ) {
+
+						pAdapter->Hardware.FullDuplexEnable = TRUE;
+				}
+				pAdapter->Hardware.DuplexCommandOverride = TRUE;
+			}
+			else if ( (index < MAX_UNITS)  &&  (full_duplex[index] == 0) )
+			{	
+				DBGPRINT_INITIALIZE(("NotAutoSelect: User disables full duplex\n"));			
+				pAdapter->Hardware.FullDuplexEnable = FALSE;
+				pAdapter->Hardware.DuplexCommandOverride = TRUE;			
+			}
+			else
+				pAdapter->Hardware.DuplexCommandOverride = FALSE;
+		}
+
+	DBGPRINT_INITIALIZE(("ReadCommandLineChanges: OUT\n"));
+	return NIC_STATUS_SUCCESS;
+}
+
Index: oldkernel/linux/drivers/net/3c90x.h
diff -u /dev/null linux/drivers/net/3c90x.h:1.1
--- /dev/null	Mon Jul 31 21:12:13 2000
+++ linux/drivers/net/3c90x.h	Thu Jun  1 14:57:34 2000
@@ -0,0 +1,2140 @@
+/*
+   3Com EtherLink 10/100 PCI (3C90x) Linux Network Driver, Copyright (c) 1999
+   3Com Corporation. All rights reserved.
+   3Com Linux Network Driver software is distributed as is, without any warranty
+   of any kind, either express or implied as further specified in the GNU Public
+   License. This software may be used and distributed according to the terms of
+   the GNU Public License, located in the file LICENSE.
+
+   3Com and EtherLink are registered trademarks of 3Com Corporation. Linux is a
+   registered trademarks of Linus Torvalds. 
+*/
+
+//#define DEBUG	1
+#define SERR_NEEDED    1
+
+
+
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+/* don't define kernel_verion in module.h */
+#define __NO_VERSION__ 
+
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#include <linux/timer.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/tqueue.h>
+
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#if LINUX_VERSION_CODE <= 0x20200
+#include <linux/bios32.h>
+#endif
+
+#if LINUX_VERSION_CODE < 0x10300
+#define RUN_AT(x)			(x)
+#define DEV_ALLOC_SKB(length)		alloc_skb(length, GFP_ATOMIC)
+
+//#if defined(__alpha)
+//#error "The Alpha architecture is only supported with kernel version 2.0."
+//#endif
+
+#define virt_to_bus(address)		((ULONG)address)
+#define bus_to_virt(address)		((PVOID)address)
+#define NR_IRQS                      16
+
+#else
+
+#define RUN_AT(x)			(jiffies + (x))
+#define DEV_ALLOC_SKB(length)		dev_alloc_skb(length)
+
+#endif
+
+
+#if LINUX_VERSION_CODE < 0x20159
+#define DEV_FREE_SKB(skb)		dev_kfree_skb(skb, FREE_WRITE);
+#else
+#define DEV_FREE_SKB(skb)		dev_kfree_skb(skb);
+#endif
+
+
+#ifdef SA_SHIRQ
+#define FREE_IRQ(irqnum, dev)		free_irq(irqnum, dev)
+#define REQUEST_IRQ(i,h,f,n,instance)	request_irq(i,h,f,n,instance)
+#define IRQ(irq, dev_id, pt_regs)	(irq, dev_id, pt_regs)
+#else
+#define FREE_IRQ(irqnum, dev)		free_irq(irqnum)
+#define REQUEST_IRQ(i,h,f,n,instance)	request_irq(i,h,f,n)
+#define IRQ(irq, dev_id, pt_regs)	(irq, pt_regs)
+#endif
+
+
+#if (LINUX_VERSION_CODE >= 0x10344)
+#define NEW_MULTICAST
+#include <linux/delay.h>
+#else
+#define udelay(microsec) \
+    do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20200
+#include <asm/spinlock.h>
+#endif
+
+#if LINUX_VERSION_CODE < 0x20138
+#define test_and_set_bit(value, address)  \
+    set_bit(value, address)
+#endif
+
+
+
+
+#define BIT_0       (1 << 0)
+#define BIT_1       (1 << 1)
+#define BIT_2       (1 << 2)
+#define BIT_3       (1 << 3)
+#define BIT_4       (1 << 4)
+#define BIT_5       (1 << 5)
+#define BIT_6       (1 << 6)
+#define BIT_7       (1 << 7)
+#define BIT_8       (1 << 8)
+#define BIT_9       (1 << 9)
+#define BIT_10      (1 << 10)
+#define BIT_11      (1 << 11)
+#define BIT_12      (1 << 12)
+#define BIT_13      (1 << 13)
+#define BIT_14      (1 << 14)
+#define BIT_15      (1 << 15)
+#define BIT_16      (1 << 16)
+#define BIT_17      (1 << 17)
+#define BIT_18      (1 << 18)
+#define BIT_19      (1 << 19)
+#define BIT_20      (1 << 20)
+#define BIT_21      (1 << 21)
+#define BIT_22      (1 << 22)
+#define BIT_23      (1 << 23)
+#define BIT_24      (1 << 24)
+#define BIT_25      (1 << 25)
+#define BIT_26      (1 << 26)
+#define BIT_27      (1 << 27)
+#define BIT_28      (1 << 28)
+#define BIT_29      (1 << 29)
+#define BIT_30      (1 << 30)
+#define BIT_31      (1 << 31)
+
+
+#ifndef HIBYTE
+ 
+#define HIBYTE(_w) (((USHORT)(_w)) >> 8)
+
+#endif
+
+#ifndef LOBYTE
+
+#define LOBYTE(_w) ((UCHAR)((_w) & 0xFF))
+
+#endif
+
+
+typedef char *PCHAR;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef unsigned short USHORT;
+typedef unsigned char UCHAR;
+typedef void VOID;
+typedef char CHAR;
+typedef int INT;
+typedef unsigned long *PULONG;
+typedef unsigned short *PUSHORT;
+typedef unsigned char *PUCHAR;
+typedef void *PVOID;
+typedef UCHAR BOOLEAN;
+typedef BOOLEAN *PBOOLEAN;
+
+typedef struct enet_statistics ENET_STATISTICS;
+typedef struct dev_mc_list DEV_MC_LIST, *PDEV_MC_LIST;
+typedef struct timer_list TIMER;
+typedef struct tq_struct TASKQ;
+
+#define FALSE		0
+#define TRUE		1
+
+//
+// Linux Error code.
+//
+typedef ULONG LINUX_ERROR_CODE;
+#define LINUX_ERROR_CODE_OUT_OF_RESOURCES	0x1
+
+#define IN 
+#define OUT
+
+
+/*
+ * Typedefs for Linux structures
+ */
+
+typedef struct device *PDEVICE;
+typedef struct device DEVICE;
+typedef struct ifreq *PIFREQ;
+typedef struct sk_buff *PSKB;
+typedef struct pt_regs *PTREGS;
+typedef struct enet_statistics *PENET_STATISTICS;
+
+
+
+
+
+/*
+ * 3Com Node Address
+ */
+
+#define EEPROM_NODE_ADDRESS_WORD_0		0x00
+#define EEPROM_NODE_ADDRESS_WORD_1		0x01
+#define EEPROM_NODE_ADDRESS_WORD_2		0x02
+
+#define EEPROM_DEVICE_ID			0x03
+/*++
+
+    Possible values:
+
+        0x9055 - PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX connector.
+        0x9056 - PCI 10/100 Mbps; shared 10BASE-T/100BASE-T4 connector.
+        0x9004 - PCI 10BASE-T (TPO)
+        0x9005 - PCI 10BASE-T/10BASE-2/AUI(COMBO)
+        0x9006 - PCI 10BASE-T/10BASE-2/(TPC)
+
+--*/
+#define EEPROM_MANUFACTURING_DATE		0x04
+
+typedef struct _MANUFACTURING_DATE {
+
+	USHORT Day:5;
+        USHORT Month:4;
+        USHORT Year:7;
+
+} MANUFACTURING_DATE;
+
+#define EEPROM_MANUFACTURING_DIVISION		0x05
+#define EEPROM_MANUFACTURING_PRODUCT_CODE	0x06
+#define EEPROM_MANUFACTURING_ID			0x07
+#define EEPROM_PCI_PARAMETERS_1			0x08
+
+typedef struct _PCI_PARAMETERS_1 {
+    
+        USHORT Bit0:1;
+        USHORT Lower1Meg:1;
+        USHORT DisableMemoryBase:1;
+        USHORT D3SupportCold:1;
+        USHORT D1Support:1;
+        USHORT D2Support:1;
+        USHORT MinimumGrant:4;
+        USHORT MaximumLatency:6;
+
+} PCI_PARAMETERS_1, *PPCI_PARAMETERS_1;
+
+#define EEPROM_ROM_INFORMATION			0x09
+
+typedef struct _ROM_INFORMATION {
+
+        USHORT Reserved:11;
+        USHORT ROMPresent:1;
+        //
+        // 0x00 - 64k * 8.
+        // 0x01 - 128k * 8.
+        // 0x1x - Reserved.
+        //
+        USHORT RomSize:2;
+
+} ROM_INFORMATION, *PROM_INFORMATION;
+
+/*
+ * OEM Node address
+ */
+#define EEPROM_OEM_NODE_ADDRESS_WORD_0		0x0A
+#define EEPROM_OEM_NODE_ADDRESS_WORD_1		0x0B
+#define EEPROM_OEM_NODE_ADDRESS_WORD_2		0x0C
+
+#define EEPROM_SOFTWARE_INFORMATION_1		0x0D
+
+typedef struct _SOFTWARE_INFORMATION_1 {
+
+        USHORT Reserved1:4;
+
+        #define EEPROM_OPTIMIZE_NORMAL              0x1
+        #define EEPROM_OPTIMIZE_FOR_THROUGHPUT      0x2
+        #define EEPROM_OPTIMIZE_FOR_CPU             0x3 
+        USHORT OptimizeFor:2;
+        
+        USHORT Reserved2:8;
+        USHORT LinkBeatDisable:1;
+
+        #define EEPROM_DISABLE_FULL_DUPLEX          0x00
+        #define EEPROM_ENABLE_FULL_DUPLEX           0x01
+        USHORT FullDuplexMode:1;
+
+} SOFTWARE_INFORMATION_1, *PSOFTWARE_INFORMATION_1;
+
+#define EEPROM_COMPATABILITY_WORD		0x0E
+#define EEPROM_COMPATABILITY_LEVEL		0x00
+typedef struct _COMPATABILITY_WORD {
+
+	USHORT WarningLevel:8;
+	USHORT FailureLevel:8;
+
+} COMPATABILITY_WORD, *PCOMPATABILITY_WORD;
+
+#define EEPROM_SOFTWARE_INFORMATION_2		0x0F
+#define ENABLE_MWI_WORK			0x0020
+
+typedef struct _SOFTWARE_INFORMATION_2 {
+
+        USHORT Reserved1:1;
+        USHORT BroadcastRxErrDone:1;
+        USHORT EncoderDecoderLoopBackErrDone:1;
+        USHORT WOLConnectorPresent:1;
+        USHORT PMEPulsed:1;
+        USHORT MWIErrDone:1;
+        USHORT AutoResetToD0:1;
+		USHORT D3Work:1;
+
+} SOFTWARE_INFORMATION_2, *PSOFTWARE_INFORMATION_2;
+
+#define EEPROM_CAPABILITIES_WORD		0x10
+typedef struct _CAPABILITIES_WORD {
+
+        USHORT SupportsPlugNPlay:1;
+        USHORT SupportsFullDuplex:1;
+        USHORT SupportsLargePackets:1;
+        USHORT SupportsSlaveDMA:1;
+        USHORT SupportsSecondDMA:1;
+        USHORT SupportsFullBusMaster:1;
+        USHORT SupportsFragBusMaster:1;
+        USHORT SupportsCRCPassThrough:1;
+        USHORT SupportsTxDone:1;
+        USHORT SupportsNoTxLength:1;
+        USHORT SupportsRxRepeat:1;
+        USHORT Supports100Mbps:1;
+        USHORT SupportsPowerManagement:1;
+
+} CAPABILITIES_WORD, *PCAPABILITIES_WORD;
+
+#define EEPROM_RESERVED_LOCATION		0x11
+#define EEPROM_INTERNAL_CONFIG_WORD_0		0x12
+#define EEPROM_INTERNAL_CONFIG_WORD_1		0x13
+#define EEPROM_ANALOG_DIAGNOSTICS		0x14
+#define EEPROM_SOFTWARE_INFORMATION_3		0x15
+
+typedef struct _SOFTWARE_INFORMATION_3 {
+
+        #define EEPROM_GENERIC_MII                  0x00
+        #define EEPROM_100BASE_T4_MII               0x01
+        #define EEPROM_10BASE_T_MII                 0x02         
+        #define EEPROM_100BASE_TX_MII               0x03
+        #define EEPROM_10_BASE_T_AUTONEGOTIATION    0x04
+        #define EEPROM_100_BASE_TX_AUTONEGOTIATION  0x04                  
+        USHORT ForceXcvr:4;
+
+        USHORT Reserved:12;
+
+} SOFTWARE_INFORMATION_3, *PSOFTWARE_INFORMATION_3;
+/*
+ * Locations 0x1E - 0x1F are reserved.
+ */
+#define EEPROM_CHECKSUM_1			0x20
+/*
+ * Locations 0x21 - 0x2F are reserved.
+ */
+#define EEPROM_SOS_PINS_1_TO_4			0x21
+#define EEPROM_SOS_PINS_5_TO_7			0x22
+/*
+ * Locations 0x00 - 0xFD are flexible format locations (4kb EEPROMs)
+ */
+#define EEPROM_CHECKSUM_2_UPPER			0xFE
+#define EEPROM_CHECKSUM_2_LOWER			0xFF
+/*
+ * Locations 0x00 - 0x3FD are flexible format locations (16Kb EEPROMs)
+ */
+#define EEPROM_CHECKSUM_3_UPPER                0x3FE
+#define EEPROM_CHECKSUM_3_LOWER                0x3FF
+#define EEPROM_COMMAND_MASK			0xE000
+#define EEPROM_COMMAND_AUTOINIT_DONE		0xE000
+#define EEPROM_COMMAND_PCI_CONFIG_WRITE		0xA000
+#define EEPROM_COMMAND_REGISTER_WRITE		0x6000
+#define EEPROM_COMMAND_TX_FIFO_WRITE		0x2000
+#define EEPROM_CURRENT_WINDOW_MASK		0x7000
+#define EEPROM_ADDRESS_MASK			0x00FF
+#define EEPROM_TX_BYTE_COUNT			0x03FF
+#define EEPROM_FLEXIBLE_FORMAT_START		0x40
+#define EEPROM_WORD_ACCESS			0x1000
+#define MAX_FLEX_EEPROM_SIZE			2048
+
+#define EEPROM_WINDOW_0				(0x0 << 0x8)
+#define EEPROM_WINDOW_1				(0x1 << 0x8)
+#define EEPROM_WINDOW_2				(0x2 << 0x8)	
+#define EEPROM_WINDOW_3				(0x3 << 0x8)
+#define EEPROM_WINDOW_4				(0x4 << 0x8)
+#define EEPROM_WINDOW_5				(0x5 << 0x8)	
+#define EEPROM_WINDOW_6				(0x6 << 0x8)
+#define EEPROM_WINDOW_7				(0x7 << 0x8)
+
+
+
+typedef struct _PCI_CONFIG_CONFIGURATION_REGISTERS {
+
+    USHORT VendorId;
+    USHORT DeviceId;
+    USHORT Command;
+    USHORT Status;
+    UCHAR RevisionId;
+    UCHAR ClassCode[3];
+    UCHAR CacheLineSize;
+    UCHAR LatencyTimer;
+    UCHAR HeaderType;
+    UCHAR Reserved1;
+    ULONG IoBaseAddress;
+    ULONG MemoryBaseAddress;
+    ULONG Reserved2;
+    ULONG Reserved3;
+    ULONG Reserved4;
+    ULONG Reserved5;
+    ULONG Reserved6;
+    USHORT SubSystemVendorId;
+    USHORT SubSystemId;
+    ULONG BIOSRomControl;
+    UCHAR CapabilityPointer;
+    UCHAR Reserved7[3];
+    ULONG Reserved8;
+    UCHAR InterruptLine;
+    UCHAR InterruptPin;
+    UCHAR MinimumGrant;
+    UCHAR MaximumLatency;
+    ULONG Reserved9;
+    ULONG Reserved10;
+    ULONG Reserved11;
+    ULONG Reserved12;
+    UCHAR MediaTestModeLow;
+    UCHAR Reserved13[3];
+    UCHAR MediaTestModeHigh;
+    UCHAR Reserved14[3];
+    UCHAR MediaTestOutput;
+    UCHAR Reserved15[3];
+    UCHAR MediaTestPattern;
+    UCHAR Reserved16[3];
+    ULONG Reserved17[31];
+    UCHAR CapabilityId;
+    UCHAR NextPointer;
+    USHORT PowerManagementCapability;
+    USHORT PowerManagementControl;
+    UCHAR Reserved18;
+    UCHAR Data;
+
+} PCI_CONFIG_CONFIGURATION_REGISTERS, *PPCI_CONFIG__CONFIGURATION_REGISTERS;
+
+typedef struct _PCI_CONFIG_COMMAND {
+
+    USHORT IoSpace:1;
+    USHORT MemorySpace:1;
+    USHORT BusMasterEnable:1;
+    USHORT Reserved1:1;
+    USHORT MWIEnable:1;
+    USHORT Reserved2:1;
+    USHORT ParityErrorResponse:1;
+    USHORT Reserved3:1;
+    USHORT SERREnable:1;
+
+} PCI_CONFIG_COMMAND, *PPCI_CONFIG_COMMAND;
+
+
+typedef struct _PCI_CONFIG_STATUS {
+
+    USHORT Reserved1:4;
+    USHORT CapabilitiesList:1;
+    USHORT Reserved2:2;
+    USHORT FastBackToBack:1;
+    USHORT DmaParityDetected:1;
+    USHORT DevselTiming:2;
+    USHORT SignalTargetAbort:1;
+    USHORT ReceivedTargetAbort:1;
+    USHORT ReceivedMasterAbort:1;
+    USHORT SignaledSystemError:1;
+    USHORT DetectedParityError:1;
+
+} PCI_CONFIG__STATUS, *PPCI_CONFIG_STATUS;
+
+typedef struct _PCI_CONFIG_REVISION_ID {
+
+    UCHAR Revision:5;
+    UCHAR ChipVersion:3;
+
+} PCI_CONFIG_REVISION_ID, *PCI_CONFIG_PREVISION_ID;
+
+
+#define PCI_POWER_CONTROL		0xE0
+#define PCI_PME_ENABLE			0x0100
+#define PCI_PME_STATUS			0x8000
+
+
+typedef struct _PCI_CONFIG_POWER_MANAGEMENT_CONTROL {
+
+    #define PCI_POWER_STATE_D0      0x00
+    #define PCI_POWER_STATE_D1      0x01
+    #define PCI_POWER_STATE_D2      0x02
+    #define PCI_POWER_STATE_D3      0x03   
+    USHORT PowerState:2;
+
+    USHORT Reserved1:6;
+    USHORT PMEEnable:1;
+    USHORT DataSelect:4;
+    USHORT DataScale:2;
+    USHORT PMEStatus:1;
+
+} PCI_CONFIG_POWER_MANAGEMENT_CONTROL, 
+ *PPCI_CONFIG_POWER_MANAGEMENT_CONTROL;
+
+
+//
+// Supported PCI device id's
+//
+#define NIC_VENDOR_ID				0x10B7
+#define NIC_PCI_DEVICE_ID_9055			0x9055
+#define NIC_PCI_DEVICE_ID_9056			0x9056
+#define NIC_PCI_DEVICE_ID_9058			0x9058
+#define NIC_PCI_DEVICE_ID_9004			0x9004
+#define NIC_PCI_DEVICE_ID_9005			0x9005
+#define NIC_PCI_DEVICE_ID_9006			0x9006
+#define NIC_PCI_DEVICE_ID_900A			0x900A
+#define NIC_PCI_DEVICE_ID_905A			0x905A
+#define NIC_PCI_DEVICE_ID_9200			0x9200
+#define NIC_PCI_DEVICE_ID_9800			0x9800
+#define NIC_PCI_DEVICE_ID_9805			0x9805
+//
+// ASIC versions.
+//
+#define NIC_ASIC_CYCLONE_KRAKATOA_LUCENT        0x0
+#define NIC_ASIC_HURRICANE_TORNADO_LUCENT       0x1
+#define NIC_ASIC_HURRICANE_NATIONAL             0x2
+#define NIC_ASIC_HURRICANE_TORNADO_BROADCOM     0x3
+//
+// Window definitions.
+//
+#define REGISTER_WINDOW_0		0x0  // setup/configuration
+#define REGISTER_WINDOW_1		0x1  // operating set
+#define REGISTER_WINDOW_2		0x2  // station address setup/read
+#define REGISTER_WINDOW_3		0x3 // FIFO management
+#define REGISTER_WINDOW_4		0x4 // diagnostics
+#define REGISTER_WINDOW_5		0x5 // registers set by commands
+#define REGISTER_WINDOW_6		0x6 // statistics
+#define REGISTER_WINDOW_7		0x7 // bus master control
+#define REGISTER_WINDOW_MASK		0xE000
+
+//
+// ------------------ Register definitions ---------------------
+//
+#define INTSTATUS_INTERRUPT_MASK	0x6EE  
+//
+// Window 0 registers.
+//
+
+#define BIOS_ROM_ADDRESS_REGISTER	0x4
+#define BIOS_ROM_DATA_REGISTER		0x8
+
+#define EEPROM_COMMAND_REGISTER		0xA
+#define EEPROM_BUSY_BIT			BIT_15
+#define EEPROM_COMMAND_READ		0x0080   
+#define EEPROM_WRITE_ENABLE		0x0030
+#define EEPROM_ERASE_REGISTER		0x00C0
+#define EEPROM_WRITE_REGISTER		0x0040
+
+#define EEPROM_DATA_REGISTER		0xC
+
+#define INTSTATUS_COMMAND_REGISTER	0xE
+#define INTSTATUS_INTERRUPT_LATCH	BIT_0
+#define INTSTATUS_HOST_ERROR		BIT_1
+#define INTSTATUS_TX_COMPLETE		BIT_2
+#define INTSTATUS_RX_COMPLETE		BIT_4
+#define INTSTATUS_INTERRUPT_REQUESTED	BIT_6
+#define INTSTATUS_UPDATE_STATISTICS	BIT_7
+#define INTSTATUS_LINK_EVENT		BIT_8
+#define INTSTATUS_DOWN_COMPLETE		BIT_9
+#define INTSTATUS_UP_COMPLETE		BIT_10
+#define INTSTATUS_COMMAND_IN_PROGRESS	BIT_12
+#define INTSTATUS_INTERRUPT_NONE	0
+#define INTSTATUS_INTERRUPT_ALL		0x6EE  
+#define INTSTATUS_ACKNOWLEDGE_ALL	0x7FF
+
+
+//
+// Window 2 registers.
+//
+#define STATION_ADDRESS_LOW_REGISTER		0x0
+#define STATION_ADDRESS_MID_REGISTER		0x2
+#define STATION_ADDRESS_HIGH_REGISTER		0x4
+
+//
+// Window 3 registers.
+//
+
+#define INTERNAL_CONFIG_REGISTER		0x0
+#define INTERNAL_CONFIG_DISABLE_BAD_SSD		BIT_8
+#define INTERNAL_CONFIG_ENABLE_TX_LARGE		BIT_14
+#define INTERNAL_CONFIG_ENABLE_RX_LARGE		BIT_15
+#define INTERNAL_CONFIG_AUTO_SELECT		BIT_24
+#define INTERNAL_CONFIG_DISABLE_ROM		BIT_25
+#define INTERNAL_CONFIG_TRANSCEIVER_MASK	0x00F00000L
+
+#define MAXIMUM_PACKET_SIZE_REGISTER		0x4
+
+#define MAC_CONTROL_REGISTER			0x6
+#define MAC_CONTROL_FULL_DUPLEX_ENABLE		BIT_5
+#define MAC_CONTROL_ALLOW_LARGE_PACKETS		BIT_6
+#define MAC_CONTROL_FLOW_CONTROL_ENABLE 	BIT_8
+#define MEDIA_OPTIONS_REGISTER			0x8
+#define MEDIA_OPTIONS_100BASET4_AVAILABLE	BIT_0
+#define MEDIA_OPTIONS_100BASETX_AVAILABLE	BIT_1
+#define MEDIA_OPTIONS_100BASEFX_AVAILABLE	BIT_2
+#define MEDIA_OPTIONS_10BASET_AVAILABLE		BIT_3
+#define MEDIA_OPTIONS_10BASE2_AVAILABLE		BIT_4
+#define MEDIA_OPTIONS_10AUI_AVAILABLE		BIT_5
+#define MEDIA_OPTIONS_MII_AVAILABLE		BIT_6
+#define MEDIA_OPTIONS_10BASEFL_AVAILABLE	BIT_8
+
+#define RX_FREE_REGISTER			0xA
+#define TX_FREE_REGISTER			0xC
+
+//
+// Window 4 registers.
+//
+#define PHYSICAL_MANAGEMENT_REGISTER		0x8
+#define NETWORK_DIAGNOSTICS_REGISTER		0x6
+#define NETWORK_DIAGNOSTICS_ASIC_REVISION	0x003E
+#define NETWORK_DIAGNOSTICS_ASIC_REVISION_LOW  	0x000E 
+#define NETWORK_DIAGNOSTICS_UPPER_BYTES_ENABLE 	BIT_6
+#define MEDIA_STATUS_REGISTER				0xA
+#define MEDIA_STATUS_SQE_STATISTICS_ENABLE	BIT_3
+#define MEDIA_STATUS_CARRIER_SENSE		BIT_5
+#define MEDIA_STATUS_JABBER_GUARD_ENABLE	BIT_6
+#define MEDIA_STATUS_LINK_BEAT_ENABLE		BIT_7
+#define MEDIA_STATUS_LINK_DETECT		BIT_11
+#define MEDIA_STATUS_TX_IN_PROGRESS		BIT_12
+#define MEDIA_STATUS_DC_CONVERTER_ENABLED	BIT_14
+#define BAD_SSD_REGISTER			0xC
+#define UPPER_BYTES_OK_REGISTER			0xD
+//
+// Window 5 registers.
+//
+#define RX_FILTER_REGISTER		0x8
+#define INTERRUPT_ENABLE_REGISTER	0xA
+#define INDICATION_ENABLE_REGISTER	0xC
+//
+// Window 6 registers.
+//
+#define CARRIER_LOST_REGISTER		0x0
+#define SQE_ERRORS_REGISTER		0x1
+#define MULTIPLE_COLLISIONS_REGISTER	0x2
+#define SINGLE_COLLISIONS_REGISTER	0x3
+#define LATE_COLLISIONS_REGISTER	0x4
+#define RX_OVERRUNS_REGISTER		0x5
+#define FRAMES_TRANSMITTED_OK_REGISTER	0x6
+#define FRAMES_RECEIVED_OK_REGISTER	0x7
+#define FRAMES_DEFERRED_REGISTER	0x8
+#define UPPER_FRAMES_OK_REGISTER	0x9
+#define BYTES_RECEIVED_OK_REGISTER	0xA
+#define BYTES_TRANSMITTED_OK_REGISTER	0xC
+//
+// Window 7 registers.
+//
+#define TIMER_REGISTER			0x1A
+#define TX_STATUS_REGISTER		0x1B
+#define TX_STATUS_MAXIMUM_COLLISION	BIT_3
+#define TX_STATUS_HWERROR		BIT_4
+#define TX_STATUS_JABBER		BIT_5
+#define TX_STATUS_INTERRUPT_REQUESTED	BIT_6
+#define TX_STATUS_COMPLETE		BIT_7
+#define INT_STATUS_AUTO_REGISTER	0x1E
+#define DMA_CONTROL_REGISTER		0x20
+#define DMA_CONTROL_DOWN_STALLED	BIT_2
+#define DMA_CONTROL_UP_COMPLETE		BIT_3
+#define DMA_CONTROL_DOWN_COMPLETE	BIT_4
+
+#define DMA_CONTROL_ARM_COUNTDOWN       BIT_6
+#define DMA_CONTROL_DOWN_IN_PROGRESS    BIT_7
+#define DMA_CONTROL_COUNTER_SPEED       BIT_8
+#define DMA_CONTROL_COUNTDOWN_MODE      BIT_9
+#define DMA_CONTROL_DOWN_SEQ_DISABLE    BIT_17
+#define DMA_CONTROL_DEFEAT_MWI          BIT_20
+#define DMA_CONTROL_DEFEAT_MRL          BIT_21
+#define DMA_CONTROL_UPOVERDISC_DISABLE	BIT_22
+#define DMA_CONTROL_TARGET_ABORT        BIT_30
+#define DMA_CONTROL_MASTER_ABORT        BIT_31
+
+#define DOWN_LIST_POINTER_REGISTER	0x24
+#define DOWN_POLL_REGISTER		0x2D
+#define UP_PACKET_STATUS_REGISTER		0x30
+#define UP_PACKET_STATUS_ERROR			BIT_14
+#define UP_PACKET_STATUS_COMPLETE		BIT_15
+#define UP_PACKET_STATUS_OVERRUN		BIT_16
+#define UP_PACKET_STATUS_RUNT_FRAME		BIT_17
+#define UP_PACKET_STATUS_ALIGNMENT_ERROR	BIT_18
+#define UP_PACKET_STATUS_CRC_ERROR             	BIT_19
+#define UP_PACKET_STATUS_OVERSIZE_FRAME        	BIT_20
+#define UP_PACKET_STATUS_DRIBBLE_BITS		BIT_23
+#define UP_PACKET_STATUS_OVERFLOW		BIT_24
+#define UP_PACKET_STATUS_IP_CHECKSUM_ERROR	BIT_25
+#define UP_PACKET_STATUS_TCP_CHECKSUM_ERROR	BIT_26
+#define UP_PACKET_STATUS_UDP_CHECKSUM_ERROR	BIT_27
+#define UP_PACKET_STATUS_IMPLIED_BUFFER_ENABLE	BIT_28
+#define UP_PACKET_STATUS_IP_CHECKSUM_CHECKED	BIT_29
+#define UP_PACKET_STATUS_TCP_CHECKSUM_CHECKED	BIT_30
+#define UP_PACKET_STATUS_UDP_CHECKSUM_CHECKED	BIT_31
+#define UP_PACKET_STATUS_ERROR_MASK		0x1F0000
+#define FREE_TIMER_REGISTER			0x34
+#define COUNTDOWN_REGISTER			0x36
+#define UP_LIST_POINTER_REGISTER		0x38
+#define UP_POLL_REGISTER			0x3D
+#define REAL_TIME_COUNTER_REGISTER		0x40
+#define CONFIG_ADDRESS_REGISTER			0x44
+#define CONFIG_DATA_REGISTER			0x48
+#define DEBUG_DATA_REGISTER			0x70
+#define DEBUG_CONTROL_REGISTER			0x74
+// ------------------ Commands ---------------------------------
+//
+// Global reset command.
+//
+
+#define COMMAND_GLOBAL_RESET		(0x0 << 0xB)
+#define GLOBAL_RESET_MASK_TP_AUI_RESET	BIT_0
+#define GLOBAL_RESET_MASK_ENDEC_RESET   BIT_1
+#define GLOBAL_RESET_MASK_NETWORK_RESET	BIT_2
+#define GLOBAL_RESET_MASK_FIFO_RESET    BIT_3
+#define GLOBAL_RESET_MASK_AISM_RESET    BIT_4
+#define GLOBAL_RESET_MASK_HOST_RESET	BIT_5
+#define GLOBAL_RESET_MASK_SMB_RESET     BIT_6
+#define GLOBAL_RESET_MASK_VCO_RESET     BIT_7
+#define GLOBAL_RESET_MASK_UP_DOWN_RESET BIT_8
+
+#define COMMAND_SELECT_REGISTER_WINDOW	(0x1 << 0xB)
+#define COMMAND_ENABLE_DC_CONVERTER	(0x2 << 0xB)
+#define COMMAND_RX_DISABLE		(0x3 << 0xB)
+#define COMMAND_RX_ENABLE		(0x4 << 0xB)
+//
+// Receiver reset command.
+//
+#define COMMAND_RX_RESET		(0x5 << 0xB)
+#define RX_RESET_MASK_TP_AUI_RESET	BIT_0
+#define RX_RESET_MASK_ENDEC_RESET	BIT_1
+#define RX_RESET_MASK_NETWORK_RESET	BIT_2
+#define RX_RESET_MASK_FIFO_RESET	BIT_3
+#define RX_RESET_MASK_UP_RESET		BIT_8
+
+#define COMMAND_UP_STALL		((0x6 << 0xB) | 0x0)
+#define COMMAND_UP_UNSTALL		((0x6 << 0xB) | 0x1)
+#define COMMAND_DOWN_STALL		((0x6 << 0xB) | 0x2)
+#define COMMAND_DOWN_UNSTALL		((0x6 << 0xB) | 0x3)
+#define COMMAND_TX_DONE			(0x7 << 0xB)
+#define COMMAND_RX_DISCARD		(0x8 << 0xB)
+#define COMMAND_TX_ENABLE		(0x9 << 0xB)
+#define COMMAND_TX_DISABLE		(0xA << 0xB)
+//
+// Transmitter reset command.
+//
+#define COMMAND_TX_RESET		(0xB << 0xB) 
+#define TX_RESET_MASK_TP_AUI_RESET	BIT_0
+#define TX_RESET_MASK_ENDEC_RESET	BIT_1
+#define TX_RESET_MASK_NETWORK_RESET	BIT_2
+#define TX_RESET_MASK_FIFO_RESET	BIT_3
+#define TX_RESET_MASK_DOWN_RESET	BIT_8
+#define COMMAND_REQUEST_INTERRUPT	(0xC << 0xB)
+//
+// Interrupt acknowledge command.
+//
+
+#define COMMAND_ACKNOWLEDGE_INTERRUPT	(0xD << 0xB)
+#define ACKNOWLEDGE_INTERRUPT_LATCH	BIT_0
+#define ACKNOWLEDGE_LINK_EVENT		BIT_1
+#define ACKNOWLEDGE_INTERRUPT_REQUESTED	BIT_6
+#define ACKNOWLEDGE_DOWN_COMPLETE	BIT_9
+#define ACKNOWLEDGE_UP_COMPLETE		BIT_10
+#define ACKNOWLEDGE_ALL_INTERRUPT	0x7FF   
+#define COMMAND_SET_INTERRUPT_ENABLE	(0xE << 0xB)
+#define DISABLE_ALL_INTERRUPT		0x0 
+#define ENABLE_ALL_INTERRUPT		0x6EE 
+#define COMMAND_SET_INDICATION_ENABLE	(0xF << 0xB)
+//
+// Receive filter command.
+//
+#define COMMAND_SET_RX_FILTER		(0x10 << 0xB)
+#define RX_FILTER_INDIVIDUAL            BIT_0
+#define RX_FILTER_ALL_MULTICAST         BIT_1
+#define RX_FILTER_BROADCAST             BIT_2
+#define RX_FILTER_PROMISCUOUS           BIT_3
+#define RX_FILTER_MULTICAST_HASH        BIT_4
+#define COMMAND_TX_AGAIN		(0x13 << 0xB)
+#define COMMAND_STATISTICS_ENABLE	(0x15 << 0xB)
+#define COMMAND_STATISTICS_DISABLE	(0x16 << 0xB)
+#define COMMAND_DISABLE_DC_CONVERTER	(0x17 << 0xB)
+#define COMMAND_SET_HASH_FILTER_BIT	(0x19 << 0xB)
+#define COMMAND_TX_FIFO_BISECT		(0x1B << 0xB)
+//
+// ------------------ Adapter limits ---------------------------
+//
+#define TRANSMIT_FIFO_SIZE         0x800
+#define RECEIVE_FIFO_SIZE          0x800
+//
+// Ethernet limits.
+//
+#define ETHERNET_MAXIMUM_FRAME_SIZE	1514
+#define ETHERNET_MINIMUM_FRAME_SIZE	60
+#define ETHERNET_ADDRESS_SIZE		6
+#define ETHERNET_HEADER_SIZE		14
+//
+// Flow Control Address that gets put into the hash filter for 
+// flow control enable
+//
+#define NIC_FLOW_CONTROL_ADDRESS_0	0x01
+#define NIC_FLOW_CONTROL_ADDRESS_1	0x80
+#define NIC_FLOW_CONTROL_ADDRESS_2	0xC2
+#define NIC_FLOW_CONTROL_ADDRESS_3	0x00
+#define NIC_FLOW_CONTROL_ADDRESS_4	0x00
+#define NIC_FLOW_CONTROL_ADDRESS_5	0x01
+//
+// DPD Frame Start header bit definitions.
+//
+#define FSH_CRC_APPEND_DISABLE		BIT_13
+#define FSH_TX_INDICATE			BIT_15
+#define FSH_DOWN_COMPLETE		BIT_16
+#define FSH_LAST_KEEP_ALIVE_PACKET	BIT_24
+#define FSH_ADD_IP_CHECKSUM		BIT_25
+#define FSH_ADD_TCP_CHECKSUM		BIT_26
+#define FSH_ADD_UDP_CHECKSUM		BIT_27
+#define FSH_ROUND_UP_DEFEAT		BIT_28
+#define FSH_DPD_EMPTY			BIT_29
+#define FSH_DOWN_INDICATE		BIT_31
+#define MAXIMUM_SCATTER_GATHER_LIST     0x10
+//
+// Scatter Gather entry defintion.
+//
+typedef struct _SCATTER_GATHER_ENTRY {
+
+    ULONG Address;
+    ULONG Count;
+
+} SCATTER_GATHER_ENTRY, *PSCATTER_GATHER_ENTRY;
+
+
+typedef struct _DPD_LIST_ENTRY {
+	ULONG DownNextPointer;
+	ULONG FrameStartHeader;
+	SCATTER_GATHER_ENTRY SGList[MAXIMUM_SCATTER_GATHER_LIST];
+	struct _DPD_LIST_ENTRY *Next;
+	struct _DPD_LIST_ENTRY *Previous;
+	ULONG DPDPhysicalAddress;
+	PSKB SocketBuffer;
+	ULONG PacketLength;
+
+} DPD_LIST_ENTRY, *PDPD_LIST_ENTRY;
+
+
+typedef struct _UPD_LIST_ENTRY {
+	ULONG UpNextPointer;
+	ULONG UpPacketStatus;
+	SCATTER_GATHER_ENTRY SGList[1];
+	struct _UPD_LIST_ENTRY *Next;
+	struct _UPD_LIST_ENTRY *Previous;
+	ULONG UPDPhysicalAddress;
+	PUCHAR RxBufferVirtual;
+	PSKB SocketBuffer;
+} UPD_LIST_ENTRY, *PUPD_LIST_ENTRY;
+//
+// Connector Type
+//
+typedef enum _CONNECTOR_TYPE {
+
+	CONNECTOR_10BASET = 0,
+	CONNECTOR_10AUI = 1,
+	CONNECTOR_10BASE2 = 3,
+	CONNECTOR_100BASETX = 4,
+	CONNECTOR_100BASEFX = 5,
+	CONNECTOR_MII = 6,
+	CONNECTOR_AUTONEGOTIATION = 8,
+	CONNECTOR_EXTERNAL_MII = 9,
+	CONNECTOR_UNKNOWN = 0xFF
+
+} CONNECTOR_TYPE, *PCONNECTOR_TYPE;
+
+
+typedef struct _NIC_PCI_INFORMATION {
+	INT InterruptVector;
+	ULONG IoBaseAddress;
+
+} NIC_PCI_INFORMATION;
+
+
+typedef struct _NIC_HARDWARE_INFORMATION {
+
+	UCHAR CacheLineSize;
+	UCHAR RevisionId;
+	UCHAR Status;
+    #define HARDWARE_STATUS_WORKING		0x0
+	#define HARDWARE_STATUS_HUNG		0x1    
+	#define HARDWARE_STATUS_FAILURE		0x2
+
+	USHORT XcvrType;
+	USHORT DeviceId;
+	ULONG BitsInHashFilter;
+	ULONG LinkSpeed;
+	ULONG UpdateInterval;
+
+	CONNECTOR_TYPE Connector;			 
+	CONNECTOR_TYPE ConfigConnector;    
+
+	BOOLEAN HurricaneEarlyRevision;
+	UCHAR FeatureSet;
+	#define MOTHERBOARD_FEATURE_SET         0x0
+	#define LOW_COST_ADAPTER_FEATURE_SET    0x1
+	#define STANDARD_ADAPTER_FEATURE_SET    0x2
+	#define SERVER_ADAPTER_FEATURE_SET      0x4
+
+	BOOLEAN OptimizeForThroughput;
+	BOOLEAN OptimizeForCPU;
+	BOOLEAN OptimizeNormal;
+
+	BOOLEAN BroadcastErrDone;
+	BOOLEAN UDPChecksumErrDone;
+	BOOLEAN FullDuplexEnable;
+	BOOLEAN DuplexCommandOverride;
+
+	BOOLEAN MWIErrDone;
+	BOOLEAN FlowControlEnable;
+	BOOLEAN FlowControlSupported;
+	BOOLEAN LinkBeatDisable;
+
+	BOOLEAN SupportsPowerManagement;
+	BOOLEAN WOLConnectorPresent;
+	BOOLEAN AutoResetToD0;
+	BOOLEAN	DontSleep;
+	BOOLEAN D3Work;
+
+	BOOLEAN WakeOnMagicPacket;
+	BOOLEAN WakeOnLinkChange;
+
+	BOOLEAN SQEDisable;
+	BOOLEAN AutoSelect;
+	BOOLEAN LightTen;
+	BOOLEAN LinkLost;
+	//
+	// TryMII sets these parameters.
+	//
+	USHORT MIIReadCommand;
+	USHORT MIIWriteCommand;
+	USHORT MIIPhyOui;
+	USHORT MIIPhyModel;
+	USHORT MIIPhyUsed;
+	USHORT MediaOverride;
+
+	USHORT phys;	/* MII device addr. - for Becker's diag */
+
+} NIC_HARDWARE_INFORMATION , *PNIC_HARDWARE_INFORMATION;
+//
+// Command line media override values
+//
+#define MEDIA_NONE			0
+#define MEDIA_10BASE_TX			1
+#define MEDIA_10AUI			2
+#define MEDIA_10BASE_2			3
+#define MEDIA_100BASE_TX		4
+#define MEDIA_100BASE_FX		5
+#define MEDIA_10BASE_FL			6
+#define MEDIA_AUTO_SELECT		7
+
+
+#define MII_PHY_ADDRESS				0x0C00
+
+//
+//--------------------- MII register definitions --------------------
+//
+#define MII_PHY_CONTROL			0   // control reg address
+#define MII_PHY_STATUS              	1   // status reg address
+#define MII_PHY_OUI                 	2   // most of the OUI bits
+#define MII_PHY_MODEL               	3   // model/rev bits, and rest of OUI
+#define MII_PHY_ANAR                	4   // Auto negotiate advertisement reg
+#define MII_PHY_ANLPAR              	5   // auto negotiate Link Partner
+#define MII_PHY_ANER                	0x6
+#define MII_PAR                     	0x19
+#define MII_PCR                     	0x17 // PCS Config register
+
+#define MII_PHY_REGISTER_24		24   // Register 24 of the MII
+#define MII_PHY_REGISTER_24_PVCIRC	0x01 // Process Variation Circuit bit
+
+//
+//--------------------- Bit definitions: Physical Management --------------------
+//
+#define PHY_WRITE			0x0004  // Write to PHY (drive MDIO)
+#define PHY_DATA1			0x0002  // MDIO data bit
+#define PHY_CLOCK			0x0001  // MII clock signal
+
+//
+//--------------------- Bit definitions: MII Control --------------------
+//
+#define MII_CONTROL_RESET		0x8000  // reset bit in control reg
+#define MII_CONTROL_100MB		0x2000  // 100Mbit or 10 Mbit flag
+#define MII_CONTROL_ENABLE_AUTO		0x1000  // autonegotiate enable
+#define MII_CONTROL_ISOLATE		0x0400  // islolate bit
+#define MII_CONTROL_START_AUTO		0x0200  // restart autonegotiate
+#define MII_CONTROL_FULL_DUPLEX		0x0100
+
+
+//
+//--------------------- Bit definitions: MII Status --------------------
+//
+#define MII_STATUS_100MB_MASK	0xE000  // any of these indicate 100 Mbit
+#define MII_STATUS_10MB_MASK	0x1800  // either of these indicate 10 Mbit
+#define MII_STATUS_AUTO_DONE	0x0020  // auto negotiation complete
+#define MII_STATUS_AUTO		0x0008  // auto negotiation is available
+#define MII_STATUS_LINK_UP	0x0004  // link status bit
+#define MII_STATUS_EXTENDED	0x0001  // extended regs exist
+#define MII_STATUS_100T4	0x8000  // capable of 100BT4
+#define MII_STATUS_100TXFD	0x4000  // capable of 100BTX full duplex
+#define MII_STATUS_100TX	0x2000  // capable of 100BTX
+#define MII_STATUS_10TFD	0x1000  // capable of 10BT full duplex
+#define MII_STATUS_10T		0x0800  // capable of 10BT
+
+
+//
+//----------- Bit definitions: Auto-Negotiation Link Partner Ability ----------
+//
+#define MII_ANLPAR_100T4	0x0200  // support 100BT4
+#define MII_ANLPAR_100TXFD	0x0100  // support 100BTX full duplex
+#define MII_ANLPAR_100TX	0x0080  // support 100BTX half duplex
+#define MII_ANLPAR_10TFD	0x0040  // support 10BT full duplex
+#define MII_ANLPAR_10T		0x0020  // support 10BT half duplex
+
+//
+//----------- Bit definitions: Auto-Negotiation Advertisement ----------
+//
+#define MII_ANAR_100T4		0x0200  // support 100BT4
+#define MII_ANAR_100TXFD	0x0100  // support 100BTX full duplex
+#define MII_ANAR_100TX		0x0080  // support 100BTX half duplex
+#define MII_ANAR_10TFD		0x0040  // support 10BT full duplex
+#define MII_ANAR_10T		0x0020  // support 10BT half duplex
+#define MII_ANAR_FLOWCONTROL	0x0400  // support Flow Control
+
+#define MII_100TXFD		0x01
+#define MII_100T4		0x02
+#define MII_100TX		0x03
+#define MII_10TFD		0x04
+#define MII_10T			0x05
+
+//
+//----------- Bit definitions: Auto-Negotiation Expansion ----------
+//
+#define MII_ANER_LPANABLE	0x0001  // Link partner autonegotiatable ?
+#define MII_ANER_MLF		0x0010  // Multiple Link Fault bit
+
+//
+// MII Transceiver Type store in miiSelect
+//
+#define MIISELECT_GENERIC	0x0000
+#define MIISELECT_100BT4	0x0001
+#define MIISELECT_10BT		0x0002
+#define MIISELECT_100BTX	0x0003
+#define MIISELECT_10BT_ANE	0x0004
+#define MIISELECT_100BTX_ANE	0x0005
+#define MIITXTYPE_MASK		0x000F
+									 
+
+
+
+#define NIC_STATUS ULONG
+
+#define NIC_STATUS_SUCCESS		0x1
+#define NIC_STATUS_FAILURE		0x2
+
+//
+// Software limits defined here.
+//
+#define NIC_DEFAULT_SEND_COUNT		0x40
+#define NIC_DEFAULT_RECEIVE_COUNT	0x40
+#define NIC_MINIMUM_SEND_COUNT		0x2
+#define NIC_MAXIMUM_SEND_COUNT		0x80
+#define NIC_MINIMUM_RECEIVE_COUNT	0x2
+#define NIC_MAXIMUM_RECEIVE_COUNT	0x80
+
+#define LINK_SPEED_100			100000000L
+#define LINK_SPEED_10			10000000L
+
+#define ETH_ADDR_SIZE		6
+#define ETH_MULTICAST_BIT	1
+
+typedef struct _ETH_ADDR {
+	UCHAR	Addr[ETH_ADDR_SIZE];
+} ETH_ADDR, *PETH_ADDR;
+
+typedef struct _NIC_RESOURCES {
+
+	ULONG ReceiveCount;
+	ULONG SendCount;
+	ULONG SharedMemorySize;
+	PUCHAR SharedMemoryVirtual;
+	TIMER Timer;
+	TASKQ hostErr_task;
+    ULONG TimerInterval;
+	ULONG DownPollRate;
+
+} NIC_RESOURCES, *PNIC_RESOURCES;
+
+//
+// Statistics maintained by the driver.
+//
+
+
+typedef struct _NIC_STATISTICS {
+
+	//
+	// Transmit statistics.
+	//
+	ULONG TxFramesOk;
+	ULONG TxBytesOk;
+	ULONG TxFramesDeferred;
+	ULONG TxSingleCollisions;
+	ULONG TxMultipleCollisions;
+	ULONG TxLateCollisions;
+	ULONG TxCarrierLost;
+
+	ULONG TxMaximumCollisions;
+	ULONG TxSQEErrors;
+	ULONG TxHWErrors;
+	ULONG TxJabberError; 
+	ULONG TxUnknownError;
+
+	ULONG TxLastPackets;
+	ULONG TxLastCollisions;
+	ULONG TxLastDeferred;
+
+	//
+	// Receive statistics.
+	//
+	ULONG RxFramesOk;
+	ULONG RxBytesOk;
+
+	ULONG RxOverruns;
+	ULONG RxBadSSD;
+	ULONG RxAlignmentError;
+	ULONG RxBadCRCError;
+	ULONG RxOversizeError;
+
+	ULONG RxNoBuffer;
+
+	ULONG RxLastPackets;
+	ULONG UpdateInterval;
+
+	//
+	// Multicasts statistics
+	//
+	ULONG Rx_MulticastPkts;
+
+} NIC_STATISTICS, *PNIC_STATISTICS;
+//
+// Memory allocation
+//
+#define NIC_IO_PORT_REGISTERED			0x00000001
+#define NIC_INTERRUPT_REGISTERED		0x00000002
+#define NIC_SHARED_MEMORY_ALLOCATED		0x00000004
+#define NIC_TIMER_REGISTERED			0x00000010
+
+#define MAXIMUM_TEST_BUFFERS			1
+//
+// This queue maintains the pending packets.
+// 
+typedef struct _PACKET_PENDING_QUEUE {
+
+    PSKB Head;
+    PSKB Tail;
+
+} PACKET_PENDING_QUEUE;
+
+typedef struct _NIC_INFORMATION {
+
+	ULONG IoBaseAddress;
+	UCHAR DeviceName[8];
+	UCHAR PermanentAddress[6];
+    UCHAR StationAddress[6];
+	ULONG ResourcesReserved;
+	NIC_PCI_INFORMATION PCI;
+
+	PUPD_LIST_ENTRY HeadUPDVirtual;
+    	PDPD_LIST_ENTRY HeadDPDVirtual;
+	PDPD_LIST_ENTRY TailDPDVirtual;
+
+    	ULONG TestDPDVirtual[MAXIMUM_TEST_BUFFERS];
+	ULONG TestDPDPhysical[MAXIMUM_TEST_BUFFERS];
+	ULONG TestBufferVirtual[MAXIMUM_TEST_BUFFERS];
+	ULONG TestBufferPhysical[MAXIMUM_TEST_BUFFERS];
+
+	NIC_RESOURCES Resources;
+	NIC_STATISTICS Statistics;
+	ENET_STATISTICS EnetStatistics;
+	NIC_HARDWARE_INFORMATION Hardware;
+	ULONG BytesInDPDQueue;
+	PDEVICE NextDevice;
+	PDEVICE Device;
+	BOOLEAN InTimer;
+    BOOLEAN DelayStart;
+	INT Index;
+	PACKET_PENDING_QUEUE PendingQueue;
+   	ULONG TxPendingQueueCount;
+#if LINUX_VERSION_CODE >= 0x20200
+	spinlock_t SpinLock;
+#endif
+	BOOLEAN DPDRingFull;
+	BOOLEAN DeviceGivenByOS;
+	ULONG keepForGlobalReset;
+
+} NIC_INFORMATION, *PNIC_INFORMATION;
+
+
+
+
+
+
+
+#ifndef LOBYTE
+#define LOBYTE(_w) ((UCHAR)((_w) & 0xFF))
+#endif
+
+#ifndef HIBYTE
+#define HIBYTE(_w) (((USHORT)(_w)) >> 8)
+#endif
+
+
+#ifndef LOWORD
+#define LOWORD(_d) ((USHORT)((_d) & 0xFFFF))
+#endif
+
+#ifndef HIWORD
+#define HIWORD(_d) (((ULONG)(_d)) >> 16)
+#endif
+
+
+#define NIC_READ_PORT_UCHAR(pAdapter, Register) \
+	inb(pAdapter->IoBaseAddress + Register)
+
+#define NIC_READ_PORT_USHORT(pAdapter, Register) \
+	inw(pAdapter->IoBaseAddress + Register)
+ 
+#define NIC_READ_PORT_ULONG(pAdapter, Register) \
+	inl(pAdapter->IoBaseAddress + Register)
+
+#define NIC_WRITE_PORT_UCHAR(pAdapter, Register, Value) \
+	outb(Value, pAdapter->IoBaseAddress + Register)
+
+#define NIC_WRITE_PORT_USHORT(pAdapter, Register, Value) \
+	outw(Value, pAdapter->IoBaseAddress + Register)
+ 
+#define NIC_WRITE_PORT_ULONG(pAdapter, Register, Value) \
+	outl(Value, pAdapter->IoBaseAddress + Register)
+
+#define NIC_COMMAND(pAdapter, Command) \
+	NIC_WRITE_PORT_USHORT(pAdapter, INTSTATUS_COMMAND_REGISTER, Command)
+
+#define NIC_MASK_ALL_INTERRUPT(pAdapter) { \
+	NIC_COMMAND( \
+        	pAdapter, \
+		COMMAND_SET_INTERRUPT_ENABLE | DISABLE_ALL_INTERRUPT \
+		); \
+	NIC_READ_PORT_USHORT(pAdapter, INTSTATUS_COMMAND_REGISTER); \
+}
+
+#define NIC_UNMASK_ALL_INTERRUPT(pAdapter){ \
+	NIC_COMMAND( \
+		pAdapter, \
+		COMMAND_SET_INTERRUPT_ENABLE | ENABLE_ALL_INTERRUPT \
+	); \
+	NIC_READ_PORT_USHORT(pAdapter, INTSTATUS_COMMAND_REGISTER); \
+}
+
+                
+#define NIC_ACKNOWLEDGE_ALL_INTERRUPT(pAdapter) \
+	NIC_COMMAND( \
+		pAdapter, \
+		COMMAND_ACKNOWLEDGE_INTERRUPT | ACKNOWLEDGE_ALL_INTERRUPT \
+		)
+
+#define NIC_ENABLE_ALL_INTERRUPT_INDICATION(pAdapter) \
+	NIC_COMMAND( \
+		pAdapter, \
+		COMMAND_SET_INDICATION_ENABLE | ENABLE_ALL_INTERRUPT \
+		)
+
+#define NIC_DISABLE_ALL_INTERRUPT_INDICATION(pAdapter) \
+	NIC_COMMAND( \
+		pAdapter, \
+		COMMAND_SET_INDICATION_ENABLE | DISABLE_ALL_INTERRUPT \
+		)
+
+#define COMPARE_MACS(pAddr1, pAddr2) \
+	( *((PULONG)((PUCHAR)(pAddr1)+2)) == *((PULONG)((PUCHAR)(pAddr2)+2)) && \
+	  *((PULONG)(pAddr1)) == *((PULONG)(pAddr2))) 
+
+#define NIC_DELAY(A)		udelay(A)
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+
+
+#ifdef DEBUG
+extern ULONG debug;
+#endif
+
+#define DEBUG_INITIALIZE	0x00000001
+#define DEBUG_FUNCTION		0x00000002
+#define DEBUG_IOCTL		0x00000004
+#define DEBUG_GET_STATISTICS	0x00000008
+#define DEBUG_SEND		0x00000010
+#define DEBUG_RECEIVE		0x00000020
+#define DEBUG_INTERRUPT		0x00000040
+#define DEBUG_ERROR		0x80000000
+
+#ifdef DEBUG
+
+#define DBGPRINT_INITIALIZE(A) if (debug & DEBUG_INITIALIZE) printk A
+#define DBGPRINT_FUNCTION(A) if (debug & DEBUG_FUNCTION) printk A
+#define DBGPRINT_SEND(A) if (debug & DEBUG_SEND) printk A
+#define DBGPRINT_RECEIVE(A) if (debug & DEBUG_RECEIVE) printk A
+#define DBGPRINT_INTERRUPT(A) if (debug & DEBUG_INTERRUPT) printk A
+#define DBGPRINT_GET_STATISTICS(A) \
+	if (debug & DEBUG_GET_STATISTICS) printk A
+#define DBGPRINT_IOCTL(A) if (debug & DEBUG_IOCTL) printk A
+#define DBGPRINT_ERROR(A) printk A
+#define DBGPRINT_INIT(A) printk A
+
+#else
+
+#define DBGPRINT_INITIALIZE(A)
+#define DBGPRINT_FUNCTION(A)
+#define DBGPRINT_SEND(A)
+#define DBGPRINT_RECEIVE(A)
+#define DBGPRINT_INTERRUPT(A)
+#define DBGPRINT_GET_STATISTICS(A)
+#define DBGPRINT_QUERY(A)
+#define DBGPRINT_SET(A)
+#define DBGPRINT_IOCTL(A)
+#define DBGPRINT_ERROR(A)
+#define DBGPRINT_INIT(A)
+
+#endif
+
+#define LOG_LABEL(A, B)
+#define ASSERT(A)
+
+
+extern PCHAR ProductName;
+extern ULONG tc90x_SendCount[];
+extern ULONG tc90x_ReceiveCount[];
+extern ULONG tc90x_Index;
+extern UCHAR BroadcastAddr[];
+
+#ifdef DEBUG
+extern ULONG debug;
+#endif
+
+extern INT switchdelay[];
+extern USHORT media_select[];
+extern INT full_duplex[];
+extern INT downpoll[];
+extern INT flowcontrol[];
+//
+//-------------------------- NIC.C Definitions --------------------------
+//
+
+NIC_STATUS
+tc90xbc_ScanDevices(
+	IN PDEVICE Device
+	);
+
+NIC_STATUS 
+tc90x_FillDeviceStructure(
+	IN PNIC_INFORMATION Adapter
+	);
+
+INT
+NICOpen(
+	IN PDEVICE Device
+	);
+
+INT
+NICClose(
+	IN PDEVICE Device
+	);
+
+//
+//-------------------------- INIT.C Definitions --------------------------
+//
+
+VOID
+tc90x_FreeAdapterResources(
+	IN PNIC_INFORMATION Adapter
+	);
+
+NIC_STATUS
+tc90x_RegisterAdapter(
+	IN PNIC_INFORMATION Adapter
+	);
+
+NIC_STATUS
+tc90x_GetAdapterProperties(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+NIC_STATUS
+tc90x_BasicInitializeAdapter(
+	IN PNIC_INFORMATION Adapter
+	);
+
+NIC_STATUS
+tc90x_AllocateSharedMemory(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+NIC_STATUS 
+tc90x_TestAdapter(
+	IN PNIC_INFORMATION Adapter
+	);
+
+NIC_STATUS
+tc90x_StartAdapter(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+VOID
+ReStartAdapter(
+	//IN PNIC_INFORMATION Adapter
+	PVOID Adapter
+    	);
+
+//-------------------------- SEND.C Definitions --------------------------
+//
+
+INT
+NICSendPacket(
+	IN PSKB SocketBuffer,
+	IN PDEVICE Device
+	);
+
+VOID
+tc90x_TxCompleteEvent(
+	IN PNIC_INFORMATION Adapter
+	);
+
+NIC_STATUS
+tc90x_ResetAndEnableTransmitter(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+
+VOID
+tc90x_CleanupSendLogic(
+	IN PDEVICE Device
+    	);
+
+
+
+//
+//-------------------------- REQUEST.C Definitions --------------------------
+//
+
+
+INT
+NICIoctl(
+	IN PDEVICE Device,
+	IN PIFREQ Request,
+	IN INT command
+	);
+
+VOID
+NICSetReceiveMode(
+	IN PDEVICE Device
+	);
+
+PENET_STATISTICS
+NICGetStatistics(
+	IN PDEVICE Device
+	);
+VOID
+NICSetMulticastList(
+	IN PDEVICE Device,
+	IN INT NumberOfAddresses,
+	PVOID AddressList
+	);
+
+
+USHORT
+tc90x_HashAddress(
+	IN PUCHAR Address
+    	);
+
+
+NIC_STATUS
+tc90x_SetMulticastAddresses(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+
+VOID
+tc90x_InitializeHashFilter(
+	IN PNIC_INFORMATION Adapter
+	);
+
+
+//
+//-------------------------- WORK.C Definitions -------------------
+//
+
+VOID
+tc90x_FlowControl(
+	IN PNIC_INFORMATION Adapter
+	);
+
+
+VOID
+tc90x_HurricaneEarlyRevision(
+	IN PNIC_INFORMATION Adapter
+	);
+
+
+NIC_STATUS 
+tc90x_SoftwareWork(
+	IN PNIC_INFORMATION Adapter
+	);
+
+
+NIC_STATUS
+RxResetAndWork(
+	IN PNIC_INFORMATION Adapter
+	);
+//
+//-------------------------- AUTOSELECT.C Definitions -------------------
+//
+
+VOID 
+tc90x_MainAutoSelectionRoutine(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT Options
+	);
+
+BOOLEAN 
+tc90x_CheckDCConverter (
+	IN PNIC_INFORMATION Adapter,
+	IN BOOLEAN EnabledState
+	);
+
+
+VOID
+tc90x_SetupConnector(    
+	IN PNIC_INFORMATION Adapter,
+ 	IN CONNECTOR_TYPE NewConnector,
+  	OUT PCONNECTOR_TYPE OldConnector 
+  	) ;
+
+
+BOOLEAN
+tc90x_TryMII(    
+	IN PNIC_INFORMATION Adapter,
+  	IN CONNECTOR_TYPE NewConnector 
+  	);
+
+BOOLEAN
+tc90x_TryLinkBeat(   
+	IN PNIC_INFORMATION Adapter,
+	IN CONNECTOR_TYPE NewConnector
+	);
+
+
+BOOLEAN
+DownloadSelfDirected(  
+	IN PNIC_INFORMATION Adapter
+	) ;
+
+BOOLEAN
+CheckTransmitInProgress(
+	IN PNIC_INFORMATION Adapter
+	);
+
+
+BOOLEAN
+TestPacket(    
+	IN PNIC_INFORMATION Adapter
+	);
+
+BOOLEAN
+GetLinkSpeed(  
+	IN PNIC_INFORMATION Adapter,
+	OUT PBOOLEAN handles100Mbitptr 
+	) ;
+
+//
+// --------------------- EEPROM.C definitions -------------------
+//
+
+NIC_STATUS
+tc90x_CheckIfEEPROMBusy(
+	IN PNIC_INFORMATION Adapter
+	);
+
+NIC_STATUS
+tc90x_ReadEEPROM(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT EEPROMAddress,
+	OUT PUSHORT Contents
+	);
+
+NIC_STATUS
+tc90x_WriteEEPROM(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT EEPROMAddress,
+	IN USHORT Data
+	);
+
+USHORT
+tc90x_CalculateEEPROMChecksum1(  
+	IN PNIC_INFORMATION Adapter
+    	) ;
+
+
+//
+// --------------------- ISR.C definitions -------------------
+//
+
+VOID
+NICInterrupt IRQ(
+	INT Irq,
+	PVOID DeviceId,
+	PTREGS Registers
+	);
+
+VOID
+tc90x_HostErrorEvent(
+	IN PNIC_INFORMATION Adapter
+	);
+
+VOID
+tc90x_CountDownTimerEvent(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+
+VOID
+tc90x_UpdateStatisticsEvent(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+
+
+
+//
+// --------------------- RECEIVE.C definitions -------------------
+//
+
+VOID
+tc90x_UpCompleteEvent(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+NIC_STATUS
+tc90x_ResetAndEnableReceiver(
+	IN PNIC_INFORMATION Adapter
+    	);
+
+
+//
+// --------------------- TIMER.C definitions -------------------
+//
+
+VOID
+NICTimer(
+	IN ULONG Data
+	);
+
+
+//
+// --------------------- CMDLINE.C definitions -------------------
+//
+
+NIC_STATUS
+tc90x_ReadCommandLineChanges(
+	IN PNIC_INFORMATION Adapter
+	);
+
+//
+// --------------------- XCVR.C definitions -------------------
+//
+
+NIC_STATUS
+tc90x_SetupMedia( 
+	IN PDEVICE Device
+	);
+
+VOID
+ProcessMediaOverrides(
+	IN PNIC_INFORMATION Adapter, 
+	IN USHORT OptionAvailable
+	);
+
+
+VOID
+tc90x_TickMediaHandler(
+	IN PNIC_INFORMATION Adapter
+	);
+
+VOID
+CheckTPLinkState(
+	IN PNIC_INFORMATION Adapter
+	);
+
+VOID
+CheckFXLinkState(
+	IN PNIC_INFORMATION Adapter
+	);
+
+NIC_STATUS
+tc90x_SetupNewDuplex(
+	IN PNIC_INFORMATION Adapter
+	);
+
+VOID
+tc90x_SetupNewSpeed(
+	IN PNIC_INFORMATION Adapter
+	);
+
+
+VOID
+IndicateToOSLinkStateChange(
+	IN PNIC_INFORMATION Adapter
+	);
+
+/**************************** MIIPHY.C *********************************/
+
+BOOLEAN
+FindMIIPhy( 
+	IN PNIC_INFORMATION Adapter
+	) ;
+
+VOID
+SendMIIPhyPreamble(    
+	IN PNIC_INFORMATION Adapter
+	) ;
+
+VOID
+WriteMIIPhy(   
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT RegAddr,
+	IN USHORT Output 
+	);
+
+BOOLEAN
+ReadMIIPhy(    
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT RegisterAddress,
+	OUT PUSHORT pInput 
+	) ;
+
+
+BOOLEAN
+MIIMediaOverride(
+	IN PNIC_INFORMATION Adapter,
+	IN USHORT PhyModes,
+	OUT PUSHORT MiiType
+	);
+
+BOOLEAN
+ProgramMII(   
+	IN PNIC_INFORMATION Adapter,
+  	IN CONNECTOR_TYPE NewConnector 
+  	) ;
+
+
+
+
+/*++
+
+Routine:
+
+    NIC_COMMAND_WAIT.
+
+Description:
+
+    This routine issues a command and spins for the completion.
+
+Arguments:
+
+    MiniportAdapterContext - Pointer to the adapter structure.
+    Command - Command to be issued.
+
+Return Value:
+
+    NIC_STATUS_SUCCESS if hardware executes the command. 
+    NIC_STATUS_FAILURE if hardware does not respond. 
+
+--*/
+
+__inline
+static
+NIC_STATUS
+NIC_COMMAND_WAIT(
+	IN PNIC_INFORMATION Adapter,
+    	IN USHORT Command
+    )
+{
+	PNIC_INFORMATION pAdapter = Adapter;
+	ULONG count;
+	USHORT value;
+
+	NIC_WRITE_PORT_USHORT(
+		pAdapter,
+		INTSTATUS_COMMAND_REGISTER,
+		Command);
+
+	count = jiffies + HZ;
+	do {
+		value = NIC_READ_PORT_USHORT(
+				pAdapter, 
+				INTSTATUS_COMMAND_REGISTER);
+		NIC_DELAY(10);
+	} while ( (value & INTSTATUS_COMMAND_IN_PROGRESS) &&
+		      (count > jiffies) );
+
+	if (count < jiffies) {
+		DBGPRINT_ERROR(("NIC_COMMAND_WAIT: timeout\n"));
+		return NIC_STATUS_FAILURE;
+    }
+	return NIC_STATUS_SUCCESS;
+}
+
+/*++
+
+Routine Name:
+
+    tc90x_SetCountDownTimer.
+
+Routine Description:
+
+    This routine sets the countdown timer on the hardware.
+
+Arguments:
+
+    MiniportAdapterContext - Pointer to the adapter structure.
+
+Return Value:
+
+    None.
+
+--*/
+
+__inline
+static
+VOID
+tc90x_SetCountDownTimer(
+	IN PNIC_INFORMATION Adapter
+    	)
+{
+    PNIC_INFORMATION pAdapter = Adapter;
+    ULONG countDownValue;
+
+    countDownValue = pAdapter->BytesInDPDQueue /4; 
+
+    if (countDownValue < 10)
+	countDownValue = 10;
+
+    NIC_WRITE_PORT_USHORT(
+	    pAdapter,
+	    COUNTDOWN_REGISTER,
+	    (USHORT)countDownValue
+	    );
+
+}
+
+
+/*++
+
+Routine Name:
+
+	GetPacketFromPendingQueueAtHead
+
+Routine Description:
+
+	This routine gets a packet from the pending queue.
+
+Arguments:
+
+	pAdapter - Pointer to the adapter structure.
+
+Return Value:
+
+	
+	SocketBuffer - if there is a socket buffer in the queue.
+	NULL - if there is no socket buffer in the queue.
+
+--*/
+
+__inline
+static
+PSKB
+GetPacketFromPendingQueueAtHead(
+	IN PNIC_INFORMATION Adapter
+	)
+{
+	PSKB socketBuffer;
+
+	//
+	// Get the socket buffer from the queue head.
+	//
+	socketBuffer = Adapter->PendingQueue.Head;
+
+	if (socketBuffer) {
+
+		//
+		// Move the head.
+		//
+		Adapter->PendingQueue.Head = socketBuffer->next;
+		Adapter->TxPendingQueueCount--;
+
+    	}
+
+	//
+	// return the socket buffer pointer.
+	//
+	socketBuffer->next = NULL;
+
+	return socketBuffer;
+
+}
+
+/*++
+
+Routine Name:
+
+	PutPacketInPendingQueueAtHead
+
+Routine Description:
+
+    	This routine puts the packet in the pending queue.
+
+Arguments:
+
+    	Adapter - Pointer to the adapter structure.
+	SocketBuffer - Socket buffer
+
+Return Value:
+
+    None.
+
+--*/
+
+__inline
+static
+VOID
+PutPacketInPendingQueueAtHead(
+	IN PNIC_INFORMATION Adapter,
+	IN PSKB SocketBuffer
+    	)
+{
+
+	//
+	// This packet points to head.
+	//      
+	SocketBuffer->next = Adapter->PendingQueue.Head;
+
+    	if (NULL == Adapter->PendingQueue.Head) {
+
+		//
+		// Nothing in queue, tail points to this packet.
+		//
+
+		Adapter->PendingQueue.Tail = SocketBuffer;
+
+    	}
+
+    	//
+    	// Point head to this packet.
+    	//
+
+    	Adapter->PendingQueue.Head = SocketBuffer;
+    	Adapter->TxPendingQueueCount++;
+
+}
+
+
+
+/*++
+
+Routine Name:
+
+    PutPacketPendingQueueAtTail.
+
+Routine Description:
+
+    This routine puts the packet in the pending queue.
+
+Arguments:
+
+    Adapter - Pointer to the adapter structure.
+    Packet - Packet pointer.
+
+Return Value:
+
+    None.
+
+--*/
+
+__inline
+static
+VOID
+PutPacketInPendingQueueAtTail(
+	IN PNIC_INFORMATION Adapter,
+	IN PSKB SocketBuffer
+    	)
+{
+
+	SocketBuffer->next = NULL;
+
+    	if (NULL == Adapter->PendingQueue.Head) {
+
+		//
+		// Head is NULL, point head to this one.
+		//
+
+		Adapter->PendingQueue.Head = SocketBuffer ;
+
+    	}
+    	else {
+
+		//
+		// Head is valid, add this packet to the tail.
+		//
+		Adapter->PendingQueue.Tail->next = SocketBuffer;
+
+    }
+
+    //
+    // Point tail to this one.
+    //
+
+    Adapter->PendingQueue.Tail = SocketBuffer;
+    Adapter->TxPendingQueueCount++;
+
+}
+
+
+/*++
+
+Routine Name:
+
+	SetRxTcpIpChecksumFlagsInPacket.
+
+Routine Description:
+
+    	This routine sets the checksum information.
+
+Arguments:
+
+	Adapter - Pointer to the adapter structure.
+	SocketBuffer - Pointer to the socket buffer.
+	UpPacketStatus - UpPacketStatus given by hardware.
+
+Return Value:
+
+    None.
+
+--*/
+
+__inline
+static
+VOID
+SetRxTcpIpChecksumOffloadFlagsInSocketBuffer(
+	IN PNIC_INFORMATION Adapter,
+	IN PSKB SocketBuffer,
+	IN ULONG UpPacketStatus
+    	)
+
+{
+    	PNIC_INFORMATION pAdapter = Adapter;
+	//
+	// Check if this is IP packet.
+	//
+	if (UpPacketStatus & UP_PACKET_STATUS_IP_CHECKSUM_CHECKED) {
+
+		if (UpPacketStatus & UP_PACKET_STATUS_IP_CHECKSUM_ERROR) {
+			DBGPRINT_ERROR((
+				KERN_CRIT "IP checksum error\n"));
+			SocketBuffer->ip_summed = CHECKSUM_NONE;
+			return;
+		}
+		//
+		// Check if packet is TCP packet. 
+		//
+		if (UpPacketStatus & UP_PACKET_STATUS_TCP_CHECKSUM_CHECKED) {
+			//
+			// Check if TCP checksum has been offloaded to us.
+			//
+			if (UpPacketStatus & 
+			    UP_PACKET_STATUS_TCP_CHECKSUM_ERROR) {
+				DBGPRINT_ERROR((
+					KERN_CRIT "TCP Checksum error\n"));
+				SocketBuffer->ip_summed = CHECKSUM_NONE;
+				return;
+			}
+		}
+	    	//
+	    	// Check if this is UDP packet.
+		//
+	    	if (UpPacketStatus & UP_PACKET_STATUS_UDP_CHECKSUM_CHECKED) {
+			if (TRUE == pAdapter->Hardware.UDPChecksumErrDone) {
+		    		if (UpPacketStatus & 
+				    UP_PACKET_STATUS_UDP_CHECKSUM_ERROR) {
+					DBGPRINT_ERROR((
+						KERN_CRIT "UDP Error"));
+					SocketBuffer->ip_summed = CHECKSUM_NONE;
+					return;
+				}
+				else {
+					SocketBuffer->ip_summed = CHECKSUM_NONE;
+					return;
+				}
+	    		}
+		}
+	}	
+	SocketBuffer->ip_summed = CHECKSUM_UNNECESSARY;	
+	return;
+}	    
+
Index: oldkernel/linux/drivers/net/Config.in
diff -u linux/drivers/net/Config.in:1.2 linux/drivers/net/Config.in:1.3
--- linux/drivers/net/Config.in:1.2	Wed May 31 14:46:15 2000
+++ linux/drivers/net/Config.in	Thu Jun  1 14:57:34 2000
@@ -71,6 +71,7 @@
     fi
     tristate '3c509/3c579 support' CONFIG_EL3
     tristate '3c515 ISA Fast EtherLink' CONFIG_3C515
+    tristate '3c90x/3c980 B/C series "Cyclone/Hurricane/Tornado" support' CONFIG_BC90X
     tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
   fi
   tristate 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
Index: oldkernel/linux/drivers/net/Makefile
diff -u linux/drivers/net/Makefile:1.2 linux/drivers/net/Makefile:1.3
--- linux/drivers/net/Makefile:1.2	Wed May 31 14:46:15 2000
+++ linux/drivers/net/Makefile	Thu Jun  1 14:57:34 2000
@@ -530,6 +530,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_BC90X),y)
+L_OBJS += 3c90x.o
+else
+  ifeq ($(CONFIG_BC90X),m)
+  M_OBJS += 3c90x.o
+  endif
+endif
+
 ifeq ($(CONFIG_VORTEX),y)
 L_OBJS += 3c59x.o
 else
Index: oldkernel/linux/drivers/net/Space.c
diff -u linux/drivers/net/Space.c:1.2 linux/drivers/net/Space.c:1.3
--- linux/drivers/net/Space.c:1.2	Wed May 31 14:46:15 2000
+++ linux/drivers/net/Space.c	Thu Jun  1 14:57:34 2000
@@ -83,6 +83,7 @@
 extern int sonic_probe(struct device *);
 extern int SK_init(struct device *);
 extern int seeq8005_probe(struct device *);
+extern int tc90xbc_probe(struct device *);
 extern int tc59x_probe(struct device *);
 extern int dgrs_probe(struct device *);
 extern int smc_init( struct device * );
@@ -189,6 +190,9 @@
 #endif
 #ifdef CONFIG_RCPCI
 	{rcpci_probe, 0},
+#endif
+#ifdef CONFIG_BC90X
+	{tc90xbc_probe, 0},
 #endif
 #ifdef CONFIG_VORTEX
 	{tc59x_probe, 0},
