diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/Config.in orig/drivers/net/Config.in
--- linux-2.4.21_pre3-gss-r2/drivers/net/Config.in	2003-01-21 16:07:01.000000000 -0500
+++ orig/drivers/net/Config.in	2003-01-21 15:57:17.000000000 -0500
@@ -165,6 +165,7 @@
       fi
 
       dep_tristate '    Apricot Xen-II on board Ethernet' CONFIG_APRICOT $CONFIG_ISA
+      dep_tristate '    Broadcom BCM4400 support' CONFIG_NET_BCM4400 $CONFIG_PCI
       dep_tristate '    CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA
       dep_tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI
       if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
@@ -251,6 +252,7 @@
 dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL
 dep_tristate 'Realtek 8169 Gigabit Ethernet support' CONFIG_R8169 $CONFIG_PCI
 dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI
+dep_tristate '  Broadcom BCM5700 support' CONFIG_NET_BROADCOM $CONFIG_PCI
 dep_tristate 'Broadcom Tigon3 support' CONFIG_TIGON3 $CONFIG_PCI
 
 endmenu
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/Makefile orig/drivers/net/Makefile
--- linux-2.4.21_pre3-gss-r2/drivers/net/Makefile	2003-01-21 16:07:01.000000000 -0500
+++ orig/drivers/net/Makefile	2003-01-21 15:55:10.000000000 -0500
@@ -33,6 +33,13 @@
   obj-$(CONFIG_ISDN) += slhc.o
 endif
 
+ifeq ($(CONFIG_NET_BCM4400),y)
+  obj-y += bcm4400/bcm4400.o
+endif
+ifeq ($(CONFIG_NET_BROADCOM),y)
+  obj-y += bcm/bcm5700.o
+endif
+
 subdir-$(CONFIG_NET_PCMCIA) += pcmcia
 subdir-$(CONFIG_NET_WIRELESS) += wireless
 subdir-$(CONFIG_TULIP) += tulip
@@ -44,6 +51,8 @@
 subdir-$(CONFIG_DEV_APPLETALK) += appletalk
 subdir-$(CONFIG_SK98LIN) += sk98lin
 subdir-$(CONFIG_SKFP) += skfp
+subdir-$(CONFIG_NET_BROADCOM) += bcm
+subdir-$(CONFIG_NET_BCM4400) += bcm4400
 subdir-$(CONFIG_E100) += e100
 subdir-$(CONFIG_E1000) += e1000
 
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/.depend orig/drivers/net/bcm/.depend
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/.depend	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/.depend	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,70 @@
+5701rls.o: 5701rls.c \
+   mm.h \
+   5701rls.h
+autoneg.o: autoneg.c \
+   mm.h
+b57proc.o: b57proc.c \
+   mm.h
+b57um.o: b57um.c \
+   mm.h \
+   nicext.h
+lm.h: \
+   queue.h \
+   bits.h
+	@touch lm.h
+mm.h: \
+   $(wildcard /usr/src/wolk2/include/config/smp.h) \
+   $(wildcard /usr/src/wolk2/include/config/modversions.h) \
+   /usr/src/wolk2/include/linux/version.h \
+   /usr/src/wolk2/include/linux/module.h \
+   /usr/src/wolk2/include/linux/kernel.h \
+   /usr/src/wolk2/include/linux/sched.h \
+   /usr/src/wolk2/include/linux/string.h \
+   /usr/src/wolk2/include/linux/timer.h \
+   /usr/src/wolk2/include/linux/errno.h \
+   /usr/src/wolk2/include/linux/ioport.h \
+   /usr/src/wolk2/include/linux/slab.h \
+   /usr/src/wolk2/include/linux/interrupt.h \
+   /usr/src/wolk2/include/linux/pci.h \
+   /usr/src/wolk2/include/linux/init.h \
+   /usr/src/wolk2/include/linux/netdevice.h \
+   /usr/src/wolk2/include/linux/etherdevice.h \
+   /usr/src/wolk2/include/linux/skbuff.h \
+   /usr/src/wolk2/include/asm/processor.h \
+   /usr/src/wolk2/include/asm/bitops.h \
+   /usr/src/wolk2/include/asm/io.h \
+   /usr/src/wolk2/include/asm/unaligned.h \
+   /usr/src/wolk2/include/linux/delay.h \
+   /usr/src/wolk2/include/asm/byteorder.h \
+   /usr/src/wolk2/include/linux/time.h \
+   /usr/src/wolk2/include/linux/ethtool.h \
+   /usr/src/wolk2/include/asm/uaccess.h \
+   $(wildcard /usr/src/wolk2/include/config/proc/fs.h) \
+   /usr/src/wolk2/include/linux/smp_lock.h \
+   /usr/src/wolk2/include/linux/proc_fs.h \
+   /usr/src/wolk2/include/linux/if_vlan.h \
+   /usr/src/wolk2/include/net/ip.h \
+   /usr/src/wolk2/include/net/tcp.h \
+   /usr/src/wolk2/include/net/checksum.h \
+   lm.h \
+   queue.h \
+   tigon3.h \
+   $(wildcard /usr/src/wolk2/include/config/highmem.h) \
+   $(wildcard /usr/src/wolk2/include/config/x86.h) \
+   $(wildcard /usr/src/wolk2/include/config/x86/64.h) \
+   $(wildcard /usr/src/wolk2/include/config/highmem64g.h)
+	@touch mm.h
+tcp_seg.o: tcp_seg.c \
+   mm.h \
+   fw_stkoffld.h \
+   fw_lso05.h
+tigon3.o: tigon3.c \
+   mm.h
+tigon3.h: \
+   lm.h \
+   autoneg.h
+	@touch tigon3.h
+.PRECIOUS:	lm.h \
+	mm.h \
+	tigon3.h \
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/5701rls.c orig/drivers/net/bcm/5701rls.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/5701rls.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/5701rls.c	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,46 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#if INCLUDE_5701_AX_FIX
+
+#include "mm.h"
+#include "5701rls.h"
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice)
+{
+  T3_FWIMG_INFO FwImgInfo;
+
+  FwImgInfo.StartAddress = t3FwStartAddr;
+  FwImgInfo.Text.Buffer = (PLM_UINT8)t3FwText;
+  FwImgInfo.Text.Offset  = t3FwTextAddr;
+  FwImgInfo.Text.Length  = t3FwTextLen;
+  FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3FwRodata;
+  FwImgInfo.ROnlyData.Offset  = t3FwRodataAddr;
+  FwImgInfo.ROnlyData.Length  = t3FwRodataLen;
+  FwImgInfo.Data.Buffer = (PLM_UINT8)t3FwData;
+  FwImgInfo.Data.Offset  = t3FwDataAddr;
+  FwImgInfo.Data.Length  = t3FwDataLen;
+
+  if (LM_LoadFirmware(pDevice,
+                      &FwImgInfo,
+                      T3_RX_CPU_ID | T3_TX_CPU_ID,
+                      T3_RX_CPU_ID) != LM_STATUS_SUCCESS)
+    {
+      return LM_STATUS_FAILURE;
+    }
+  
+  return LM_STATUS_SUCCESS;
+}
+
+#endif /* INCLUDE_5701_AX_FIX */
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/5701rls.h orig/drivers/net/bcm/5701rls.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/5701rls.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/5701rls.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,198 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+typedef unsigned long U32;
+int t3FwReleaseMajor = 0x0;
+int t3FwReleaseMinor = 0x0;
+int t3FwReleaseFix = 0x0;
+U32 t3FwStartAddr = 0x08000000;
+U32 t3FwTextAddr = 0x08000000;
+int t3FwTextLen = 0x9c0;
+U32 t3FwRodataAddr = 0x080009c0;
+int t3FwRodataLen = 0x60;
+U32 t3FwDataAddr = 0x08000a40;
+int t3FwDataLen = 0x20;
+U32 t3FwSbssAddr = 0x08000a60;
+int t3FwSbssLen = 0xc;
+U32 t3FwBssAddr = 0x08000a70;
+int t3FwBssLen = 0x10;
+U32 t3FwText[(0x9c0/4) + 1] = {
+0x0, 
+0x10000003, 0x0, 0xd, 0xd, 
+0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, 
+0x26100000, 0xe000018, 0x0, 0xd, 
+0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, 
+0x26100034, 0xe00021c, 0x0, 0xd, 
+0x0, 0x0, 0x0, 0x27bdffe0, 
+0x3c1cc000, 0xafbf0018, 0xaf80680c, 0xe00004c, 
+0x241b2105, 0x97850000, 0x97870002, 0x9782002c, 
+0x9783002e, 0x3c040800, 0x248409c0, 0xafa00014, 
+0x21400, 0x621825, 0x52c00, 0xafa30010, 
+0x8f860010, 0xe52825, 0xe000060, 0x24070102, 
+0x3c02ac00, 0x34420100, 0x3c03ac01, 0x34630100, 
+0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, 
+0xaf82049c, 0x24020001, 0xaf825ce0, 0xe00003f, 
+0xaf825d00, 0xe000140, 0x0, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, 
+0x8f835400, 0x34630400, 0xaf835400, 0xaf825404, 
+0x3c020800, 0x24420034, 0xaf82541c, 0x3e00008, 
+0xaf805400, 0x0, 0x0, 0x3c020800, 
+0x34423000, 0x3c030800, 0x34633000, 0x3c040800, 
+0x348437ff, 0x3c010800, 0xac220a64, 0x24020040, 
+0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, 
+0xac600000, 0x24630004, 0x83102b, 0x5040fffd, 
+0xac600000, 0x3e00008, 0x0, 0x804821, 
+0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, 
+0x8c840a68, 0x8fab0014, 0x24430001, 0x44102b, 
+0x3c010800, 0xac230a60, 0x14400003, 0x4021, 
+0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, 
+0x3c030800, 0x8c630a64, 0x91240000, 0x21140, 
+0x431021, 0x481021, 0x25080001, 0xa0440000, 
+0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 
+0x8c420a60, 0x3c030800, 0x8c630a64, 0x8f84680c, 
+0x21140, 0x431021, 0xac440008, 0xac45000c, 
+0xac460010, 0xac470014, 0xac4a0018, 0x3e00008, 
+0xac4b001c, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x2000008, 
+0x0, 0xa0001e3, 0x3c0a0001, 0xa0001e3, 
+0x3c0a0002, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x3c0a0007, 0xa0001e3, 0x3c0a0008, 0xa0001e3, 
+0x3c0a0009, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x3c0a000b, 0xa0001e3, 
+0x3c0a000c, 0xa0001e3, 0x3c0a000d, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x3c0a000e, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x0, 0xa0001e3, 
+0x0, 0xa0001e3, 0x3c0a0013, 0xa0001e3, 
+0x3c0a0014, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x27bdffe0, 
+0x1821, 0x1021, 0xafbf0018, 0xafb10014, 
+0xafb00010, 0x3c010800, 0x220821, 0xac200a70, 
+0x3c010800, 0x220821, 0xac200a74, 0x3c010800, 
+0x220821, 0xac200a78, 0x24630001, 0x1860fff5, 
+0x2442000c, 0x24110001, 0x8f906810, 0x32020004, 
+0x14400005, 0x24040001, 0x3c020800, 0x8c420a78, 
+0x18400003, 0x2021, 0xe000182, 0x0, 
+0x32020001, 0x10400003, 0x0, 0xe000169, 
+0x0, 0xa000153, 0xaf915028, 0x8fbf0018, 
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020, 
+0x3c050800, 0x8ca50a70, 0x3c060800, 0x8cc60a80, 
+0x3c070800, 0x8ce70a78, 0x27bdffe0, 0x3c040800, 
+0x248409d0, 0xafbf0018, 0xafa00010, 0xe000060, 
+0xafa00014, 0xe00017b, 0x2021, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x24020001, 0x8f836810, 
+0x821004, 0x21027, 0x621824, 0x3e00008, 
+0xaf836810, 0x27bdffd8, 0xafbf0024, 0x1080002e, 
+0xafb00020, 0x8f825cec, 0xafa20018, 0x8f825cec, 
+0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, 
+0xaf825cec, 0x8e020000, 0x18400016, 0x0, 
+0x3c020800, 0x94420a74, 0x8fa3001c, 0x221c0, 
+0xac830004, 0x8fa2001c, 0x3c010800, 0xe000201, 
+0xac220a74, 0x10400005, 0x0, 0x8e020000, 
+0x24420001, 0xa0001df, 0xae020000, 0x3c020800, 
+0x8c420a70, 0x21c02, 0x321c0, 0xa0001c5, 
+0xafa2001c, 0xe000201, 0x0, 0x1040001f, 
+0x0, 0x8e020000, 0x8fa3001c, 0x24420001, 
+0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, 
+0xa0001df, 0xae020000, 0x3c100800, 0x26100a78, 
+0x8e020000, 0x18400028, 0x0, 0xe000201, 
+0x0, 0x14400024, 0x0, 0x8e020000, 
+0x3c030800, 0x8c630a70, 0x2442ffff, 0xafa3001c, 
+0x18400006, 0xae020000, 0x31402, 0x221c0, 
+0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, 
+0x2442ff00, 0x2c420300, 0x1440000b, 0x24024000, 
+0x3c040800, 0x248409dc, 0xafa00010, 0xafa00014, 
+0x8fa6001c, 0x24050008, 0xe000060, 0x3821, 
+0xa0001df, 0x0, 0xaf825cf8, 0x3c020800, 
+0x8c420a40, 0x8fa3001c, 0x24420001, 0xaf835cf8, 
+0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, 
+0x3e00008, 0x27bd0028, 0x27bdffe0, 0x3c040800, 
+0x248409e8, 0x2821, 0x3021, 0x3821, 
+0xafbf0018, 0xafa00010, 0xe000060, 0xafa00014, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f82680c, 
+0x8f85680c, 0x21827, 0x3182b, 0x31823, 
+0x431024, 0x441021, 0xa2282b, 0x10a00006, 
+0x0, 0x401821, 0x8f82680c, 0x43102b, 
+0x1440fffd, 0x0, 0x3e00008, 0x0, 
+0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, 
+0x64102b, 0x54400002, 0x831023, 0x641023, 
+0x2c420008, 0x3e00008, 0x38420001, 0x27bdffe0, 
+0x802821, 0x3c040800, 0x24840a00, 0x3021, 
+0x3821, 0xafbf0018, 0xafa00010, 0xe000060, 
+0xafa00014, 0xa000216, 0x0, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x0, 0x27bdffe0, 
+0x3c1cc000, 0xafbf0018, 0xe00004c, 0xaf80680c, 
+0x3c040800, 0x24840a10, 0x3802821, 0x3021, 
+0x3821, 0xafa00010, 0xe000060, 0xafa00014, 
+0x2402ffff, 0xaf825404, 0x3c0200aa, 0xe000234, 
+0xaf825434, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
+0x0, 0x0, 0x0, 0x27bdffe8, 
+0xafb00010, 0x24100001, 0xafbf0014, 0x3c01c003, 
+0xac200000, 0x8f826810, 0x30422000, 0x10400003, 
+0x0, 0xe000246, 0x0, 0xa00023a, 
+0xaf905428, 0x8fbf0014, 0x8fb00010, 0x3e00008, 
+0x27bd0018, 0x27bdfff8, 0x8f845d0c, 0x3c0200ff, 
+0x3c030800, 0x8c630a50, 0x3442fff8, 0x821024, 
+0x1043001e, 0x3c0500ff, 0x34a5fff8, 0x3c06c003, 
+0x3c074000, 0x851824, 0x8c620010, 0x3c010800, 
+0xac230a50, 0x30420008, 0x10400005, 0x871025, 
+0x8cc20000, 0x24420001, 0xacc20000, 0x871025, 
+0xaf825d0c, 0x8fa20000, 0x24420001, 0xafa20000, 
+0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, 
+0x8fa20000, 0x8f845d0c, 0x3c030800, 0x8c630a50, 
+0x851024, 0x1443ffe8, 0x851824, 0x27bd0008, 
+0x3e00008, 0x0, 0x0, 0x0 };
+U32 t3FwRodata[(0x60/4) + 1] = {
+0x35373031, 0x726c7341, 0x0, 
+0x0, 0x53774576, 0x656e7430, 0x0, 
+0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 
+0x45766e74, 0x0, 0x0, 0x0, 
+0x0, 0x66617461, 0x6c457272, 0x0, 
+0x0, 0x4d61696e, 0x43707542, 0x0, 
+0x0, 0x0 };
+U32 t3FwData[(0x20/4) + 1] = {
+0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0 };
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/Makefile orig/drivers/net/bcm/Makefile
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/Makefile	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,13 @@
+
+#
+# Makefile for linux/drivers/net/bcm
+#
+
+O_TARGET := bcm5700.o
+obj-y    := b57um.o b57proc.o tigon3.o autoneg.o 5701rls.o tcp_seg.o
+obj-m    := $(O_TARGET)
+
+EXTRA_CFLAGS = -DDBG=0 -DT3_JUMBO_RCV_RCB_ENTRY_COUNT=256 -DNICE_SUPPORT -DPCIX_TARGET_WORKAROUND=1 -DINCLUDE_TBI_SUPPORT -DINCLUDE_5701_AX_FIX=1
+
+include $(TOPDIR)/Rules.make
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/autoneg.c orig/drivers/net/bcm/autoneg.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/autoneg.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/autoneg.c	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,438 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+#if INCLUDE_TBI_SUPPORT
+#include "mm.h"
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+MM_AnTxConfig(
+    PAN_STATE_INFO pAnInfo)
+{
+    PLM_DEVICE_BLOCK pDevice;
+
+    pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
+
+    REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT);
+
+    pDevice->MacMode |= MAC_MODE_SEND_CONFIGS;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+MM_AnTxIdle(
+    PAN_STATE_INFO pAnInfo)
+{
+    PLM_DEVICE_BLOCK pDevice;
+
+    pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
+
+    pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+char
+MM_AnRxConfig(
+    PAN_STATE_INFO pAnInfo,
+    unsigned short *pRxConfig)
+{
+    PLM_DEVICE_BLOCK pDevice;
+    LM_UINT32 Value32;
+    char Retcode;
+
+    Retcode = AN_FALSE;
+
+    pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
+
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+    if(Value32 & MAC_STATUS_RECEIVING_CFG)
+    {
+        Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg);
+        *pRxConfig = (unsigned short) Value32;
+
+        Retcode = AN_TRUE;
+    }
+
+    return Retcode;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+AutonegInit(
+    PAN_STATE_INFO pAnInfo)
+{
+    unsigned long j;
+
+    for(j = 0; j < sizeof(AN_STATE_INFO); j++)
+    {
+        ((unsigned char *) pAnInfo)[j] = 0;
+    }
+
+    /* Initialize the default advertisement register. */
+    pAnInfo->mr_adv_full_duplex = 1;
+    pAnInfo->mr_adv_sym_pause = 1;
+    pAnInfo->mr_adv_asym_pause = 1;
+    pAnInfo->mr_an_enable = 1;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+AUTONEG_STATUS
+Autoneg8023z(
+    PAN_STATE_INFO pAnInfo)
+{
+    unsigned short RxConfig;
+    unsigned long Delta_us;
+    AUTONEG_STATUS AnRet;
+
+    /* Get the current time. */
+    if(pAnInfo->State == AN_STATE_UNKNOWN)
+    {
+        pAnInfo->RxConfig.AsUSHORT = 0;
+        pAnInfo->CurrentTime_us = 0;
+        pAnInfo->LinkTime_us = 0;
+        pAnInfo->AbilityMatchCfg = 0;
+        pAnInfo->AbilityMatchCnt = 0;
+        pAnInfo->AbilityMatch = AN_FALSE;
+        pAnInfo->IdleMatch = AN_FALSE;
+        pAnInfo->AckMatch = AN_FALSE;
+    }
+
+    /* Increment the timer tick.  This function is called every microsecon. */
+//    pAnInfo->CurrentTime_us++;
+
+    /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */
+    /* corresponding conditions are satisfied. */
+    if(MM_AnRxConfig(pAnInfo, &RxConfig))
+    {
+        if(RxConfig != pAnInfo->AbilityMatchCfg)
+        {
+            pAnInfo->AbilityMatchCfg = RxConfig;
+            pAnInfo->AbilityMatch = AN_FALSE;
+            pAnInfo->AbilityMatchCnt = 0;
+        }
+        else
+        {
+            pAnInfo->AbilityMatchCnt++;
+            if(pAnInfo->AbilityMatchCnt > 1)
+            {
+                pAnInfo->AbilityMatch = AN_TRUE;
+                pAnInfo->AbilityMatchCfg = RxConfig;
+            }
+        }
+
+        if(RxConfig & AN_CONFIG_ACK)
+        {
+            pAnInfo->AckMatch = AN_TRUE;
+        }
+        else
+        {
+            pAnInfo->AckMatch = AN_FALSE;
+        }
+
+        pAnInfo->IdleMatch = AN_FALSE;
+    }
+    else
+    {
+        pAnInfo->IdleMatch = AN_TRUE;
+
+        pAnInfo->AbilityMatchCfg = 0;
+        pAnInfo->AbilityMatchCnt = 0;
+        pAnInfo->AbilityMatch = AN_FALSE;
+        pAnInfo->AckMatch = AN_FALSE;
+
+        RxConfig = 0;
+    }
+
+    /* Save the last Config. */
+    pAnInfo->RxConfig.AsUSHORT = RxConfig;
+
+    /* Default return code. */
+    AnRet = AUTONEG_STATUS_OK;
+
+    /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */
+    switch(pAnInfo->State)
+    {
+        case AN_STATE_UNKNOWN:
+            if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an)
+            {
+                pAnInfo->CurrentTime_us = 0;
+                pAnInfo->State = AN_STATE_AN_ENABLE;
+            }
+
+            /* Fall through.*/
+
+        case AN_STATE_AN_ENABLE:
+            pAnInfo->mr_an_complete = AN_FALSE;
+            pAnInfo->mr_page_rx = AN_FALSE;
+
+            if(pAnInfo->mr_an_enable)
+            {
+                pAnInfo->LinkTime_us = 0;
+                pAnInfo->AbilityMatchCfg = 0;
+                pAnInfo->AbilityMatchCnt = 0;
+                pAnInfo->AbilityMatch = AN_FALSE;
+                pAnInfo->IdleMatch = AN_FALSE;
+                pAnInfo->AckMatch = AN_FALSE;
+
+                pAnInfo->State = AN_STATE_AN_RESTART_INIT;
+            }
+            else
+            {
+                pAnInfo->State = AN_STATE_DISABLE_LINK_OK;
+            }
+            break;
+
+        case AN_STATE_AN_RESTART_INIT:
+            pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
+            pAnInfo->mr_np_loaded = AN_FALSE;
+
+            pAnInfo->TxConfig.AsUSHORT = 0;
+            MM_AnTxConfig(pAnInfo);
+
+            AnRet = AUTONEG_STATUS_TIMER_ENABLED;
+
+            pAnInfo->State = AN_STATE_AN_RESTART;
+
+            /* Fall through.*/
+
+        case AN_STATE_AN_RESTART:
+            /* Get the current time and compute the delta with the saved */
+            /* link timer. */
+            Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
+            if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
+            {
+                pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT;
+            }
+            else
+            {
+                AnRet = AUTONEG_STATUS_TIMER_ENABLED;
+            }
+            break;
+
+        case AN_STATE_DISABLE_LINK_OK:
+            AnRet = AUTONEG_STATUS_DONE;
+            break;
+
+        case AN_STATE_ABILITY_DETECT_INIT:
+            /* Note: in the state diagram, this variable is set to */
+            /* mr_adv_ability<12>.  Is this right?. */
+            pAnInfo->mr_toggle_tx = AN_FALSE;
+
+            /* Send the config as advertised in the advertisement register. */
+            pAnInfo->TxConfig.AsUSHORT = 0;
+            pAnInfo->TxConfig.D5_FD = pAnInfo->mr_adv_full_duplex;
+            pAnInfo->TxConfig.D6_HD = pAnInfo->mr_adv_half_duplex;
+            pAnInfo->TxConfig.D7_PS1 = pAnInfo->mr_adv_sym_pause;
+            pAnInfo->TxConfig.D8_PS2 = pAnInfo->mr_adv_asym_pause;
+            pAnInfo->TxConfig.D12_RF1 = pAnInfo->mr_adv_remote_fault1;
+            pAnInfo->TxConfig.D13_RF2 = pAnInfo->mr_adv_remote_fault2;
+            pAnInfo->TxConfig.D15_NP = pAnInfo->mr_adv_next_page;
+
+            MM_AnTxConfig(pAnInfo);
+
+            pAnInfo->State = AN_STATE_ABILITY_DETECT;
+
+            break;
+
+        case AN_STATE_ABILITY_DETECT:
+            if(pAnInfo->AbilityMatch == AN_TRUE &&
+                pAnInfo->RxConfig.AsUSHORT != 0)
+            {
+                pAnInfo->State = AN_STATE_ACK_DETECT_INIT;
+            }
+
+            break;
+
+        case AN_STATE_ACK_DETECT_INIT:
+            pAnInfo->TxConfig.D14_ACK = 1;
+            MM_AnTxConfig(pAnInfo);
+
+            pAnInfo->State = AN_STATE_ACK_DETECT;
+
+            /* Fall through. */
+
+        case AN_STATE_ACK_DETECT:
+            if(pAnInfo->AckMatch == AN_TRUE)
+            {
+                if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) ==
+                    (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK))
+                {
+                    pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT;
+                }
+                else
+                {
+                    pAnInfo->State = AN_STATE_AN_ENABLE;
+                }
+            }
+            else if(pAnInfo->AbilityMatch == AN_TRUE &&
+                pAnInfo->RxConfig.AsUSHORT == 0)
+            {
+                pAnInfo->State = AN_STATE_AN_ENABLE;
+            }
+
+            break;
+
+        case AN_STATE_COMPLETE_ACK_INIT:
+            /* Make sure invalid bits are not set. */
+            if(pAnInfo->RxConfig.bits.D0 || pAnInfo->RxConfig.bits.D1 ||
+                pAnInfo->RxConfig.bits.D2 || pAnInfo->RxConfig.bits.D3 ||
+                pAnInfo->RxConfig.bits.D4 || pAnInfo->RxConfig.bits.D9 ||
+                pAnInfo->RxConfig.bits.D10 || pAnInfo->RxConfig.bits.D11)
+            {
+                AnRet = AUTONEG_STATUS_FAILED;
+                break;
+            }
+
+            /* Set up the link partner advertisement register. */
+            pAnInfo->mr_lp_adv_full_duplex = pAnInfo->RxConfig.D5_FD;
+            pAnInfo->mr_lp_adv_half_duplex = pAnInfo->RxConfig.D6_HD;
+            pAnInfo->mr_lp_adv_sym_pause = pAnInfo->RxConfig.D7_PS1;
+            pAnInfo->mr_lp_adv_asym_pause = pAnInfo->RxConfig.D8_PS2;
+            pAnInfo->mr_lp_adv_remote_fault1 = pAnInfo->RxConfig.D12_RF1;
+            pAnInfo->mr_lp_adv_remote_fault2 = pAnInfo->RxConfig.D13_RF2;
+            pAnInfo->mr_lp_adv_next_page = pAnInfo->RxConfig.D15_NP;
+
+            pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
+
+            pAnInfo->mr_toggle_tx = !pAnInfo->mr_toggle_tx;
+            pAnInfo->mr_toggle_rx = pAnInfo->RxConfig.bits.D11;
+            pAnInfo->mr_np_rx = pAnInfo->RxConfig.D15_NP;
+            pAnInfo->mr_page_rx = AN_TRUE;
+
+            pAnInfo->State = AN_STATE_COMPLETE_ACK;
+            AnRet = AUTONEG_STATUS_TIMER_ENABLED;
+
+            break;
+
+        case AN_STATE_COMPLETE_ACK:
+            if(pAnInfo->AbilityMatch == AN_TRUE &&
+                pAnInfo->RxConfig.AsUSHORT == 0)
+            {
+                pAnInfo->State = AN_STATE_AN_ENABLE;
+                break;
+            }
+
+            Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
+
+            if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
+            {
+                if(pAnInfo->mr_adv_next_page == 0 ||
+                    pAnInfo->mr_lp_adv_next_page == 0)
+                {
+                    pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
+                }
+                else
+                {
+                    if(pAnInfo->TxConfig.bits.D15 == 0 &&
+                        pAnInfo->mr_np_rx == 0)
+                    {
+                        pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
+                    }
+                    else
+                    {
+                        AnRet = AUTONEG_STATUS_FAILED;
+                    }
+                }
+            }
+
+            break;
+
+        case AN_STATE_IDLE_DETECT_INIT:
+            pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
+
+            MM_AnTxIdle(pAnInfo);
+
+            pAnInfo->State = AN_STATE_IDLE_DETECT;
+
+            AnRet = AUTONEG_STATUS_TIMER_ENABLED;
+
+            break;
+
+        case AN_STATE_IDLE_DETECT:
+            if(pAnInfo->AbilityMatch == AN_TRUE &&
+                pAnInfo->RxConfig.AsUSHORT == 0)
+            {
+                pAnInfo->State = AN_STATE_AN_ENABLE;
+                break;
+            }
+
+            Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
+            if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
+            {
+//                if(pAnInfo->IdleMatch == AN_TRUE)
+//                {
+                    pAnInfo->State = AN_STATE_LINK_OK;
+//                }
+//                else
+//                {
+//                    AnRet = AUTONEG_STATUS_FAILED;
+//                    break;
+//                }
+            }
+
+            break;
+
+        case AN_STATE_LINK_OK:
+            pAnInfo->mr_an_complete = AN_TRUE;
+            pAnInfo->mr_link_ok = AN_TRUE;
+            AnRet = AUTONEG_STATUS_DONE;
+
+            break;
+
+        case AN_STATE_NEXT_PAGE_WAIT_INIT:
+            break;
+
+        case AN_STATE_NEXT_PAGE_WAIT:
+            break;
+
+        default:
+            AnRet = AUTONEG_STATUS_FAILED;
+            break;
+    }
+
+    return AnRet;
+}
+#endif /* INCLUDE_TBI_SUPPORT */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/autoneg.h orig/drivers/net/bcm/autoneg.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/autoneg.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/autoneg.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,418 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+
+#ifndef AUTONEG_H
+#define AUTONEG_H
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+#define AN_LINK_TIMER_INTERVAL_US           12000       /* 10ms */
+
+/* TRUE, FALSE */
+#define AN_TRUE                             1
+#define AN_FALSE                            0
+
+
+
+/******************************************************************************/
+/* Main data structure for keeping track of 802.3z auto-negotation state */
+/* variables as shown in Figure 37-6 of the IEEE 802.3z specification. */
+/******************************************************************************/
+
+typedef struct
+{
+    /* Pointer to the operating system specific data structure. */
+    void *pContext;
+
+    /* Current auto-negotiation state. */
+    unsigned long State;
+    #define AN_STATE_UNKNOWN                        0
+    #define AN_STATE_AN_ENABLE                      1
+    #define AN_STATE_AN_RESTART_INIT                2
+    #define AN_STATE_AN_RESTART                     3
+    #define AN_STATE_DISABLE_LINK_OK                4
+    #define AN_STATE_ABILITY_DETECT_INIT            5
+    #define AN_STATE_ABILITY_DETECT                 6
+    #define AN_STATE_ACK_DETECT_INIT                7
+    #define AN_STATE_ACK_DETECT                     8
+    #define AN_STATE_COMPLETE_ACK_INIT              9
+    #define AN_STATE_COMPLETE_ACK                   10
+    #define AN_STATE_IDLE_DETECT_INIT               11
+    #define AN_STATE_IDLE_DETECT                    12
+    #define AN_STATE_LINK_OK                        13
+    #define AN_STATE_NEXT_PAGE_WAIT_INIT            14
+    #define AN_STATE_NEXT_PAGE_WAIT                 16
+
+    /* Link timer. */
+    unsigned long LinkTime_us;
+
+    /* Current time. */
+    unsigned long CurrentTime_us;
+
+    /* Ability, idle, and ack match functions. */
+    unsigned long AbilityMatchCnt;
+
+    /* Need these values for consistency check. */
+    unsigned short AbilityMatchCfg;
+
+    unsigned short reserved;
+
+    char AbilityMatch;
+    char IdleMatch;
+    char AckMatch;
+    char reserved1;
+
+    /* Tx config data */
+    union
+    {
+        /* The TxConfig register is arranged as follows:                      */
+        /*                                                                    */
+        /* MSB                                                           LSB  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8|  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        struct
+        {
+#ifdef BIG_ENDIAN_HOST
+            unsigned short D7:1;        /* PS1 */
+            unsigned short D6:1;        /* HD */
+            unsigned short D5:1;        /* FD */
+            unsigned short D4:1;
+            unsigned short D3:1;
+            unsigned short D2:1;
+            unsigned short D1:1;
+            unsigned short D0:1;
+            unsigned short D15:1;       /* NP */
+            unsigned short D14:1;       /* ACK */
+            unsigned short D13:1;       /* RF2 */
+            unsigned short D12:1;       /* RF1 */
+            unsigned short D11:1;
+            unsigned short D10:1;
+            unsigned short D9:1;
+            unsigned short D8:1;        /* PS2 */
+#else /* BIG_ENDIAN_HOST */
+            unsigned int D8:1;        /* PS2 */
+            unsigned int D9:1;
+            unsigned int D10:1;
+            unsigned int D11:1;
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D13:1;       /* RF2 */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D15:1;       /* NP */
+            unsigned int D0:1;
+            unsigned int D1:1;
+            unsigned int D2:1;
+            unsigned int D3:1;
+            unsigned int D4:1;
+            unsigned int D5:1;        /* FD */
+            unsigned int D6:1;        /* HD */
+            unsigned int D7:1;        /* PS1 */
+#endif
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define D8_PS2                      bits.D8
+        #define D12_RF1                     bits.D12
+        #define D13_RF2                     bits.D13
+        #define D14_ACK                     bits.D14
+        #define D15_NP                      bits.D15
+        #define D5_FD                       bits.D5
+        #define D6_HD                       bits.D6
+        #define D7_PS1                      bits.D7
+    } TxConfig;
+
+    /* Rx config data */
+    union
+    {
+        /* The RxConfig register is arranged as follows:                      */
+        /*                                                                    */
+        /* MSB                                                           LSB  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8|  */
+        /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+  */
+        struct
+        {
+#ifdef BIG_ENDIAN_HOST
+	    unsigned short D7:1;        /* PS1 */
+            unsigned short D6:1;        /* HD */
+	    unsigned short D5:1;        /* FD */
+            unsigned short D4:1;
+            unsigned short D3:1;
+            unsigned short D2:1;
+            unsigned short D1:1;
+            unsigned short D0:1;
+  	    unsigned short D15:1;       /* NP */
+            unsigned short D14:1;       /* ACK */
+            unsigned short D13:1;       /* RF2 */    
+            unsigned short D12:1;       /* RF1 */
+            unsigned short D11:1;
+            unsigned short D10:1;
+            unsigned short D9:1;
+            unsigned short D8:1;        /* PS2 */
+#else /* BIG_ENDIAN_HOST */
+            unsigned int D8:1;        /* PS2 */
+            unsigned int D9:1;
+            unsigned int D10:1;
+            unsigned int D11:1;
+            unsigned int D12:1;       /* RF1 */
+            unsigned int D13:1;       /* RF2 */
+            unsigned int D14:1;       /* ACK */
+            unsigned int D15:1;       /* NP */
+            unsigned int D0:1;
+            unsigned int D1:1;
+            unsigned int D2:1;
+            unsigned int D3:1;
+            unsigned int D4:1;
+            unsigned int D5:1;        /* FD */
+            unsigned int D6:1;        /* HD */
+            unsigned int D7:1;        /* PS1 */
+#endif
+        } bits;
+
+        unsigned short AsUSHORT;
+    } RxConfig;
+
+    #define AN_CONFIG_NP                            0x0080
+    #define AN_CONFIG_ACK                           0x0040
+    #define AN_CONFIG_RF2                           0x0020
+    #define AN_CONFIG_RF1                           0x0010
+    #define AN_CONFIG_PS2                           0x0001
+    #define AN_CONFIG_PS1                           0x8000
+    #define AN_CONFIG_HD                            0x4000
+    #define AN_CONFIG_FD                            0x2000
+
+
+    /* Management registers. */
+
+    /* Control register. */
+    union
+    {
+        struct
+        {
+            unsigned int an_enable:1;
+            unsigned int loopback:1;
+            unsigned int reset:1;
+            unsigned int restart_an:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_an_enable                Mr0.bits.an_enable
+        #define mr_loopback                 Mr0.bits.loopback
+        #define mr_main_reset               Mr0.bits.reset
+        #define mr_restart_an               Mr0.bits.restart_an
+    } Mr0;
+
+    /* Status register. */
+    union
+    {
+        struct
+        {
+            unsigned int an_complete:1;
+            unsigned int link_ok:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_an_complete              Mr1.bits.an_complete
+        #define mr_link_ok                  Mr1.bits.link_ok
+    } Mr1;
+
+    /* Advertisement register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_4:5;
+            unsigned int full_duplex:1;
+            unsigned int half_duplex:1;
+            unsigned int sym_pause:1;
+            unsigned int asym_pause:1;
+            unsigned int reserved_11:3;
+            unsigned int remote_fault1:1;
+            unsigned int remote_fault2:1;
+            unsigned int reserved_14:1;
+            unsigned int next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_adv_full_duplex          Mr4.bits.full_duplex
+        #define mr_adv_half_duplex          Mr4.bits.half_duplex
+        #define mr_adv_sym_pause            Mr4.bits.sym_pause
+        #define mr_adv_asym_pause           Mr4.bits.asym_pause
+        #define mr_adv_remote_fault1        Mr4.bits.remote_fault1
+        #define mr_adv_remote_fault2        Mr4.bits.remote_fault2
+        #define mr_adv_next_page            Mr4.bits.next_page
+    } Mr4;
+
+    /* Link partner advertisement register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_4:5;
+            unsigned int lp_full_duplex:1;
+            unsigned int lp_half_duplex:1;
+            unsigned int lp_sym_pause:1;
+            unsigned int lp_asym_pause:1;
+            unsigned int reserved_11:3;
+            unsigned int lp_remote_fault1:1;
+            unsigned int lp_remote_fault2:1;
+            unsigned int lp_ack:1;
+            unsigned int lp_next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_lp_adv_full_duplex       Mr5.bits.lp_full_duplex
+        #define mr_lp_adv_half_duplex       Mr5.bits.lp_half_duplex
+        #define mr_lp_adv_sym_pause         Mr5.bits.lp_sym_pause
+        #define mr_lp_adv_asym_pause        Mr5.bits.lp_asym_pause
+        #define mr_lp_adv_remote_fault1     Mr5.bits.lp_remote_fault1
+        #define mr_lp_adv_remote_fault2     Mr5.bits.lp_remote_fault2
+        #define mr_lp_adv_next_page         Mr5.bits.lp_next_page
+    } Mr5;
+
+    /* Auto-negotiation expansion register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_0:1;
+            unsigned int page_received:1;
+            unsigned int next_pageable:1;
+            unsigned int reserved_15:13;
+        } bits;
+
+        unsigned short AsUSHORT;
+    } Mr6;
+
+    /* Auto-negotiation next page transmit register. */
+    union
+    {
+        struct
+        {
+            unsigned int code_field:11;
+            unsigned int toggle:1;
+            unsigned int ack2:1;
+            unsigned int message_page:1;
+            unsigned int reserved_14:1;
+            unsigned int next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_np_tx                    Mr7.AsUSHORT
+    } Mr7;
+
+    /* Auto-negotiation link partner ability register. */
+    union
+    {
+        struct
+        {
+            unsigned int code_field:11;
+            unsigned int toggle:1;
+            unsigned int ack2:1;
+            unsigned int message_page:1;
+            unsigned int ack:1;
+            unsigned int next_page:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+        
+        #define mr_lp_np_rx                 Mr8.AsUSHORT
+    } Mr8;
+
+    /* Extended status register. */
+    union
+    {
+        struct
+        {
+            unsigned int reserved_11:12;
+            unsigned int base1000_t_hd:1;
+            unsigned int base1000_t_fd:1;
+            unsigned int base1000_x_hd:1;
+            unsigned int base1000_x_fd:1;
+        } bits;      
+
+        unsigned short AsUSHORT;
+    } Mr15;
+
+    /* Miscellaneous state variables. */
+    union
+    {
+        struct
+        {
+            unsigned int toggle_tx:1;
+            unsigned int toggle_rx:1;
+            unsigned int np_rx:1;
+            unsigned int page_rx:1;
+            unsigned int np_loaded:1;
+        } bits;
+
+        unsigned short AsUSHORT;
+
+        #define mr_toggle_tx                MrMisc.bits.toggle_tx
+        #define mr_toggle_rx                MrMisc.bits.toggle_rx
+        #define mr_np_rx                    MrMisc.bits.np_rx
+        #define mr_page_rx                  MrMisc.bits.page_rx
+        #define mr_np_loaded                MrMisc.bits.np_loaded
+    } MrMisc;
+
+} AN_STATE_INFO, *PAN_STATE_INFO;
+
+
+
+/******************************************************************************/
+/* Return code of Autoneg8023z. */
+/******************************************************************************/
+
+typedef enum
+{
+    AUTONEG_STATUS_OK               = 0,
+    AUTONEG_STATUS_DONE             = 1,
+    AUTONEG_STATUS_TIMER_ENABLED    = 2,
+//    AUTONEG_STATUS_FAILED           = 0xffffffff,
+    AUTONEG_STATUS_FAILED           = 0xfffffff
+} AUTONEG_STATUS, *PAUTONEG_STATUS;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+AUTONEG_STATUS Autoneg8023z(PAN_STATE_INFO pAnInfo);
+void AutonegInit(PAN_STATE_INFO pAnInfo);
+
+
+
+/******************************************************************************/
+/* The following functions are defined in the os-dependent module. */
+/******************************************************************************/
+
+void MM_AnTxConfig(PAN_STATE_INFO pAnInfo);
+void MM_AnTxIdle(PAN_STATE_INFO pAnInfo);
+char MM_AnRxConfig(PAN_STATE_INFO pAnInfo, unsigned short *pRxConfig);
+
+
+
+#endif /* AUTONEG_H */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/b57proc.c orig/drivers/net/bcm/b57proc.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/b57proc.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/b57proc.c	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,461 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* /proc file system handling code.                                           */
+/*                                                                            */
+/******************************************************************************/
+
+#include "mm.h"
+#ifdef BCM_PROC_FS
+
+#define NICINFO_PROC_DIR "nicinfo"
+
+static struct proc_dir_entry *bcm5700_procfs_dir;
+
+extern char bcm5700_driver[], bcm5700_version[];
+
+extern unsigned long bcm5700_crc_count(PUM_DEVICE_BLOCK pUmDevice);
+
+static char *na_str = "n/a";
+static char *pause_str = "pause ";
+static char *asym_pause_str = "asym_pause ";
+static char *on_str = "on";
+static char *off_str = "off";
+static char *up_str = "up";
+static char *down_str = "down";
+
+static struct proc_dir_entry *
+proc_getdir(char *name, struct proc_dir_entry *proc_dir)
+{
+	struct proc_dir_entry *pde = proc_dir;
+
+	lock_kernel();
+	for (pde=pde->subdir; pde; pde = pde->next) {
+		if (pde->namelen && (strcmp(name, pde->name) == 0)) {
+			/* directory exists */
+			break;
+		}
+	}
+	if (pde == (struct proc_dir_entry *) 0)
+	{
+		/* create the directory */
+#if (LINUX_VERSION_CODE > 0x20300)
+		pde = proc_mkdir(name, proc_dir);
+#else
+		pde = create_proc_entry(name, S_IFDIR, proc_dir);
+#endif
+		if (pde == (struct proc_dir_entry *) 0) {
+			unlock_kernel();
+			return (pde);
+		}
+	}
+	unlock_kernel();
+	return (pde);
+}
+
+int
+bcm5700_proc_create(void)
+{
+	bcm5700_procfs_dir = proc_getdir(NICINFO_PROC_DIR, proc_net);
+
+	if (bcm5700_procfs_dir == (struct proc_dir_entry *) 0) {
+		printk(KERN_DEBUG "Could not create procfs nicinfo directory %s\n", NICINFO_PROC_DIR);
+		return -1;
+	}
+	return 0;
+}
+
+void
+b57_get_speed_adv(PUM_DEVICE_BLOCK pUmDevice, char *str)
+{
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (pDevice->DisableAutoNeg == TRUE) {
+		strcpy(str, na_str);
+		return;
+	}
+	if (pDevice->EnableTbi) {
+		strcpy(str, "1000full");
+		return;
+	}
+	str[0] = 0;
+	if (pDevice->advertising & PHY_AN_AD_10BASET_HALF) {
+		strcat(str, "10half ");
+	}
+	if (pDevice->advertising & PHY_AN_AD_10BASET_FULL) {
+		strcat(str, "10full ");
+	}
+	if (pDevice->advertising & PHY_AN_AD_100BASETX_HALF) {
+		strcat(str, "100half ");
+	}
+	if (pDevice->advertising & PHY_AN_AD_100BASETX_FULL) {
+		strcat(str, "100full ");
+	}
+	if (pDevice->advertising1000 & BCM540X_AN_AD_1000BASET_HALF) {
+		strcat(str, "1000half ");
+	}
+	if (pDevice->advertising1000 & BCM540X_AN_AD_1000BASET_FULL) {
+		strcat(str, "1000full ");
+	}
+}
+
+void
+b57_get_fc_adv(PUM_DEVICE_BLOCK pUmDevice, char *str)
+{
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (pDevice->DisableAutoNeg == TRUE) {
+		strcpy(str, na_str);
+		return;
+	}
+	str[0] = 0;
+	if (pDevice->EnableTbi) {
+		if (pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE) {
+			if (pDevice->FlowControlCap &
+				LM_FLOW_CONTROL_RECEIVE_PAUSE) {
+
+				strcpy(str, pause_str);
+				if (!(pDevice->FlowControlCap &
+					LM_FLOW_CONTROL_TRANSMIT_PAUSE)) {
+
+					strcpy(str, asym_pause_str);
+				}
+			}
+			else if (pDevice->FlowControlCap &
+				LM_FLOW_CONTROL_TRANSMIT_PAUSE) {
+
+				strcpy(str, asym_pause_str);
+			}
+		}
+		return;
+	}
+	if (pDevice->advertising & PHY_AN_AD_PAUSE_CAPABLE) {
+		strcat(str, pause_str);
+	}
+	if (pDevice->advertising & PHY_AN_AD_ASYM_PAUSE) {
+		strcat(str, asym_pause_str);
+	}
+}
+
+int
+bcm5700_read_pfs(char *page, char **start, off_t off, int count,
+	int *eof, void *data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+	PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
+	int len = 0;
+	unsigned long rx_mac_errors, rx_crc_errors, rx_align_errors;
+	unsigned long rx_runt_errors, rx_frag_errors, rx_long_errors;
+	unsigned long rx_overrun_errors, rx_jabber_errors;
+	char str[64];
+
+	if (pUmDevice->opened == 0)
+		pStats = 0;
+
+	len += sprintf(page+len, "Description\t\t\t%s\n", pUmDevice->name);
+	len += sprintf(page+len, "Driver_Name\t\t\t%s\n", bcm5700_driver);
+	len += sprintf(page+len, "Driver_Version\t\t\t%s\n", bcm5700_version);
+	len += sprintf(page+len, "Bootcode_Version\t\t%s\n", pDevice->BootCodeVer);
+	len += sprintf(page+len, "PCI_Vendor\t\t\t0x%04x\n", pDevice->PciVendorId);
+	len += sprintf(page+len, "PCI_Device_ID\t\t\t0x%04x\n",
+		pDevice->PciDeviceId);
+	len += sprintf(page+len, "PCI_Subsystem_Vendor\t\t0x%04x\n",
+		pDevice->SubsystemVendorId);
+	len += sprintf(page+len, "PCI_Subsystem_ID\t\t0x%04x\n",
+		pDevice->SubsystemId);
+	len += sprintf(page+len, "PCI_Revision_ID\t\t\t0x%02x\n",
+		pDevice->PciRevId);
+	len += sprintf(page+len, "PCI_Slot\t\t\t%d\n",
+		PCI_SLOT(pUmDevice->pdev->devfn));
+	if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
+		len += sprintf(page+len, "PCI_Function\t\t\t%d\n",
+			pDevice->FunctNum);
+	}
+	len += sprintf(page+len, "PCI_Bus\t\t\t\t%d\n",
+		pUmDevice->pdev->bus->number);
+
+	len += sprintf(page+len, "PCI_Bus_Speed\t\t\t%s\n",
+		pDevice->BusSpeedStr);
+
+	len += sprintf(page+len, "Memory\t\t\t\t0x%lx\n", pUmDevice->dev->base_addr);
+	len += sprintf(page+len, "IRQ\t\t\t\t%d\n", dev->irq);
+	len += sprintf(page+len, "System_Device_Name\t\t%s\n", dev->name);
+	len += sprintf(page+len, "Current_HWaddr\t\t\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+	len += sprintf(page+len,
+		"Permanent_HWaddr\t\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+		pDevice->NodeAddress[0], pDevice->NodeAddress[1],
+		pDevice->NodeAddress[2], pDevice->NodeAddress[3],
+		pDevice->NodeAddress[4], pDevice->NodeAddress[5]);
+	len += sprintf(page+len, "Part_Number\t\t\t%s\n\n", pDevice->PartNo);
+
+	len += sprintf(page+len, "Link\t\t\t\t%s\n", 
+		(pUmDevice->opened == 0) ? "unknown" :
+    		((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) ? up_str :
+		down_str));
+	len += sprintf(page+len, "Auto_Negotiate\t\t\t%s\n", 
+    		(pDevice->DisableAutoNeg == TRUE) ? off_str : on_str);
+	b57_get_speed_adv(pUmDevice, str);
+	len += sprintf(page+len, "Speed_Advertisement\t\t%s\n", str);
+	b57_get_fc_adv(pUmDevice, str);
+	len += sprintf(page+len, "Flow_Control_Advertisement\t%s\n", str);
+	len += sprintf(page+len, "Speed\t\t\t\t%s\n", 
+    		((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
+		(pUmDevice->opened == 0)) ? na_str :
+    		((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) ? "1000" :
+    		((pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) ? "100" :
+    		(pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) ? "10" : na_str)));
+	len += sprintf(page+len, "Duplex\t\t\t\t%s\n", 
+    		((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
+		(pUmDevice->opened == 0)) ? na_str :
+		((pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) ? "full" :
+			"half"));
+	len += sprintf(page+len, "Flow_Control\t\t\t%s\n", 
+    		((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
+		(pUmDevice->opened == 0)) ? na_str :
+		((pDevice->FlowControl == LM_FLOW_CONTROL_NONE) ? off_str :
+		(((pDevice->FlowControl & LM_FLOW_CONTROL_RX_TX_PAUSE) ==
+			LM_FLOW_CONTROL_RX_TX_PAUSE) ? "receive/transmit" :
+		(pDevice->FlowControl & LM_FLOW_CONTROL_RECEIVE_PAUSE) ?
+			"receive" : "transmit")));
+	len += sprintf(page+len, "State\t\t\t\t%s\n", 
+		(pUmDevice->suspended ? "suspended" :
+    		((dev->flags & IFF_UP) ? up_str : down_str)));
+	len += sprintf(page+len, "MTU_Size\t\t\t%d\n\n", dev->mtu);
+	len += sprintf(page+len, "Rx_Packets\t\t\t%lu\n", 
+			((pStats == 0) ? 0 :
+			MM_GETSTATS(pStats->ifHCInUcastPkts) +
+			MM_GETSTATS(pStats->ifHCInMulticastPkts) +
+			MM_GETSTATS(pStats->ifHCInBroadcastPkts)));
+	if (dev->mtu > 1500) {
+		len += sprintf(page+len, "Rx_Jumbo_Packets\t\t%lu\n", 
+			((pStats == 0) ? 0 :
+			MM_GETSTATS(
+				pStats->etherStatsPkts1523Octetsto2047Octets) +
+			MM_GETSTATS(
+				pStats->etherStatsPkts2048Octetsto4095Octets) +
+			MM_GETSTATS(
+				pStats->etherStatsPkts4096Octetsto8191Octets) +
+			MM_GETSTATS(
+				pStats->etherStatsPkts8192Octetsto9022Octets)));
+	}
+	len += sprintf(page+len, "Tx_Packets\t\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->ifHCOutUcastPkts) +
+		MM_GETSTATS(pStats->ifHCOutMulticastPkts) +
+		MM_GETSTATS(pStats->ifHCOutBroadcastPkts)));
+#ifdef BCM_TSO
+	len += sprintf(page+len, "TSO_Large_Packets\t\t%lu\n",
+		pUmDevice->tso_pkt_count);
+#endif
+	len += sprintf(page+len, "Rx_Bytes\t\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->ifHCInOctets)));
+	len += sprintf(page+len, "Tx_Bytes\t\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->ifHCOutOctets)));
+	if (pStats == 0) {
+		rx_crc_errors = 0;
+		rx_align_errors = 0;
+		rx_runt_errors = 0;
+		rx_frag_errors = 0;
+		rx_long_errors = 0;
+		rx_overrun_errors = 0;
+		rx_jabber_errors = 0;
+	}
+	else {
+		rx_crc_errors = bcm5700_crc_count(pUmDevice);
+		rx_align_errors = MM_GETSTATS(pStats->dot3StatsAlignmentErrors);
+		rx_runt_errors = MM_GETSTATS(pStats->etherStatsUndersizePkts);
+		rx_frag_errors = MM_GETSTATS(pStats->etherStatsFragments);
+		rx_long_errors = MM_GETSTATS(pStats->dot3StatsFramesTooLong);
+		rx_overrun_errors = MM_GETSTATS(pStats->nicNoMoreRxBDs);
+		rx_jabber_errors = MM_GETSTATS(pStats->etherStatsJabbers);
+	}
+	rx_mac_errors = rx_crc_errors + rx_align_errors + rx_runt_errors +
+		rx_frag_errors + rx_long_errors + rx_jabber_errors;
+	len += sprintf(page+len, "Rx_Errors\t\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		rx_mac_errors + rx_overrun_errors + pUmDevice->rx_misc_errors));
+	len += sprintf(page+len, "Tx_Errors\t\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->ifOutErrors)));
+	len += sprintf(page+len, "\nTx_Carrier_Errors\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors)));
+	len += sprintf(page+len, "Tx_Abort_Excess_Coll\t\t%lu\n",
+		((pStats == 0) ? 0 :
+    		MM_GETSTATS(pStats->dot3StatsExcessiveCollisions)));
+	len += sprintf(page+len, "Tx_Abort_Late_Coll\t\t%lu\n",
+		((pStats == 0) ? 0 :
+    		MM_GETSTATS(pStats->dot3StatsLateCollisions)));
+	len += sprintf(page+len, "Tx_Deferred_Ok\t\t\t%lu\n",
+		((pStats == 0) ? 0 :
+    		MM_GETSTATS(pStats->dot3StatsDeferredTransmissions)));
+	len += sprintf(page+len, "Tx_Single_Coll_Ok\t\t%lu\n",
+		((pStats == 0) ? 0 :
+    		MM_GETSTATS(pStats->dot3StatsSingleCollisionFrames)));
+	len += sprintf(page+len, "Tx_Multi_Coll_Ok\t\t%lu\n",
+		((pStats == 0) ? 0 :
+    		MM_GETSTATS(pStats->dot3StatsMultipleCollisionFrames)));
+	len += sprintf(page+len, "Tx_Total_Coll_Ok\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->etherStatsCollisions)));
+	len += sprintf(page+len, "Tx_XON_Pause_Frames\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->outXonSent)));
+	len += sprintf(page+len, "Tx_XOFF_Pause_Frames\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->outXoffSent)));
+	len += sprintf(page+len, "\nRx_CRC_Errors\t\t\t%lu\n", rx_crc_errors);
+	len += sprintf(page+len, "Rx_Short_Fragment_Errors\t%lu\n",
+		rx_frag_errors);
+	len += sprintf(page+len, "Rx_Short_Length_Errors\t\t%lu\n",
+		rx_runt_errors);
+	len += sprintf(page+len, "Rx_Long_Length_Errors\t\t%lu\n",
+		rx_long_errors);
+	len += sprintf(page+len, "Rx_Align_Errors\t\t\t%lu\n",
+		rx_align_errors);
+	len += sprintf(page+len, "Rx_Overrun_Errors\t\t%lu\n",
+		rx_overrun_errors);
+	len += sprintf(page+len, "Rx_XON_Pause_Frames\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->xonPauseFramesReceived)));
+	len += sprintf(page+len, "Rx_XOFF_Pause_Frames\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->xoffPauseFramesReceived)));
+	len += sprintf(page+len, "\nTx_MAC_Errors\t\t\t%lu\n",
+		((pStats == 0) ? 0 :
+		MM_GETSTATS(pStats->dot3StatsInternalMacTransmitErrors)));
+	len += sprintf(page+len, "Rx_MAC_Errors\t\t\t%lu\n\n",
+		rx_mac_errors);
+
+	len += sprintf(page+len, "Tx_Checksum\t\t\t%s\n",
+		((pDevice->TaskToOffload & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM) ?
+		on_str : off_str));
+	len += sprintf(page+len, "Rx_Checksum\t\t\t%s\n",
+		((pDevice->TaskToOffload & LM_TASK_OFFLOAD_RX_TCP_CHECKSUM) ?
+		on_str : off_str));
+	len += sprintf(page+len, "Scatter_Gather\t\t\t%s\n",
+#if (LINUX_VERSION_CODE >= 0x20400)
+		((dev->features & NETIF_F_SG) ? on_str : off_str));
+#else
+		off_str);
+#endif
+#ifdef BCM_TSO
+	len += sprintf(page+len, "TSO\t\t\t\t%s\n",
+		((dev->features & NETIF_F_TSO) ? on_str : off_str));
+#endif
+	len += sprintf(page+len, "VLAN\t\t\t\t%s\n\n",
+		((pDevice->RxMode & RX_MODE_KEEP_VLAN_TAG) ? off_str : on_str));
+
+	len += sprintf(page+len, "Tx_Desc_Count\t\t\t%u\n",
+		pDevice->TxPacketDescCnt);
+	len += sprintf(page+len, "Rx_Desc_Count\t\t\t%u\n",
+		pDevice->RxStdDescCnt);
+	len += sprintf(page+len, "Rx_Jumbo_Desc_Count\t\t%u\n",
+		pDevice->RxJumboDescCnt);
+#ifdef BCM_INT_COAL
+	len += sprintf(page+len, "Adaptive_Coalescing\t\t%s\n",
+		(pUmDevice->adaptive_coalesce ? on_str : off_str));
+	len += sprintf(page+len, "Rx_Coalescing_Ticks\t\t%u\n",
+		pUmDevice->rx_curr_coalesce_ticks);
+	len += sprintf(page+len, "Rx_Coalesced_Frames\t\t%u\n",
+		pUmDevice->rx_curr_coalesce_frames);
+	len += sprintf(page+len, "Tx_Coalescing_Ticks\t\t%u\n",
+		pDevice->TxCoalescingTicks);
+	len += sprintf(page+len, "Tx_Coalesced_Frames\t\t%u\n",
+		pUmDevice->tx_curr_coalesce_frames);
+	len += sprintf(page+len, "Stats_Coalescing_Ticks\t\t%u\n",
+		pDevice->StatsCoalescingTicks);
+#endif
+#ifdef BCM_WOL
+	len += sprintf(page+len, "Wake_On_LAN\t\t\t%s\n",
+        	((pDevice->WakeUpMode & LM_WAKE_UP_MODE_MAGIC_PACKET) ?
+		on_str : off_str));
+#endif
+#if TIGON3_DEBUG
+	len += sprintf(page+len, "\nDmaReadWriteCtrl\t\t%x\n",
+		pDevice->DmaReadWriteCtrl);
+	len += sprintf(page+len, "\nTx_Zero_Copy_Packets\t\t%u\n",
+		pUmDevice->tx_zc_count);
+	len += sprintf(page+len, "Tx_Chksum_Packets\t\t%u\n",
+		pUmDevice->tx_chksum_count);
+	len += sprintf(page+len, "Tx_Highmem_Fragments\t\t%u\n",
+		pUmDevice->tx_himem_count);
+	len += sprintf(page+len, "Rx_Good_Chksum_Packets\t\t%u\n",
+		pUmDevice->rx_good_chksum_count);
+	len += sprintf(page+len, "Rx_Bad_Chksum_Packets\t\t%u\n",
+		pUmDevice->rx_bad_chksum_count);
+	if (!pDevice->EnableTbi) {
+		LM_UINT32 value32;
+		unsigned long flags;
+
+		flags = bcm5700_phy_lock(pUmDevice);
+        	LM_ReadPhy(pDevice, 0, &value32);
+		len += sprintf(page+len, "\nPhy_Register_0x00\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 1, &value32);
+		len += sprintf(page+len, "Phy_Register_0x01\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 2, &value32);
+		len += sprintf(page+len, "Phy_Register_0x02\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 3, &value32);
+		len += sprintf(page+len, "Phy_Register_0x03\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 4, &value32);
+		len += sprintf(page+len, "Phy_Register_0x04\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 5, &value32);
+		len += sprintf(page+len, "Phy_Register_0x05\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 9, &value32);
+		len += sprintf(page+len, "Phy_Register_0x09\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 0xa, &value32);
+		len += sprintf(page+len, "Phy_Register_0x0A\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 0xf, &value32);
+		len += sprintf(page+len, "Phy_Register_0x0F\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 0x10, &value32);
+		len += sprintf(page+len, "Phy_Register_0x10\t\t0x%x\n", value32);
+        	LM_ReadPhy(pDevice, 0x19, &value32);
+		len += sprintf(page+len, "Phy_Register_0x19\t\t0x%x\n", value32);
+		bcm5700_phy_unlock(pUmDevice, flags);
+	}
+#endif
+
+	*eof = 1;
+	return len;
+}
+
+int
+bcm5700_proc_create_dev(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+
+	if (!bcm5700_procfs_dir)
+		return -1;
+
+	sprintf(pUmDevice->pfs_name, "%s.info", dev->name);
+	pUmDevice->pfs_entry = create_proc_entry(pUmDevice->pfs_name,
+		S_IFREG, bcm5700_procfs_dir);
+	if (pUmDevice->pfs_entry == 0)
+		return -1;
+	pUmDevice->pfs_entry->read_proc = bcm5700_read_pfs;
+	pUmDevice->pfs_entry->data = dev;
+	return 0;
+}
+int
+bcm5700_proc_remove_dev(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+
+	remove_proc_entry(pUmDevice->pfs_name, bcm5700_procfs_dir);
+	return 0;
+}
+
+#endif
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/b57um.c orig/drivers/net/bcm/b57um.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/b57um.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/b57um.c	2003-01-21 16:38:40.000000000 -0500
@@ -0,0 +1,3430 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/******************************************************************************/
+
+
+char bcm5700_driver[] = "bcm5700";
+char bcm5700_version[] = "5.0.17";
+char bcm5700_date[] = "(01/10/03)";
+
+#define B57UM
+#include "mm.h"
+
+/* A few user-configurable values. */
+
+#define MAX_UNITS 16
+/* Used to pass the full-duplex flag, etc. */
+static int line_speed[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static int auto_speed[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int full_duplex[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int rx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int tx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int auto_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int mtu[MAX_UNITS] = {1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500};	/* Jumbo MTU for interfaces. */
+static int tx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int rx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int scatter_gather[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+
+#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
+static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
+	{TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
+	TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
+	TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
+	TX_DESC_CNT};
+
+#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
+static unsigned int rx_std_desc_cnt[MAX_UNITS] =
+	{RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
+	RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
+	RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
+	RX_DESC_CNT };
+
+#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
+static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
+	{JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
+	JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
+	JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
+	JBO_DESC_CNT };
+
+#ifdef BCM_INT_COAL
+static unsigned int adaptive_coalesce[MAX_UNITS] =
+	{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+
+#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
+static unsigned int rx_coalesce_ticks[MAX_UNITS] =
+	{RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
+	RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
+	RX_COAL_TK,RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
+	RX_COAL_TK};
+
+#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
+static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
+	{RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
+	RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
+	RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
+	RX_COAL_FM};
+
+#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
+static unsigned int tx_coalesce_ticks[MAX_UNITS] =
+	{TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
+	TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
+	TX_COAL_TK,TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
+	TX_COAL_TK};
+
+#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
+static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
+	{TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
+	TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
+	TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
+	TX_COAL_FM};
+
+#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
+static unsigned int stats_coalesce_ticks[MAX_UNITS] =
+	{ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
+	ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
+	ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
+	ST_COAL_TK,};
+
+#endif
+#ifdef BCM_WOL
+static int enable_wol[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#endif
+static int enable_tso[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+
+#if (LINUX_VERSION_CODE < 0x02030d)
+#define pci_resource_start(dev, bar)	(dev->base_address[bar] & PCI_BASE_ADDRESS_MEM_MASK)
+#elif (LINUX_VERSION_CODE < 0x02032b)
+#define pci_resource_start(dev, bar)	(dev->resource[bar] & PCI_BASE_ADDRESS_MEM_MASK)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+#define dev_kfree_skb_irq(skb)  dev_kfree_skb(skb)
+#define netif_wake_queue(dev)	clear_bit(0, &dev->tbusy); mark_bh(NET_BH)
+#define netif_stop_queue(dev)	set_bit(0, &dev->tbusy)
+
+static inline void netif_start_queue(struct net_device *dev)
+{
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+}
+
+#define netif_queue_stopped(dev)	dev->tbusy
+#define netif_running(dev)		dev->start
+
+static inline void tasklet_schedule(struct tasklet_struct *tasklet)
+{
+	queue_task(tasklet, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+static inline void tasklet_init(struct tasklet_struct *tasklet,
+				void (*func)(unsigned long),
+				unsigned long data)
+{
+        tasklet->next = NULL;
+        tasklet->sync = 0;
+        tasklet->routine = (void (*)(void *))func;
+        tasklet->data = (void *)data;
+}
+
+#define tasklet_kill(tasklet)
+
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020300)
+struct pci_device_id {
+	unsigned int vendor, device;		/* Vendor and device ID or PCI_ANY_ID */
+	unsigned int subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
+	unsigned int class, class_mask;		/* (class,subclass,prog-if) triplet */
+	unsigned long driver_data;		/* Data private to the driver */
+};
+
+#define PCI_ANY_ID		0
+
+#define pci_set_drvdata(pdev, dev)
+#define pci_get_drvdata(pdev) 0
+
+#define pci_enable_device(pdev) 0
+
+#define __devinit		__init
+#define __devinitdata		__initdata
+#define __devexit
+
+#define SET_MODULE_OWNER(dev)
+#define MODULE_DEVICE_TABLE(pci, pci_tbl)
+
+#endif
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(license)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032a)
+static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
+					 dma_addr_t *dma_handle)
+{
+	void *virt_ptr;
+
+	/* Maximum in slab.c */
+	if (size > 131072)
+		return 0;
+
+	virt_ptr = kmalloc(size, GFP_KERNEL);
+	*dma_handle = virt_to_bus(virt_ptr);
+	return virt_ptr;
+}
+#define pci_free_consistent(dev, size, ptr, dma_ptr)	kfree(ptr)
+
+#endif /*#if (LINUX_VERSION_CODE < 0x02032a) */
+
+
+#if (LINUX_VERSION_CODE < 0x020329)
+#define pci_set_dma_mask(pdev, mask) (0)
+#else
+#if (LINUX_VERSION_CODE < 0x020403)
+int
+pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
+{
+    if(! pci_dma_supported(dev, mask))
+        return -EIO;
+
+    dev->dma_mask = mask;
+
+    return 0;
+}
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020402)
+#define pci_request_regions(pdev, name) (0)
+#define pci_release_regions(pdev)
+#endif
+
+#if ! defined(spin_is_locked)
+#define spin_is_locked(lock)    (test_bit(0,(lock)))
+#endif
+
+inline unsigned long
+bcm5700_lock(PUM_DEVICE_BLOCK pUmDevice)
+{
+	unsigned long flags;
+	
+	if (pUmDevice->do_global_lock) {
+		spin_lock_irqsave(&pUmDevice->global_lock, flags);
+		return flags;
+	}
+	return 0;
+}
+
+inline void
+bcm5700_unlock(PUM_DEVICE_BLOCK pUmDevice, unsigned long flags)
+{
+	if (pUmDevice->do_global_lock) {
+		spin_unlock_irqrestore(&pUmDevice->global_lock, flags);
+	}
+}
+
+int
+bcm5700_trylock(PUM_DEVICE_BLOCK pUmDevice, unsigned long *flags)
+{
+	if (pUmDevice->do_global_lock) {
+		if (spin_is_locked(&pUmDevice->global_lock))
+			return 0;
+		spin_lock_irqsave(&pUmDevice->global_lock, *flags);
+		return 1;
+	}
+	return 1;
+}
+
+inline void
+bcm5700_intr_lock(PUM_DEVICE_BLOCK pUmDevice)
+{
+	if (pUmDevice->do_global_lock) {
+		spin_lock(&pUmDevice->global_lock);
+	}
+}
+
+inline void
+bcm5700_intr_unlock(PUM_DEVICE_BLOCK pUmDevice)
+{
+	if (pUmDevice->do_global_lock) {
+		spin_unlock(&pUmDevice->global_lock);
+	}
+}
+
+unsigned long
+bcm5700_phy_lock(PUM_DEVICE_BLOCK pUmDevice)
+{
+	unsigned long flags;
+	
+	if (pUmDevice->do_global_lock) {
+		spin_lock_irqsave(&pUmDevice->global_lock, flags);
+		return flags;
+	}
+	else {
+		spin_lock_irqsave(&pUmDevice->phy_lock, flags);
+		return flags;
+	}
+	return 0;
+}
+
+void
+bcm5700_phy_unlock(PUM_DEVICE_BLOCK pUmDevice, unsigned long flags)
+{
+	if (pUmDevice->do_global_lock) {
+		spin_unlock_irqrestore(&pUmDevice->global_lock, flags);
+	}
+	else {
+		spin_unlock_irqrestore(&pUmDevice->phy_lock, flags);
+	}
+}
+
+void
+bcm5700_intr_off(PUM_DEVICE_BLOCK pUmDevice)
+{
+	atomic_inc(&pUmDevice->intr_sem);
+	LM_DisableInterrupt(&pUmDevice->lm_dev);
+#if (LINUX_VERSION_CODE >= 0x2051c)
+	synchronize_irq(pUmDevice->dev->irq);
+#else
+	synchronize_irq();
+#endif
+	LM_DisableInterrupt(&pUmDevice->lm_dev);
+}
+
+void
+bcm5700_intr_on(PUM_DEVICE_BLOCK pUmDevice)
+{
+	if (atomic_dec_and_test(&pUmDevice->intr_sem)) {
+		LM_EnableInterrupt(&pUmDevice->lm_dev);
+	}
+}
+
+/*
+ * Broadcom NIC Extension support
+ * -ffan
+ */
+#ifdef NICE_SUPPORT
+#include "nicext.h"
+
+typedef struct {
+	ushort  tag;
+	ushort  signature;
+} vlan_tag_t;
+
+#endif /* NICE_SUPPORT */
+
+int MM_Packet_Desc_Size = sizeof(UM_PACKET);
+
+#if defined(MODULE)
+MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
+MODULE_DESCRIPTION("BCM5700 Driver");
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM(line_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(auto_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(tx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(auto_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(mtu, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(tx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(scatter_gather, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(tx_pkt_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_std_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_jumbo_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#ifdef BCM_INT_COAL
+MODULE_PARM(adaptive_coalesce, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(tx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(tx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(stats_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+#ifdef BCM_WOL
+MODULE_PARM(enable_wol, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+MODULE_PARM(enable_tso, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+
+#define RUN_AT(x) (jiffies + (x))
+
+
+#define PCI_SUPPORT_VER2
+
+#if ! defined(CAP_NET_ADMIN)
+#define capable(CAP_XXX) (suser())
+#endif
+
+#define tigon3_debug debug
+#if TIGON3_DEBUG
+static int tigon3_debug = TIGON3_DEBUG;
+#else
+static int tigon3_debug = 0;
+#endif
+
+
+STATIC int bcm5700_open(struct net_device *dev);
+STATIC void bcm5700_timer(unsigned long data);
+STATIC void bcm5700_reset(struct net_device *dev);
+STATIC int bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev);
+STATIC void bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+#ifdef BCM_TASKLET
+STATIC void bcm5700_tasklet(unsigned long data);
+#endif
+STATIC int bcm5700_close(struct net_device *dev);
+STATIC struct net_device_stats *bcm5700_get_stats(struct net_device *dev);
+STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+STATIC void bcm5700_set_rx_mode(struct net_device *dev);
+STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p);
+STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu);
+STATIC int replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice);
+STATIC int bcm5700_freemem(struct net_device *dev);
+#ifdef BCM_INT_COAL
+STATIC int bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice);
+#endif
+#ifdef BCM_VLAN
+STATIC void bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp);
+STATIC void bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid);
+#endif
+void bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice);
+void bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice);
+void bcm5700_validate_param_range(struct net_device *dev, int *param,
+	char *param_name, int min, int max, int deflt);
+
+
+/* A list of all installed bcm5700 devices. */
+static struct net_device *root_tigon3_dev = NULL;
+
+typedef enum {
+	BCM5700VIGIL = 0,
+	BCM5700A6,
+	BCM5700T6,
+	BCM5700A9,
+	BCM5700T9,
+	BCM5700,
+	BCM5701A5,
+	BCM5701T1,
+	BCM5701T8,
+	BCM5701A7,
+	BCM5701A10,
+	BCM5701A12,
+	BCM5701,
+	BCM5702,
+	BCM5703,
+	BCM5703A31,
+	BCM5703ARBUCKLE,
+	TC996T,
+	TC996ST,
+	TC996SSX,
+	TC996SX,
+	TC996BT,
+	TC997T,
+	TC997SX,
+	TC1000T,
+	TC1000BT,
+	TC940BR01,
+	TC942BR01,
+	TC998T,
+	TC998SX,
+	TC999T,
+	NC6770,
+	NC7760,
+	NC7770,
+	NC7771,
+	NC7780,
+	NC7781,
+	NC7772,
+	NC7782,
+	NC7783,
+	BCM5704CIOBE,
+	BCM5704,
+	BCM5704S,
+	BCM5705,
+	BCM5705M,
+	BCM5782
+} board_t;
+
+
+/* indexed by board_t, above */
+static struct {
+	char *name;
+} board_info[] __devinitdata = {
+	{ "Broadcom Vigil B5700 1000Base-T" },
+	{ "Broadcom BCM5700 1000Base-T" },
+	{ "Broadcom BCM5700 1000Base-SX" },
+	{ "Broadcom BCM5700 1000Base-SX" },
+	{ "Broadcom BCM5700 1000Base-T" },
+	{ "Broadcom BCM5700" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-SX" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701" },
+	{ "Broadcom BCM5702 1000Base-T" },
+	{ "Broadcom BCM5703 1000Base-T" },
+	{ "Broadcom BCM5703 1000Base-SX" },
+	{ "Broadcom Arbuckle B5703 1000Base-SX" },
+	{ "3Com 3C996 10/100/1000 Server NIC" },
+	{ "3Com 3C996 10/100/1000 Server NIC" },
+	{ "3Com 3C996 Gigabit Fiber-SX Server NIC" },
+	{ "3Com 3C996 Gigabit Fiber-SX Server NIC" },
+	{ "3Com 3C996B Gigabit Server NIC" },
+	{ "3Com 3C997 Gigabit Server NIC" },
+	{ "3Com 3C997 Gigabit Fiber-SX Server NIC" },
+	{ "3Com 3C1000 Gigabit NIC" },
+	{ "3Com 3C1000B-T 10/100/1000 PCI" },
+	{ "3Com 3C940 Gigabit LOM (21X21)" },
+	{ "3Com 3C942 Gigabit LOM (31X31)" },
+	{ "3Com 3C998-T Dual Port 10/100/1000 PCI-X Server NIC" },
+	{ "3Com 3C998-SX Dual Port 1000-SX PCI-X Server NIC" },
+	{ "3Com 3C999-T Quad Port 10/100/1000 PCI-X Server NIC" },
+	{ "Compaq NC6770 Gigabit Server Adapter" },
+	{ "Compaq NC7760 Gigabit Server Adapter" },
+	{ "Compaq NC7770 Gigabit Server Adapter" },
+	{ "Compaq NC7771 Gigabit Server Adapter" },
+	{ "Compaq NC7780 Gigabit Server Adapter" },
+	{ "Compaq NC7781 Gigabit Server Adapter" },
+	{ "HP NC7772 Gigabit Server Adapter" },
+	{ "HP NC7782 Gigabit Server Adapter" },
+	{ "HP NC7783 Gigabit Server Adapter" },
+	{ "Broadcom BCM5704 CIOB-E 1000Base-T" },
+	{ "Broadcom BCM5704 1000Base-T" },
+	{ "Broadcom BCM5704 1000Base-SX" },
+	{ "Broadcom BCM5705 1000Base-T" },
+	{ "Broadcom BCM5705M 1000Base-T" },
+	{ "Broadcom BCM5782 1000Base-T" },
+	{ 0 },
+	};
+
+static struct pci_device_id bcm5700_pci_tbl[] __devinitdata = {
+	{0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL },
+	{0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 },
+	{0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 },
+	{0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 },
+	{0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 },
+	{0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 },
+	{0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 },
+	{0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 },
+	{0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 },
+	{0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T },
+	{0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST },
+	{0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX },
+	{0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T },
+	{0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX },
+	{0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 },
+	{0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 },
+	{0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 },
+	{0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 },
+	{0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 },
+	{0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 },
+	{0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 },
+	{0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 },
+	{0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 },
+	{0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 },
+	{0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 },
+	{0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 },
+	{0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX },
+	{0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT },
+	{0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T },
+	{0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 },
+	{0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 },
+	{0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 },
+	{0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
+	{0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 },
+	{0x14e4, 0x16a6, 0x14e4, 0x000c, 0, 0, BCM5702 },
+	{0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 },
+	{0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
+	{0x14e4, 0x16c6, 0x10b7, 0x1100, 0, 0, TC1000BT },
+	{0x14e4, 0x16c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
+	{0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 },
+	{0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
+	{0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 },
+	{0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 },
+	{0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
+	{0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 },
+	{0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
+	{0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 },
+	{0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 },
+	{0x14e4, 0x16a7, 0x0e11, 0xca, 0, 0, NC7771 },
+	{0x14e4, 0x16a7, 0x0e11, 0xcb, 0, 0, NC7781 },
+	{0x14e4, 0x16a7, 0x1014, 0x0281, 0, 0, BCM5703ARBUCKLE },
+	{0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
+	{0x14e4, 0x16c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
+	{0x14e4, 0x1648, 0x0e11, 0xcf, 0, 0, NC7772 },
+	{0x14e4, 0x1648, 0x0e11, 0xd0, 0, 0, NC7782 },
+	{0x14e4, 0x1648, 0x0e11, 0xd1, 0, 0, NC7783 },
+	{0x14e4, 0x1648, 0x10b7, 0x2000, 0, 0, TC998T },
+	{0x14e4, 0x1648, 0x10b7, 0x3000, 0, 0, TC999T },
+	{0x14e4, 0x1648, 0x1166, 0x1648, 0, 0, BCM5704CIOBE },
+	{0x14e4, 0x1648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704 },
+	{0x14e4, 0x16a8, 0x14e4, 0x16a8, 0, 0, BCM5704S },
+	{0x14e4, 0x16a8, 0x10b7, 0x2001, 0, 0, TC998SX },
+	{0x14e4, 0x16a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
+	{0x14e4, 0x1653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
+	{0x14e4, 0x165d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
+	{0x14e4, 0x1696, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5782 },
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, bcm5700_pci_tbl);
+
+#ifdef BCM_PROC_FS
+extern int bcm5700_proc_create(void);
+extern int bcm5700_proc_create_dev(struct net_device *dev);
+extern int bcm5700_proc_remove_dev(struct net_device *dev);
+#endif
+
+static int __devinit bcm5700_init_board(struct pci_dev *pdev,
+					struct net_device **dev_out,
+					int board_idx)
+{
+	struct net_device *dev;
+	PUM_DEVICE_BLOCK pUmDevice;
+	PLM_DEVICE_BLOCK pDevice;
+	int rc;
+
+	*dev_out = NULL;
+
+	/* dev zeroed in init_etherdev */
+	dev = init_etherdev(NULL, sizeof(*pUmDevice));
+	if (dev == NULL) {
+		printk (KERN_ERR "%s: unable to alloc new ethernet\n",
+			bcm5700_driver);
+		return -ENOMEM;
+	}
+	SET_MODULE_OWNER(dev);
+	pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+
+	/* enable device (incl. PCI PM wakeup), and bus-mastering */
+	rc = pci_enable_device (pdev);
+	if (rc)
+		goto err_out;
+
+	rc = pci_request_regions(pdev, bcm5700_driver);
+	if (rc)
+		goto err_out;
+
+	pci_set_master(pdev);
+
+	if (pci_set_dma_mask(pdev, ~(0UL)) != 0) {
+		printk(KERN_ERR "System does not support DMA\n");
+		pci_release_regions(pdev);
+		goto err_out;
+	}
+
+	pUmDevice->dev = dev;
+	pUmDevice->pdev = pdev;
+	pUmDevice->mem_list_num = 0;
+	pUmDevice->next_module = root_tigon3_dev;
+	pUmDevice->index = board_idx;
+	root_tigon3_dev = dev;
+
+	spin_lock_init(&pUmDevice->global_lock);
+
+	spin_lock_init(&pUmDevice->undi_lock);
+
+	spin_lock_init(&pUmDevice->phy_lock);
+
+	pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	pDevice->FunctNum = PCI_FUNC(pUmDevice->pdev->devfn);
+
+	bcm5700_validate_param_range(dev, &mtu[board_idx], "mtu", 1500, 9000, 1500);
+	dev->mtu = mtu[board_idx];
+
+	if (pci_find_device(0x8086, 0x2418, NULL) ||
+		pci_find_device(0x8086, 0x2428, NULL) ||
+		pci_find_device(0x8086, 0x244e, NULL) ||
+		pci_find_device(0x8086, 0x2448, NULL)) {
+
+		/* Found ICH, ICH0, or ICH2 */
+		pDevice->UndiFix = 1;
+	}
+
+	if (LM_GetAdapterInfo(pDevice) != LM_STATUS_SUCCESS) {
+		printk(KERN_ERR "Get Adapter info failed\n");
+		rc = -ENODEV;
+		goto err_out_unmap;
+	}
+
+	if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) {
+		if (dev->mtu > 1500) {
+			dev->mtu = 1500;
+			printk(KERN_WARNING "%s: Jumbo mtu sizes not supported, using mtu=1500\n", dev->name);
+		}
+	}
+	if (pci_find_device(0x1022, 0x700c, NULL)) {
+		/* AMD762 writes I/O out of order */
+		/* Setting bit 1 in 762's register 0x4C still doesn't work */
+		/* in all cases */
+		pDevice->FlushPostedWrites = TRUE;
+		pDevice->NicSendBd = FALSE;
+	}
+	if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
+		if ((REG_RD(pDevice, PciCfg.DualMacCtrl) &
+			T3_DUAL_MAC_CH_CTRL_MASK) == 3) {
+
+			printk(KERN_WARNING "%s: Device is configured for Hardware Based Teaming which is not supported with this operating system. Please consult the user diagnostic guide to disable Turbo Teaming.\n", dev->name);
+		}
+	}
+
+	pUmDevice->do_global_lock = 0;
+	if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
+		/* The 5700 chip works best without interleaved register */
+		/* accesses on certain machines. */
+		pUmDevice->do_global_lock = 1;
+	}
+	if ((T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5701) &&
+		((pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) == 0)) {
+
+		pUmDevice->rx_buf_align = 0;
+	}
+	else {
+		pUmDevice->rx_buf_align = 2;
+	}
+/*	dev->base_addr = pci_resource_start(pdev, 0);*/
+	dev->mem_start = pci_resource_start(pdev, 0);
+	dev->mem_end = dev->mem_start + sizeof(T3_STD_MEM_MAP); 
+	dev->irq = pdev->irq;
+
+	*dev_out = dev;
+	return 0;
+
+err_out_unmap:
+	pci_release_regions(pdev);
+	bcm5700_freemem(dev);
+
+err_out:
+	unregister_netdev(dev);
+	kfree (dev);
+	return rc;
+}
+
+static int __devinit
+bcm5700_print_ver(void)
+{
+	printk(KERN_INFO "Broadcom Gigabit Ethernet Driver %s ",
+		bcm5700_driver);
+#ifdef NICE_SUPPORT
+	printk("with Broadcom NIC Extension (NICE) ");
+#endif
+	printk("ver. %s %s\n", bcm5700_version, bcm5700_date);
+	return 0;
+}
+
+static int __devinit
+bcm5700_init_one(struct pci_dev *pdev,
+				       const struct pci_device_id *ent)
+{
+	struct net_device *dev = NULL;
+	PUM_DEVICE_BLOCK pUmDevice;
+	PLM_DEVICE_BLOCK pDevice;
+	int i;
+	static int board_idx = -1;
+	static int printed_version = 0;
+	struct pci_dev *amd_dev;
+
+	board_idx++;
+
+	if (!printed_version) {
+		bcm5700_print_ver();
+#ifdef BCM_PROC_FS
+		bcm5700_proc_create();
+#endif
+		printed_version = 1;
+	}
+
+	i = bcm5700_init_board(pdev, &dev, board_idx);
+	if (i < 0) {
+		return i;
+	}
+
+	if (dev == NULL)
+		return -ENOMEM;
+
+	dev->open = bcm5700_open;
+	dev->hard_start_xmit = bcm5700_start_xmit;
+	dev->stop = bcm5700_close;
+	dev->get_stats = bcm5700_get_stats;
+	dev->set_multicast_list = bcm5700_set_rx_mode;
+	dev->do_ioctl = bcm5700_ioctl;
+	dev->set_mac_address = &bcm5700_set_mac_addr;
+	dev->change_mtu = &bcm5700_change_mtu;
+#if (LINUX_VERSION_CODE >= 0x20400)
+	dev->tx_timeout = bcm5700_reset;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#endif
+#ifdef BCM_VLAN
+	dev->vlan_rx_register = &bcm5700_vlan_rx_register;
+	dev->vlan_rx_kill_vid = &bcm5700_vlan_rx_kill_vid;
+#endif
+
+	pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+	dev->base_addr = pci_resource_start(pdev, 0);
+	dev->irq = pdev->irq;
+
+	pci_set_drvdata(pdev, dev);
+
+	memcpy(dev->dev_addr, pDevice->NodeAddress, 6);
+	pUmDevice->name = board_info[ent->driver_data].name,
+	printk(KERN_INFO "%s: %s found at mem %lx, IRQ %d, ",
+		dev->name, pUmDevice->name, dev->base_addr,
+		dev->irq);
+	printk("node addr ");
+	for (i = 0; i < 6; i++) {
+		printk("%2.2x", dev->dev_addr[i]);
+	}
+	printk("\n");
+
+	printk(KERN_INFO "%s: ", dev->name);
+	if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
+		printk("Broadcom BCM5400 Copper ");
+	else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+		printk("Broadcom BCM5401 Copper ");
+	else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
+		printk("Broadcom BCM5411 Copper ");
+	else if (((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID) &&
+		!pDevice->EnableTbi) {
+		printk("Broadcom BCM5701 Integrated Copper ");
+	}
+	else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) {
+		printk("Broadcom BCM5703 Integrated ");
+		if (pDevice->EnableTbi)
+			printk("SerDes ");
+		else
+			printk("Copper ");
+	}
+	else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5704_PHY_ID)
+		printk("Broadcom BCM5704 Integrated Copper ");
+	else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5705_PHY_ID)
+		printk("Broadcom BCM5705 Integrated Copper ");
+	else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
+		printk("Broadcom BCM8002 SerDes ");
+	else if (pDevice->EnableTbi) {
+		if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
+			printk("Broadcom BCM5704 Integrated SerDes ");
+		}
+		else {
+			printk("Agilent HDMP-1636 SerDes ");
+		}
+	}
+	else {
+		printk("Unknown ");
+	}
+	printk("transceiver found\n");
+
+	printk(KERN_INFO "%s: ", dev->name);
+#if (LINUX_VERSION_CODE >= 0x20400)
+	if (scatter_gather[board_idx]) {
+		dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA;
+	}
+	if ((pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM) &&
+		tx_checksum[board_idx]) {
+		dev->features |= NETIF_F_IP_CSUM;
+	}
+#ifdef BCM_VLAN
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+#endif
+	if ((pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TCP_SEGMENTATION) &&
+		enable_tso[board_idx]) {
+#ifdef BCM_TSO
+		dev->features |= NETIF_F_TSO;
+#endif
+	}
+
+	printk("Scatter-gather %s, 64-bit DMA %s, Tx Checksum %s, ",
+		(char *) ((dev->features & NETIF_F_SG) ? "ON" : "OFF"),
+		(char *) ((dev->features & NETIF_F_HIGHDMA) ? "ON" : "OFF"),
+		(char *) ((dev->features & NETIF_F_IP_CSUM) ? "ON" : "OFF"));
+#endif
+	if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) &&
+		rx_checksum[board_idx])
+		printk("Rx Checksum ON");
+	else
+		printk("Rx Checksum OFF");
+#ifdef BCM_VLAN
+	printk(", 802.1Q VLAN ON");
+#endif
+#ifdef BCM_TSO
+	if (dev->features & NETIF_F_TSO) {
+		printk(", TSO ON\n");
+	}
+	else
+#endif
+	printk("\n");
+
+#ifdef BCM_PROC_FS
+	bcm5700_proc_create_dev(dev);
+#endif
+#ifdef BCM_TASKLET
+	tasklet_init(&pUmDevice->tasklet, bcm5700_tasklet,
+		(unsigned long) pUmDevice);
+#endif
+	if ((amd_dev = pci_find_device(0x1022, 0x700c, NULL))) {
+		u32 val;
+
+		/* Found AMD 762 North bridge */
+		pci_read_config_dword(amd_dev, 0x4c, &val);
+		if ((val & 0x02) == 0) {
+			pci_write_config_dword(amd_dev, 0x4c, val | 0x02);
+			printk(KERN_INFO "%s: Setting AMD762 Northbridge to enable PCI ordering compliance\n", bcm5700_driver);
+		}
+	}
+	return 0;
+
+}
+
+
+static void __devexit
+bcm5700_remove_one (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+
+#ifdef BCM_PROC_FS
+	bcm5700_proc_remove_dev(dev); 
+#endif
+	unregister_netdev(dev);
+
+	if (pUmDevice->lm_dev.pMappedMemBase)
+		iounmap(pUmDevice->lm_dev.pMappedMemBase);
+
+	pci_release_regions(pdev);
+
+	kfree(dev);
+
+	pci_set_drvdata(pdev, NULL);
+
+/*	pci_power_off(pdev, -1);*/
+
+}
+
+
+
+STATIC int
+bcm5700_open(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+	if (pUmDevice->suspended)
+		return -EAGAIN;
+
+	/* delay for 4 seconds */
+	pUmDevice->delayed_link_ind = (4 * HZ) / pUmDevice->timer_interval;
+
+#ifdef BCM_INT_COAL
+	pUmDevice->adaptive_expiry = HZ / pUmDevice->timer_interval;
+#endif
+
+#if INCLUDE_TBI_SUPPORT
+	if(pDevice->PollTbiLink)
+		pUmDevice->poll_tbi_expiry = HZ / pUmDevice->timer_interval;
+#endif
+
+	pUmDevice->asf_heartbeat = (120 * HZ) / pUmDevice->timer_interval;
+
+	/* Sometimes we get spurious ints. after reset when link is down. */
+	/* This field tells the isr to service the int. even if there is */
+	/* no status block update. */
+	if (pDevice->LedMode != LED_MODE_LINK10) {
+		pUmDevice->adapter_just_inited = (3 * HZ) /
+			pUmDevice->timer_interval;
+	}
+	else {
+		pUmDevice->adapter_just_inited = 0;
+	}
+
+	if (request_irq(dev->irq, &bcm5700_interrupt, SA_SHIRQ, dev->name, dev)) {
+		return -EAGAIN;
+	}
+
+	pUmDevice->opened = 1;
+#if TIGON3_DEBUG
+	pUmDevice->tx_zc_count = 0;
+	pUmDevice->tx_chksum_count = 0;
+	pUmDevice->tx_himem_count = 0;
+	pUmDevice->rx_good_chksum_count = 0;
+	pUmDevice->rx_bad_chksum_count = 0;
+#endif
+	if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
+		free_irq(dev->irq, dev);
+		bcm5700_freemem(dev);
+		return -EAGAIN;
+	}
+
+	if (pDevice->UndiFix) {
+		printk(KERN_INFO "%s: Using indirect register access\n", dev->name);
+	}
+
+	if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
+		LM_SetMacAddress(pDevice, dev->dev_addr);
+	}
+
+	if (tigon3_debug > 1)
+		printk(KERN_DEBUG "%s: tigon3_open() irq %d.\n", dev->name, dev->irq);
+
+	QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
+        MAX_RX_PACKET_DESC_COUNT);
+	netif_start_queue(dev);
+
+#if (LINUX_VERSION_CODE < 0x020300)
+	MOD_INC_USE_COUNT;
+#endif
+
+	init_timer(&pUmDevice->timer);
+	pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
+	pUmDevice->timer.data = (unsigned long)dev;
+	pUmDevice->timer.function = &bcm5700_timer;
+	add_timer(&pUmDevice->timer);
+
+	atomic_set(&pUmDevice->intr_sem, 0);
+	LM_EnableInterrupt(pDevice);
+
+	return 0;
+}
+
+
+STATIC void
+bcm5700_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	unsigned long flags;
+	LM_UINT32 value32;
+
+	if (!pUmDevice->opened)
+		return;
+
+	if (atomic_read(&pUmDevice->intr_sem) || pUmDevice->suspended) {
+		pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
+		add_timer(&pUmDevice->timer);
+		return;
+	}
+
+	if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) &&
+		(pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)) {
+
+		LM_GetStats(pDevice);
+	}
+
+#if INCLUDE_TBI_SUPPORT
+	if(pDevice->PollTbiLink && (--pUmDevice->poll_tbi_expiry == 0)) {
+		flags = bcm5700_phy_lock(pUmDevice);
+		value32 = REG_RD(pDevice, MacCtrl.Status);
+		if (((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) &&
+			((value32 & MAC_STATUS_LINK_STATE_CHANGED) ||
+			!(value32 & MAC_STATUS_PCS_SYNCED)))
+			||
+			((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) &&
+			(value32 & MAC_STATUS_PCS_SYNCED)))
+		{
+			LM_SetupPhy(pDevice);
+		}
+		bcm5700_phy_unlock(pUmDevice, flags);
+		pUmDevice->poll_tbi_expiry = HZ / pUmDevice->timer_interval;
+		
+        }
+#endif
+
+	if (pUmDevice->delayed_link_ind > 0) {
+		if (pUmDevice->delayed_link_ind == 1)
+			MM_IndicateStatus(pDevice, pDevice->LinkStatus);
+		else
+			pUmDevice->delayed_link_ind--;
+	}
+	if (pUmDevice->adapter_just_inited > 0) {
+		pUmDevice->adapter_just_inited--;
+	}
+
+	if (pUmDevice->crc_counter_expiry > 0)
+		pUmDevice->crc_counter_expiry--;
+
+	if (!pUmDevice->interrupt) {
+		if (!pDevice->UseTaggedStatus) {
+			flags = bcm5700_lock(pUmDevice);
+			if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
+				/* This will generate an interrupt */
+				REG_WR(pDevice, Grc.LocalCtrl,
+					pDevice->GrcLocalCtrl |
+					GRC_MISC_LOCAL_CTRL_SET_INT);
+			}
+			else {
+				REG_WR(pDevice, HostCoalesce.Mode,
+					pDevice->CoalesceMode |
+					HOST_COALESCE_ENABLE |
+					HOST_COALESCE_NOW);
+			}
+			if (!(REG_RD(pDevice, DmaWrite.Mode) &
+				DMA_WRITE_MODE_ENABLE)) {
+				bcm5700_unlock(pUmDevice, flags);
+				bcm5700_reset(dev);
+			}
+			else {
+				bcm5700_unlock(pUmDevice, flags);
+			}
+			if (pUmDevice->tx_queued) {
+				pUmDevice->tx_queued = 0;
+				netif_wake_queue(dev);
+			}
+		}
+#if (LINUX_VERSION_CODE < 0x02032b)
+		if ((QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) !=
+			pDevice->TxPacketDescCnt) &&
+			((jiffies - dev->trans_start) > TX_TIMEOUT)) {
+
+			printk(KERN_WARNING "%s: Tx hung\n", dev->name);
+			bcm5700_reset(dev);
+		}
+#endif
+	}
+#ifdef BCM_INT_COAL
+	if (pUmDevice->adaptive_coalesce) {
+		pUmDevice->adaptive_expiry--;
+		if (pUmDevice->adaptive_expiry == 0) {	
+			pUmDevice->adaptive_expiry = HZ /
+				pUmDevice->timer_interval;
+			bcm5700_adapt_coalesce(pUmDevice);
+		}
+	}
+#endif
+	if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container) >
+		pUmDevice->rx_buf_repl_panic_thresh) {
+		/* Generate interrupt and let isr allocate buffers */
+		REG_WR(pDevice, HostCoalesce.Mode, pDevice->CoalesceMode |
+			HOST_COALESCE_ENABLE | HOST_COALESCE_NOW);
+	}
+
+#ifdef BCM_ASF
+	if (pDevice->EnableAsf) {
+		pUmDevice->asf_heartbeat--;
+		if (pUmDevice->asf_heartbeat == 0) {
+			MEM_WR_OFFSET(pDevice, T3_CMD_MAILBOX,
+				T3_CMD_NICDRV_ALIVE);
+			MEM_WR_OFFSET(pDevice, T3_CMD_LENGTH_MAILBOX, 4);
+			MEM_WR_OFFSET(pDevice, T3_CMD_DATA_MAILBOX, 3);
+			value32 = REG_RD(pDevice, Grc.RxCpuEvent);
+			REG_WR(pDevice, Grc.RxCpuEvent, value32 | BIT_14);
+			pUmDevice->asf_heartbeat = (120 * HZ) /
+				pUmDevice->timer_interval;
+		}
+	}
+#endif
+
+	pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
+	add_timer(&pUmDevice->timer);
+}
+
+#ifdef BCM_INT_COAL
+STATIC int
+bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice)
+{
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+	uint rx_curr_cnt, tx_curr_cnt, rx_delta, tx_delta, total_delta;
+	int adapt = 0;
+	unsigned long flags;
+
+	rx_curr_cnt = pDevice->pStatsBlkVirt->ifHCInUcastPkts.Low;
+	tx_curr_cnt = pDevice->pStatsBlkVirt->ifHCOutUcastPkts.Low;
+	if ((rx_curr_cnt <= pUmDevice->rx_last_cnt) ||
+		(tx_curr_cnt <= pUmDevice->tx_last_cnt)) {
+
+		/* skip if there is counter rollover */
+		pUmDevice->rx_last_cnt = rx_curr_cnt;
+		pUmDevice->tx_last_cnt = tx_curr_cnt;
+		return 0;
+	}
+
+	rx_delta = rx_curr_cnt - pUmDevice->rx_last_cnt;
+	tx_delta = tx_curr_cnt - pUmDevice->tx_last_cnt;
+	total_delta = (((rx_delta + rx_delta) + tx_delta) / 3) << 1;
+
+	pUmDevice->rx_last_cnt = rx_curr_cnt;
+	pUmDevice->tx_last_cnt = tx_curr_cnt;
+
+	if (total_delta < rx_delta)
+		return 0;
+
+	if (total_delta < ADAPTIVE_LO_PKT_THRESH) {
+		if (pUmDevice->rx_curr_coalesce_frames !=
+			ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES) {
+
+			if (!bcm5700_trylock(pUmDevice, &flags))
+				return 0;
+
+			adapt = 1;
+
+			pUmDevice->rx_curr_coalesce_frames =
+				ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES;
+			pUmDevice->rx_curr_coalesce_ticks =
+				ADAPTIVE_LO_RX_COALESCING_TICKS;
+			pUmDevice->tx_curr_coalesce_frames =
+				ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES;
+			pUmDevice->rx_curr_coalesce_frames_intr =
+				ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES_DURING_INT;
+
+		}
+	}
+	else if (total_delta < ADAPTIVE_HI_PKT_THRESH) {
+		if (pUmDevice->rx_curr_coalesce_frames !=
+			DEFAULT_RX_MAX_COALESCED_FRAMES) {
+
+			if (!bcm5700_trylock(pUmDevice, &flags))
+				return 0;
+
+			adapt = 1;
+
+			pUmDevice->rx_curr_coalesce_frames = 
+				DEFAULT_RX_MAX_COALESCED_FRAMES;
+			pUmDevice->rx_curr_coalesce_ticks =
+				DEFAULT_RX_COALESCING_TICKS;
+			pUmDevice->tx_curr_coalesce_frames = 
+				DEFAULT_TX_MAX_COALESCED_FRAMES;
+			pUmDevice->rx_curr_coalesce_frames_intr =
+				DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT;
+
+		}
+	}
+	else {
+		if (pUmDevice->rx_curr_coalesce_frames !=
+			ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES) {
+
+			if (!bcm5700_trylock(pUmDevice, &flags))
+				return 0;
+
+			adapt = 1;
+
+			pUmDevice->rx_curr_coalesce_frames = 
+				ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES;
+			pUmDevice->rx_curr_coalesce_ticks =
+				ADAPTIVE_HI_RX_COALESCING_TICKS;
+			pUmDevice->tx_curr_coalesce_frames = 
+				ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES;
+			pUmDevice->rx_curr_coalesce_frames_intr =
+				ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES_DURING_INT;
+
+		}
+	}
+	if (adapt) {
+    		REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames,
+			pUmDevice->rx_curr_coalesce_frames); 
+
+		REG_WR(pDevice, HostCoalesce.RxCoalescingTicks,
+			pUmDevice->rx_curr_coalesce_ticks);
+
+		REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames,
+			pUmDevice->tx_curr_coalesce_frames); 
+
+		REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt,
+			pUmDevice->rx_curr_coalesce_frames_intr);
+
+		bcm5700_unlock(pUmDevice, flags);
+	}
+	return 0;
+}
+#endif
+
+STATIC void
+bcm5700_reset(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	unsigned long flags;
+
+	netif_stop_queue(dev);
+	bcm5700_intr_off(pUmDevice);
+	flags = bcm5700_phy_lock(pUmDevice);
+	LM_ResetAdapter(pDevice);	
+	if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
+		LM_SetMacAddress(pDevice, dev->dev_addr);
+	}
+	bcm5700_phy_unlock(pUmDevice, flags);
+	atomic_set(&pUmDevice->intr_sem, 1);
+	bcm5700_intr_on(pUmDevice);
+	netif_wake_queue(dev);
+}
+
+#ifdef BCM_VLAN
+STATIC void
+bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	bcm5700_intr_off(pUmDevice);
+	pUmDevice->vlgrp = vlgrp;
+	if (vlgrp && (pDevice->ReceiveMask & LM_KEEP_VLAN_TAG)) {
+		LM_SetReceiveMask(pDevice,
+			pDevice->ReceiveMask & ~LM_KEEP_VLAN_TAG);
+	}
+	else if (!vlgrp && !(pDevice->ReceiveMask & LM_KEEP_VLAN_TAG)) {
+		LM_SetReceiveMask(pDevice,
+			pDevice->ReceiveMask | LM_KEEP_VLAN_TAG);
+	}
+	bcm5700_intr_on(pUmDevice);
+}
+
+STATIC void
+bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+
+	bcm5700_intr_off(pUmDevice);
+	if (pUmDevice->vlgrp) {
+		pUmDevice->vlgrp->vlan_devices[vid] = NULL;
+	}
+	bcm5700_intr_on(pUmDevice);
+}
+#endif
+
+STATIC int
+bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+	unsigned long flags;
+	int frag_no;
+#ifdef NICE_SUPPORT
+	vlan_tag_t *vlan_tag;
+#endif
+#ifdef BCM_TSO
+	LM_UINT32 mss;
+	uint16_t ip_tcp_len, tcp_opt_len, last_seg_len, tcp_seg_flags;
+#endif
+
+	if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
+		!pDevice->InitDone || pUmDevice->suspended)
+	{
+		dev_kfree_skb(skb);
+		return 0;
+	}
+	
+#if (LINUX_VERSION_CODE < 0x02032b)
+	if (test_and_set_bit(0, &dev->tbusy)) {
+		return 1;
+	}
+#endif
+
+	if (pUmDevice->do_global_lock && pUmDevice->interrupt) {
+		netif_stop_queue(dev);
+		pUmDevice->tx_queued = 1;
+		if (!pUmDevice->interrupt) {
+			netif_wake_queue(dev);
+			pUmDevice->tx_queued = 0;
+		}
+		return 1;
+	}
+
+	pPacket = (PLM_PACKET)
+		QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
+	if (pPacket == 0) {
+		netif_stop_queue(dev);
+		pUmDevice->tx_full = 1;
+		if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container)) {
+			netif_wake_queue(dev);
+			pUmDevice->tx_full = 0;
+		}
+		return 1;
+	}
+	pUmPacket = (PUM_PACKET) pPacket;
+	pUmPacket->skbuff = skb;
+
+	if (skb->ip_summed == CHECKSUM_HW) {
+		pPacket->Flags = SND_BD_FLAG_TCP_UDP_CKSUM;
+#if TIGON3_DEBUG
+		pUmDevice->tx_chksum_count++;
+#endif
+	}
+	else {
+		pPacket->Flags = 0;
+	}
+#if MAX_SKB_FRAGS
+	frag_no = skb_shinfo(skb)->nr_frags;
+#else
+	frag_no = 0;
+#endif
+	if (atomic_read(&pDevice->SendBdLeft) < (frag_no + 1)) {
+		netif_stop_queue(dev);
+		pUmDevice->tx_full = 1;
+		QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+		if (atomic_read(&pDevice->SendBdLeft) >= (frag_no + 1)) {
+			netif_wake_queue(dev);
+			pUmDevice->tx_full = 0;
+		}
+		return 1;
+	}
+
+	pPacket->u.Tx.FragCount = frag_no + 1;
+#if TIGON3_DEBUG
+	if (pPacket->u.Tx.FragCount > 1)
+		pUmDevice->tx_zc_count++;
+#endif
+
+#ifdef BCM_VLAN
+	if (pUmDevice->vlgrp && vlan_tx_tag_present(skb)) {
+		pPacket->VlanTag = vlan_tx_tag_get(skb);
+		pPacket->Flags |= SND_BD_FLAG_VLAN_TAG;
+	}
+#endif
+#ifdef NICE_SUPPORT
+	vlan_tag = (vlan_tag_t *) &skb->cb[0];
+	if (vlan_tag->signature == 0x5555) {
+		pPacket->VlanTag = vlan_tag->tag;
+		pPacket->Flags |= SND_BD_FLAG_VLAN_TAG;
+		vlan_tag->signature = 0;
+	}
+#endif
+
+#ifdef BCM_TSO
+	if ((mss = (LM_UINT32) skb_shinfo(skb)->tso_size) &&
+		(skb->len > pDevice->TxMtu)) {
+
+		pUmDevice->tso_pkt_count++;
+
+		pPacket->Flags |= SND_BD_FLAG_CPU_PRE_DMA |
+			SND_BD_FLAG_CPU_POST_DMA;
+
+		tcp_opt_len = 0;
+		if (skb->h.th->doff > 5) {
+			tcp_opt_len = (skb->h.th->doff - 5) << 2;
+		}
+		ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr);
+		skb->nh.iph->check = 0;
+		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
+			skb->nh.iph->daddr, 0, IPPROTO_TCP, 0);
+
+		skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
+		tcp_seg_flags = 0;
+		if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) {
+			if (tcp_opt_len || (skb->nh.iph->ihl > 5)) {
+				tcp_seg_flags =
+					((skb->nh.iph->ihl - 5) +
+					(tcp_opt_len >> 2)) << 11;
+			}
+		}
+		else {
+			last_seg_len = (skb->len - ip_tcp_len - tcp_opt_len -
+				14) % mss;
+			mss += tcp_opt_len;
+		}
+		pPacket->u.Tx.MaxSegmentSize = mss | tcp_seg_flags;
+	}
+	else
+	{
+		pPacket->u.Tx.MaxSegmentSize = 0;
+	}
+#endif
+	flags = bcm5700_lock(pUmDevice);
+	LM_SendPacket(pDevice, pPacket);
+	bcm5700_unlock(pUmDevice, flags);
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+	netif_wake_queue(dev);
+#endif
+	dev->trans_start = jiffies;
+	return 0;
+}
+
+
+STATIC void
+bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)dev_instance;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	LM_UINT32 oldtag, newtag;
+	int i;
+#ifdef BCM_TASKLET
+	int repl_buf_count;
+#endif
+
+	if (!pDevice->InitDone)
+		return;
+
+	if (atomic_read(&pUmDevice->intr_sem))
+		return;
+
+	bcm5700_intr_lock(pUmDevice);
+	if (test_and_set_bit(0, (void*)&pUmDevice->interrupt)) {
+		printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by "
+			   "processor %d.\n",
+			   dev->name, hard_smp_processor_id());
+		bcm5700_intr_unlock(pUmDevice);
+		return;
+	}
+
+	if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
+#ifdef NICE_SUPPORT
+		pUmDevice->adapter_just_inited || pUmDevice->intr_test)
+#else
+		pUmDevice->adapter_just_inited)
+#endif
+	{
+
+#ifdef NICE_SUPPORT
+		if (pUmDevice->intr_test) {
+			if (!(REG_RD(pDevice, PciCfg.PciState) &
+				T3_PCI_STATE_INTERRUPT_NOT_ACTIVE)) {
+				pUmDevice->intr_test_result = 1;
+			}
+			pUmDevice->intr_test = 0;
+		}
+#endif
+		if (pDevice->UseTaggedStatus) {
+			MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+			oldtag = pDevice->pStatusBlkVirt->StatusTag;
+
+			for (i = 0; ; i++) {
+   				pDevice->pStatusBlkVirt->Status &=
+					~STATUS_BLOCK_UPDATED;
+
+				LM_ServiceInterrupts(pDevice);
+				newtag = pDevice->pStatusBlkVirt->StatusTag;
+				if ((newtag == oldtag) || (i > 50)) {
+					MB_REG_WR(pDevice,
+						Mailbox.Interrupt[0].Low,
+						oldtag << 24);
+					pDevice->LastTag = oldtag;
+					if (pDevice->UndiFix) {
+						REG_WR(pDevice, Grc.LocalCtrl,
+						pDevice->GrcLocalCtrl | 0x2);
+					}
+					break;
+				}
+				oldtag = newtag;
+			}
+		}
+		else {
+			do {
+				uint dummy;
+
+				MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+   				pDevice->pStatusBlkVirt->Status &=
+					~STATUS_BLOCK_UPDATED;
+				LM_ServiceInterrupts(pDevice);
+				MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+				dummy = MB_REG_RD(pDevice,
+					Mailbox.Interrupt[0].Low);
+			}
+			while (pDevice->pStatusBlkVirt->Status &
+				STATUS_BLOCK_UPDATED);
+			if (pDevice->UndiFix) {
+				REG_WR(pDevice, Grc.LocalCtrl,
+					pDevice->GrcLocalCtrl | 0x2);
+			}
+		}
+	}
+#ifdef BCM_TASKLET
+	repl_buf_count = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container);
+	if (((repl_buf_count > pUmDevice->rx_buf_repl_panic_thresh) ||
+		pDevice->QueueAgain) &&
+		(!test_and_set_bit(0, &pUmDevice->tasklet_busy))) {
+
+		replenish_rx_buffers(pUmDevice);
+		clear_bit(0, (void*)&pUmDevice->tasklet_busy);
+	}
+	else if ((repl_buf_count > pUmDevice->rx_buf_repl_thresh) &&
+		!pUmDevice->tasklet_pending) {
+
+		pUmDevice->tasklet_pending = 1;
+		tasklet_schedule(&pUmDevice->tasklet);
+	}
+#else
+	if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+		replenish_rx_buffers(pUmDevice);
+	}
+
+	if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container) ||
+		pDevice->QueueAgain) {
+
+		LM_QueueRxPackets(pDevice);
+	}
+#endif
+
+	clear_bit(0, (void*)&pUmDevice->interrupt);
+	bcm5700_intr_unlock(pUmDevice);
+	if (pUmDevice->tx_queued) {
+		pUmDevice->tx_queued = 0;
+		netif_wake_queue(dev);
+	}
+	return;
+}
+
+
+#ifdef BCM_TASKLET
+STATIC void
+bcm5700_tasklet(unsigned long data)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)data;
+
+	/* RH 7.2 Beta 3 tasklets are reentrant */
+	if (test_and_set_bit(0, &pUmDevice->tasklet_busy)) {
+		pUmDevice->tasklet_pending = 0;
+		return;
+	}
+
+	pUmDevice->tasklet_pending = 0;
+	replenish_rx_buffers(pUmDevice);
+	clear_bit(0, &pUmDevice->tasklet_busy);
+}
+#endif
+
+STATIC int
+bcm5700_close(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+	dev->start = 0;
+#endif
+	netif_stop_queue(dev);
+	pUmDevice->opened = 0;
+
+	if (tigon3_debug > 1)
+		printk(KERN_DEBUG "%s: Shutting down Tigon3\n",
+			   dev->name);
+
+#ifdef BCM_TASKLET
+//	tasklet_disable(&pUmDevice->tasklet);
+	tasklet_kill(&pUmDevice->tasklet);
+#endif
+	bcm5700_shutdown(pUmDevice);
+	del_timer(&pUmDevice->timer);
+
+	free_irq(dev->irq, dev);
+#if (LINUX_VERSION_CODE < 0x020300)
+	MOD_DEC_USE_COUNT;
+#endif
+	LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
+	bcm5700_freemem(dev);
+
+	return 0;
+}
+
+STATIC int
+bcm5700_freemem(struct net_device *dev)
+{
+	int i;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+
+	for (i = 0; i < pUmDevice->mem_list_num; i++) {
+		if (pUmDevice->mem_size_list[i] == 0) {
+			kfree(pUmDevice->mem_list[i]);
+		}
+		else {
+			pci_free_consistent(pUmDevice->pdev,
+				(size_t) pUmDevice->mem_size_list[i],
+				pUmDevice->mem_list[i],
+				pUmDevice->dma_list[i]);
+		}
+	}
+	pUmDevice->mem_list_num = 0;
+	return 0;
+}
+
+unsigned long
+bcm5700_crc_count(PUM_DEVICE_BLOCK pUmDevice)
+{
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+	LM_UINT32 Value32;
+	PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
+	unsigned long flags;
+
+	if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+		T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) &&
+		!pDevice->EnableTbi) { 
+
+		if (!pUmDevice->opened || !pDevice->InitDone ||
+			pUmDevice->adapter_just_inited) {
+
+			return 0;
+		}
+
+		/* regulate MDIO access during run time */
+		if (pUmDevice->crc_counter_expiry > 0)
+			return pDevice->PhyCrcCount;
+
+		pUmDevice->crc_counter_expiry = (5 * HZ) /
+			pUmDevice->timer_interval;
+
+		flags = bcm5700_phy_lock(pUmDevice);
+		LM_ReadPhy(pDevice, 0x1e, &Value32);
+		if ((Value32 & 0x8000) == 0)
+			LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
+		LM_ReadPhy(pDevice, 0x14, &Value32);
+		bcm5700_phy_unlock(pUmDevice, flags);
+		/* Sometimes data on the MDIO bus can be corrupted */
+		if (Value32 != 0xffff)
+			pDevice->PhyCrcCount += Value32;
+		return pDevice->PhyCrcCount;
+	}
+	else if (pStats == 0) {
+		return 0;
+	}
+	else {
+		return (MM_GETSTATS(pStats->dot3StatsFCSErrors));
+	}
+}
+
+STATIC struct net_device_stats *
+bcm5700_get_stats(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
+	struct net_device_stats *p_netstats = &pUmDevice->stats;
+
+	if (pStats == 0)
+		return p_netstats;
+
+	/* Get stats from LM */
+	p_netstats->rx_packets =
+		MM_GETSTATS(pStats->ifHCInUcastPkts) +
+		MM_GETSTATS(pStats->ifHCInMulticastPkts) +
+		MM_GETSTATS(pStats->ifHCInBroadcastPkts);
+	p_netstats->tx_packets = 
+		MM_GETSTATS(pStats->ifHCOutUcastPkts) +
+		MM_GETSTATS(pStats->ifHCOutMulticastPkts) +
+		MM_GETSTATS(pStats->ifHCOutBroadcastPkts);
+	p_netstats->rx_bytes = MM_GETSTATS(pStats->ifHCInOctets);
+	p_netstats->tx_bytes = MM_GETSTATS(pStats->ifHCOutOctets);
+	p_netstats->tx_errors =
+		MM_GETSTATS(pStats->dot3StatsInternalMacTransmitErrors) +
+		MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors) +
+		MM_GETSTATS(pStats->ifOutDiscards) +
+		MM_GETSTATS(pStats->ifOutErrors);
+	p_netstats->multicast = MM_GETSTATS(pStats->ifHCInMulticastPkts);
+	p_netstats->collisions = MM_GETSTATS(pStats->etherStatsCollisions);
+	p_netstats->rx_length_errors =
+		MM_GETSTATS(pStats->dot3StatsFramesTooLong) +
+		MM_GETSTATS(pStats->etherStatsUndersizePkts);
+	p_netstats->rx_over_errors = MM_GETSTATS(pStats->nicNoMoreRxBDs);
+	p_netstats->rx_frame_errors =
+		MM_GETSTATS(pStats->dot3StatsAlignmentErrors);
+	p_netstats->rx_crc_errors = bcm5700_crc_count(pUmDevice);
+	p_netstats->rx_errors =
+		p_netstats->rx_length_errors +
+		p_netstats->rx_over_errors +
+		p_netstats->rx_frame_errors +
+		p_netstats->rx_crc_errors +
+		MM_GETSTATS(pStats->etherStatsFragments) +
+		MM_GETSTATS(pStats->etherStatsJabbers);
+	
+	p_netstats->tx_aborted_errors = MM_GETSTATS(pStats->ifOutDiscards);
+	p_netstats->tx_carrier_errors =
+		MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors);
+
+	return p_netstats;
+}
+
+#ifdef SIOCETHTOOL
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct ethtool_cmd ethcmd;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+		
+	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+		return -EFAULT;
+
+        switch (ethcmd.cmd) {
+#ifdef ETHTOOL_GDRVINFO
+        case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+
+		strcpy(info.driver,  bcm5700_driver);
+#if INCLUDE_5701_AX_FIX
+		if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0) {
+			extern int t3FwReleaseMajor;
+			extern int t3FwReleaseMinor;
+			extern int t3FwReleaseFix;
+
+			sprintf(info.fw_version, "%i.%i.%i",
+				t3FwReleaseMajor, t3FwReleaseMinor, 
+				t3FwReleaseFix);
+		}
+#endif
+		strcpy(info.version, bcm5700_version);
+		strcpy(info.bus_info, pUmDevice->pdev->slot_name);
+#ifdef ETHTOOL_GEEPROM
+		if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+			T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+			BCM_EEDUMP_LEN(&info, SEEPROM_CHIP_SIZE);
+		}
+		else {
+			BCM_EEDUMP_LEN(&info, NVRAM_ADDRESS_MASK + 1);
+		}
+#endif
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+#endif
+        case ETHTOOL_GSET: {
+		if (pDevice->EnableTbi) {
+			ethcmd.supported =
+				(SUPPORTED_1000baseT_Full |
+				SUPPORTED_Autoneg);
+			ethcmd.supported |= SUPPORTED_FIBRE;
+			ethcmd.port = PORT_FIBRE;
+		}
+		else {
+			ethcmd.supported =
+				(SUPPORTED_10baseT_Half |
+				SUPPORTED_10baseT_Full |
+				SUPPORTED_100baseT_Half |
+				SUPPORTED_100baseT_Full |
+				SUPPORTED_1000baseT_Half |
+				SUPPORTED_1000baseT_Full |
+				SUPPORTED_Autoneg);
+			ethcmd.supported |= SUPPORTED_TP;
+			ethcmd.port = PORT_TP;
+		}
+
+		ethcmd.transceiver = XCVR_INTERNAL;
+		ethcmd.phy_address = 0;
+
+		if (pUmDevice->line_speed == 1000)
+			ethcmd.speed = SPEED_1000;
+		else if (pUmDevice->line_speed == 100)
+			ethcmd.speed = SPEED_100;
+		else if (pUmDevice->line_speed == 10)
+			ethcmd.speed = SPEED_10;
+		else
+			ethcmd.speed = 0;
+
+		if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+			ethcmd.duplex = DUPLEX_FULL;
+		else
+			ethcmd.duplex = DUPLEX_HALF;
+
+		if (pDevice->DisableAutoNeg == FALSE) {
+			ethcmd.autoneg = AUTONEG_ENABLE;
+			ethcmd.advertising = ADVERTISED_Autoneg;
+			if (pDevice->EnableTbi) {
+				ethcmd.advertising |=
+					ADVERTISED_1000baseT_Full |
+					ADVERTISED_FIBRE;
+			}
+			else {
+				ethcmd.advertising |=
+					ADVERTISED_TP;
+				if (pDevice->advertising &
+					PHY_AN_AD_10BASET_HALF) {
+
+					ethcmd.advertising |=
+						ADVERTISED_10baseT_Half;
+				}
+				if (pDevice->advertising &
+					PHY_AN_AD_10BASET_FULL) {
+
+					ethcmd.advertising |=
+						ADVERTISED_10baseT_Full;
+				}
+				if (pDevice->advertising &
+					PHY_AN_AD_100BASETX_HALF) {
+
+					ethcmd.advertising |=
+						ADVERTISED_100baseT_Half;
+				}
+				if (pDevice->advertising &
+					PHY_AN_AD_100BASETX_FULL) {
+
+					ethcmd.advertising |=
+						ADVERTISED_100baseT_Full;
+				}
+				if (pDevice->advertising1000 &
+					BCM540X_AN_AD_1000BASET_HALF) {
+
+					ethcmd.advertising |=
+						ADVERTISED_1000baseT_Half;
+				}
+				if (pDevice->advertising1000 &
+					BCM540X_AN_AD_1000BASET_FULL) {
+
+					ethcmd.advertising |=
+						ADVERTISED_1000baseT_Full;
+				}
+			}
+		}
+		else {
+			ethcmd.autoneg = AUTONEG_DISABLE;
+			ethcmd.advertising = 0;
+		}
+
+		ethcmd.maxtxpkt = pDevice->TxMaxCoalescedFrames;
+		ethcmd.maxrxpkt = pDevice->RxMaxCoalescedFrames;
+
+		if(copy_to_user(useraddr, &ethcmd, sizeof(ethcmd)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SSET: {
+		unsigned long flags;
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (ethcmd.autoneg == AUTONEG_ENABLE) {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+			pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+			pDevice->DisableAutoNeg = FALSE;
+		}
+		else {
+			if (ethcmd.speed == SPEED_1000) {
+				if (!pDevice->EnableTbi || pDevice->No1000)
+					return -EINVAL;
+
+				pDevice->RequestedLineSpeed =
+					LM_LINE_SPEED_1000MBPS;
+
+				pDevice->RequestedDuplexMode =
+					LM_DUPLEX_MODE_FULL;
+			}
+			else if (ethcmd.speed == SPEED_100) {
+				pDevice->RequestedLineSpeed =
+					LM_LINE_SPEED_100MBPS;
+			}
+			else if (ethcmd.speed == SPEED_10) {
+				pDevice->RequestedLineSpeed =
+					LM_LINE_SPEED_10MBPS;
+			}
+			else {
+				return -EINVAL;
+			}
+
+			pDevice->DisableAutoNeg = TRUE;
+			if (ethcmd.duplex == DUPLEX_FULL) {
+				pDevice->RequestedDuplexMode =
+					LM_DUPLEX_MODE_FULL;
+			}
+			else {
+				pDevice->RequestedDuplexMode =
+					LM_DUPLEX_MODE_HALF;
+			}
+		}
+		flags = bcm5700_phy_lock(pUmDevice);
+		LM_SetupPhy(pDevice);
+		bcm5700_phy_unlock(pUmDevice, flags);
+		return 0;
+	}
+#ifdef ETHTOOL_GWOL
+#ifdef BCM_WOL
+	case ETHTOOL_GWOL: {
+		struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
+
+		if (pDevice->EnableTbi && !pDevice->FiberWolCapable) {
+			wol.supported = 0;
+			wol.wolopts = 0;
+		}
+		else {
+			wol.supported = WAKE_MAGIC;
+			if (pDevice->WakeUpMode == LM_WAKE_UP_MODE_MAGIC_PACKET)
+			{
+				wol.wolopts = WAKE_MAGIC;
+			}
+			else {
+				wol.wolopts = 0;
+			}
+		}
+		if (copy_to_user(useraddr, &wol, sizeof(wol)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SWOL: {
+		struct ethtool_wolinfo wol;
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&wol, useraddr, sizeof(wol)))
+			return -EFAULT;
+		if (pDevice->EnableTbi && !pDevice->FiberWolCapable &&
+			wol.wolopts) {
+			return -EINVAL;
+		}
+		
+		if ((wol.wolopts & ~WAKE_MAGIC) != 0) {
+			return -EINVAL;
+		}
+		if (wol.wolopts & WAKE_MAGIC) {
+			pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
+			pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
+		}
+		else {
+			pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
+			pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE;
+		}
+		return 0;
+        }
+#endif
+#endif
+#ifdef ETHTOOL_GLINK
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+
+		if (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)
+			edata.data =  1;
+		else
+			edata.data =  0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+#endif
+#ifdef ETHTOOL_NWAY_RST
+	case ETHTOOL_NWAY_RST: {
+		LM_UINT32 phyctrl;
+		unsigned long flags;
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (pDevice->DisableAutoNeg) {
+			return -EINVAL;
+		}
+		flags = bcm5700_phy_lock(pUmDevice);
+		if (pDevice->EnableTbi) {
+			LM_SetupPhy(pDevice);
+		}
+		else {
+			LM_ReadPhy(pDevice, PHY_CTRL_REG, &phyctrl);
+			LM_WritePhy(pDevice, PHY_CTRL_REG, phyctrl |
+				PHY_CTRL_AUTO_NEG_ENABLE |
+				PHY_CTRL_RESTART_AUTO_NEG);
+		}
+		bcm5700_phy_unlock(pUmDevice, flags);
+		return 0;
+	}
+#endif
+#ifdef ETHTOOL_GEEPROM
+	case ETHTOOL_GEEPROM: {
+		struct ethtool_eeprom eeprom;
+		LM_UINT32 *buf = 0;
+		LM_UINT32 buf1[64/4];
+		int i, j, offset, len;
+
+		if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+			return -EFAULT;
+		
+		if (eeprom.offset >= 0x20000)
+			return -EFAULT;
+
+		if (eeprom.len > 64) {
+			buf = kmalloc(eeprom.len, GFP_KERNEL);
+			if (!buf)
+				return -EFAULT;
+		}
+		else {
+			buf = buf1;
+		}
+		useraddr += offsetof(struct ethtool_eeprom, data);
+
+		offset = eeprom.offset;
+		len = eeprom.len;
+		if (offset & 3) {
+			offset &= 0xfffffffc;
+			len += (offset & 3);
+		}
+		len = (len + 3) & 0xfffffffc;
+		for (i = 0, j = 0; j < len; i++, j += 4) {
+			if (LM_NvramRead(pDevice, offset + j, buf + i) !=
+				LM_STATUS_SUCCESS) {
+				break;
+			}
+		}
+		if (j >= len) {
+			buf += (eeprom.offset & 3);
+			i = copy_to_user(useraddr, buf, eeprom.len);
+		}
+		if (eeprom.len > 64) {
+			kfree(buf);
+		}
+		if (i)
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SEEPROM: {
+		struct ethtool_eeprom eeprom;
+		LM_UINT32 buf[64/4];
+		int i, offset, len;
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+			return -EFAULT;
+		
+		if ((eeprom.offset & 3) || (eeprom.offset >= 0x10000))
+			return -EFAULT;
+
+		if (((eeprom.offset + eeprom.len) >= 0x10000) ||
+			(eeprom.len & 3)) {
+
+			eeprom.len = 0x10000 - eeprom.offset;
+		}
+
+		useraddr += offsetof(struct ethtool_eeprom, data);
+
+		len = eeprom.len;
+		offset = eeprom.offset;
+		for (; len > 0; ) {
+			if (len < 64)
+				i = len;
+			else
+				i = 64;
+			if (copy_from_user(&buf, useraddr, i))
+				return -EFAULT;
+
+			if (LM_NvramWriteBlock(pDevice, offset, buf, i/4) !=
+				LM_STATUS_SUCCESS) {
+				return -EFAULT;
+			}
+			len -= i;
+			offset += i;
+			useraddr += i;
+		}
+		return 0;
+	}
+#endif
+
+	}
+	
+	return -EOPNOTSUPP;
+}
+#endif
+
+/* Provide ioctl() calls to examine the MII xcvr state. */
+STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	u16 *data = (u16 *)&rq->ifr_data;
+	u32 value;
+	unsigned long flags;
+
+	switch(cmd) {
+#ifdef SIOCGMIIPHY
+	case SIOCGMIIPHY:
+#endif
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		data[0] = pDevice->PhyAddr;
+
+#ifdef SIOCGMIIREG
+	case SIOCGMIIREG:
+#endif
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		flags = bcm5700_phy_lock(pUmDevice);
+		LM_ReadPhy(pDevice, data[1] & 0x1f, (LM_UINT32 *) &value);
+		bcm5700_phy_unlock(pUmDevice, flags);
+		data[3] = value & 0xffff;
+		return 0;
+
+#ifdef SIOCSMIIREG
+	case SIOCSMIIREG:
+#endif
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		flags = bcm5700_phy_lock(pUmDevice);
+		LM_WritePhy(pDevice, data[1] & 0x1f, data[2]);
+		bcm5700_phy_unlock(pUmDevice, flags);
+		return 0;
+
+#ifdef NICE_SUPPORT
+	case SIOCNICE:
+	{
+		struct nice_req* nrq;
+
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		nrq = (struct nice_req*)&rq->ifr_ifru;
+		if( nrq->cmd == NICE_CMD_QUERY_SUPPORT ) {
+			nrq->nrq_magic = NICE_DEVICE_MAGIC;
+			nrq->nrq_support_rx = 1;
+			nrq->nrq_support_vlan = 1;
+			nrq->nrq_support_get_speed = 1;
+			return 0;
+		}
+		else if( nrq->cmd == NICE_CMD_SET_RX ) {
+			pUmDevice->nice_rx = nrq->nrq_rx;
+			pUmDevice->nice_ctx = nrq->nrq_ctx;
+			if (nrq->nrq_rx && (pDevice->ReceiveMask &
+				LM_KEEP_VLAN_TAG)) {
+				LM_SetReceiveMask(pDevice,
+					pDevice->ReceiveMask &
+					~LM_KEEP_VLAN_TAG);
+			}
+			else if (!nrq->nrq_rx && !(pDevice->ReceiveMask &
+				LM_KEEP_VLAN_TAG)) {
+				LM_SetReceiveMask(pDevice,
+					pDevice->ReceiveMask |
+					LM_KEEP_VLAN_TAG);
+			}
+			return 0;
+		}
+		else if( nrq->cmd == NICE_CMD_GET_RX ) {
+			nrq->nrq_rx = pUmDevice->nice_rx;
+			nrq->nrq_ctx = pUmDevice->nice_ctx;
+			return 0;
+		}
+		else if( nrq->cmd == NICE_CMD_GET_SPEED ) {
+			nrq->nrq_speed = pUmDevice->line_speed;
+			return 0;
+		}
+		else {
+			int j;
+
+			if (!pUmDevice->opened)
+				return -EINVAL;
+
+			switch (nrq->cmd) {
+			case NICE_CMD_BLINK_LED:
+				return LM_BlinkLED(pDevice,
+					nrq->nrq_blink_time);
+
+			case NICE_CMD_DIAG_SUSPEND:
+				bcm5700_intr_off(pUmDevice);
+				pUmDevice->suspended = 1;
+				netif_carrier_off(dev);
+				netif_stop_queue(dev);
+				LM_Abort(pDevice);
+				LM_ResetChip(pDevice);
+				return 0;
+
+			case NICE_CMD_DIAG_RESUME:
+				if (pUmDevice->suspended) {
+					pUmDevice->suspended = 0;
+					bcm5700_reset(dev);
+				}
+				return 0;
+
+			case NICE_CMD_REG_READ:
+				if (nrq->nrq_offset >= 0x10000) {
+					nrq->nrq_data = LM_RegRdInd(pDevice,
+						nrq->nrq_offset);
+				}
+				else {
+					nrq->nrq_data = LM_RegRd(pDevice,
+						nrq->nrq_offset);
+				}
+				return 0;
+
+			case NICE_CMD_REG_WRITE:
+				if (nrq->nrq_offset >= 0x10000) {
+					LM_RegWrInd(pDevice, nrq->nrq_offset,
+						nrq->nrq_data);
+				}
+				else {
+					LM_RegWr(pDevice, nrq->nrq_offset,
+						nrq->nrq_data, FALSE);
+				}
+				return 0;
+
+			case NICE_CMD_MEM_READ:
+				nrq->nrq_data = LM_MemRdInd(pDevice,
+					nrq->nrq_offset);
+				return 0;
+
+			case NICE_CMD_MEM_WRITE:
+				LM_MemWrInd(pDevice, nrq->nrq_offset,
+					nrq->nrq_data);
+				return 0;
+
+			case NICE_CMD_ENABLE_MAC_LOOPBACK:
+				if (pDevice->PhyLoopBack)
+					return -EINVAL;
+
+				flags = bcm5700_phy_lock(pUmDevice);
+				LM_EnableMacLoopBack(pDevice);
+				bcm5700_phy_unlock(pUmDevice, flags);
+				return 0;
+
+			case NICE_CMD_DISABLE_MAC_LOOPBACK:
+				if (!pDevice->MacLoopBack)
+					return -EINVAL;
+
+				flags = bcm5700_phy_lock(pUmDevice);
+				LM_DisableMacLoopBack(pDevice);
+				bcm5700_phy_unlock(pUmDevice, flags);
+				return 0;
+
+			case NICE_CMD_ENABLE_PHY_LOOPBACK:
+				if (pDevice->MacLoopBack || pDevice->EnableTbi)
+					return -EINVAL;
+
+				flags = bcm5700_phy_lock(pUmDevice);
+				LM_EnablePhyLoopBack(pDevice);
+				bcm5700_phy_unlock(pUmDevice, flags);
+				return 0;
+
+			case NICE_CMD_DISABLE_PHY_LOOPBACK:
+				if (!pDevice->PhyLoopBack)
+					return -EINVAL;
+
+				flags = bcm5700_phy_lock(pUmDevice);
+				LM_DisablePhyLoopBack(pDevice);
+				bcm5700_phy_unlock(pUmDevice, flags);
+				return 0;
+
+			case NICE_CMD_INTERRUPT_TEST:
+				pUmDevice->intr_test_result = 0;
+				pUmDevice->intr_test = 1;
+				REG_WR(pDevice, Grc.LocalCtrl,
+					pDevice->GrcLocalCtrl |
+					GRC_MISC_LOCAL_CTRL_SET_INT);
+				for (j = 0; j < 100; j++) {
+					if (pUmDevice->intr_test_result)
+						break;
+					MM_Wait(10);
+				}
+				nrq->nrq_intr_test_result =
+					pUmDevice->intr_test_result;
+				return 0;
+			}
+		}
+		break;
+	}
+#endif /* NICE_SUPPORT */
+#ifdef SIOCETHTOOL
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+#endif
+	default:
+		return -EOPNOTSUPP;
+	}
+	return -EOPNOTSUPP;
+}
+
+STATIC void bcm5700_set_rx_mode(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	int i;
+	struct dev_mc_list *mclist;
+
+	LM_MulticastClear(pDevice);
+	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+			 i++, mclist = mclist->next) {
+		LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr);
+	}
+	if (dev->flags & IFF_ALLMULTI) {
+		if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) {
+			LM_SetReceiveMask(pDevice,
+				pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
+		}
+	}
+	else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) {
+		LM_SetReceiveMask(pDevice,
+			pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST);
+	}
+	if (dev->flags & IFF_PROMISC) {
+		if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) {
+			LM_SetReceiveMask(pDevice,
+				pDevice->ReceiveMask | LM_PROMISCUOUS_MODE);
+		}
+	}
+	else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) {
+		LM_SetReceiveMask(pDevice,
+			pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE);
+	}
+}
+
+/*
+ * Set the hardware MAC address.
+ */
+STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr=p;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) dev->priv;
+	UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+
+	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+	if (pUmDevice->opened)
+		LM_SetMacAddress(pDevice, dev->dev_addr);
+	return 0;
+}
+
+STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu)
+{
+	int pkt_size = new_mtu + ETHERNET_PACKET_HEADER_SIZE;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+	unsigned long flags;
+	int reinit = 0;
+
+	if ((pkt_size < MIN_ETHERNET_PACKET_SIZE_NO_CRC) || 
+		(pkt_size > MAX_ETHERNET_JUMBO_PACKET_SIZE_NO_CRC)) {
+
+		return -EINVAL;
+	}
+	if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) &&
+		(pkt_size > MAX_ETHERNET_PACKET_SIZE_NO_CRC)) {
+
+		return -EINVAL;
+	}
+	if (pUmDevice->suspended)
+		return -EAGAIN;
+
+	if (pUmDevice->opened && (new_mtu != dev->mtu) &&
+		(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)) {
+		reinit = 1;
+	}
+
+	flags = bcm5700_phy_lock(pUmDevice);
+	if (reinit) {
+		netif_stop_queue(dev);
+		bcm5700_shutdown(pUmDevice);
+		bcm5700_freemem(dev);
+	}
+
+	dev->mtu = new_mtu;
+	if (pkt_size < MAX_ETHERNET_PACKET_SIZE_NO_CRC) {
+		pDevice->RxMtu = pDevice->TxMtu =
+			MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+	}
+	else {
+		pDevice->RxMtu = pDevice->TxMtu = pkt_size;
+	}
+
+	if (dev->mtu <= 1514) {
+		pDevice->RxJumboDescCnt = 0;
+	}
+	else {
+		pDevice->RxJumboDescCnt =
+			rx_jumbo_desc_cnt[pUmDevice->index];
+	}
+	pDevice->RxPacketDescCnt = pDevice->RxJumboDescCnt +
+		pDevice->RxStdDescCnt;
+
+	pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ +
+		COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK;
+
+	if (reinit) {
+		LM_InitializeAdapter(pDevice);
+		if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
+			LM_SetMacAddress(pDevice, dev->dev_addr);
+		}
+		netif_start_queue(dev);
+		bcm5700_intr_on(pUmDevice);
+	}
+	bcm5700_phy_unlock(pUmDevice, flags);
+
+	return 0;
+}
+
+
+#if (LINUX_VERSION_CODE < 0x020300)
+
+int
+bcm5700_probe(struct net_device *dev)
+{
+	int cards_found = 0;
+	struct pci_dev *pdev = NULL;
+	struct pci_device_id *pci_tbl;
+	u16 ssvid, ssid;
+
+	if ( ! pci_present())
+		return -ENODEV;
+
+	pci_tbl = bcm5700_pci_tbl;
+	while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
+		int idx;
+
+		pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &ssvid);
+		pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &ssid);
+		for (idx = 0; pci_tbl[idx].vendor; idx++) {
+			if ((pci_tbl[idx].vendor == PCI_ANY_ID ||
+				pci_tbl[idx].vendor == pdev->vendor) &&
+				(pci_tbl[idx].device == PCI_ANY_ID ||
+				pci_tbl[idx].device == pdev->device) &&
+				(pci_tbl[idx].subvendor == PCI_ANY_ID ||
+				pci_tbl[idx].subvendor == ssvid) &&
+				(pci_tbl[idx].subdevice == PCI_ANY_ID ||
+				pci_tbl[idx].subdevice == ssid))
+			{
+
+				break;
+			}
+		}
+		if (pci_tbl[idx].vendor == 0)
+			continue;
+
+
+		if (bcm5700_init_one(pdev, &pci_tbl[idx]) == 0)
+			cards_found++;
+	}
+
+	return cards_found ? 0 : -ENODEV;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return bcm5700_probe(NULL);
+}
+
+void cleanup_module(void)
+{
+	struct net_device *next_dev;
+	PUM_DEVICE_BLOCK pUmDevice;
+
+	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	while (root_tigon3_dev) {
+		pUmDevice = (PUM_DEVICE_BLOCK)root_tigon3_dev->priv;
+#ifdef BCM_PROC_FS
+		bcm5700_proc_remove_dev(root_tigon3_dev); 
+#endif
+		next_dev = pUmDevice->next_module;
+		unregister_netdev(root_tigon3_dev);
+		if (pUmDevice->lm_dev.pMappedMemBase)
+			iounmap(pUmDevice->lm_dev.pMappedMemBase);
+		kfree(root_tigon3_dev);
+		root_tigon3_dev = next_dev;
+	}
+}
+
+#endif  /* MODULE */
+#else	/* LINUX_VERSION_CODE < 0x020300 */
+
+#if (LINUX_VERSION_CODE >= 0x020406)
+static int bcm5700_suspend (struct pci_dev *pdev, u32 state)
+#else
+static void bcm5700_suspend (struct pci_dev *pdev)
+#endif
+{
+	struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (!netif_running(dev))
+#if (LINUX_VERSION_CODE >= 0x020406)
+		return 0;
+#else
+		return;
+#endif
+
+	netif_device_detach (dev);
+	bcm5700_shutdown(pUmDevice);
+	LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
+
+/*	pci_power_off(pdev, -1);*/
+#if (LINUX_VERSION_CODE >= 0x020406)
+	return 0;
+#endif
+}
+
+
+#if (LINUX_VERSION_CODE >= 0x020406)
+static int bcm5700_resume(struct pci_dev *pdev)
+#else
+static void bcm5700_resume(struct pci_dev *pdev)
+#endif
+{
+	struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (!netif_running(dev))
+#if (LINUX_VERSION_CODE >= 0x020406)
+		return 0;
+#else
+		return;
+#endif
+/*	pci_power_on(pdev);*/
+	netif_device_attach(dev);
+	LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+	MM_InitializeUmPackets(pDevice);
+	bcm5700_reset(dev);
+#if (LINUX_VERSION_CODE >= 0x020406)
+	return 0;
+#endif
+}
+
+
+static struct pci_driver bcm5700_pci_driver = {
+	name:		bcm5700_driver,
+	id_table:	bcm5700_pci_tbl,
+	probe:		bcm5700_init_one,
+	remove:		bcm5700_remove_one,
+	suspend:	bcm5700_suspend,
+	resume:		bcm5700_resume,
+};
+
+
+static int __init bcm5700_init_module (void)
+{
+	return pci_module_init(&bcm5700_pci_driver);
+}
+
+
+static void __exit bcm5700_cleanup_module (void)
+{
+	pci_unregister_driver(&bcm5700_pci_driver);
+}
+
+
+module_init(bcm5700_init_module);
+module_exit(bcm5700_cleanup_module);
+#endif
+
+/*
+ * Middle Module
+ *
+ */
+
+
+LM_STATUS
+MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT16 *pValue16)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_read_config_word(pUmDevice->pdev, Offset, (u16 *) pValue16);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT32 *pValue32)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_read_config_dword(pUmDevice->pdev, Offset, (u32 *) pValue32);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT16 Value16)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_write_config_word(pUmDevice->pdev, Offset, Value16);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT32 Value32)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_write_config_dword(pUmDevice->pdev, Offset, Value32);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+	PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
+	LM_BOOL Cached)
+{
+	PLM_VOID pvirt;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	dma_addr_t mapping;
+
+	pvirt = pci_alloc_consistent(pUmDevice->pdev, BlockSize,
+					       &mapping);
+	if (!pvirt) {
+		return LM_STATUS_FAILURE;
+	}
+	pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+	pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
+	pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+	memset(pvirt, 0, BlockSize);
+	*pMemoryBlockVirt = (PLM_VOID) pvirt;
+	MM_SetAddr(pMemoryBlockPhy, mapping);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+	PLM_VOID *pMemoryBlockVirt)
+{
+	PLM_VOID pvirt;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+
+
+	/* Maximum in slab.c */
+	if (BlockSize > 131072) {
+		goto MM_Alloc_error;
+	}
+
+	pvirt = kmalloc(BlockSize, GFP_KERNEL);
+	if (!pvirt) {
+		goto MM_Alloc_error;
+	}
+	pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+	pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
+	pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = 0;
+	/* mem_size_list[i] == 0 indicates that the memory should be freed */
+	/* using kfree */
+	memset(pvirt, 0, BlockSize);
+	*pMemoryBlockVirt = pvirt;
+	return LM_STATUS_SUCCESS;
+
+MM_Alloc_error:
+	printk(KERN_WARNING "%s: Memory allocation failed - buffer parameters may be set too high\n", pUmDevice->dev->name);
+	return LM_STATUS_FAILURE;
+}
+
+LM_STATUS
+MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+
+	pDevice->pMappedMemBase = ioremap_nocache(
+		pci_resource_start(pUmDevice->pdev, 0), sizeof(T3_STD_MEM_MAP));
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
+{
+	int i;
+	struct sk_buff *skb;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	PUM_PACKET pUmPacket;
+	PLM_PACKET pPacket;
+
+	for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
+		pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+		pUmPacket = (PUM_PACKET) pPacket;
+		if (pPacket == 0) {
+			printk(KERN_DEBUG "Bad RxPacketFreeQ\n");
+		}
+		if (pUmPacket->skbuff == 0) {
+			skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2);
+			if (skb == 0) {
+				pUmPacket->skbuff = 0;
+				QQ_PushTail(
+					&pUmDevice->rx_out_of_buf_q.Container,
+					pPacket);
+				continue;
+			}
+			pUmPacket->skbuff = skb;
+			skb->dev = pUmDevice->dev;
+			skb_reserve(skb, pUmDevice->rx_buf_align);
+		}
+		QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+	}
+	if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
+		/* reallocate buffers in the ISR */
+		pUmDevice->rx_buf_repl_thresh = 0;
+		pUmDevice->rx_buf_repl_panic_thresh = 0;
+	}
+	else {
+		pUmDevice->rx_buf_repl_thresh = pDevice->RxPacketDescCnt / 8;
+		pUmDevice->rx_buf_repl_panic_thresh =
+			pDevice->RxPacketDescCnt / 2;
+
+		if (pDevice->RxJumboDescCnt != 0) {
+			if (pUmDevice->rx_buf_repl_thresh >=
+				pDevice->RxJumboDescCnt) {
+
+				pUmDevice->rx_buf_repl_thresh = 
+				pUmDevice->rx_buf_repl_panic_thresh = 
+					pDevice->RxJumboDescCnt - 1;
+			}
+			if (pUmDevice->rx_buf_repl_thresh >=
+				pDevice->RxStdDescCnt) {
+
+				pUmDevice->rx_buf_repl_thresh = 
+				pUmDevice->rx_buf_repl_panic_thresh = 
+					pDevice->RxStdDescCnt - 1;
+			}
+		}
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	int index = pUmDevice->index;
+	struct net_device *dev = pUmDevice->dev;
+
+	bcm5700_validate_param_range(dev, &auto_speed[index], "auto_speed",
+		0, 1, 1);
+	if (auto_speed[index] == 0)
+		pDevice->DisableAutoNeg = TRUE;
+	else
+		pDevice->DisableAutoNeg = FALSE;
+
+	if (line_speed[index] == 0) {
+		pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+		pDevice->DisableAutoNeg = FALSE;
+	}
+	else {
+		bcm5700_validate_param_range(dev, &full_duplex[index],
+			"full_duplex", 0, 1, 1);
+		if (full_duplex[index]) {
+			pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
+		}
+		else {
+			pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_HALF;
+		}
+
+		if (line_speed[index] == 1000) {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS;
+			if (pDevice->No1000) {
+				pDevice->RequestedLineSpeed =
+					LM_LINE_SPEED_100MBPS;
+				printk(KERN_WARNING "%s: Invalid line_speed parameter (1000), using 100\n", dev->name);
+			}
+			else {
+				if (pDevice->EnableTbi && !full_duplex[index]) {
+
+					printk(KERN_WARNING "%s: Invalid full_duplex parameter (0) for fiber, using 1\n", dev->name);
+					pDevice->RequestedDuplexMode =
+						LM_DUPLEX_MODE_FULL;
+				}
+
+				if (!pDevice->EnableTbi && !auto_speed[index]) {
+					printk(KERN_WARNING "%s: Invalid auto_speed parameter (0) for copper, using 1\n", dev->name);
+					pDevice->DisableAutoNeg = FALSE;
+				}
+			}
+		}
+		else if (line_speed[index] == 100) {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_100MBPS;
+		}
+		else if (line_speed[index] == 10) {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_10MBPS;
+		}
+		else {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+			pDevice->DisableAutoNeg = FALSE;
+			printk(KERN_WARNING "%s: Invalid line_speed parameter (%d), using 0\n", dev->name, line_speed[index]);
+		}
+
+	}
+	pDevice->FlowControlCap = 0;
+	bcm5700_validate_param_range(dev, &rx_flow_control[index],
+		"rx_flow_control", 0, 1, 0);
+	if (rx_flow_control[index] != 0) {
+		pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+	}
+	bcm5700_validate_param_range(dev, &tx_flow_control[index],
+		"tx_flow_control", 0, 1, 0);
+	if (tx_flow_control[index] != 0) {
+		pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+	}
+	bcm5700_validate_param_range(dev, &auto_flow_control[index],
+		"auto_flow_control", 0, 1, 0);
+	if (auto_flow_control[index] != 0) {
+		if (pDevice->DisableAutoNeg == FALSE) {
+
+			pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
+			if ((tx_flow_control[index] == 0) &&
+				(rx_flow_control[index] == 0)) {
+
+				pDevice->FlowControlCap |=
+					LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+					LM_FLOW_CONTROL_RECEIVE_PAUSE;
+			}
+		}
+	}
+
+	if (dev->mtu > 1500) {
+		pDevice->RxMtu = dev->mtu + 14;
+	}
+
+	if (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) {
+		pDevice->UseTaggedStatus = TRUE;
+		pUmDevice->timer_interval = HZ;
+	}
+	else {
+		pUmDevice->timer_interval = HZ/10;
+	}
+
+	bcm5700_validate_param_range(dev, &tx_pkt_desc_cnt[index],
+		"tx_pkt_desc_cnt", 1, MAX_TX_PACKET_DESC_COUNT, TX_DESC_CNT);
+	pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
+	bcm5700_validate_param_range(dev, &rx_std_desc_cnt[index],
+		"rx_std_desc_cnt", 1, T3_STD_RCV_RCB_ENTRY_COUNT-1,
+		RX_DESC_CNT);
+	pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
+
+	bcm5700_validate_param_range(dev, &rx_jumbo_desc_cnt[index],
+		"rx_jumbo_desc_cnt", 1, T3_JUMBO_RCV_RCB_ENTRY_COUNT-1,
+		JBO_DESC_CNT);
+
+	if (mtu[index] <= 1514)
+		pDevice->RxJumboDescCnt = 0;
+	else
+		pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
+
+#ifdef BCM_INT_COAL
+	bcm5700_validate_param_range(dev, &adaptive_coalesce[index],
+		"adaptive_coalesce", 0, 1, 1);
+	pUmDevice->adaptive_coalesce = adaptive_coalesce[index];
+	if (!pUmDevice->adaptive_coalesce) {
+		bcm5700_validate_param_range(dev, &rx_coalesce_ticks[index],
+			"rx_coalesce_ticks", 0, MAX_RX_COALESCING_TICKS,
+			RX_COAL_TK);
+		if ((rx_coalesce_ticks[index] == 0) &&
+			(rx_max_coalesce_frames[index] == 0)) {
+
+			printk(KERN_WARNING "%s: Conflicting rx_coalesce_ticks (0) and rx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
+				dev->name, RX_COAL_TK, RX_COAL_FM);
+
+			rx_coalesce_ticks[index] = RX_COAL_TK;
+			rx_max_coalesce_frames[index] = RX_COAL_FM;
+		}
+		pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
+		pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
+
+		bcm5700_validate_param_range(dev,
+			&rx_max_coalesce_frames[index],
+			"rx_max_coalesce_frames", 0,
+			MAX_RX_MAX_COALESCED_FRAMES, RX_COAL_FM);
+
+		pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
+		pUmDevice->rx_curr_coalesce_frames =
+			pDevice->RxMaxCoalescedFrames;
+
+		bcm5700_validate_param_range(dev, &tx_coalesce_ticks[index],
+			"tx_coalesce_ticks", 0, MAX_TX_COALESCING_TICKS,
+			TX_COAL_TK);
+		if ((tx_coalesce_ticks[index] == 0) &&
+			(tx_max_coalesce_frames[index] == 0)) {
+
+			printk(KERN_WARNING "%s: Conflicting tx_coalesce_ticks (0) and tx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
+				dev->name, TX_COAL_TK, TX_COAL_FM);
+
+			tx_coalesce_ticks[index] = TX_COAL_TK;
+			tx_max_coalesce_frames[index] = TX_COAL_FM;
+		}
+		pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
+		bcm5700_validate_param_range(dev,
+			&tx_max_coalesce_frames[index],
+			"tx_max_coalesce_frames", 0,
+			MAX_TX_MAX_COALESCED_FRAMES, TX_COAL_FM);
+		pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
+		pUmDevice->tx_curr_coalesce_frames =
+			pDevice->TxMaxCoalescedFrames;
+
+		bcm5700_validate_param_range(dev, &stats_coalesce_ticks[index],
+			"stats_coalesce_ticks", 0,
+			MAX_STATS_COALESCING_TICKS, ST_COAL_TK);
+		if ((stats_coalesce_ticks[index] > 0) &&
+			(stats_coalesce_ticks[index] < 100)) {
+			printk(KERN_WARNING "%s: Invalid stats_coalesce_ticks parameter (%u), using 100\n", dev->name, (unsigned int) stats_coalesce_ticks[index]);
+			stats_coalesce_ticks[index] = 100;
+		}
+		pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
+		pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
+	}
+	else {
+		pUmDevice->rx_curr_coalesce_frames = RX_COAL_FM;
+		pUmDevice->rx_curr_coalesce_ticks = RX_COAL_TK;
+		pUmDevice->tx_curr_coalesce_frames = TX_COAL_FM;
+	}
+#endif
+
+#ifdef BCM_WOL
+	bcm5700_validate_param_range(dev, &enable_wol[index], "enable_wol",
+		0, 1, 0);
+	if (enable_wol[index]) {
+		pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
+		pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
+	}
+#endif
+#ifdef BCM_NIC_SEND_BD
+	if (pDevice->EnablePciXFix)
+		pDevice->NicSendBd = FALSE;
+	else
+		pDevice->NicSendBd = TRUE;
+#ifdef BCM_VLAN
+	pDevice->NicSendBd = FALSE;
+#endif
+#ifdef BCM_TSO
+	pDevice->NicSendBd = FALSE;
+#endif
+#endif
+#if INCLUDE_TBI_SUPPORT
+	pDevice->PollTbiLink = TRUE;
+#endif
+	bcm5700_validate_param_range(dev, &scatter_gather[index],
+		"scatter_gather", 0, 1, 1);
+	bcm5700_validate_param_range(dev, &tx_checksum[index], "tx_checksum",
+		0, 1, 1);
+	bcm5700_validate_param_range(dev, &rx_checksum[index], "rx_checksum",
+		0, 1, 1);
+	if (!(pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
+		if (tx_checksum[index] || rx_checksum[index]) {
+
+			pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; 
+			printk(KERN_WARNING "%s: Checksum offload not available on this NIC\n", dev->name);
+		}
+	}
+	else {
+		if (rx_checksum[index]) {
+			pDevice->TaskToOffload |=
+				LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+				LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+		}
+		if (tx_checksum[index]) {
+			pDevice->TaskToOffload |=
+				LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+				LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
+			pDevice->NoTxPseudoHdrChksum = TRUE;
+		}
+	}
+	bcm5700_validate_param_range(dev, &enable_tso[index], "enable_tso",
+		0, 1, 0);
+	if (enable_tso[index]) {
+#ifdef BCM_TSO
+		if (pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
+		{
+			pDevice->TaskToOffload |=
+				LM_TASK_OFFLOAD_TCP_SEGMENTATION;
+		}
+		else
+#endif
+		{
+			printk(KERN_WARNING "%s: TSO not available on this NIC or not supported by kernel\n", dev->name);
+		}
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+	struct sk_buff *skb;
+	int size;
+	int vlan_tag_size = 0;
+
+	if (pDevice->ReceiveMask & LM_KEEP_VLAN_TAG)
+		vlan_tag_size = 4;
+
+	while (1) {
+		pPacket = (PLM_PACKET)
+			QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
+		if (pPacket == 0)
+			break;
+		pUmPacket = (PUM_PACKET) pPacket;
+#if ! defined(NO_PCI_UNMAP)
+		pci_unmap_single(pUmDevice->pdev,
+				pci_unmap_addr(pUmPacket, map[0]),
+				pPacket->u.Rx.RxBufferSize,
+				PCI_DMA_FROMDEVICE);
+#endif
+		if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
+			((size = pPacket->PacketSize) >
+			(pDevice->RxMtu + vlan_tag_size))) {
+
+			/* reuse skb */
+#ifdef BCM_TASKLET
+			QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+#else
+			QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+#endif
+			pUmDevice->rx_misc_errors++;
+			continue;
+		}
+		skb = pUmPacket->skbuff;
+		skb_put(skb, size);
+		skb->pkt_type = 0;
+		skb->protocol = eth_type_trans(skb, skb->dev);
+		if (size > pDevice->RxMtu) {
+			/* Make sure we have a valid VLAN tag */
+			if (htons(skb->protocol) != 0x8100) {
+				dev_kfree_skb_irq(skb);
+				pUmDevice->rx_misc_errors++;
+				goto drop_rx;
+			}
+		}
+		if ((pPacket->Flags & RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD) &&
+			(pDevice->TaskToOffload &
+				LM_TASK_OFFLOAD_RX_TCP_CHECKSUM)) {
+			if (pPacket->u.Rx.TcpUdpChecksum == 0xffff) {
+
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+#if TIGON3_DEBUG
+				pUmDevice->rx_good_chksum_count++;
+#endif
+			}
+			else {
+				skb->ip_summed = CHECKSUM_NONE;
+				pUmDevice->rx_bad_chksum_count++;
+			}
+		}
+		else {
+			skb->ip_summed = CHECKSUM_NONE;
+		}
+#ifdef NICE_SUPPORT
+		if( pUmDevice->nice_rx ) {
+			vlan_tag_t *vlan_tag;
+
+			vlan_tag = (vlan_tag_t *) &skb->cb[0];
+			if (pPacket->Flags & RCV_BD_FLAG_VLAN_TAG) {
+				vlan_tag->signature = 0x7777;
+				vlan_tag->tag = pPacket->VlanTag;
+			}
+			else {
+				vlan_tag->signature = 0;
+			}
+			pUmDevice->nice_rx(skb, pUmDevice->nice_ctx);
+		}
+		else
+#endif
+		{
+#ifdef BCM_VLAN
+			if (pUmDevice->vlgrp &&
+				(pPacket->Flags & RCV_BD_FLAG_VLAN_TAG)) {
+
+				vlan_hwaccel_rx(skb, pUmDevice->vlgrp,
+					pPacket->VlanTag);
+			}
+			else
+#endif
+			{
+				netif_rx(skb);
+			}
+		}
+		pUmDevice->dev->last_rx = jiffies;
+
+drop_rx:
+#ifdef BCM_TASKLET
+		pUmPacket->skbuff = 0;
+		QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+#else
+		skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2);
+		if (skb == 0) {
+			pUmPacket->skbuff = 0;
+			QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+		}
+		else {
+			pUmPacket->skbuff = skb;
+			skb->dev = pUmDevice->dev;
+			skb_reserve(skb, pUmDevice->rx_buf_align);
+			QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+		}
+#endif
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+	PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+	struct sk_buff *skb = pUmPacket->skbuff;
+	struct sk_buff *nskb;
+#if ! defined(NO_PCI_UNMAP)
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+
+	pci_unmap_single(pUmDevice->pdev,
+			pci_unmap_addr(pUmPacket, map[0]),
+			pci_unmap_len(pUmPacket, map_len[0]),
+			PCI_DMA_TODEVICE);
+#if MAX_SKB_FRAGS
+	{
+		int i;
+
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			pci_unmap_page(pUmDevice->pdev,
+				pci_unmap_addr(pUmPacket, map[i + 1]),
+				pci_unmap_len(pUmPacket, map_len[i + 1]),
+				PCI_DMA_TODEVICE);
+		}
+	}
+#endif
+#endif
+	if ((nskb = skb_copy(skb, GFP_ATOMIC))) {
+		pUmPacket->lm_packet.u.Tx.FragCount = 1;
+		dev_kfree_skb(skb);
+		pUmPacket->skbuff = nskb;
+		return LM_STATUS_SUCCESS;
+	}
+	dev_kfree_skb(skb);
+	pUmPacket->skbuff = 0;
+	return LM_STATUS_FAILURE;
+}
+
+/* Returns 1 if not all buffers are allocated */
+STATIC int
+replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice)
+{
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	struct sk_buff *skb;
+	int queue_rx = 0;
+	int ret = 0;
+
+	while ((pUmPacket = (PUM_PACKET)
+		QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
+		pPacket = (PLM_PACKET) pUmPacket;
+		if (pUmPacket->skbuff) {
+			/* reuse an old skb */
+			QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+			queue_rx = 1;
+			continue;
+		}
+		if ((skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2)) == 0) {
+			QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,
+				pPacket);
+			ret = 1;
+			break;
+		}
+		pUmPacket->skbuff = skb;
+		skb->dev = pUmDevice->dev;
+		skb_reserve(skb, pUmDevice->rx_buf_align);
+		QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+		queue_rx = 1;
+	}
+	if (queue_rx || pDevice->QueueAgain) {
+		LM_QueueRxPackets(pDevice);
+	}
+	return ret;
+}
+
+LM_STATUS
+MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+	struct sk_buff *skb;
+#if ! defined(NO_PCI_UNMAP) && MAX_SKB_FRAGS
+	int i;
+#endif
+
+	while (1) {
+		pPacket = (PLM_PACKET)
+			QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
+		if (pPacket == 0)
+			break;
+		pUmPacket = (PUM_PACKET) pPacket;
+		skb = pUmPacket->skbuff;
+#if ! defined(NO_PCI_UNMAP)
+		pci_unmap_single(pUmDevice->pdev,
+				pci_unmap_addr(pUmPacket, map[0]),
+				pci_unmap_len(pUmPacket, map_len[0]),
+				PCI_DMA_TODEVICE);
+#if MAX_SKB_FRAGS
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			pci_unmap_page(pUmDevice->pdev,
+				pci_unmap_addr(pUmPacket, map[i + 1]),
+				pci_unmap_len(pUmPacket, map_len[i + 1]),
+				PCI_DMA_TODEVICE);
+		}
+#endif
+#endif
+		dev_kfree_skb_irq(skb);
+		pUmPacket->skbuff = 0;
+		QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+	}
+	if (pUmDevice->tx_full) {
+		if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
+			(pDevice->TxPacketDescCnt >> 1)) {
+
+			pUmDevice->tx_full = 0;
+			netif_wake_queue(pUmDevice->dev);
+		}
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	struct net_device *dev = pUmDevice->dev;
+	LM_FLOW_CONTROL flow_control;
+
+	if (!pUmDevice->opened)
+		return LM_STATUS_SUCCESS;
+
+	if (pUmDevice->delayed_link_ind > 0) {
+		pUmDevice->delayed_link_ind = 0;
+		if (Status == LM_STATUS_LINK_DOWN) {
+			pUmDevice->line_speed = 0;
+			netif_carrier_off(dev);
+			printk(KERN_ERR "%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name);
+		}
+		else if (Status == LM_STATUS_LINK_ACTIVE) {
+			netif_carrier_on(dev);
+			printk(KERN_INFO "%s: %s NIC Link is UP, ", bcm5700_driver, dev->name);
+		}
+	}
+	else {
+		if (Status == LM_STATUS_LINK_DOWN) {
+			pUmDevice->line_speed = 0;
+			netif_carrier_off(dev);
+			printk(KERN_ERR "%s: %s NIC Link is Down\n", bcm5700_driver, dev->name);
+		}
+		else if (Status == LM_STATUS_LINK_ACTIVE) {
+			netif_carrier_on(dev);
+			printk(KERN_INFO "%s: %s NIC Link is Up, ", bcm5700_driver, dev->name);
+		}
+	}
+
+	if (Status == LM_STATUS_LINK_ACTIVE) {
+		if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS)
+			pUmDevice->line_speed = 1000;
+		else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
+			pUmDevice->line_speed = 100;
+		else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+			pUmDevice->line_speed = 10;
+
+		printk("%d Mbps ", pUmDevice->line_speed);
+
+		if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+			printk("full duplex");
+		else
+			printk("half duplex");
+
+		flow_control = pDevice->FlowControl &
+			(LM_FLOW_CONTROL_RECEIVE_PAUSE |
+			LM_FLOW_CONTROL_TRANSMIT_PAUSE);
+		if (flow_control) {
+			if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
+				printk(", receive ");
+				if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+					printk("& transmit ");
+			}
+			else {
+				printk(", transmit ");
+			}
+			printk("flow control ON");
+		}
+		printk("\n");
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+	PUM_PACKET pUmPacket;
+	struct sk_buff *skb;
+
+	if (pPacket == 0)
+		return LM_STATUS_SUCCESS;
+	pUmPacket = (PUM_PACKET) pPacket;
+	if ((skb = pUmPacket->skbuff))
+		dev_kfree_skb(skb);
+	pUmPacket->skbuff = 0;
+	return LM_STATUS_SUCCESS;
+}
+
+void
+bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice)
+{
+	LM_DEVICE_BLOCK *pDevice = (LM_DEVICE_BLOCK *) pUmDevice;
+
+	bcm5700_intr_off(pUmDevice);
+	netif_carrier_off(pUmDevice->dev);
+	LM_Halt(pDevice);
+	pDevice->InitDone = 0;
+	bcm5700_free_remaining_rx_bufs(pUmDevice);
+}
+
+void
+bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice)
+{
+	LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+	UM_PACKET *pUmPacket;
+	struct sk_buff *skb;
+	int cnt, i;
+
+	cnt = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container);
+	for (i = 0; i < cnt; i++) {
+		if ((pUmPacket =
+			QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container))
+			!= 0) {
+
+			if ((skb = pUmPacket->skbuff))
+				dev_kfree_skb(skb);
+			pUmPacket->skbuff = 0;
+			QQ_PushTail(&pDevice->RxPacketFreeQ.Container,
+				pUmPacket);
+		}
+	}
+}
+
+void
+bcm5700_validate_param_range(struct net_device *dev, int *param,
+	char *param_name, int min, int max, int deflt)
+{
+	if (((unsigned int) *param < (unsigned int) min) ||
+		((unsigned int) *param > (unsigned int) max)) {
+
+		printk(KERN_WARNING "%s: Invalid %s parameter (%u), using %u\n", dev->name, param_name, (unsigned int) *param, (unsigned int) deflt);
+		*param = deflt;
+	}
+}
+
+struct net_device *
+bcm5700_find_peer(struct net_device *dev)
+{
+	struct net_device *tmp_dev;
+	UM_DEVICE_BLOCK *pUmDevice, *pUmTmp;
+	LM_DEVICE_BLOCK *pDevice;
+
+	tmp_dev = 0;
+	pUmDevice = (UM_DEVICE_BLOCK *) dev->priv;
+	pDevice = &pUmDevice->lm_dev;
+	if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
+		tmp_dev = root_tigon3_dev;
+		while (tmp_dev) {
+			pUmTmp = (PUM_DEVICE_BLOCK) tmp_dev->priv;
+			if ((tmp_dev != dev) &&
+				(pUmDevice->pdev->bus->number ==
+				pUmTmp->pdev->bus->number) &&
+				PCI_SLOT(pUmDevice->pdev->devfn) ==
+				PCI_SLOT(pUmTmp->pdev->devfn)) {
+
+				break;
+			}
+			tmp_dev = pUmTmp->next_module;
+		}
+	}
+	return tmp_dev;
+}
+
+LM_DEVICE_BLOCK *
+MM_FindPeerDev(LM_DEVICE_BLOCK *pDevice)
+{
+	UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	struct net_device *dev = pUmDevice->dev;
+	struct net_device *peer_dev;
+
+	peer_dev = bcm5700_find_peer(dev);
+	if (!peer_dev)
+		return 0;
+	return ((LM_DEVICE_BLOCK *) peer_dev->priv);
+}
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/bits.h orig/drivers/net/bcm/bits.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/bits.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/bits.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,61 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef BITS_H
+#define BITS_H
+
+
+
+/******************************************************************************/
+/* Bit Mask definitions */
+/******************************************************************************/
+
+#define BIT_NONE            0x00
+#define BIT_0               0x01
+#define BIT_1               0x02
+#define BIT_2               0x04
+#define BIT_3               0x08
+#define BIT_4               0x10
+#define BIT_5               0x20
+#define BIT_6               0x40
+#define BIT_7               0x80
+#define BIT_8               0x0100
+#define BIT_9               0x0200
+#define BIT_10              0x0400
+#define BIT_11              0x0800
+#define BIT_12              0x1000
+#define BIT_13              0x2000
+#define BIT_14              0x4000
+#define BIT_15              0x8000
+#define BIT_16              0x010000
+#define BIT_17              0x020000
+#define BIT_18              0x040000
+#define BIT_19              0x080000
+#define BIT_20              0x100000
+#define BIT_21              0x200000
+#define BIT_22              0x400000
+#define BIT_23              0x800000
+#define BIT_24              0x01000000
+#define BIT_25              0x02000000
+#define BIT_26              0x04000000
+#define BIT_27              0x08000000
+#define BIT_28              0x10000000
+#define BIT_29              0x20000000
+#define BIT_30              0x40000000
+#define BIT_31              0x80000000
+
+
+
+#endif /* BITS_H */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/fw_lso05.h orig/drivers/net/bcm/fw_lso05.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/fw_lso05.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/fw_lso05.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,273 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+#ifndef __FW_LSO05_H__ 
+#define __FW_LSO05_H__ 
+
+int t3StkOffLd05FwReleaseMajor = 0x0;
+int t3StkOffLd05FwReleaseMinor = 0x0;
+int t3StkOffLd05FwReleaseFix = 0x0;
+U32 t3StkOffLd05FwStartAddr = 0x00010000;
+U32 t3StkOffLd05FwTextAddr = 0x00010000;
+int t3StkOffLd05FwTextLen = 0xe40;
+U32 t3StkOffLd05FwRodataAddr = 0x00010e40;
+int t3StkOffLd05FwRodataLen = 0x40;
+U32 t3StkOffLd05FwDataAddr = 0x00010ea0;
+int t3StkOffLd05FwDataLen = 0x20;
+U32 t3StkOffLd05FwSbssAddr = 0x00010ec0;
+int t3StkOffLd05FwSbssLen = 0x28;
+U32 t3StkOffLd05FwBssAddr = 0x00010ef0;
+int t3StkOffLd05FwBssLen = 0x88;
+U32 t3StkOffLd05FwText[(0xe40/4) + 1] = {
+0xc004003, 0x0, 0x10eb0, 
+0x0, 0x10000003, 0x0, 0xd, 
+0xd, 0x3c1d0001, 0x37bde000, 0x3a0f021, 
+0x3c100001, 0x26100000, 0xc004010, 0x0, 
+0xd, 0x27bdffe0, 0x3c04fefe, 0xafbf0018, 
+0xc0042d4, 0x34840002, 0xc004350, 0x0, 
+0x3c030001, 0x90630ed4, 0x24020002, 0x3c040001, 
+0x24840e4c, 0x14620003, 0x24050001, 0x3c040001, 
+0x24840e40, 0x3021, 0x3821, 0xafa00010, 
+0xc004364, 0xafa00014, 0xc00402c, 0x0, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 
+0x0, 0x27bdffe0, 0xafbf001c, 0xafb20018, 
+0xafb10014, 0xc00404e, 0xafb00010, 0x3c128000, 
+0x24110001, 0x8f706810, 0x32020400, 0x10400007, 
+0x0, 0x8f641008, 0x921024, 0x14400003, 
+0x0, 0xc004064, 0x0, 0x3c020001, 
+0x90420ef6, 0x10510003, 0x32020200, 0x1040fff1, 
+0x0, 0xc0041b4, 0x0, 0x8004034, 
+0x0, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe0, 
+0x3c040001, 0x24840e60, 0x2821, 0x3021, 
+0x3821, 0xafbf0018, 0xafa00010, 0xc004364, 
+0xafa00014, 0xd021, 0x24020130, 0xaf625000, 
+0x3c010001, 0xa4200ef0, 0x3c010001, 0xa0200ef7, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 
+0x0, 0x3c030001, 0x24630f00, 0x90620000, 
+0x27bdfff0, 0x14400003, 0x80c021, 0x8004073, 
+0x4821, 0x3c022000, 0x3021024, 0x10400003, 
+0x24090002, 0x8004073, 0xa0600000, 0x24090001, 
+0x181040, 0x30431f80, 0x346f8008, 0x1520004b, 
+0x25eb0028, 0x3c040001, 0x832021, 0x8c848010, 
+0x3c050001, 0x24a50f1a, 0x41402, 0xa0a20000, 
+0x3c010001, 0xa0240f1b, 0x3c020001, 0x431021, 
+0x94428014, 0x3c010001, 0xa0220f1c, 0x3c0c0001, 
+0x1836021, 0x8d8c8018, 0x304200ff, 0x24420008, 
+0x220c3, 0x24020001, 0x3c010001, 0xa0220f00, 
+0x124102b, 0x1040000c, 0x3821, 0x24a6000e, 
+0x1602821, 0x8ca20000, 0x8ca30004, 0x24a50008, 
+0x24e70001, 0xacc20000, 0xacc30004, 0xe4102b, 
+0x1440fff8, 0x24c60008, 0x3821, 0x3c080001, 
+0x25080f1b, 0x91060000, 0x3c020001, 0x90420f1c, 
+0x2503000d, 0xc32821, 0x461023, 0x21fc2, 
+0x431021, 0x21043, 0x1840000c, 0x2021, 
+0x91020001, 0x461023, 0x21fc2, 0x431021, 
+0x21843, 0x94a20000, 0x24e70001, 0x822021, 
+0xe3102a, 0x1440fffb, 0x24a50002, 0x41c02, 
+0x3082ffff, 0x622021, 0x41402, 0x822021, 
+0x3c02ffff, 0x1821024, 0x3083ffff, 0x431025, 
+0x3c010001, 0x80040fa, 0xac220f20, 0x3c050001, 
+0x24a50f1c, 0x90a20000, 0x3c0c0001, 0x1836021, 
+0x8d8c8018, 0x220c2, 0x1080000e, 0x3821, 
+0x1603021, 0x24a5000c, 0x8ca20000, 0x8ca30004, 
+0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 
+0xe4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 
+0x24a50f1c, 0x90a20000, 0x30430007, 0x24020004, 
+0x10620011, 0x28620005, 0x10400005, 0x24020002, 
+0x10620008, 0x710c0, 0x80040fa, 0x0, 
+0x24020006, 0x1062000e, 0x710c0, 0x80040fa, 
+0x0, 0xa21821, 0x9463000c, 0x4b1021, 
+0x80040fa, 0xa4430000, 0x710c0, 0xa21821, 
+0x8c63000c, 0x4b1021, 0x80040fa, 0xac430000, 
+0xa21821, 0x8c63000c, 0x4b2021, 0xa21021, 
+0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 
+0x3c020001, 0x90420f1c, 0x3c030001, 0x90630f1a, 
+0xe2c823, 0x3c020001, 0x90420f1b, 0x24630028, 
+0x1e34021, 0x24420028, 0x15200012, 0x1e23021, 
+0x94c2000c, 0x3c010001, 0xa4220f18, 0x94c20004, 
+0x94c30006, 0x3c010001, 0xa4200f16, 0x3c010001, 
+0xa4200f12, 0x21400, 0x431025, 0x3c010001, 
+0xac220f0c, 0x95020004, 0x3c010001, 0x8004124, 
+0xa4220f10, 0x3c020001, 0x94420f10, 0x3c030001, 
+0x94630f12, 0x431021, 0xa5020004, 0x3c020001, 
+0x94420f0c, 0xa4c20004, 0x3c020001, 0x8c420f0c, 
+0xa4c20006, 0x3c040001, 0x94840f12, 0x3c020001, 
+0x94420f10, 0x3c0a0001, 0x954a0f16, 0x441821, 
+0x3063ffff, 0x62182a, 0x24020002, 0x1122000b, 
+0x832023, 0x3c030001, 0x94630f18, 0x30620009, 
+0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 
+0x94420f18, 0x30420009, 0x1425023, 0x24020001, 
+0x1122001b, 0x29220002, 0x50400005, 0x24020002, 
+0x11200007, 0x31a2ffff, 0x8004197, 0x0, 
+0x1122001d, 0x24020016, 0x8004197, 0x31a2ffff, 
+0x3c0e0001, 0x95ce0f20, 0x10800005, 0x1806821, 
+0x1c42021, 0x41c02, 0x3082ffff, 0x627021, 
+0xe1027, 0xa502000a, 0x3c030001, 0x90630f1b, 
+0x31a2ffff, 0xe21021, 0x800418d, 0x432023, 
+0x3c020001, 0x94420f20, 0x442021, 0x41c02, 
+0x3082ffff, 0x622021, 0x807021, 0x41027, 
+0x8004185, 0xa502000a, 0x3c050001, 0x24a50f1a, 
+0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 
+0x90a20000, 0xe21023, 0xa5020002, 0x3c030001, 
+0x94630f20, 0x3c020001, 0x94420efa, 0x30e5ffff, 
+0x641821, 0x451023, 0x622023, 0x41c02, 
+0x3082ffff, 0x622021, 0x41027, 0xa502000a, 
+0x3c030001, 0x90630f1c, 0x24620001, 0x14a20005, 
+0x807021, 0x1631021, 0x90420000, 0x8004185, 
+0x26200, 0x24620002, 0x14a20003, 0x306200fe, 
+0x4b1021, 0x944c0000, 0x3c020001, 0x94420f22, 
+0x3183ffff, 0x3c040001, 0x90840f1b, 0x431021, 
+0xe21021, 0x442023, 0x8a2021, 0x41c02, 
+0x3082ffff, 0x622021, 0x41402, 0x822021, 
+0x806821, 0x41027, 0xa4c20010, 0x31a2ffff, 
+0xe1c00, 0x431025, 0x3c040001, 0x24840f12, 
+0xade20010, 0x94820000, 0x3c050001, 0x94a50f16, 
+0x3c030001, 0x8c630f0c, 0x24420001, 0xb92821, 
+0xa4820000, 0x3322ffff, 0x622021, 0x83182b, 
+0x3c010001, 0xa4250f16, 0x10600003, 0x24a2ffff, 
+0x3c010001, 0xa4220f16, 0x3c024000, 0x3021025, 
+0x3c010001, 0xac240f0c, 0xaf621008, 0x3e00008, 
+0x27bd0010, 0x3c030001, 0x90630ef6, 0x27bdffe8, 
+0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 
+0x8f620cf4, 0x2442ffff, 0x3042007f, 0x21100, 
+0x8c434000, 0x3c010001, 0xac230f04, 0x8c434008, 
+0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 
+0x24020088, 0x24020008, 0x3c010001, 0xa4220f08, 
+0x30620004, 0x10400005, 0x24020001, 0x3c010001, 
+0xa0220ef7, 0x80041d5, 0x31402, 0x3c010001, 
+0xa0200ef7, 0x31402, 0x3c010001, 0xa4220ef4, 
+0x9483000c, 0x24020001, 0x3c010001, 0xa4200ef0, 
+0x3c010001, 0xa0220ef6, 0x3c010001, 0xa4230f02, 
+0x24020001, 0x1342001e, 0x0, 0x13400005, 
+0x24020003, 0x13420067, 0x0, 0x80042cf, 
+0x0, 0x3c020001, 0x94420f02, 0x241a0001, 
+0x3c010001, 0xa4200efe, 0x3c010001, 0xa4200ef2, 
+0x304407ff, 0x21bc2, 0x31823, 0x3063003e, 
+0x34630036, 0x21242, 0x3042003c, 0x621821, 
+0x3c010001, 0xa4240ef8, 0x832021, 0x24630030, 
+0x3c010001, 0xa4240efa, 0x3c010001, 0xa4230efc, 
+0x3c060001, 0x24c60ef2, 0x94c50000, 0x94c30002, 
+0x3c040001, 0x94840efa, 0x651021, 0x44102a, 
+0x10400013, 0x3c108000, 0xa31021, 0xa4c20000, 
+0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200ef6, 
+0x8f641008, 0x901024, 0x14400003, 0x0, 
+0xc004064, 0x0, 0x8f620cf4, 0x501024, 
+0x104000b7, 0x0, 0x800420f, 0x0, 
+0x3c030001, 0x94630ef0, 0x851023, 0xa4c40000, 
+0x621821, 0x3042ffff, 0x3c010001, 0xa4230ef0, 
+0xaf620ce8, 0x3c020001, 0x94420f08, 0x34420024, 
+0xaf620cec, 0x94c30002, 0x3c020001, 0x94420ef0, 
+0x14620012, 0x3c028000, 0x3c108000, 0x3c02a000, 
+0xaf620cf4, 0x3c010001, 0xa0200ef6, 0x8f641008, 
+0x901024, 0x14400003, 0x0, 0xc004064, 
+0x0, 0x8f620cf4, 0x501024, 0x1440fff7, 
+0x0, 0x80042cf, 0x241a0003, 0xaf620cf4, 
+0x3c108000, 0x8f641008, 0x901024, 0x14400003, 
+0x0, 0xc004064, 0x0, 0x8f620cf4, 
+0x501024, 0x1440fff7, 0x0, 0x80042cf, 
+0x241a0003, 0x3c070001, 0x24e70ef0, 0x94e20000, 
+0x3821021, 0xaf620ce0, 0x3c020001, 0x8c420f04, 
+0xaf620ce4, 0x3c050001, 0x94a50ef4, 0x94e30000, 
+0x3c040001, 0x94840ef8, 0x3c020001, 0x94420efe, 
+0xa32823, 0x822023, 0x30a6ffff, 0x3083ffff, 
+0xc3102b, 0x14400043, 0x0, 0x3c020001, 
+0x94420efc, 0x21400, 0x621025, 0xaf620ce8, 
+0x94e20000, 0x3c030001, 0x94630ef4, 0x441021, 
+0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 
+0x3c020001, 0x90420ef7, 0x10400006, 0x3c03000c, 
+0x3c020001, 0x94420f08, 0x34630624, 0x800427c, 
+0xd021, 0x3c020001, 0x94420f08, 0x3c030008, 
+0x34630624, 0x431025, 0xaf620cec, 0x3c108000, 
+0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200ef6, 
+0x8f641008, 0x901024, 0x14400003, 0x0, 
+0xc004064, 0x0, 0x8f620cf4, 0x501024, 
+0x10400015, 0x0, 0x8004283, 0x0, 
+0x3c030001, 0x94630f08, 0x34420624, 0x3c108000, 
+0x621825, 0x3c028000, 0xaf630cec, 0xaf620cf4, 
+0x8f641008, 0x901024, 0x14400003, 0x0, 
+0xc004064, 0x0, 0x8f620cf4, 0x501024, 
+0x1440fff7, 0x0, 0x3c010001, 0x80042cf, 
+0xa4200efe, 0x3c020001, 0x94420efc, 0x21400, 
+0xc21025, 0xaf620ce8, 0x3c020001, 0x90420ef7, 
+0x10400009, 0x3c03000c, 0x3c020001, 0x94420f08, 
+0x34630624, 0xd021, 0x431025, 0xaf620cec, 
+0x80042c1, 0x3c108000, 0x3c020001, 0x94420f08, 
+0x3c030008, 0x34630604, 0x431025, 0xaf620cec, 
+0x3c020001, 0x94420efe, 0x451021, 0x3c010001, 
+0xa4220efe, 0x3c108000, 0x3c02a000, 0xaf620cf4, 
+0x3c010001, 0xa0200ef6, 0x8f641008, 0x901024, 
+0x14400003, 0x0, 0xc004064, 0x0, 
+0x8f620cf4, 0x501024, 0x1440fff7, 0x0, 
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 
+0x0, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 
+0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 
+0xaf626804, 0x8f634000, 0x24020b50, 0x3c010001, 
+0xac220ec0, 0x24020b78, 0x3c010001, 0xac220ed0, 
+0x34630002, 0xaf634000, 0xc004301, 0x808021, 
+0x3c010001, 0xa0220ed4, 0x304200ff, 0x24030002, 
+0x14430005, 0x0, 0x3c020001, 0x8c420ec0, 
+0x80042f4, 0xac5000c0, 0x3c020001, 0x8c420ec0, 
+0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 
+0x3c010001, 0xac220ec8, 0x3c010001, 0xac230ed8, 
+0x3c010001, 0xac240ec4, 0x8fbf0014, 0x8fb00010, 
+0x3e00008, 0x27bd0018, 0x3e00008, 0x24020001, 
+0x27bdfff8, 0x18800009, 0x2821, 0x8f63680c, 
+0x8f62680c, 0x1043fffe, 0x0, 0x24a50001, 
+0xa4102a, 0x1440fff9, 0x0, 0x3e00008, 
+0x27bd0008, 0x8f634450, 0x3c020001, 0x8c420ec8, 
+0x31c02, 0x43102b, 0x14400008, 0x3c038000, 
+0x3c040001, 0x8c840ed8, 0x8f624450, 0x21c02, 
+0x83102b, 0x1040fffc, 0x3c038000, 0xaf634444, 
+0x8f624444, 0x431024, 0x1440fffd, 0x0, 
+0x8f624448, 0x3e00008, 0x3042ffff, 0x3082ffff, 
+0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 
+0x8004333, 0x2402ffff, 0x822025, 0xaf645c38, 
+0x8f625c30, 0x30420002, 0x1440fffc, 0x1021, 
+0x3e00008, 0x0, 0x8f624450, 0x3c030001, 
+0x8c630ec4, 0x800433c, 0x3042ffff, 0x8f624450, 
+0x3042ffff, 0x43102b, 0x1440fffc, 0x0, 
+0x3e00008, 0x0, 0x27bdffe0, 0x802821, 
+0x3c040001, 0x24840e70, 0x3021, 0x3821, 
+0xafbf0018, 0xafa00010, 0xc004364, 0xafa00014, 
+0x800434b, 0x0, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x3c020001, 0x3442d600, 0x3c030001, 
+0x3463d600, 0x3c040001, 0x3484ddff, 0x3c010001, 
+0xac220ee0, 0x24020040, 0x3c010001, 0xac220ee4, 
+0x3c010001, 0xac200edc, 0xac600000, 0x24630004, 
+0x83102b, 0x5040fffd, 0xac600000, 0x3e00008, 
+0x0, 0x804821, 0x8faa0010, 0x3c020001, 
+0x8c420edc, 0x3c040001, 0x8c840ee4, 0x8fab0014, 
+0x24430001, 0x44102b, 0x3c010001, 0xac230edc, 
+0x14400003, 0x4021, 0x3c010001, 0xac200edc, 
+0x3c020001, 0x8c420edc, 0x3c030001, 0x8c630ee0, 
+0x91240000, 0x21140, 0x431021, 0x481021, 
+0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, 
+0x25290001, 0x3c020001, 0x8c420edc, 0x3c030001, 
+0x8c630ee0, 0x8f64680c, 0x21140, 0x431021, 
+0xac440008, 0xac45000c, 0xac460010, 0xac470014, 
+0xac4a0018, 0x3e00008, 0xac4b001c, 0x0, 
+0x0, 0x0 };
+U32 t3StkOffLd05FwRodata[(0x40/4) + 1] = {
+0x4d61696e, 
+0x43707542, 0x0, 0x4d61696e, 0x43707541, 
+0x0, 0x0, 0x0, 0x73746b6f, 
+0x66666c64, 0x496e0000, 0x0, 0x66617461, 
+0x6c457272, 0x0, 0x0, 0x0 };
+U32 t3StkOffLd05FwData[(0x20/4) + 1] = {
+0x0, 
+0x0, 0x0, 0x0, 0x73746b6f, 
+0x66666c64, 0x5f76312e, 0x302e3000, 0x0 };
+
+
+#endif /* __FW_LSO05_H__   */
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/fw_stkoffld.h orig/drivers/net/bcm/fw_stkoffld.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/fw_stkoffld.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/fw_stkoffld.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,500 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2002 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/*  Name: F W _ S T K O F F L D . H                                           */
+/*  Author : Kevin Tran                                                       */
+/*                                                                            */
+/* Module Description:  This file contains firmware binary code of for TCP/IP */
+/* stack offload support.  Currently, this firmware supports the following    */
+/* features:                                                                  */
+/*     1. TCP segmentation (aka Large Send Offload -- LSO)                    */
+/*     2. UDP Checksum offload support for IP fragmented UDP frames.          */
+/*                                                                            */
+/* History:                                                                   */
+/*    07/17/01 Kevin Tran       Incarnation.                                  */
+/*    10/10/01 Kevin Tran       Added UDP checksum offload support.           */
+/*    10/20/01 Kevin Tran       Fixed a problem where pseudo checksum is not  */
+/*                              calculated correctly in case of IP            */
+/*                              fragmentation case.                           */
+/*    10/30/01 Kevin Tran       Fixed a problem where checksum is incorrectly */
+/*                              computed if bit BD_FLAG_TCP_UDP_CKSUM is set  */
+/*                              in Send BDs.                                  */
+/*    05/30/02 Kevin Tran       Fixed a problem where UDP checksum is         */
+/*                              incorrectly computed if the length of data is */
+/*                              less than 6 bytes in the last packetst of     */
+/*                              of a chain of fragmented IP/UDP packets.      */
+/******************************************************************************/
+
+#ifndef __FW_STKOFFLD_H__ 
+#define __FW_STKOFFLD_H__ 
+
+typedef unsigned long U32;
+
+int t3StkOffLdFwReleaseMajor = 0x1;
+int t3StkOffLdFwReleaseMinor = 0x3;
+int t3StkOffLdFwReleaseFix = 0x0;
+U32 t3StkOffLdFwStartAddr = 0x08000000;
+U32 t3StkOffLdFwTextAddr = 0x08000000;
+int t3StkOffLdFwTextLen = 0x1ac0;
+U32 t3StkOffLdFwRodataAddr = 0x08001ac0;
+int t3StkOffLdFwRodataLen = 0x60;
+U32 t3StkOffLdFwDataAddr = 0x08001b40;
+int t3StkOffLdFwDataLen = 0x20;
+U32 t3StkOffLdFwSbssAddr = 0x08001b60;
+int t3StkOffLdFwSbssLen = 0x2c;
+U32 t3StkOffLdFwBssAddr = 0x08001b90;
+int t3StkOffLdFwBssLen = 0x890;
+U32 t3StkOffLdFwText[(0x1ac0/4) + 1] = {
+0x0, 0x10000003, 0x0, 
+0xd, 0xd, 0x3c1d0800, 0x37bd4000, 
+0x3a0f021, 0x3c100800, 0x26100000, 0xe000010, 
+0x0, 0xd, 0x0, 0x0, 
+0x0, 0x27bdffe0, 0x3c04fefe, 0xafbf0018, 
+0xe0005e0, 0x34840002, 0xe000670, 0x0, 
+0x3c030800, 0x90631b78, 0x24020002, 0x3c040800, 
+0x24841acc, 0x14620003, 0x24050001, 0x3c040800, 
+0x24841ac0, 0x2406000a, 0x3821, 0xafa00010, 
+0xe000684, 0xafa00014, 0x8f625c50, 0x34420001, 
+0xaf625c50, 0x8f625c90, 0x34420001, 0xaf625c90, 
+0x2402ffff, 0xe000034, 0xaf625404, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x0, 0x0, 
+0x0, 0x27bdffe0, 0xafbf0018, 0xafb10014, 
+0xe000052, 0xafb00010, 0x24110001, 0x8f706820, 
+0x32020100, 0x10400003, 0x0, 0xe0000b2, 
+0x0, 0x8f706820, 0x32022000, 0x10400004, 
+0x32020001, 0xe0001e3, 0x24040001, 0x32020001, 
+0x10400003, 0x0, 0xe00009a, 0x0, 
+0xa00003a, 0xaf715028, 0x8fbf0018, 0x8fb10014, 
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe0, 
+0x3c040800, 0x24841ae0, 0x2821, 0x3021, 
+0x3821, 0xafbf0018, 0xafa00010, 0xe000684, 
+0xafa00014, 0x3c040800, 0x248423e8, 0xa4800000, 
+0x3c010800, 0xa0201ba8, 0x3c010800, 0xac201bac, 
+0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4, 
+0x3c010800, 0xac201bbc, 0x3c010800, 0xac201bc8, 
+0x3c010800, 0xac201bcc, 0x8f624434, 0x3c010800, 
+0xac221b98, 0x8f624438, 0x3c010800, 0xac221b9c, 
+0x8f624410, 0xac80f7a8, 0x3c010800, 0xac201b94, 
+0x3c010800, 0xac2023f0, 0x3c010800, 0xac2023d8, 
+0x3c010800, 0xac2023dc, 0x3c010800, 0xac202410, 
+0x3c010800, 0xac221ba0, 0x8f620068, 0x24030007, 
+0x21702, 0x10430005, 0x0, 0x8f620068, 
+0x21702, 0x14400004, 0x24020001, 0x3c010800, 
+0xa00008e, 0xac20241c, 0xac820034, 0x3c040800, 
+0x24841aec, 0x3c050800, 0x8ca5241c, 0x3021, 
+0x3821, 0xafa00010, 0xe000684, 0xafa00014, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 
+0x3c040800, 0x24841af8, 0x2821, 0x3021, 
+0x3821, 0xafbf0018, 0xafa00010, 0xe000684, 
+0xafa00014, 0xe000052, 0x0, 0xe0000ab, 
+0x2021, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
+0x24020001, 0x8f636820, 0x821004, 0x21027, 
+0x621824, 0x3e00008, 0xaf636820, 0x27bdffd0, 
+0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, 
+0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 
+0x8f665c5c, 0x3c030800, 0x24631bcc, 0x8c620000, 
+0x14460005, 0x3c0200ff, 0x3c020800, 0x90421ba8, 
+0x14400115, 0x3c0200ff, 0x3442fff8, 0xc28824, 
+0xac660000, 0x111902, 0x306300ff, 0x30c20003, 
+0x211c0, 0x623825, 0xe02821, 0x61602, 
+0x3c030800, 0x90631ba8, 0x3044000f, 0x1460002b, 
+0x804021, 0x24020001, 0x3c010800, 0xa0221ba8, 
+0x71100, 0x821025, 0x3c010800, 0xac201bac, 
+0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4, 
+0x3c010800, 0xac201bbc, 0x3c010800, 0xac201bc8, 
+0x3c010800, 0xac201bc0, 0x3c010800, 0xac201bc4, 
+0x3c010800, 0xa42223e8, 0x9623000c, 0x30628000, 
+0x10400008, 0x30627fff, 0x2442003e, 0x3c010800, 
+0xa4221ba6, 0x24020001, 0x3c010800, 0xa0000f9, 
+0xac222404, 0x24620036, 0x3c010800, 0xa4221ba6, 
+0x3c010800, 0xac202404, 0x3c010800, 0xac202400, 
+0x3c010800, 0xa000101, 0xac202408, 0x9622000c, 
+0x3c010800, 0xa42223fc, 0x3c040800, 0x24841bac, 
+0x8c820000, 0x21100, 0x3c010800, 0x220821, 
+0xac311bd8, 0x8c820000, 0x21100, 0x3c010800, 
+0x220821, 0xac261bdc, 0x8c820000, 0x24a30001, 
+0x306701ff, 0x21100, 0x3c010800, 0x220821, 
+0xac271be0, 0x8c820000, 0x21100, 0x3c010800, 
+0x220821, 0xac281be4, 0x96230008, 0x3c020800, 
+0x8c421bbc, 0x432821, 0x3c010800, 0xac251bbc, 
+0x9622000a, 0x30420004, 0x14400018, 0x71100, 
+0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, 
+0x3c02c000, 0x8f630c14, 0x3c020800, 0x8c421b50, 
+0x3063000f, 0x24420001, 0x3c010800, 0xac221b50, 
+0x2c620002, 0x1040fff7, 0x3c02c000, 0xc21825, 
+0xaf635c5c, 0x8f625c50, 0x30420002, 0x10400014, 
+0x0, 0xa000133, 0x0, 0x3c030800, 
+0x8c631b90, 0x3c040800, 0x94841ba4, 0x1021025, 
+0x3c010800, 0xa42223ea, 0x24020001, 0x3c010800, 
+0xac221bc8, 0x24630001, 0x85202a, 0x3c010800, 
+0x10800003, 0xac231b90, 0x3c010800, 0xa4251ba4, 
+0x3c060800, 0x24c61bac, 0x8cc20000, 0x24420001, 
+0xacc20000, 0x28420080, 0x14400005, 0x0, 
+0xe00065e, 0x24040002, 0xa0001d9, 0x0, 
+0x3c020800, 0x8c421bc8, 0x1040007f, 0x24020001, 
+0x3c040800, 0x90841ba8, 0x14820077, 0x24020003, 
+0x3c150800, 0x96b51ba6, 0x3c050800, 0x8ca51bbc, 
+0x32a3ffff, 0xa3102a, 0x14400073, 0x0, 
+0x14a30003, 0x0, 0x3c010800, 0xac242400, 
+0x10600061, 0x9021, 0x24d60004, 0x60a021, 
+0x24d30014, 0x8ec20000, 0x28100, 0x3c110800, 
+0x2308821, 0xe00062d, 0x8e311bd8, 0x403021, 
+0x10c00059, 0x0, 0x9628000a, 0x31020040, 
+0x10400004, 0x2407180c, 0x8e22000c, 0x2407188c, 
+0xacc20018, 0x31021000, 0x10400004, 0x34e32000, 
+0x81040, 0x3042c000, 0x623825, 0x3c030800, 
+0x701821, 0x8c631be0, 0x3c020800, 0x501021, 
+0x8c421be4, 0x31d00, 0x21400, 0x621825, 
+0xacc30014, 0x8ec30004, 0x96220008, 0x432023, 
+0x3242ffff, 0x3083ffff, 0x431021, 0x282102a, 
+0x14400002, 0x2b22823, 0x802821, 0x8e620000, 
+0x30a4ffff, 0x441021, 0xae620000, 0x8e220000, 
+0xacc20000, 0x8e220004, 0x8e63fff4, 0x431021, 
+0xacc20004, 0xa4c5000e, 0x8e62fff4, 0x441021, 
+0xae62fff4, 0x96230008, 0x43102a, 0x14400005, 
+0x2459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 
+0xae62fff0, 0xacc00008, 0x3242ffff, 0x14540008, 
+0x24020305, 0x31020080, 0x54400001, 0x34e70010, 
+0x24020905, 0xa4c2000c, 0xa0001bc, 0x34e70020, 
+0xa4c2000c, 0x3c020800, 0x8c422400, 0x10400003, 
+0x3c024b65, 0xa0001c4, 0x34427654, 0x3c02b49a, 
+0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010, 
+0xe0005ac, 0xc02021, 0x3242ffff, 0x54102b, 
+0x1440ffa4, 0x0, 0x24020002, 0x3c010800, 
+0xa0001d9, 0xa0221ba8, 0x8ec2083c, 0x24420001, 
+0xa0001d9, 0xaec2083c, 0x14820003, 0x0, 
+0xe0004bb, 0x0, 0x8fbf002c, 0x8fb60028, 
+0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 
+0x27bdffd0, 0xafbf0028, 0xafb30024, 0xafb20020, 
+0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff, 
+0x3442fff8, 0x3c060800, 0x24c61bc4, 0x2428824, 
+0x9623000e, 0x8cc20000, 0x431021, 0xacc20000, 
+0x8e220010, 0x30420020, 0x14400011, 0x809821, 
+0xe000643, 0x2202021, 0x3c02c000, 0x2421825, 
+0xaf635c9c, 0x8f625c90, 0x30420002, 0x10400121, 
+0x0, 0xaf635c9c, 0x8f625c90, 0x30420002, 
+0x1040011c, 0x0, 0xa000200, 0x0, 
+0x8e240008, 0x8e230014, 0x41402, 0x241c0, 
+0x31502, 0x304201ff, 0x2442ffff, 0x3042007f, 
+0x31942, 0x30637800, 0x21100, 0x24424000, 
+0x625021, 0x9542000a, 0x3084ffff, 0x30420008, 
+0x104000b3, 0x429c0, 0x3c020800, 0x8c422410, 
+0x1440002d, 0x25050008, 0x95020014, 0x3c010800, 
+0xa42223e0, 0x8d070010, 0x71402, 0x3c010800, 
+0xa42223e2, 0x3c010800, 0xa42723e4, 0x9502000e, 
+0x30e3ffff, 0x431023, 0x3c010800, 0xac222418, 
+0x8f626800, 0x3c030010, 0x431024, 0x10400005, 
+0x0, 0x9503001a, 0x9502001c, 0xa000235, 
+0x431021, 0x9502001a, 0x3c010800, 0xac22240c, 
+0x3c02c000, 0x2421825, 0x3c010800, 0xac282410, 
+0x3c010800, 0xac322414, 0xaf635c9c, 0x8f625c90, 
+0x30420002, 0x104000df, 0x0, 0xaf635c9c, 
+0x8f625c90, 0x30420002, 0x104000da, 0x0, 
+0xa000242, 0x0, 0x9502000e, 0x3c030800, 
+0x946323e4, 0x434823, 0x3123ffff, 0x2c620008, 
+0x1040001c, 0x0, 0x95020014, 0x24420028, 
+0xa22821, 0x31042, 0x1840000b, 0x2021, 
+0x24c60848, 0x403821, 0x94a30000, 0x8cc20000, 
+0x24840001, 0x431021, 0xacc20000, 0x87102a, 
+0x1440fff9, 0x24a50002, 0x31220001, 0x1040001f, 
+0x3c024000, 0x3c040800, 0x2484240c, 0xa0a00001, 
+0x94a30000, 0x8c820000, 0x431021, 0xa000281, 
+0xac820000, 0x8f626800, 0x3c030010, 0x431024, 
+0x10400009, 0x0, 0x9502001a, 0x3c030800, 
+0x8c63240c, 0x431021, 0x3c010800, 0xac22240c, 
+0xa000282, 0x3c024000, 0x9502001a, 0x9504001c, 
+0x3c030800, 0x8c63240c, 0x441023, 0x621821, 
+0x3c010800, 0xac23240c, 0x3c024000, 0x2421825, 
+0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 
+0x0, 0x9542000a, 0x30420010, 0x10400095, 
+0x0, 0x3c060800, 0x24c62410, 0x3c020800, 
+0x944223e4, 0x8cc50000, 0x3c040800, 0x8c842418, 
+0x24420030, 0xa22821, 0x94a20004, 0x3c030800, 
+0x8c63240c, 0x441023, 0x621821, 0x603821, 
+0x32402, 0x30e2ffff, 0x823821, 0x71402, 
+0xe23821, 0x71027, 0x3c010800, 0xac23240c, 
+0xa4a20006, 0x3c030800, 0x8c632414, 0x3c0200ff, 
+0x3442fff8, 0x628824, 0x96220008, 0x24040001, 
+0x24034000, 0x241c0, 0xe01021, 0xa502001a, 
+0xa500001c, 0xacc00000, 0x3c010800, 0xac241b70, 
+0xaf635cb8, 0x8f625cb0, 0x30420002, 0x10400003, 
+0x0, 0x3c010800, 0xac201b70, 0x8e220008, 
+0xaf625cb8, 0x8f625cb0, 0x30420002, 0x10400003, 
+0x0, 0x3c010800, 0xac201b70, 0x3c020800, 
+0x8c421b70, 0x1040ffec, 0x0, 0x3c040800, 
+0xe000643, 0x8c842414, 0xa000320, 0x0, 
+0x3c030800, 0x90631ba8, 0x24020002, 0x14620003, 
+0x3c034b65, 0xa0002d7, 0x8021, 0x8e22001c, 
+0x34637654, 0x10430002, 0x24100002, 0x24100001, 
+0x1002021, 0xe000346, 0x2003021, 0x24020003, 
+0x3c010800, 0xa0221ba8, 0x24020002, 0x1202000a, 
+0x24020001, 0x3c030800, 0x8c632400, 0x10620006, 
+0x0, 0x3c020800, 0x944223e8, 0x21400, 
+0xa000315, 0xae220014, 0x3c040800, 0x248423ea, 
+0x94820000, 0x21400, 0xae220014, 0x3c020800, 
+0x8c421bcc, 0x3c03c000, 0x3c010800, 0xa0201ba8, 
+0x431025, 0xaf625c5c, 0x8f625c50, 0x30420002, 
+0x10400009, 0x0, 0x2484f7e2, 0x8c820000, 
+0x431025, 0xaf625c5c, 0x8f625c50, 0x30420002, 
+0x1440fffa, 0x0, 0x3c020800, 0x24421b94, 
+0x8c430000, 0x24630001, 0xac430000, 0x8f630c14, 
+0x3063000f, 0x2c620002, 0x1440000c, 0x3c024000, 
+0x8f630c14, 0x3c020800, 0x8c421b50, 0x3063000f, 
+0x24420001, 0x3c010800, 0xac221b50, 0x2c620002, 
+0x1040fff7, 0x0, 0x3c024000, 0x2421825, 
+0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 
+0x0, 0x12600003, 0x0, 0xe0004bb, 
+0x0, 0x8fbf0028, 0x8fb30024, 0x8fb20020, 
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030, 
+0x8f634450, 0x3c040800, 0x24841b98, 0x8c820000, 
+0x31c02, 0x43102b, 0x14400007, 0x3c038000, 
+0x8c840004, 0x8f624450, 0x21c02, 0x83102b, 
+0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 
+0x431024, 0x1440fffd, 0x0, 0x8f624448, 
+0x3e00008, 0x3042ffff, 0x3c024000, 0x822025, 
+0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 
+0x0, 0x3e00008, 0x0, 0x27bdffe0, 
+0x805821, 0x14c00017, 0x256e0008, 0x3c020800, 
+0x8c422404, 0x1040000a, 0x2402003e, 0x3c010800, 
+0xa42223e0, 0x24020016, 0x3c010800, 0xa42223e2, 
+0x2402002a, 0x3c010800, 0xa000360, 0xa42223e4, 
+0x95620014, 0x3c010800, 0xa42223e0, 0x8d670010, 
+0x71402, 0x3c010800, 0xa42223e2, 0x3c010800, 
+0xa42723e4, 0x3c040800, 0x948423e4, 0x3c030800, 
+0x946323e2, 0x95cf0006, 0x3c020800, 0x944223e0, 
+0x832023, 0x1e2c023, 0x3065ffff, 0x24a20028, 
+0x1c24821, 0x3082ffff, 0x14c0001a, 0x1226021, 
+0x9582000c, 0x3042003f, 0x3c010800, 0xa42223e6, 
+0x95820004, 0x95830006, 0x3c010800, 0xac2023f4, 
+0x3c010800, 0xac2023f8, 0x21400, 0x431025, 
+0x3c010800, 0xac221bd0, 0x95220004, 0x3c010800, 
+0xa4221bd4, 0x95230002, 0x1e51023, 0x43102a, 
+0x10400010, 0x24020001, 0x3c010800, 0xa000394, 
+0xac222408, 0x3c030800, 0x8c6323f8, 0x3c020800, 
+0x94421bd4, 0x431021, 0xa5220004, 0x3c020800, 
+0x94421bd0, 0xa5820004, 0x3c020800, 0x8c421bd0, 
+0xa5820006, 0x3c020800, 0x8c422400, 0x3c0d0800, 
+0x8dad23f4, 0x3c0a0800, 0x144000e7, 0x8d4a23f8, 
+0x3c020800, 0x94421bd4, 0x4a1821, 0x3063ffff, 
+0x62182b, 0x24020002, 0x10c2000d, 0x1435023, 
+0x3c020800, 0x944223e6, 0x30420009, 0x10400008, 
+0x0, 0x9582000c, 0x3042fff6, 0xa582000c, 
+0x3c020800, 0x944223e6, 0x30420009, 0x1a26823, 
+0x3c020800, 0x8c422408, 0x1040004a, 0x1203821, 
+0x3c020800, 0x944223e2, 0x4021, 0xa520000a, 
+0x1e21023, 0xa5220002, 0x3082ffff, 0x21042, 
+0x18400008, 0x3021, 0x401821, 0x94e20000, 
+0x25080001, 0xc23021, 0x103102a, 0x1440fffb, 
+0x24e70002, 0x61c02, 0x30c2ffff, 0x623021, 
+0x61402, 0xc23021, 0xc02821, 0x61027, 
+0xa522000a, 0x3021, 0x2527000c, 0x4021, 
+0x94e20000, 0x25080001, 0xc23021, 0x2d020004, 
+0x1440fffb, 0x24e70002, 0x95220002, 0x4021, 
+0x91230009, 0x442023, 0x1803821, 0x3082ffff, 
+0xa4e00010, 0x621821, 0x21042, 0x18400010, 
+0xc33021, 0x404821, 0x94e20000, 0x24e70002, 
+0xc23021, 0x30e2007f, 0x14400006, 0x25080001, 
+0x8d630000, 0x3c02007f, 0x3442ff80, 0x625824, 
+0x25670008, 0x109102a, 0x1440fff3, 0x0, 
+0x30820001, 0x10400005, 0x61c02, 0xa0e00001, 
+0x94e20000, 0xc23021, 0x61c02, 0x30c2ffff, 
+0x623021, 0x61402, 0xc23021, 0xa00047b, 
+0x30c6ffff, 0x24020002, 0x14c20083, 0x0, 
+0x3c020800, 0x8c42241c, 0x14400007, 0x0, 
+0x3c020800, 0x944223e2, 0x95230002, 0x1e21023, 
+0x10620079, 0x0, 0x3c020800, 0x944223e2, 
+0x1e21023, 0xa5220002, 0x3c020800, 0x8c42241c, 
+0x1040001d, 0x1203821, 0x8dc70010, 0x3c020800, 
+0x94421ba6, 0x31e4ffff, 0xe04021, 0x72c02, 
+0xaa1821, 0x441023, 0x623823, 0x71c02, 
+0x30e2ffff, 0x623821, 0x71402, 0xe23821, 
+0x71027, 0xa522000a, 0x3102ffff, 0x3c030800, 
+0x946323e4, 0x453023, 0xe02821, 0x832023, 
+0x8d2021, 0xc43021, 0x61c02, 0x30c2ffff, 
+0xa00047b, 0x623021, 0x4021, 0x3082ffff, 
+0x21042, 0x18400008, 0x3021, 0x401821, 
+0x94e20000, 0x25080001, 0xc23021, 0x103102a, 
+0x1440fffb, 0x24e70002, 0x61c02, 0x30c2ffff, 
+0x623021, 0x61402, 0xc23021, 0xc02821, 
+0x61027, 0xa522000a, 0x3021, 0x2527000c, 
+0x4021, 0x94e20000, 0x25080001, 0xc23021, 
+0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, 
+0x4021, 0x91230009, 0x442023, 0x1803821, 
+0x3082ffff, 0xa4e00010, 0x3c040800, 0x948423e4, 
+0x621821, 0xc33021, 0x61c02, 0x30c2ffff, 
+0x623021, 0x61c02, 0x3c020800, 0x944223e0, 
+0xc34821, 0x441023, 0x21fc2, 0x431021, 
+0x21043, 0x18400010, 0x3021, 0x402021, 
+0x94e20000, 0x24e70002, 0xc23021, 0x30e2007f, 
+0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 
+0x3442ff80, 0x625824, 0x25670008, 0x104102a, 
+0x1440fff3, 0x0, 0x3c020800, 0x944223fc, 
+0xc23021, 0x3122ffff, 0xc23021, 0x61c02, 
+0x30c2ffff, 0x623021, 0x61402, 0xc23021, 
+0xc04021, 0x61027, 0xa5820010, 0xadc00014, 
+0xa00049b, 0xadc00000, 0x8dc70010, 0xe04021, 
+0x11400007, 0x72c02, 0xaa3021, 0x61402, 
+0x30c3ffff, 0x433021, 0x61402, 0xc22821, 
+0x51027, 0xa522000a, 0x3c030800, 0x946323e4, 
+0x3102ffff, 0x1e21021, 0x433023, 0xcd3021, 
+0x61c02, 0x30c2ffff, 0x623021, 0x61402, 
+0xc23021, 0xc04021, 0x61027, 0xa5820010, 
+0x3102ffff, 0x51c00, 0x431025, 0xadc20010, 
+0x3c020800, 0x8c422404, 0x10400002, 0x25e2fff2, 
+0xa5c20034, 0x3c020800, 0x8c4223f8, 0x3c040800, 
+0x8c8423f4, 0x24420001, 0x3c010800, 0xac2223f8, 
+0x3c020800, 0x8c421bd0, 0x3303ffff, 0x832021, 
+0x3c010800, 0xac2423f4, 0x431821, 0x62102b, 
+0x10400003, 0x2482ffff, 0x3c010800, 0xac2223f4, 
+0x3c010800, 0xac231bd0, 0x3e00008, 0x27bd0020, 
+0x27bdffb8, 0x3c050800, 0x24a51ba8, 0xafbf0044, 
+0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034, 
+0xafb40030, 0xafb3002c, 0xafb20028, 0xafb10024, 
+0xafb00020, 0x90a30000, 0x24020003, 0x146200d5, 
+0x0, 0x3c090800, 0x95291ba6, 0x3c020800, 
+0x944223e0, 0x3c030800, 0x8c631bc0, 0x3c040800, 
+0x8c841bbc, 0x1221023, 0x64182a, 0xa7a9001e, 
+0x106000c8, 0xa7a20016, 0x24be0020, 0x97b6001e, 
+0x24b30018, 0x24b70014, 0x8fc20000, 0x14400008, 
+0x0, 0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 
+0x431021, 0x82202a, 0x148000ba, 0x0, 
+0x97d50818, 0x32a2ffff, 0x104000ad, 0x9021, 
+0x40a021, 0x8821, 0xe00062d, 0x0, 
+0x403021, 0x14c00007, 0x0, 0x3c020800, 
+0x8c4223ec, 0x24420001, 0x3c010800, 0xa0005a0, 
+0xac2223ec, 0x3c100800, 0x2118021, 0x8e101bd8, 
+0x9608000a, 0x31020040, 0x10400004, 0x2407180c, 
+0x8e02000c, 0x2407188c, 0xacc20018, 0x31021000, 
+0x10400004, 0x34e32000, 0x81040, 0x3042c000, 
+0x623825, 0x31020080, 0x54400001, 0x34e70010, 
+0x3c020800, 0x511021, 0x8c421be0, 0x3c030800, 
+0x711821, 0x8c631be4, 0x21500, 0x31c00, 
+0x431025, 0xacc20014, 0x96040008, 0x3242ffff, 
+0x821021, 0x282102a, 0x14400002, 0x2b22823, 
+0x802821, 0x8e020000, 0x2459021, 0xacc20000, 
+0x8e020004, 0xc02021, 0x26310010, 0xac820004, 
+0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010, 
+0x24020305, 0xe0005ac, 0xa482000c, 0x3242ffff, 
+0x54102b, 0x1440ffc0, 0x3242ffff, 0xa000598, 
+0x0, 0x8e620000, 0x8e63fffc, 0x43102a, 
+0x1040006c, 0x0, 0x8e62fff0, 0x28900, 
+0x3c100800, 0x2118021, 0xe00062d, 0x8e101bd8, 
+0x403021, 0x14c00005, 0x0, 0x8e62082c, 
+0x24420001, 0xa0005a0, 0xae62082c, 0x9608000a, 
+0x31020040, 0x10400004, 0x2407180c, 0x8e02000c, 
+0x2407188c, 0xacc20018, 0x31021000, 0x10400004, 
+0x34e32000, 0x81040, 0x3042c000, 0x623825, 
+0x3c020800, 0x511021, 0x8c421be0, 0x3c030800, 
+0x711821, 0x8c631be4, 0x21500, 0x31c00, 
+0x431025, 0xacc20014, 0x8e63fff4, 0x96020008, 
+0x432023, 0x3242ffff, 0x3083ffff, 0x431021, 
+0x2c2102a, 0x10400003, 0x802821, 0x97a9001e, 
+0x1322823, 0x8e620000, 0x30a4ffff, 0x441021, 
+0xae620000, 0xa4c5000e, 0x8e020000, 0xacc20000, 
+0x8e020004, 0x8e63fff4, 0x431021, 0xacc20004, 
+0x8e63fff4, 0x96020008, 0x641821, 0x62102a, 
+0x14400006, 0x2459021, 0x8e62fff0, 0xae60fff4, 
+0x24420001, 0xa00057b, 0xae62fff0, 0xae63fff4, 
+0xacc00008, 0x3242ffff, 0x10560003, 0x31020004, 
+0x10400006, 0x24020305, 0x31020080, 0x54400001, 
+0x34e70010, 0x34e70020, 0x24020905, 0xa4c2000c, 
+0x8ee30000, 0x8ee20004, 0x14620007, 0x3c02b49a, 
+0x8ee20860, 0x54400001, 0x34e70400, 0x3c024b65, 
+0xa000592, 0x34427654, 0x344289ab, 0xacc2001c, 
+0x30e2ffff, 0xacc20010, 0xe0005ac, 0xc02021, 
+0x3242ffff, 0x56102b, 0x1440ff96, 0x0, 
+0x8e620000, 0x8e63fffc, 0x43102a, 0x1440ff3e, 
+0x0, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 
+0x8fb60038, 0x8fb50034, 0x8fb40030, 0x8fb3002c, 
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 
+0x27bd0048, 0x27bdffe8, 0xafbf0014, 0xafb00010, 
+0x8f624450, 0x8f634410, 0xa0005bb, 0x808021, 
+0x8f626820, 0x30422000, 0x10400003, 0x0, 
+0xe0001e3, 0x2021, 0x8f624450, 0x8f634410, 
+0x3042ffff, 0x43102b, 0x1440fff5, 0x0, 
+0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, 
+0x0, 0x8f630c14, 0x3c020800, 0x8c421b50, 
+0x3063000f, 0x24420001, 0x3c010800, 0xac221b50, 
+0x2c620002, 0x1040fff7, 0x0, 0xaf705c18, 
+0x8f625c10, 0x30420002, 0x10400009, 0x0, 
+0x8f626820, 0x30422000, 0x1040fff8, 0x0, 
+0xe0001e3, 0x2021, 0xa0005ce, 0x0, 
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 
+0x0, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 
+0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 
+0xaf626804, 0x8f634000, 0x24020b50, 0x3c010800, 
+0xac221b64, 0x24020b78, 0x3c010800, 0xac221b74, 
+0x34630002, 0xaf634000, 0xe00060d, 0x808021, 
+0x3c010800, 0xa0221b78, 0x304200ff, 0x24030002, 
+0x14430005, 0x0, 0x3c020800, 0x8c421b64, 
+0xa000600, 0xac5000c0, 0x3c020800, 0x8c421b64, 
+0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 
+0x3c010800, 0xac221b6c, 0x3c010800, 0xac231b7c, 
+0x3c010800, 0xac241b68, 0x8fbf0014, 0x8fb00010, 
+0x3e00008, 0x27bd0018, 0x3c040800, 0x8c870000, 
+0x3c03aa55, 0x3463aa55, 0x3c06c003, 0xac830000, 
+0x8cc20000, 0x14430007, 0x24050002, 0x3c0355aa, 
+0x346355aa, 0xac830000, 0x8cc20000, 0x50430001, 
+0x24050001, 0x3c020800, 0xac470000, 0x3e00008, 
+0xa01021, 0x27bdfff8, 0x18800009, 0x2821, 
+0x8f63680c, 0x8f62680c, 0x1043fffe, 0x0, 
+0x24a50001, 0xa4102a, 0x1440fff9, 0x0, 
+0x3e00008, 0x27bd0008, 0x8f634450, 0x3c020800, 
+0x8c421b6c, 0x31c02, 0x43102b, 0x14400008, 
+0x3c038000, 0x3c040800, 0x8c841b7c, 0x8f624450, 
+0x21c02, 0x83102b, 0x1040fffc, 0x3c038000, 
+0xaf634444, 0x8f624444, 0x431024, 0x1440fffd, 
+0x0, 0x8f624448, 0x3e00008, 0x3042ffff, 
+0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 
+0x3c024000, 0xa000650, 0x2402ffff, 0x822025, 
+0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 
+0x1021, 0x3e00008, 0x0, 0x8f624450, 
+0x3c030800, 0x8c631b68, 0xa000659, 0x3042ffff, 
+0x8f624450, 0x3042ffff, 0x43102b, 0x1440fffc, 
+0x0, 0x3e00008, 0x0, 0x27bdffe0, 
+0x802821, 0x3c040800, 0x24841b10, 0x3021, 
+0x3821, 0xafbf0018, 0xafa00010, 0xe000684, 
+0xafa00014, 0xa000668, 0x0, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x0, 0x0, 
+0x0, 0x3c020800, 0x34423000, 0x3c030800, 
+0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 
+0xac221b84, 0x24020040, 0x3c010800, 0xac221b88, 
+0x3c010800, 0xac201b80, 0xac600000, 0x24630004, 
+0x83102b, 0x5040fffd, 0xac600000, 0x3e00008, 
+0x0, 0x804821, 0x8faa0010, 0x3c020800, 
+0x8c421b80, 0x3c040800, 0x8c841b88, 0x8fab0014, 
+0x24430001, 0x44102b, 0x3c010800, 0xac231b80, 
+0x14400003, 0x4021, 0x3c010800, 0xac201b80, 
+0x3c020800, 0x8c421b80, 0x3c030800, 0x8c631b84, 
+0x91240000, 0x21140, 0x431021, 0x481021, 
+0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, 
+0x25290001, 0x3c020800, 0x8c421b80, 0x3c030800, 
+0x8c631b84, 0x8f64680c, 0x21140, 0x431021, 
+0xac440008, 0xac45000c, 0xac460010, 0xac470014, 
+0xac4a0018, 0x3e00008, 0xac4b001c, 0x0, 
+0x0, 0x0 };
+U32 t3StkOffLdFwRodata[(0x60/4) + 1] = {
+0x4d61696e, 
+0x43707542, 0x0, 0x4d61696e, 0x43707541, 
+0x0, 0x0, 0x0, 0x73746b6f, 
+0x66666c64, 0x496e0000, 0x73746b6f, 0x66662a2a, 
+0x0, 0x53774576, 0x656e7430, 0x0, 
+0x0, 0x0, 0x0, 0x66617461, 
+0x6c457272, 0x0, 0x0, 0x0 };
+U32 t3StkOffLdFwData[(0x20/4) + 1] = {
+0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0 };
+
+#endif /* __FW_STKOFFLD_H__  */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/lm.h orig/drivers/net/bcm/lm.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/lm.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/lm.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,448 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef LM_H
+#define LM_H
+
+#include "queue.h"
+#include "bits.h"
+
+
+
+/******************************************************************************/
+/* Basic types. */
+/******************************************************************************/
+
+typedef char           LM_CHAR,    *PLM_CHAR;
+typedef unsigned int   LM_UINT,    *PLM_UINT;
+typedef unsigned char  LM_UINT8,   *PLM_UINT8;
+typedef unsigned short LM_UINT16,  *PLM_UINT16;
+typedef unsigned int   LM_UINT32,  *PLM_UINT32;
+typedef unsigned int   LM_COUNTER, *PLM_COUNTER;
+typedef void           LM_VOID,    *PLM_VOID;
+typedef char           LM_BOOL,    *PLM_BOOL;
+
+/* 64bit value. */
+typedef struct {
+#ifdef BIG_ENDIAN_HOST
+    LM_UINT32 High;
+    LM_UINT32 Low;
+#else /* BIG_ENDIAN_HOST */
+    LM_UINT32 Low;
+    LM_UINT32 High;
+#endif /* !BIG_ENDIAN_HOST */
+} LM_UINT64, *PLM_UINT64;
+
+typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
+
+/* void LM_INC_PHYSICAL_ADDRESS(PLM_PHYSICAL_ADDRESS pAddr,LM_UINT32 IncSize) */
+#define LM_INC_PHYSICAL_ADDRESS(pAddr, IncSize)             \
+    {                                                       \
+        LM_UINT32 OrgLow;                                   \
+                                                            \
+        OrgLow = (pAddr)->Low;                              \
+        (pAddr)->Low += IncSize;                            \
+        if((pAddr)->Low < OrgLow) {                         \
+            (pAddr)->High++; /* Wrap around. */             \
+        }                                                   \
+    }
+    
+
+#ifndef TRUE
+#define TRUE           1
+#endif /* TRUE */
+
+#ifndef FALSE
+#define FALSE          0
+#endif /* FALSE */
+
+#ifndef NULL
+#define NULL                ((void *) 0)
+#endif /* NULL */
+
+#ifndef OFFSETOF
+#define OFFSETOF(_s, _m)    (MM_UINT_PTR(&(((_s *) 0)->_m)))
+#endif /* OFFSETOF */
+
+
+
+/******************************************************************************/
+/* Simple macros. */
+/******************************************************************************/
+
+#define IS_ETH_BROADCAST(_pEthAddr)                                         \
+    (((unsigned char *) (_pEthAddr))[0] == ((unsigned char) 0xff))
+
+#define IS_ETH_MULTICAST(_pEthAddr)                                         \
+    (((unsigned char *) (_pEthAddr))[0] & ((unsigned char) 0x01))
+
+#define IS_ETH_ADDRESS_EQUAL(_pEtherAddr1, _pEtherAddr2)                    \
+    ((((unsigned char *) (_pEtherAddr1))[0] ==                              \
+    ((unsigned char *) (_pEtherAddr2))[0]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[1] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[1]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[2] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[2]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[3] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[3]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[4] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[4]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[5] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[5]))
+
+#define COPY_ETH_ADDRESS(_Src, _Dst)                                        \
+    ((unsigned char *) (_Dst))[0] = ((unsigned char *) (_Src))[0];          \
+    ((unsigned char *) (_Dst))[1] = ((unsigned char *) (_Src))[1];          \
+    ((unsigned char *) (_Dst))[2] = ((unsigned char *) (_Src))[2];          \
+    ((unsigned char *) (_Dst))[3] = ((unsigned char *) (_Src))[3];          \
+    ((unsigned char *) (_Dst))[4] = ((unsigned char *) (_Src))[4];          \
+    ((unsigned char *) (_Dst))[5] = ((unsigned char *) (_Src))[5];
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+#define ETHERNET_ADDRESS_SIZE           6
+#define ETHERNET_PACKET_HEADER_SIZE     14
+#define MIN_ETHERNET_PACKET_SIZE        64      /* with 4 byte crc. */
+#define MAX_ETHERNET_PACKET_SIZE        1518    /* with 4 byte crc. */
+#define MIN_ETHERNET_PACKET_SIZE_NO_CRC 60
+#define MAX_ETHERNET_PACKET_SIZE_NO_CRC 1514
+#define MAX_ETHERNET_PACKET_BUFFER_SIZE 1536    /* A nice even number. */
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE_NO_CRC 9014
+
+#ifndef LM_MAX_MC_TABLE_SIZE
+#define LM_MAX_MC_TABLE_SIZE            32
+#endif /* LM_MAX_MC_TABLE_SIZE */
+#define LM_MC_ENTRY_SIZE                (ETHERNET_ADDRESS_SIZE+1)
+#define LM_MC_INSTANCE_COUNT_INDEX      (LM_MC_ENTRY_SIZE-1)
+
+
+/* Receive filter masks. */
+#define LM_ACCEPT_UNICAST               0x0001
+#define LM_ACCEPT_MULTICAST             0x0002
+#define LM_ACCEPT_ALL_MULTICAST         0x0004
+#define LM_ACCEPT_BROADCAST             0x0008
+#define LM_ACCEPT_ERROR_PACKET          0x0010
+#define LM_KEEP_VLAN_TAG                0x0020
+
+#define LM_PROMISCUOUS_MODE             0x10000
+
+
+
+/******************************************************************************/
+/* PCI registers. */
+/******************************************************************************/
+
+#define PCI_VENDOR_ID_REG               0x00
+#define PCI_DEVICE_ID_REG               0x02
+
+#define PCI_COMMAND_REG                 0x04
+#define PCI_IO_SPACE_ENABLE             0x0001
+#define PCI_MEM_SPACE_ENABLE            0x0002
+#define PCI_BUSMASTER_ENABLE            0x0004
+#define PCI_MEMORY_WRITE_INVALIDATE     0x0010
+#define PCI_PARITY_ERROR_ENABLE         0x0040
+#define PCI_SYSTEM_ERROR_ENABLE         0x0100
+#define PCI_FAST_BACK_TO_BACK_ENABLE    0x0200
+
+#define PCI_STATUS_REG                  0x06
+#define PCI_REV_ID_REG                  0x08
+
+#define PCI_CACHE_LINE_SIZE_REG         0x0c
+
+#define PCI_IO_BASE_ADDR_REG            0x10
+#define PCI_IO_BASE_ADDR_MASK           0xfffffff0
+
+#define PCI_MEM_BASE_ADDR_LOW           0x10
+#define PCI_MEM_BASE_ADDR_HIGH          0x14
+
+#define PCI_SUBSYSTEM_VENDOR_ID_REG     0x2c
+#define PCI_SUBSYSTEM_ID_REG            0x2e
+#define PCI_INT_LINE_REG                0x3c
+
+#define PCIX_CAP_REG                    0x40
+#define PCIX_ENABLE_RELAXED_ORDERING    BIT_17
+
+/******************************************************************************/
+/* Fragment structure. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT32 FragSize;
+    LM_PHYSICAL_ADDRESS FragBuf;
+} LM_FRAG, *PLM_FRAG;
+
+typedef struct {
+    /* FragCount is initialized for the caller to the maximum array size, on */
+    /* return FragCount is the number of the actual fragments in the array. */
+    LM_UINT32 FragCount;
+
+    /* Total buffer size. */
+    LM_UINT32 TotalSize;
+
+    /* Fragment array buffer. */
+    LM_FRAG Fragments[1];
+} LM_FRAG_LIST, *PLM_FRAG_LIST;
+
+#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \
+    typedef struct {                                                         \
+        LM_FRAG_LIST FragList;                                               \
+        LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1];                           \
+    } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME
+
+
+
+/******************************************************************************/
+/* Status codes. */
+/******************************************************************************/
+
+#define LM_STATUS_SUCCESS                                       0
+#define LM_STATUS_FAILURE                                       1
+
+#define LM_STATUS_INTERRUPT_ACTIVE                              2
+#define LM_STATUS_INTERRUPT_NOT_ACTIVE                          3
+
+#define LM_STATUS_LINK_ACTIVE                                   4
+#define LM_STATUS_LINK_DOWN                                     5
+#define LM_STATUS_LINK_SETTING_MISMATCH                         6
+
+#define LM_STATUS_TOO_MANY_FRAGMENTS                            7
+#define LM_STATUS_TRANSMIT_ABORTED                              8
+#define LM_STATUS_TRANSMIT_ERROR                                9
+#define LM_STATUS_RECEIVE_ABORTED                               10
+#define LM_STATUS_RECEIVE_ERROR                                 11
+#define LM_STATUS_INVALID_PACKET_SIZE                           12
+#define LM_STATUS_OUT_OF_MAP_REGISTERS                          13
+#define LM_STATUS_UNKNOWN_ADAPTER                               14
+
+typedef LM_UINT LM_STATUS, *PLM_STATUS;
+
+
+/******************************************************************************/
+/* Line speed. */
+/******************************************************************************/
+
+#define LM_LINE_SPEED_UNKNOWN                                   0
+#define LM_LINE_SPEED_AUTO                  LM_LINE_SPEED_UNKNOWN
+#define LM_LINE_SPEED_10MBPS                                    10
+#define LM_LINE_SPEED_100MBPS                                   100
+#define LM_LINE_SPEED_1000MBPS                                  1000
+
+typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED;
+
+
+
+/******************************************************************************/
+/* Duplex mode. */
+/******************************************************************************/
+
+#define LM_DUPLEX_MODE_UNKNOWN                                  0
+#define LM_DUPLEX_MODE_HALF                                     1
+#define LM_DUPLEX_MODE_FULL                                     2
+
+typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE;
+
+
+
+/******************************************************************************/
+/* Power state. */
+/******************************************************************************/
+
+#define LM_POWER_STATE_D0       0
+#define LM_POWER_STATE_D1       1
+#define LM_POWER_STATE_D2       2
+#define LM_POWER_STATE_D3       3
+
+typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE;
+
+
+
+/******************************************************************************/
+/* Task offloading. */
+/******************************************************************************/
+
+#define LM_TASK_OFFLOAD_NONE                    0x0000
+#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM          0x0001
+#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM          0x0002
+#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM         0x0004
+#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM         0x0008
+#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM         0x0010
+#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM         0x0020
+#define LM_TASK_OFFLOAD_TCP_SEGMENTATION        0x0040
+
+typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD;
+
+
+
+/******************************************************************************/
+/* Flow control. */
+/******************************************************************************/
+
+#define LM_FLOW_CONTROL_NONE                    0x00
+#define LM_FLOW_CONTROL_RECEIVE_PAUSE           0x01
+#define LM_FLOW_CONTROL_TRANSMIT_PAUSE          0x02
+#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \
+    LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+
+/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE.  If the */
+/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */
+/* bits are set, then flow control is enabled regardless of link partner's */
+/* flow control capability. */
+#define LM_FLOW_CONTROL_AUTO_PAUSE              0x80000000
+
+typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL;
+
+
+
+/******************************************************************************/
+/* Wake up mode. */
+/******************************************************************************/
+
+#define LM_WAKE_UP_MODE_NONE                    0
+#define LM_WAKE_UP_MODE_MAGIC_PACKET            1
+#define LM_WAKE_UP_MODE_NWUF                    2
+#define LM_WAKE_UP_MODE_LINK_CHANGE             4
+
+typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE;
+
+
+
+/******************************************************************************/
+/* Counters. */
+/******************************************************************************/
+
+#define LM_COUNTER_FRAMES_XMITTED_OK                            0
+#define LM_COUNTER_FRAMES_RECEIVED_OK                           1
+#define LM_COUNTER_ERRORED_TRANSMIT_COUNT                       2
+#define LM_COUNTER_ERRORED_RECEIVE_COUNT                        3
+#define LM_COUNTER_RCV_CRC_ERROR                                4
+#define LM_COUNTER_ALIGNMENT_ERROR                              5
+#define LM_COUNTER_SINGLE_COLLISION_FRAMES                      6
+#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES                    7
+#define LM_COUNTER_FRAMES_DEFERRED                              8
+#define LM_COUNTER_MAX_COLLISIONS                               9
+#define LM_COUNTER_RCV_OVERRUN                                  10
+#define LM_COUNTER_XMIT_UNDERRUN                                11
+#define LM_COUNTER_UNICAST_FRAMES_XMIT                          12
+#define LM_COUNTER_MULTICAST_FRAMES_XMIT                        13
+#define LM_COUNTER_BROADCAST_FRAMES_XMIT                        14
+#define LM_COUNTER_UNICAST_FRAMES_RCV                           15
+#define LM_COUNTER_MULTICAST_FRAMES_RCV                         16
+#define LM_COUNTER_BROADCAST_FRAMES_RCV                         17
+
+typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE;
+
+
+
+/******************************************************************************/
+/* Forward definition. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK;
+typedef struct _LM_PACKET *PLM_PACKET;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+LM_STATUS LM_GetAdapterInfo(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_InitializeAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_ResetAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_DisableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_EnableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS LM_ServiceInterrupts(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask);
+LM_STATUS LM_Halt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_ResetChip(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_MulticastAdd(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastDel(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS LM_MulticastClear(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_SetMacAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress);
+LM_STATUS LM_LoopbackAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress);
+
+LM_UINT32 LM_GetCrcCounter(PLM_DEVICE_BLOCK pDevice);
+
+LM_WAKE_UP_MODE LM_PMCapabilities(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_NwufAdd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+    LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_NwufRemove(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize,
+    LM_UINT8 *pByteMask, LM_UINT8 *pPattern);
+LM_STATUS LM_SetPowerState(PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel);
+
+LM_VOID LM_ReadPhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    PLM_UINT32 pData32);
+LM_VOID LM_WritePhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    LM_UINT32 Data32);
+
+LM_STATUS LM_EnableMacLoopBack(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_DisableMacLoopBack(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_EnablePhyLoopBack(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_DisablePhyLoopBack(PLM_DEVICE_BLOCK pDevice);
+
+LM_STATUS LM_SetupPhy(PLM_DEVICE_BLOCK pDevice);
+int LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration);
+LM_STATUS LM_GetStats(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_NvramRead(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 *pData);
+LM_STATUS LM_NvramWriteBlock(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 *pData, LM_UINT32 Size);
+
+
+
+/******************************************************************************/
+/* These are the OS specific functions called by LMAC. */
+/******************************************************************************/
+
+LM_STATUS MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT16 *pValue16);
+LM_STATUS MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT16 Value16);
+LM_STATUS MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 *pValue32);
+LM_STATUS MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 Value32);
+LM_STATUS MM_MapMemBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_MapIoBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, 
+    PLM_VOID *pMemoryBlockVirt);
+LM_STATUS MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+    PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
+    LM_BOOL Cached);
+LM_STATUS MM_GetConfig(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status);
+LM_STATUS MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+PLM_DEVICE_BLOCK MM_FindPeerDev(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_MbufWorkAround(PLM_DEVICE_BLOCK pDevice);
+
+#if INCLUDE_5703_A0_FIX
+LM_STATUS LM_Load5703DmaWFirmware(PLM_DEVICE_BLOCK pDevice);
+#endif
+
+
+#endif /* LM_H */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/mm.h orig/drivers/net/bcm/mm.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/mm.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/mm.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,496 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef MM_H
+#define MM_H
+
+#include <linux/config.h>
+#if defined(CONFIG_SMP) && ! defined(__SMP__)
+#define __SMP__
+#endif
+#if defined(CONFIG_MODVERSIONS) && defined(MODULE) && ! defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+
+#ifndef B57UM
+#define __NO_VERSION__
+#endif
+#include <linux/version.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#define SET_MODULE_OWNER(dev)
+#define MODULE_DEVICE_TABLE(pci, pci_tbl)
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <asm/processor.h>		/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/time.h>
+#if (LINUX_VERSION_CODE >= 0x020400)
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+#endif
+#ifdef CONFIG_PROC_FS
+#include <linux/smp_lock.h>
+#include <linux/proc_fs.h>
+#define BCM_PROC_FS 1
+#endif
+#ifdef NETIF_F_HW_VLAN_TX
+#include <linux/if_vlan.h>
+#define BCM_VLAN 1
+#endif
+#ifdef NETIF_F_TSO
+#define BCM_TSO 1
+#define INCLUDE_TCP_SEG_SUPPORT 1
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/checksum.h>
+#endif
+
+#if (LINUX_VERSION_CODE >= 0x020400)
+#ifndef ETHTOOL_GEEPROM
+
+#define ETHTOOL_GEEPROM		0x0000000b /* Get EEPROM data */
+#define ETHTOOL_SEEPROM		0x0000000c /* Set EEPROM data */
+
+/* for passing EEPROM chunks */
+struct ethtool_eeprom {
+	u32	cmd;
+	u32	magic;
+	u32	offset; /* in bytes */
+	u32	len; /* in bytes */
+	u8	data[0];
+};
+#define BCM_EEDUMP_LEN(info_p, size) *((u32 *) &((info_p)->reserved1[24]))=size
+
+#else
+
+#define BCM_EEDUMP_LEN(info_p, size) (info_p)->eedump_len=size
+
+#endif
+#endif
+
+#define BCM_INT_COAL 1
+#define BCM_NIC_SEND_BD 1
+#define BCM_ASF 1
+#define BCM_WOL 1
+#define BCM_TASKLET 1
+
+#ifdef BCM_SMALL_DRV
+#undef BCM_PROC_FS
+#undef ETHTOOL_GEEPROM
+#undef ETHTOOL_SEEPROM
+#undef BCM_INT_COAL
+#undef BCM_NIC_SEND_BD
+#undef BCM_ASF
+#undef BCM_WOL
+#undef NICE_SUPPORT
+#undef BCM_TASKLET
+#undef BCM_TSO
+#endif
+
+#ifdef __BIG_ENDIAN
+#define BIG_ENDIAN_HOST 1
+#endif
+
+#define MM_SWAP_LE32(x) cpu_to_le32(x)
+
+#if (LINUX_VERSION_CODE < 0x020327)
+#define __raw_readl readl
+#define __raw_writel writel
+#endif
+
+#define MM_MEMWRITEL(ptr, val) __raw_writel(val, ptr)
+#define MM_MEMREADL(ptr) __raw_readl(ptr)
+
+typedef atomic_t MM_ATOMIC_T;
+
+#define MM_ATOMIC_SET(ptr, val) atomic_set(ptr, val)
+#define MM_ATOMIC_READ(ptr) atomic_read(ptr)
+#define MM_ATOMIC_INC(ptr) atomic_inc(ptr)
+#define MM_ATOMIC_ADD(ptr, val) atomic_add(val, ptr)
+#define MM_ATOMIC_DEC(ptr) atomic_dec(ptr)
+#define MM_ATOMIC_SUB(ptr, val) atomic_sub(val, ptr)
+
+#define MM_MB() mb()
+#define MM_WMB() wmb()
+
+#include "lm.h"
+#include "queue.h"
+#include "tigon3.h"
+
+#if DBG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+extern int MM_Packet_Desc_Size;
+
+#define MM_PACKET_DESC_SIZE MM_Packet_Desc_Size
+
+DECLARE_QUEUE_TYPE(UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT+1);
+
+#define MAX_MEM 16
+
+#if (LINUX_VERSION_CODE < 0x020211)
+typedef u32 dma_addr_t;
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032a)
+#define pci_map_single(dev, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(dev, dma_addr, size, dir)
+#endif
+
+#if MAX_SKB_FRAGS
+#if (LINUX_VERSION_CODE >= 0x02040d)
+
+typedef dma_addr_t dmaaddr_high_t;
+
+#else
+
+#if defined(CONFIG_HIGHMEM) && defined(CONFIG_X86) && ! defined(CONFIG_X86_64)
+
+#if defined(CONFIG_HIGHMEM64G)
+typedef unsigned long long dmaaddr_high_t;
+#else
+typedef dma_addr_t dmaaddr_high_t;
+#endif
+
+#ifndef pci_map_page
+#define pci_map_page bcm_pci_map_page
+#endif
+
+static inline dmaaddr_high_t
+bcm_pci_map_page(struct pci_dev *dev, struct page *page,
+		    int offset, size_t size, int dir)
+{
+	dmaaddr_high_t phys;
+
+	phys = (page-mem_map) *	(dmaaddr_high_t) PAGE_SIZE + offset;
+
+	return phys;
+}
+
+#ifndef pci_unmap_page
+#define pci_unmap_page(dev, map, size, dir)
+#endif
+
+#else /* #if defined(CONFIG_HIGHMEM) && defined(CONFIG_X86) && ! defined(CONFIG_X86_64)*/
+
+typedef dma_addr_t dmaaddr_high_t;
+
+/* Warning - This may not work for all architectures if HIGHMEM is defined */
+
+#ifndef pci_map_page
+#define pci_map_page(dev, page, offset, size, dir) \
+	pci_map_single(dev, page_address(page) + (offset), size, dir)
+#endif
+#ifndef pci_unmap_page
+#define pci_unmap_page(dev, map, size, dir) \
+	pci_unmap_single(dev, map, size, dir)
+#endif
+
+#endif /* #if defined(CONFIG_HIGHMEM) && defined(CONFIG_X86) && ! defined(CONFIG_X86_64)*/
+
+#endif /* #if (LINUX_VERSION_CODE >= 0x02040d)*/
+#endif /* #if MAX_SKB_FRAGS*/
+
+#if defined (CONFIG_X86) && ! defined(CONFIG_X86_64)
+#define NO_PCI_UNMAP 1
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020412)
+#if ! defined (NO_PCI_UNMAP)
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME;
+
+#define pci_unmap_addr(PTR, ADDR_NAME)	\
+	((PTR)->ADDR_NAME)
+
+#define pci_unmap_len(PTR, LEN_NAME)	\
+	((PTR)->LEN_NAME)
+
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	\
+	(((PTR)->ADDR_NAME) = (VAL))
+
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	\
+	(((PTR)->LEN_NAME) = (VAL))
+#else
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(ADDR_NAME)
+
+#define pci_unmap_addr(PTR, ADDR_NAME)	0
+#define pci_unmap_len(PTR, LEN_NAME)	0
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02030e)
+#define net_device device
+#define netif_carrier_on(dev)
+#define netif_carrier_off(dev)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+#define tasklet_struct			tq_struct
+#endif
+
+typedef struct _UM_DEVICE_BLOCK {
+	LM_DEVICE_BLOCK lm_dev;
+	struct net_device *dev;
+	struct pci_dev *pdev;
+	struct net_device *next_module;
+	char *name;
+#ifdef BCM_PROC_FS
+	struct proc_dir_entry *pfs_entry;
+	char pfs_name[32];
+#endif
+	void *mem_list[MAX_MEM];
+	dma_addr_t dma_list[MAX_MEM];
+	int mem_size_list[MAX_MEM];
+	int mem_list_num;
+	int index;
+	int opened;
+	int suspended;
+	int delayed_link_ind; /* Delay link status during initial load */
+	int adapter_just_inited; /* the first few seconds after init. */
+	int timer_interval;
+	int adaptive_expiry;
+	int crc_counter_expiry;
+	int poll_tbi_expiry;
+	int asf_heartbeat;
+	int tx_full;
+	int tx_queued;
+	int line_speed;		/* in Mbps, 0 if link is down */
+	UM_RX_PACKET_Q rx_out_of_buf_q;
+	int rx_out_of_buf;
+	int rx_buf_repl_thresh;
+	int rx_buf_repl_panic_thresh;
+	int rx_buf_align;
+	struct timer_list timer;
+	int do_global_lock;
+	spinlock_t global_lock;
+	spinlock_t undi_lock;
+	spinlock_t phy_lock;
+	unsigned long undi_flags;
+	volatile unsigned long interrupt;
+	atomic_t intr_sem;
+	int tasklet_pending;
+	volatile unsigned long tasklet_busy;
+	struct tasklet_struct tasklet;
+	struct net_device_stats stats;
+#ifdef NICE_SUPPORT
+	void (*nice_rx)( struct sk_buff*, void* );
+	void* nice_ctx;
+	int intr_test;
+	int intr_test_result;
+#endif /* NICE_SUPPORT */
+#ifdef NETIF_F_HW_VLAN_TX
+	struct vlan_group *vlgrp;
+#endif
+	int adaptive_coalesce;
+	uint rx_last_cnt;
+	uint tx_last_cnt;
+	uint rx_curr_coalesce_frames;
+	uint rx_curr_coalesce_frames_intr;
+	uint rx_curr_coalesce_ticks;
+	uint tx_curr_coalesce_frames;
+#if TIGON3_DEBUG
+	unsigned long tx_zc_count;
+	unsigned long tx_chksum_count;
+	unsigned long tx_himem_count;
+	unsigned long rx_good_chksum_count;
+#endif
+	unsigned long rx_bad_chksum_count;
+#ifdef BCM_TSO
+	unsigned long tso_pkt_count;
+#endif
+	unsigned long rx_misc_errors;
+} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK;
+
+typedef struct _UM_PACKET {
+	LM_PACKET lm_packet;
+	struct sk_buff *skbuff;
+#if MAX_SKB_FRAGS
+	DECLARE_PCI_UNMAP_ADDR(map[MAX_SKB_FRAGS + 1])
+	DECLARE_PCI_UNMAP_LEN(map_len[MAX_SKB_FRAGS + 1])
+#else
+	DECLARE_PCI_UNMAP_ADDR(map[1])
+	DECLARE_PCI_UNMAP_LEN(map_len[1])
+#endif
+} UM_PACKET, *PUM_PACKET;
+
+static inline void MM_SetAddr(LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr)
+{
+#if (BITS_PER_LONG == 64)
+	paddr->High = ((unsigned long) addr) >> 32;
+	paddr->Low = ((unsigned long) addr) & 0xffffffff;
+#else
+	paddr->High = 0;
+	paddr->Low = (unsigned long) addr;
+#endif
+}
+
+static inline void MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr)
+{
+#if (BITS_PER_LONG == 64)
+	paddr->High = ((unsigned long) addr) >> 32;
+	paddr->Low = ((unsigned long) addr) & 0xffffffff;
+#else
+	paddr->High = 0;
+	paddr->Low = (unsigned long) addr;
+#endif
+}
+
+#if MAX_SKB_FRAGS
+static inline void MM_SetT3AddrHigh(T3_64BIT_HOST_ADDR *paddr,
+	dmaaddr_high_t addr)
+{
+#if defined(CONFIG_HIGHMEM64G) && defined(CONFIG_X86) && ! defined(CONFIG_X86_64)
+	paddr->High = (unsigned long) (addr >> 32);
+	paddr->Low = (unsigned long) (addr & 0xffffffff);
+#else
+	MM_SetT3Addr(paddr, (dma_addr_t) addr);
+#endif
+}
+#endif
+
+static inline void MM_MapRxDma(PLM_DEVICE_BLOCK pDevice,
+	struct _LM_PACKET *pPacket,
+	T3_64BIT_HOST_ADDR *paddr)
+{
+	dma_addr_t map;
+	struct sk_buff *skb = ((struct _UM_PACKET *) pPacket)->skbuff;
+
+	map = pci_map_single(((struct _UM_DEVICE_BLOCK *)pDevice)->pdev,
+			skb->tail,
+			pPacket->u.Rx.RxBufferSize,
+			PCI_DMA_FROMDEVICE);
+	pci_unmap_addr_set(((struct _UM_PACKET *) pPacket), map[0], map);
+	MM_SetT3Addr(paddr, map);
+}
+
+static inline void MM_MapTxDma(PLM_DEVICE_BLOCK pDevice,
+	struct _LM_PACKET *pPacket,
+	T3_64BIT_HOST_ADDR *paddr,
+	LM_UINT32 *len,
+	int frag)
+{
+	dma_addr_t map;
+	struct sk_buff *skb = ((struct _UM_PACKET *) pPacket)->skbuff;
+	unsigned int length;
+
+	if (frag == 0) {
+#if MAX_SKB_FRAGS
+		if (skb_shinfo(skb)->nr_frags)
+			length = skb->len - skb->data_len;
+		else
+#endif
+			length = skb->len;
+		map = pci_map_single(((struct _UM_DEVICE_BLOCK *)pDevice)->pdev,
+			skb->data, length, PCI_DMA_TODEVICE);
+		MM_SetT3Addr(paddr, map);
+		pci_unmap_addr_set(((struct _UM_PACKET *)pPacket), map[0], map);
+		pci_unmap_len_set(((struct _UM_PACKET *) pPacket), map_len[0],
+			length);
+		*len = length;
+	}
+#if MAX_SKB_FRAGS
+	else {
+		skb_frag_t *sk_frag;
+		dmaaddr_high_t hi_map;
+
+		sk_frag = &skb_shinfo(skb)->frags[frag - 1];
+			
+		hi_map = pci_map_page(
+				((struct _UM_DEVICE_BLOCK *)pDevice)->pdev,
+				sk_frag->page,
+				sk_frag->page_offset,
+				sk_frag->size, PCI_DMA_TODEVICE);
+
+		MM_SetT3AddrHigh(paddr, hi_map);
+		pci_unmap_addr_set(((struct _UM_PACKET *) pPacket), map[frag],
+			hi_map);
+		pci_unmap_len_set(((struct _UM_PACKET *) pPacket),
+			map_len[frag], sk_frag->size);
+		*len = sk_frag->size;
+	}
+#endif
+}
+
+#define MM_ACQUIRE_UNDI_LOCK(_pDevice) \
+	if (!(((PUM_DEVICE_BLOCK)(_pDevice))->do_global_lock)) {	\
+		unsigned long flags;					\
+		spin_lock_irqsave(&((PUM_DEVICE_BLOCK)(_pDevice))->undi_lock, flags);	\
+		((PUM_DEVICE_BLOCK)(_pDevice))->undi_flags = flags; \
+	}
+
+#define MM_RELEASE_UNDI_LOCK(_pDevice) \
+	if (!(((PUM_DEVICE_BLOCK)(_pDevice))->do_global_lock)) {	\
+		unsigned long flags = ((PUM_DEVICE_BLOCK) (_pDevice))->undi_flags; \
+		spin_unlock_irqrestore(&((PUM_DEVICE_BLOCK)(_pDevice))->undi_lock, flags); \
+	}
+
+#define MM_ACQUIRE_PHY_LOCK_IN_IRQ(_pDevice) \
+	if (!(((PUM_DEVICE_BLOCK)(_pDevice))->do_global_lock)) {	\
+		spin_lock(&((PUM_DEVICE_BLOCK)(_pDevice))->phy_lock);	\
+	}
+
+#define MM_RELEASE_PHY_LOCK_IN_IRQ(_pDevice) \
+	if (!(((PUM_DEVICE_BLOCK)(_pDevice))->do_global_lock)) {	\
+		spin_unlock(&((PUM_DEVICE_BLOCK)(_pDevice))->phy_lock); \
+	}
+
+#define MM_UINT_PTR(_ptr)   ((unsigned long) (_ptr))
+
+#if (BITS_PER_LONG == 64)
+#define MM_GETSTATS(_Ctr) \
+	(unsigned long) (_Ctr).Low + ((unsigned long) (_Ctr).High << 32)
+#else
+#define MM_GETSTATS(_Ctr) \
+	(unsigned long) (_Ctr).Low
+#endif
+
+
+#define DbgPrint(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
+#if defined(CONFIG_X86)
+#define DbgBreakPoint() __asm__("int $129")
+#else
+#define DbgBreakPoint()
+#endif
+#define MM_Wait(time) udelay(time)
+
+#endif
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/nicext.h orig/drivers/net/bcm/nicext.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/nicext.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/nicext.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,139 @@
+/****************************************************************************
+ * Copyright(c) 2000-2003 Broadcom Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.          
+ *
+ * Name:        nicext.h
+ *
+ * Description: Broadcom Network Interface Card Extension (NICE) is an 
+ *              extension to Linux NET device kernel mode drivers. 
+ *              NICE is designed to provide additional functionalities, 
+ *              such as receive packet intercept. To support Broadcom NICE, 
+ *              the network device driver can be modified by adding an 
+ *              device ioctl handler and by indicating receiving packets 
+ *              to the NICE receive handler. Broadcom NICE will only be 
+ *              enabled by a NICE-aware intermediate driver, such as 
+ *              Broadcom Advanced Server Program Driver (BASP). When NICE 
+ *              is not enabled, the modified network device drivers 
+ *              functions exactly as other non-NICE aware drivers.
+ *
+ * Author:      Frankie Fan
+ *
+ * Created:     September 17, 2000
+ *
+ ****************************************************************************/
+#ifndef _nicext_h_
+#define _nicext_h_
+
+/*
+ * ioctl for NICE
+ */
+#define SIOCNICE                   	SIOCDEVPRIVATE+7
+
+/*
+ * SIOCNICE: 
+ *
+ * The following structure needs to be less than IFNAMSIZ (16 bytes) because
+ * we're overloading ifreq.ifr_ifru.
+ *
+ * If 16 bytes is not enough, we should consider relaxing this because
+ * this is no field after ifr_ifru in the ifreq structure. But we may
+ * run into future compatiability problem in case of changing struct ifreq.
+ */
+struct nice_req
+{
+    __u32 cmd;
+    
+    union
+    {
+#ifdef __KERNEL__
+        /* cmd = NICE_CMD_SET_RX or NICE_CMD_GET_RX */
+        struct
+        {
+            void (*nrqus1_rx)( struct sk_buff*, void* );
+            void* nrqus1_ctx;
+        } nrqu_nrqus1;
+
+        /* cmd = NICE_CMD_QUERY_SUPPORT */
+        struct
+        {
+            __u32 nrqus2_magic;
+            __u32 nrqus2_support_rx:1;
+            __u32 nrqus2_support_vlan:1;
+            __u32 nrqus2_support_get_speed:1;
+        } nrqu_nrqus2;
+#endif
+
+        /* cmd = NICE_CMD_GET_SPEED */
+        struct
+        {
+            unsigned int nrqus3_speed; /* 0 if link is down, */
+                                       /* otherwise speed in Mbps */
+        } nrqu_nrqus3;
+
+        /* cmd = NICE_CMD_BLINK_LED */
+        struct
+        {
+            unsigned int nrqus4_blink_time; /* blink duration in seconds */
+        } nrqu_nrqus4;
+
+        /* cmd = NICE_CMD_REG_READ */
+        /* cmd = NICE_CMD_REG_WRITE */
+        /* cmd = NICE_CMD_MEM_READ */
+        /* cmd = NICE_CMD_MEM_WRITE */
+        struct
+        {
+            unsigned int nrqus5_offset; /* offset */
+            unsigned int nrqus5_data; /* value */
+        } nrqu_nrqus5;
+
+        /* cmd = NICE_CMD_INTERRUPT_TEST */
+        struct
+        {
+            unsigned int nrqus6_intr_test_result; /* 1 == pass */
+        } nrqu_nrqus6;
+    } nrq_nrqu;
+};
+
+#define nrq_rx           nrq_nrqu.nrqu_nrqus1.nrqus1_rx
+#define nrq_ctx          nrq_nrqu.nrqu_nrqus1.nrqus1_ctx
+#define nrq_support_rx   nrq_nrqu.nrqu_nrqus2.nrqus2_support_rx
+#define nrq_magic        nrq_nrqu.nrqu_nrqus2.nrqus2_magic
+#define nrq_support_vlan nrq_nrqu.nrqu_nrqus2.nrqus2_support_vlan
+#define nrq_support_get_speed nrq_nrqu.nrqu_nrqus2.nrqus2_support_get_speed
+#define nrq_speed        nrq_nrqu.nrqu_nrqus3.nrqus3_speed
+#define nrq_blink_time   nrq_nrqu.nrqu_nrqus4.nrqus4_blink_time
+#define nrq_offset       nrq_nrqu.nrqu_nrqus5.nrqus5_offset
+#define nrq_data         nrq_nrqu.nrqu_nrqus5.nrqus5_data
+#define nrq_intr_test_result  nrq_nrqu.nrqu_nrqus6.nrqus6_intr_test_result
+
+/*
+ * magic constants
+ */
+#define NICE_REQUESTOR_MAGIC            0x4543494E // NICE in ascii
+#define NICE_DEVICE_MAGIC               0x4E494345 // ECIN in ascii
+
+/*
+ * command field
+ */
+#define NICE_CMD_QUERY_SUPPORT          0x00000001
+#define NICE_CMD_SET_RX                 0x00000002
+#define NICE_CMD_GET_RX                 0x00000003
+#define NICE_CMD_GET_SPEED              0x00000004
+#define NICE_CMD_BLINK_LED              0x00000005
+#define NICE_CMD_DIAG_SUSPEND           0x00000006
+#define NICE_CMD_DIAG_RESUME            0x00000007
+#define NICE_CMD_REG_READ               0x00000008
+#define NICE_CMD_REG_WRITE              0x00000009
+#define NICE_CMD_MEM_READ               0x0000000a
+#define NICE_CMD_MEM_WRITE              0x0000000b
+#define NICE_CMD_ENABLE_MAC_LOOPBACK    0x0000000c
+#define NICE_CMD_DISABLE_MAC_LOOPBACK   0x0000000d
+#define NICE_CMD_ENABLE_PHY_LOOPBACK    0x0000000e
+#define NICE_CMD_DISABLE_PHY_LOOPBACK   0x0000000f
+#define NICE_CMD_INTERRUPT_TEST         0x00000010
+
+#endif  // _nicext_h_ 
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/queue.h orig/drivers/net/bcm/queue.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/queue.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/queue.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,341 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* Queue functions.                                                           */
+/*    void          QQ_InitQueue(PQQ_CONTAINER pQueue)                        */
+/*    char          QQ_Full(PQQ_CONTAINER pQueue)                             */
+/*    char          QQ_Empty(PQQ_CONTAINER pQueue)                            */
+/*    unsigned int QQ_GetSize(PQQ_CONTAINER pQueue)                          */
+/*    unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue)                      */
+/*    char          QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
+/*    char          QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
+/*    PQQ_ENTRY     QQ_PopHead(PQQ_CONTAINER pQueue)                          */
+/*    PQQ_ENTRY     QQ_PopTail(PQQ_CONTAINER pQueue)                          */
+/*    PQQ_ENTRY     QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx)       */
+/*    PQQ_ENTRY     QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx)       */
+/*                                                                            */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef BCM_QUEUE_H
+#define BCM_QUEUE_H
+
+
+
+/******************************************************************************/
+/* Queue definitions. */
+/******************************************************************************/
+
+/* Entry for queueing. */
+typedef void *PQQ_ENTRY;
+
+
+/* Queue header -- base type. */
+typedef struct {
+    unsigned int Head;
+    unsigned int Tail;
+    unsigned int Size;
+    MM_ATOMIC_T EntryCnt;
+    PQQ_ENTRY Array[1];
+} QQ_CONTAINER, *PQQ_CONTAINER;
+
+
+/* Declare queue type macro. */
+#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE)            \
+                                                                \
+    typedef struct {                                            \
+        QQ_CONTAINER Container;                                 \
+        PQQ_ENTRY EntryBuffer[_QUEUE_SIZE];                     \
+    } _QUEUE_TYPE, *P##_QUEUE_TYPE
+
+
+
+/******************************************************************************/
+/* Compilation switches. */
+/******************************************************************************/
+
+#if DBG
+#undef QQ_NO_OVERFLOW_CHECK
+#undef QQ_NO_UNDERFLOW_CHECK
+#endif /* DBG */
+
+#ifdef QQ_USE_MACROS
+/* notdone */
+#else
+
+#ifdef QQ_NO_INLINE
+#define __inline
+#endif /* QQ_NO_INLINE */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static void 
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+    pQueue->Head = 0;
+    pQueue->Tail = 0;
+    pQueue->Size = QueueSize+1;
+    MM_ATOMIC_SET(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+    unsigned int NewHead;
+
+    NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+    return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+    return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static unsigned int 
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+    return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static unsigned int 
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+    return MM_ATOMIC_READ(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_PushHead(
+PQQ_CONTAINER pQueue, 
+PQQ_ENTRY pEntry) {
+    unsigned int Head;
+
+    Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[pQueue->Head] = pEntry;
+    MM_WMB();
+    pQueue->Head = Head;
+    MM_ATOMIC_INC(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Tail;
+
+    Tail = pQueue->Tail;
+    if(Tail == 0) {
+        Tail = pQueue->Size;
+    } /* if */
+    Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[Tail] = pEntry;
+    MM_WMB();
+    pQueue->Tail = Tail;
+    MM_ATOMIC_INC(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+    unsigned int Head;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    if(Head == 0) {
+        Head = pQueue->Size;
+    } /* if */
+    Head--;
+
+    Entry = pQueue->Array[Head];
+    MM_MB();
+    pQueue->Head = Head;
+    MM_ATOMIC_DEC(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    Entry = pQueue->Array[Tail];
+    MM_MB();
+    pQueue->Tail = (Tail + 1) % pQueue->Size;
+    MM_ATOMIC_DEC(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_GetHead(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= MM_ATOMIC_READ(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    if(pQueue->Head > Idx)
+    {
+        Idx = pQueue->Head - Idx;
+    }
+    else
+    {
+        Idx = pQueue->Size - (Idx - pQueue->Head);
+    }
+    Idx--;
+
+    return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_GetTail(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= MM_ATOMIC_READ(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    Idx += pQueue->Tail;
+    if(Idx >= pQueue->Size)
+    {
+        Idx = Idx - pQueue->Size;
+    }
+
+    return pQueue->Array[Idx];
+}
+
+#endif /* QQ_USE_MACROS */
+
+
+
+#endif /* QUEUE_H */
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/tcp_seg.c orig/drivers/net/bcm/tcp_seg.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/tcp_seg.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/tcp_seg.c	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,98 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2002 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#include "mm.h"
+
+#if INCLUDE_TCP_SEG_SUPPORT
+#include "fw_stkoffld.h"
+#include "fw_lso05.h"
+
+LM_UINT32 LM_GetStkOffLdFirmwareSize(PLM_DEVICE_BLOCK pDevice)
+{
+  LM_UINT32 FwSize;
+
+  if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) 
+    {
+      FwSize =  (LM_UINT32)(t3StkOffLd05FwTextLen + 
+			    t3StkOffLd05FwRodataLen + 
+			    t3StkOffLd05FwDataLen +
+			    t3StkOffLd05FwSbssLen +
+			    t3StkOffLd05FwBssLen);
+    }
+  else
+    {
+      FwSize = (LM_UINT32)(t3StkOffLdFwTextLen +
+			   t3StkOffLdFwRodataLen +
+			   t3StkOffLdFwDataLen +
+			   t3StkOffLdFwSbssLen +
+			   t3StkOffLdFwBssLen);
+    }
+
+  return FwSize;
+}
+
+LM_STATUS LM_LoadStkOffLdFirmware(PLM_DEVICE_BLOCK pDevice)
+{
+  T3_FWIMG_INFO FwImgInfo;
+  LM_UINT32 Cpu;
+
+  if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) 
+    {
+      FwImgInfo.StartAddress = t3StkOffLd05FwStartAddr;
+      FwImgInfo.Text.Buffer = (PLM_UINT8)t3StkOffLd05FwText;
+      FwImgInfo.Text.Offset  = t3StkOffLd05FwTextAddr;
+      FwImgInfo.Text.Length  = t3StkOffLd05FwTextLen;
+      FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3StkOffLd05FwRodata;
+      FwImgInfo.ROnlyData.Offset  = t3StkOffLd05FwRodataAddr;
+      FwImgInfo.ROnlyData.Length  = t3StkOffLd05FwRodataLen;
+      FwImgInfo.Data.Buffer = (PLM_UINT8)t3StkOffLd05FwData;
+      FwImgInfo.Data.Offset  = t3StkOffLd05FwDataAddr;
+      FwImgInfo.Data.Length  = t3StkOffLd05FwDataLen;
+      FwImgInfo.Sbss.Offset = t3StkOffLd05FwSbssAddr;
+      FwImgInfo.Sbss.Length = t3StkOffLd05FwSbssLen;
+      FwImgInfo.Bss.Offset = t3StkOffLd05FwBssAddr;
+      FwImgInfo.Bss.Length = t3StkOffLd05FwBssLen;
+      Cpu = T3_RX_CPU_ID;
+    }
+  else
+    {
+      FwImgInfo.StartAddress = t3StkOffLdFwStartAddr;
+      FwImgInfo.Text.Buffer = (PLM_UINT8)t3StkOffLdFwText;
+      FwImgInfo.Text.Offset  = t3StkOffLdFwTextAddr;
+      FwImgInfo.Text.Length  = t3StkOffLdFwTextLen;
+      FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3StkOffLdFwRodata;
+      FwImgInfo.ROnlyData.Offset  = t3StkOffLdFwRodataAddr;
+      FwImgInfo.ROnlyData.Length  = t3StkOffLdFwRodataLen;
+      FwImgInfo.Data.Buffer = (PLM_UINT8)t3StkOffLdFwData;
+      FwImgInfo.Data.Offset  = t3StkOffLdFwDataAddr;
+      FwImgInfo.Data.Length  = t3StkOffLdFwDataLen;
+      FwImgInfo.Sbss.Offset = t3StkOffLdFwSbssAddr;
+      FwImgInfo.Sbss.Length = t3StkOffLdFwSbssLen;
+      FwImgInfo.Bss.Offset = t3StkOffLdFwBssAddr;
+      FwImgInfo.Bss.Length = t3StkOffLdFwBssLen;
+      Cpu = T3_TX_CPU_ID;
+    }
+
+  if (LM_LoadFirmware(pDevice,
+                      &FwImgInfo,
+                      Cpu,
+                      Cpu) != LM_STATUS_SUCCESS)
+    {
+      return LM_STATUS_FAILURE;
+    }
+  
+  return LM_STATUS_SUCCESS;
+}
+
+#endif /* INCLUDE_TCP_SEG_SUPPORT */
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/tigon3.c orig/drivers/net/bcm/tigon3.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/tigon3.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/tigon3.c	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,6786 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+#include "mm.h"
+
+
+
+/******************************************************************************/
+/* Local functions. */
+/******************************************************************************/
+
+LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_InitBcm540xPhy(PLM_DEVICE_BLOCK pDevice);
+
+LM_VOID LM_ServiceRxInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_VOID LM_ServiceTxInterrupt(PLM_DEVICE_BLOCK pDevice);
+
+static LM_STATUS LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice);
+static LM_UINT32 GetPhyAdFlowCntrlSettings(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_SetFlowControl(PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd);
+STATIC LM_STATUS LM_SetupFiberPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_SetupCopperPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_VOID LM_ResetPhy(LM_DEVICE_BLOCK *pDevice);
+STATIC LM_VOID LM_SetEthWireSpeed(LM_DEVICE_BLOCK *pDevice);
+STATIC LM_STATUS LM_PhyAdvertiseAll(LM_DEVICE_BLOCK *pDevice);
+STATIC LM_STATUS LM_InitBcm800xPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid(LM_UINT16 Svid, LM_UINT16 Ssid);
+STATIC LM_STATUS LM_SwitchClocks(PLM_DEVICE_BLOCK pDevice);
+LM_VOID LM_SwitchVaux(PLM_DEVICE_BLOCK pDevice, PLM_DEVICE_BLOCK pDevice2);
+STATIC LM_STATUS LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
+           LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize);
+STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number);
+STATIC LM_STATUS LM_DisableChip(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_DisableFW(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+    PT3_SND_BD pSendBd);
+
+
+/******************************************************************************/
+/* External functions. */
+/******************************************************************************/
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice);
+#if INCLUDE_TCP_SEG_SUPPORT
+LM_STATUS LM_LoadStkOffLdFirmware(PLM_DEVICE_BLOCK pDevice);
+LM_UINT32 LM_GetStkOffLdFirmwareSize(PLM_DEVICE_BLOCK pDevice);
+#endif
+
+LM_UINT32
+LM_ByteSwap(LM_UINT32 Value32)
+{
+    return ((Value32 & 0xff) << 24)| ((Value32 & 0xff00) << 8)|
+        ((Value32 & 0xff0000) >> 8) | ((Value32 >> 24) & 0xff);
+}
+
+LM_UINT32
+LM_RegRd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register)
+{
+#if PCIX_TARGET_WORKAROUND
+    if (pDevice->UndiFix)
+    {
+        return (LM_RegRdInd(pDevice, Register));
+    }
+    else
+#endif
+    {
+        return (REG_RD_OFFSET(pDevice, Register));
+    }
+}
+
+LM_VOID
+LM_RegWr(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, LM_UINT32 Value32,
+    LM_UINT32 ReadBack)
+{
+#if PCIX_TARGET_WORKAROUND
+    if (pDevice->EnablePciXFix)
+    {
+        LM_RegWrInd(pDevice, Register, Value32);
+    }
+    else
+#endif
+    {
+        LM_UINT32 dummy;
+
+        REG_WR_OFFSET(pDevice, Register, Value32);
+        if (ReadBack && pDevice->RegReadBack)
+        {
+            dummy = REG_RD_OFFSET(pDevice, Register);
+        }
+    }
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_RegRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register) {
+    LM_UINT32 Value32;
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32);
+#if PCIX_TARGET_WORKAROUND
+    MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+
+    return Value32;
+} /* LM_RegRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_RegWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register,
+LM_UINT32 Value32) {
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#endif
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, Value32);
+#if PCIX_TARGET_WORKAROUND
+    MM_RELEASE_UNDI_LOCK(pDevice);
+#endif
+} /* LM_RegWrInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_MemRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr) {
+    LM_UINT32 Value32;
+
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    Value32 = REG_RD(pDevice, PciCfg.MemWindowData);
+    /*    Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */
+#else
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_ReadConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32);
+#endif
+    MM_RELEASE_UNDI_LOCK(pDevice);
+
+    return Value32;
+} /* LM_MemRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_MemWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr,
+LM_UINT32 Value32) {
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+#ifdef BIG_ENDIAN_HOST
+    REG_WR(pDevice,PciCfg.MemWindowBaseAddr,MemAddr);
+    REG_WR(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4],Value32);
+#else
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32);
+#endif
+    MM_RELEASE_UNDI_LOCK(pDevice);
+} /* LM_MemWrInd */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_QueueRxPackets(
+PLM_DEVICE_BLOCK pDevice) {
+    LM_STATUS Lmstatus;
+    PLM_PACKET pPacket;
+    PT3_RCV_BD pRcvBd = 0;
+    LM_UINT32 StdBdAdded = 0;
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    LM_UINT32 JumboBdAdded = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+    LM_UINT32 ConIdx;
+    LM_UINT32 Diff = 0;
+
+    Lmstatus = LM_STATUS_SUCCESS;
+
+    if (pDevice->RxBDLimit64)
+    {
+        ConIdx = pDevice->pStatusBlkVirt->RcvStdConIdx;
+        Diff = (pDevice->RxStdProdIdx - ConIdx) &
+            T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+        if (Diff >= 56)
+        {
+            if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container))
+            {
+                pDevice->QueueAgain = TRUE;
+            }
+            return LM_STATUS_SUCCESS;
+        }
+    }
+
+    pDevice->QueueAgain = FALSE;
+
+    pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+    while(pPacket) {
+        switch(pPacket->u.Rx.RcvProdRing) {
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+            case T3_JUMBO_RCV_PROD_RING:        /* Jumbo Receive Ring. */
+                /* Initialize the buffer descriptor. */
+                pRcvBd = 
+                    &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx];
+                pRcvBd->Flags = RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING;
+                pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize;
+
+                /* Update the producer index. */
+                pDevice->RxJumboProdIdx = (pDevice->RxJumboProdIdx + 1) & 
+                    T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+
+                JumboBdAdded++;
+                break;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+            case T3_STD_RCV_PROD_RING:      /* Standard Receive Ring. */
+                /* Initialize the buffer descriptor. */
+                pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx];
+                pRcvBd->Flags = RCV_BD_FLAG_END;
+                pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE;
+
+                /* Update the producer index. */
+                pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) & 
+                    T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+
+                StdBdAdded++;
+                break;
+
+            case T3_UNKNOWN_RCV_PROD_RING:
+            default:
+                Lmstatus = LM_STATUS_FAILURE;
+                break;
+        } /* switch */
+
+        /* Bail out if there is any error. */
+        if(Lmstatus != LM_STATUS_SUCCESS)
+        {
+            break;
+        }
+
+        /* Initialize the receive buffer pointer */
+        MM_MapRxDma(pDevice, pPacket, &pRcvBd->HostAddr);
+
+        /* The opaque field may point to an offset from a fix addr. */
+        pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR(pPacket) - 
+            MM_UINT_PTR(pDevice->pPacketDescBase));
+
+        if (pDevice->RxBDLimit64 && ((Diff + StdBdAdded) >= 63))
+        {
+            if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container))
+            {
+                pDevice->QueueAgain = TRUE;
+            }
+            break;
+        }
+        pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+    } /* while */
+
+    MM_WMB();
+    /* Update the procedure index. */
+    if(StdBdAdded)
+    {
+        MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low,
+            pDevice->RxStdProdIdx);
+        if (pDevice->FlushPostedWrites)
+        {
+            MB_REG_RD(pDevice, Mailbox.RcvStdProdIdx.Low);
+        }
+    }
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if(JumboBdAdded)
+    {
+        MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low,
+            pDevice->RxJumboProdIdx);
+        if (pDevice->FlushPostedWrites)
+        {
+            MB_REG_RD(pDevice, Mailbox.RcvJumboProdIdx.Low);
+        }
+    }
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    return Lmstatus;
+} /* LM_QueueRxPackets */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_VOID
+LM_NvramInit(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+
+    /* Intialize clock period and state machine. */
+    Value32 = SEEPROM_ADDR_CLK_PERD(SEEPROM_CLOCK_PERIOD) |
+        SEEPROM_ADDR_FSM_RESET;
+    REG_WR(pDevice, Grc.EepromAddr, Value32);
+
+    MM_Wait(100);
+
+    /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */
+    Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+    REG_WR(pDevice, Grc.LocalCtrl, Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM);
+
+    /* Set the 5701 compatibility mode if we are using EEPROM. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+        if((Value32 & FLASH_INTERFACE_ENABLE) == 0)
+        {
+            /* Use the new interface to read EEPROM. */
+            Value32 &= ~FLASH_COMPAT_BYPASS;
+
+            REG_WR(pDevice, Nvram.Config1, Value32);
+        }
+    }
+
+    MM_Wait(100);
+
+} /* LM_NvRamInit */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_EepromRead(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 Addr;
+    LM_UINT32 Dev;
+    LM_UINT32 j;
+
+    if(Offset > SEEPROM_CHIP_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    Dev = Offset / SEEPROM_CHIP_SIZE;
+    Addr = Offset % SEEPROM_CHIP_SIZE;
+    
+    Value32 = REG_RD(pDevice, Grc.EepromAddr);
+    Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK |
+        SEEPROM_ADDR_RW_MASK);
+    REG_WR(pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID(Dev) |
+        SEEPROM_ADDR_ADDRESS(Addr) | SEEPROM_ADDR_START | SEEPROM_ADDR_READ);
+
+    for(j = 0; j < 1000; j++)
+    {
+        Value32 = REG_RD(pDevice, Grc.EepromAddr);
+        if(Value32 & SEEPROM_ADDR_COMPLETE)
+        {
+            break;
+        }
+        MM_Wait(20);
+    }
+
+    if(Value32 & SEEPROM_ADDR_COMPLETE)
+    {
+        Value32 = REG_RD(pDevice, Grc.EepromData);
+        *pData = Value32;
+
+        return LM_STATUS_SUCCESS;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* LM_EepromRead */
+
+#ifdef ETHTOOL_SEEPROM
+
+STATIC LM_STATUS
+LM_EepromWriteBlock(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData,
+    LM_UINT32 Size)
+{
+    LM_UINT32 Value32 = 0;
+    LM_UINT32 Addr;
+    LM_UINT32 Dev;
+    LM_UINT32 i, j;
+
+    if(Offset > SEEPROM_CHIP_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Enable EEPROM write. */
+    if(pDevice->EepromWp)
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+        MM_Wait(40);
+
+        Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+        if(Value32 & GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1)
+        {
+            return LM_STATUS_FAILURE;
+        }
+    }
+
+    for (i = 0; i < Size ; i++, pData++, Offset += 4) {
+
+        Dev = Offset / SEEPROM_CHIP_SIZE;
+        Addr = Offset % SEEPROM_CHIP_SIZE;
+
+        /* Set the write value to the eeprom */    
+        REG_WR(pDevice, Grc.EepromData, *pData);  
+
+        Value32 = REG_RD(pDevice, Grc.EepromAddr);
+        Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK |
+                            SEEPROM_ADDR_RW_MASK);
+
+        REG_WR(pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID(Dev) |
+                        SEEPROM_ADDR_ADDRESS(Addr) | SEEPROM_ADDR_START | SEEPROM_ADDR_WRITE);
+
+        for(j = 0; j < 1000; j++)
+        {
+            Value32 = REG_RD(pDevice, Grc.EepromAddr);
+            if(Value32 & SEEPROM_ADDR_COMPLETE)
+            {
+                break;
+            }
+            MM_Wait(10);
+        }
+    } 
+
+    /* Write-protect EEPROM. */
+    if(pDevice->EepromWp)
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+            GRC_MISC_LOCAL_CTRL_GPIO_OE1 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+        MM_Wait(40);
+    }
+
+    if(Value32 & SEEPROM_ADDR_COMPLETE)
+    {
+        return LM_STATUS_SUCCESS;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* LM_EepromWriteBlock */
+#endif
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_NvramRead(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData)
+{
+    LM_UINT32 Value32;
+    LM_STATUS Status;
+    LM_UINT32 j;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        Status = LM_EepromRead(pDevice, Offset, pData);
+    }
+    else
+    {
+        /* Determine if we have flash or EEPROM. */
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+        if(Value32 & FLASH_INTERFACE_ENABLE)
+        {
+            if(Value32 & FLASH_SSRAM_BUFFERED_MODE)
+            {
+                Offset = ((Offset/BUFFERED_FLASH_PAGE_SIZE) <<
+                    BUFFERED_FLASH_PAGE_POS) +
+                    (Offset % BUFFERED_FLASH_PAGE_SIZE);
+            }
+        }
+
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+        for (j = 0; j < 1000; j++)
+        {
+            if (REG_RD(pDevice, Nvram.SwArb) & SW_ARB_GNT1)
+            {
+                break;
+            }
+            MM_Wait(20);
+        }
+        if (j == 1000)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* Read from flash or EEPROM with the new 5703/02 interface. */
+        REG_WR(pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK);
+
+        REG_WR(pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT |
+            NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+
+        /* Wait for the done bit to clear. */
+        for(j = 0; j < 1000; j++)
+        {
+            MM_Wait(10);
+
+            Value32 = REG_RD(pDevice, Nvram.Cmd);
+            if(Value32 & NVRAM_CMD_DONE)
+            {
+                MM_Wait(10);
+
+                *pData = REG_RD(pDevice, Nvram.ReadData);
+
+                /* Change the endianess. */
+                *pData = LM_ByteSwap(*pData);
+
+                break;
+            }
+        }
+
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1);
+        if(Value32 & NVRAM_CMD_DONE)
+        {
+            Status = LM_STATUS_SUCCESS;
+        }
+        else
+        {
+            Status = LM_STATUS_FAILURE;
+        }
+    }
+
+    return Status;
+} /* LM_NvramRead */
+
+
+#ifdef ETHTOOL_SEEPROM
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_NvramWriteBlock(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 Offset,
+    LM_UINT32 *pData,
+    LM_UINT32 Size)
+{
+    LM_UINT32 Value32 = 0;
+    LM_UINT32 ControlReg;
+    LM_UINT32 AddrOffset;
+    LM_STATUS Status;
+    LM_UINT32  i , j;
+    LM_UINT32 BufferedFlash;
+    LM_UINT32 GrcMode;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        Status = LM_EepromWriteBlock(pDevice, Offset, pData, Size);
+    }
+    else
+    {
+        /* Request access to the flash interface. */
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+
+        for(j = 0; j < 1000; j++)
+        {
+            Value32 = REG_RD(pDevice, Nvram.SwArb);
+            if(Value32 & SW_ARB_GNT1)
+            {
+                break;
+            }
+            MM_Wait(20);
+        }
+
+        if(!(Value32 & SW_ARB_GNT1))
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* Enable EEPROM write. */
+        if(pDevice->EepromWp)
+        {
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                        GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+            MM_Wait(40);
+
+            Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+            if(Value32 & GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1)
+            {
+                return LM_STATUS_FAILURE;
+             }
+        }
+
+        GrcMode = REG_RD(pDevice, Grc.Mode);
+        REG_WR(pDevice, Grc.Mode, GrcMode | GRC_MODE_NVRAM_WRITE_ENABLE);
+
+        BufferedFlash = FALSE;
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+        if(Value32 & FLASH_INTERFACE_ENABLE)
+        {
+            if(Value32 & FLASH_SSRAM_BUFFERED_MODE)
+            {
+                BufferedFlash = TRUE;
+            }
+        }
+
+        for (i = 0 ; i < Size ; i++, pData++, Offset += 4) {
+
+            /* Change the endianess. */
+            Value32 = LM_ByteSwap(*pData);
+
+            /* set the desired write data value to the flash */
+            REG_WR(pDevice, Nvram.WriteData, Value32);
+
+            /* set targeted address */
+            AddrOffset = Offset;
+
+            /* Determine if we have flash or buffered flash. */
+            if(BufferedFlash)
+            {
+                AddrOffset = ((Offset/BUFFERED_FLASH_PAGE_SIZE) <<
+                                        BUFFERED_FLASH_PAGE_POS) +
+                                    (Offset % BUFFERED_FLASH_PAGE_SIZE);
+            }
+
+            /* Write to flash or EEPROM with the new 5703/02 interface. */
+            REG_WR(pDevice, Nvram.Addr, AddrOffset & NVRAM_ADDRESS_MASK);
+
+            ControlReg = NVRAM_CMD_DO_IT | NVRAM_CMD_DONE | NVRAM_CMD_WR;
+            if(i == 0)
+            {
+                ControlReg |= NVRAM_CMD_FIRST;
+            }
+            if(i == (Size - 1))  
+            {
+                ControlReg |= NVRAM_CMD_LAST;
+            }
+
+            if(BufferedFlash)
+            {
+                /* Set CMD_FIRST when we are at the beginning of a page. */
+                if(!(AddrOffset & BUFFERED_FLASH_BYTE_ADDR_MASK))
+                {
+                    ControlReg |= NVRAM_CMD_FIRST;
+                }
+                else if((AddrOffset & BUFFERED_FLASH_BYTE_ADDR_MASK) ==
+                    (BUFFERED_FLASH_PAGE_SIZE - 4))
+                {
+                    ControlReg |=  NVRAM_CMD_LAST;
+                }
+            }
+
+            REG_WR(pDevice, Nvram.Cmd,  ControlReg);
+
+            /* Wait for the done bit to go High. */
+            for(j = 0; j < 4000 ; j++)
+            {
+                MM_Wait(10);
+
+                Value32 = REG_RD(pDevice, Nvram.Cmd);
+
+                if(Value32 & NVRAM_CMD_DONE)
+                {
+                    MM_Wait(5);
+                    break;
+                }
+            }
+        }  
+
+        REG_WR(pDevice, Grc.Mode, GrcMode);
+
+        /* Write-protect EEPROM. */
+        if(pDevice->EepromWp)
+        {
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+            MM_Wait(40);
+        }
+
+        /* Relinquish nvram interface. */
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1);
+
+        if(Value32 & NVRAM_CMD_DONE)
+        {
+            Status = LM_STATUS_SUCCESS;
+        }
+        else
+        {
+            Status = LM_STATUS_FAILURE;
+        }
+    }
+
+    return Status;
+} /* LM_NvramWriteBlock */
+#endif
+
+STATIC void
+LM_ReadVPD(PLM_DEVICE_BLOCK pDevice)
+{
+#ifdef BCM_PROC_FS
+    LM_UINT32 Vpd_arr[256/4];
+    LM_UINT8 *Vpd = (LM_UINT8 *) &Vpd_arr[0];
+    LM_UINT32 *Vpd_dptr = &Vpd_arr[0];
+    LM_UINT32 Value32;
+    unsigned int j;
+
+    /* Read PN from VPD */
+    for (j = 0; j < 256; j += 4, Vpd_dptr++ )
+    {
+        if (LM_NvramRead(pDevice, 0x100 + j, &Value32) != LM_STATUS_SUCCESS) {
+            printk(KERN_ERR "VPD read failed\n");
+            return;
+        }
+        *Vpd_dptr = MM_SWAP_LE32(Value32);
+    }
+    for (j = 0; j < 256; )
+    {
+        unsigned int Vpd_r_len;
+        unsigned int Vpd_r_end;
+
+        if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91))
+        {
+            j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8);
+        }
+        else if (Vpd[j] == 0x90)
+        {
+            Vpd_r_len =  Vpd[j + 1] + (Vpd[j + 2] << 8);
+            j += 3;
+            Vpd_r_end = Vpd_r_len + j;
+            while (j < Vpd_r_end)
+            {
+                if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N'))
+                {
+                    unsigned int len = Vpd[j + 2];
+
+                    if (len <= 24)
+                    {
+                        memcpy(pDevice->PartNo, &Vpd[j + 3], len);
+                    }
+                    break;
+                }
+                else
+                {
+                    if (Vpd[j + 2] == 0)
+                    {
+                        break;
+                    }
+                    j = j + Vpd[j + 2];
+                }
+            }
+            break;
+        }
+        else {
+            break;
+        }
+    }
+#endif
+}
+
+STATIC void
+LM_ReadBootCodeVersion(PLM_DEVICE_BLOCK pDevice)
+{
+#ifdef BCM_PROC_FS
+    LM_UINT32 Value32, offset, ver_offset, start_addr;
+    int i;
+
+    if (LM_NvramRead(pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS)
+        return;
+    if (Value32 != 0xaa559966)
+        return;
+    if (LM_NvramRead(pDevice, 0xc, &offset) != LM_STATUS_SUCCESS)
+        return;
+
+    offset = LM_ByteSwap(offset);
+
+    if((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701) &&
+        ((REG_RD(pDevice, Nvram.Config1) & BUFFERED_FLASH) == BUFFERED_FLASH))
+    {
+        offset = (offset >> BUFFERED_FLASH_PAGE_POS) *
+            BUFFERED_FLASH_PAGE_SIZE + (offset & BUFFERED_FLASH_BYTE_ADDR_MASK);
+    }
+    if (LM_NvramRead(pDevice, offset, &Value32) != LM_STATUS_SUCCESS)
+        return;
+    if ((((Value32 & ~0xf0000) == 0x0300000e) ||
+        ((Value32 & ~0xff0000) == 0x0300000c)) &&
+        (LM_NvramRead(pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) &&
+        (Value32 == 0)) {
+
+        if (LM_NvramRead(pDevice, offset + 8, &ver_offset) != LM_STATUS_SUCCESS)
+            return;
+        if (LM_NvramRead(pDevice, 4, &start_addr) != LM_STATUS_SUCCESS)
+            return;
+        ver_offset = LM_ByteSwap(ver_offset);
+        start_addr = LM_ByteSwap(start_addr);
+        offset += ver_offset - start_addr;
+        for (i = 0; i < 16; i += 4) {
+            if (LM_NvramRead(pDevice, offset + i, &Value32) !=
+                LM_STATUS_SUCCESS)
+            {
+                return;
+            }
+            *((LM_UINT32 *) &pDevice->BootCodeVer[i]) = MM_SWAP_LE32(Value32);
+        }
+    }
+    else {
+        char c;
+
+        if (LM_NvramRead(pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS)
+            return;
+
+        i = 0;
+        c = ((Value32 & 0xff0000) >> 16);
+
+        if (c < 10) {
+            pDevice->BootCodeVer[i++] = c + '0';
+        }
+        else {
+            pDevice->BootCodeVer[i++] = (c / 10) + '0';
+            pDevice->BootCodeVer[i++] = (c % 10) + '0';
+        }
+        pDevice->BootCodeVer[i++] = '.';
+        c = (Value32 & 0xff000000) >> 24;
+        if (c < 10) {
+            pDevice->BootCodeVer[i++] = '0';
+            pDevice->BootCodeVer[i++] = c + '0';
+        }
+        else {
+            pDevice->BootCodeVer[i++] = (c / 10) + '0';
+            pDevice->BootCodeVer[i++] = (c % 10) + '0';
+        }
+        pDevice->BootCodeVer[i] = 0;
+    }
+#endif
+}
+
+STATIC void
+LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice)
+{
+#ifdef BCM_PROC_FS
+    LM_UINT32 PciState = pDevice->PciState;
+    LM_UINT32 ClockCtrl;
+    char *SpeedStr = "";
+
+    if (PciState & T3_PCI_STATE_32BIT_PCI_BUS)
+    {
+        strcpy(pDevice->BusSpeedStr, "32-bit ");
+    }
+    else
+    {
+        strcpy(pDevice->BusSpeedStr, "64-bit ");
+    }
+    if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)
+    {
+        strcat(pDevice->BusSpeedStr, "PCI ");
+        if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED) 
+        {
+            SpeedStr = "66MHz";
+        }
+        else
+        {
+            SpeedStr = "33MHz";
+        }
+    }
+    else
+    {
+        strcat(pDevice->BusSpeedStr, "PCIX ");
+        if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)
+        {
+            SpeedStr = "133MHz";
+        }
+        else
+        {
+            ClockCtrl = pDevice->ClockCtrl & 0x1f;
+            switch (ClockCtrl)
+            {
+            case 0:
+                SpeedStr = "33MHz";
+                break;
+
+            case 2:
+                SpeedStr = "50MHz";
+                break;
+
+            case 4:
+                SpeedStr = "66MHz";
+                break;
+
+            case 6:
+                SpeedStr = "100MHz";
+                break;
+
+            case 7:
+                SpeedStr = "133MHz";
+                break;
+            }
+        }
+    }
+    strcat(pDevice->BusSpeedStr, SpeedStr);
+#endif
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine initializes default parameters and reads the PCI           */
+/*    configurations.                                                         */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_GetAdapterInfo(
+PLM_DEVICE_BLOCK pDevice)
+{
+    PLM_ADAPTER_INFO pAdapterInfo;
+    LM_UINT32 Value32;
+    LM_STATUS Status;
+    LM_UINT32 EeSigFound;
+    LM_UINT32 EePhyTypeSerdes = 0;
+    LM_UINT32 EePhyLedMode = 0;
+    LM_UINT32 EePhyId = 0;
+
+    /* Get Device Id and Vendor Id */
+    Status = MM_ReadConfig32(pDevice, PCI_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciVendorId = (LM_UINT16) Value32;
+    pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16);
+
+    Status = MM_ReadConfig32(pDevice, PCI_REV_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciRevId = (LM_UINT8) Value32;
+
+    /* Get chip revision id. */
+    Status = MM_ReadConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32);
+    pDevice->ChipRevId = Value32 >> 16;
+
+    /* Get subsystem vendor. */
+    Status = MM_ReadConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->SubsystemVendorId = (LM_UINT16) Value32;
+
+    /* Get PCI subsystem id. */
+    pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16);
+
+    /* Get the cache line size. */
+    MM_ReadConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32);
+    pDevice->CacheLineSize = (LM_UINT8) Value32;
+    pDevice->SavedCacheLineReg = Value32;
+
+    if(pDevice->ChipRevId != T3_CHIP_ID_5703_A1 &&
+        pDevice->ChipRevId != T3_CHIP_ID_5703_A2 &&
+        pDevice->ChipRevId != T3_CHIP_ID_5704_A0)
+    {
+        pDevice->UndiFix = FALSE;
+    }
+#if !PCIX_TARGET_WORKAROUND
+    pDevice->UndiFix = FALSE;
+#endif
+    /* Map the memory base to system address space. */
+    if (!pDevice->UndiFix)
+    {
+        Status = MM_MapMemBase(pDevice);
+        if(Status != LM_STATUS_SUCCESS)
+        {
+            return Status;
+        }
+        /* Initialize the memory view pointer. */
+        pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase;
+    }
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        pDevice->RegReadBack = TRUE;
+    }
+#if PCIX_TARGET_WORKAROUND
+    /* store whether we are in PCI are PCI-X mode */
+    pDevice->EnablePciXFix = FALSE;
+
+    MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+    if((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)
+    {
+        /* Enable PCI-X workaround only if we are running on 5700 BX. */
+        if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+        {
+            pDevice->EnablePciXFix = TRUE;
+        }
+    }
+    if (pDevice->UndiFix)
+    {
+        pDevice->EnablePciXFix = TRUE;
+    }
+#endif
+    /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */
+    /* management register may be clobbered which may cause the */
+    /* BCM5700 to go into D3 state.  While in this state, we will */
+    /* not have memory mapped register access.  As a workaround, we */
+    /* need to restore the device to D0 state. */
+    MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32);
+    Value32 |= T3_PM_PME_ASSERTED;
+    Value32 &= ~T3_PM_POWER_STATE_MASK;
+    Value32 |= T3_PM_POWER_STATE_D0;
+    MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32);
+
+    /* read the current PCI command word */
+    MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32);
+
+    /* Make sure bus-mastering is enabled. */
+    Value32 |= PCI_BUSMASTER_ENABLE;
+
+#if PCIX_TARGET_WORKAROUND
+    /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR#
+        are enabled */
+    if (pDevice->EnablePciXFix == TRUE) {
+        Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE | 
+                    PCI_PARITY_ERROR_ENABLE);
+    }
+    if (pDevice->UndiFix)
+    {
+        Value32 &= ~PCI_MEM_SPACE_ENABLE;
+    }
+
+#endif
+
+    if(pDevice->EnableMWI)
+    {
+        Value32 |= PCI_MEMORY_WRITE_INVALIDATE;
+    }
+    else {
+        Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE);
+    }
+
+    /* save the value we are going to write into the PCI command word */	
+    pDevice->PciCommandStatusWords = Value32;	
+
+    Status = MM_WriteConfig32(pDevice, PCI_COMMAND_REG, Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* Set power state to D0. */
+    LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+    /* Setup the mode registers. */
+    pDevice->MiscHostCtrl = 
+        MISC_HOST_CTRL_MASK_PCI_INT | 
+        MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | 
+#ifdef BIG_ENDIAN_HOST
+        MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP |  
+#endif /* BIG_ENDIAN_HOST */
+        MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS |
+        MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW;
+	/* write to PCI misc host ctr first in order to enable indirect accesses */
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl);
+
+#ifdef BIG_ENDIAN_HOST
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | 
+              GRC_MODE_WORD_SWAP_NON_FRAME_DATA;
+#else
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA;
+#endif
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+            GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+    }
+    MM_Wait(40);
+
+    /* Enable indirect memory access */
+    REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+    LM_SwitchClocks(pDevice);
+
+    REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+#if PCIX_TARGET_WORKAROUND
+    MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+    if ((pDevice->EnablePciXFix == FALSE) &&
+        ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0))
+    {
+        if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B0 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B2 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5701_B5)
+        {
+            MM_MEMWRITEL(&(pDevice->pMemView->uIntMem.MemBlock32K[0x300]), 0);
+            MM_MEMWRITEL(&(pDevice->pMemView->uIntMem.MemBlock32K[0x301]), 0);
+            MM_MEMWRITEL(&(pDevice->pMemView->uIntMem.MemBlock32K[0x301]),
+                0xffffffff);
+            if (MM_MEMREADL(&(pDevice->pMemView->uIntMem.MemBlock32K[0x300])))
+            {
+                pDevice->EnablePciXFix = TRUE;
+            }
+        }
+    }
+#endif
+
+    LM_NvramInit(pDevice);
+
+    /* Get the node address.  First try to get in from the shared memory. */
+    /* If the signature is not present, then get it from the NVRAM. */
+    Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_HIGH_MAILBOX);
+    if((Value32 >> 16) == 0x484b)
+    {
+
+        pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8);
+        pDevice->NodeAddress[1] = (LM_UINT8) Value32;
+
+        Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_LOW_MAILBOX);
+
+        pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24);
+        pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16);
+        pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8);
+        pDevice->NodeAddress[5] = (LM_UINT8) Value32;
+
+        Status = LM_STATUS_SUCCESS;
+    }
+    else
+    {
+        int MacOffset;
+
+        MacOffset = 0x7c;
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+        {
+            if (REG_RD(pDevice, PciCfg.DualMacCtrl) & T3_DUAL_MAC_ID)
+            {
+                MacOffset = 0xcc;
+            }
+        }
+        Status = LM_NvramRead(pDevice, MacOffset, &Value32);
+        if(Status == LM_STATUS_SUCCESS)
+        {
+            pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16);
+            pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24);
+
+            Status = LM_NvramRead(pDevice, MacOffset + 4, &Value32);
+
+            pDevice->NodeAddress[2] = (LM_UINT8) Value32;
+            pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8);
+            pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16);
+            pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24);
+        }
+    }
+
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        printk(KERN_ERR "Cannot get MAC addr from NVRAM\n");
+        return LM_STATUS_FAILURE;
+    }
+
+    memcpy(pDevice->PermanentNodeAddress, pDevice->NodeAddress, 6);
+
+    /* Initialize the default values. */
+    pDevice->NoTxPseudoHdrChksum = FALSE;
+    pDevice->NoRxPseudoHdrChksum = FALSE;
+    pDevice->NicSendBd = FALSE;
+    pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT;
+    pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT;
+    pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS;
+    pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS;
+    pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES;
+    pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES;
+    pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE;
+    pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS;
+    pDevice->EnableMWI = FALSE;
+    pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    pDevice->DisableAutoNeg = FALSE;
+    pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO;
+    pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO;
+    pDevice->LedMode = LED_MODE_AUTO;
+    pDevice->ResetPhyOnInit = TRUE;
+    pDevice->ResetPhyOnLinkDown = FALSE;
+    pDevice->DelayPciGrant = TRUE;
+    pDevice->UseTaggedStatus = FALSE;
+    pDevice->OneDmaAtOnce = FALSE;
+
+    pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+    pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE;
+    pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+    pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE;
+    pDevice->EnableTbi = FALSE;
+#if INCLUDE_TBI_SUPPORT
+    pDevice->PollTbiLink = BAD_DEFAULT_VALUE;
+#endif
+#if INCLUDE_TCP_SEG_SUPPORT
+    pDevice->LargeSendMaxSize = T3_TCP_SEG_MAX_OFFLOAD_SIZE;
+    pDevice->LargeSendMinNumSeg = T3_TCP_SEG_MIN_NUM_SEG;
+#endif
+
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) ||
+        (pDevice->ChipRevId == T3_CHIP_ID_5705_A0))
+    {
+        pDevice->ResetPhyOnLinkDown = TRUE;
+    }
+
+    switch (T3_ASIC_REV(pDevice->ChipRevId))
+    {
+    case T3_ASIC_REV_5704:
+        pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+        pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64;
+        break;
+    default:
+        pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR;
+        pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96;
+        break;
+    }
+
+    pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+    pDevice->QueueRxPackets = TRUE;
+
+    pDevice->EnableWireSpeed = TRUE;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        pDevice->RxJumboDescCnt = 0;
+    }
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    pDevice->BondId = REG_RD(pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK;
+
+    if(((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) &&
+        ((pDevice->BondId == 0x10000) || (pDevice->BondId == 0x18000))) ||
+        ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) &&
+        ((pDevice->BondId == 0x14000) || (pDevice->BondId == 0x1c000))))
+    {
+        return LM_STATUS_UNKNOWN_ADAPTER;
+    }
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+    {
+        if ((pDevice->BondId == 0x8000) || (pDevice->BondId == 0x4000))
+        {
+            pDevice->No1000 = TRUE;
+        }
+    }
+
+    pDevice->SplitModeEnable = SPLIT_MODE_DISABLE;
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) &&
+        (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE))
+    {
+        pDevice->SplitModeEnable = SPLIT_MODE_ENABLE;
+        pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ;
+    }
+
+    /* Get Eeprom info. */
+    Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_SIG_ADDR);
+    if (Value32 == T3_NIC_DATA_SIG)
+    {
+        EeSigFound = TRUE;
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR);
+
+        if (Value32 & T3_NIC_MINI_PCI)
+        {
+            pDevice->MiniPci = TRUE;
+        }
+        /* Determine PHY type. */
+        switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK)
+        {
+            case T3_NIC_CFG_PHY_TYPE_COPPER:
+                EePhyTypeSerdes = FALSE;
+                break;
+
+            case T3_NIC_CFG_PHY_TYPE_FIBER:
+                EePhyTypeSerdes = TRUE;
+                break;
+
+            default:
+                EePhyTypeSerdes = FALSE;
+                break;
+        }
+
+        /* Determine PHY led mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+            {
+                case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED:
+                    EePhyLedMode = LED_MODE_THREE_LINK;
+                    break;
+
+                case T3_NIC_CFG_LED_MODE_LINK_SPEED:
+                    EePhyLedMode = LED_MODE_LINK10;
+                    break;
+
+                default:
+                    EePhyLedMode = LED_MODE_AUTO;
+                    break;
+            }
+        }
+        else
+        {
+            switch(Value32 & T3_NIC_CFG_LED_MODE_MASK)
+            {
+                case T3_NIC_CFG_LED_MODE_OPEN_DRAIN:
+                    EePhyLedMode = LED_MODE_OPEN_DRAIN;
+                    break;
+
+                case T3_NIC_CFG_LED_MODE_OUTPUT:
+                    EePhyLedMode = LED_MODE_OUTPUT;
+                    break;
+
+                default:
+                    EePhyLedMode = LED_MODE_AUTO;
+                    break;
+            }
+        }
+        if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 ||
+            pDevice->ChipRevId == T3_CHIP_ID_5703_A2)
+        {
+            /* Enable EEPROM write protection. */
+            if(Value32 & T3_NIC_EEPROM_WP)
+            {
+                pDevice->EepromWp = TRUE;
+            }
+        }
+        pDevice->EnableAsf = FALSE;
+#ifdef BCM_ASF
+        if (Value32 & T3_NIC_CFG_ENABLE_ASF)
+        {
+            pDevice->EnableAsf = TRUE;
+        }
+#endif
+        if (Value32 & T3_NIC_FIBER_WOL_CAPABLE)
+        {
+            pDevice->FiberWolCapable = 1;
+        }
+        if (Value32 & T3_NIC_WOL_LIMIT_10)
+        {
+            pDevice->WolLimit10 = TRUE;
+        }
+
+        /* Get the PHY Id. */
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_PHY_ID_ADDR);
+        if (Value32)
+        {
+            EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) &
+                PHY_ID1_OUI_MASK) << 10;
+
+            Value32 = Value32 & T3_NIC_PHY_ID2_MASK;
+
+            EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+              (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+        }
+        else
+        {
+            EePhyId = 0;
+        }
+    }
+    else
+    {
+        EeSigFound = FALSE;
+    }
+
+    /* Set the PHY address. */
+    pDevice->PhyAddr = PHY_DEVICE_ID;
+
+    /* Disable auto polling. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    MM_Wait(40);
+
+    /* Get the PHY id. */
+    LM_ReadPhy(pDevice, PHY_ID1_REG, &Value32);
+    pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10;
+
+    LM_ReadPhy(pDevice, PHY_ID2_REG, &Value32);
+    pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) |
+      (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK);
+
+    /* Set the EnableTbi flag to false if we have a copper PHY. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM5400_PHY_ID:
+        case PHY_BCM5401_PHY_ID:
+        case PHY_BCM5411_PHY_ID:
+        case PHY_BCM5701_PHY_ID:
+        case PHY_BCM5703_PHY_ID:
+        case PHY_BCM5704_PHY_ID:
+        case PHY_BCM5705_PHY_ID:
+            pDevice->EnableTbi = FALSE;
+            break;
+
+        case PHY_BCM8002_PHY_ID:
+            pDevice->EnableTbi = TRUE;
+            break;
+
+        default:
+
+            if (EeSigFound)
+            {
+                pDevice->PhyId = EePhyId;
+                pDevice->EnableTbi = EePhyTypeSerdes;
+            }
+            else if ((pAdapterInfo = LM_GetAdapterInfoBySsid(
+                pDevice->SubsystemVendorId,
+                pDevice->SubsystemId)))
+            {
+                pDevice->PhyId = pAdapterInfo->PhyId;
+                pDevice->EnableTbi = pAdapterInfo->Serdes;
+            }
+            break;
+    }
+
+    /* Bail out if we don't know the copper PHY id. */
+    if(UNKNOWN_PHY_ID(pDevice->PhyId) && !pDevice->EnableTbi)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+    {
+        if((pDevice->SavedCacheLineReg & 0xff00) < 0x4000)
+        {
+            pDevice->SavedCacheLineReg &= 0xffff00ff;
+            pDevice->SavedCacheLineReg |= 0x4000;
+        }
+    }
+
+    pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST |
+        LM_ACCEPT_UNICAST | LM_KEEP_VLAN_TAG;
+
+    pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+        LM_TASK_OFFLOAD_TX_UDP_CHECKSUM | LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+        LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+
+    if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0)
+    {
+       	pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+            LM_TASK_OFFLOAD_TX_UDP_CHECKSUM);
+    }
+
+#if INCLUDE_TCP_SEG_SUPPORT
+    pDevice->TaskOffloadCap |= LM_TASK_OFFLOAD_TCP_SEGMENTATION;
+
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) ||
+        (pDevice->ChipRevId == T3_CHIP_ID_5705_A0))
+    {
+        pDevice->TaskOffloadCap &= ~LM_TASK_OFFLOAD_TCP_SEGMENTATION;
+    }
+#endif
+
+#ifdef BCM_ASF
+    if (pDevice->EnableAsf)
+    {
+       	pDevice->TaskOffloadCap &= ~LM_TASK_OFFLOAD_TCP_SEGMENTATION;
+    }
+#endif
+
+    /* Change driver parameters. */
+    Status = MM_GetConfig(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        pDevice->NicSendBd = FALSE;
+    }
+
+    /* Save the current phy link status. */
+    if(!pDevice->EnableTbi)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        /* If we don't have link reset the PHY. */
+        if(!(Value32 & PHY_STATUS_LINK_PASS) || pDevice->ResetPhyOnInit)
+        {
+
+            LM_ResetPhy(pDevice);
+
+            if (LM_PhyAdvertiseAll(pDevice) != LM_STATUS_SUCCESS)
+            {
+                Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
+                    PHY_AN_AD_ALL_SPEEDS;
+                Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+                LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+                pDevice->advertising = Value32;
+
+                Value32 = BCM540X_AN_AD_ALL_1G_SPEEDS ;
+#if INCLUDE_5701_AX_FIX
+                if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+                    pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+                {
+                    Value32 |= BCM540X_CONFIG_AS_MASTER |
+                        BCM540X_ENABLE_CONFIG_AS_MASTER;
+                }
+#endif
+                LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+                pDevice->advertising1000 = Value32;
+
+                LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+                    PHY_CTRL_RESTART_AUTO_NEG);
+            }
+
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+            {
+                LM_WritePhy(pDevice, 0x18, 0x0c00);
+                LM_WritePhy(pDevice, 0x17, 0x201f);
+                LM_WritePhy(pDevice, 0x15, 0x2aaa);
+            }
+            if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+            {
+                LM_WritePhy(pDevice, 0x1c, 0x8d68);
+                LM_WritePhy(pDevice, 0x1c, 0x8d68);
+            }
+        }
+        LM_SetEthWireSpeed(pDevice);
+
+        LM_ReadPhy(pDevice, PHY_AN_AD_REG, &pDevice->advertising);
+        LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG,
+            &pDevice->advertising1000);
+    }
+
+    /* Turn off tap power management. */
+    if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+        LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+        LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+        MM_Wait(40);
+    }
+
+#if INCLUDE_TBI_SUPPORT
+    pDevice->IgnoreTbiLinkChange = FALSE;
+
+    if(pDevice->EnableTbi)
+    {
+        if (!pDevice->FiberWolCapable)
+        {
+            pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
+        }
+        pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+        if (pDevice->PollTbiLink == BAD_DEFAULT_VALUE)
+        {
+            pDevice->PollTbiLink = FALSE;
+        }
+    }
+    else
+    {
+        pDevice->PollTbiLink = FALSE;
+    }
+#endif /* INCLUDE_TBI_SUPPORT */
+
+    /* UseTaggedStatus is only valid for 5701 and later. */
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->UseTaggedStatus = FALSE;
+
+        pDevice->CoalesceMode = 0;
+    }
+    else
+    {
+        pDevice->CoalesceMode = HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT |
+            HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT;
+    }
+
+    /* Set the status block size. */
+    if(T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_AX &&
+        T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_BX)
+    {
+        pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE;
+    }
+
+    /* Check the DURING_INT coalescing ticks parameters. */
+    if(pDevice->UseTaggedStatus)
+    {
+        if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxCoalescingTicksDuringInt =
+                DEFAULT_RX_COALESCING_TICKS_DURING_INT;
+        }
+
+        if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxCoalescingTicksDuringInt =
+                DEFAULT_TX_COALESCING_TICKS_DURING_INT;
+        }
+
+        if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxMaxCoalescedFramesDuringInt =
+                DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT;
+        }
+
+        if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxMaxCoalescedFramesDuringInt =
+                DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT;
+        }
+    }
+    else
+    {
+        if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxCoalescingTicksDuringInt = 0;
+        }
+
+        if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxCoalescingTicksDuringInt = 0;
+        }
+
+        if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->RxMaxCoalescedFramesDuringInt = 0;
+        }
+
+        if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE)
+        {
+            pDevice->TxMaxCoalescedFramesDuringInt = 0;
+        }
+    }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if(pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */))
+    {
+        pDevice->RxJumboDescCnt = 0;
+        if(pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+        {
+            pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+        }
+    }
+    else if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+        pDevice->RxJumboDescCnt = 0;
+    }
+    else
+    {
+        pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ +
+            COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK;
+
+        if(pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE)
+        {
+            pDevice->RxJumboBufferSize = DEFAULT_JUMBO_RCV_BUFFER_SIZE;
+            pDevice->RxMtu = pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */;
+        }
+        pDevice->TxMtu = pDevice->RxMtu;
+
+    }
+#else
+    pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    pDevice->RxPacketDescCnt = 
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        pDevice->RxJumboDescCnt +
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+        pDevice->RxStdDescCnt;
+
+    if(pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC)
+    {
+        pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC;
+    }
+
+    if(pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE)
+    {
+        pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE;
+    }
+
+    /* Configure the proper ways to get link change interrupt. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+        }
+        else
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+        }
+    }
+    else if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        /* Auto-polling does not work on 5700_AX and 5700_BX. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+        }
+    }
+
+    /* Determine the method to get link change status. */
+    if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO)
+    {
+        /* The link status bit in the status block does not work on 5700_AX */
+        /* and 5700_BX chips. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+        }
+        else
+        {
+            pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_BLOCK;
+        }
+    }
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+    }
+
+    /* Configure PHY led mode. */
+    if(pDevice->LedMode == LED_MODE_AUTO)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            if(pDevice->SubsystemVendorId == T3_SVID_DELL)
+            {
+                pDevice->LedMode = LED_MODE_LINK10;
+            }
+            else
+            {
+                pDevice->LedMode = LED_MODE_THREE_LINK;
+
+                if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+                {
+                    pDevice->LedMode = EePhyLedMode;
+                }
+            }
+
+            /* bug? 5701 in LINK10 mode does not seem to work when */
+            /* PhyIntMode is LINK_READY. */
+            if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+#if INCLUDE_TBI_SUPPORT
+                pDevice->EnableTbi == FALSE &&
+#endif
+                pDevice->LedMode == LED_MODE_LINK10)
+            {
+                pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+                pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+            }
+
+            if(pDevice->EnableTbi)
+            {
+                pDevice->LedMode = LED_MODE_THREE_LINK;
+            }
+        }
+        else
+        {
+            if(EeSigFound && EePhyLedMode != LED_MODE_AUTO)
+            {
+                pDevice->LedMode = EePhyLedMode;
+            }
+            else
+            {
+                pDevice->LedMode = LED_MODE_OPEN_DRAIN;
+            }
+        }
+    }
+
+#ifdef BCM_WOL
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B2)
+    {
+        pDevice->WolSpeed = WOL_SPEED_10MB;
+    }
+    else
+    {
+        if (pDevice->WolLimit10)
+        {
+            pDevice->WolSpeed = WOL_SPEED_10MB;
+        }
+	else
+        {
+            pDevice->WolSpeed = WOL_SPEED_100MB;
+        }
+    }
+#endif
+
+    pDevice->PciState = REG_RD(pDevice, PciCfg.PciState);
+    LM_ReadVPD(pDevice);
+    LM_ReadBootCodeVersion(pDevice);
+    LM_GetBusSpeed(pDevice);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_GetAdapterInfo */
+
+STATIC PLM_ADAPTER_INFO
+LM_GetAdapterInfoBySsid(
+    LM_UINT16 Svid,
+    LM_UINT16 Ssid)
+{
+    static LM_ADAPTER_INFO AdapterArr[] =
+    {
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, PHY_BCM5401_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, PHY_BCM8002_PHY_ID, 1},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1 },
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, PHY_BCM5701_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, PHY_BCM5703_PHY_ID, 0},
+        { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, PHY_BCM5703_PHY_ID, 0},
+
+        { T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0 },
+
+        { T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+        { T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0 },
+
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0 },
+        { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, 0 },
+
+    };
+    LM_UINT32 j;
+
+    for(j = 0; j < sizeof(AdapterArr)/sizeof(LM_ADAPTER_INFO); j++)
+    {
+        if(AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid)
+        {
+            return &AdapterArr[j];
+        }
+    }
+
+    return NULL;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets up receive/transmit buffer descriptions queues.       */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_InitializeAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_PHYSICAL_ADDRESS MemPhy;
+    PLM_UINT8 pMemVirt;
+    PLM_PACKET pPacket;
+    LM_STATUS Status;
+    LM_UINT32 Size;
+    LM_UINT32 Value32, j;
+
+    /* Set power state to D0. */
+    LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+    /* Intialize the queues. */
+    QQ_InitQueue(&pDevice->RxPacketReceivedQ.Container, 
+        MAX_RX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
+        MAX_RX_PACKET_DESC_COUNT);
+
+    QQ_InitQueue(&pDevice->TxPacketFreeQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketActiveQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        pDevice->RcvRetRcbEntryCount = 512;
+        pDevice->RcvRetRcbEntryCountMask = 511;
+    }
+    else
+    {
+        pDevice->RcvRetRcbEntryCount = T3_RCV_RETURN_RCB_ENTRY_COUNT;
+        pDevice->RcvRetRcbEntryCountMask = T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK;
+    }
+
+    /* Allocate shared memory for: status block, the buffers for receive */
+    /* rings -- standard, mini, jumbo, and return rings. */
+    Size = T3_STATUS_BLOCK_SIZE + sizeof(T3_STATS_BLOCK) +
+        T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) +
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) +
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+        (pDevice->RcvRetRcbEntryCount * sizeof(T3_RCV_BD));
+
+    /* Memory for host based Send BD. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        Size += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+    }
+
+    /* Allocate the memory block. */
+    Status = MM_AllocateSharedMemory(pDevice, Size, (PLM_VOID) &pMemVirt, &MemPhy, FALSE);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* Program DMA Read/Write */
+    if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS)
+    {
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+        {
+            pDevice->DmaReadWriteCtrl = 0x763f0000;
+        }
+        else
+        {
+            pDevice->DmaReadWriteCtrl = 0x763f000f;    
+        }
+    }
+    else
+    {
+        if((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) ||
+            (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704))
+        {
+            pDevice->DmaReadWriteCtrl = 0x761f0000; 
+
+            Value32 = REG_RD(pDevice, PciCfg.ClockCtrl) & 0x1f;
+            if ((Value32 == 0x6) || (Value32 == 0x7))
+            {
+                pDevice->OneDmaAtOnce = TRUE;
+            }
+        }
+        else
+        {
+            pDevice->DmaReadWriteCtrl = 0x761b000f;    
+        }
+    }
+    if((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704))
+    {
+        pDevice->DmaReadWriteCtrl &= 0xfffffff0;
+    }
+
+    if(pDevice->OneDmaAtOnce)
+    {
+        pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE;
+    }
+    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);
+
+    LM_SwitchClocks(pDevice);
+
+    if (LM_DmaTest(pDevice, pMemVirt, MemPhy, 0x400) != LM_STATUS_SUCCESS)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Status block. */
+    pDevice->pStatusBlkVirt = (PT3_STATUS_BLOCK) pMemVirt;
+    pDevice->StatusBlkPhy = MemPhy;
+    pMemVirt += T3_STATUS_BLOCK_SIZE;
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, T3_STATUS_BLOCK_SIZE);
+
+    /* Statistics block. */
+    pDevice->pStatsBlkVirt = (PT3_STATS_BLOCK) pMemVirt;
+    pDevice->StatsBlkPhy = MemPhy;
+    pMemVirt += sizeof(T3_STATS_BLOCK);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, sizeof(T3_STATS_BLOCK));
+
+    /* Receive standard BD buffer. */
+    pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt;
+    pDevice->RxStdBdPhy = MemPhy;
+
+    pMemVirt += T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, 
+        T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Receive jumbo BD buffer. */
+    pDevice->pRxJumboBdVirt = (PT3_RCV_BD) pMemVirt;
+    pDevice->RxJumboBdPhy = MemPhy;
+
+    pMemVirt += T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, 
+        T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD));
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Receive return BD buffer. */
+    pDevice->pRcvRetBdVirt = (PT3_RCV_BD) pMemVirt;
+    pDevice->RcvRetBdPhy = MemPhy;
+
+    pMemVirt += pDevice->RcvRetRcbEntryCount * sizeof(T3_RCV_BD);
+    LM_INC_PHYSICAL_ADDRESS(&MemPhy, 
+        pDevice->RcvRetRcbEntryCount * sizeof(T3_RCV_BD));
+
+    /* Set up Send BD. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt;
+        pDevice->SendBdPhy = MemPhy;
+
+        pMemVirt += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT;
+        LM_INC_PHYSICAL_ADDRESS(&MemPhy, 
+            sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT);
+    }
+#ifdef BCM_NIC_SEND_BD
+    else
+    {
+        pDevice->pSendBdVirt = (PT3_SND_BD)
+            pDevice->pMemView->uIntMem.First32k.BufferDesc;
+        pDevice->SendBdPhy.High = 0;
+        pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR;
+    }
+#endif
+
+    /* Allocate memory for packet descriptors. */
+    Size = (pDevice->RxPacketDescCnt + 
+        pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE;
+    Status = MM_AllocateMemory(pDevice, Size, (PLM_VOID *) &pPacket);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->pPacketDescBase = (PLM_VOID) pPacket;
+
+    /* Create transmit packet descriptors from the memory block and add them */
+    /* to the TxPacketFreeQ for each send ring. */
+    for(j = 0; j < pDevice->TxPacketDescCnt; j++)
+    {
+        /* Ring index. */
+        pPacket->Flags = 0;
+
+        /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */
+        QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for(j.. */
+
+    /* Create receive packet descriptors from the memory block and add them */
+    /* to the RxPacketFreeQ.  Create the Standard packet descriptors. */
+    for(j = 0; j < pDevice->RxStdDescCnt; j++)
+    {
+        /* Receive producer ring. */
+        pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING;
+
+        /* Receive buffer size. */
+        pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE;
+
+        /* Add the descriptor to RxPacketFreeQ. */
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for */
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Create the Jumbo packet descriptors. */
+    for(j = 0; j < pDevice->RxJumboDescCnt; j++)
+    {
+        /* Receive producer ring. */
+        pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING;
+
+        /* Receive buffer size. */
+        pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize;
+
+        /* Add the descriptor to RxPacketFreeQ. */
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        /* Get the pointer to the next descriptor.  MM_PACKET_DESC_SIZE */
+        /* is the total size of the packet descriptor including the */
+        /* os-specific extensions in the UM_PACKET structure. */
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
+    } /* for */
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Initialize the rest of the packet descriptors. */
+    Status = MM_InitializeUmPackets(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    } /* if */
+
+    /* Default receive mask. */
+    pDevice->ReceiveMask &= LM_KEEP_VLAN_TAG;
+    pDevice->ReceiveMask |= LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST |
+        LM_ACCEPT_UNICAST;
+
+    /* Make sure we are in the first 32k memory window or NicSendBd. */
+    REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+    /* Initialize the hardware. */
+    Status = LM_ResetAdapter(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* We are done with initialization. */
+    pDevice->InitDone = TRUE;
+
+    return LM_STATUS_SUCCESS;
+} /* LM_InitializeAdapter */
+
+
+LM_STATUS
+LM_DisableChip(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 data;
+
+    pDevice->RxMode &= ~RX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+    if(!(REG_RD(pDevice, MacCtrl.RxMode) & RX_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, RcvBdIn.Mode);
+    data &= ~RCV_BD_IN_MODE_ENABLE;
+    REG_WR(pDevice, RcvBdIn.Mode,data);
+    if(!(REG_RD(pDevice, RcvBdIn.Mode) & RCV_BD_IN_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, RcvListPlmt.Mode);
+    data &= ~RCV_LIST_PLMT_MODE_ENABLE;
+    REG_WR(pDevice, RcvListPlmt.Mode,data);
+    if(!(REG_RD(pDevice, RcvListPlmt.Mode) & RCV_LIST_PLMT_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        data = REG_RD(pDevice, RcvListSel.Mode);
+        data &= ~RCV_LIST_SEL_MODE_ENABLE;
+        REG_WR(pDevice, RcvListSel.Mode,data);
+        if(!(REG_RD(pDevice, RcvListSel.Mode) & RCV_LIST_SEL_MODE_ENABLE))
+        {
+            MM_Wait(20);
+        }
+    }
+    data = REG_RD(pDevice, RcvDataBdIn.Mode);
+    data &= ~RCV_DATA_BD_IN_MODE_ENABLE;
+    REG_WR(pDevice, RcvDataBdIn.Mode,data);
+    if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_BD_IN_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, RcvDataComp.Mode);
+    data &= ~RCV_DATA_COMP_MODE_ENABLE;
+    REG_WR(pDevice, RcvDataComp.Mode,data);
+    if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_COMP_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, RcvBdComp.Mode);
+    data &= ~RCV_BD_COMP_MODE_ENABLE;
+    REG_WR(pDevice, RcvBdComp.Mode,data);
+    if(!(REG_RD(pDevice, RcvBdComp.Mode) & RCV_BD_COMP_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }     
+    data = REG_RD(pDevice, SndBdSel.Mode);
+    data &= ~SND_BD_SEL_MODE_ENABLE;
+    REG_WR(pDevice, SndBdSel.Mode, data);
+    if(!(REG_RD(pDevice, SndBdSel.Mode) & SND_BD_SEL_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, SndBdIn.Mode);
+    data &= ~SND_BD_IN_MODE_ENABLE;
+    REG_WR(pDevice, SndBdIn.Mode, data);
+    if(!(REG_RD(pDevice, SndBdIn.Mode) & SND_BD_IN_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, SndDataIn.Mode);
+    data &= ~T3_SND_DATA_IN_MODE_ENABLE;
+    REG_WR(pDevice, SndDataIn.Mode,data);
+    if(!(REG_RD(pDevice, SndDataIn.Mode) & T3_SND_DATA_IN_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, DmaRead.Mode);
+    data &= ~DMA_READ_MODE_ENABLE;
+    REG_WR(pDevice, DmaRead.Mode, data);
+    if(!(REG_RD(pDevice, DmaRead.Mode) & DMA_READ_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, SndDataComp.Mode);
+    data &= ~SND_DATA_COMP_MODE_ENABLE;
+    REG_WR(pDevice, SndDataComp.Mode, data);
+    if(!(REG_RD(pDevice, SndDataComp.Mode) & SND_DATA_COMP_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        data = REG_RD(pDevice,DmaComp.Mode);
+        data &= ~DMA_COMP_MODE_ENABLE;
+        REG_WR(pDevice, DmaComp.Mode, data);
+        if(!(REG_RD(pDevice, DmaComp.Mode) & DMA_COMP_MODE_ENABLE))
+        {
+            MM_Wait(20);
+        }
+    }
+    data = REG_RD(pDevice, SndBdComp.Mode);
+    data &= ~SND_BD_COMP_MODE_ENABLE;
+    REG_WR(pDevice, SndBdComp.Mode, data);
+    if(!(REG_RD(pDevice, SndBdComp.Mode) & SND_BD_COMP_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    /* Clear TDE bit */
+    pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    pDevice->TxMode &= ~TX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+    if(!(REG_RD(pDevice, MacCtrl.TxMode) & TX_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, HostCoalesce.Mode);
+    data &= ~HOST_COALESCE_ENABLE;
+    REG_WR(pDevice, HostCoalesce.Mode, data);
+    if(!(REG_RD(pDevice, SndBdIn.Mode) & HOST_COALESCE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    data = REG_RD(pDevice, DmaWrite.Mode);
+    data &= ~DMA_WRITE_MODE_ENABLE;
+    REG_WR(pDevice, DmaWrite.Mode,data);
+    if(!(REG_RD(pDevice, DmaWrite.Mode) & DMA_WRITE_MODE_ENABLE))
+    {
+        MM_Wait(20);
+    }
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        data = REG_RD(pDevice, MbufClusterFree.Mode);
+        data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE;
+        REG_WR(pDevice, MbufClusterFree.Mode,data);
+        if(!(REG_RD(pDevice, MbufClusterFree.Mode) & MBUF_CLUSTER_FREE_MODE_ENABLE))
+        {
+            MM_Wait(20);
+        }
+    }
+    /* Reset all FTQs */
+    REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+    REG_WR(pDevice, Ftq.Reset, 0x0);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        data = REG_RD(pDevice, BufMgr.Mode);
+        data &= ~BUFMGR_MODE_ENABLE;
+        REG_WR(pDevice, BufMgr.Mode,data);
+        if(!(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE))
+        {
+            MM_Wait(20);
+        }
+        data = REG_RD(pDevice, MemArbiter.Mode);
+        data &= ~T3_MEM_ARBITER_MODE_ENABLE;
+        REG_WR(pDevice, MemArbiter.Mode, data);
+        if(!(REG_RD(pDevice, MemArbiter.Mode) & T3_MEM_ARBITER_MODE_ENABLE)) 
+        {
+            MM_Wait(20);
+        }       
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_DisableFW(PLM_DEVICE_BLOCK pDevice)
+{
+#ifdef BCM_ASF
+    int j;
+    LM_UINT32 Value32;
+
+    if (pDevice->EnableAsf)
+    {
+        MEM_WR_OFFSET(pDevice, T3_CMD_MAILBOX, T3_CMD_NICDRV_PAUSE_FW);
+        Value32 = REG_RD(pDevice, Grc.RxCpuEvent);
+        REG_WR(pDevice, Grc.RxCpuEvent, Value32 | BIT_14);
+        for (j = 0; j < 100; j++)
+        {
+            Value32 = REG_RD(pDevice, Grc.RxCpuEvent);
+            if (!(Value32 & BIT_14))
+            {
+                break;
+            }
+            MM_Wait(1);
+        }
+    }
+#endif
+    return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This function reinitializes the adapter.                                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_ResetAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j, k;
+    int reset_count = 0;
+
+    /* Disable interrupt. */
+    LM_DisableInterrupt(pDevice);
+
+restart_reset:
+    LM_DisableFW(pDevice);
+
+    /* May get a spurious interrupt */
+    pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED;
+
+    /* Disable transmit and receive DMA engines.  Abort all pending requests. */
+    if(pDevice->InitDone)
+    {
+        LM_Abort(pDevice);
+    }
+
+    pDevice->ShuttingDown = FALSE;
+
+    LM_ResetChip(pDevice);
+
+#ifdef BCM_ASF
+    if (pDevice->EnableAsf)
+    {
+        MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_START);
+    }
+    else
+#endif
+    {
+        MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_SUSPEND);
+    }
+
+    /* Bug: Athlon fix for B3 silicon only.  This bit does not do anything */
+    /* in other chip revisions. */
+    if(pDevice->DelayPciGrant)
+    {
+        REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl | BIT_31);
+    }
+
+    if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciState);
+            Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+            REG_WR(pDevice, PciCfg.PciState, Value32);
+        }
+    }
+
+    /* Enable TaggedStatus mode. */
+    if(pDevice->UseTaggedStatus)
+    {
+        pDevice->MiscHostCtrl |= MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE;
+    }
+
+    /* Restore PCI configuration registers. */
+    MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+        pDevice->SavedCacheLineReg);
+//    LM_RegWrInd(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, 
+//        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+    MM_WriteConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, 
+        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+    /* Clear the statistics block. */
+    for(j = 0x0300; j < 0x0b00; j++)
+    {
+        MEM_WR_OFFSET(pDevice, j, 0);
+    }
+
+    /* Initialize the statistis Block */
+    pDevice->pStatusBlkVirt->Status = 0;
+    pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+    for(j = 0; j < 16; j++)
+    {
+       pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0;
+       pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0;
+    }
+
+    for(k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT ;k++)
+    {
+       pDevice->pRxStdBdVirt[k].HostAddr.High = 0;
+       pDevice->pRxStdBdVirt[k].HostAddr.Low = 0;
+    }
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Receive jumbo BD buffer. */
+    for(k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++)
+    {
+        pDevice->pRxJumboBdVirt[k].HostAddr.High = 0;
+        pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0;
+    }
+#endif
+
+    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl);    
+
+    /* GRC mode control register. */
+    Value32 = 
+#ifdef BIG_ENDIAN_HOST
+        GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | 
+        GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+        GRC_MODE_BYTE_SWAP_DATA |
+        GRC_MODE_WORD_SWAP_DATA |
+#else
+        GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+        GRC_MODE_BYTE_SWAP_DATA |
+        GRC_MODE_WORD_SWAP_DATA |
+#endif
+        GRC_MODE_INT_ON_MAC_ATTN |
+        GRC_MODE_HOST_STACK_UP;
+
+    /* Configure send BD mode. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        Value32 |= GRC_MODE_HOST_SEND_BDS;
+    }
+#ifdef BCM_NIC_SEND_BD
+    else
+    {
+        Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS;
+    }
+#endif
+
+    /* Configure pseudo checksum mode. */
+    if(pDevice->NoTxPseudoHdrChksum)
+    {
+        Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    if(pDevice->NoRxPseudoHdrChksum)
+    {
+        Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    /* Setup the timer prescalar register. */
+    Value32 = REG_RD(pDevice, Grc.MiscCfg) & ~0xff;
+    /* Clock is always 66Mhz. */
+    REG_WR(pDevice, Grc.MiscCfg, Value32 | (65 << 1));
+
+    /* Set up the MBUF pool base address and size. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+#if INCLUDE_TCP_SEG_SUPPORT
+        if (pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
+        {
+            Value32 = LM_GetStkOffLdFirmwareSize(pDevice);
+            Value32 = (Value32 + 0x7f) & ~0x7f;
+            pDevice->MbufBase = T3_NIC_BCM5705_MBUF_POOL_ADDR + Value32;
+            pDevice->MbufSize = T3_NIC_BCM5705_MBUF_POOL_SIZE - Value32 - 0xa00;
+            REG_WR(pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase);
+            REG_WR(pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize);
+        }
+#endif
+    }
+    else
+    {
+        REG_WR(pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase);
+        REG_WR(pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize);
+
+        /* Set up the DMA descriptor pool base address and size. */
+        REG_WR(pDevice, BufMgr.DmaDescPoolAddr, T3_NIC_DMA_DESC_POOL_ADDR);
+        REG_WR(pDevice, BufMgr.DmaDescPoolSize, T3_NIC_DMA_DESC_POOL_SIZE);
+    
+    }
+
+    /* Configure MBUF and Threshold watermarks */
+    /* Configure the DMA read MBUF low water mark. */
+    if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE)
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+        {
+            REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+                T3_DEF_DMA_MBUF_LOW_WMARK_5705);
+            REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+                T3_DEF_RX_MAC_MBUF_LOW_WMARK_5705);
+            REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+                T3_DEF_MBUF_HIGH_WMARK_5705);
+        }
+        else
+        {
+            REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+                T3_DEF_DMA_MBUF_LOW_WMARK);
+            REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+                T3_DEF_RX_MAC_MBUF_LOW_WMARK);
+            REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+                T3_DEF_MBUF_HIGH_WMARK);
+        }
+    }
+    else
+    {
+        REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,
+            T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO);
+        REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,
+            T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO);
+        REG_WR(pDevice, BufMgr.MbufHighWaterMark,
+            T3_DEF_MBUF_HIGH_WMARK_JUMBO);
+    }
+
+    REG_WR(pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK);
+    REG_WR(pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK);
+
+    /* Enable buffer manager. */
+    REG_WR(pDevice, BufMgr.Mode, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+
+    for(j = 0 ;j < 2000; j++)
+    {
+        if(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE)
+            break;
+        MM_Wait(10);
+    }
+
+    if(j >= 2000)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Enable the FTQs. */
+    REG_WR(pDevice, Ftq.Reset, 0xffffffff);
+    REG_WR(pDevice, Ftq.Reset, 0);
+
+    /* Wait until FTQ is ready */
+    for(j = 0; j < 2000; j++)
+    {
+        if(REG_RD(pDevice, Ftq.Reset) == 0)
+            break;
+        MM_Wait(10);
+    }
+
+    if(j >= 2000)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Receive BD Ring replenish threshold. */
+    REG_WR(pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt/8);
+
+    /* Initialize the Standard Receive RCB. */
+    REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.High, 
+        pDevice->RxStdBdPhy.High);
+    REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.Low, 
+        pDevice->RxStdBdPhy.Low);
+    REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr,
+        (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags,
+            512 << 16);
+    }
+    else
+    {
+        REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags,
+            MAX_STD_RCV_BUFFER_SIZE << 16);
+
+        /* Initialize the Jumbo Receive RCB. */
+        REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags,
+            T3_RCB_FLAG_RING_DISABLED);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.High, 
+            pDevice->RxJumboBdPhy.High);
+        REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.Low, 
+            pDevice->RxJumboBdPhy.Low);
+        REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0);
+        REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr,
+            (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR);
+
+        REG_WR(pDevice, RcvBdIn.JumboRcvThreshold, pDevice->RxJumboDescCnt/8);
+
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+        /* Initialize the Mini Receive RCB. */
+        REG_WR(pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags,
+            T3_RCB_FLAG_RING_DISABLED);
+
+        /* Disable all the unused rings. */
+        for(j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) {
+            MEM_WR(pDevice, SendRcb[j].u.MaxLen_Flags,
+                T3_RCB_FLAG_RING_DISABLED);
+        } /* for */
+
+    }
+
+    /* Initialize the indices. */
+    pDevice->SendProdIdx = 0;
+    pDevice->SendConIdx = 0;
+
+    MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, 0); 
+    MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, 0);
+
+    /* Set up host or NIC based send RCB. */
+    if(pDevice->NicSendBd == FALSE)
+    {
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.High, 
+            pDevice->SendBdPhy.High);
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low, 
+            pDevice->SendBdPhy.Low);
+
+        /* Setup the RCB. */
+        MEM_WR(pDevice, SendRcb[0].u.MaxLen_Flags,
+            T3_SEND_RCB_ENTRY_COUNT << 16);
+
+        if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+        {
+            /* Set up the NIC ring address in the RCB. */
+            MEM_WR(pDevice, SendRcb[0].NicRingAddr,T3_NIC_SND_BUFFER_DESC_ADDR);
+
+            for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++)
+            {
+                pDevice->pSendBdVirt[k].HostAddr.High = 0;
+                pDevice->pSendBdVirt[k].HostAddr.Low = 0;
+            }
+        }
+    }
+#ifdef BCM_NIC_SEND_BD
+    else
+    {
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.High, 0);
+        MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low, 0);
+        MEM_WR(pDevice, SendRcb[0].NicRingAddr,
+            pDevice->SendBdPhy.Low);
+
+        for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++)
+        {
+            MM_MEMWRITEL(&(pDevice->pSendBdVirt[k].HostAddr.High), 0);
+            MM_MEMWRITEL(&(pDevice->pSendBdVirt[k].HostAddr.Low), 0);
+            MM_MEMWRITEL(&(pDevice->pSendBdVirt[k].u1.Len_Flags), 0);
+            pDevice->ShadowSendBd[k].HostAddr.High = 0;
+            pDevice->ShadowSendBd[k].u1.Len_Flags = 0;
+        }
+    }
+#endif
+    MM_ATOMIC_SET(&pDevice->SendBdLeft, T3_SEND_RCB_ENTRY_COUNT-1);
+
+    /* Configure the receive return rings. */
+    for(j = 0; j < T3_MAX_RCV_RETURN_RCB_COUNT; j++)
+    {
+        MEM_WR(pDevice, RcvRetRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED);
+    }
+
+    pDevice->RcvRetConIdx = 0;
+
+    MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.High, 
+        pDevice->RcvRetBdPhy.High);
+    MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.Low,
+        pDevice->RcvRetBdPhy.Low);
+
+    MEM_WR(pDevice, RcvRetRcb[0].NicRingAddr, 0);
+
+    /* Setup the RCB. */
+    MEM_WR(pDevice, RcvRetRcb[0].u.MaxLen_Flags,
+        pDevice->RcvRetRcbEntryCount << 16);
+
+    /* Reinitialize RX ring producer index */
+    MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, 0);
+    MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low, 0);
+    MB_REG_WR(pDevice, Mailbox.RcvMiniProdIdx.Low, 0);
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    pDevice->RxJumboProdIdx = 0;
+    pDevice->RxJumboQueuedCnt = 0;
+#endif
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxStdProdIdx = 0;
+    pDevice->RxStdQueuedCnt = 0;
+
+#if T3_JUMBO_RCV_ENTRY_COUNT
+    pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_ENTRY_COUNT */
+
+    /* Configure the MAC address. */
+    LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    /* Initialize the transmit random backoff seed. */
+    Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] + 
+        pDevice->NodeAddress[2] + pDevice->NodeAddress[3] + 
+        pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) & 
+        MAC_TX_BACKOFF_SEED_MASK;
+    REG_WR(pDevice, MacCtrl.TxBackoffSeed, Value32);
+
+    /* Receive MTU.  Frames larger than the MTU is marked as oversized. */
+    REG_WR(pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8);   /* CRC + VLAN. */
+
+    /* Configure Time slot/IPG per 802.3 */
+    REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+
+    /*
+     * Configure Receive Rules so that packets don't match 
+     * Programmble rule will be queued to Return Ring 1 
+     */
+    REG_WR(pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS);
+
+    /* 
+     * Configure to have 16 Classes of Services (COS) and one
+     * queue per class.  Bad frames are queued to RRR#1.
+     * And frames don't match rules are also queued to COS#1.
+     */
+    REG_WR(pDevice, RcvListPlmt.Config, 0x181);
+    
+    /* Enable Receive Placement Statistics */
+    REG_WR(pDevice, RcvListPlmt.StatsEnableMask,0xffffff);
+    REG_WR(pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE);
+
+    /* Enable Send Data Initator Statistics */
+    REG_WR(pDevice, SndDataIn.StatsEnableMask,0xffffff);
+    REG_WR(pDevice, SndDataIn.StatsCtrl,
+        T3_SND_DATA_IN_STATS_CTRL_ENABLE | \
+        T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE);
+
+    /* Disable the host coalescing state machine before configuring it's */
+    /* parameters. */
+    REG_WR(pDevice, HostCoalesce.Mode, 0); 
+    for(j = 0; j < 2000; j++)
+    {
+        Value32 = REG_RD(pDevice, HostCoalesce.Mode);
+        if(!(Value32 & HOST_COALESCE_ENABLE))
+        {
+            break;
+        }
+        MM_Wait(10);
+    }
+
+    /* Host coalescing configurations. */
+    REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, pDevice->RxCoalescingTicks);
+    REG_WR(pDevice, HostCoalesce.TxCoalescingTicks, pDevice->TxCoalescingTicks);
+    REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames,
+        pDevice->RxMaxCoalescedFrames);
+    REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames,
+        pDevice->TxMaxCoalescedFrames);
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        REG_WR(pDevice, HostCoalesce.RxCoalescedTickDuringInt,
+            pDevice->RxCoalescingTicksDuringInt);
+        REG_WR(pDevice, HostCoalesce.TxCoalescedTickDuringInt,
+            pDevice->TxCoalescingTicksDuringInt);
+    }
+    REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt,
+        pDevice->RxMaxCoalescedFramesDuringInt);
+    REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFramesDuringInt,
+        pDevice->TxMaxCoalescedFramesDuringInt);
+
+    /* Initialize the address of the status block.  The NIC will DMA */
+    /* the status block to this memory which resides on the host. */
+    REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.High, 
+        pDevice->StatusBlkPhy.High);
+    REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.Low,
+        pDevice->StatusBlkPhy.Low);
+
+    /* Initialize the address of the statistics block.  The NIC will DMA */
+    /* the statistics to this block of memory. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.High, 
+            pDevice->StatsBlkPhy.High);
+        REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.Low,
+            pDevice->StatsBlkPhy.Low);
+
+        REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks,
+            pDevice->StatsCoalescingTicks);
+
+        REG_WR(pDevice, HostCoalesce.StatsBlkNicAddr, 0x300);
+        REG_WR(pDevice, HostCoalesce.StatusBlkNicAddr,0xb00);
+    }
+
+    /* Enable Host Coalesing state machine */
+    REG_WR(pDevice, HostCoalesce.Mode, HOST_COALESCE_ENABLE |
+        pDevice->CoalesceMode);
+
+    /* Enable the Receive BD Completion state machine. */
+    REG_WR(pDevice, RcvBdComp.Mode, RCV_BD_COMP_MODE_ENABLE |
+        RCV_BD_COMP_MODE_ATTN_ENABLE);
+
+    /* Enable the Receive List Placement state machine. */
+    REG_WR(pDevice, RcvListPlmt.Mode, RCV_LIST_PLMT_MODE_ENABLE);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        /* Enable the Receive List Selector state machine. */
+        REG_WR(pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE |
+            RCV_LIST_SEL_MODE_ATTN_ENABLE);
+    }
+
+    /* Enable transmit DMA, clear statistics. */
+    pDevice->MacMode =  MAC_MODE_ENABLE_TX_STATISTICS |
+        MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE |
+        MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+        MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS);
+
+    /* GRC miscellaneous local control register. */
+    pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN |
+        GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+            GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1;
+    }
+
+    REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+    MM_Wait(40);
+
+    /* Reset RX counters. */
+    for(j = 0; j < sizeof(LM_RX_COUNTERS); j++)
+    {
+        ((PLM_UINT8) &pDevice->RxCounters)[j] = 0;
+    }
+
+    /* Reset TX counters. */
+    for(j = 0; j < sizeof(LM_TX_COUNTERS); j++)
+    {
+        ((PLM_UINT8) &pDevice->TxCounters)[j] = 0;
+    }
+
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
+    pDevice->LastTag = 0;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        /* Enable the DMA Completion state machine. */
+        REG_WR(pDevice, DmaComp.Mode, DMA_COMP_MODE_ENABLE);
+    }
+
+    /* Enable the DMA Write state machine. */
+    Value32 = DMA_WRITE_MODE_ENABLE |
+        DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE |
+        DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE |
+        DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE |
+        DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+        DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+        DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+        DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+        DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE;
+
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) &&
+        (pDevice->ChipRevId != T3_CHIP_ID_5705_A0))
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_HIGH_BUS_SPEED))
+        {
+            Value32 |= DMA_WRITE_MODE_RECEIVE_ACCELERATE;
+        }
+    }
+    REG_WR(pDevice, DmaWrite.Mode, Value32);
+
+    if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+    {
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciXCapabilities);
+            Value32 &= ~PCIX_CMD_MAX_BURST_MASK;
+            Value32 |= PCIX_CMD_MAX_BURST_CPIOB << PCIX_CMD_MAX_BURST_SHL;
+            REG_WR(pDevice, PciCfg.PciXCapabilities, Value32);
+        }
+        else if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciXCapabilities);
+            Value32 &= ~(PCIX_CMD_MAX_SPLIT_MASK | PCIX_CMD_MAX_BURST_MASK);
+            Value32 |= ((PCIX_CMD_MAX_BURST_CPIOB << PCIX_CMD_MAX_BURST_SHL) &
+                PCIX_CMD_MAX_BURST_MASK);
+            if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+            {
+                Value32 |= (pDevice->SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL)
+                   & PCIX_CMD_MAX_SPLIT_MASK;
+            }
+            REG_WR(pDevice, PciCfg.PciXCapabilities, Value32);
+        }
+    }
+
+    /* Enable the Read DMA state machine. */
+    Value32 = DMA_READ_MODE_ENABLE |
+        DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE |
+        DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE |
+        DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE |
+        DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+        DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+        DMA_READ_MODE_LONG_READ_ATTN_ENABLE;
+
+    if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE)
+    {
+        Value32 |= DMA_READ_MODE_SPLIT_ENABLE;
+    }
+
+    pDevice->RxBDLimit64 = FALSE;
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        if (pDevice->ChipRevId != T3_CHIP_ID_5705_A0)
+        {
+#if INCLUDE_TCP_SEG_SUPPORT
+            if (pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
+            {
+                Value32 |= DMA_READ_MODE_FIFO_SIZE_128;
+            }
+            else
+#endif
+            {
+                if (!(pDevice->PciState & T3_PCI_STATE_HIGH_BUS_SPEED))
+                {
+                    Value32 |= DMA_READ_MODE_FIFO_LONG_BURST;
+                    if (pDevice->ChipRevId == T3_CHIP_ID_5705_A1)
+                    {
+                        pDevice->RxBDLimit64 = TRUE;
+                    }
+                }
+            }
+        }
+    }
+
+    REG_WR(pDevice, DmaRead.Mode, Value32);
+
+    /* Enable the Receive Data Completion state machine. */
+    REG_WR(pDevice, RcvDataComp.Mode, RCV_DATA_COMP_MODE_ENABLE |
+        RCV_DATA_COMP_MODE_ATTN_ENABLE);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        /* Enable the Mbuf Cluster Free state machine. */
+        REG_WR(pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE);
+    }
+
+    /* Enable the Send Data Completion state machine. */
+    REG_WR(pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE);
+
+    /* Enable the Send BD Completion state machine. */
+    REG_WR(pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE |
+        SND_BD_COMP_MODE_ATTN_ENABLE);
+
+    /* Enable the Receive BD Initiator state machine. */
+    REG_WR(pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE |
+        RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE);
+
+    /* Enable the Receive Data and Receive BD Initiator state machine. */
+    REG_WR(pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE |
+        RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE);
+
+    /* Enable the Send Data Initiator state machine. */
+    REG_WR(pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE);
+
+    /* Enable the Send BD Initiator state machine. */
+    REG_WR(pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE |
+        SND_BD_IN_MODE_ATTN_ENABLE);
+
+    /* Enable the Send BD Selector state machine. */
+    REG_WR(pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE |
+        SND_BD_SEL_MODE_ATTN_ENABLE);
+
+#if INCLUDE_5701_AX_FIX
+    /* Load the firmware for the 5701_A0 workaround. */
+    if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0)
+    {
+        LM_LoadRlsFirmware(pDevice);
+    }
+#endif
+
+    /* Queue Rx packet buffers. */
+    if(pDevice->QueueRxPackets)
+    {
+        LM_QueueRxPackets(pDevice);
+    }
+
+    if (pDevice->ChipRevId == T3_CHIP_ID_5705_A0)
+    {
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_STD_RCV_BUFFER_DESC_ADDR + 8);
+        j = 0;
+        while ((Value32 != MAX_STD_RCV_BUFFER_SIZE) && (j < 10))
+        {
+            MM_Wait(20);
+            Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_STD_RCV_BUFFER_DESC_ADDR + 8);
+            j++;
+        }
+        if (j >= 10)
+        {
+            reset_count++;
+            LM_Abort(pDevice);
+            if (reset_count > 5)
+                return LM_STATUS_FAILURE;
+            goto restart_reset;
+        }
+    }
+
+    /* Enable the transmitter. */
+    pDevice->TxMode = TX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+    
+    /* Enable the receiver. */
+    pDevice->RxMode = (pDevice->RxMode & RX_MODE_KEEP_VLAN_TAG) |
+        RX_MODE_ENABLE;
+    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+#ifdef BCM_WOL
+    if (pDevice->RestoreOnWakeUp)
+    {
+        pDevice->RestoreOnWakeUp = FALSE;
+        pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg;
+        pDevice->RequestedLineSpeed = pDevice->WakeUpRequestedLineSpeed;
+        pDevice->RequestedDuplexMode = pDevice->WakeUpRequestedDuplexMode;
+    }
+#endif
+
+    /* Disable auto polling. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        Value32 = LED_CTRL_PHY_MODE_1;
+    }
+    else
+    {
+        if(pDevice->LedMode == LED_MODE_OUTPUT)
+        {
+            Value32 = LED_CTRL_PHY_MODE_2;
+        }
+        else
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+    }
+    REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+    
+    /* Activate Link to enable MAC state machine */
+    REG_WR(pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN);
+
+    if (pDevice->EnableTbi)
+    {
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_RESET);
+        MM_Wait(10);
+        REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+        if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1)
+        {
+            REG_WR(pDevice, MacCtrl.SerdesCfg, 0x616000);
+        }
+    }
+
+    REG_WR(pDevice, MacCtrl.LowWaterMarkMaxRxFrame, 2);
+
+    pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+
+    LM_ResetPhy(pDevice);
+
+    /* Setup the phy chip. */
+    LM_SetupPhy(pDevice);
+
+    if (!pDevice->EnableTbi) {
+        /* Clear CRC stats */
+        LM_ReadPhy(pDevice, 0x1e, &Value32);
+        LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
+        LM_ReadPhy(pDevice, 0x14, &Value32);
+    }
+
+    /* Set up the receive mask. */
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask);
+
+#if INCLUDE_TCP_SEG_SUPPORT
+    if (pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
+    {
+        if (LM_LoadStkOffLdFirmware(pDevice) == LM_STATUS_FAILURE)
+        {
+            return LM_STATUS_FAILURE;
+        }
+    }
+#endif
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ResetAdapter */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine disables the adapter from generating interrupts.           */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_DisableInterrupt(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl | 
+        MISC_HOST_CTRL_MASK_PCI_INT);
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+    if (pDevice->FlushPostedWrites)
+    {
+        MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine enables the adapter to generate interrupts.                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_EnableInterrupt(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, pDevice->LastTag << 24);
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl &
+        ~MISC_HOST_CTRL_MASK_PCI_INT);
+
+    REG_WR(pDevice, HostCoalesce.Mode, pDevice->CoalesceMode |
+        HOST_COALESCE_ENABLE | HOST_COALESCE_NOW);
+
+    if (pDevice->FlushPostedWrites)
+    {
+        MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine puts a packet on the wire if there is a transmit DMA       */
+/*    descriptor available; otherwise the packet is queued for later          */
+/*    transmission.  If the second argue is NULL, this routine will put       */
+/*    the queued packet on the wire if possible.                              */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    LM_UINT32 FragCount;
+    PT3_SND_BD pSendBd, pTmpSendBd;
+#ifdef BCM_NIC_SEND_BD
+    PT3_SND_BD pShadowSendBd;
+    T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT];
+#endif
+    LM_UINT32 StartIdx, Idx;
+
+    while (1)
+    {
+        /* Initalize the send buffer descriptors. */
+        StartIdx = Idx = pDevice->SendProdIdx;
+
+#ifdef BCM_NIC_SEND_BD
+        if (pDevice->NicSendBd)
+        {
+            pTmpSendBd = pSendBd = &NicSendBdArr[0];
+        }
+        else
+#endif
+        {
+            pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx];
+        }
+
+        /* Next producer index. */
+        for(FragCount = 0; ; )
+        {
+            LM_UINT32 Value32, Len;
+
+            /* Initialize the pointer to the send buffer fragment. */
+            MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount);
+
+            pSendBd->u2.VlanTag = pPacket->VlanTag;
+
+            /* Setup the control flags and send buffer size. */
+            Value32 = (Len << 16) | pPacket->Flags;
+
+#if INCLUDE_TCP_SEG_SUPPORT
+            if (Value32 & (SND_BD_FLAG_CPU_PRE_DMA | SND_BD_FLAG_CPU_POST_DMA))
+            {
+                if (FragCount == 0)
+                {
+                    pSendBd->u2.s2.Reserved = pPacket->u.Tx.MaxSegmentSize;
+                }
+                else
+                {
+                    pSendBd->u2.s2.Reserved = 0;
+                }
+            }
+#endif
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+                
+            FragCount++;
+            if (FragCount >= pPacket->u.Tx.FragCount)
+            {
+                pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END;
+                break;
+            }
+            else
+            {
+                pSendBd->u1.Len_Flags = Value32;
+            }
+
+            pSendBd++;
+            if ((Idx == 0) && !pDevice->NicSendBd)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        } /* for */
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+        {
+            if (LM_Test4GBoundary(pDevice, pPacket, pTmpSendBd) ==
+                LM_STATUS_SUCCESS)
+            {
+                if (MM_CoalesceTxBuffer(pDevice, pPacket) != LM_STATUS_SUCCESS)
+                {
+                    QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+                    return LM_STATUS_FAILURE;
+                }
+                continue;
+            }
+        }
+        break;
+    }
+    /* Put the packet descriptor in the ActiveQ. */
+    QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
+
+#ifdef BCM_NIC_SEND_BD
+    if (pDevice->NicSendBd)
+    {
+        pSendBd = &pDevice->pSendBdVirt[StartIdx];
+        pShadowSendBd = &pDevice->ShadowSendBd[StartIdx];
+
+        while (StartIdx != Idx)
+        {
+            LM_UINT32 Value32;
+
+            if ((Value32 = pTmpSendBd->HostAddr.High) !=
+                pShadowSendBd->HostAddr.High)
+            {
+                MM_MEMWRITEL(&(pSendBd->HostAddr.High), Value32);
+                pShadowSendBd->HostAddr.High = Value32;
+            }
+
+            MM_MEMWRITEL(&(pSendBd->HostAddr.Low), pTmpSendBd->HostAddr.Low);
+
+            if ((Value32 = pTmpSendBd->u1.Len_Flags) !=
+                pShadowSendBd->u1.Len_Flags)
+            {
+                MM_MEMWRITEL(&(pSendBd->u1.Len_Flags), Value32);
+                pShadowSendBd->u1.Len_Flags = Value32;
+            }
+
+            if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG)
+            {
+                MM_MEMWRITEL(&(pSendBd->u2.VlanTag), pTmpSendBd->u2.VlanTag);
+            }
+
+            StartIdx = (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+            if (StartIdx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+                pShadowSendBd = &pDevice->ShadowSendBd[0];
+            }
+            else
+            {
+                pSendBd++;
+                pShadowSendBd++;
+            }
+            pTmpSendBd++;
+        }
+        MM_WMB();
+        MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+
+        if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+        {
+            MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
+        }
+        if (pDevice->FlushPostedWrites)
+        {
+            MB_REG_RD(pDevice, Mailbox.SendNicProdIdx[0].Low);
+        }
+    }
+    else
+#endif
+    {
+        MM_WMB();
+        MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+
+        if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
+        {
+            MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
+        }
+        if (pDevice->FlushPostedWrites)
+        {
+            MB_REG_RD(pDevice, Mailbox.SendHostProdIdx[0].Low);
+        }
+    }
+
+    /* Update the SendBdLeft count. */
+    MM_ATOMIC_SUB(&pDevice->SendBdLeft, pPacket->u.Tx.FragCount);
+
+    /* Update the producer index. */
+    pDevice->SendProdIdx = Idx;
+
+    return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS
+LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket,
+    PT3_SND_BD pSendBd)
+{
+    int FragCount;
+    LM_UINT32 Idx, Base, Len;
+
+    Idx = pDevice->SendProdIdx;
+    for(FragCount = 0; ; )
+    {
+        Len = pSendBd->u1.Len_Flags >> 16;
+        if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) &&
+            (pSendBd->HostAddr.High == 0) &&
+            ((Base + 8 + Len) < Base))
+        {
+            return LM_STATUS_SUCCESS;
+        }
+        FragCount++;
+        if (FragCount >= pPacket->u.Tx.FragCount)
+        {
+            break;
+        }
+        pSendBd++;
+        if (!pDevice->NicSendBd)
+        {
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+            if (Idx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        }
+    }
+    return LM_STATUS_FAILURE;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static unsigned long
+ComputeCrc32(
+unsigned char *pBuffer,
+unsigned long BufferSize) {
+    unsigned long Reg;
+    unsigned long Tmp;
+    unsigned long j, k;
+
+    Reg = 0xffffffff;
+
+    for(j = 0; j < BufferSize; j++)
+    {
+        Reg ^= pBuffer[j];
+
+        for(k = 0; k < 8; k++)
+        {
+            Tmp = Reg & 0x01;
+
+            Reg >>= 1;
+
+            if(Tmp)
+            {
+                Reg ^= 0xedb88320;
+            }
+        }
+    }
+
+    return ~Reg;
+} /* ComputeCrc32 */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets the receive control register according to ReceiveMask */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask)
+{
+    LM_UINT32 ReceiveMask;
+    LM_UINT32 RxMode;
+    LM_UINT32 j, k;
+
+    ReceiveMask = Mask;
+
+    RxMode = pDevice->RxMode;
+
+    if(Mask & LM_ACCEPT_UNICAST)
+    {
+        Mask &= ~LM_ACCEPT_UNICAST;
+    }
+
+    if(Mask & LM_ACCEPT_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_ALL_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_ALL_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_BROADCAST)
+    {
+        Mask &= ~LM_ACCEPT_BROADCAST;
+    }
+
+    RxMode &= ~RX_MODE_KEEP_VLAN_TAG;
+    if (Mask & LM_KEEP_VLAN_TAG)
+    {
+        RxMode |= RX_MODE_KEEP_VLAN_TAG;
+        Mask &= ~LM_KEEP_VLAN_TAG;
+    }
+
+    RxMode &= ~RX_MODE_PROMISCUOUS_MODE;
+    if(Mask & LM_PROMISCUOUS_MODE)
+    {
+        RxMode |= RX_MODE_PROMISCUOUS_MODE;
+        Mask &= ~LM_PROMISCUOUS_MODE;
+    }
+
+    RxMode &= ~(RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED);
+    if(Mask & LM_ACCEPT_ERROR_PACKET)
+    {
+        RxMode |= RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED;
+        Mask &= ~LM_ACCEPT_ERROR_PACKET;
+    }
+
+    /* Make sure all the bits are valid before committing changes. */
+    if(Mask)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    /* Commit the new filter. */
+    pDevice->ReceiveMask = ReceiveMask;
+
+    pDevice->RxMode = RxMode;
+
+    if (pDevice->PowerLevel != LM_POWER_STATE_D0)
+    {
+        return LM_STATUS_SUCCESS;
+    }
+
+    REG_WR(pDevice, MacCtrl.RxMode, RxMode);
+
+    /* Set up the MC hash table. */
+    if(ReceiveMask & LM_ACCEPT_ALL_MULTICAST)
+    {
+        for(k = 0; k < 4; k++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[k], 0xffffffff);
+        }
+    }
+    else if(ReceiveMask & LM_ACCEPT_MULTICAST)
+    {
+        LM_UINT32 HashReg[4];
+
+        HashReg[0] = 0; HashReg[1] = 0; HashReg[2] = 0; HashReg[3] = 0;
+        for(j = 0; j < pDevice->McEntryCount; j++)
+        {
+            LM_UINT32 RegIndex;
+            LM_UINT32 Bitpos;
+            LM_UINT32 Crc32;
+
+            Crc32 = ComputeCrc32(pDevice->McTable[j], ETHERNET_ADDRESS_SIZE);
+
+            /* The most significant 7 bits of the CRC32 (no inversion), */
+            /* are used to index into one of the possible 128 bit positions. */
+            Bitpos = ~Crc32 & 0x7f;
+
+            /* Hash register index. */
+            RegIndex = (Bitpos & 0x60) >> 5;
+
+            /* Bit to turn on within a hash register. */
+            Bitpos &= 0x1f;
+
+            /* Enable the multicast bit. */
+            HashReg[RegIndex] |= (1 << Bitpos);
+        }
+
+        /* REV_AX has problem with multicast filtering where it uses both */
+        /* DA and SA to perform hashing. */
+        for(k = 0; k < 4; k++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[k], HashReg[k]);
+        }
+    }
+    else
+    {
+        /* Reject all multicast frames. */
+        for(j = 0; j < 4; j++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[j], 0);
+        }
+    }
+
+    /* By default, Tigon3 will accept broadcast frames.  We need to setup */
+    if(ReceiveMask & LM_ACCEPT_BROADCAST)
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule,
+            REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value,
+            REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, 
+            REJECT_BROADCAST_RULE1_RULE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, 
+            REJECT_BROADCAST_RULE1_VALUE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, 
+            REJECT_BROADCAST_RULE2_RULE);
+        REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, 
+            REJECT_BROADCAST_RULE2_VALUE);
+    }
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        k = 16;
+    }
+    else
+    {
+        k = 8;
+    }
+#ifdef BCM_ASF
+    if (pDevice->EnableAsf)
+    {
+        k -= 4;
+    }
+#endif
+
+    /* disable the rest of the rules. */
+    for(j = RCV_LAST_RULE_IDX; j < k; j++)
+    {
+        REG_WR(pDevice, MacCtrl.RcvRules[j].Rule, 0);
+        REG_WR(pDevice, MacCtrl.RcvRules[j].Value, 0);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetReceiveMask */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Disable the interrupt and put the transmitter and receiver engines in   */
+/*    an idle state.  Also aborts all pending send requests and receive       */
+/*    buffers.                                                                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_Abort(
+PLM_DEVICE_BLOCK pDevice)
+{
+    PLM_PACKET pPacket;
+    LM_UINT Idx;
+
+    LM_DisableInterrupt(pDevice);
+
+    LM_DisableChip(pDevice);
+
+    /* Abort packets that have already queued to go out. */
+    pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    while(pPacket)
+    {
+
+        pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED;
+        pDevice->TxCounters.TxPacketAbortedCnt++;
+
+        MM_ATOMIC_ADD(&pDevice->SendBdLeft, pPacket->u.Tx.FragCount);
+
+        QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+        pPacket = (PLM_PACKET) 
+            QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    }
+
+    /* Cleanup the receive return rings. */
+    LM_ServiceRxInterrupt(pDevice);
+
+    /* Don't want to indicate rx packets in Ndis miniport shutdown context. */
+    /* Doing so may cause system crash. */
+    if(!pDevice->ShuttingDown)
+    {
+        /* Indicate packets to the protocol. */
+        MM_IndicateTxPackets(pDevice);
+
+        /* Indicate received packets to the protocols. */
+        MM_IndicateRxPackets(pDevice);
+    }
+    else
+    {
+        /* Move the receive packet descriptors in the ReceivedQ to the */
+        /* free queue. */
+        for(; ;)
+        {
+            pPacket = (PLM_PACKET) QQ_PopHead(
+                &pDevice->RxPacketReceivedQ.Container);
+            if(pPacket == NULL)
+            {
+                break;
+            }
+            QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+        }
+    }
+
+    /* Clean up the Std Receive Producer ring. */
+    Idx = pDevice->pStatusBlkVirt->RcvStdConIdx;
+
+    while(Idx != pDevice->RxStdProdIdx) {
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pDevice->pRxStdBdVirt[Idx].Opaque));
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK;
+    } /* while */
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxStdProdIdx = 0;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    /* Clean up the Jumbo Receive Producer ring. */
+    Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx;
+
+    while(Idx != pDevice->RxJumboProdIdx) {
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pDevice->pRxJumboBdVirt[Idx].Opaque));
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK;
+    } /* while */
+
+    /* Reinitialize our copy of the indices. */
+    pDevice->RxJumboProdIdx = 0;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* Initialize the statistis Block */
+    pDevice->pStatusBlkVirt->Status = 0;
+    pDevice->pStatusBlkVirt->RcvStdConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvJumboConIdx = 0;
+    pDevice->pStatusBlkVirt->RcvMiniConIdx = 0;
+
+    return LM_STATUS_SUCCESS;
+} /* LM_Abort */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Disable the interrupt and put the transmitter and receiver engines in   */
+/*    an idle state.  Aborts all pending send requests and receive buffers.   */
+/*    Also free all the receive buffers.                                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_Halt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    LM_UINT32 EntryCnt;
+
+    LM_DisableFW(pDevice);
+
+    LM_Abort(pDevice);
+
+    /* Get the number of entries in the queue. */
+    EntryCnt = QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container);
+
+    /* Make sure all the packets have been accounted for. */
+    for(EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++)
+    {
+        pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+        if (pPacket == 0)
+            break;
+
+        MM_FreeRxBuffer(pDevice, pPacket);
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+
+    LM_ResetChip(pDevice);
+
+#ifdef BCM_ASF
+    if (pDevice->EnableAsf)
+    {
+        if (pDevice->WakeUpModeCap == LM_WAKE_UP_MODE_NONE)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_UNLOAD);
+        }
+        else
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_WOL);
+        }
+    }
+    else
+#endif
+    {
+        MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_SUSPEND);
+    }
+    /* Restore PCI configuration registers. */
+    MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+        pDevice->SavedCacheLineReg);
+    LM_RegWrInd(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, 
+        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+    /* Reprogram the MAC address. */
+    LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_Halt */
+
+
+LM_STATUS
+LM_ResetChip(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    /* Wait for access to the nvram interface before resetting.  This is */
+    /* a workaround to prevent EEPROM corruption. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        /* Request access to the flash interface. */
+        REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1);
+
+        for(j = 0; j < 1000; j++)
+        {
+            Value32 = REG_RD(pDevice, Nvram.SwArb);
+            if(Value32 & SW_ARB_GNT1)
+            {
+                break;
+            }
+            MM_Wait(20);
+        }
+    }
+
+    Value32 = GRC_MISC_CFG_CORE_CLOCK_RESET;
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        Value32 |= GRC_MISC_GPHY_KEEP_POWER_DURING_RESET;
+    }
+    /* Global reset. */
+    RAW_REG_WR(pDevice, Grc.MiscCfg, Value32);
+    MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+    /* make sure we re-enable indirect accesses */
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG,
+        pDevice->MiscHostCtrl);
+
+    /* Set MAX PCI retry to zero. */
+    Value32 = T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE;
+    if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 |= T3_PCI_STATE_RETRY_SAME_DMA;
+        }
+    }
+    MM_WriteConfig32(pDevice, T3_PCI_STATE_REG, Value32);
+
+    /* Restore PCI command register. */
+    MM_WriteConfig32(pDevice, PCI_COMMAND_REG,
+        pDevice->PciCommandStatusWords);
+
+    /* Disable PCI-X relaxed ordering bit. */
+    MM_ReadConfig32(pDevice, PCIX_CAP_REG, &Value32);
+    Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING;
+    MM_WriteConfig32(pDevice, PCIX_CAP_REG, Value32);
+
+    /* Enable memory arbiter. */
+    REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+
+#ifdef BIG_ENDIAN_HOST
+    /* Reconfigure the mode register. */
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | 
+              GRC_MODE_WORD_SWAP_NON_FRAME_DATA |
+              GRC_MODE_BYTE_SWAP_DATA |
+              GRC_MODE_WORD_SWAP_DATA;
+#else
+    /* Reconfigure the mode register. */
+    Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA;
+#endif
+    REG_WR(pDevice, Grc.Mode, Value32);
+
+    if (pDevice->MiniPci &&
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705))
+    {
+        pDevice->ClockCtrl |= T3_PCI_FORCE_CLKRUN | T3_PCI_CLKRUN_OUTPUT_EN;
+        REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl);
+    }
+
+    /* Prevent PXE from restarting. */
+    MEM_WR_OFFSET(pDevice, T3_FIRMWARE_MAILBOX,T3_MAGIC_NUM_FIRMWARE_INIT_DONE);
+
+    if(pDevice->EnableTbi) {
+        pDevice->MacMode = MAC_MODE_PORT_MODE_TBI;
+        REG_WR(pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI);
+    }
+    else {
+        REG_WR(pDevice, MacCtrl.Mode, 0);
+    }
+
+    /* Wait for the firmware to finish initialization. */
+    for(j = 0; j < 100000; j++)
+    {
+        MM_Wait(10);
+
+        Value32 = MEM_RD_OFFSET(pDevice, T3_FIRMWARE_MAILBOX);
+        if(Value32 == ~T3_MAGIC_NUM_FIRMWARE_INIT_DONE)
+        {
+            break;
+        }
+    }
+
+#ifdef BCM_ASF
+    pDevice->EnableAsf = FALSE;
+    Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_SIG_ADDR);
+    if (Value32 == T3_NIC_DATA_SIG)
+    {
+        Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR);
+        if (Value32 & T3_NIC_CFG_ENABLE_ASF)
+        {
+            pDevice->EnableAsf = TRUE;
+        }
+    }
+#endif
+
+    return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+LM_ServiceTxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    LM_UINT32 HwConIdx;
+    LM_UINT32 SwConIdx;
+
+    HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+
+    /* Get our copy of the consumer index.  The buffer descriptors */
+    /* that are in between the consumer indices are freed. */
+    SwConIdx = pDevice->SendConIdx;
+
+    /* Move the packets from the TxPacketActiveQ that are sent out to */
+    /* the TxPacketXmittedQ.  Packets that are sent use the */
+    /* descriptors that are between SwConIdx and HwConIdx. */
+    while(SwConIdx != HwConIdx)
+    {
+        /* Get the packet that was sent from the TxPacketActiveQ. */
+        pPacket = (PLM_PACKET) QQ_PopHead(
+            &pDevice->TxPacketActiveQ.Container);
+
+        /* Set the return status. */
+        pPacket->PacketStatus = LM_STATUS_SUCCESS;
+
+        /* Put the packet in the TxPacketXmittedQ for indication later. */
+        QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+        /* Move to the next packet's BD. */
+        SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) & 
+            T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+        /* Update the number of unused BDs. */
+        MM_ATOMIC_ADD(&pDevice->SendBdLeft, pPacket->u.Tx.FragCount);
+
+        /* Get the new updated HwConIdx. */
+        HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx;
+    } /* while */
+
+    /* Save the new SwConIdx. */
+    pDevice->SendConIdx = SwConIdx;
+
+} /* LM_ServiceTxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+LM_ServiceRxInterrupt(
+PLM_DEVICE_BLOCK pDevice) {
+    PLM_PACKET pPacket;
+    PT3_RCV_BD pRcvBd;
+    LM_UINT32 HwRcvRetProdIdx;
+    LM_UINT32 SwRcvRetConIdx;
+
+    /* Loop thru the receive return rings for received packets. */
+    HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+
+    SwRcvRetConIdx = pDevice->RcvRetConIdx;
+    while(SwRcvRetConIdx != HwRcvRetProdIdx)
+    {
+        pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx];
+
+        /* Get the received packet descriptor. */
+        pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+            MM_UINT_PTR(pRcvBd->Opaque));
+
+        /* Check the error flag. */
+        if(pRcvBd->ErrorFlag &&
+            pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+        {
+            pPacket->PacketStatus = LM_STATUS_FAILURE;
+
+            pDevice->RxCounters.RxPacketErrCnt++;
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC)
+            {
+                pDevice->RxCounters.RxErrCrcCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT)
+            {
+                pDevice->RxCounters.RxErrCollCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT)
+            {
+                pDevice->RxCounters.RxErrLinkLostCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR)
+            {
+                pDevice->RxCounters.RxErrPhyDecodeCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII)
+            {
+                pDevice->RxCounters.RxErrOddNibbleCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT)
+            {
+                pDevice->RxCounters.RxErrMacAbortCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64)
+            {
+                pDevice->RxCounters.RxErrShortPacketCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES)
+            {
+                pDevice->RxCounters.RxErrNoResourceCnt++;
+            }
+
+            if(pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD)
+            {
+                pDevice->RxCounters.RxErrLargePacketCnt++;
+            }
+        }
+        else
+        {
+            pPacket->PacketStatus = LM_STATUS_SUCCESS;
+            pPacket->PacketSize = pRcvBd->Len - 4;
+
+            pPacket->Flags = pRcvBd->Flags;
+            if(pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG)
+            {
+                pPacket->VlanTag = pRcvBd->VlanTag;
+            }
+
+            pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum;
+        }
+
+        /* Put the packet descriptor containing the received packet */
+        /* buffer in the RxPacketReceivedQ for indication later. */
+        QQ_PushTail(&pDevice->RxPacketReceivedQ.Container, pPacket);
+
+        /* Go to the next buffer descriptor. */
+        SwRcvRetConIdx = (SwRcvRetConIdx + 1) &
+            pDevice->RcvRetRcbEntryCountMask;
+
+        /* Get the updated HwRcvRetProdIdx. */
+        HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+    } /* while */
+
+    pDevice->RcvRetConIdx = SwRcvRetConIdx;
+
+    /* Update the receive return ring consumer index. */
+    MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx);
+    if (pDevice->FlushPostedWrites)
+    {
+        MB_REG_RD(pDevice, Mailbox.RcvRetConIdx[0].Low);
+    }
+} /* LM_ServiceRxInterrupt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This is the interrupt event handler routine. It acknowledges all        */
+/*    pending interrupts and process all pending events.                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+LM_ServiceInterrupts(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    int ServicePhyInt = FALSE;
+
+    /* Setup the phy chip whenever the link status changes. */
+    if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG)
+    {
+        Value32 = REG_RD(pDevice, MacCtrl.Status);
+        if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+        {
+            if (Value32 & MAC_STATUS_MI_INTERRUPT)
+            {
+                ServicePhyInt = TRUE;
+            }
+        }
+        else if(Value32 & MAC_STATUS_LINK_STATE_CHANGED)
+        {
+            ServicePhyInt = TRUE;
+        }
+    }
+    else
+    {
+        if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_LINK_CHANGED_STATUS)
+        {
+            pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+                (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+            ServicePhyInt = TRUE;
+        }
+    }
+#if INCLUDE_TBI_SUPPORT
+    if (pDevice->IgnoreTbiLinkChange == TRUE)
+    {
+        ServicePhyInt = FALSE;
+    }
+#endif
+    if (ServicePhyInt == TRUE)
+    {
+        MM_ACQUIRE_PHY_LOCK_IN_IRQ(pDevice);
+        LM_SetupPhy(pDevice);
+        MM_RELEASE_PHY_LOCK_IN_IRQ(pDevice);
+    }
+
+    /* Service receive and transmit interrupts. */
+    LM_ServiceRxInterrupt(pDevice);
+    LM_ServiceTxInterrupt(pDevice);
+        
+    /* No spinlock for this queue since this routine is serialized. */
+    if(!QQ_Empty(&pDevice->RxPacketReceivedQ.Container))
+    {
+        /* Indicate receive packets. */
+        MM_IndicateRxPackets(pDevice);
+//        LM_QueueRxPackets(pDevice);
+    }
+
+    /* No spinlock for this queue since this routine is serialized. */
+    if(!QQ_Empty(&pDevice->TxPacketXmittedQ.Container))
+    {
+        MM_IndicateTxPackets(pDevice);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ServiceInterrupts */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastAdd(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, increment the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1;
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+    
+    if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    pEntry = pDevice->McTable[pDevice->McEntryCount];
+
+    COPY_ETH_ADDRESS(pMcAddress, pEntry);
+    pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1;
+
+    pDevice->McEntryCount++;
+
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_MulticastAdd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastDel(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, decrement the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1;
+
+            /* No more instance left, remove the address from the table. */
+            /* Move the last entry in the table to the delete slot. */
+            if(pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 &&
+                pDevice->McEntryCount > 1)
+            {
+
+                COPY_ETH_ADDRESS(
+                    pDevice->McTable[pDevice->McEntryCount-1], pEntry);
+                pEntry[LM_MC_INSTANCE_COUNT_INDEX] =
+                    pDevice->McTable[pDevice->McEntryCount-1]
+                    [LM_MC_INSTANCE_COUNT_INDEX];
+            }
+            pDevice->McEntryCount--;
+
+            /* Update the receive mask if the table is empty. */
+            if(pDevice->McEntryCount == 0)
+            {
+                LM_SetReceiveMask(pDevice, 
+                    pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+            }
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* LM_MulticastDel */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastClear(
+PLM_DEVICE_BLOCK pDevice) {
+    pDevice->McEntryCount = 0;
+
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_MulticastClear */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetMacAddress(
+    PLM_DEVICE_BLOCK pDevice,
+    PLM_UINT8 pMacAddress)
+{
+    LM_UINT32 j;
+
+    for(j = 0; j < 4; j++)
+    {
+        REG_WR(pDevice, MacCtrl.MacAddr[j].High,
+            (pMacAddress[0] << 8) | pMacAddress[1]);
+        REG_WR(pDevice, MacCtrl.MacAddr[j].Low,
+            (pMacAddress[2] << 24) | (pMacAddress[3] << 16) |
+            (pMacAddress[4] << 8) | pMacAddress[5]);
+    }
+
+    if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705))
+    {
+        for (j = 0; j < 12; j++)
+        {
+            REG_WR(pDevice, MacCtrl.MacAddrExt[j].High,
+                (pMacAddress[0] << 8) | pMacAddress[1]);
+            REG_WR(pDevice, MacCtrl.MacAddrExt[j].Low,
+                (pMacAddress[2] << 24) | (pMacAddress[3] << 16) |
+                (pMacAddress[4] << 8) | pMacAddress[5]);
+        }
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_LINK_ACTIVE                                                   */
+/*    LM_STATUS_LINK_DOWN                                                     */
+/******************************************************************************/
+static LM_STATUS
+LM_InitBcm540xPhy(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_LINE_SPEED CurrentLineSpeed;
+    LM_DUPLEX_MODE CurrentDuplexMode;
+    LM_STATUS CurrentLinkStatus;
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x02);
+
+    if ((pDevice->ResetPhyOnLinkDown) &&
+        (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE))
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        if(!(Value32 & PHY_STATUS_LINK_PASS))
+        {
+            LM_ResetPhy(pDevice);
+        }
+    }
+    if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        if(!pDevice->InitDone)
+        {
+            Value32 = 0;
+        }
+
+        if(!(Value32 & PHY_STATUS_LINK_PASS))
+        {
+            LM_WritePhy(pDevice, BCM5401_AUX_CTRL,  0x0c20);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+                
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+                
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+                
+            LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+            LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+
+            LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+            for(j = 0; j < 1000; j++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+                if(Value32 & PHY_STATUS_LINK_PASS)
+                {
+                    MM_Wait(40);
+                    break;
+                }
+            }
+
+            if((pDevice->PhyId & PHY_ID_REV_MASK) == PHY_BCM5401_B0_REV)
+            {
+                if(!(Value32 & PHY_STATUS_LINK_PASS) &&
+                    (pDevice->OldLineSpeed == LM_LINE_SPEED_1000MBPS))
+                {
+                    LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+                    for(j = 0; j < 100; j++)
+                    {
+                        MM_Wait(10);
+
+                        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+                        if(!(Value32 & PHY_CTRL_PHY_RESET))
+                        {
+                            MM_Wait(40);
+                            break;
+                        }
+                    }
+
+                    LM_WritePhy(pDevice, BCM5401_AUX_CTRL,  0x0c20);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804);
+                        
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204);
+                        
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132);
+
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232);
+                        
+                    LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f);
+                    LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20);
+                }
+            }
+        }
+    }
+    else if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+        pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+    {
+        /* Bug: 5701 A0, B0 TX CRC workaround. */
+        LM_WritePhy(pDevice, 0x15, 0x0a75);
+        LM_WritePhy(pDevice, 0x1c, 0x8c68);
+        LM_WritePhy(pDevice, 0x1c, 0x8d68);
+        LM_WritePhy(pDevice, 0x1c, 0x8c68);
+    }
+
+    /* Acknowledge interrupts. */
+    LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+    LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32);
+
+    /* Configure the interrupt mask. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+    {
+        LM_WritePhy(pDevice, BCM540X_INT_MASK_REG, ~BCM540X_INT_LINK_CHANGE);
+    }
+
+    /* Configure PHY led mode. */
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700))
+    {
+        if(pDevice->LedMode == LED_MODE_THREE_LINK)
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 
+                BCM540X_EXT_CTRL_LINK3_LED_MODE);
+        }
+        else
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 0);
+        }
+    }
+
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Get current link and duplex mode. */
+    for(j = 0; j < 100; j++)
+    {
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+        if(Value32 & PHY_STATUS_LINK_PASS)
+        {
+            break;
+        }
+        MM_Wait(40);
+    }
+
+    if(Value32 & PHY_STATUS_LINK_PASS)
+    {
+
+        /* Determine the current line and duplex settings. */
+        LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+        for(j = 0; j < 2000; j++)
+        {
+            MM_Wait(10);
+
+            LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32);
+            if(Value32)
+            {
+                break;
+            }
+        }
+
+        switch(Value32 & BCM540X_AUX_SPEED_MASK)
+        {
+            case BCM540X_AUX_10BASET_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_10BASET_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_10MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            case BCM540X_AUX_100BASETX_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_100BASETX_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            case BCM540X_AUX_100BASET_HD:
+                CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_HALF;
+                break;
+
+            case BCM540X_AUX_100BASET_FD:
+                CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+                CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+                break;
+
+            default:
+
+                CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN;
+                CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+                break;
+        }
+
+        /* Make sure we are in auto-neg mode. */
+        for (j = 0; j < 200; j++)
+        {
+            LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+            if(Value32 && Value32 != 0x7fff)
+            {
+                break;
+            }
+
+            if(Value32 == 0 &&
+                pDevice->RequestedLineSpeed == LM_LINE_SPEED_10MBPS &&
+                pDevice->RequestedDuplexMode == LM_DUPLEX_MODE_HALF)
+            {
+                break;
+            }
+
+            MM_Wait(10);
+        }
+
+        /* Use the current line settings for "auto" mode. */
+        if(pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO)
+        {
+            if(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+
+                /* We may be exiting low power mode and the link is in */
+                /* 10mb.  In this case, we need to restart autoneg. */
+
+                if (LM_PhyAdvertiseAll(pDevice) != LM_STATUS_SUCCESS)
+                {
+                    CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+                }
+            }
+            else
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+            }
+        }
+        else
+        {
+            /* Force line settings. */
+            /* Use the current setting if it matches the user's requested */
+            /* setting. */
+            LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+            if((pDevice->LineSpeed == CurrentLineSpeed) &&
+                (pDevice->DuplexMode == CurrentDuplexMode))
+            {
+                if ((pDevice->DisableAutoNeg &&
+                    !(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)) ||
+                    (!pDevice->DisableAutoNeg &&
+                    (Value32 & PHY_CTRL_AUTO_NEG_ENABLE)))
+                {
+                    CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+                }
+                else
+                {
+                    CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+                } 
+            }
+            else
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH;
+            } 
+        }
+
+        /* Save line settings. */
+        pDevice->LineSpeed = CurrentLineSpeed;
+        pDevice->DuplexMode = CurrentDuplexMode;
+    }
+
+    return CurrentLinkStatus;
+} /* LM_InitBcm540xPhy */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetFlowControl(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd,
+    LM_UINT32 RemotePhyAd)
+{
+    LM_FLOW_CONTROL FlowCap;
+
+    /* Resolve flow control. */
+    FlowCap = LM_FLOW_CONTROL_NONE;
+
+    /* See Table 28B-3 of 802.3ab-1999 spec. */
+    if(pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE)
+    {
+        if(LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE)
+        {
+            if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+                else if(RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+            else
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+        }
+        else if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+        {
+            if((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) &&
+                (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE))
+            {
+                FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+            }
+        }
+    }
+    else
+    {
+        FlowCap = pDevice->FlowControlCap;
+    }
+
+    pDevice->FlowControl = LM_FLOW_CONTROL_NONE;
+
+    /* Enable/disable rx PAUSE. */
+    pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL;
+    if(FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+        pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL;
+
+    }
+    REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+
+    /* Enable/disable tx PAUSE. */
+    pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL;
+    if(FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+        pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL;
+
+    }
+    REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode);
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+#if INCLUDE_TBI_SUPPORT
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_InitBcm800xPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+
+    /* Reset the SERDES during init and when we have link. */
+    if(!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED)
+    {
+        /* Set PLL lock range. */
+        LM_WritePhy(pDevice, 0x16, 0x8007);
+
+        /* Software reset. */
+        LM_WritePhy(pDevice, 0x00, 0x8000);
+
+        /* Wait for reset to complete. */
+        for(j = 0; j < 500; j++)
+        {
+            MM_Wait(10);
+        }
+
+        /* Config mode; seletct PMA/Ch 1 regs. */
+        LM_WritePhy(pDevice, 0x10, 0x8411);
+
+        /* Enable auto-lock and comdet, select txclk for tx. */
+        LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+        LM_WritePhy(pDevice, 0x18, 0x00a0);
+        LM_WritePhy(pDevice, 0x16, 0x41ff);
+
+        /* Assert and deassert POR. */
+        LM_WritePhy(pDevice, 0x13, 0x0400);
+        MM_Wait(40);
+        LM_WritePhy(pDevice, 0x13, 0x0000);
+
+        LM_WritePhy(pDevice, 0x11, 0x0a50);
+        MM_Wait(40);
+        LM_WritePhy(pDevice, 0x11, 0x0a10);
+
+        /* Delay for signal to stabilize. */
+        for(j = 0; j < 15000; j++)
+        {
+            MM_Wait(10);
+        }
+
+        /* Deselect the channel register so we can read the PHY id later. */
+        LM_WritePhy(pDevice, 0x10, 0x8011);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_SetupFiberPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS CurrentLinkStatus;
+    AUTONEG_STATUS AnStatus = 0;
+    LM_UINT32 Value32;
+    LM_UINT32 Cnt;
+    LM_UINT32 j, k;
+    LM_UINT32 MacStatus, RemotePhyAd, LocalPhyAd;
+
+    if (pDevice->MacLoopBack)
+    {
+        pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE;
+        MM_IndicateStatus(pDevice, LM_STATUS_LINK_ACTIVE);
+        return LM_STATUS_SUCCESS;
+    }
+
+    pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK);
+
+    /* Initialize the send_config register. */
+    REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+    /* Enable TBI and full duplex mode. */
+    pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    /* Initialize the BCM8002 SERDES PHY. */
+    switch(pDevice->PhyId & PHY_ID_MASK)
+    {
+        case PHY_BCM8002_PHY_ID:
+            LM_InitBcm800xPhy(pDevice);
+            break;
+
+        default:
+            break;
+    }
+
+    /* Enable link change interrupt. */
+    REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+
+    /* Default to link down. */
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Get the link status. */
+    MacStatus = REG_RD(pDevice, MacCtrl.Status);
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+    {
+        LM_UINT32 SgDigCtrl, SgDigStatus;
+        LM_UINT32 ExpectedSgDigCtrl = 0;
+        LM_UINT32 WorkAround = 0;
+        LM_UINT32 PortA = 1;
+
+        if ((pDevice->ChipRevId != T3_CHIP_ID_5704_A0) &&
+            (pDevice->ChipRevId != T3_CHIP_ID_5704_A1))
+        {
+            WorkAround = 1;
+            if (REG_RD(pDevice, PciCfg.DualMacCtrl) & T3_DUAL_MAC_ID)
+            {
+                PortA = 0;
+            }
+        }
+        SgDigCtrl = REG_RD(pDevice, MacCtrl.SgDigControl);
+        if((pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) ||
+            (pDevice->DisableAutoNeg == FALSE))
+        {
+        
+            ExpectedSgDigCtrl = 0x81388400;
+            LocalPhyAd = GetPhyAdFlowCntrlSettings(pDevice);
+            if(LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE)
+            {
+                ExpectedSgDigCtrl |= BIT_11;
+            }
+            if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+            {
+                ExpectedSgDigCtrl |= BIT_12;
+            }
+            if (SgDigCtrl != ExpectedSgDigCtrl)
+            {
+                if (WorkAround)
+                {
+                    REG_WR(pDevice, MacCtrl.SerdesCfg, 0xca11330);
+                }
+                REG_WR(pDevice, MacCtrl.SgDigControl, ExpectedSgDigCtrl |
+                    BIT_30);
+		MM_Wait(5);
+                REG_WR(pDevice, MacCtrl.SgDigControl, ExpectedSgDigCtrl);
+            }
+            else if(MacStatus & MAC_STATUS_PCS_SYNCED)
+            {
+                SgDigStatus = REG_RD(pDevice, MacCtrl.SgDigStatus);
+                if (SgDigStatus & BIT_1)
+                {
+                    RemotePhyAd = 0;
+                    if(SgDigStatus & BIT_19)
+                    {
+                        RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
+                    }
+
+                    if(SgDigStatus & BIT_20)
+                    {
+                        RemotePhyAd |= PHY_LINK_PARTNER_ASYM_PAUSE;
+                    }
+
+                    LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+                    CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+                }
+                else
+                {
+                    if (WorkAround)
+                    {
+                        if (PortA)
+                        {
+                            REG_WR(pDevice, MacCtrl.SerdesCfg, 0xca10330);
+                        }
+                        else
+                        {
+                            REG_WR(pDevice, MacCtrl.SerdesCfg, 0x4a10330);
+                        }
+                    }
+                    REG_WR(pDevice, MacCtrl.SgDigControl, 0x01388400);
+                    MM_Wait(40);
+                    MacStatus = REG_RD(pDevice, MacCtrl.Status);
+                    if (MacStatus & MAC_STATUS_PCS_SYNCED)
+                    {
+                        LM_SetFlowControl(pDevice, 0, 0);
+                        CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (SgDigCtrl & BIT_31) {
+                if (WorkAround)
+                {
+                    if (PortA)
+                    {
+                        REG_WR(pDevice, MacCtrl.SerdesCfg, 0xca10330);
+                    }
+                    else
+                    {
+                        REG_WR(pDevice, MacCtrl.SerdesCfg, 0x4a10330);
+                    }
+                }
+                REG_WR(pDevice, MacCtrl.SgDigControl, 0x01388400);
+            }
+            if(MacStatus & MAC_STATUS_PCS_SYNCED)
+            {
+                LM_SetFlowControl(pDevice, 0, 0);
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            }
+        }
+    }
+    else if(MacStatus & MAC_STATUS_PCS_SYNCED)
+    {
+        if((pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) ||
+            (pDevice->DisableAutoNeg == FALSE))
+        {
+            /* auto-negotiation mode. */
+            /* Initialize the autoneg default capaiblities. */
+            AutonegInit(&pDevice->AnInfo);
+
+            /* Set the context pointer to point to the main device structure. */
+            pDevice->AnInfo.pContext = pDevice;
+
+            /* Setup flow control advertisement register. */
+            Value32 = GetPhyAdFlowCntrlSettings(pDevice);
+            if(Value32 & PHY_AN_AD_PAUSE_CAPABLE)
+            {
+                pDevice->AnInfo.mr_adv_sym_pause = 1;
+            }
+            else
+            {
+                pDevice->AnInfo.mr_adv_sym_pause = 0;
+            }
+
+            if(Value32 & PHY_AN_AD_ASYM_PAUSE)
+            {
+                pDevice->AnInfo.mr_adv_asym_pause = 1;
+            }
+            else
+            {
+                pDevice->AnInfo.mr_adv_asym_pause = 0;
+            }
+
+            /* Try to autoneg up to six times. */
+            if (pDevice->IgnoreTbiLinkChange)
+            {
+                Cnt = 1;
+            }
+            else
+            {
+                Cnt = 6;
+            }
+            for (j = 0; j < Cnt; j++)
+            {
+                REG_WR(pDevice, MacCtrl.TxAutoNeg, 0);
+
+                Value32 = pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK;
+                REG_WR(pDevice, MacCtrl.Mode, Value32);
+                MM_Wait(20);
+
+                REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                    MAC_MODE_SEND_CONFIGS);
+
+                MM_Wait(20);
+
+                pDevice->AnInfo.State = AN_STATE_UNKNOWN;
+                pDevice->AnInfo.CurrentTime_us = 0;
+
+                REG_WR(pDevice, Grc.Timer, 0);
+                for(k = 0; (pDevice->AnInfo.CurrentTime_us < 75000) &&
+                    (k < 75000); k++)
+                {
+                    AnStatus = Autoneg8023z(&pDevice->AnInfo);
+
+                    if((AnStatus == AUTONEG_STATUS_DONE) || 
+                        (AnStatus == AUTONEG_STATUS_FAILED))
+                    {
+                        break;
+                    }
+
+                    pDevice->AnInfo.CurrentTime_us = REG_RD(pDevice, Grc.Timer);
+                
+                }
+                if((AnStatus == AUTONEG_STATUS_DONE) || 
+                    (AnStatus == AUTONEG_STATUS_FAILED))
+                {
+                    break;
+                }
+                if (j >= 1)
+                {
+                    if (!(REG_RD(pDevice, MacCtrl.Status) &
+                        MAC_STATUS_PCS_SYNCED)) {
+                        break;
+                    }
+                }
+            }
+
+            /* Stop sending configs. */
+            MM_AnTxIdle(&pDevice->AnInfo);
+
+            /* Resolve flow control settings. */
+            if((AnStatus == AUTONEG_STATUS_DONE) &&
+                pDevice->AnInfo.mr_an_complete && pDevice->AnInfo.mr_link_ok &&
+                pDevice->AnInfo.mr_lp_adv_full_duplex)
+                {
+                LM_UINT32 RemotePhyAd;
+                LM_UINT32 LocalPhyAd;
+
+                LocalPhyAd = 0;
+                if(pDevice->AnInfo.mr_adv_sym_pause)
+                {
+                    LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE;
+                }
+
+                if(pDevice->AnInfo.mr_adv_asym_pause)
+                {
+                    LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE;
+                }
+
+                RemotePhyAd = 0;
+                if(pDevice->AnInfo.mr_lp_adv_sym_pause)
+                {
+                    RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
+                }
+
+                if(pDevice->AnInfo.mr_lp_adv_asym_pause)
+                {
+                    RemotePhyAd |= PHY_LINK_PARTNER_ASYM_PAUSE;
+                }
+
+                LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            }
+            else
+            {
+                LM_SetFlowControl(pDevice, 0, 0);
+            }
+            for (j = 0; j < 30; j++)
+            {
+                MM_Wait(20);
+                REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+                    MAC_STATUS_CFG_CHANGED);
+                MM_Wait(20);
+                if ((REG_RD(pDevice, MacCtrl.Status) &
+                    (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+                    break;
+            }
+            if (pDevice->PollTbiLink)
+            {
+                Value32 = REG_RD(pDevice, MacCtrl.Status);
+                if (Value32 & MAC_STATUS_RECEIVING_CFG)
+                {
+                    pDevice->IgnoreTbiLinkChange = TRUE;
+                }
+                else
+                {
+                    pDevice->IgnoreTbiLinkChange = FALSE;
+                }
+            }
+            Value32 = REG_RD(pDevice, MacCtrl.Status);
+            if (CurrentLinkStatus == LM_STATUS_LINK_DOWN &&
+                 (Value32 & MAC_STATUS_PCS_SYNCED) &&
+                 ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0))
+            {
+                CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            }
+        }
+        else
+        {
+            /* We are forcing line speed. */
+            pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+            LM_SetFlowControl(pDevice, 0, 0);
+
+            CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                MAC_MODE_SEND_CONFIGS);
+        }
+    }
+    /* Set the link polarity bit. */
+    pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+        (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+
+    for (j = 0; j < 100; j++)
+    {
+        REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+            MAC_STATUS_CFG_CHANGED);
+        MM_Wait(5);
+        if ((REG_RD(pDevice, MacCtrl.Status) &
+            (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+            break;
+    }
+
+    Value32 = REG_RD(pDevice, MacCtrl.Status);
+    if((Value32 & MAC_STATUS_PCS_SYNCED) == 0)
+    {
+        CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+        if (pDevice->DisableAutoNeg == FALSE)
+        {
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                MAC_MODE_SEND_CONFIGS);
+            MM_Wait(1);
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+        }
+    }
+
+    /* Initialize the current link status. */
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS;
+        pDevice->DuplexMode = LM_DUPLEX_MODE_FULL;
+        REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+            LED_CTRL_1000MBPS_LED_ON);
+    }
+    else
+    {
+        pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN;
+        pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+        REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+            LED_CTRL_OVERRIDE_TRAFFIC_LED);
+    }
+
+    /* Indicate link status. */
+    if (pDevice->LinkStatus != CurrentLinkStatus) {
+        pDevice->LinkStatus = CurrentLinkStatus;
+        MM_IndicateStatus(pDevice, CurrentLinkStatus);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+#endif /* INCLUDE_TBI_SUPPORT */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetupCopperPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS CurrentLinkStatus;
+    LM_UINT32 Value32;
+
+    /* Assume there is not link first. */
+    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Disable phy link change attention. */
+    REG_WR(pDevice, MacCtrl.MacEvent, 0);
+
+    /* Clear link change attention. */
+    REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+        MAC_STATUS_CFG_CHANGED | MAC_STATUS_MI_COMPLETION |
+        MAC_STATUS_LINK_STATE_CHANGED);
+
+    /* Disable auto-polling for the moment. */
+    pDevice->MiMode = 0xc0000;
+    REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    MM_Wait(40);
+
+    /* Determine the requested line speed and duplex. */
+    pDevice->OldLineSpeed = pDevice->LineSpeed;
+    pDevice->LineSpeed = pDevice->RequestedLineSpeed;
+    pDevice->DuplexMode = pDevice->RequestedDuplexMode;
+
+    /* Set the phy to loopback mode. */
+    if(pDevice->PhyLoopBack || pDevice->MacLoopBack)
+    {
+        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+        if(!(Value32 & PHY_CTRL_LOOPBACK_MODE) && pDevice->PhyLoopBack)
+        {
+            /* Disable link change and PHY interrupts. */
+            REG_WR(pDevice, MacCtrl.MacEvent, 0);
+
+            /* Clear link change attention. */
+            REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+                MAC_STATUS_CFG_CHANGED);
+
+            LM_WritePhy(pDevice, PHY_CTRL_REG, 0x4140);
+            MM_Wait(40);
+
+            pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 ||
+                T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703 ||
+                T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704 ||
+                T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705 ||
+                (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 &&
+                (pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID))
+            {
+                pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+            }
+
+            /* Prevent the interrupt handling from being called. */
+            pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+                (pDevice->pStatusBlkVirt->Status &
+                ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+
+            /* GMII interface. */
+            pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK;
+            pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+            MM_Wait(40);
+
+            /* Configure PHY led mode. */
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 ||
+                (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700))
+            {
+                LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 
+                    BCM540X_EXT_CTRL_LINK3_LED_MODE);
+                MM_Wait(40);
+            }
+
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+            {
+                int j = 0;
+
+                while (REG_RD(pDevice, DmaWrite.Mode) & DMA_WRITE_MODE_ENABLE)
+                {
+                    MM_Wait(40);
+                    j++;
+                    if (j > 20)
+                        break;
+                }
+
+                Value32 = DMA_WRITE_MODE_ENABLE |
+                    DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE |
+                    DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE |
+                    DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE |
+                    DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE |
+                    DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE |
+                    DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE |
+                    DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE |
+                    DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE;
+                REG_WR(pDevice, DmaWrite.Mode, Value32);
+            }
+        }
+
+        pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE;
+        MM_IndicateStatus(pDevice, LM_STATUS_LINK_ACTIVE);
+
+        return LM_STATUS_SUCCESS;
+    }
+
+    LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+    if(Value32 & PHY_CTRL_LOOPBACK_MODE)
+    {
+        CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+
+        /* Re-enable link change interrupt.  This was disabled when we */
+        /* enter loopback mode. */
+        if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+        {
+            REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_MI_INTERRUPT);
+        }
+        else
+        {
+            REG_WR(pDevice, MacCtrl.MacEvent, 
+                MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+        }
+    }
+    else
+    {
+        /* Initialize the phy chip. */
+        CurrentLinkStatus = LM_InitBcm540xPhy(pDevice);
+    }
+
+    if(CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH)
+    {
+        CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+    }
+    
+    /* Setup flow control. */
+    pDevice->FlowControl = LM_FLOW_CONTROL_NONE;
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        LM_FLOW_CONTROL FlowCap;     /* Flow control capability. */
+
+        FlowCap = LM_FLOW_CONTROL_NONE;
+
+        if(pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+        {
+            if(pDevice->DisableAutoNeg == FALSE ||
+                pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO)
+            {
+                LM_UINT32 ExpectedPhyAd;
+                LM_UINT32 LocalPhyAd;
+                LM_UINT32 RemotePhyAd;
+
+                LM_ReadPhy(pDevice, PHY_AN_AD_REG, &LocalPhyAd);
+		pDevice->advertising = LocalPhyAd;
+                LocalPhyAd &= (PHY_AN_AD_ASYM_PAUSE | PHY_AN_AD_PAUSE_CAPABLE);
+
+                ExpectedPhyAd = GetPhyAdFlowCntrlSettings(pDevice);
+
+                if(LocalPhyAd != ExpectedPhyAd)
+                {
+                    CurrentLinkStatus = LM_STATUS_LINK_DOWN;
+                }
+                else
+                {
+                    LM_ReadPhy(pDevice, PHY_LINK_PARTNER_ABILITY_REG,
+                        &RemotePhyAd);
+
+                    LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd);
+                }
+            }
+            else
+            {
+                pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+                LM_SetFlowControl(pDevice, 0, 0);
+            }
+        }
+    }
+
+    if(CurrentLinkStatus == LM_STATUS_LINK_DOWN)
+    {
+        LM_ForceAutoNeg(pDevice);
+
+        /* If we force line speed, we make get link right away. */
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+        if(Value32 & PHY_STATUS_LINK_PASS)
+        {
+            CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+        }
+    }
+
+    /* GMII interface. */
+    pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK;
+    if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+    {
+        if(pDevice->LineSpeed == LM_LINE_SPEED_100MBPS ||
+            pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+        {
+            pDevice->MacMode |= MAC_MODE_PORT_MODE_MII;
+        }
+        else
+        {
+            pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+        }
+    }
+    else {
+        pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+    }
+
+    /* Set the MAC to operate in the appropriate duplex mode. */
+    pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX;
+    if(pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)
+    {
+        pDevice->MacMode |= MAC_MODE_HALF_DUPLEX;
+    }
+
+    /* Set the link polarity bit. */
+    pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY;
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+    {
+        if((pDevice->LedMode == LED_MODE_LINK10) ||
+             (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE &&
+             pDevice->LineSpeed == LM_LINE_SPEED_10MBPS))
+        {
+            pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+        }
+    }
+    else
+    {
+        if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE)
+        {
+            pDevice->MacMode |= MAC_MODE_LINK_POLARITY;
+        }
+
+        /* Set LED mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+        else
+        {
+            if(pDevice->LedMode == LED_MODE_OUTPUT)
+            {
+                Value32 = LED_CTRL_PHY_MODE_2;
+            }
+            else
+            {
+                Value32 = LED_CTRL_PHY_MODE_1;
+            }
+        }
+        REG_WR(pDevice, MacCtrl.LedCtrl, Value32);
+    }
+
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+
+    /* Enable auto polling. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE;
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+    }
+
+    /* Enable phy link change attention. */
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT)
+    {
+        REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_MI_INTERRUPT);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.MacEvent, 
+            MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+    }
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) &&
+        (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) &&
+        (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+        (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) &&
+          (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) ||
+         !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)))
+    {
+        MM_Wait(120);
+        REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+            MAC_STATUS_CFG_CHANGED);
+        MEM_WR_OFFSET(pDevice, T3_FIRMWARE_MAILBOX,
+            T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE);
+    }
+
+    /* Indicate link status. */
+    if (pDevice->LinkStatus != CurrentLinkStatus) {
+        pDevice->LinkStatus = CurrentLinkStatus;
+        MM_IndicateStatus(pDevice, CurrentLinkStatus);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetupCopperPhy */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetupPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS LmStatus;
+    LM_UINT32 Value32;
+
+#if INCLUDE_TBI_SUPPORT
+    if(pDevice->EnableTbi)
+    {
+        LmStatus = LM_SetupFiberPhy(pDevice);
+    }
+    else
+#endif /* INCLUDE_TBI_SUPPORT */
+    {
+        LmStatus = LM_SetupCopperPhy(pDevice);
+    }
+    if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))
+        {
+            Value32 = REG_RD(pDevice, PciCfg.PciState);
+            REG_WR(pDevice, PciCfg.PciState,
+                Value32 | T3_PCI_STATE_RETRY_SAME_DMA);
+        }
+    }
+    if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) &&
+        (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF))
+    {
+        REG_WR(pDevice, MacCtrl.TxLengths, 0x26ff);
+    }
+    else
+    {
+        REG_WR(pDevice, MacCtrl.TxLengths, 0x2620);
+    }
+    if (pDevice->LinkStatus == LM_STATUS_LINK_DOWN)
+    {
+        REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks, 0);
+    }
+    else
+    {
+        REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks,
+            pDevice->StatsCoalescingTicks);
+    }
+
+    return LmStatus;
+}
+
+STATIC LM_VOID
+LM_ResetPhy(LM_DEVICE_BLOCK *pDevice)
+{
+    int j;
+    LM_UINT32 miireg;
+
+    LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+
+    for(j = 0; j < 100; j++)
+    {
+        MM_Wait(10);
+
+        LM_ReadPhy(pDevice, PHY_CTRL_REG, &miireg);
+        if(miireg && !(miireg & PHY_CTRL_PHY_RESET))
+        {
+            MM_Wait(40);
+            break;
+        }
+    }
+    LM_SetEthWireSpeed(pDevice);
+}
+
+STATIC LM_VOID
+LM_SetEthWireSpeed(LM_DEVICE_BLOCK *pDevice)
+{
+    LM_UINT32 Value32;
+
+    /* Enable Ethernet@WireSpeed. */
+    if (pDevice->EnableWireSpeed &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700))
+    {
+        LM_WritePhy(pDevice, 0x18, 0x7007);
+        LM_ReadPhy(pDevice, 0x18, &Value32);
+        LM_WritePhy(pDevice, 0x18, Value32 | BIT_15 | BIT_4);
+    }
+}
+
+STATIC LM_STATUS
+LM_PhyAdvertiseAll(LM_DEVICE_BLOCK *pDevice)
+{
+    LM_UINT32 miireg;
+
+    LM_ReadPhy(pDevice, PHY_AN_AD_REG, &miireg);
+    pDevice->advertising = miireg;
+    if ((miireg & PHY_AN_AD_ALL_SPEEDS) != PHY_AN_AD_ALL_SPEEDS)
+    {
+        return LM_STATUS_FAILURE;
+    }
+    if(!pDevice->No1000)
+    {
+        LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG, &miireg);
+        pDevice->advertising1000 = miireg;
+        if ((miireg & BCM540X_AN_AD_ALL_1G_SPEEDS) !=
+            BCM540X_AN_AD_ALL_1G_SPEEDS)
+        {
+            return LM_STATUS_FAILURE;
+        }
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_ReadPhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+PLM_UINT32 pData32) {
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+            ~MI_MODE_AUTO_POLLING_ENABLE);
+        MM_Wait(40);
+    }
+
+    Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+        ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+        MI_COM_CMD_READ | MI_COM_START;
+
+    REG_WR(pDevice, MacCtrl.MiCom, Value32);
+    
+    for(j = 0; j < 20; j++)
+    {
+        MM_Wait(25);
+
+        Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+        if(!(Value32 & MI_COM_BUSY))
+        {
+            MM_Wait(5);
+            Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+            Value32 &= MI_COM_PHY_DATA_MASK;
+            break;
+        }
+    }
+
+    if(Value32 & MI_COM_BUSY)
+    {
+        Value32 = 0;
+    }
+
+    *pData32 = Value32;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+        MM_Wait(40);
+    }
+} /* LM_ReadPhy */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_WritePhy(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 PhyReg,
+LM_UINT32 Data32) {
+    LM_UINT32 Value32;
+    LM_UINT32 j;
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode &
+            ~MI_MODE_AUTO_POLLING_ENABLE);
+        MM_Wait(40);
+    }
+
+    Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) |
+        ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) |
+        (Data32 & MI_COM_PHY_DATA_MASK) | MI_COM_CMD_WRITE | MI_COM_START;
+
+    REG_WR(pDevice, MacCtrl.MiCom, Value32);
+    
+    for(j = 0; j < 20; j++)
+    {
+        MM_Wait(25);
+
+        Value32 = REG_RD(pDevice, MacCtrl.MiCom);
+
+        if(!(Value32 & MI_COM_BUSY))
+        {
+            MM_Wait(5);
+            break;
+        }
+    }
+
+    if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING)
+    {
+        REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode);
+        MM_Wait(40);
+    }
+} /* LM_WritePhy */
+
+LM_STATUS
+LM_EnableMacLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->MacLoopBack = TRUE;
+    pDevice->PhyLoopBack = FALSE;
+    pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK;
+    pDevice->MacMode |= MAC_MODE_PORT_INTERNAL_LOOPBACK |
+        MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_DisableMacLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->MacLoopBack = FALSE;
+    pDevice->MacMode &= ~(MAC_MODE_PORT_INTERNAL_LOOPBACK |
+        MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_MASK);
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_EnablePhyLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->PhyLoopBack = TRUE;
+    pDevice->MacLoopBack = FALSE;
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_DisablePhyLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->PhyLoopBack = FALSE;
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetPowerState(
+PLM_DEVICE_BLOCK pDevice,
+LM_POWER_STATE PowerLevel)
+{
+#ifdef BCM_WOL
+    LM_UINT32 PmeSupport;
+    LM_UINT32 Value32;
+    PLM_DEVICE_BLOCK pDevice2 = 0;
+    int j;
+#endif
+    LM_UINT32 PmCtrl;
+
+    /* make sureindirect accesses are enabled*/
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+
+    /* Clear the PME_ASSERT bit and the power state bits.  Also enable */
+    /* the PME bit. */
+    MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &PmCtrl);
+
+    PmCtrl |= T3_PM_PME_ASSERTED;
+    PmCtrl &= ~T3_PM_POWER_STATE_MASK;
+
+    /* Set the appropriate power state. */
+    if(PowerLevel == LM_POWER_STATE_D0)
+    {
+
+        /* Bring the card out of low power mode. */
+        PmCtrl |= T3_PM_POWER_STATE_D0;
+        MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+	MM_Wait(40);	/* Required delay is about 20us. */
+
+        pDevice->PowerLevel = PowerLevel;
+        return LM_STATUS_SUCCESS;
+    }
+#ifdef BCM_WOL
+    else if(PowerLevel == LM_POWER_STATE_D1)
+    {
+        PmCtrl |= T3_PM_POWER_STATE_D1;
+    }
+    else if(PowerLevel == LM_POWER_STATE_D2)
+    {
+        PmCtrl |= T3_PM_POWER_STATE_D2;
+    }
+    else if(PowerLevel == LM_POWER_STATE_D3)
+    {
+        PmCtrl |= T3_PM_POWER_STATE_D3;
+    }
+    else
+    {
+        return LM_STATUS_FAILURE;
+    }
+    PmCtrl |= T3_PM_PME_ENABLE;
+
+    /* Mask out all interrupts so LM_SetupPhy won't be called while we are */
+    /* setting new line speed. */
+    Value32 = REG_RD(pDevice, PciCfg.MiscHostCtrl);
+    REG_WR(pDevice, PciCfg.MiscHostCtrl, Value32 | MISC_HOST_CTRL_MASK_PCI_INT);
+
+    if(!pDevice->RestoreOnWakeUp)
+    {
+        pDevice->RestoreOnWakeUp = TRUE;
+        pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg;
+        pDevice->WakeUpRequestedLineSpeed = pDevice->RequestedLineSpeed;
+        pDevice->WakeUpRequestedDuplexMode = pDevice->RequestedDuplexMode;
+    }
+
+    /* Force auto-negotiation to 10 line speed. */
+    pDevice->DisableAutoNeg = FALSE;
+
+    if (!pDevice->EnableTbi)
+    {
+        pDevice->RequestedLineSpeed = LM_LINE_SPEED_10MBPS;
+        LM_SetupPhy(pDevice);
+    }
+
+    /* Put the driver in the initial state, and go through the power down */
+    /* sequence. */
+    LM_Halt(pDevice);
+
+    for(j = 0; j < 20000; j++)
+    {
+        MM_Wait(10);
+
+        Value32 = MEM_RD_OFFSET(pDevice, T3_ASF_FW_STATUS_MAILBOX);
+        if(Value32 == ~T3_MAGIC_NUM_FIRMWARE_INIT_DONE)
+        {
+            break;
+        }
+    }
+
+    MEM_WR_OFFSET(pDevice, DRV_WOL_MAILBOX, DRV_WOL_SIGNATURE |
+        DRV_DOWN_STATE_SHUTDOWN | 0x2 | DRV_WOL_SET_MAGIC_PKT);
+
+    MM_ReadConfig32(pDevice, T3_PCI_PM_CAP_REG, &PmeSupport);
+
+    if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)
+    {
+
+        /* Enable WOL. */
+        if (!pDevice->EnableTbi)
+        {
+            LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x5a);
+            MM_Wait(40);
+        }
+
+        /* Set LED mode. */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = LED_CTRL_PHY_MODE_1;
+        }
+        else
+        {
+            if(pDevice->LedMode == LED_MODE_OUTPUT)
+            {
+                Value32 = LED_CTRL_PHY_MODE_2;
+            }
+            else
+            {
+                Value32 = LED_CTRL_PHY_MODE_1;
+            }
+        }
+
+        if (pDevice->EnableTbi)
+        {
+            Value32 = MAC_MODE_PORT_MODE_TBI;
+        }
+        else
+        {
+            Value32 = MAC_MODE_PORT_MODE_MII;
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)
+            {
+                if(pDevice->LedMode == LED_MODE_LINK10 ||
+                    pDevice->WolSpeed == WOL_SPEED_10MB)
+                {
+                    Value32 |= MAC_MODE_LINK_POLARITY;
+                }
+            }
+            else
+            {
+                Value32 |= MAC_MODE_LINK_POLARITY;
+            }
+        }
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+        MM_Wait(40); MM_Wait(40); MM_Wait(40);
+
+        /* Always enable magic packet wake-up if we have vaux. */
+        if((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) && 
+            (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET))
+        {
+            Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE;
+        }
+
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+
+        /* Enable the receiver. */
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_ENABLE);
+    }
+    else if (!pDevice->EnableTbi)
+    {
+        LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG,
+            BCM540X_EXT_CTRL_FORCE_LED_OFF);
+        LM_WritePhy(pDevice, 0x18, 0x01b2);
+        if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+            (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5704) &&
+            (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705))
+        {
+            LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_LOWER_POWER_MODE);
+        }
+    }
+
+    /* Disable tx/rx clocks, and select an alternate clock. */
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) ||
+        ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) &&
+        (pDevice->WolSpeed == WOL_SPEED_10MB)))
+    {
+        Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+            T3_PCI_SELECT_ALTERNATE_CLOCK |
+            T3_PCI_POWER_DOWN_PCI_PLL133;
+
+        REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl | Value32);
+    }
+    else
+    {
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+                T3_PCI_SELECT_ALTERNATE_CLOCK;
+        }
+        else if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+        {
+            Value32 = T3_PCI_625_CORE_CLOCK;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK;
+        }
+        REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl | Value32);
+
+        MM_Wait(40);
+
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+                T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_44MHZ_CORE_CLOCK;
+        }
+        else if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_625_CORE_CLOCK;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_44MHZ_CORE_CLOCK;
+        }
+
+        REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl | Value32);
+
+        if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+        {
+            MM_Wait(40);
+
+            if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+                T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+            {
+                Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK |
+                    T3_PCI_44MHZ_CORE_CLOCK;
+            }
+            else
+            {
+                Value32 = T3_PCI_44MHZ_CORE_CLOCK;
+            }
+
+            REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl | Value32);
+        }
+    }
+
+    MM_Wait(40);
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+    {
+        pDevice2 = MM_FindPeerDev(pDevice);
+    }
+    if(!pDevice->EepromWp)
+    {
+        LM_SwitchVaux(pDevice, pDevice2);
+    }
+
+    /* Set the phy to low power mode. */
+    /* Put the the hardware in low power mode. */
+    MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+    pDevice->PowerLevel = PowerLevel;
+#endif
+    return LM_STATUS_SUCCESS;
+} /* LM_SetPowerState */
+
+
+LM_VOID
+LM_SwitchVaux(PLM_DEVICE_BLOCK pDevice, PLM_DEVICE_BLOCK pDevice2)
+{
+    /* Switch adapter to auxilliary power if WOL enabled */
+    if ((pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) ||
+        (pDevice2 && (pDevice2->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)))
+    {
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+        {
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+            MM_Wait(40);
+        }
+        else
+        {
+            if (pDevice2 && pDevice2->InitDone)
+            {
+                return;
+            }
+
+            /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+            MM_Wait(40);
+
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2);
+            MM_Wait(40);
+
+            /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE0 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE2 | 
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+            MM_Wait(40);
+        }
+    }
+    else /* WOL disabled */
+    {
+        if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+            (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701))
+        {
+            if (pDevice2 && pDevice2->InitDone)
+            {
+                return;
+            }
+
+            /* GPIO1 = 1 */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+            MM_Wait(40);
+
+            /* GPIO1 = 0 */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+            MM_Wait(40);
+
+            /* GPIO1 = 1 */
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+            MM_Wait(40);
+        }
+    }
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+static LM_UINT32
+GetPhyAdFlowCntrlSettings(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+
+    Value32 = 0;
+
+    /* Auto negotiation flow control only when autonegotiation is enabled. */
+    if(pDevice->DisableAutoNeg == FALSE ||
+        pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO)
+    {
+        /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */
+        if((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) ||
+            ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
+            (pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_ASYM_PAUSE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
+        }
+    }
+
+    return Value32;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_FAILURE                                                       */
+/*    LM_STATUS_SUCCESS                                                       */
+/*                                                                            */
+/******************************************************************************/
+static LM_STATUS
+LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice) 
+{
+    LM_LINE_SPEED LineSpeed;
+    LM_DUPLEX_MODE DuplexMode;
+    LM_UINT32 NewPhyCtrl;
+    LM_UINT32 Value32;
+    LM_UINT32 Cnt;
+
+    /* Get the interface type, line speed, and duplex mode. */
+    LineSpeed = pDevice->RequestedLineSpeed;
+    DuplexMode = pDevice->RequestedDuplexMode;
+
+#ifdef BCM_WOL
+    if (pDevice->RestoreOnWakeUp)
+    {
+        LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+        pDevice->advertising1000 = 0;
+        Value32 = PHY_AN_AD_10BASET_FULL | PHY_AN_AD_10BASET_HALF;
+        if (pDevice->WolSpeed == WOL_SPEED_100MB)
+        {
+            Value32 |= PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF;
+        }
+        Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+        Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+        LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+        pDevice->advertising = Value32;
+    }
+    /* Setup the auto-negotiation advertisement register. */
+    else if(LineSpeed == LM_LINE_SPEED_UNKNOWN)
+#else
+    /* Setup the auto-negotiation advertisement register. */
+    if(LineSpeed == LM_LINE_SPEED_UNKNOWN)
+#endif
+    {
+        /* Setup the 10/100 Mbps auto-negotiation advertisement register. */
+        Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | PHY_AN_AD_ALL_SPEEDS;
+        Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+        LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+        pDevice->advertising = Value32;
+
+        /* Advertise 1000Mbps */
+        if (!pDevice->No1000)
+        {
+            Value32 = BCM540X_AN_AD_ALL_1G_SPEEDS;
+
+#if INCLUDE_5701_AX_FIX
+            /* Bug: workaround for CRC error in gigabit mode when we are in */
+            /* slave mode.  This will force the PHY to operate in */
+            /* master mode. */
+            if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+                pDevice->ChipRevId == T3_CHIP_ID_5701_B0)
+            {
+                Value32 |= BCM540X_CONFIG_AS_MASTER |
+                    BCM540X_ENABLE_CONFIG_AS_MASTER;
+            }
+#endif
+
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+            pDevice->advertising1000 = Value32;
+        }
+    }
+    else
+    {
+        if(pDevice->No1000 && (LineSpeed == LM_LINE_SPEED_1000MBPS))
+        {
+            LineSpeed = LM_LINE_SPEED_100MBPS;
+        }
+        if(LineSpeed == LM_LINE_SPEED_1000MBPS)
+        {
+            Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = BCM540X_AN_AD_1000BASET_HALF;
+            }
+            else
+            {
+                Value32 = BCM540X_AN_AD_1000BASET_FULL;
+            }
+
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+            pDevice->advertising1000 = Value32;
+        }
+        else if(LineSpeed == LM_LINE_SPEED_100MBPS)
+        {
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+            pDevice->advertising1000 = 0;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = PHY_AN_AD_100BASETX_HALF;
+            }
+            else
+            {
+                Value32 = PHY_AN_AD_100BASETX_FULL;
+            }
+
+            Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+        }
+        else if(LineSpeed == LM_LINE_SPEED_10MBPS)
+        {
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+            pDevice->advertising1000 = 0;
+
+            if(DuplexMode != LM_DUPLEX_MODE_FULL)
+            {
+                Value32 = PHY_AN_AD_10BASET_HALF;
+            }
+            else
+            {
+                Value32 = PHY_AN_AD_10BASET_FULL;
+            }
+
+            Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+            Value32 |= GetPhyAdFlowCntrlSettings(pDevice);
+
+            LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32);
+            pDevice->advertising = Value32;
+        }
+    }
+
+    /* Force line speed if auto-negotiation is disabled. */
+    if(pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN)
+    {
+        /* This code path is executed only when there is link. */
+        pDevice->LineSpeed = LineSpeed;
+        pDevice->DuplexMode = DuplexMode;
+
+        /* Force line seepd. */
+        NewPhyCtrl = 0;
+        switch(LineSpeed)
+        {
+            case LM_LINE_SPEED_10MBPS:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_10MBPS;
+                break;
+            case LM_LINE_SPEED_100MBPS:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_100MBPS;
+                break;
+            case LM_LINE_SPEED_1000MBPS:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS;
+                break;
+            default:
+                NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS;
+                break;
+        }
+
+        if(DuplexMode == LM_DUPLEX_MODE_FULL)
+        {
+            NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE;
+        }
+
+        /* Don't do anything if the PHY_CTRL is already what we wanted. */
+        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+        if(Value32 != NewPhyCtrl)
+        {
+            /* Temporary bring the link down before forcing line speed. */
+            LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_LOOPBACK_MODE);
+            
+            /* Wait for link to go down. */
+            for(Cnt = 0; Cnt < 1500; Cnt++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+                LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32);
+
+                if(!(Value32 & PHY_STATUS_LINK_PASS))
+                {
+                    MM_Wait(40);
+                    break;
+                }
+            }
+
+            LM_WritePhy(pDevice, PHY_CTRL_REG, NewPhyCtrl);
+            MM_Wait(40);
+        }
+    }
+    else
+    {
+        LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+            PHY_CTRL_RESTART_AUTO_NEG);
+    }
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ForceAutoNegBcm540xPhy */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice,
+                          PT3_FWIMG_INFO pFwImg,
+                          LM_UINT32 LoadCpu,
+                          LM_UINT32 StartCpu)
+{
+    LM_UINT32 i;
+    LM_UINT32 address;
+    LM_VOID (*Wr_fn)(PLM_DEVICE_BLOCK pDevice,LM_UINT32 Register,LM_UINT32 Value32);
+    LM_UINT32 (*Rd_fn)(PLM_DEVICE_BLOCK pDevice,LM_UINT32 Register);
+    LM_UINT32 len;
+    LM_UINT32 base_addr;
+
+#if INCLUDE_TCP_SEG_SUPPORT
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+      {
+	Wr_fn = LM_MemWrInd;
+	Rd_fn = LM_MemRdInd;
+	len = LM_GetStkOffLdFirmwareSize(pDevice);
+	base_addr = T3_NIC_BCM5705_MBUF_POOL_ADDR;
+      }
+    else
+#endif
+      {
+	Wr_fn = LM_RegWrInd;
+	Rd_fn = LM_RegRdInd;
+	len = T3_RX_CPU_SPAD_SIZE;
+	base_addr = T3_RX_CPU_SPAD_ADDR;
+      }
+
+    if (LoadCpu & T3_RX_CPU_ID)
+    {
+        if (LM_HaltCpu(pDevice,T3_RX_CPU_ID) != LM_STATUS_SUCCESS)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* First of all clear scrach pad memory */
+        for (i = 0; i < len; i+=4)
+        { 
+	    Wr_fn(pDevice,base_addr+i,0);
+        }
+
+        /* Copy code first */
+        address = base_addr + (pFwImg->Text.Offset & 0xffff);
+        for (i = 0; i <= pFwImg->Text.Length; i+=4)
+        {
+            Wr_fn(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]);
+        }
+
+        address = base_addr + (pFwImg->ROnlyData.Offset & 0xffff);
+        for (i = 0; i <= pFwImg->ROnlyData.Length; i+=4)
+        {
+            Wr_fn(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]);
+        }
+
+        address = base_addr + (pFwImg->Data.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->Data.Length; i+=4)
+        {
+            Wr_fn(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+        }
+    }
+
+    if ((LoadCpu & T3_TX_CPU_ID) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705))
+    {
+        if (LM_HaltCpu(pDevice,T3_TX_CPU_ID) != LM_STATUS_SUCCESS)
+        {
+            return LM_STATUS_FAILURE;
+        }
+
+        /* First of all clear scrach pad memory */
+        for (i = 0; i < T3_TX_CPU_SPAD_SIZE; i+=4)
+        { 
+            Wr_fn(pDevice,T3_TX_CPU_SPAD_ADDR+i,0);
+        }
+
+        /* Copy code first */
+        address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->Text.Length; i+=4)
+        {
+            Wr_fn(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]);
+        }
+
+        address = T3_TX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->ROnlyData.Length; i+=4)
+        {
+            Wr_fn(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]);
+        }
+
+        address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff);
+        for (i= 0; i <= pFwImg->Data.Length; i+=4)
+        {
+            Wr_fn(pDevice,address+i,
+                        ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]);
+        }
+    }
+
+    if (StartCpu & T3_RX_CPU_ID)
+    {
+        /* Start Rx CPU */
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+        for (i = 0 ; i < 5; i++)
+        {
+          if (pFwImg->StartAddress == REG_RD(pDevice,rxCpu.reg.PC))
+             break;
+
+          REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+          REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+          REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress);
+          MM_Wait(1000);
+        }
+
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.mode, 0);
+    }
+
+    if ((StartCpu & T3_TX_CPU_ID) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705))
+    {
+        /* Start Tx CPU */
+        REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+        for (i = 0 ; i < 5; i++)
+        {
+          if (pFwImg->StartAddress == REG_RD(pDevice,txCpu.reg.PC))
+             break;
+
+          REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+          REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+          REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress);
+          MM_Wait(1000);
+        }
+        
+        REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,txCpu.reg.mode, 0);
+    }
+    
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number)
+{
+    LM_UINT32 i;
+
+    if((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) &&
+       (cpu_number != T3_RX_CPU_ID))
+    {
+        return LM_STATUS_SUCCESS;
+    }
+
+    if (cpu_number == T3_RX_CPU_ID)
+    {
+        for (i = 0 ; i < 10000; i++)
+        {
+            REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+            REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+
+            if (REG_RD(pDevice,rxCpu.reg.mode) & CPU_MODE_HALT)
+              break;
+        }
+
+        REG_WR(pDevice,rxCpu.reg.state, 0xffffffff);
+        REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT);
+        MM_Wait(10);
+    }
+    else
+    {
+        for (i = 0 ; i < 10000; i++)
+        {
+            REG_WR(pDevice,txCpu.reg.state, 0xffffffff);
+            REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT);
+
+            if (REG_RD(pDevice,txCpu.reg.mode) & CPU_MODE_HALT)
+               break;
+        }
+    }
+
+  return (( i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS);
+}
+
+
+int
+LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
+{
+	LM_UINT32 Oldcfg;
+	int j;
+	int ret = 0;
+
+	if(BlinkDurationSec == 0)
+	{
+		return 0;
+        }
+	if(BlinkDurationSec > 120)
+        {
+	        BlinkDurationSec = 120;
+	}
+
+	Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl);
+	for(j = 0; j < BlinkDurationSec * 2; j++)
+	{
+		if(j % 2)
+		{
+			// Turn on the LEDs.
+			REG_WR(pDevice, MacCtrl.LedCtrl,
+				LED_CTRL_OVERRIDE_LINK_LED |
+				LED_CTRL_1000MBPS_LED_ON |
+				LED_CTRL_100MBPS_LED_ON |
+				LED_CTRL_10MBPS_LED_ON |
+				LED_CTRL_OVERRIDE_TRAFFIC_LED |
+				LED_CTRL_BLINK_TRAFFIC_LED |
+				LED_CTRL_TRAFFIC_LED);
+		}
+		else
+		{
+			// Turn off the LEDs.
+			REG_WR(pDevice, MacCtrl.LedCtrl,
+				LED_CTRL_OVERRIDE_LINK_LED |
+				LED_CTRL_OVERRIDE_TRAFFIC_LED);
+		}
+		current->state = TASK_INTERRUPTIBLE;
+		if (schedule_timeout(HZ/2) != 0) {
+			ret = -EINTR;
+			break;
+		}
+	}
+	REG_WR(pDevice, MacCtrl.LedCtrl, Oldcfg);
+	return ret;
+}
+
+STATIC LM_STATUS
+LM_SwitchClocks(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 ClockCtrl;
+
+    ClockCtrl = REG_RD(pDevice, PciCfg.ClockCtrl);
+    pDevice->ClockCtrl = ClockCtrl & (T3_PCI_FORCE_CLKRUN |
+        T3_PCI_CLKRUN_OUTPUT_EN | 0x1f);
+    if (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        if (ClockCtrl & T3_PCI_44MHZ_CORE_CLOCK)
+        {
+            REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl |
+                T3_PCI_44MHZ_CORE_CLOCK | T3_PCI_SELECT_ALTERNATE_CLOCK);
+            MM_Wait(40);  /* required delay is 27usec */
+            REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl |
+                T3_PCI_SELECT_ALTERNATE_CLOCK);
+            MM_Wait(40);  /* required delay is 27usec */
+        }
+    }
+
+    REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl);
+    MM_Wait(40);  /* required delay is 27usec */
+    return LM_STATUS_SUCCESS;
+}
+
+int t3_do_dma(PLM_DEVICE_BLOCK pDevice, 
+                   LM_PHYSICAL_ADDRESS host_addr_phy, int length,
+                   int dma_read)
+{
+    T3_DMA_DESC dma_desc;
+    int i;
+    LM_UINT32 dma_desc_addr;
+    LM_UINT32 value32;
+
+    REG_WR(pDevice, BufMgr.Mode, 0);
+    REG_WR(pDevice, Ftq.Reset, 0);
+
+    dma_desc.host_addr.High = host_addr_phy.High;
+    dma_desc.host_addr.Low = host_addr_phy.Low;
+    dma_desc.nic_mbuf = 0x2100;
+    dma_desc.len = length;
+    dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */
+
+    if (dma_read)
+    {
+        dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) |
+            T3_QID_DMA_HIGH_PRI_READ;
+        REG_WR(pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE);
+    }
+    else
+    {
+        dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) |
+            T3_QID_DMA_HIGH_PRI_WRITE;
+        REG_WR(pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE);
+    }
+
+    dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR;
+
+    /* Writing this DMA descriptor to DMA memory */
+    for (i = 0; i < sizeof(T3_DMA_DESC); i += 4)
+    {
+        value32 = *((PLM_UINT32) (((PLM_UINT8) &dma_desc) + i));
+        MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, dma_desc_addr+i);
+        MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG,
+            MM_SWAP_LE32(value32));
+    }
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, 0);
+
+    if (dma_read)
+        REG_WR(pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue, dma_desc_addr);
+    else
+        REG_WR(pDevice, Ftq.DmaHighWriteFtqFifoEnqueueDequeue, dma_desc_addr);
+
+    for (i = 0; i < 40; i++)
+    {
+        if (dma_read)
+            value32 = REG_RD(pDevice, Ftq.RcvBdCompFtqFifoEnqueueDequeue);
+        else
+            value32 = REG_RD(pDevice, Ftq.RcvDataCompFtqFifoEnqueueDequeue);
+
+        if ((value32 & 0xffff) == dma_desc_addr)
+            break;
+
+        MM_Wait(10);
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+STATIC LM_STATUS
+LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt,
+           LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize)
+{
+    int j;
+    LM_UINT32 *ptr;
+    int dma_success = 0;
+    LM_STATUS ret = LM_STATUS_FAILURE;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+        T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701)
+    {
+        return LM_STATUS_SUCCESS;
+    }
+    while (!dma_success)
+    {
+        /* Fill data with incremental patterns */
+        ptr = (LM_UINT32 *)pBufferVirt;
+        for (j = 0; j < BufferSize/4; j++)
+            *ptr++ = j;
+
+        if (t3_do_dma(pDevice,BufferPhy,BufferSize, 1) == LM_STATUS_FAILURE)
+        {
+            goto LM_DmaTestDone;
+        }
+
+        MM_Wait(40);
+        ptr = (LM_UINT32 *)pBufferVirt;
+        /* Fill data with zero */
+        for (j = 0; j < BufferSize/4; j++)
+            *ptr++ = 0;
+
+        if (t3_do_dma(pDevice,BufferPhy,BufferSize, 0) == LM_STATUS_FAILURE)
+        {
+            goto LM_DmaTestDone;
+        }
+
+        MM_Wait(40);
+        /* Check for data */
+        ptr = (LM_UINT32 *)pBufferVirt;
+        for (j = 0; j < BufferSize/4; j++)
+        {
+            if (*ptr++ != j)
+            {
+                if ((pDevice->DmaReadWriteCtrl & DMA_CTRL_WRITE_BOUNDARY_MASK)
+                    == DMA_CTRL_WRITE_BOUNDARY_DISABLE)
+                {
+                    pDevice->DmaReadWriteCtrl = (pDevice->DmaReadWriteCtrl &
+                         ~DMA_CTRL_WRITE_BOUNDARY_MASK) |
+                          DMA_CTRL_WRITE_BOUNDARY_16;
+                    REG_WR(pDevice, PciCfg.DmaReadWriteCtrl,
+                           pDevice->DmaReadWriteCtrl);
+                    break;
+                 }
+                 else
+                 {
+                     goto LM_DmaTestDone;
+                 }
+            }
+        }
+        if (j == (BufferSize/4))
+            dma_success = 1;
+    }
+    ret = LM_STATUS_SUCCESS;
+LM_DmaTestDone:
+    memset(pBufferVirt, 0, BufferSize);
+    return ret;
+}
+
+void
+LM_Add32To64Counter(LM_UINT32 Counter32, T3_64BIT_REGISTER *Counter64)
+{
+    Counter64->Low += Counter32;
+    if (Counter64->Low < Counter32)
+    {
+        Counter64->High++;
+    }
+}
+
+LM_STATUS
+LM_GetStats(PLM_DEVICE_BLOCK pDevice)
+{
+    PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5705)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    if (pStats == 0)
+    {
+        return LM_STATUS_FAILURE;
+    }
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCOutOctets),
+        &pStats->ifHCOutOctets);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.etherStatsCollisions),
+        &pStats->etherStatsCollisions);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.outXonSent),
+        &pStats->outXonSent);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.outXoffSent),
+        &pStats->outXoffSent);
+    LM_Add32To64Counter(REG_RD(pDevice,
+	MacCtrl.dot3StatsInternalMacTransmitErrors),
+        &pStats->dot3StatsInternalMacTransmitErrors);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.dot3StatsSingleCollisionFrames),
+        &pStats->dot3StatsSingleCollisionFrames);
+    LM_Add32To64Counter(REG_RD(pDevice,
+	MacCtrl.dot3StatsMultipleCollisionFrames),
+        &pStats->dot3StatsMultipleCollisionFrames);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.dot3StatsDeferredTransmissions),
+        &pStats->dot3StatsDeferredTransmissions);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.dot3StatsExcessiveCollisions),
+        &pStats->dot3StatsExcessiveCollisions);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.dot3StatsLateCollisions),
+        &pStats->dot3StatsLateCollisions);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCOutUcastPkts),
+        &pStats->ifHCOutUcastPkts);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCOutMulticastPkts),
+        &pStats->ifHCOutMulticastPkts);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCOutBroadcastPkts),
+        &pStats->ifHCOutBroadcastPkts);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCInOctets),
+        &pStats->ifHCInOctets);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.etherStatsFragments),
+        &pStats->etherStatsFragments);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCInUcastPkts),
+        &pStats->ifHCInUcastPkts);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCInMulticastPkts),
+        &pStats->ifHCInMulticastPkts);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.ifHCInBroadcastPkts),
+        &pStats->ifHCInBroadcastPkts);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.dot3StatsFCSErrors),
+        &pStats->dot3StatsFCSErrors);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.dot3StatsAlignmentErrors),
+        &pStats->dot3StatsAlignmentErrors);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.xonPauseFramesReceived),
+        &pStats->xonPauseFramesReceived);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.xoffPauseFramesReceived),
+        &pStats->xoffPauseFramesReceived);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.macControlFramesReceived),
+        &pStats->macControlFramesReceived);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.xoffStateEntered),
+        &pStats->xoffStateEntered);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.dot3StatsFramesTooLong),
+        &pStats->dot3StatsFramesTooLong);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.etherStatsJabbers),
+        &pStats->etherStatsJabbers);
+    LM_Add32To64Counter(REG_RD(pDevice, MacCtrl.etherStatsUndersizePkts),
+        &pStats->etherStatsUndersizePkts);
+
+    return LM_STATUS_SUCCESS;
+}
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm/tigon3.h orig/drivers/net/bcm/tigon3.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm/tigon3.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm/tigon3.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,3470 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom  */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef TIGON3_H
+#define TIGON3_H
+
+#include "lm.h"
+#if INCLUDE_TBI_SUPPORT
+#include "autoneg.h"
+#endif
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+/* Maxim number of packet descriptors used for sending packets. */
+#define MAX_TX_PACKET_DESC_COUNT            600
+#define DEFAULT_TX_PACKET_DESC_COUNT        100
+
+/* Maximum number of packet descriptors used for receiving packets. */
+#if T3_JUMBO_RCB_ENTRY_COUNT
+#define MAX_RX_PACKET_DESC_COUNT                                            \
+    (T3_STD_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT)
+#else
+#define MAX_RX_PACKET_DESC_COUNT            800
+#endif
+#define DEFAULT_RX_PACKET_DESC_COUNT        200
+
+/* Threshhold for double copying small tx packets.  0 will disable double */
+/* copying of small Tx packets. */
+#define DEFAULT_TX_COPY_BUFFER_SIZE         0
+#define MIN_TX_COPY_BUFFER_SIZE             64 
+#define MAX_TX_COPY_BUFFER_SIZE             512
+
+/* Cache line. */
+#define COMMON_CACHE_LINE_SIZE              0x20
+#define COMMON_CACHE_LINE_MASK              (COMMON_CACHE_LINE_SIZE-1)
+
+/* Maximum number of fragment we can handle. */
+#ifndef MAX_FRAGMENT_COUNT
+#define MAX_FRAGMENT_COUNT                  32
+#endif
+
+/* B0 bug. */
+#define BCM5700_BX_MIN_FRAG_SIZE            10
+#define BCM5700_BX_MIN_FRAG_BUF_SIZE        16  /* nice aligned size. */
+#define BCM5700_BX_MIN_FRAG_BUF_SIZE_MASK   (BCM5700_BX_MIN_FRAG_BUF_SIZE-1)
+#define BCM5700_BX_TX_COPY_BUF_SIZE         (BCM5700_BX_MIN_FRAG_BUF_SIZE * \
+                                            MAX_FRAGMENT_COUNT)
+
+/* MAGIC number. */
+//#define T3_MAGIC_NUM                        'KevT'
+#define T3_FIRMWARE_MAILBOX                0x0b50
+#define T3_MAGIC_NUM_FIRMWARE_INIT_DONE    0x4B657654 
+#define T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE 0x4861764b
+
+#define T3_NIC_DATA_SIG_ADDR               0x0b54
+#define T3_NIC_DATA_SIG                    0x4b657654
+
+#define T3_NIC_DATA_NIC_CFG_ADDR           0x0b58
+#define T3_NIC_CFG_LED_MODE_UNKNOWN        BIT_NONE
+#define T3_NIC_CFG_LED_MODE_TRIPLE_SPEED   BIT_2
+#define T3_NIC_CFG_LED_MODE_LINK_SPEED     BIT_3
+#define T3_NIC_CFG_LED_MODE_OPEN_DRAIN     BIT_2
+#define T3_NIC_CFG_LED_MODE_OUTPUT         BIT_3
+#define T3_NIC_CFG_LED_MODE_MASK           (BIT_2 | BIT_3)
+#define T3_NIC_CFG_PHY_TYPE_UNKNOWN         BIT_NONE
+#define T3_NIC_CFG_PHY_TYPE_COPPER          BIT_4
+#define T3_NIC_CFG_PHY_TYPE_FIBER           BIT_5
+#define T3_NIC_CFG_PHY_TYPE_MASK            (BIT_4 | BIT_5)
+#define T3_NIC_CFG_ENABLE_WOL               BIT_6
+#define T3_NIC_CFG_ENABLE_ASF               BIT_7
+#define T3_NIC_EEPROM_WP                    BIT_8
+#define T3_NIC_WOL_LIMIT_10                 BIT_10
+#define T3_NIC_MINI_PCI                     BIT_12
+#define T3_NIC_FIBER_WOL_CAPABLE            BIT_14
+
+#define T3_NIC_DATA_PHY_ID_ADDR            0x0b74
+#define T3_NIC_PHY_ID1_MASK                0xffff0000
+#define T3_NIC_PHY_ID2_MASK                0x0000ffff
+
+#define T3_CMD_MAILBOX                      0x0b78
+#define T3_CMD_NICDRV_ALIVE                 0x01
+#define T3_CMD_NICDRV_PAUSE_FW              0x02
+#define T3_CMD_NICDRV_IPV4ADDR_CHANGE       0x03
+#define T3_CMD_NICDRV_IPV6ADDR_CHANGE       0x04
+#define T3_CMD_5703A0_FIX_DMAFW_DMAR        0x05
+#define T3_CMD_5703A0_FIX_DMAFW_DMAW        0x06
+
+#define T3_CMD_LENGTH_MAILBOX               0x0b7c
+#define T3_CMD_DATA_MAILBOX                 0x0b80
+
+#define T3_ASF_FW_STATUS_MAILBOX            0x0c00
+
+#define T3_DRV_STATE_MAILBOX                0x0c04
+#define T3_DRV_STATE_START                  0x01
+#define T3_DRV_STATE_UNLOAD                 0x02
+#define T3_DRV_STATE_WOL                    0x03
+#define T3_DRV_STATE_SUSPEND                0x04
+
+#define T3_FW_RESET_TYPE_MAILBOX            0x0c08
+
+#define T3_MAC_ADDR_HIGH_MAILBOX            0x0c14
+#define T3_MAC_ADDR_LOW_MAILBOX             0x0c18
+
+#define DRV_WOL_MAILBOX                     0xd30
+#define DRV_WOL_SIGNATURE                   0x474c0000
+
+#define DRV_DOWN_STATE_SHUTDOWN             0x1
+
+#define DRV_WOL_SET_MAGIC_PKT               BIT_2
+
+/******************************************************************************/
+/* Hardware constants. */
+/******************************************************************************/
+
+/* Number of entries in the send ring:  must be 512. */
+#define T3_SEND_RCB_ENTRY_COUNT             512     
+#define T3_SEND_RCB_ENTRY_COUNT_MASK        (T3_SEND_RCB_ENTRY_COUNT-1)
+
+/* Number of send RCBs.  May be 1-16 but for now, only support one. */
+#define T3_MAX_SEND_RCB_COUNT               16
+
+/* Number of entries in the Standard Receive RCB.  Must be 512 entries. */
+#define T3_STD_RCV_RCB_ENTRY_COUNT          512
+#define T3_STD_RCV_RCB_ENTRY_COUNT_MASK     (T3_STD_RCV_RCB_ENTRY_COUNT-1)
+#define DEFAULT_STD_RCV_DESC_COUNT          200    /* Must be < 512. */
+#define MAX_STD_RCV_BUFFER_SIZE             0x600
+
+/* Number of entries in the Mini Receive RCB.  This value can either be */
+/* 0, 1024.  Currently Mini Receive RCB is disabled. */
+#ifndef T3_MINI_RCV_RCB_ENTRY_COUNT
+#define T3_MINI_RCV_RCB_ENTRY_COUNT         0
+#endif /* T3_MINI_RCV_RCB_ENTRY_COUNT */
+#define T3_MINI_RCV_RCB_ENTRY_COUNT_MASK    (T3_MINI_RCV_RCB_ENTRY_COUNT-1)
+#define MAX_MINI_RCV_BUFFER_SIZE            512
+#define DEFAULT_MINI_RCV_BUFFER_SIZE        64
+#define DEFAULT_MINI_RCV_DESC_COUNT         100    /* Must be < 1024. */
+
+/* Number of entries in the Jumbo Receive RCB.  This value must 256 or 0. */
+/* Currently, Jumbo Receive RCB is disabled. */
+#ifndef T3_JUMBO_RCV_RCB_ENTRY_COUNT
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT        0
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+#define T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK   (T3_JUMBO_RCV_RCB_ENTRY_COUNT-1)
+
+#define MAX_JUMBO_RCV_BUFFER_SIZE           (10 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_BUFFER_SIZE       (4 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_RCV_DESC_COUNT        128     /* Must be < 256. */
+
+#define MAX_JUMBO_TX_BUFFER_SIZE            (8 * 1024) /* > 1514 */
+#define DEFAULT_JUMBO_TX_BUFFER_SIZE        (4 * 1024) /* > 1514 */
+
+/* Number of receive return RCBs.  Maybe 1-16 but for now, only support one. */
+#define T3_MAX_RCV_RETURN_RCB_COUNT         16
+
+/* Number of entries in a Receive Return ring.  This value is either 1024 */
+/* or 2048. */
+#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT 
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT       1024
+#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */
+#define T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK  (T3_RCV_RETURN_RCB_ENTRY_COUNT-1)
+
+
+/* Default coalescing parameters. */
+#define DEFAULT_RX_COALESCING_TICKS         80
+#define MAX_RX_COALESCING_TICKS             500
+#define DEFAULT_TX_COALESCING_TICKS         200
+#define MAX_TX_COALESCING_TICKS             500
+#define DEFAULT_RX_MAX_COALESCED_FRAMES     15
+#define MAX_RX_MAX_COALESCED_FRAMES         100
+#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES    5
+#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES    48
+#define ADAPTIVE_LO_RX_COALESCING_TICKS         25
+#define ADAPTIVE_HI_RX_COALESCING_TICKS         135
+#define ADAPTIVE_LO_PKT_THRESH              55000
+#define ADAPTIVE_HI_PKT_THRESH              118000
+#define DEFAULT_TX_MAX_COALESCED_FRAMES     35
+#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES    20
+#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES    75
+#define MAX_TX_MAX_COALESCED_FRAMES         100
+
+#define DEFAULT_RX_COALESCING_TICKS_DURING_INT          25
+#define DEFAULT_TX_COALESCING_TICKS_DURING_INT          25
+#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT      2
+#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES_DURING_INT  1
+#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES_DURING_INT  5
+#define DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT      5
+
+#define BAD_DEFAULT_VALUE                               0xffffffff
+
+#define DEFAULT_STATS_COALESCING_TICKS      1000000
+#define MIN_STATS_COALESCING_TICKS          100
+#define MAX_STATS_COALESCING_TICKS          3600000000U
+
+
+/* Receive BD Replenish thresholds. */
+#define DEFAULT_RCV_STD_BD_REPLENISH_THRESHOLD      4
+#define DEFAULT_RCV_JUMBO_BD_REPLENISH_THRESHOLD    4
+
+#define SPLIT_MODE_DISABLE                          0
+#define SPLIT_MODE_ENABLE                           1
+
+#define SPLIT_MODE_5704_MAX_REQ                     3
+
+/* Maximum physical fragment size. */
+#define MAX_FRAGMENT_SIZE                   (64 * 1024)
+
+
+/* Standard view. */
+#define T3_STD_VIEW_SIZE                    (64 * 1024)
+#define T3_FLAT_VIEW_SIZE                   (32 * 1024 * 1024)
+
+
+/* Buffer descriptor base address on the NIC's memory. */
+
+#define T3_NIC_SND_BUFFER_DESC_ADDR         0x4000
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR     0x6000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR   0x7000
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR_EXT_MEM     0xc000
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR_EXT_MEM   0xd000
+#define T3_NIC_MINI_RCV_BUFFER_DESC_ADDR_EXT_MEM    0xe000
+
+#define T3_NIC_SND_BUFFER_DESC_SIZE         (T3_SEND_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_SND_BD) / 4)
+
+#define T3_NIC_STD_RCV_BUFFER_DESC_SIZE     (T3_STD_RCV_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_RCV_BD) / 4)
+
+#define T3_NIC_JUMBO_RCV_BUFFER_DESC_SIZE   (T3_JUMBO_RCV_RCB_ENTRY_COUNT * \
+                                            sizeof(T3_EXT_RCV_BD) / 4)
+
+
+/* MBUF pool. */
+#define T3_NIC_MBUF_POOL_ADDR               0x8000
+#define T3_NIC_MBUF_POOL_SIZE96             0x18000
+#define T3_NIC_MBUF_POOL_SIZE64             0x10000
+
+#define T3_NIC_MBUF_POOL_ADDR_EXT_MEM       0x20000
+
+#define T3_NIC_BCM5705_MBUF_POOL_ADDR               0x10000
+#define T3_NIC_BCM5705_MBUF_POOL_SIZE               0xe000
+
+/* DMA descriptor pool */
+#define T3_NIC_DMA_DESC_POOL_ADDR           0x2000
+#define T3_NIC_DMA_DESC_POOL_SIZE           0x2000      /* 8KB. */
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK           0x50
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK        0x20
+#define T3_DEF_MBUF_HIGH_WMARK              0x60
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK_5705       0x0
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_5705    0x10
+#define T3_DEF_MBUF_HIGH_WMARK_5705          0x60
+
+#define T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO     304
+#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO  152
+#define T3_DEF_MBUF_HIGH_WMARK_JUMBO        380
+
+#define T3_DEF_DMA_DESC_LOW_WMARK           5
+#define T3_DEF_DMA_DESC_HIGH_WMARK          10
+
+/* Maximum size of giant TCP packet can be sent */
+#define T3_TCP_SEG_MAX_OFFLOAD_SIZE         64*1000
+#define T3_TCP_SEG_MIN_NUM_SEG              20
+
+#define T3_RX_CPU_ID    0x1
+#define T3_TX_CPU_ID    0x2
+#define T3_RX_CPU_SPAD_ADDR  0x30000
+#define T3_RX_CPU_SPAD_SIZE  0x4000
+#define T3_TX_CPU_SPAD_ADDR  0x34000
+#define T3_TX_CPU_SPAD_SIZE  0x4000
+
+typedef struct T3_DIR_ENTRY
+{
+  PLM_UINT8 Buffer;
+  LM_UINT32 Offset;
+  LM_UINT32 Length;
+} T3_DIR_ENTRY,*PT3_DIR_ENTRY;
+
+typedef struct T3_FWIMG_INFO
+{
+  LM_UINT32 StartAddress;
+  T3_DIR_ENTRY Text;
+  T3_DIR_ENTRY ROnlyData;
+  T3_DIR_ENTRY Data;
+  T3_DIR_ENTRY Sbss;
+  T3_DIR_ENTRY Bss;
+} T3_FWIMG_INFO, *PT3_FWIMG_INFO;
+
+
+
+/******************************************************************************/
+/* Tigon3 PCI Registers. */
+/******************************************************************************/
+#define T3_PCI_ID_BCM5700                   0x164414e4
+#define T3_PCI_ID_BCM5701                   0x164514e4
+#define T3_PCI_ID_BCM5702                   0x164614e4
+#define T3_PCI_ID_BCM5702x                  0x16A614e4
+#define T3_PCI_ID_BCM5703                   0x164714e4
+#define T3_PCI_ID_BCM5703x                  0x16A714e4
+#define T3_PCI_ID_BCM5702FE                 0x164D14e4
+#define T3_PCI_ID_BCM5704                   0x164814e4
+#define T3_PCI_ID_BCM5705                   0x165314e4
+#define T3_PCI_ID_BCM5705M                  0x165D14e4
+
+#define T3_PCI_VENDOR_ID(x)                 ((x) & 0xffff)
+#define T3_PCI_DEVICE_ID(x)                 ((x) >> 16)
+
+#define T3_PCI_MISC_HOST_CTRL_REG           0x68
+
+/* The most significant 16bit of register 0x68. */
+/* ChipId:4, ChipRev:4, MetalRev:8 */
+#define T3_CHIP_ID_5700_A0                  0x7000
+#define T3_CHIP_ID_5700_A1                  0x7001
+#define T3_CHIP_ID_5700_B0                  0x7100
+#define T3_CHIP_ID_5700_B1                  0x7101
+#define T3_CHIP_ID_5700_C0                  0x7200
+
+#define T3_CHIP_ID_5701_A0                  0x0000
+#define T3_CHIP_ID_5701_B0                  0x0100
+#define T3_CHIP_ID_5701_B2                  0x0102
+#define T3_CHIP_ID_5701_B5                  0x0105
+
+#define T3_CHIP_ID_5703_A0                  0x1000
+#define T3_CHIP_ID_5703_A1                  0x1001
+#define T3_CHIP_ID_5703_A2                  0x1002
+#define T3_CHIP_ID_5703_A3                  0x1003
+
+#define T3_CHIP_ID_5704_A0                  0x2000
+#define T3_CHIP_ID_5704_A1                  0x2001
+#define T3_CHIP_ID_5704_A2                  0x2002
+
+#define T3_CHIP_ID_5705_A0                  0x3000
+#define T3_CHIP_ID_5705_A1                  0x3001
+
+/* Chip Id. */
+#define T3_ASIC_REV(_ChipRevId)             ((_ChipRevId) >> 12)
+#define T3_ASIC_REV_5700                    0x07
+#define T3_ASIC_REV_5701                    0x00
+#define T3_ASIC_REV_5703                    0x01
+#define T3_ASIC_REV_5704                    0x02
+#define T3_ASIC_REV_5705                    0x03
+
+/* Chip id and revision. */
+#define T3_CHIP_REV(_ChipRevId)             ((_ChipRevId) >> 8)
+#define T3_CHIP_REV_5700_AX                 0x70
+#define T3_CHIP_REV_5700_BX                 0x71
+#define T3_CHIP_REV_5700_CX                 0x72
+#define T3_CHIP_REV_5701_AX                 0x00
+
+/* Metal revision. */
+#define T3_METAL_REV(_ChipRevId)            ((_ChipRevId) & 0xff)
+#define T3_METAL_REV_A0                     0x00
+#define T3_METAL_REV_A1                     0x01
+#define T3_METAL_REV_B0                     0x00
+#define T3_METAL_REV_B1                     0x01
+#define T3_METAL_REV_B2                     0x02
+
+#define T3_PCI_REG_CLOCK_CTRL               0x74
+
+#define T3_PCI_DISABLE_RX_CLOCK             BIT_10
+#define T3_PCI_DISABLE_TX_CLOCK             BIT_11
+#define T3_PCI_SELECT_ALTERNATE_CLOCK       BIT_12
+#define T3_PCI_POWER_DOWN_PCI_PLL133        BIT_15
+#define T3_PCI_44MHZ_CORE_CLOCK             BIT_18
+#define T3_PCI_625_CORE_CLOCK               BIT_20
+#define T3_PCI_FORCE_CLKRUN                 BIT_21
+#define T3_PCI_CLKRUN_OUTPUT_EN             BIT_22
+
+
+#define T3_PCI_REG_ADDR_REG                 0x78
+#define T3_PCI_REG_DATA_REG                 0x80
+
+#define T3_PCI_MEM_WIN_ADDR_REG             0x7c
+#define T3_PCI_MEM_WIN_DATA_REG             0x84
+
+#define T3_PCI_PM_CAP_REG                   0x48
+
+#define T3_PCI_PM_CAP_PME_D3COLD            BIT_31
+#define T3_PCI_PM_CAP_PME_D3HOT             BIT_30
+
+#define T3_PCI_PM_STATUS_CTRL_REG           0x4c
+
+#define T3_PM_POWER_STATE_MASK              (BIT_0 | BIT_1)
+#define T3_PM_POWER_STATE_D0                BIT_NONE
+#define T3_PM_POWER_STATE_D1                BIT_0
+#define T3_PM_POWER_STATE_D2                BIT_1
+#define T3_PM_POWER_STATE_D3                (BIT_0 | BIT_1)
+
+#define T3_PM_PME_ENABLE                    BIT_8
+#define T3_PM_PME_ASSERTED                  BIT_15
+
+
+/* PCI state register. */
+#define T3_PCI_STATE_REG                    0x70
+
+#define T3_PCI_STATE_FORCE_RESET            BIT_0
+#define T3_PCI_STATE_INT_NOT_ACTIVE         BIT_1
+#define T3_PCI_STATE_CONVENTIONAL_PCI_MODE  BIT_2
+#define T3_PCI_STATE_BUS_SPEED_HIGH         BIT_3
+#define T3_PCI_STATE_32BIT_PCI_BUS          BIT_4
+
+
+/* Broadcom subsystem/subvendor IDs. */
+#define T3_SVID_BROADCOM                            0x14e4
+
+#define T3_SSID_BROADCOM_BCM95700A6                 0x1644
+#define T3_SSID_BROADCOM_BCM95701A5                 0x0001
+#define T3_SSID_BROADCOM_BCM95700T6                 0x0002  /* BCM8002 */
+#define T3_SSID_BROADCOM_BCM95700A9                 0x0003  /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701T1                 0x0005
+#define T3_SSID_BROADCOM_BCM95701T8                 0x0006
+#define T3_SSID_BROADCOM_BCM95701A7                 0x0007  /* Agilent */
+#define T3_SSID_BROADCOM_BCM95701A10                0x0008
+#define T3_SSID_BROADCOM_BCM95701A12                0x8008
+#define T3_SSID_BROADCOM_BCM95703Ax1                0x0009
+#define T3_SSID_BROADCOM_BCM95703Ax2                0x8009
+
+/* 3COM subsystem/subvendor IDs. */
+#define T3_SVID_3COM                                0x10b7
+
+#define T3_SSID_3COM_3C996T                         0x1000
+#define T3_SSID_3COM_3C996BT                        0x1006
+#define T3_SSID_3COM_3C996CT                        0x1002
+#define T3_SSID_3COM_3C997T                         0x1003
+#define T3_SSID_3COM_3C1000T                        0x1007
+#define T3_SSID_3COM_3C940BR01                      0x1008
+
+/* Fiber boards. */
+#define T3_SSID_3COM_3C996SX                        0x1004
+#define T3_SSID_3COM_3C997SX                        0x1005
+
+
+/* Dell subsystem/subvendor IDs. */
+
+#define T3_SVID_DELL                                0x1028
+
+#define T3_SSID_DELL_VIPER                          0x00d1
+#define T3_SSID_DELL_JAGUAR                         0x0106
+#define T3_SSID_DELL_MERLOT                         0x0109
+#define T3_SSID_DELL_SLIM_MERLOT                    0x010a
+
+/* Compaq subsystem/subvendor IDs */
+
+#define T3_SVID_COMPAQ                              0x0e11
+
+#define T3_SSID_COMPAQ_BANSHEE                      0x007c
+#define T3_SSID_COMPAQ_BANSHEE_2                    0x009a
+#define T3_SSID_COMPAQ_CHANGELING                   0x007d
+#define T3_SSID_COMPAQ_NC7780                       0x0085
+#define T3_SSID_COMPAQ_NC7780_2                     0x0099
+
+
+/******************************************************************************/
+/* MII registers. */
+/******************************************************************************/
+
+/* Control register. */
+#define PHY_CTRL_REG                                0x00
+
+#define PHY_CTRL_SPEED_MASK                         (BIT_6 | BIT_13)
+#define PHY_CTRL_SPEED_SELECT_10MBPS                BIT_NONE
+#define PHY_CTRL_SPEED_SELECT_100MBPS               BIT_13
+#define PHY_CTRL_SPEED_SELECT_1000MBPS              BIT_6
+#define PHY_CTRL_COLLISION_TEST_ENABLE              BIT_7
+#define PHY_CTRL_FULL_DUPLEX_MODE                   BIT_8
+#define PHY_CTRL_RESTART_AUTO_NEG                   BIT_9
+#define PHY_CTRL_ISOLATE_PHY                        BIT_10
+#define PHY_CTRL_LOWER_POWER_MODE                   BIT_11
+#define PHY_CTRL_AUTO_NEG_ENABLE                    BIT_12
+#define PHY_CTRL_LOOPBACK_MODE                      BIT_14
+#define PHY_CTRL_PHY_RESET                          BIT_15
+
+
+/* Status register. */
+#define PHY_STATUS_REG                              0x01
+
+#define PHY_STATUS_LINK_PASS                        BIT_2
+#define PHY_STATUS_AUTO_NEG_COMPLETE                BIT_5
+
+
+/* Phy Id registers. */
+#define PHY_ID1_REG                                 0x02
+#define PHY_ID1_OUI_MASK                            0xffff
+
+#define PHY_ID2_REG                                 0x03
+#define PHY_ID2_REV_MASK                            0x000f
+#define PHY_ID2_MODEL_MASK                          0x03f0
+#define PHY_ID2_OUI_MASK                            0xfc00
+
+
+/* Auto-negotiation advertisement register. */
+#define PHY_AN_AD_REG                               0x04
+
+#define PHY_AN_AD_ASYM_PAUSE                        BIT_11
+#define PHY_AN_AD_PAUSE_CAPABLE                     BIT_10
+#define PHY_AN_AD_10BASET_HALF                      BIT_5
+#define PHY_AN_AD_10BASET_FULL                      BIT_6
+#define PHY_AN_AD_100BASETX_HALF                    BIT_7
+#define PHY_AN_AD_100BASETX_FULL                    BIT_8
+#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD            0x01
+
+#define PHY_AN_AD_ALL_SPEEDS (PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL |\
+    PHY_AN_AD_100BASETX_HALF | PHY_AN_AD_100BASETX_FULL)
+
+/* Auto-negotiation Link Partner Ability register. */
+#define PHY_LINK_PARTNER_ABILITY_REG                0x05
+
+#define PHY_LINK_PARTNER_ASYM_PAUSE                 BIT_11
+#define PHY_LINK_PARTNER_PAUSE_CAPABLE              BIT_10
+
+
+/* Auto-negotiation expansion register. */
+#define PHY_AN_EXPANSION_REG                        0x06
+
+
+
+/******************************************************************************/
+/* BCM5400 and BCM5401 phy info. */
+/******************************************************************************/
+
+#define PHY_DEVICE_ID           1
+
+/* OUI: bit 31-10;   Model#: bit 9-4;   Rev# bit 3-0. */
+#define PHY_UNKNOWN_PHY                             0x00000000
+#define PHY_BCM5400_PHY_ID                          0x60008040
+#define PHY_BCM5401_PHY_ID                          0x60008050
+#define PHY_BCM5411_PHY_ID                          0x60008070
+#define PHY_BCM5701_PHY_ID                          0x60008110
+#define PHY_BCM5703_PHY_ID                          0x60008160
+#define PHY_BCM5704_PHY_ID                          0x60008190
+#define PHY_BCM5705_PHY_ID                          0x600081a0
+#define PHY_BCM8002_PHY_ID                          0x60010140
+
+#define PHY_BCM5401_B0_REV                          0x1
+#define PHY_BCM5401_B2_REV                          0x3
+#define PHY_BCM5401_C0_REV                          0x6
+
+#define PHY_ID_OUI_MASK                             0xfffffc00
+#define PHY_ID_MODEL_MASK                           0x000003f0
+#define PHY_ID_REV_MASK                             0x0000000f
+#define PHY_ID_MASK                                 (PHY_ID_OUI_MASK |      \
+                                                    PHY_ID_MODEL_MASK)
+
+
+#define UNKNOWN_PHY_ID(x)   ((((x) & PHY_ID_MASK) != PHY_BCM5400_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5401_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5701_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5703_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5704_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5705_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID))
+
+
+
+/* 1000Base-T control register. */
+#define BCM540X_1000BASET_CTRL_REG                  0x09
+
+#define BCM540X_AN_AD_1000BASET_HALF                BIT_8
+#define BCM540X_AN_AD_1000BASET_FULL                BIT_9
+#define BCM540X_CONFIG_AS_MASTER                    BIT_11
+#define BCM540X_ENABLE_CONFIG_AS_MASTER             BIT_12
+
+#define BCM540X_AN_AD_ALL_1G_SPEEDS (BCM540X_AN_AD_1000BASET_HALF | \
+    BCM540X_AN_AD_1000BASET_FULL)
+
+/* Extended control register. */
+#define BCM540X_EXT_CTRL_REG                        0x10
+
+#define BCM540X_EXT_CTRL_LINK3_LED_MODE             BIT_1
+#define BCM540X_EXT_CTRL_FORCE_LED_OFF              BIT_3
+#define BCM540X_EXT_CTRL_TBI                        BIT_15
+
+/* PHY extended status register. */
+#define BCM540X_EXT_STATUS_REG                      0x11
+
+#define BCM540X_EXT_STATUS_LINK_PASS                BIT_8
+
+
+/* DSP Coefficient Read/Write Port. */
+#define BCM540X_DSP_RW_PORT                         0x15
+
+
+/* DSP Coeficient Address Register. */
+#define BCM540X_DSP_ADDRESS_REG                     0x17
+
+#define BCM540X_DSP_TAP_NUMBER_MASK                 0x00
+#define BCM540X_DSP_AGC_A                           0x00
+#define BCM540X_DSP_AGC_B                           0x01
+#define BCM540X_DSP_MSE_PAIR_STATUS                 0x02
+#define BCM540X_DSP_SOFT_DECISION                   0x03
+#define BCM540X_DSP_PHASE_REG                       0x04
+#define BCM540X_DSP_SKEW                            0x05
+#define BCM540X_DSP_POWER_SAVER_UPPER_BOUND         0x06
+#define BCM540X_DSP_POWER_SAVER_LOWER_BOUND         0x07
+#define BCM540X_DSP_LAST_ECHO                       0x08
+#define BCM540X_DSP_FREQUENCY                       0x09
+#define BCM540X_DSP_PLL_BANDWIDTH                   0x0a
+#define BCM540X_DSP_PLL_PHASE_OFFSET                0x0b
+
+#define BCM540X_DSP_FILTER_DCOFFSET                 (BIT_10 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT3                    (BIT_8 | BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT2                    (BIT_9 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT1                    (BIT_8 | BIT_11)
+#define BCM540X_DSP_FILTER_FEXT0                    BIT_11
+#define BCM540X_DSP_FILTER_NEXT3                    (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT2                    (BIT_9 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT1                    (BIT_8 | BIT_10)
+#define BCM540X_DSP_FILTER_NEXT0                    BIT_10
+#define BCM540X_DSP_FILTER_ECHO                     (BIT_8 | BIT_9)
+#define BCM540X_DSP_FILTER_DFE                      BIT_9
+#define BCM540X_DSP_FILTER_FFE                      BIT_8
+
+#define BCM540X_DSP_CONTROL_ALL_FILTERS             BIT_12
+
+#define BCM540X_DSP_SEL_CH_0                        BIT_NONE
+#define BCM540X_DSP_SEL_CH_1                        BIT_13
+#define BCM540X_DSP_SEL_CH_2                        BIT_14
+#define BCM540X_DSP_SEL_CH_3                        (BIT_13 | BIT_14)
+
+#define BCM540X_CONTROL_ALL_CHANNELS                BIT_15
+
+
+/* Auxilliary Control Register (Shadow Register) */
+#define BCM5401_AUX_CTRL                            0x18
+
+#define BCM5401_SHADOW_SEL_MASK                     0x7
+#define BCM5401_SHADOW_SEL_NORMAL                   0x00
+#define BCM5401_SHADOW_SEL_10BASET                  0x01
+#define BCM5401_SHADOW_SEL_POWER_CONTROL            0x02
+#define BCM5401_SHADOW_SEL_IP_PHONE                 0x03
+#define BCM5401_SHADOW_SEL_MISC_TEST1               0x04
+#define BCM5401_SHADOW_SEL_MISC_TEST2               0x05
+#define BCM5401_SHADOW_SEL_IP_PHONE_SEED            0x06
+
+
+/* Shadow register selector == '000' */
+#define BCM5401_SHDW_NORMAL_DIAG_MODE               BIT_3
+#define BCM5401_SHDW_NORMAL_DISABLE_MBP             BIT_4
+#define BCM5401_SHDW_NORMAL_DISABLE_LOW_PWR         BIT_5
+#define BCM5401_SHDW_NORMAL_DISABLE_INV_PRF         BIT_6
+#define BCM5401_SHDW_NORMAL_DISABLE_PRF             BIT_7
+#define BCM5401_SHDW_NORMAL_RX_SLICING_NORMAL       BIT_NONE
+#define BCM5401_SHDW_NORMAL_RX_SLICING_4D           BIT_8
+#define BCM5401_SHDW_NORMAL_RX_SLICING_3LVL_1D      BIT_9
+#define BCM5401_SHDW_NORMAL_RX_SLICING_5LVL_1D      (BIT_8 | BIT_9)
+#define BCM5401_SHDW_NORMAL_TX_6DB_CODING           BIT_10
+#define BCM5401_SHDW_NORMAL_ENABLE_SM_DSP_CLOCK     BIT_11
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_4NS       BIT_NONE
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_5NS       BIT_12
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_3NS       BIT_13
+#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_0NS       (BIT_12 | BIT_13)
+#define BCM5401_SHDW_NORMAL_EXT_PACKET_LENGTH       BIT_14
+#define BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK       BIT_15
+
+
+/* Auxilliary status summary. */
+#define BCM540X_AUX_STATUS_REG                      0x19
+
+#define BCM540X_AUX_LINK_PASS                       BIT_2
+#define BCM540X_AUX_SPEED_MASK                      (BIT_8 | BIT_9 | BIT_10)
+#define BCM540X_AUX_10BASET_HD                      BIT_8
+#define BCM540X_AUX_10BASET_FD                      BIT_9
+#define BCM540X_AUX_100BASETX_HD                    (BIT_8 | BIT_9)
+#define BCM540X_AUX_100BASET4                       BIT_10
+#define BCM540X_AUX_100BASETX_FD                    (BIT_8 | BIT_10)
+#define BCM540X_AUX_100BASET_HD                     (BIT_9 | BIT_10)
+#define BCM540X_AUX_100BASET_FD                     (BIT_8 | BIT_9 | BIT_10)
+
+
+/* Interrupt status. */
+#define BCM540X_INT_STATUS_REG                      0x1a
+
+#define BCM540X_INT_LINK_CHANGE                     BIT_1
+#define BCM540X_INT_SPEED_CHANGE                    BIT_2
+#define BCM540X_INT_DUPLEX_CHANGE                   BIT_3
+#define BCM540X_INT_AUTO_NEG_PAGE_RX                BIT_10
+
+
+/* Interrupt mask register. */
+#define BCM540X_INT_MASK_REG                        0x1b
+
+
+
+/******************************************************************************/
+/* Register definitions. */
+/******************************************************************************/
+
+typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER;
+typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER;
+typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER;
+
+typedef struct {
+    /* Big endian format. */
+    T3_32BIT_REGISTER High;
+    T3_32BIT_REGISTER Low;
+} T3_64BIT_REGISTER, *PT3_64BIT_REGISTER;
+
+typedef T3_64BIT_REGISTER T3_64BIT_HOST_ADDR, *PT3_64BIT_HOST_ADDR;
+
+#define T3_NUM_OF_DMA_DESC    256
+#define T3_NUM_OF_MBUF        768
+
+typedef struct 
+{
+  T3_64BIT_REGISTER host_addr;
+  T3_32BIT_REGISTER nic_mbuf;
+  T3_16BIT_REGISTER len;
+  T3_16BIT_REGISTER cqid_sqid;
+  T3_32BIT_REGISTER flags;
+  T3_32BIT_REGISTER opaque1;
+  T3_32BIT_REGISTER opaque2;
+  T3_32BIT_REGISTER opaque3;
+}T3_DMA_DESC, *PT3_DMA_DESC;
+
+
+
+/******************************************************************************/
+/* Ring control block. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_REGISTER HostRingAddr;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            T3_16BIT_REGISTER MaxLen;
+            T3_16BIT_REGISTER Flags;
+#else /* BIG_ENDIAN_HOST */
+            T3_16BIT_REGISTER Flags;
+            T3_16BIT_REGISTER MaxLen;
+#endif
+        } s;
+
+        T3_32BIT_REGISTER MaxLen_Flags;
+    } u;
+
+    T3_32BIT_REGISTER NicRingAddr;
+} T3_RCB, *PT3_RCB;
+
+#define T3_RCB_FLAG_USE_EXT_RECV_BD                     BIT_0
+#define T3_RCB_FLAG_RING_DISABLED                       BIT_1
+
+
+
+/******************************************************************************/
+/* Status block. */
+/******************************************************************************/
+
+/* 
+ * Size of status block is actually 0x50 bytes.  Use 0x80 bytes for
+ * cache line alignment. 
+ */
+#define T3_STATUS_BLOCK_SIZE                                    0x80
+
+typedef struct {
+    volatile LM_UINT32 Status;
+    #define STATUS_BLOCK_UPDATED                                BIT_0
+    #define STATUS_BLOCK_LINK_CHANGED_STATUS                    BIT_1
+    #define STATUS_BLOCK_ERROR                                  BIT_2
+
+    volatile LM_UINT32 StatusTag;
+
+#ifdef BIG_ENDIAN_HOST
+    volatile LM_UINT16 RcvStdConIdx;
+    volatile LM_UINT16 RcvJumboConIdx;
+
+    volatile LM_UINT16 Reserved2;
+    volatile LM_UINT16 RcvMiniConIdx;
+
+    struct {
+        volatile LM_UINT16 SendConIdx;   /* Send consumer index. */
+        volatile LM_UINT16 RcvProdIdx;   /* Receive producer index. */
+    } Idx[16];
+#else /* BIG_ENDIAN_HOST */
+    volatile LM_UINT16 RcvJumboConIdx;
+    volatile LM_UINT16 RcvStdConIdx;
+
+    volatile LM_UINT16 RcvMiniConIdx;
+    volatile LM_UINT16 Reserved2;
+
+    struct {
+        volatile LM_UINT16 RcvProdIdx;   /* Receive producer index. */
+        volatile LM_UINT16 SendConIdx;   /* Send consumer index. */
+    } Idx[16];
+#endif
+} T3_STATUS_BLOCK, *PT3_STATUS_BLOCK;
+
+
+
+/******************************************************************************/
+/* Receive buffer descriptors. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr;
+
+#ifdef BIG_ENDIAN_HOST
+    volatile LM_UINT16 Index;
+    volatile LM_UINT16 Len;
+
+    volatile LM_UINT16 Type;
+    volatile LM_UINT16 Flags;
+
+    volatile LM_UINT16 IpCksum;
+    volatile LM_UINT16 TcpUdpCksum;
+
+    volatile LM_UINT16 ErrorFlag;
+    volatile LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+    volatile LM_UINT16 Len;
+    volatile LM_UINT16 Index;
+
+    volatile LM_UINT16 Flags;
+    volatile LM_UINT16 Type;
+
+    volatile LM_UINT16 TcpUdpCksum;
+    volatile LM_UINT16 IpCksum;
+
+    volatile LM_UINT16 VlanTag;
+    volatile LM_UINT16 ErrorFlag;
+#endif
+
+    volatile LM_UINT32 Reserved;
+    volatile LM_UINT32 Opaque;
+} T3_RCV_BD, *PT3_RCV_BD;
+
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr[3];
+
+#ifdef BIG_ENDIAN_HOST
+    LM_UINT16 Len1;
+    LM_UINT16 Len2;
+
+    LM_UINT16 Len3;
+    LM_UINT16 Reserved1;
+#else /* BIG_ENDIAN_HOST */
+    LM_UINT16 Len2;
+    LM_UINT16 Len1;
+
+    LM_UINT16 Reserved1;
+    LM_UINT16 Len3;
+#endif
+
+    T3_RCV_BD StdRcvBd;
+} T3_EXT_RCV_BD, *PT3_EXT_RCV_BD;
+
+
+/* Error flags. */
+#define RCV_BD_ERR_BAD_CRC                          0x0001
+#define RCV_BD_ERR_COLL_DETECT                      0x0002
+#define RCV_BD_ERR_LINK_LOST_DURING_PKT             0x0004
+#define RCV_BD_ERR_PHY_DECODE_ERR                   0x0008
+#define RCV_BD_ERR_ODD_NIBBLED_RCVD_MII             0x0010
+#define RCV_BD_ERR_MAC_ABORT                        0x0020
+#define RCV_BD_ERR_LEN_LT_64                        0x0040
+#define RCV_BD_ERR_TRUNC_NO_RESOURCES               0x0080
+#define RCV_BD_ERR_GIANT_FRAME_RCVD                 0x0100
+
+
+/* Buffer descriptor flags. */
+#define RCV_BD_FLAG_END                             0x0004
+#define RCV_BD_FLAG_JUMBO_RING                      0x0020
+#define RCV_BD_FLAG_VLAN_TAG                        0x0040
+#define RCV_BD_FLAG_FRAME_HAS_ERROR                 0x0400
+#define RCV_BD_FLAG_MINI_RING                       0x0800
+#define RCV_BD_FLAG_IP_CHKSUM_FIELD                 0x1000
+#define RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD            0x2000
+#define RCV_BD_FLAG_TCP_PACKET                      0x4000
+
+
+
+/******************************************************************************/
+/* Send buffer descriptor. */
+/******************************************************************************/
+
+typedef struct {
+    T3_64BIT_HOST_ADDR HostAddr;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            LM_UINT16 Len;
+            LM_UINT16 Flags;
+#else /* BIG_ENDIAN_HOST */
+            LM_UINT16 Flags;
+            LM_UINT16 Len;
+#endif
+        } s1;
+
+        LM_UINT32 Len_Flags;
+    } u1;
+
+    union {
+        struct {
+#ifdef BIG_ENDIAN_HOST
+            LM_UINT16 Reserved;
+            LM_UINT16 VlanTag;
+#else /* BIG_ENDIAN_HOST */
+            LM_UINT16 VlanTag;
+            LM_UINT16 Reserved;
+#endif
+        } s2;
+
+        LM_UINT32 VlanTag;
+    } u2;
+} T3_SND_BD, *PT3_SND_BD;
+
+
+/* Send buffer descriptor flags. */
+#define SND_BD_FLAG_TCP_UDP_CKSUM                   0x0001
+#define SND_BD_FLAG_IP_CKSUM                        0x0002
+#define SND_BD_FLAG_END                             0x0004
+#define SND_BD_FLAG_IP_FRAG                         0x0008
+#define SND_BD_FLAG_IP_FRAG_END                     0x0010
+#define SND_BD_FLAG_VLAN_TAG                        0x0040
+#define SND_BD_FLAG_COAL_NOW                        0x0080
+#define SND_BD_FLAG_CPU_PRE_DMA                     0x0100
+#define SND_BD_FLAG_CPU_POST_DMA                    0x0200
+#define SND_BD_FLAG_INSERT_SRC_ADDR                 0x1000
+#define SND_BD_FLAG_CHOOSE_SRC_ADDR                 0x6000
+#define SND_BD_FLAG_DONT_GEN_CRC                    0x8000
+
+/* MBUFs */
+typedef struct T3_MBUF_FRAME_DESC {
+#ifdef BIG_ENDIAN_HOST
+  LM_UINT32 status_control;
+  union {
+    struct {
+      LM_UINT8 cqid;
+      LM_UINT8 reserved1;
+      LM_UINT16 length;
+    }s1;
+    LM_UINT32 word;
+  }u1;
+  union {
+    struct 
+    {
+      LM_UINT16 ip_hdr_start;
+      LM_UINT16 tcp_udp_hdr_start;
+    }s2;
+
+    LM_UINT32 word;
+  }u2;
+
+  union {
+    struct {
+      LM_UINT16 data_start;
+      LM_UINT16 vlan_id;
+    }s3;
+    
+    LM_UINT32 word;
+  }u3;
+
+  union {
+    struct {
+      LM_UINT16 ip_checksum;
+      LM_UINT16 tcp_udp_checksum;
+    }s4;
+
+    LM_UINT32 word;
+  }u4;
+
+  union {
+    struct {
+      LM_UINT16 pseudo_checksum;
+      LM_UINT16 checksum_status;
+    }s5;
+
+    LM_UINT32 word;
+  }u5;
+  
+  union {
+    struct {
+      LM_UINT16 rule_match;
+      LM_UINT8 class;
+      LM_UINT8 rupt;
+    }s6;
+
+    LM_UINT32 word;
+  }u6;
+
+  union {
+    struct {
+      LM_UINT16 reserved2;
+      LM_UINT16 mbuf_num;
+    }s7;
+
+    LM_UINT32 word;
+  }u7;
+
+  LM_UINT32 reserved3;
+  LM_UINT32 reserved4;
+#else
+  LM_UINT32 status_control;
+  union {
+    struct {
+      LM_UINT16 length;
+      LM_UINT8  reserved1;
+      LM_UINT8  cqid;
+    }s1;
+    LM_UINT32 word;
+  }u1;
+  union {
+    struct 
+    {
+      LM_UINT16 tcp_udp_hdr_start;
+      LM_UINT16 ip_hdr_start;
+    }s2;
+
+    LM_UINT32 word;
+  }u2;
+
+  union {
+    struct {
+      LM_UINT16 vlan_id;
+      LM_UINT16 data_start;
+    }s3;
+    
+    LM_UINT32 word;
+  }u3;
+
+  union {
+    struct {
+      LM_UINT16 tcp_udp_checksum;
+      LM_UINT16 ip_checksum;
+    }s4;
+
+    LM_UINT32 word;
+  }u4;
+
+  union {
+    struct {
+      LM_UINT16 checksum_status;
+      LM_UINT16 pseudo_checksum;
+    }s5;
+
+    LM_UINT32 word;
+  }u5;
+  
+  union {
+    struct {
+      LM_UINT8 rupt;
+      LM_UINT8 class;
+      LM_UINT16 rule_match;
+    }s6;
+
+    LM_UINT32 word;
+  }u6;
+
+  union {
+    struct {
+      LM_UINT16 mbuf_num;
+      LM_UINT16 reserved2;
+    }s7;
+
+    LM_UINT32 word;
+  }u7;
+
+  LM_UINT32 reserved3;
+  LM_UINT32 reserved4;
+#endif
+}T3_MBUF_FRAME_DESC,*PT3_MBUF_FRAME_DESC;
+
+typedef struct T3_MBUF_HDR {
+  union {
+    struct {
+      unsigned int C:1;
+      unsigned int F:1;
+      unsigned int reserved1:7;
+      unsigned int next_mbuf:16;
+      unsigned int length:7;
+    }s1;
+    
+    LM_UINT32 word;
+  }u1;
+  
+  LM_UINT32 next_frame_ptr;
+}T3_MBUF_HDR, *PT3_MBUF_HDR;
+
+typedef struct T3_MBUF
+{
+  T3_MBUF_HDR hdr;
+  union
+  {
+    struct {
+      T3_MBUF_FRAME_DESC frame_hdr;
+      LM_UINT32 data[20];
+    }s1;
+
+    struct {
+      LM_UINT32 data[30];
+    }s2;
+  }body;
+}T3_MBUF, *PT3_MBUF;
+
+#define T3_MBUF_BASE   (T3_NIC_MBUF_POOL_ADDR >> 7)
+#define T3_MBUF_END    ((T3_NIC_MBUF_POOL_ADDR + T3_NIC_MBUF_POOL_SIZE) >> 7)
+
+
+
+/******************************************************************************/
+/* Statistics block. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT8 Reserved0[0x400-0x300];
+
+    /* Statistics maintained by Receive MAC. */
+    T3_64BIT_REGISTER ifHCInOctets;
+    T3_64BIT_REGISTER Reserved1;
+    T3_64BIT_REGISTER etherStatsFragments;
+    T3_64BIT_REGISTER ifHCInUcastPkts;
+    T3_64BIT_REGISTER ifHCInMulticastPkts;
+    T3_64BIT_REGISTER ifHCInBroadcastPkts;
+    T3_64BIT_REGISTER dot3StatsFCSErrors;
+    T3_64BIT_REGISTER dot3StatsAlignmentErrors;
+    T3_64BIT_REGISTER xonPauseFramesReceived;
+    T3_64BIT_REGISTER xoffPauseFramesReceived;
+    T3_64BIT_REGISTER macControlFramesReceived;
+    T3_64BIT_REGISTER xoffStateEntered;
+    T3_64BIT_REGISTER dot3StatsFramesTooLong;
+    T3_64BIT_REGISTER etherStatsJabbers;
+    T3_64BIT_REGISTER etherStatsUndersizePkts;
+    T3_64BIT_REGISTER inRangeLengthError;
+    T3_64BIT_REGISTER outRangeLengthError;
+    T3_64BIT_REGISTER etherStatsPkts64Octets;
+    T3_64BIT_REGISTER etherStatsPkts65Octetsto127Octets;
+    T3_64BIT_REGISTER etherStatsPkts128Octetsto255Octets;
+    T3_64BIT_REGISTER etherStatsPkts256Octetsto511Octets;
+    T3_64BIT_REGISTER etherStatsPkts512Octetsto1023Octets;
+    T3_64BIT_REGISTER etherStatsPkts1024Octetsto1522Octets;
+    T3_64BIT_REGISTER etherStatsPkts1523Octetsto2047Octets;
+    T3_64BIT_REGISTER etherStatsPkts2048Octetsto4095Octets;
+    T3_64BIT_REGISTER etherStatsPkts4096Octetsto8191Octets;
+    T3_64BIT_REGISTER etherStatsPkts8192Octetsto9022Octets;
+
+    T3_64BIT_REGISTER Unused1[37];
+
+    /* Statistics maintained by Transmit MAC. */
+    T3_64BIT_REGISTER ifHCOutOctets;
+    T3_64BIT_REGISTER Reserved2;
+    T3_64BIT_REGISTER etherStatsCollisions;
+    T3_64BIT_REGISTER outXonSent;
+    T3_64BIT_REGISTER outXoffSent;
+    T3_64BIT_REGISTER flowControlDone;
+    T3_64BIT_REGISTER dot3StatsInternalMacTransmitErrors;
+    T3_64BIT_REGISTER dot3StatsSingleCollisionFrames;
+    T3_64BIT_REGISTER dot3StatsMultipleCollisionFrames;
+    T3_64BIT_REGISTER dot3StatsDeferredTransmissions;
+    T3_64BIT_REGISTER Reserved3;
+    T3_64BIT_REGISTER dot3StatsExcessiveCollisions;
+    T3_64BIT_REGISTER dot3StatsLateCollisions;
+    T3_64BIT_REGISTER dot3Collided2Times;
+    T3_64BIT_REGISTER dot3Collided3Times;
+    T3_64BIT_REGISTER dot3Collided4Times;
+    T3_64BIT_REGISTER dot3Collided5Times;
+    T3_64BIT_REGISTER dot3Collided6Times;
+    T3_64BIT_REGISTER dot3Collided7Times;
+    T3_64BIT_REGISTER dot3Collided8Times;
+    T3_64BIT_REGISTER dot3Collided9Times;
+    T3_64BIT_REGISTER dot3Collided10Times;
+    T3_64BIT_REGISTER dot3Collided11Times;
+    T3_64BIT_REGISTER dot3Collided12Times;
+    T3_64BIT_REGISTER dot3Collided13Times;
+    T3_64BIT_REGISTER dot3Collided14Times;
+    T3_64BIT_REGISTER dot3Collided15Times;
+    T3_64BIT_REGISTER ifHCOutUcastPkts;
+    T3_64BIT_REGISTER ifHCOutMulticastPkts;
+    T3_64BIT_REGISTER ifHCOutBroadcastPkts;
+    T3_64BIT_REGISTER dot3StatsCarrierSenseErrors;
+    T3_64BIT_REGISTER ifOutDiscards;
+    T3_64BIT_REGISTER ifOutErrors;
+
+    T3_64BIT_REGISTER Unused2[31];
+
+    /* Statistics maintained by Receive List Placement. */
+    T3_64BIT_REGISTER COSIfHCInPkts[16];
+    T3_64BIT_REGISTER COSFramesDroppedDueToFilters;
+    T3_64BIT_REGISTER nicDmaWriteQueueFull;
+    T3_64BIT_REGISTER nicDmaWriteHighPriQueueFull;
+    T3_64BIT_REGISTER nicNoMoreRxBDs;
+    T3_64BIT_REGISTER ifInDiscards;
+    T3_64BIT_REGISTER ifInErrors;
+    T3_64BIT_REGISTER nicRecvThresholdHit;
+
+    T3_64BIT_REGISTER Unused3[9];
+
+    /* Statistics maintained by Send Data Initiator. */
+    T3_64BIT_REGISTER COSIfHCOutPkts[16];
+    T3_64BIT_REGISTER nicDmaReadQueueFull;
+    T3_64BIT_REGISTER nicDmaReadHighPriQueueFull;
+    T3_64BIT_REGISTER nicSendDataCompQueueFull;
+
+    /* Statistics maintained by Host Coalescing. */
+    T3_64BIT_REGISTER nicRingSetSendProdIndex;
+    T3_64BIT_REGISTER nicRingStatusUpdate;
+    T3_64BIT_REGISTER nicInterrupts;
+    T3_64BIT_REGISTER nicAvoidedInterrupts;
+    T3_64BIT_REGISTER nicSendThresholdHit;
+
+    LM_UINT8 Reserved4[0xb00-0x9c0];
+} T3_STATS_BLOCK, *PT3_STATS_BLOCK;
+
+
+
+/******************************************************************************/
+/* PCI configuration registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_16BIT_REGISTER VendorId;
+    T3_16BIT_REGISTER DeviceId;
+
+    T3_16BIT_REGISTER Command;
+    T3_16BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER ClassCodeRevId;
+
+    T3_8BIT_REGISTER CacheLineSize;
+    T3_8BIT_REGISTER LatencyTimer;
+    T3_8BIT_REGISTER HeaderType;
+    T3_8BIT_REGISTER Bist;
+
+    T3_32BIT_REGISTER MemBaseAddrLow;
+    T3_32BIT_REGISTER MemBaseAddrHigh;
+
+    LM_UINT8 Unused1[20];
+
+    T3_16BIT_REGISTER SubsystemVendorId;
+    T3_16BIT_REGISTER SubsystemId;
+
+    T3_32BIT_REGISTER RomBaseAddr;
+
+    T3_8BIT_REGISTER PciXCapiblityPtr;
+    LM_UINT8 Unused2[7];
+
+    T3_8BIT_REGISTER IntLine;
+    T3_8BIT_REGISTER IntPin;
+    T3_8BIT_REGISTER MinGnt;
+    T3_8BIT_REGISTER MaxLat;
+
+    T3_8BIT_REGISTER PciXCapabilities;
+    T3_8BIT_REGISTER PmCapabilityPtr;
+    T3_16BIT_REGISTER PciXCommand;
+
+    T3_32BIT_REGISTER PciXStatus;
+
+    T3_8BIT_REGISTER PmCapabilityId;
+    T3_8BIT_REGISTER VpdCapabilityPtr;
+    T3_16BIT_REGISTER PmCapabilities;
+
+    T3_16BIT_REGISTER PmCtrlStatus;
+    #define PM_CTRL_PME_STATUS            BIT_15
+    #define PM_CTRL_PME_ENABLE            BIT_8
+    #define PM_CTRL_PME_POWER_STATE_D0    0
+    #define PM_CTRL_PME_POWER_STATE_D1    1
+    #define PM_CTRL_PME_POWER_STATE_D2    2
+    #define PM_CTRL_PME_POWER_STATE_D3H   3
+
+    T3_8BIT_REGISTER BridgeSupportExt;
+    T3_8BIT_REGISTER PmData;
+
+    T3_8BIT_REGISTER VpdCapabilityId;
+    T3_8BIT_REGISTER MsiCapabilityPtr;
+    T3_16BIT_REGISTER VpdAddrFlag;
+    #define VPD_FLAG_WRITE      (1 << 15)
+    #define VPD_FLAG_RW_MASK    (1 << 15)
+    #define VPD_FLAG_READ       0
+
+
+    T3_32BIT_REGISTER VpdData;
+
+    T3_8BIT_REGISTER MsiCapabilityId;
+    T3_8BIT_REGISTER NextCapabilityPtr;
+    T3_16BIT_REGISTER MsiCtrl;
+    #define MSI_CTRL_64BIT_CAP     (1 << 7)
+    #define MSI_CTRL_MSG_ENABLE(x) (x << 4)
+    #define MSI_CTRL_MSG_CAP(x)    (x << 1)
+    #define MSI_CTRL_ENABLE        (1 << 0)
+  
+
+    T3_32BIT_REGISTER MsiAddrLow;
+    T3_32BIT_REGISTER MsiAddrHigh;
+
+    T3_16BIT_REGISTER MsiData;
+    T3_16BIT_REGISTER Unused3;
+
+    T3_32BIT_REGISTER MiscHostCtrl;
+    #define MISC_HOST_CTRL_CLEAR_INT                        BIT_0
+    #define MISC_HOST_CTRL_MASK_PCI_INT                     BIT_1
+    #define MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP          BIT_2
+    #define MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP          BIT_3
+    #define MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW          BIT_4
+    #define MISC_HOST_CTRL_ENABLE_CLK_REG_RW                BIT_5
+    #define MISC_HOST_CTRL_ENABLE_REG_WORD_SWAP             BIT_6
+    #define MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS           BIT_7
+    #define MISC_HOST_CTRL_ENABLE_INT_MASK_MODE             BIT_8
+    #define MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE        BIT_9
+
+    T3_32BIT_REGISTER DmaReadWriteCtrl;
+    #define DMA_CTRL_WRITE_BOUNDARY_MASK            (BIT_11 | BIT_12 | BIT_13)
+    #define DMA_CTRL_WRITE_BOUNDARY_DISABLE         0
+    #define DMA_CTRL_WRITE_BOUNDARY_16              BIT_11
+    #define DMA_CTRL_WRITE_BOUNDARY_32              BIT_12
+    #define DMA_CTRL_WRITE_BOUNDARY_64              (BIT_12 | BIT_11)
+    #define DMA_CTRL_WRITE_BOUNDARY_128             BIT_13
+    #define DMA_CTRL_WRITE_BOUNDARY_256             (BIT_13 | BIT_11)
+    #define DMA_CTRL_WRITE_BOUNDARY_512             (BIT_13 | BIT_12)
+    #define DMA_CTRL_WRITE_BOUNDARY_1024            (BIT_13 | BIT_12 | BIT_11)
+    #define DMA_CTRL_WRITE_ONE_DMA_AT_ONCE          BIT_14
+
+
+    T3_32BIT_REGISTER PciState;
+    #define T3_PCI_STATE_FORCE_PCI_RESET                    BIT_0
+    #define T3_PCI_STATE_INTERRUPT_NOT_ACTIVE               BIT_1
+    #define T3_PCI_STATE_NOT_PCI_X_BUS                      BIT_2
+    #define T3_PCI_STATE_HIGH_BUS_SPEED                     BIT_3
+    #define T3_PCI_STATE_32BIT_PCI_BUS                      BIT_4
+    #define T3_PCI_STATE_PCI_ROM_ENABLE                     BIT_5
+    #define T3_PCI_STATE_PCI_ROM_RETRY_ENABLE               BIT_6
+    #define T3_PCI_STATE_FLAT_VIEW                          BIT_8
+    #define T3_PCI_STATE_RETRY_SAME_DMA                     BIT_13
+
+    T3_32BIT_REGISTER ClockCtrl;
+    #define T3_PCI_CLKCTRL_TXCPU_CLK_DISABLE                BIT_11
+    #define T3_PCI_CLKCTRL_RXCPU_CLK_DISABLE                BIT_10
+    #define T3_PCI_CLKCTRL_CORE_CLK_DISABLE                 BIT_9
+
+    T3_32BIT_REGISTER RegBaseAddr;
+
+    T3_32BIT_REGISTER MemWindowBaseAddr;
+    
+#ifdef NIC_CPU_VIEW
+  /* These registers are ONLY visible to NIC CPU */
+    T3_32BIT_REGISTER PowerConsumed;
+    T3_32BIT_REGISTER PowerDissipated;
+#else /* NIC_CPU_VIEW */
+    T3_32BIT_REGISTER RegData;
+    T3_32BIT_REGISTER MemWindowData;
+#endif /* !NIC_CPU_VIEW */
+
+    T3_32BIT_REGISTER ModeCtrl;
+
+    T3_32BIT_REGISTER MiscCfg;
+
+    T3_32BIT_REGISTER MiscLocalCtrl;
+
+    T3_32BIT_REGISTER Unused4;
+
+    /* NOTE: Big/Little-endian clarification needed.  Are these register */
+    /* in big or little endian formate. */
+    T3_64BIT_REGISTER StdRingProdIdx;
+    T3_64BIT_REGISTER RcvRetRingConIdx;
+    T3_64BIT_REGISTER SndProdIdx;
+
+    T3_32BIT_REGISTER Unused5[2];
+
+    T3_32BIT_REGISTER DualMacCtrl;
+    #define T3_DUAL_MAC_CH_CTRL_MASK     (BIT_1 | BIT_0)
+    #define T3_DUAL_MAC_ID               BIT_2
+
+    LM_UINT8 Unused6[68];
+
+} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION;
+
+#define PCIX_CMD_MAX_SPLIT_MASK                         0x00700000
+#define PCIX_CMD_MAX_SPLIT_SHL                          20
+#define PCIX_CMD_MAX_BURST_MASK                         0x000c0000
+#define PCIX_CMD_MAX_BURST_SHL                          18
+#define PCIX_CMD_MAX_BURST_CPIOB                        2
+
+/******************************************************************************/
+/* Mac control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* MAC mode control. */
+    T3_32BIT_REGISTER Mode;
+    #define MAC_MODE_GLOBAL_RESET                       BIT_0
+    #define MAC_MODE_HALF_DUPLEX                        BIT_1
+    #define MAC_MODE_PORT_MODE_MASK                     (BIT_2 | BIT_3)
+    #define MAC_MODE_PORT_MODE_TBI                      (BIT_2 | BIT_3)
+    #define MAC_MODE_PORT_MODE_GMII                     BIT_3
+    #define MAC_MODE_PORT_MODE_MII                      BIT_2
+    #define MAC_MODE_PORT_MODE_NONE                     BIT_NONE
+    #define MAC_MODE_PORT_INTERNAL_LOOPBACK             BIT_4
+    #define MAC_MODE_TAGGED_MAC_CONTROL                 BIT_7
+    #define MAC_MODE_TX_BURSTING                        BIT_8
+    #define MAC_MODE_MAX_DEFER                          BIT_9
+    #define MAC_MODE_LINK_POLARITY                      BIT_10
+    #define MAC_MODE_ENABLE_RX_STATISTICS               BIT_11
+    #define MAC_MODE_CLEAR_RX_STATISTICS                BIT_12
+    #define MAC_MODE_FLUSH_RX_STATISTICS                BIT_13
+    #define MAC_MODE_ENABLE_TX_STATISTICS               BIT_14
+    #define MAC_MODE_CLEAR_TX_STATISTICS                BIT_15
+    #define MAC_MODE_FLUSH_TX_STATISTICS                BIT_16
+    #define MAC_MODE_SEND_CONFIGS                       BIT_17
+    #define MAC_MODE_DETECT_MAGIC_PACKET_ENABLE         BIT_18
+    #define MAC_MODE_ACPI_POWER_ON_ENABLE               BIT_19
+    #define MAC_MODE_ENABLE_MIP                         BIT_20
+    #define MAC_MODE_ENABLE_TDE                         BIT_21
+    #define MAC_MODE_ENABLE_RDE                         BIT_22
+    #define MAC_MODE_ENABLE_FHDE                        BIT_23
+
+    /* MAC status */
+    T3_32BIT_REGISTER Status;
+    #define MAC_STATUS_PCS_SYNCED                       BIT_0
+    #define MAC_STATUS_SIGNAL_DETECTED                  BIT_1
+    #define MAC_STATUS_RECEIVING_CFG                    BIT_2
+    #define MAC_STATUS_CFG_CHANGED                      BIT_3
+    #define MAC_STATUS_SYNC_CHANGED                     BIT_4
+    #define MAC_STATUS_PORT_DECODE_ERROR                BIT_10
+    #define MAC_STATUS_LINK_STATE_CHANGED               BIT_12
+    #define MAC_STATUS_MI_COMPLETION                    BIT_22
+    #define MAC_STATUS_MI_INTERRUPT                     BIT_23
+    #define MAC_STATUS_AP_ERROR                         BIT_24
+    #define MAC_STATUS_ODI_ERROR                        BIT_25
+    #define MAC_STATUS_RX_STATS_OVERRUN                 BIT_26
+    #define MAC_STATUS_TX_STATS_OVERRUN                 BIT_27
+
+    /* Event Enable */
+    T3_32BIT_REGISTER MacEvent;
+    #define MAC_EVENT_ENABLE_PORT_DECODE_ERR            BIT_10
+    #define MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN    BIT_12
+    #define MAC_EVENT_ENABLE_MI_COMPLETION              BIT_22
+    #define MAC_EVENT_ENABLE_MI_INTERRUPT               BIT_23
+    #define MAC_EVENT_ENABLE_AP_ERROR                   BIT_24
+    #define MAC_EVENT_ENABLE_ODI_ERROR                  BIT_25
+    #define MAC_EVENT_ENABLE_RX_STATS_OVERRUN           BIT_26
+    #define MAC_EVENT_ENABLE_TX_STATS_OVERRUN           BIT_27
+
+    /* Led control. */
+    T3_32BIT_REGISTER LedCtrl;
+    #define LED_CTRL_OVERRIDE_LINK_LED                  BIT_0
+    #define LED_CTRL_1000MBPS_LED_ON                    BIT_1
+    #define LED_CTRL_100MBPS_LED_ON                     BIT_2
+    #define LED_CTRL_10MBPS_LED_ON                      BIT_3
+    #define LED_CTRL_OVERRIDE_TRAFFIC_LED               BIT_4
+    #define LED_CTRL_BLINK_TRAFFIC_LED                  BIT_5
+    #define LED_CTRL_TRAFFIC_LED                        BIT_6
+    #define LED_CTRL_1000MBPS_LED_STATUS                BIT_7
+    #define LED_CTRL_100MBPS_LED_STATUS                 BIT_8
+    #define LED_CTRL_10MBPS_LED_STATUS                  BIT_9
+    #define LED_CTRL_TRAFFIC_LED_STATUS                 BIT_10
+    #define LED_CTRL_MAC_MODE                           BIT_NONE
+    #define LED_CTRL_PHY_MODE_1                         BIT_11
+    #define LED_CTRL_PHY_MODE_2                         BIT_12
+    #define LED_CTRL_BLINK_RATE_MASK                    0x7ff80000
+    #define LED_CTRL_OVERRIDE_BLINK_PERIOD              BIT_19
+    #define LED_CTRL_OVERRIDE_BLINK_RATE                BIT_31
+
+    /* MAC addresses. */
+    struct {
+        T3_32BIT_REGISTER High;             /* Upper 2 bytes. */
+        T3_32BIT_REGISTER Low;              /* Lower 4 bytes. */
+    } MacAddr[4];
+
+    /* ACPI Mbuf pointer. */
+    T3_32BIT_REGISTER AcpiMbufPtr;
+
+    /* ACPI Length and Offset. */
+    T3_32BIT_REGISTER AcpiLengthOffset;
+    #define ACPI_LENGTH_MASK                            0xffff
+    #define ACPI_OFFSET_MASK                            0x0fff0000
+    #define ACPI_LENGTH(x)                              x
+    #define ACPI_OFFSET(x)                              ((x) << 16)
+
+    /* Transmit random backoff. */
+    T3_32BIT_REGISTER TxBackoffSeed;
+    #define MAC_TX_BACKOFF_SEED_MASK                    0x3ff
+
+    /* Receive MTU */
+    T3_32BIT_REGISTER MtuSize;
+    #define MAC_RX_MTU_MASK                             0xffff
+
+    /* Gigabit PCS Test. */
+    T3_32BIT_REGISTER PcsTest;
+    #define MAC_PCS_TEST_DATA_PATTERN_MASK              0x0fffff
+    #define MAC_PCS_TEST_ENABLE                         BIT_20
+
+    /* Transmit Gigabit Auto-Negotiation. */
+    T3_32BIT_REGISTER TxAutoNeg;
+    #define MAC_AN_TX_AN_DATA_MASK                      0xffff
+
+    /* Receive Gigabit Auto-Negotiation. */
+    T3_32BIT_REGISTER RxAutoNeg;
+    #define MAC_AN_RX_AN_DATA_MASK                      0xffff
+
+    /* MI Communication. */
+    T3_32BIT_REGISTER MiCom;
+    #define MI_COM_CMD_MASK                             (BIT_26 | BIT_27)
+    #define MI_COM_CMD_WRITE                            BIT_26
+    #define MI_COM_CMD_READ                             BIT_27
+    #define MI_COM_READ_FAILED                          BIT_28
+    #define MI_COM_START                                BIT_29
+    #define MI_COM_BUSY                                 BIT_29
+
+    #define MI_COM_PHY_ADDR_MASK                        0x1f
+    #define MI_COM_FIRST_PHY_ADDR_BIT                   21
+
+    #define MI_COM_PHY_REG_ADDR_MASK                    0x1f
+    #define MI_COM_FIRST_PHY_REG_ADDR_BIT               16
+
+    #define MI_COM_PHY_DATA_MASK                        0xffff
+
+    /* MI Status. */
+    T3_32BIT_REGISTER MiStatus;
+    #define MI_STATUS_ENABLE_LINK_STATUS_ATTN           BIT_0
+
+    /* MI Mode. */
+    T3_32BIT_REGISTER MiMode;
+    #define MI_MODE_CLOCK_SPEED_10MHZ                   BIT_0
+    #define MI_MODE_USE_SHORT_PREAMBLE                  BIT_1
+    #define MI_MODE_AUTO_POLLING_ENABLE                 BIT_4
+    #define MI_MODE_CORE_CLOCK_SPEED_62MHZ              BIT_15
+
+    /* Auto-polling status. */
+    T3_32BIT_REGISTER AutoPollStatus;
+    #define AUTO_POLL_ERROR                             BIT_0
+
+    /* Transmit MAC mode. */
+    T3_32BIT_REGISTER TxMode;
+    #define TX_MODE_RESET                               BIT_0
+    #define TX_MODE_ENABLE                              BIT_1
+    #define TX_MODE_ENABLE_FLOW_CONTROL                 BIT_4
+    #define TX_MODE_ENABLE_BIG_BACKOFF                  BIT_5
+    #define TX_MODE_ENABLE_LONG_PAUSE                   BIT_6
+
+    /* Transmit MAC status. */
+    T3_32BIT_REGISTER TxStatus;
+    #define TX_STATUS_RX_CURRENTLY_XOFFED               BIT_0
+    #define TX_STATUS_SENT_XOFF                         BIT_1
+    #define TX_STATUS_SENT_XON                          BIT_2
+    #define TX_STATUS_LINK_UP                           BIT_3
+    #define TX_STATUS_ODI_UNDERRUN                      BIT_4
+    #define TX_STATUS_ODI_OVERRUN                       BIT_5
+
+    /* Transmit MAC length. */
+    T3_32BIT_REGISTER TxLengths;
+    #define TX_LEN_SLOT_TIME_MASK                       0xff
+    #define TX_LEN_IPG_MASK                             0x0f00
+    #define TX_LEN_IPG_CRS_MASK                         (BIT_12 | BIT_13)
+
+    /* Receive MAC mode. */
+    T3_32BIT_REGISTER RxMode;
+    #define RX_MODE_RESET                               BIT_0
+    #define RX_MODE_ENABLE                              BIT_1
+    #define RX_MODE_ENABLE_FLOW_CONTROL                 BIT_2
+    #define RX_MODE_KEEP_MAC_CONTROL                    BIT_3
+    #define RX_MODE_KEEP_PAUSE                          BIT_4
+    #define RX_MODE_ACCEPT_OVERSIZED                    BIT_5
+    #define RX_MODE_ACCEPT_RUNTS                        BIT_6
+    #define RX_MODE_LENGTH_CHECK                        BIT_7
+    #define RX_MODE_PROMISCUOUS_MODE                    BIT_8
+    #define RX_MODE_NO_CRC_CHECK                        BIT_9
+    #define RX_MODE_KEEP_VLAN_TAG                       BIT_10
+
+    /* Receive MAC status. */
+    T3_32BIT_REGISTER RxStatus;
+    #define RX_STATUS_REMOTE_TRANSMITTER_XOFFED         BIT_0
+    #define RX_STATUS_XOFF_RECEIVED                     BIT_1
+    #define RX_STATUS_XON_RECEIVED                      BIT_2
+
+    /* Hash registers. */
+    T3_32BIT_REGISTER HashReg[4];
+
+    /* Receive placement rules registers. */
+    struct {
+        T3_32BIT_REGISTER Rule;
+        T3_32BIT_REGISTER Value;
+    } RcvRules[16];
+
+    #define RCV_DISABLE_RULE_MASK                       0x7fffffff
+
+    #define RCV_RULE1_REJECT_BROADCAST_IDX              0x00
+    #define REJECT_BROADCAST_RULE1_RULE                 0xc2000000
+    #define REJECT_BROADCAST_RULE1_VALUE                0xffffffff
+
+    #define RCV_RULE2_REJECT_BROADCAST_IDX              0x01
+    #define REJECT_BROADCAST_RULE2_RULE                 0x86000004
+    #define REJECT_BROADCAST_RULE2_VALUE                0xffffffff
+
+#if INCLUDE_5701_AX_FIX
+    #define RCV_LAST_RULE_IDX                           0x04
+#else
+    #define RCV_LAST_RULE_IDX                           0x02
+#endif
+
+    T3_32BIT_REGISTER RcvRuleCfg;
+    #define RX_RULE_DEFAULT_CLASS                       (1 << 3)
+
+    T3_32BIT_REGISTER LowWaterMarkMaxRxFrame;
+
+    LM_UINT8 Reserved1[24];
+
+    T3_32BIT_REGISTER HashRegU[4];
+
+    struct {
+        T3_32BIT_REGISTER High;
+        T3_32BIT_REGISTER Low;
+    } MacAddrExt[12];
+
+    T3_32BIT_REGISTER SerdesCfg;
+    T3_32BIT_REGISTER SerdesStatus;
+
+    LM_UINT8 Reserved2[24];
+
+    T3_32BIT_REGISTER SgDigControl;
+    T3_32BIT_REGISTER SgDigStatus;
+
+    LM_UINT8 Reserved3[72];
+
+    volatile LM_UINT8 TxMacState[16];
+    volatile LM_UINT8 RxMacState[20];
+
+    LM_UINT8 Reserved4[476];
+
+    T3_32BIT_REGISTER ifHCOutOctets;
+    T3_32BIT_REGISTER Reserved5;
+    T3_32BIT_REGISTER etherStatsCollisions;
+    T3_32BIT_REGISTER outXonSent;
+    T3_32BIT_REGISTER outXoffSent;
+    T3_32BIT_REGISTER Reserved6;
+    T3_32BIT_REGISTER dot3StatsInternalMacTransmitErrors;
+    T3_32BIT_REGISTER dot3StatsSingleCollisionFrames;
+    T3_32BIT_REGISTER dot3StatsMultipleCollisionFrames;
+    T3_32BIT_REGISTER dot3StatsDeferredTransmissions;
+    T3_32BIT_REGISTER Reserved7;
+    T3_32BIT_REGISTER dot3StatsExcessiveCollisions;
+    T3_32BIT_REGISTER dot3StatsLateCollisions;
+    T3_32BIT_REGISTER Reserved8[14];
+    T3_32BIT_REGISTER ifHCOutUcastPkts;
+    T3_32BIT_REGISTER ifHCOutMulticastPkts;
+    T3_32BIT_REGISTER ifHCOutBroadcastPkts;
+    T3_32BIT_REGISTER Reserved9[2];
+    T3_32BIT_REGISTER ifHCInOctets;
+    T3_32BIT_REGISTER Reserved10;
+    T3_32BIT_REGISTER etherStatsFragments;
+    T3_32BIT_REGISTER ifHCInUcastPkts;
+    T3_32BIT_REGISTER ifHCInMulticastPkts;
+    T3_32BIT_REGISTER ifHCInBroadcastPkts;
+    T3_32BIT_REGISTER dot3StatsFCSErrors;
+    T3_32BIT_REGISTER dot3StatsAlignmentErrors;
+    T3_32BIT_REGISTER xonPauseFramesReceived;
+    T3_32BIT_REGISTER xoffPauseFramesReceived;
+    T3_32BIT_REGISTER macControlFramesReceived;
+    T3_32BIT_REGISTER xoffStateEntered;
+    T3_32BIT_REGISTER dot3StatsFramesTooLong;
+    T3_32BIT_REGISTER etherStatsJabbers;
+    T3_32BIT_REGISTER etherStatsUndersizePkts;
+
+    T3_32BIT_REGISTER Reserved11[209];
+
+} T3_MAC_CONTROL, *PT3_MAC_CONTROL;
+
+
+
+/******************************************************************************/
+/* Send data initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define T3_SND_DATA_IN_MODE_RESET                       BIT_0
+    #define T3_SND_DATA_IN_MODE_ENABLE                      BIT_1
+    #define T3_SND_DATA_IN_MODE_STATS_OFLW_ATTN_ENABLE      BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define T3_SND_DATA_IN_STATUS_STATS_OFLW_ATTN           BIT_2
+
+    T3_32BIT_REGISTER StatsCtrl;
+    #define T3_SND_DATA_IN_STATS_CTRL_ENABLE                BIT_0
+    #define T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE         BIT_1
+    #define T3_SND_DATA_IN_STATS_CTRL_CLEAR                 BIT_2
+    #define T3_SND_DATA_IN_STATS_CTRL_FLUSH                 BIT_3
+    #define T3_SND_DATA_IN_STATS_CTRL_FORCE_ZERO            BIT_4
+
+    T3_32BIT_REGISTER StatsEnableMask;
+    T3_32BIT_REGISTER StatsIncMask;
+
+    LM_UINT8 Reserved[108];
+
+    T3_32BIT_REGISTER ClassOfServCnt[16];
+    T3_32BIT_REGISTER DmaReadQFullCnt;
+    T3_32BIT_REGISTER DmaPriorityReadQFullCnt;
+    T3_32BIT_REGISTER SdcQFullCnt;
+
+    T3_32BIT_REGISTER NicRingSetSendProdIdxCnt;
+    T3_32BIT_REGISTER StatusUpdatedCnt;
+    T3_32BIT_REGISTER InterruptsCnt;
+    T3_32BIT_REGISTER AvoidInterruptsCnt;
+    T3_32BIT_REGISTER SendThresholdHitCnt;
+
+    /* Unused space. */
+    LM_UINT8 Unused[800];
+} T3_SEND_DATA_INITIATOR, *PT3_SEND_DATA_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send data completion control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_DATA_COMP_MODE_RESET                        BIT_0
+    #define SND_DATA_COMP_MODE_ENABLE                       BIT_1
+
+    /* Unused space. */
+    LM_UINT8 Unused[1020];
+} T3_SEND_DATA_COMPLETION, *PT3_SEND_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Send BD Ring Selector Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_SEL_MODE_RESET                           BIT_0
+    #define SND_BD_SEL_MODE_ENABLE                          BIT_1
+    #define SND_BD_SEL_MODE_ATTN_ENABLE                     BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define SND_BD_SEL_STATUS_ERROR_ATTN                    BIT_2
+
+    T3_32BIT_REGISTER HwDiag;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[52];
+
+    /* Send BD Ring Selector Local NIC Send BD Consumer Index. */
+    T3_32BIT_REGISTER NicSendBdSelConIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused2[896];
+} T3_SEND_BD_SELECTOR, *PT3_SEND_BD_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Send BD initiator control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_IN_MODE_RESET                            BIT_0
+    #define SND_BD_IN_MODE_ENABLE                           BIT_1
+    #define SND_BD_IN_MODE_ATTN_ENABLE                      BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define SND_BD_IN_STATUS_ERROR_ATTN                     BIT_2
+
+    /* Send BD initiator local NIC send BD producer index. */
+    T3_32BIT_REGISTER NicSendBdInProdIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused2[952];
+} T3_SEND_BD_INITIATOR, *PT3_SEND_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Send BD Completion Control. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define SND_BD_COMP_MODE_RESET                          BIT_0
+    #define SND_BD_COMP_MODE_ENABLE                         BIT_1
+    #define SND_BD_COMP_MODE_ATTN_ENABLE                    BIT_2
+
+    /* Unused space. */
+    LM_UINT8 Unused2[1020];
+} T3_SEND_BD_COMPLETION, *PT3_SEND_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list placement control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define RCV_LIST_PLMT_MODE_RESET                        BIT_0
+    #define RCV_LIST_PLMT_MODE_ENABLE                       BIT_1
+    #define RCV_LIST_PLMT_MODE_CLASS0_ATTN_ENABLE           BIT_2
+    #define RCV_LIST_PLMT_MODE_MAPPING_OOR_ATTN_ENABLE      BIT_3
+    #define RCV_LIST_PLMT_MODE_STATS_OFLOW_ATTN_ENABLE      BIT_4
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define RCV_LIST_PLMT_STATUS_CLASS0_ATTN                BIT_2
+    #define RCV_LIST_PLMT_STATUS_MAPPING_ATTN               BIT_3
+    #define RCV_LIST_PLMT_STATUS_STATS_OFLOW_ATTN           BIT_4
+
+    /* Receive selector list lock register. */
+    T3_32BIT_REGISTER Lock;
+    #define RCV_LIST_SEL_LOCK_REQUEST_MASK                  0xffff
+    #define RCV_LIST_SEL_LOCK_GRANT_MASK                    0xffff0000
+
+    /* Selector non-empty bits. */
+    T3_32BIT_REGISTER NonEmptyBits;
+    #define RCV_LIST_SEL_NON_EMPTY_MASK                     0xffff
+
+    /* Receive list placement configuration register. */
+    T3_32BIT_REGISTER Config;
+
+    /* Receive List Placement statistics Control. */
+    T3_32BIT_REGISTER StatsCtrl;
+#define RCV_LIST_STATS_ENABLE                               BIT_0
+#define RCV_LIST_STATS_FAST_UPDATE                          BIT_1
+
+    /* Receive List Placement statistics Enable Mask. */
+    T3_32BIT_REGISTER StatsEnableMask;
+
+    /* Receive List Placement statistics Increment Mask. */
+    T3_32BIT_REGISTER StatsIncMask;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[224];
+
+    struct {
+        T3_32BIT_REGISTER Head;
+        T3_32BIT_REGISTER Tail;
+        T3_32BIT_REGISTER Count;
+
+        /* Unused space. */
+        LM_UINT8 Unused[4];
+    } RcvSelectorList[16];
+
+    /* Local statistics counter. */
+    T3_32BIT_REGISTER ClassOfServCnt[16];
+
+    T3_32BIT_REGISTER DropDueToFilterCnt;
+    T3_32BIT_REGISTER DmaWriteQFullCnt;
+    T3_32BIT_REGISTER DmaHighPriorityWriteQFullCnt;
+    T3_32BIT_REGISTER NoMoreReceiveBdCnt;
+    T3_32BIT_REGISTER IfInDiscardsCnt;
+    T3_32BIT_REGISTER IfInErrorsCnt;
+    T3_32BIT_REGISTER RcvThresholdHitCnt;
+
+    /* Another unused space. */
+    LM_UINT8 Unused2[420];
+} T3_RCV_LIST_PLACEMENT, *PT3_RCV_LIST_PLACEMENT;
+
+
+
+/******************************************************************************/
+/* Receive Data and Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define RCV_DATA_BD_IN_MODE_RESET                   BIT_0
+    #define RCV_DATA_BD_IN_MODE_ENABLE                  BIT_1
+    #define RCV_DATA_BD_IN_MODE_JUMBO_BD_NEEDED         BIT_2
+    #define RCV_DATA_BD_IN_MODE_FRAME_TOO_BIG           BIT_3
+    #define RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE       BIT_4
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define RCV_DATA_BD_IN_STATUS_JUMBO_BD_NEEDED       BIT_2
+    #define RCV_DATA_BD_IN_STATUS_FRAME_TOO_BIG         BIT_3
+    #define RCV_DATA_BD_IN_STATUS_INVALID_RING_SIZE     BIT_4
+
+    /* Split frame minium size. */
+    T3_32BIT_REGISTER SplitFrameMinSize;
+
+    /* Unused space. */
+    LM_UINT8 Unused1[0x2440-0x240c];
+
+    /* Receive RCBs. */
+    T3_RCB JumboRcvRcb;
+    T3_RCB StdRcvRcb;
+    T3_RCB MiniRcvRcb;
+
+    /* Receive Data and Receive BD Ring Initiator Local NIC Receive */
+    /* BD Consumber Index. */
+    T3_32BIT_REGISTER NicJumboConIdx;
+    T3_32BIT_REGISTER NicStdConIdx;
+    T3_32BIT_REGISTER NicMiniConIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[4];
+
+    /* Receive Data and Receive BD Initiator Local Receive Return ProdIdx. */
+    T3_32BIT_REGISTER RcvDataBdProdIdx[16];
+
+    /* Receive Data and Receive BD Initiator Hardware Diagnostic. */
+    T3_32BIT_REGISTER HwDiag;
+
+    /* Unused space. */
+    LM_UINT8 Unused3[828];
+} T3_RCV_DATA_BD_INITIATOR, *PT3_RCV_DATA_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive Data Completion Control Registes. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_DATA_COMP_MODE_RESET                        BIT_0
+    #define RCV_DATA_COMP_MODE_ENABLE                       BIT_1
+    #define RCV_DATA_COMP_MODE_ATTN_ENABLE                  BIT_2
+
+    /* Unused spaced. */
+    LM_UINT8 Unused[1020];
+} T3_RCV_DATA_COMPLETION, *PT3_RCV_DATA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive BD Initiator Control. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_BD_IN_MODE_RESET                            BIT_0
+    #define RCV_BD_IN_MODE_ENABLE                           BIT_1
+    #define RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE    BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_BD_IN_STATUS_BD_IN_DIABLED_RCB_ATTN         BIT_2
+
+    T3_32BIT_REGISTER NicJumboRcvProdIdx;
+    T3_32BIT_REGISTER NicStdRcvProdIdx;
+    T3_32BIT_REGISTER NicMiniRcvProdIdx;
+
+    T3_32BIT_REGISTER MiniRcvThreshold;
+    T3_32BIT_REGISTER StdRcvThreshold;
+    T3_32BIT_REGISTER JumboRcvThreshold;
+
+    /* Unused space. */
+    LM_UINT8 Unused[992];
+} T3_RCV_BD_INITIATOR, *PT3_RCV_BD_INITIATOR;
+
+
+
+/******************************************************************************/
+/* Receive BD Completion Control Registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_BD_COMP_MODE_RESET                          BIT_0
+    #define RCV_BD_COMP_MODE_ENABLE                         BIT_1
+    #define RCV_BD_COMP_MODE_ATTN_ENABLE                    BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_BD_COMP_STATUS_ERROR_ATTN                   BIT_2
+
+    T3_32BIT_REGISTER  NicJumboRcvBdProdIdx;
+    T3_32BIT_REGISTER  NicStdRcvBdProdIdx;
+    T3_32BIT_REGISTER  NicMiniRcvBdProdIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1004];
+} T3_RCV_BD_COMPLETION, *PT3_RCV_BD_COMPLETION;
+
+
+
+/******************************************************************************/
+/* Receive list selector control register. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define RCV_LIST_SEL_MODE_RESET                         BIT_0
+    #define RCV_LIST_SEL_MODE_ENABLE                        BIT_1
+    #define RCV_LIST_SEL_MODE_ATTN_ENABLE                   BIT_2
+
+    T3_32BIT_REGISTER Status;
+    #define RCV_LIST_SEL_STATUS_ERROR_ATTN                  BIT_2
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR;
+
+
+
+/******************************************************************************/
+/* Mbuf cluster free registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define MBUF_CLUSTER_FREE_MODE_RESET    BIT_0
+#define MBUF_CLUSTER_FREE_MODE_ENABLE   BIT_1
+
+    T3_32BIT_REGISTER Status;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_MBUF_CLUSTER_FREE, *PT3_MBUF_CLUSTER_FREE;
+
+
+
+/******************************************************************************/
+/* Host coalescing control registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode. */
+    T3_32BIT_REGISTER Mode;
+    #define HOST_COALESCE_RESET                         BIT_0
+    #define HOST_COALESCE_ENABLE                        BIT_1
+    #define HOST_COALESCE_ATTN                          BIT_2
+    #define HOST_COALESCE_NOW                           BIT_3
+    #define HOST_COALESCE_FULL_STATUS_MODE              BIT_NONE
+    #define HOST_COALESCE_64_BYTE_STATUS_MODE           BIT_7
+    #define HOST_COALESCE_32_BYTE_STATUS_MODE           BIT_8
+    #define HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT    BIT_9
+    #define HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT    BIT_10
+    #define HOST_COALESCE_NO_INT_ON_COALESCE_NOW_MODE   BIT_11
+    #define HOST_COALESCE_NO_INT_ON_FORCE_DMAD_MODE     BIT_12
+
+    /* Status. */
+    T3_32BIT_REGISTER Status;
+    #define HOST_COALESCE_ERROR_ATTN                    BIT_2
+
+    /* Receive coalescing ticks. */
+    T3_32BIT_REGISTER RxCoalescingTicks;
+
+    /* Send coalescing ticks. */
+    T3_32BIT_REGISTER TxCoalescingTicks;
+
+    /* Receive max coalesced frames. */
+    T3_32BIT_REGISTER RxMaxCoalescedFrames;
+
+    /* Send max coalesced frames. */
+    T3_32BIT_REGISTER TxMaxCoalescedFrames;
+
+    /* Receive coalescing ticks during interrupt. */
+    T3_32BIT_REGISTER RxCoalescedTickDuringInt;
+
+    /* Send coalescing ticks during interrupt. */
+    T3_32BIT_REGISTER TxCoalescedTickDuringInt;
+
+    /* Receive max coalesced frames during interrupt. */
+    T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt;
+
+    /* Send max coalesced frames during interrupt. */
+    T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt;
+
+    /* Statistics tick. */
+    T3_32BIT_REGISTER StatsCoalescingTicks;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[4];
+
+    /* Statistics host address. */
+    T3_64BIT_REGISTER StatsBlkHostAddr;
+
+    /* Status block host address.*/
+    T3_64BIT_REGISTER StatusBlkHostAddr;
+
+    /* Statistics NIC address. */
+    T3_32BIT_REGISTER StatsBlkNicAddr;
+
+    /* Statust block NIC address. */
+    T3_32BIT_REGISTER StatusBlkNicAddr;
+
+    /* Flow attention registers. */
+    T3_32BIT_REGISTER FlowAttn;
+
+    /* Unused space. */
+    LM_UINT8 Unused3[4];
+
+    T3_32BIT_REGISTER NicJumboRcvBdConIdx;
+    T3_32BIT_REGISTER NicStdRcvBdConIdx;
+    T3_32BIT_REGISTER NicMiniRcvBdConIdx;
+
+    /* Unused space. */
+    LM_UINT8 Unused4[36];
+
+    T3_32BIT_REGISTER NicRetProdIdx[16];
+    T3_32BIT_REGISTER NicSndBdConIdx[16];
+
+    /* Unused space. */
+    LM_UINT8 Unused5[768];
+} T3_HOST_COALESCING, *PT3_HOST_COALESCING;
+
+
+
+/******************************************************************************/
+/* Memory arbiter registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define T3_MEM_ARBITER_MODE_RESET       BIT_0
+#define T3_MEM_ARBITER_MODE_ENABLE      BIT_1
+
+    T3_32BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER ArbTrapAddrLow;
+    T3_32BIT_REGISTER ArbTrapAddrHigh;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1008];
+} T3_MEM_ARBITER, *PT3_MEM_ARBITER;
+
+
+
+/******************************************************************************/
+/* Buffer manager control register. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define BUFMGR_MODE_RESET                           BIT_0
+    #define BUFMGR_MODE_ENABLE                          BIT_1
+    #define BUFMGR_MODE_ATTN_ENABLE                     BIT_2
+    #define BUFMGR_MODE_BM_TEST                         BIT_3
+    #define BUFMGR_MODE_MBUF_LOW_ATTN_ENABLE            BIT_4
+
+    T3_32BIT_REGISTER Status;
+    #define BUFMGR_STATUS_ERROR                         BIT_2
+    #define BUFMGR_STATUS_MBUF_LOW                      BIT_4
+
+    T3_32BIT_REGISTER MbufPoolAddr;
+    T3_32BIT_REGISTER MbufPoolSize;
+    T3_32BIT_REGISTER MbufReadDmaLowWaterMark;
+    T3_32BIT_REGISTER MbufMacRxLowWaterMark;
+    T3_32BIT_REGISTER MbufHighWaterMark;
+
+    T3_32BIT_REGISTER RxCpuMbufAllocReq;
+    #define BUFMGR_MBUF_ALLOC_BIT                     BIT_31
+    T3_32BIT_REGISTER RxCpuMbufAllocResp;
+    T3_32BIT_REGISTER TxCpuMbufAllocReq;
+    T3_32BIT_REGISTER TxCpuMbufAllocResp;
+
+    T3_32BIT_REGISTER DmaDescPoolAddr;
+    T3_32BIT_REGISTER DmaDescPoolSize;
+    T3_32BIT_REGISTER DmaLowWaterMark;
+    T3_32BIT_REGISTER DmaHighWaterMark;
+
+    T3_32BIT_REGISTER RxCpuDmaAllocReq;
+    T3_32BIT_REGISTER RxCpuDmaAllocResp;
+    T3_32BIT_REGISTER TxCpuDmaAllocReq;
+    T3_32BIT_REGISTER TxCpuDmaAllocResp;
+
+    T3_32BIT_REGISTER Hwdiag[3];
+
+    /* Unused space. */
+    LM_UINT8 Unused[936];
+} T3_BUFFER_MANAGER, *PT3_BUFFER_MANAGER;
+
+
+
+/******************************************************************************/
+/* Read DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_READ_MODE_RESET                         BIT_0
+    #define DMA_READ_MODE_ENABLE                        BIT_1
+    #define DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE      BIT_2
+    #define DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE      BIT_3
+    #define DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE      BIT_4
+    #define DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE     BIT_5
+    #define DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE      BIT_6
+    #define DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE     BIT_7
+    #define DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE     BIT_8
+    #define DMA_READ_MODE_LONG_READ_ATTN_ENABLE         BIT_9
+    #define DMA_READ_MODE_SPLIT_ENABLE                  BIT_11
+    #define DMA_READ_MODE_SPLIT_RESET                   BIT_12
+    #define DMA_READ_MODE_FIFO_SIZE_128                 BIT_17
+    #define DMA_READ_MODE_FIFO_LONG_BURST               (BIT_16 | BIT_17)
+
+    T3_32BIT_REGISTER Status;
+    #define DMA_READ_STATUS_TARGET_ABORT_ATTN           BIT_2
+    #define DMA_READ_STATUS_MASTER_ABORT_ATTN           BIT_3
+    #define DMA_READ_STATUS_PARITY_ERROR_ATTN           BIT_4
+    #define DMA_READ_STATUS_ADDR_OVERFLOW_ATTN          BIT_5
+    #define DMA_READ_STATUS_FIFO_OVERRUN_ATTN           BIT_6
+    #define DMA_READ_STATUS_FIFO_UNDERRUN_ATTN          BIT_7
+    #define DMA_READ_STATUS_FIFO_OVERREAD_ATTN          BIT_8
+    #define DMA_READ_STATUS_LONG_READ_ATTN              BIT_9
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_DMA_READ, *PT3_DMA_READ;
+
+typedef union T3_CPU 
+{
+  struct
+  {
+    T3_32BIT_REGISTER mode;
+    #define CPU_MODE_HALT   BIT_10
+    #define CPU_MODE_RESET  BIT_0 
+    T3_32BIT_REGISTER state;
+    T3_32BIT_REGISTER EventMask;
+    T3_32BIT_REGISTER reserved1[4];
+    T3_32BIT_REGISTER PC;
+    T3_32BIT_REGISTER Instruction;
+    T3_32BIT_REGISTER SpadUnderflow;
+    T3_32BIT_REGISTER WatchdogClear;
+    T3_32BIT_REGISTER WatchdogVector;
+    T3_32BIT_REGISTER WatchdogSavedPC;
+    T3_32BIT_REGISTER HardwareBp;
+    T3_32BIT_REGISTER reserved2[3];
+    T3_32BIT_REGISTER WatchdogSavedState;    
+    T3_32BIT_REGISTER LastBrchAddr;    
+    T3_32BIT_REGISTER SpadUnderflowSet;    
+    T3_32BIT_REGISTER reserved3[(0x200-0x50)/4];
+    T3_32BIT_REGISTER Regs[32];
+    T3_32BIT_REGISTER reserved4[(0x400-0x280)/4];
+  }reg;
+}T3_CPU, *PT3_CPU;
+
+/******************************************************************************/
+/* Write DMA control registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_WRITE_MODE_RESET                        BIT_0
+    #define DMA_WRITE_MODE_ENABLE                       BIT_1
+    #define DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE     BIT_2
+    #define DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE     BIT_3
+    #define DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE     BIT_4
+    #define DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE    BIT_5
+    #define DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE     BIT_6
+    #define DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE    BIT_7
+    #define DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE    BIT_8
+    #define DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE        BIT_9
+    #define DMA_WRITE_MODE_RECEIVE_ACCELERATE           BIT_10
+
+    T3_32BIT_REGISTER Status;
+    #define DMA_WRITE_STATUS_TARGET_ABORT_ATTN          BIT_2
+    #define DMA_WRITE_STATUS_MASTER_ABORT_ATTN          BIT_3
+    #define DMA_WRITE_STATUS_PARITY_ERROR_ATTN          BIT_4
+    #define DMA_WRITE_STATUS_ADDR_OVERFLOW_ATTN         BIT_5
+    #define DMA_WRITE_STATUS_FIFO_OVERRUN_ATTN          BIT_6
+    #define DMA_WRITE_STATUS_FIFO_UNDERRUN_ATTN         BIT_7
+    #define DMA_WRITE_STATUS_FIFO_OVERREAD_ATTN         BIT_8
+    #define DMA_WRITE_STATUS_LONG_READ_ATTN             BIT_9
+
+    /* Unused space. */
+    LM_UINT8 Unused[1016];
+} T3_DMA_WRITE, *PT3_DMA_WRITE;
+
+
+
+/******************************************************************************/
+/* Mailbox registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Interrupt mailbox registers. */
+    T3_64BIT_REGISTER Interrupt[4];
+
+    /* General mailbox registers. */
+    T3_64BIT_REGISTER General[8];
+
+    /* Reload statistics mailbox. */
+    T3_64BIT_REGISTER ReloadStat;
+
+    /* Receive BD ring producer index registers. */
+    T3_64BIT_REGISTER RcvStdProdIdx;
+    T3_64BIT_REGISTER RcvJumboProdIdx;
+    T3_64BIT_REGISTER RcvMiniProdIdx;
+
+    /* Receive return ring consumer index registers. */
+    T3_64BIT_REGISTER RcvRetConIdx[16];
+
+    /* Send BD ring host producer index registers. */
+    T3_64BIT_REGISTER SendHostProdIdx[16];
+
+    /* Send BD ring nic producer index registers. */
+    T3_64BIT_REGISTER SendNicProdIdx[16];
+}T3_MAILBOX, *PT3_MAILBOX;
+
+typedef struct {
+    T3_MAILBOX Mailbox;
+
+    /* Priority mailbox registers. */
+    T3_32BIT_REGISTER HighPriorityEventVector;
+    T3_32BIT_REGISTER HighPriorityEventMask;
+    T3_32BIT_REGISTER LowPriorityEventVector;
+    T3_32BIT_REGISTER LowPriorityEventMask;
+
+    /* Unused space. */
+    LM_UINT8 Unused[496];
+} T3_GRC_MAILBOX, *PT3_GRC_MAILBOX;
+
+
+/******************************************************************************/
+/* Flow through queues. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Reset;
+    
+    LM_UINT8 Unused[12];
+
+    T3_32BIT_REGISTER DmaNormalReadFtqCtrl;
+    T3_32BIT_REGISTER DmaNormalReadFtqFullCnt;
+    T3_32BIT_REGISTER DmaNormalReadFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaNormalReadFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaHighReadFtqCtrl;
+    T3_32BIT_REGISTER DmaHighReadFtqFullCnt;
+    T3_32BIT_REGISTER DmaHighReadFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaHighReadFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaCompDiscardFtqCtrl;
+    T3_32BIT_REGISTER DmaCompDiscardFtqFullCnt;
+    T3_32BIT_REGISTER DmaCompDiscardFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaCompDiscardFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SendBdCompFtqCtrl;
+    T3_32BIT_REGISTER SendBdCompFtqFullCnt;
+    T3_32BIT_REGISTER SendBdCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SendBdCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SendDataInitiatorFtqCtrl;
+    T3_32BIT_REGISTER SendDataInitiatorFtqFullCnt;
+    T3_32BIT_REGISTER SendDataInitiatorFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SendDataInitiatorFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaNormalWriteFtqCtrl;
+    T3_32BIT_REGISTER DmaNormalWriteFtqFullCnt;
+    T3_32BIT_REGISTER DmaNormalWriteFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaNormalWriteFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER DmaHighWriteFtqCtrl;
+    T3_32BIT_REGISTER DmaHighWriteFtqFullCnt;
+    T3_32BIT_REGISTER DmaHighWriteFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER DmaHighWriteFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SwType1FtqCtrl;
+    T3_32BIT_REGISTER SwType1FtqFullCnt;
+    T3_32BIT_REGISTER SwType1FtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SwType1FtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SendDataCompFtqCtrl;
+    T3_32BIT_REGISTER SendDataCompFtqFullCnt;
+    T3_32BIT_REGISTER SendDataCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SendDataCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER HostCoalesceFtqCtrl;
+    T3_32BIT_REGISTER HostCoalesceFtqFullCnt;
+    T3_32BIT_REGISTER HostCoalesceFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER HostCoalesceFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER MacTxFtqCtrl;
+    T3_32BIT_REGISTER MacTxFtqFullCnt;
+    T3_32BIT_REGISTER MacTxFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER MacTxFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER MbufClustFreeFtqCtrl;
+    T3_32BIT_REGISTER MbufClustFreeFtqFullCnt;
+    T3_32BIT_REGISTER MbufClustFreeFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER MbufClustFreeFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvBdCompFtqCtrl;
+    T3_32BIT_REGISTER RcvBdCompFtqFullCnt;
+    T3_32BIT_REGISTER RcvBdCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvBdCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvListPlmtFtqCtrl;
+    T3_32BIT_REGISTER RcvListPlmtFtqFullCnt;
+    T3_32BIT_REGISTER RcvListPlmtFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvListPlmtFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqCtrl;
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqFullCnt;
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER RcvDataCompFtqCtrl;
+    T3_32BIT_REGISTER RcvDataCompFtqFullCnt;
+    T3_32BIT_REGISTER RcvDataCompFtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER RcvDataCompFtqFifoWritePeek;
+
+    T3_32BIT_REGISTER SwType2FtqCtrl;
+    T3_32BIT_REGISTER SwType2FtqFullCnt;
+    T3_32BIT_REGISTER SwType2FtqFifoEnqueueDequeue;
+    T3_32BIT_REGISTER SwType2FtqFifoWritePeek;
+
+    /* Unused space. */
+    LM_UINT8 Unused2[736];
+} T3_FTQ, *PT3_FTQ;
+
+
+
+/******************************************************************************/
+/* Message signaled interrupt registers. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+#define MSI_MODE_RESET       BIT_0
+#define MSI_MODE_ENABLE      BIT_1
+    T3_32BIT_REGISTER Status;
+
+    T3_32BIT_REGISTER MsiFifoAccess;
+
+    /* Unused space. */
+    LM_UINT8 Unused[1012];
+} T3_MSG_SIGNALED_INT, *PT3_MSG_SIGNALED_INT;
+
+
+
+/******************************************************************************/
+/* DMA Completion registes. */
+/******************************************************************************/
+
+typedef struct {
+    T3_32BIT_REGISTER Mode;
+    #define DMA_COMP_MODE_RESET                         BIT_0
+    #define DMA_COMP_MODE_ENABLE                        BIT_1
+
+    /* Unused space. */
+    LM_UINT8 Unused[1020];
+} T3_DMA_COMPLETION, *PT3_DMA_COMPLETION;
+
+
+
+/******************************************************************************/
+/* GRC registers. */
+/******************************************************************************/
+
+typedef struct {
+    /* Mode control register. */
+    T3_32BIT_REGISTER Mode;
+    #define GRC_MODE_UPDATE_ON_COALESCING               BIT_0
+    #define GRC_MODE_BYTE_SWAP_NON_FRAME_DATA           BIT_1
+    #define GRC_MODE_WORD_SWAP_NON_FRAME_DATA           BIT_2
+    #define GRC_MODE_BYTE_SWAP_DATA                     BIT_4
+    #define GRC_MODE_WORD_SWAP_DATA                     BIT_5
+    #define GRC_MODE_SPLIT_HEADER_MODE                  BIT_8
+    #define GRC_MODE_NO_FRAME_CRACKING                  BIT_9
+    #define GRC_MODE_INCLUDE_CRC                        BIT_10
+    #define GRC_MODE_ALLOW_BAD_FRAMES                   BIT_11
+    #define GRC_MODE_NO_INTERRUPT_ON_SENDS              BIT_13
+    #define GRC_MODE_NO_INTERRUPT_ON_RECEIVE            BIT_14
+    #define GRC_MODE_FORCE_32BIT_PCI_BUS_MODE           BIT_15
+    #define GRC_MODE_HOST_STACK_UP                      BIT_16
+    #define GRC_MODE_HOST_SEND_BDS                      BIT_17
+    #define GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM         BIT_20
+    #define GRC_MODE_NVRAM_WRITE_ENABLE                 BIT_21
+    #define GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM         BIT_23
+    #define GRC_MODE_INT_ON_TX_CPU_ATTN                 BIT_24
+    #define GRC_MODE_INT_ON_RX_CPU_ATTN                 BIT_25
+    #define GRC_MODE_INT_ON_MAC_ATTN                    BIT_26
+    #define GRC_MODE_INT_ON_DMA_ATTN                    BIT_27
+    #define GRC_MODE_INT_ON_FLOW_ATTN                   BIT_28
+    #define GRC_MODE_4X_NIC_BASED_SEND_RINGS            BIT_29
+    #define GRC_MODE_MULTICAST_FRAME_ENABLE             BIT_30
+
+    /* Misc configuration register. */
+    T3_32BIT_REGISTER MiscCfg;
+    #define GRC_MISC_CFG_CORE_CLOCK_RESET               BIT_0
+    #define GRC_MISC_PRESCALAR_TIMER_MASK               0xfe
+    #define GRC_MISC_BD_ID_MASK                         0x0001e000
+    #define GRC_MISC_BD_ID_5700                         0x0001e000
+    #define GRC_MISC_BD_ID_5701                         0x00000000
+    #define GRC_MISC_BD_ID_5703                         0x00000000
+    #define GRC_MISC_BD_ID_5703S                        0x00002000
+    #define GRC_MISC_BD_ID_5702FE                       0x00004000
+    #define GRC_MISC_BD_ID_5704                         0x00000000
+    #define GRC_MISC_BD_ID_5704CIOBE                    0x00004000
+    #define GRC_MISC_GPHY_KEEP_POWER_DURING_RESET       BIT_26
+
+    /* Miscellaneous local control register. */
+    T3_32BIT_REGISTER LocalCtrl;
+    #define GRC_MISC_LOCAL_CTRL_INT_ACTIVE              BIT_0
+    #define GRC_MISC_LOCAL_CTRL_CLEAR_INT               BIT_1
+    #define GRC_MISC_LOCAL_CTRL_SET_INT                 BIT_2
+    #define GRC_MISC_LOCAL_CTRL_INT_ON_ATTN             BIT_3
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT0             BIT_8
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT1             BIT_9
+    #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT2             BIT_10
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE0                BIT_11
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE1                BIT_12
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE2                BIT_13
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0            BIT_14
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1            BIT_15
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2            BIT_16
+    #define GRC_MISC_LOCAL_CTRL_ENABLE_EXT_MEMORY       BIT_17
+    #define GRC_MISC_LOCAL_CTRL_BANK_SELECT             BIT_21
+    #define GRC_MISC_LOCAL_CTRL_SSRAM_TYPE              BIT_22
+
+    #define GRC_MISC_MEMSIZE_256K     0
+    #define GRC_MISC_MEMSIZE_512K     (1 << 18)
+    #define GRC_MISC_MEMSIZE_1024K    (2 << 18)
+    #define GRC_MISC_MEMSIZE_2048K    (3 << 18)
+    #define GRC_MISC_MEMSIZE_4096K    (4 << 18)
+    #define GRC_MISC_MEMSIZE_8192K    (5 << 18)
+    #define GRC_MISC_MEMSIZE_16M      (6 << 18)
+    #define GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM            BIT_24
+
+
+    T3_32BIT_REGISTER Timer;
+
+    T3_32BIT_REGISTER RxCpuEvent;
+    T3_32BIT_REGISTER RxTimerRef;
+    T3_32BIT_REGISTER RxCpuSemaphore;
+    T3_32BIT_REGISTER RemoteRxCpuAttn;
+
+    T3_32BIT_REGISTER TxCpuEvent;
+    T3_32BIT_REGISTER TxTimerRef;
+    T3_32BIT_REGISTER TxCpuSemaphore;
+    T3_32BIT_REGISTER RemoteTxCpuAttn;
+
+    T3_64BIT_REGISTER MemoryPowerUp;
+
+    T3_32BIT_REGISTER EepromAddr;
+    #define SEEPROM_ADDR_WRITE       0
+    #define SEEPROM_ADDR_READ        (1 << 31)
+    #define SEEPROM_ADDR_RW_MASK     0x80000000
+    #define SEEPROM_ADDR_COMPLETE    (1 << 30)
+    #define SEEPROM_ADDR_FSM_RESET   (1 << 29)
+    #define SEEPROM_ADDR_DEV_ID(x)   (x << 26)
+    #define SEEPROM_ADDR_DEV_ID_MASK 0x1c000000
+    #define SEEPROM_ADDR_START       (1 << 25)
+    #define SEEPROM_ADDR_CLK_PERD(x) (x << 16)
+    #define SEEPROM_ADDR_ADDRESS(x)  (x & 0xfffc)
+    #define SEEPROM_ADDR_ADDRESS_MASK 0x0000ffff
+
+    #define SEEPROM_CLOCK_PERIOD        60
+    #define SEEPROM_CHIP_SIZE           (64 * 1024)
+
+    T3_32BIT_REGISTER EepromData;
+    T3_32BIT_REGISTER EepromCtrl;
+
+    T3_32BIT_REGISTER MdiCtrl;
+    T3_32BIT_REGISTER SepromDelay;
+
+    /* Unused space. */
+    LM_UINT8 Unused[948];
+} T3_GRC, *PT3_GRC;
+
+
+/******************************************************************************/
+/* NVRAM control registers. */
+/******************************************************************************/
+
+typedef struct
+{
+    T3_32BIT_REGISTER Cmd;
+    #define NVRAM_CMD_RESET                             BIT_0
+    #define NVRAM_CMD_DONE                              BIT_3
+    #define NVRAM_CMD_DO_IT                             BIT_4
+    #define NVRAM_CMD_WR                                BIT_5
+    #define NVRAM_CMD_RD                                BIT_NONE
+    #define NVRAM_CMD_ERASE                             BIT_6
+    #define NVRAM_CMD_FIRST                             BIT_7
+    #define NVRAM_CMD_LAST                              BIT_8
+
+    T3_32BIT_REGISTER Status;
+    T3_32BIT_REGISTER WriteData;
+
+    T3_32BIT_REGISTER Addr;
+    #define NVRAM_ADDRESS_MASK                          0xffffff
+
+    T3_32BIT_REGISTER ReadData;
+
+    /* Flash config 1 register. */
+    T3_32BIT_REGISTER Config1;
+    #define FLASH_INTERFACE_ENABLE                      BIT_0
+    #define FLASH_SSRAM_BUFFERED_MODE                  BIT_1
+    #define FLASH_PASS_THRU_MODE                        BIT_2
+    #define FLASH_BIT_BANG_MODE                         BIT_3
+    #define FLASH_COMPAT_BYPASS                         BIT_31
+
+    #define BUFFERED_FLASH (FLASH_INTERFACE_ENABLE | FLASH_SSRAM_BUFFERED_MODE)
+
+    /* Buffered flash (Atmel: AT45DB011B) specific information */
+    #define BUFFERED_FLASH_PAGE_POS         9
+    #define BUFFERED_FLASH_BYTE_ADDR_MASK   ((1<<BUFFERED_FLASH_PAGE_POS) - 1)
+    #define BUFFERED_FLASH_PAGE_SIZE        264
+    #define BUFFERED_FLASH_PHY_PAGE_SIZE    512
+
+    T3_32BIT_REGISTER Config2;
+    T3_32BIT_REGISTER Config3;
+    T3_32BIT_REGISTER SwArb;
+    #define SW_ARB_REQ_SET0                             BIT_0
+    #define SW_ARB_REQ_SET1                             BIT_1
+    #define SW_ARB_REQ_SET2                             BIT_2
+    #define SW_ARB_REQ_SET3                             BIT_3
+    #define SW_ARB_REQ_CLR0                             BIT_4
+    #define SW_ARB_REQ_CLR1                             BIT_5
+    #define SW_ARB_REQ_CLR2                             BIT_6
+    #define SW_ARB_REQ_CLR3                             BIT_7
+    #define SW_ARB_GNT0                                 BIT_8
+    #define SW_ARB_GNT1                                 BIT_9
+    #define SW_ARB_GNT2                                 BIT_10
+    #define SW_ARB_GNT3                                 BIT_11
+    #define SW_ARB_REQ0                                 BIT_12
+    #define SW_ARB_REQ1                                 BIT_13
+    #define SW_ARB_REQ2                                 BIT_14
+    #define SW_ARB_REQ3                                 BIT_15
+
+    /* Unused space. */
+    LM_UINT8 Unused[988];
+} T3_NVRAM, *PT3_NVRAM;
+
+
+/******************************************************************************/
+/* NIC's internal memory. */
+/******************************************************************************/
+
+typedef struct {
+    /* Page zero for the internal CPUs. */
+    LM_UINT8 PageZero[0x100];               /* 0x0000 */
+
+    /* Send RCBs. */
+    T3_RCB SendRcb[16];                     /* 0x0100 */
+
+    /* Receive Return RCBs. */
+    T3_RCB RcvRetRcb[16];                   /* 0x0200 */
+
+    /* Statistics block. */
+    T3_STATS_BLOCK StatsBlk;                /* 0x0300 */
+
+    /* Status block. */
+    T3_STATUS_BLOCK StatusBlk;              /* 0x0b00 */
+
+    /* Reserved for software. */
+    LM_UINT8 Reserved[1200];                /* 0x0b50 */
+
+    /* Unmapped region. */
+    LM_UINT8 Unmapped[4096];                /* 0x1000 */
+
+    /* DMA descriptors. */
+    LM_UINT8 DmaDesc[8192];                 /* 0x2000 */
+
+    /* Buffer descriptors. */
+    LM_UINT8 BufferDesc[16384];             /* 0x4000 */
+} T3_FIRST_32K_SRAM, *PT3_FIRST_32K_SRAM;
+
+
+
+/******************************************************************************/
+/* Memory layout. */
+/******************************************************************************/
+
+typedef struct {
+    /* PCI configuration registers. */
+    T3_PCI_CONFIGURATION PciCfg;
+
+    /* Unused. */
+    LM_UINT8 Unused1[0x100];                            /* 0x0100 */
+
+    /* Mailbox . */
+    T3_MAILBOX Mailbox;                                 /* 0x0200 */
+
+    /* MAC control registers. */
+    T3_MAC_CONTROL MacCtrl;                             /* 0x0400 */
+
+    /* Send data initiator control registers. */
+    T3_SEND_DATA_INITIATOR SndDataIn;                   /* 0x0c00 */
+
+    /* Send data completion Control registers. */
+    T3_SEND_DATA_COMPLETION SndDataComp;                /* 0x1000 */
+
+    /* Send BD ring selector. */
+    T3_SEND_BD_SELECTOR SndBdSel;                       /* 0x1400 */
+
+    /* Send BD initiator control registers. */
+    T3_SEND_BD_INITIATOR SndBdIn;                       /* 0x1800 */
+
+    /* Send BD completion control registers. */
+    T3_SEND_BD_COMPLETION SndBdComp;                    /* 0x1c00 */
+
+    /* Receive list placement control registers. */
+    T3_RCV_LIST_PLACEMENT RcvListPlmt;                  /* 0x2000 */
+
+    /* Receive Data and Receive BD Initiator Control. */
+    T3_RCV_DATA_BD_INITIATOR RcvDataBdIn;               /* 0x2400 */
+
+    /* Receive Data Completion Control */
+    T3_RCV_DATA_COMPLETION RcvDataComp;                 /* 0x2800 */
+
+    /* Receive BD Initiator Control Registers. */
+    T3_RCV_BD_INITIATOR RcvBdIn;                        /* 0x2c00 */
+
+    /* Receive BD Completion Control Registers. */
+    T3_RCV_BD_COMPLETION RcvBdComp;                     /* 0x3000 */
+
+    /* Receive list selector control registers. */
+    T3_RCV_LIST_SELECTOR RcvListSel;                    /* 0x3400 */
+
+    /* Mbuf cluster free registers. */
+    T3_MBUF_CLUSTER_FREE MbufClusterFree;               /* 0x3800 */
+
+    /* Host coalescing control registers. */
+    T3_HOST_COALESCING HostCoalesce;                    /* 0x3c00 */
+
+    /* Memory arbiter control registers. */
+    T3_MEM_ARBITER MemArbiter;                          /* 0x4000 */
+    
+    /* Buffer manger control registers. */
+    T3_BUFFER_MANAGER BufMgr;                           /* 0x4400 */
+
+    /* Read DMA control registers. */
+    T3_DMA_READ DmaRead;                                /* 0x4800 */
+
+    /* Write DMA control registers. */
+    T3_DMA_WRITE DmaWrite;                              /* 0x4c00 */
+
+    T3_CPU rxCpu;                                       /* 0x5000 */
+    T3_CPU txCpu;                                       /* 0x5400 */
+
+    /* Mailboxes. */
+    T3_GRC_MAILBOX GrcMailbox;                          /* 0x5800 */
+
+    /* Flow Through queues. */
+    T3_FTQ Ftq;                                         /* 0x5c00 */
+
+    /* Message signaled interrupt registes. */
+    T3_MSG_SIGNALED_INT Msi;                            /* 0x6000 */
+
+    /* DMA completion registers. */
+    T3_DMA_COMPLETION DmaComp;                          /* 0x6400 */
+
+    /* GRC registers. */
+    T3_GRC Grc;                                         /* 0x6800 */
+
+    /* Unused space. */
+    LM_UINT8 Unused2[1024];                             /* 0x6c00 */
+
+    /* NVRAM registers. */
+    T3_NVRAM Nvram;                                     /* 0x7000 */
+
+    /* Unused space. */
+    LM_UINT8 Unused3[3072];                             /* 0x7400 */
+    
+    /* The 32k memory window into the NIC's */
+    /* internal memory.  The memory window is */
+    /* controlled by the Memory Window Base */
+    /* Address register.  This register is located */
+    /* in the PCI configuration space. */
+    union {                                             /* 0x8000 */
+        T3_FIRST_32K_SRAM First32k;
+
+        /* Use the memory window base address register to determine the */
+        /* MBUF segment. */
+        LM_UINT32 Mbuf[32768/4];
+        LM_UINT32 MemBlock32K[32768/4];
+    } uIntMem;
+} T3_STD_MEM_MAP, *PT3_STD_MEM_MAP;
+
+
+/******************************************************************************/
+/* Adapter info. */
+/******************************************************************************/
+
+typedef struct
+{
+    LM_UINT16 Svid;
+    LM_UINT16 Ssid;
+    LM_UINT32 PhyId;
+    LM_UINT32 Serdes;   /* 0 = copper PHY, 1 = Serdes */
+} LM_ADAPTER_INFO, *PLM_ADAPTER_INFO;
+
+
+/******************************************************************************/
+/* Packet queues. */
+/******************************************************************************/
+
+DECLARE_QUEUE_TYPE(LM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT);
+DECLARE_QUEUE_TYPE(LM_TX_PACKET_Q, MAX_TX_PACKET_DESC_COUNT);
+
+
+
+/******************************************************************************/
+/* Tx counters. */
+/******************************************************************************/
+
+typedef struct {
+    LM_COUNTER TxPacketGoodCnt;
+    LM_COUNTER TxBytesGoodCnt;
+    LM_COUNTER TxPacketAbortedCnt;
+    LM_COUNTER NoSendBdLeftCnt;
+    LM_COUNTER NoMapRegisterLeftCnt;
+    LM_COUNTER TooManyFragmentsCnt;
+    LM_COUNTER NoTxPacketDescCnt;
+} LM_TX_COUNTERS, *PLM_TX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Rx counters. */
+/******************************************************************************/
+
+typedef struct {
+    LM_COUNTER RxPacketGoodCnt;
+    LM_COUNTER RxBytesGoodCnt;
+    LM_COUNTER RxPacketErrCnt;
+    LM_COUNTER RxErrCrcCnt;
+    LM_COUNTER RxErrCollCnt;
+    LM_COUNTER RxErrLinkLostCnt;
+    LM_COUNTER RxErrPhyDecodeCnt;
+    LM_COUNTER RxErrOddNibbleCnt;
+    LM_COUNTER RxErrMacAbortCnt;
+    LM_COUNTER RxErrShortPacketCnt;
+    LM_COUNTER RxErrNoResourceCnt;
+    LM_COUNTER RxErrLargePacketCnt;
+} LM_RX_COUNTERS, *PLM_RX_COUNTERS;
+
+
+
+/******************************************************************************/
+/* Receive producer rings. */
+/******************************************************************************/
+
+typedef enum {
+    T3_UNKNOWN_RCV_PROD_RING    = 0,
+    T3_STD_RCV_PROD_RING        = 1,
+    T3_MINI_RCV_PROD_RING       = 2,
+    T3_JUMBO_RCV_PROD_RING      = 3
+} T3_RCV_PROD_RING, *PT3_RCV_PROD_RING;
+
+
+
+/******************************************************************************/
+/* Packet descriptor. */
+/******************************************************************************/
+
+#define LM_PACKET_SIGNATURE_TX              0x6861766b
+#define LM_PACKET_SIGNATURE_RX              0x6b766168
+
+typedef struct _LM_PACKET {
+    /* Set in LM. */
+    LM_STATUS PacketStatus;
+
+    /* Set in LM for Rx, in UM for Tx. */
+    LM_UINT32 PacketSize;
+
+    LM_UINT16 Flags;
+
+    LM_UINT16 VlanTag;
+
+    union {
+        /* Send info. */
+        struct {
+            /* Set up by UM. */
+            LM_UINT32 FragCount;
+
+#if INCLUDE_TCP_SEG_SUPPORT
+            LM_UINT32 MaxSegmentSize;
+            LM_UINT32 LastFragmentChksum;
+#endif
+        } Tx;
+
+        /* Receive info. */
+        struct {
+            /* This descriptor belongs to either Std, Mini, or Jumbo ring. */
+            T3_RCV_PROD_RING RcvProdRing;
+
+            /* Receive buffer size */
+            LM_UINT32 RxBufferSize;
+
+            /* Checksum information. */
+            LM_UINT16 IpChecksum;
+            LM_UINT16 TcpUdpChecksum;
+
+        } Rx;
+    } u;
+} LM_PACKET;
+
+
+
+/******************************************************************************/
+/* Tigon3 device block. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK {
+    /* Memory view. */
+    PT3_STD_MEM_MAP pMemView;
+
+    /* Base address of the block of memory in which the LM_PACKET descriptors */
+    /* are allocated from. */
+    PLM_VOID pPacketDescBase;
+
+    LM_UINT32 MiscHostCtrl;
+    LM_UINT32 GrcLocalCtrl;
+    LM_UINT32 DmaReadWriteCtrl;
+    LM_UINT32 PciState;
+    LM_UINT32 ClockCtrl;
+
+    LM_UINT32 PowerLevel;
+    LM_UINT32 MiniPci;
+
+    /* Rx info */
+    LM_UINT32 RxStdDescCnt;
+    LM_UINT32 RxStdQueuedCnt;
+    LM_UINT32 RxStdProdIdx;
+
+    PT3_RCV_BD pRxStdBdVirt;
+    LM_PHYSICAL_ADDRESS RxStdBdPhy;
+
+    LM_UINT32 RxPacketDescCnt;
+    LM_RX_PACKET_Q RxPacketFreeQ;
+    LM_RX_PACKET_Q RxPacketReceivedQ;
+
+    /* Receive info. */
+    PT3_RCV_BD pRcvRetBdVirt;
+    LM_PHYSICAL_ADDRESS RcvRetBdPhy;
+    LM_UINT32 RcvRetConIdx;
+    LM_UINT32 RcvRetRcbEntryCount;
+    LM_UINT32 RcvRetRcbEntryCountMask;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    LM_UINT32 RxJumboDescCnt;
+    LM_UINT32 RxJumboBufferSize;
+    LM_UINT32 RxJumboQueuedCnt;
+
+    LM_UINT32 RxJumboProdIdx;
+
+    PT3_RCV_BD pRxJumboBdVirt;
+    LM_PHYSICAL_ADDRESS RxJumboBdPhy;
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    /* These values are used by the upper module to inform the protocol */
+    /* of the maximum transmit/receive packet size. */
+    LM_UINT32 TxMtu;    /* Does not include CRC. */
+    LM_UINT32 RxMtu;    /* Does not include CRC. */
+
+#if INCLUDE_TCP_SEG_SUPPORT
+    LM_UINT32 LargeSendMaxSize;
+    LM_UINT32 LargeSendMinNumSeg;
+#endif
+
+    /* We need to shadow the EMAC, Rx, Tx mode registers.  With B0 silicon, */
+    /* we may have problems reading any MAC registers in 10mb mode. */
+    LM_UINT32 MacMode;
+    LM_UINT32 RxMode;
+    LM_UINT32 TxMode;
+
+    /* MiMode register. */
+    LM_UINT32 MiMode;
+
+    /* Host coalesce mode register. */
+    LM_UINT32 CoalesceMode;
+
+    /* Send info. */
+    LM_UINT32 TxPacketDescCnt;
+
+    /* Tx info. */
+    LM_TX_PACKET_Q TxPacketFreeQ;
+    LM_TX_PACKET_Q TxPacketActiveQ;
+    LM_TX_PACKET_Q TxPacketXmittedQ;
+
+    /* Pointers to SendBd. */
+    PT3_SND_BD pSendBdVirt;
+    LM_PHYSICAL_ADDRESS SendBdPhy;  /* Only valid for Host based Send BD. */
+
+    /* Send producer and consumer indices. */
+    LM_UINT32 SendProdIdx;
+    LM_UINT32 SendConIdx;
+
+    /* Number of BD left. */
+    MM_ATOMIC_T SendBdLeft;
+
+    T3_SND_BD ShadowSendBd[T3_SEND_RCB_ENTRY_COUNT];
+
+    /* Counters. */
+    LM_RX_COUNTERS RxCounters;
+    LM_TX_COUNTERS TxCounters;
+
+    /* Host coalescing parameters. */
+    LM_UINT32 RxCoalescingTicks;
+    LM_UINT32 TxCoalescingTicks;
+    LM_UINT32 RxMaxCoalescedFrames;
+    LM_UINT32 TxMaxCoalescedFrames;
+    LM_UINT32 StatsCoalescingTicks;
+    LM_UINT32 RxCoalescingTicksDuringInt;
+    LM_UINT32 TxCoalescingTicksDuringInt;
+    LM_UINT32 RxMaxCoalescedFramesDuringInt;
+    LM_UINT32 TxMaxCoalescedFramesDuringInt;
+
+    /* DMA water marks. */
+    LM_UINT32 DmaMbufLowMark;
+    LM_UINT32 RxMacMbufLowMark;
+    LM_UINT32 MbufHighMark;
+
+    /* Status block. */
+    PT3_STATUS_BLOCK pStatusBlkVirt;
+    LM_PHYSICAL_ADDRESS StatusBlkPhy;
+
+    /* Statistics block. */
+    PT3_STATS_BLOCK pStatsBlkVirt;
+    LM_PHYSICAL_ADDRESS StatsBlkPhy;
+
+    /* Current receive mask. */
+    LM_UINT32 ReceiveMask;
+
+    /* Task offload capabilities. */
+    LM_TASK_OFFLOAD TaskOffloadCap;
+
+    /* Task offload selected. */
+    LM_TASK_OFFLOAD TaskToOffload;
+
+    LM_UINT32 FiberWolCapable;
+    LM_UINT32 WolLimit10;
+
+    /* Wake up capability. */
+    LM_WAKE_UP_MODE WakeUpModeCap;
+
+    /* Wake up capability. */
+    LM_WAKE_UP_MODE WakeUpMode;
+
+    /* Flow control. */
+    LM_FLOW_CONTROL FlowControlCap;
+    LM_FLOW_CONTROL FlowControl;
+
+    /* Enable or disable PCI MWI. */
+    LM_UINT32 EnableMWI;
+
+    /* Enable 5701 tagged status mode. */
+    LM_UINT32 UseTaggedStatus;
+
+    LM_UINT32 LastTag;
+
+    /* NIC will not compute the pseudo header checksum.  The driver or OS */
+    /* must seed the checksum field with the pseudo checksum. */
+    LM_UINT32 NoTxPseudoHdrChksum;
+
+    /* The receive checksum in the BD does not include the pseudo checksum. */
+    /* The OS or the driver must calculate the pseudo checksum and add it to */
+    /* the checksum in the BD. */
+    LM_UINT32 NoRxPseudoHdrChksum;
+
+    /* Current node address. */
+    LM_UINT8 NodeAddress[8];
+
+    /* The adapter's node address. */
+    LM_UINT8 PermanentNodeAddress[8];
+
+    /* Adapter info. */
+    LM_UINT16 BusNum;               // Init by the upper module.
+    LM_UINT8 DevNum;                // Init by the upper module.
+    LM_UINT8 FunctNum;              // Init by the upper module.
+    LM_UINT16 PciVendorId;
+    LM_UINT16 PciDeviceId;
+    LM_UINT32 BondId;
+    LM_UINT8 Irq;
+    LM_UINT8 IntPin;
+    LM_UINT8 CacheLineSize;
+    LM_UINT8 PciRevId;
+#if PCIX_TARGET_WORKAROUND
+    LM_UINT32 EnablePciXFix;
+#endif
+    LM_UINT32 UndiFix;
+    LM_UINT32 FlushPostedWrites;
+    LM_UINT32 RegReadBack;
+    LM_UINT32 PciCommandStatusWords;
+    LM_UINT32 ChipRevId;
+    LM_UINT16 SubsystemVendorId;
+    LM_UINT16 SubsystemId;
+    PLM_UINT8 pMappedMemBase;
+
+    /* Saved PCI configuration registers for restoring after a reset. */
+    LM_UINT32 SavedCacheLineReg;
+
+    /* Phy info. */
+    LM_UINT32 PhyAddr;
+    LM_UINT32 PhyId;
+
+    /* Requested phy settings. */
+    LM_LINE_SPEED RequestedLineSpeed;
+    LM_DUPLEX_MODE RequestedDuplexMode;
+
+    /* Disable auto-negotiation. */
+    LM_UINT32 DisableAutoNeg;
+
+    /* Ways for the MAC to get link change interrupt. */
+    LM_UINT32 PhyIntMode;
+    #define T3_PHY_INT_MODE_AUTO                        0
+    #define T3_PHY_INT_MODE_MI_INTERRUPT                1
+    #define T3_PHY_INT_MODE_LINK_READY                  2
+    #define T3_PHY_INT_MODE_AUTO_POLLING                3
+
+    /* Ways to determine link change status. */
+    LM_UINT32 LinkChngMode;
+    #define T3_LINK_CHNG_MODE_AUTO                      0
+    #define T3_LINK_CHNG_MODE_USE_STATUS_REG            1
+    #define T3_LINK_CHNG_MODE_USE_STATUS_BLOCK          2
+
+    /* LED mode. */
+    LM_UINT32 LedMode;
+
+    #define LED_MODE_AUTO                               0
+
+    /* 5700/01 LED mode. */
+    #define LED_MODE_THREE_LINK                         1
+    #define LED_MODE_LINK10                             2
+
+    /* 5703/02/04 LED mode. */
+    #define LED_MODE_OPEN_DRAIN                         1
+    #define LED_MODE_OUTPUT                             2
+
+    /* WOL Speed */
+    LM_UINT32 WolSpeed;
+    #define WOL_SPEED_10MB                              1
+    #define WOL_SPEED_100MB                             2
+
+    /* Reset the PHY on initialization. */
+    LM_UINT32 ResetPhyOnInit;
+    LM_UINT32 ResetPhyOnLinkDown;
+
+    LM_UINT32 RestoreOnWakeUp;
+    LM_LINE_SPEED WakeUpRequestedLineSpeed;
+    LM_DUPLEX_MODE WakeUpRequestedDuplexMode;
+    LM_UINT32 WakeUpDisableAutoNeg;
+
+    /* Current phy settings. */
+    LM_LINE_SPEED LineSpeed;
+    LM_LINE_SPEED OldLineSpeed;
+    LM_DUPLEX_MODE DuplexMode;
+    LM_STATUS LinkStatus;
+    LM_UINT32 advertising;
+    LM_UINT32 advertising1000;
+    LM_UINT32 No1000;
+
+    LM_UINT32 MacLoopBack;
+    LM_UINT32 PhyLoopBack;
+
+    /* Multicast address list. */
+    LM_UINT32 McEntryCount;
+    LM_UINT8 McTable[LM_MAX_MC_TABLE_SIZE][LM_MC_ENTRY_SIZE];
+
+    /* Use NIC or Host based send BD. */
+    LM_UINT32 NicSendBd;
+
+    LM_UINT32 EnableAsf;
+
+    /* Athlon fix. */
+    LM_UINT32 DelayPciGrant;
+
+    /* Enable OneDmaAtOnce */
+    LM_UINT32 OneDmaAtOnce;
+
+    /* Split Mode flags */
+    LM_UINT32 SplitModeEnable;
+    LM_UINT32 SplitModeMaxReq;
+
+    /* Init flag. */
+    LM_BOOL InitDone;
+
+    /* Shutdown flag.  Set by the upper module. */
+    LM_BOOL ShuttingDown;
+
+    /* Flag to determine whether to call LM_QueueRxPackets or not in */
+    /* LM_ResetAdapter routine. */
+    LM_BOOL QueueRxPackets;
+    LM_BOOL QueueAgain;
+    LM_BOOL RxBDLimit64;
+
+    LM_UINT32 MbufBase;
+    LM_UINT32 MbufSize;
+
+    /* TRUE if we have a SERDES PHY. */
+    LM_UINT32 EnableTbi;
+
+    /* Ethernet@WireSpeed. */
+    LM_UINT32 EnableWireSpeed;
+
+    LM_UINT32 EepromWp;
+
+#if INCLUDE_TBI_SUPPORT
+    /* Autoneg state info. */
+    AN_STATE_INFO AnInfo;
+    LM_UINT32 PollTbiLink;
+    LM_UINT32 IgnoreTbiLinkChange;
+#endif
+    char PartNo[24];
+    char BootCodeVer[16];
+    char BusSpeedStr[24];
+    unsigned long PhyCrcCount;
+
+} LM_DEVICE_BLOCK;
+
+
+#define T3_REG_CPU_VIEW               0xc0000000
+
+#define T3_BLOCK_DMA_RD               (1 << 0)
+#define T3_BLOCK_DMA_COMP             (1 << 1)
+#define T3_BLOCK_RX_BD_INITIATOR      (1 << 2)
+#define T3_BLOCK_RX_BD_COMP           (1 << 3)
+#define T3_BLOCK_DMA_WR               (1 << 4)
+#define T3_BLOCK_MSI_HANDLER          (1 << 5)
+#define T3_BLOCK_RX_LIST_PLMT         (1 << 6)
+#define T3_BLOCK_RX_LIST_SELECTOR     (1 << 7)
+#define T3_BLOCK_RX_DATA_INITIATOR    (1 << 8)
+#define T3_BLOCK_RX_DATA_COMP         (1 << 9)
+#define T3_BLOCK_HOST_COALESING       (1 << 10)
+#define T3_BLOCK_MAC_RX_ENGINE        (1 << 11)
+#define T3_BLOCK_MBUF_CLUSTER_FREE    (1 << 12)
+#define T3_BLOCK_SEND_BD_INITIATOR    (1 << 13)
+#define T3_BLOCK_SEND_BD_COMP         (1 << 14)
+#define T3_BLOCK_SEND_BD_SELECTOR     (1 << 15)
+#define T3_BLOCK_SEND_DATA_INITIATOR  (1 << 16)
+#define T3_BLOCK_SEND_DATA_COMP       (1 << 17)
+#define T3_BLOCK_MAC_TX_ENGINE        (1 << 18)
+#define T3_BLOCK_MEM_ARBITOR          (1 << 19)
+#define T3_BLOCK_MBUF_MANAGER         (1 << 20)
+#define T3_BLOCK_MAC_GLOBAL           (1 << 21)
+
+#define LM_ENABLE               1
+#define LM_DISABLE              2
+
+#define RX_CPU_EVT_SW0              0
+#define RX_CPU_EVT_SW1              1
+#define RX_CPU_EVT_RLP              2
+#define RX_CPU_EVT_SW3              3
+#define RX_CPU_EVT_RLS              4
+#define RX_CPU_EVT_SW4              5
+#define RX_CPU_EVT_RX_BD_COMP       6
+#define RX_CPU_EVT_SW5              7
+#define RX_CPU_EVT_RDI              8
+#define RX_CPU_EVT_DMA_WR           9
+#define RX_CPU_EVT_DMA_RD           10
+#define RX_CPU_EVT_SWQ              11
+#define RX_CPU_EVT_SW6              12
+#define RX_CPU_EVT_RDC              13
+#define RX_CPU_EVT_SW7              14
+#define RX_CPU_EVT_HOST_COALES      15
+#define RX_CPU_EVT_SW8              16
+#define RX_CPU_EVT_HIGH_DMA_WR      17
+#define RX_CPU_EVT_HIGH_DMA_RD      18
+#define RX_CPU_EVT_SW9              19
+#define RX_CPU_EVT_DMA_ATTN         20
+#define RX_CPU_EVT_LOW_P_MBOX       21
+#define RX_CPU_EVT_HIGH_P_MBOX      22
+#define RX_CPU_EVT_SW10             23
+#define RX_CPU_EVT_TX_CPU_ATTN      24
+#define RX_CPU_EVT_MAC_ATTN         25
+#define RX_CPU_EVT_RX_CPU_ATTN      26
+#define RX_CPU_EVT_FLOW_ATTN        27
+#define RX_CPU_EVT_SW11             28
+#define RX_CPU_EVT_TIMER            29
+#define RX_CPU_EVT_SW12             30
+#define RX_CPU_EVT_SW13             31
+
+/* RX-CPU event */
+#define RX_CPU_EVENT_SW_EVENT0      (1 << RX_CPU_EVT_SW0)
+#define RX_CPU_EVENT_SW_EVENT1      (1 << RX_CPU_EVT_SW1)
+#define RX_CPU_EVENT_RLP            (1 << RX_CPU_EVT_RLP)
+#define RX_CPU_EVENT_SW_EVENT3      (1 << RX_CPU_EVT_SW3)
+#define RX_CPU_EVENT_RLS            (1 << RX_CPU_EVT_RLS)
+#define RX_CPU_EVENT_SW_EVENT4      (1 << RX_CPU_EVT_SW4)
+#define RX_CPU_EVENT_RX_BD_COMP     (1 << RX_CPU_EVT_RX_BD_COMP)
+#define RX_CPU_EVENT_SW_EVENT5      (1 << RX_CPU_EVT_SW5)
+#define RX_CPU_EVENT_RDI            (1 << RX_CPU_EVT_RDI)
+#define RX_CPU_EVENT_DMA_WR         (1 << RX_CPU_EVT_DMA_WR)
+#define RX_CPU_EVENT_DMA_RD         (1 << RX_CPU_EVT_DMA_RD)
+#define RX_CPU_EVENT_SWQ            (1 << RX_CPU_EVT_SWQ)
+#define RX_CPU_EVENT_SW_EVENT6      (1 << RX_CPU_EVT_SW6)
+#define RX_CPU_EVENT_RDC            (1 << RX_CPU_EVT_RDC)
+#define RX_CPU_EVENT_SW_EVENT7      (1 << RX_CPU_EVT_SW7)
+#define RX_CPU_EVENT_HOST_COALES    (1 << RX_CPU_EVT_HOST_COALES)
+#define RX_CPU_EVENT_SW_EVENT8      (1 << RX_CPU_EVT_SW8)
+#define RX_CPU_EVENT_HIGH_DMA_WR    (1 << RX_CPU_EVT_HIGH_DMA_WR)
+#define RX_CPU_EVENT_HIGH_DMA_RD    (1 << RX_CPU_EVT_HIGH_DMA_RD)
+#define RX_CPU_EVENT_SW_EVENT9      (1 << RX_CPU_EVT_SW9)
+#define RX_CPU_EVENT_DMA_ATTN       (1 << RX_CPU_EVT_DMA_ATTN)
+#define RX_CPU_EVENT_LOW_P_MBOX     (1 << RX_CPU_EVT_LOW_P_MBOX)
+#define RX_CPU_EVENT_HIGH_P_MBOX    (1 << RX_CPU_EVT_HIGH_P_MBOX)
+#define RX_CPU_EVENT_SW_EVENT10     (1 << RX_CPU_EVT_SW10)
+#define RX_CPU_EVENT_TX_CPU_ATTN    (1 << RX_CPU_EVT_TX_CPU_ATTN)
+#define RX_CPU_EVENT_MAC_ATTN       (1 << RX_CPU_EVT_MAC_ATTN)
+#define RX_CPU_EVENT_RX_CPU_ATTN    (1 << RX_CPU_EVT_RX_CPU_ATTN)
+#define RX_CPU_EVENT_FLOW_ATTN      (1 << RX_CPU_EVT_FLOW_ATTN)
+#define RX_CPU_EVENT_SW_EVENT11     (1 << RX_CPU_EVT_SW11)
+#define RX_CPU_EVENT_TIMER          (1 << RX_CPU_EVT_TIMER)
+#define RX_CPU_EVENT_SW_EVENT12     (1 << RX_CPU_EVT_SW12)
+#define RX_CPU_EVENT_SW_EVENT13     (1 << RX_CPU_EVT_SW13)
+
+#define RX_CPU_MASK (RX_CPU_EVENT_SW_EVENT0 | \
+		     RX_CPU_EVENT_RLP | \
+		     RX_CPU_EVENT_RDI | \
+		     RX_CPU_EVENT_RDC)
+
+#define TX_CPU_EVT_SW0              0
+#define TX_CPU_EVT_SW1              1
+#define TX_CPU_EVT_SW2              2
+#define TX_CPU_EVT_SW3              3
+#define TX_CPU_EVT_TX_MAC           4
+#define TX_CPU_EVT_SW4              5
+#define TX_CPU_EVT_SBDC             6
+#define TX_CPU_EVT_SW5              7
+#define TX_CPU_EVT_SDI              8
+#define TX_CPU_EVT_DMA_WR           9
+#define TX_CPU_EVT_DMA_RD           10
+#define TX_CPU_EVT_SWQ              11
+#define TX_CPU_EVT_SW6              12
+#define TX_CPU_EVT_SDC              13
+#define TX_CPU_EVT_SW7              14
+#define TX_CPU_EVT_HOST_COALES      15
+#define TX_CPU_EVT_SW8              16
+#define TX_CPU_EVT_HIGH_DMA_WR      17
+#define TX_CPU_EVT_HIGH_DMA_RD      18
+#define TX_CPU_EVT_SW9              19
+#define TX_CPU_EVT_DMA_ATTN         20
+#define TX_CPU_EVT_LOW_P_MBOX       21
+#define TX_CPU_EVT_HIGH_P_MBOX      22
+#define TX_CPU_EVT_SW10             23
+#define TX_CPU_EVT_RX_CPU_ATTN      24
+#define TX_CPU_EVT_MAC_ATTN         25
+#define TX_CPU_EVT_TX_CPU_ATTN      26
+#define TX_CPU_EVT_FLOW_ATTN        27
+#define TX_CPU_EVT_SW11             28
+#define TX_CPU_EVT_TIMER            29
+#define TX_CPU_EVT_SW12             30
+#define TX_CPU_EVT_SW13             31
+
+
+/* TX-CPU event */
+#define TX_CPU_EVENT_SW_EVENT0      (1 << TX_CPU_EVT_SW0)
+#define TX_CPU_EVENT_SW_EVENT1      (1 << TX_CPU_EVT_SW1)
+#define TX_CPU_EVENT_SW_EVENT2      (1 << TX_CPU_EVT_SW2)
+#define TX_CPU_EVENT_SW_EVENT3      (1 << TX_CPU_EVT_SW3)
+#define TX_CPU_EVENT_TX_MAC         (1 << TX_CPU_EVT_TX_MAC)
+#define TX_CPU_EVENT_SW_EVENT4      (1 << TX_CPU_EVT_SW4)
+#define TX_CPU_EVENT_SBDC           (1 << TX_CPU_EVT_SBDC)
+#define TX_CPU_EVENT_SW_EVENT5      (1 << TX_CPU_EVT_SW5)
+#define TX_CPU_EVENT_SDI            (1 << TX_CPU_EVT_SDI)
+#define TX_CPU_EVENT_DMA_WR         (1 << TX_CPU_EVT_DMA_WR)
+#define TX_CPU_EVENT_DMA_RD         (1 << TX_CPU_EVT_DMA_RD)
+#define TX_CPU_EVENT_SWQ            (1 << TX_CPU_EVT_SWQ)
+#define TX_CPU_EVENT_SW_EVENT6      (1 << TX_CPU_EVT_SW6)
+#define TX_CPU_EVENT_SDC            (1 << TX_CPU_EVT_SDC)
+#define TX_CPU_EVENT_SW_EVENT7      (1 << TX_CPU_EVT_SW7)
+#define TX_CPU_EVENT_HOST_COALES    (1 << TX_CPU_EVT_HOST_COALES)
+#define TX_CPU_EVENT_SW_EVENT8      (1 << TX_CPU_EVT_SW8)
+#define TX_CPU_EVENT_HIGH_DMA_WR    (1 << TX_CPU_EVT_HIGH_DMA_WR)
+#define TX_CPU_EVENT_HIGH_DMA_RD    (1 << TX_CPU_EVT_HIGH_DMA_RD)
+#define TX_CPU_EVENT_SW_EVENT9      (1 << TX_CPU_EVT_SW9)
+#define TX_CPU_EVENT_DMA_ATTN       (1 << TX_CPU_EVT_DMA_ATTN)
+#define TX_CPU_EVENT_LOW_P_MBOX     (1 << TX_CPU_EVT_LOW_P_MBOX)
+#define TX_CPU_EVENT_HIGH_P_MBOX    (1 << TX_CPU_EVT_HIGH_P_MBOX)
+#define TX_CPU_EVENT_SW_EVENT10     (1 << TX_CPU_EVT_SW10)
+#define TX_CPU_EVENT_RX_CPU_ATTN    (1 << TX_CPU_EVT_RX_CPU_ATTN)
+#define TX_CPU_EVENT_MAC_ATTN       (1 << TX_CPU_EVT_MAC_ATTN)
+#define TX_CPU_EVENT_TX_CPU_ATTN    (1 << TX_CPU_EVT_TX_CPU_ATTN)
+#define TX_CPU_EVENT_FLOW_ATTN      (1 << TX_CPU_EVT_FLOW_ATTN)
+#define TX_CPU_EVENT_SW_EVENT11     (1 << TX_CPU_EVT_SW11)
+#define TX_CPU_EVENT_TIMER          (1 << TX_CPU_EVT_TIMER)
+#define TX_CPU_EVENT_SW_EVENT12     (1 << TX_CPU_EVT_SW12)
+#define TX_CPU_EVENT_SW_EVENT13     (1 << TX_CPU_EVT_SW13)
+
+
+#define TX_CPU_MASK (TX_CPU_EVENT_SW_EVENT0 | \
+		     TX_CPU_EVENT_SDI  | \
+		     TX_CPU_EVENT_SDC)
+
+
+#define T3_FTQ_TYPE1_UNDERFLOW_BIT   (1 << 29)
+#define T3_FTQ_TYPE1_PASS_BIT        (1 << 30)
+#define T3_FTQ_TYPE1_SKIP_BIT        (1 << 31)
+
+#define T3_FTQ_TYPE2_UNDERFLOW_BIT   (1 << 13)
+#define T3_FTQ_TYPE2_PASS_BIT        (1 << 14)
+#define T3_FTQ_TYPE2_SKIP_BIT        (1 << 15)
+
+#define T3_QID_DMA_READ               1
+#define T3_QID_DMA_HIGH_PRI_READ      2
+#define T3_QID_DMA_COMP_DX            3
+#define T3_QID_SEND_BD_COMP           4
+#define T3_QID_SEND_DATA_INITIATOR    5
+#define T3_QID_DMA_WRITE              6
+#define T3_QID_DMA_HIGH_PRI_WRITE     7
+#define T3_QID_SW_TYPE_1              8
+#define T3_QID_SEND_DATA_COMP         9
+#define T3_QID_HOST_COALESCING        10
+#define T3_QID_MAC_TX                 11
+#define T3_QID_MBUF_CLUSTER_FREE      12
+#define T3_QID_RX_BD_COMP             13
+#define T3_QID_RX_LIST_PLM            14
+#define T3_QID_RX_DATA_BD_INITIATOR   15
+#define T3_QID_RX_DATA_COMP           16
+#define T3_QID_SW_TYPE2               17
+
+LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice,
+                          PT3_FWIMG_INFO pFwImg,
+                          LM_UINT32 LoadCpu,
+                          LM_UINT32 StartCpu);
+
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+/* MAC register access. */
+LM_UINT32 LM_RegRd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register);
+
+LM_VOID LM_RegWr(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register,
+    LM_UINT32 Value32, LM_UINT32 ReadBack);
+
+LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register);
+LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register,
+    LM_UINT32 Value32);
+
+/* MAC memory access. */
+LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr);
+
+LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr,
+    LM_UINT32 Value32);
+
+#define MB_REG_WR(pDevice, OffsetName, Value32)                               \
+    ((pDevice)->UndiFix) ?                                                    \
+        LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600,     \
+            Value32) :                                                        \
+        (void) MM_MEMWRITEL(&((pDevice)->pMemView->OffsetName), Value32)
+
+#define MB_REG_RD(pDevice, OffsetName)                                        \
+    (((pDevice)->UndiFix) ?                                                   \
+        LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600) :   \
+        MM_MEMREADL(&((pDevice)->pMemView->OffsetName)))
+
+#define REG_RD(pDevice, OffsetName)                                         \
+    LM_RegRd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName))
+
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+    LM_RegWr(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32, TRUE)
+
+#define RAW_REG_WR(pDevice, OffsetName, Value32)                            \
+    LM_RegWr(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32, FALSE)
+
+#define REG_RD_OFFSET(pDevice, Offset)                                      \
+    MM_MEMREADL(((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+#define REG_WR_OFFSET(pDevice, Offset, Value32)                             \
+    MM_MEMWRITEL(((LM_UINT8 *) (pDevice)->pMemView + Offset), Value32)
+
+#define MEM_RD(pDevice, AddrName)                                           \
+    LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName))
+#define MEM_WR(pDevice, AddrName, Value32)                                  \
+    LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32)
+
+#define MEM_RD_OFFSET(pDevice, Offset)                                      \
+    LM_MemRdInd(pDevice, Offset)
+#define MEM_WR_OFFSET(pDevice, Offset, Value32)                             \
+    LM_MemWrInd(pDevice, Offset, Value32)
+				
+
+#endif /* TIGON3_H */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/.depend orig/drivers/net/bcm4400/.depend
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/.depend	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/.depend	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,53 @@
+b44.h: \
+   b44lm.h
+	@touch b44.h
+b44lm.o: b44lm.c \
+   b44mm.h
+b44lm.h: \
+   b44queue.h
+	@touch b44lm.h
+b44mm.h: \
+   $(wildcard /usr/src/wolk2/include/config/smp.h) \
+   $(wildcard /usr/src/wolk2/include/config/modversions.h) \
+   /usr/src/wolk2/include/linux/version.h \
+   /usr/src/wolk2/include/linux/module.h \
+   /usr/src/wolk2/include/linux/kernel.h \
+   /usr/src/wolk2/include/linux/sched.h \
+   /usr/src/wolk2/include/linux/string.h \
+   /usr/src/wolk2/include/linux/timer.h \
+   /usr/src/wolk2/include/linux/errno.h \
+   /usr/src/wolk2/include/linux/ioport.h \
+   /usr/src/wolk2/include/linux/slab.h \
+   /usr/src/wolk2/include/linux/interrupt.h \
+   /usr/src/wolk2/include/linux/pci.h \
+   /usr/src/wolk2/include/linux/init.h \
+   /usr/src/wolk2/include/linux/netdevice.h \
+   /usr/src/wolk2/include/linux/etherdevice.h \
+   /usr/src/wolk2/include/linux/skbuff.h \
+   /usr/src/wolk2/include/asm/processor.h \
+   /usr/src/wolk2/include/asm/bitops.h \
+   /usr/src/wolk2/include/asm/io.h \
+   /usr/src/wolk2/include/asm/unaligned.h \
+   /usr/src/wolk2/include/linux/delay.h \
+   /usr/src/wolk2/include/asm/byteorder.h \
+   /usr/src/wolk2/include/linux/time.h \
+   /usr/src/wolk2/include/linux/ethtool.h \
+   /usr/src/wolk2/include/asm/uaccess.h \
+   $(wildcard /usr/src/wolk2/include/config/proc/fs.h) \
+   /usr/src/wolk2/include/linux/smp_lock.h \
+   /usr/src/wolk2/include/linux/proc_fs.h \
+   b44lm.h \
+   b44queue.h \
+   b44.h \
+   $(wildcard /usr/src/wolk2/include/config/highmem.h) \
+   $(wildcard /usr/src/wolk2/include/config/x86.h) \
+   $(wildcard /usr/src/wolk2/include/config/highmem64g.h)
+	@touch b44mm.h
+b44proc.o: b44proc.c \
+   b44mm.h
+b44um.o: b44um.c \
+   b44mm.h
+.PRECIOUS:	b44.h \
+	b44lm.h \
+	b44mm.h \
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/Makefile orig/drivers/net/bcm4400/Makefile
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/Makefile	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,13 @@
+
+#
+# Makefile for linux/drivers/net/bcm4400
+#
+
+O_TARGET := bcm4400.o
+obj-y    := b44um.o b44proc.o b44lm.o
+obj-m    := $(O_TARGET)
+
+EXTRA_CFLAGS = -DDBG=0
+
+include $(TOPDIR)/Rules.make
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44.h orig/drivers/net/bcm4400/b44.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/b44.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,1108 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM4400 Linux Network Driver, Copyright (c) 2002 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef B44_H
+#define B44_H
+
+#include "b44lm.h"
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+/* Maxim number of packet descriptors used for sending packets. */
+#define MAX_TX_PACKET_DESC_COUNT            512
+#define DEFAULT_TX_PACKET_DESC_COUNT        64
+
+#define MAX_RX_PACKET_DESC_COUNT            512
+#define DEFAULT_RX_PACKET_DESC_COUNT        64
+
+#define BIT_0                               0x01
+#define BIT_1                               0x02
+#define BIT_2                               0x04
+#define BIT_3                               0x08
+#define BIT_4                               0x10
+#define BIT_5                               0x20
+#define BIT_6                               0x40
+#define BIT_7                               0x80
+#define BIT_8                               0x100
+#define BIT_9                               0x200
+#define BIT_10                              0x400
+#define BIT_11                              0x800
+#define BIT_12                              0x1000
+#define BIT_13                              0x2000
+#define BIT_14                              0x4000
+#define BIT_15                              0x8000
+#define BIT_16                              0x10000
+#define BIT_17                              0x20000
+#define BIT_18                              0x40000
+#define BIT_19                              0x80000
+#define BIT_20                              0x100000
+#define BIT_21                              0x200000
+#define BIT_22                              0x400000
+#define BIT_23                              0x800000
+#define BIT_24                              0x1000000
+#define BIT_25                              0x2000000
+#define BIT_26                              0x4000000
+#define BIT_27                              0x8000000
+#define BIT_28                              0x10000000
+#define BIT_29                              0x20000000
+#define BIT_30                              0x40000000
+#define BIT_31                              0x80000000
+
+#define ROUNDUP(x, y)        ((((LM_UINT32)(x)+((y)-1))/(y))*(y))
+
+/******************************************************************************/
+/* MII registers. */
+/******************************************************************************/
+
+/* Control register. */
+#define PHY_CTRL_REG                                0x00
+
+#define PHY_CTRL_SPEED_MASK                         (BIT_6 | BIT_13)
+#define PHY_CTRL_SPEED_SELECT_10MBPS                BIT_NONE
+#define PHY_CTRL_SPEED_SELECT_100MBPS               BIT_13
+#define PHY_CTRL_SPEED_SELECT_1000MBPS              BIT_6
+#define PHY_CTRL_COLLISION_TEST_ENABLE              BIT_7
+#define PHY_CTRL_FULL_DUPLEX_MODE                   BIT_8
+#define PHY_CTRL_RESTART_AUTO_NEG                   BIT_9
+#define PHY_CTRL_ISOLATE_PHY                        BIT_10
+#define PHY_CTRL_LOWER_POWER_MODE                   BIT_11
+#define PHY_CTRL_AUTO_NEG_ENABLE                    BIT_12
+#define PHY_CTRL_LOOPBACK_MODE                      BIT_14
+#define PHY_CTRL_PHY_RESET                          BIT_15
+
+
+/* Status register. */
+#define PHY_STATUS_REG                              0x01
+
+#define PHY_STATUS_LINK_PASS                        BIT_2
+#define PHY_STATUS_AUTO_NEG_COMPLETE                BIT_5
+
+
+/* Phy Id registers. */
+#define PHY_ID1_REG                                 0x02
+#define PHY_ID1_OUI_MASK                            0xffff
+
+#define PHY_ID2_REG                                 0x03
+#define PHY_ID2_REV_MASK                            0x000f
+#define PHY_ID2_MODEL_MASK                          0x03f0
+#define PHY_ID2_OUI_MASK                            0xfc00
+
+
+/* Auto-negotiation advertisement register. */
+#define PHY_AN_AD_REG                               0x04
+
+#define PHY_AN_AD_ASYM_PAUSE                        BIT_11
+#define PHY_AN_AD_PAUSE_CAPABLE                     BIT_10
+#define PHY_AN_AD_10BASET_HALF                      BIT_5
+#define PHY_AN_AD_10BASET_FULL                      BIT_6
+#define PHY_AN_AD_100BASETX_HALF                    BIT_7
+#define PHY_AN_AD_100BASETX_FULL                    BIT_8
+#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD            0x01
+
+#define PHY_AN_AD_ALL_SPEEDS (PHY_AN_AD_10BASET_HALF | \
+    PHY_AN_AD_10BASET_FULL | PHY_AN_AD_100BASETX_HALF | \
+    PHY_AN_AD_100BASETX_FULL)
+
+/* Auto-negotiation Link Partner Ability register. */
+#define PHY_LINK_PARTNER_ABILITY_REG                0x05
+
+#define PHY_LINK_PARTNER_ASYM_PAUSE                 BIT_11
+#define PHY_LINK_PARTNER_PAUSE_CAPABLE              BIT_10
+
+
+#define	STAT_REMFAULT	(1 << 4)	/* remote fault */
+#define	STAT_LINK	(1 << 2)	/* link status */
+#define	STAT_JAB	(1 << 1)	/* jabber detected */
+#define	AUX_FORCED	(1 << 2)	/* forced 10/100 */
+#define	AUX_SPEED	(1 << 1)	/* speed 0=10mbps 1=100mbps */
+#define	AUX_DUPLEX	(1 << 0)	/* duplex 0=half 1=full */
+
+
+/******************************************************************************/
+/* Register definitions. */
+/******************************************************************************/
+
+typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER;
+typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER;
+typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER;
+
+/*
+ * Each DMA processor consists of a transmit channel and a receive channel.
+ */
+typedef volatile struct {
+	/* transmit channel */
+	LM_UINT32	xmtcontrol;			/* enable, et al */
+	LM_UINT32	xmtaddr;			/* descriptor ring base address (4K aligned) */
+	LM_UINT32	xmtptr;				/* last descriptor posted to chip */
+	LM_UINT32	xmtstatus;			/* current active descriptor, et al */
+
+	/* receive channel */
+	LM_UINT32	rcvcontrol;			/* enable, et al */
+	LM_UINT32	rcvaddr;			/* descriptor ring base address (4K aligned) */
+	LM_UINT32	rcvptr;				/* last descriptor posted to chip */
+	LM_UINT32	rcvstatus;			/* current active descriptor, et al */
+
+	/* diag access */
+	LM_UINT32	fifoaddr;			/* diag address */
+	LM_UINT32	fifodatalow;			/* low 32bits of data */
+	LM_UINT32	fifodatahigh;			/* high 32bits of data */
+	LM_UINT32	pad;				/* reserved */
+} dmaregs_t;
+
+/* transmit channel control */
+#define	XC_XE		((LM_UINT32)1 << 0)	/* transmit enable */
+#define	XC_SE		((LM_UINT32)1 << 1)	/* transmit suspend request */
+#define	XC_LE		((LM_UINT32)1 << 2)	/* loopback enable */
+#define	XC_FPRI		((LM_UINT32)1 << 3)	/* fair priority */
+#define	XC_FL		((LM_UINT32)1 << 4)	/* flush request */
+
+/* transmit descriptor table pointer */
+#define	XP_LD_MASK	0xfff			/* last valid descriptor */
+
+/* transmit channel status */
+#define	XS_CD_MASK	0x0fff			/* current descriptor pointer */
+#define	XS_XS_MASK	0xf000			/* transmit state */
+#define	XS_XS_SHIFT	12
+#define	XS_XS_DISABLED	0x0000			/* disabled */
+#define	XS_XS_ACTIVE	0x1000			/* active */
+#define	XS_XS_IDLE	0x2000			/* idle wait */
+#define	XS_XS_STOPPED	0x3000			/* stopped */
+#define	XS_XS_SUSP	0x4000			/* suspend pending */
+#define	XS_XE_MASK	0xf0000			/* transmit errors */
+#define	XS_XE_SHIFT	16
+#define	XS_XE_NOERR	0x00000			/* no error */
+#define	XS_XE_DPE	0x10000			/* descriptor protocol error */
+#define	XS_XE_DFU	0x20000			/* data fifo underrun */
+#define	XS_XE_BEBR	0x30000			/* bus error on buffer read */
+#define	XS_XE_BEDA	0x40000			/* bus error on descriptor access */
+#define	XS_FL		((LM_UINT32)1 << 20)	/* flushed */
+
+/* receive channel control */
+#define	RC_RE		((LM_UINT32)1 << 0)	/* receive enable */
+#define	RC_RO_MASK	0xfe			/* receive frame offset */
+#define	RC_RO_SHIFT	1
+
+/* receive descriptor table pointer */
+#define	RP_LD_MASK	0xfff			/* last valid descriptor */
+
+/* receive channel status */
+#define	RS_CD_MASK	0x0fff			/* current descriptor pointer */
+#define	RS_RS_MASK	0xf000			/* receive state */
+#define	RS_RS_SHIFT	12
+#define	RS_RS_DISABLED	0x0000			/* disabled */
+#define	RS_RS_ACTIVE	0x1000			/* active */
+#define	RS_RS_IDLE	0x2000			/* idle wait */
+#define	RS_RS_STOPPED	0x3000			/* reserved */
+#define	RS_RE_MASK	0xf0000			/* receive errors */
+#define	RS_RE_SHIFT	16
+#define	RS_RE_NOERR	0x00000			/* no error */
+#define	RS_RE_DPE	0x10000			/* descriptor protocol error */
+#define	RS_RE_DFO	0x20000			/* data fifo overflow */
+#define	RS_RE_BEBW	0x30000			/* bus error on buffer write */
+#define	RS_RE_BEDA	0x40000			/* bus error on descriptor access */
+
+/* fifoaddr */
+#define	FA_OFF_MASK	0xffff			/* offset */
+#define	FA_SEL_MASK	0xf0000			/* select */
+#define	FA_SEL_SHIFT	16
+#define	FA_SEL_XDD	0x00000			/* transmit dma data */
+#define	FA_SEL_XDP	0x10000			/* transmit dma pointers */
+#define	FA_SEL_RDD	0x40000			/* receive dma data */
+#define	FA_SEL_RDP	0x50000			/* receive dma pointers */
+#define	FA_SEL_XFD	0x80000			/* transmit fifo data */
+#define	FA_SEL_XFP	0x90000			/* transmit fifo pointers */
+#define	FA_SEL_RFD	0xc0000			/* receive fifo data */
+#define	FA_SEL_RFP	0xd0000			/* receive fifo pointers */
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+typedef volatile struct {
+	LM_UINT32	ctrl;		/* misc control bits & bufcount */
+	LM_UINT32	addr;		/* data buffer address */
+} dmadd_t;
+
+/*
+ * Each descriptor ring must be 4096byte aligned
+ * and fit within a single 4096byte page.
+ */
+#define	DMAMAXRINGSZ	4096
+#define	DMARINGALIGN	4096
+
+/* control flags */
+#define	CTRL_BC_MASK	0x1fff			/* buffer byte count */
+#define	CTRL_EOT	((LM_UINT32)1 << 28)	/* end of descriptor table */
+#define	CTRL_IOC	((LM_UINT32)1 << 29)	/* interrupt on completion */
+#define	CTRL_EOF	((LM_UINT32)1 << 30)	/* end of frame */
+#define	CTRL_SOF	((LM_UINT32)1 << 31)	/* start of frame */
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define	CTRL_CORE_MASK	0x0ff00000
+
+
+#define	BCMENET_NFILTERS	64		/* # ethernet address filter entries */
+#define	BCMENET_MCHASHBASE	0x200		/* multicast hash filter base address */
+#define	BCMENET_MCHASHSIZE	256		/* multicast hash filter size in bytes */
+#define	BCMENET_MAX_DMA		4096		/* chip has 12 bits of DMA addressing */
+
+/* power management event wakeup pattern constants */
+#define	BCMENET_NPMP		4		/* chip supports 4 wakeup patterns */
+#define	BCMENET_PMPBASE		0x400		/* wakeup pattern base address */
+#define	BCMENET_PMPSIZE		0x80		/* 128bytes each pattern */
+#define	BCMENET_PMMBASE		0x600		/* wakeup mask base address */
+#define	BCMENET_PMMSIZE		0x10		/* 128bits each mask */
+
+/* PCI config space "back door" access registers */
+#define BCMENET_BACK_DOOR_ADDR	0xa0
+#define BCMENET_BACK_DOOR_DATA	0xa4
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+#endif	/* PAD */
+
+/*
+ * EMAC MIB Registers
+ */
+typedef volatile struct {
+	LM_UINT32 tx_good_octets;
+	LM_UINT32 tx_good_pkts;
+	LM_UINT32 tx_octets;
+	LM_UINT32 tx_pkts;
+	LM_UINT32 tx_broadcast_pkts;
+	LM_UINT32 tx_multicast_pkts;
+	LM_UINT32 tx_len_64;
+	LM_UINT32 tx_len_65_to_127;
+	LM_UINT32 tx_len_128_to_255;
+	LM_UINT32 tx_len_256_to_511;
+	LM_UINT32 tx_len_512_to_1023;
+	LM_UINT32 tx_len_1024_to_max;
+	LM_UINT32 tx_jabber_pkts;
+	LM_UINT32 tx_oversize_pkts;
+	LM_UINT32 tx_fragment_pkts;
+	LM_UINT32 tx_underruns;
+	LM_UINT32 tx_total_cols;
+	LM_UINT32 tx_single_cols;
+	LM_UINT32 tx_multiple_cols;
+	LM_UINT32 tx_excessive_cols;
+	LM_UINT32 tx_late_cols;
+	LM_UINT32 tx_defered;
+	LM_UINT32 tx_carrier_lost;
+	LM_UINT32 tx_pause_pkts;
+	LM_UINT32 PAD[8];
+
+	LM_UINT32 rx_good_octets;
+	LM_UINT32 rx_good_pkts;
+	LM_UINT32 rx_octets;
+	LM_UINT32 rx_pkts;
+	LM_UINT32 rx_broadcast_pkts;
+	LM_UINT32 rx_multicast_pkts;
+	LM_UINT32 rx_len_64;
+	LM_UINT32 rx_len_65_to_127;
+	LM_UINT32 rx_len_128_to_255;
+	LM_UINT32 rx_len_256_to_511;
+	LM_UINT32 rx_len_512_to_1023;
+	LM_UINT32 rx_len_1024_to_max;
+	LM_UINT32 rx_jabber_pkts;
+	LM_UINT32 rx_oversize_pkts;
+	LM_UINT32 rx_fragment_pkts;
+	LM_UINT32 rx_missed_pkts;
+	LM_UINT32 rx_crc_align_errs;
+	LM_UINT32 rx_undersize;
+	LM_UINT32 rx_crc_errs;
+	LM_UINT32 rx_align_errs;
+	LM_UINT32 rx_symbol_errs;
+	LM_UINT32 rx_pause_pkts;
+	LM_UINT32 rx_nonpause_pkts;
+} bcmenetmib_t;
+
+#define SB_ENUM_BASE    0x18000000
+#define SB_CORE_SIZE    0x1000
+#define	SBCONFIGOFF	0xf00			/* core register space offset in bytes */
+#define	SBCONFIGSIZE	256			/* size in bytes */
+
+/*
+ * Sonics Configuration Space Registers.
+ */
+typedef volatile struct _sbconfig {
+	LM_UINT32	PAD[2];
+	LM_UINT32	sbipsflag;		/* initiator port ocp slave flag */
+	LM_UINT32	PAD[3];
+	LM_UINT32	sbtpsflag;		/* target port ocp slave flag */
+	LM_UINT32	PAD[17];
+	LM_UINT32	sbadmatch3;		/* address match3 */
+	LM_UINT32	PAD;
+	LM_UINT32	sbadmatch2;		/* address match2 */
+	LM_UINT32	PAD;
+	LM_UINT32	sbadmatch1;		/* address match1 */
+	LM_UINT32	PAD[7];
+	LM_UINT32	sbimstate;		/* initiator agent state */
+	LM_UINT32	sbintvec;		/* interrupt mask */
+	LM_UINT32	sbtmstatelow;		/* target state */
+	LM_UINT32	sbtmstatehigh;		/* target state */
+	LM_UINT32	sbbwa0;			/* bandwidth allocation table0 */
+	LM_UINT32	PAD;
+	LM_UINT32	sbimconfiglow;		/* initiator configuration */
+	LM_UINT32	sbimconfighigh;		/* initiator configuration */
+	LM_UINT32	sbadmatch0;		/* address match0 */
+	LM_UINT32	PAD;
+	LM_UINT32	sbtmconfiglow;		/* target configuration */
+	LM_UINT32	sbtmconfighigh;		/* target configuration */
+	LM_UINT32	sbbconfig;		/* broadcast configuration */
+	LM_UINT32	PAD;
+	LM_UINT32	sbbstate;		/* broadcast state */
+	LM_UINT32	PAD[3];
+	LM_UINT32	sbactcnfg;		/* activate configuration */
+	LM_UINT32	PAD[3];
+	LM_UINT32	sbflagst;		/* current sbflags */
+	LM_UINT32	PAD[3];
+	LM_UINT32	sbidlow;		/* identification */
+	LM_UINT32	sbidhigh;		/* identification */
+} sbconfig_t;
+
+/* XXX 4710-specific and should be deleted since they can be read from sbtpsflag */
+/* interrupt sbFlags */
+#define	SBFLAG_PCI	0
+#define	SBFLAG_ENET0	1
+#define	SBFLAG_ILINE20	2
+#define	SBFLAG_CODEC	3
+#define	SBFLAG_USB	4
+#define	SBFLAG_EXTIF	5
+#define	SBFLAG_ENET1	6
+
+/* sbipsflag */
+#define SBIPSFLAG	0x08		/* offset */
+#define	SBIPS_INT1_MASK	0x3f		/* which sbflags get routed to mips interrupt 1 */
+#define	SBIPS_INT1_SHIFT	0
+#define	SBIPS_INT2_MASK	0x3f00		/* which sbflags get routed to mips interrupt 2 */
+#define	SBIPS_INT2_SHIFT	8
+#define	SBIPS_INT3_MASK	0x3f0000	/* which sbflags get routed to mips interrupt 3 */
+#define	SBIPS_INT3_SHIFT	16
+#define	SBIPS_INT4_MASK	0x3f000000	/* which sbflags get routed to mips interrupt 4 */
+#define	SBIPS_INT4_SHIFT	24
+
+/* sbtpsflag */
+#define SBTPSFLAG	0x18		/* offset */
+#define	SBTPS_NUM0_MASK	0x3f		/* interrupt sbFlag # generated by this core */
+#define	SBTPS_F0EN0	0x40		/* interrupt is always sent on the backplane */
+
+/* sbadmatch */
+#define SBADMATCH3	0x60		/* offset */
+#define SBADMATCH2	0x68		/* offset */
+#define SBADMATCH1	0x70		/* offset */
+
+/* sbimstate */
+#define SBIMSTATE	0x90		/* offset */
+#define	SBIM_PC		0xf		/* pipecount */
+#define	SBIM_AP_MASK	0x30		/* arbitration policy */
+#define	SBIM_AP_BOTH	0x00		/* use both timeslaces and token */
+#define	SBIM_AP_TS	0x10		/* use timesliaces only */
+#define	SBIM_AP_TK	0x20		/* use token only */
+#define	SBIM_AP_RSV	0x30		/* reserved */
+#define	SBIM_IBE	0x20000		/* inbanderror */
+#define	SBIM_TO		0x40000		/* timeout */
+
+/* sbintvec */
+#define SBINTVEC	0x94		/* offset */
+#define	SBIV_PCI	0x1		/* enable interrupts for pci */
+#define	SBIV_ENET0	0x2		/* enable interrupts for enet 0 */
+#define	SBIV_ILINE20	0x4		/* enable interrupts for iline20 */
+#define	SBIV_CODEC	0x8		/* enable interrupts for v90 codec */
+#define	SBIV_USB	0x10		/* enable interrupts for usb */
+#define	SBIV_EXTIF	0x20		/* enable interrupts for external i/f */
+#define	SBIV_ENET1	0x40		/* enable interrupts for enet 1 */
+
+/* sbtmstatelow */
+#define SBTMSTATELOW	0x98		/* offset */
+#define	SBTML_RESET	0x1		/* reset */
+#define	SBTML_REJ	0x2		/* reject */
+#define	SBTML_CLK	0x10000		/* clock enable */
+#define	SBTML_FGC	0x20000		/* force gated clocks on */
+#define	SBTML_PE	0x40000000	/* pme enable */
+#define	SBTML_BE	0x80000000	/* bist enable */
+
+/* sbtmstatehigh */
+#define SBTMSTATEHIGH	0x9C		/* offset */
+#define	SBTMH_SERR	0x1		/* serror */
+#define	SBTMH_INT	0x2		/* interrupt */
+#define	SBTMH_BUSY	0x4		/* busy */
+#define	SBTMH_GCR	0x20000000	/* gated clock request */
+#define	SBTMH_BISTF	0x40000000	/* bist failed */
+#define	SBTMH_BISTD	0x80000000	/* bist done */
+
+/* sbbwa0 */
+#define SBBWA0		0xA0		/* offset */
+#define	SBBWA_TAB0_MASK	0xffff		/* lookup table 0 */
+#define	SBBWA_TAB1_MASK	0xffff		/* lookup table 1 */
+#define	SBBWA_TAB1_SHIFT	16
+
+/* sbimconfiglow */
+#define SBIMCONFIGLOW	0xA8		/* offset */
+#define	SBIMCL_STO_MASK	0x3		/* service timeout */
+#define	SBIMCL_RTO_MASK	0x30		/* request timeout */
+#define	SBIMCL_RTO_SHIFT	4
+#define	SBIMCL_CID_MASK	0xff0000	/* connection id */
+#define	SBIMCL_CID_SHIFT	16
+
+/* sbimconfighigh */
+#define SBIMCONFIGHIGH	0xAC		/* offset */
+#define	SBIMCH_IEM_MASK	0xc		/* inband error mode */
+#define	SBIMCH_TEM_MASK	0x30		/* timeout error mode */
+#define	SBIMCH_TEM_SHIFT	4
+#define	SBIMCH_BEM_MASK	0xc0		/* bus error mode */
+#define	SBIMCH_BEM_SHIFT	6
+
+/* sbadmatch0 */
+#define SBADMATCH0	0xB0		/* offset */
+#define	SBAM_TYPE_MASK	0x3		/* address type */
+#define	SBAM_AD64	0x4		/* reserved */
+#define	SBAM_ADINT0_MASK	0xf8	/* type0 size */
+#define	SBAM_ADINT0_SHIFT	3
+#define	SBAM_ADINT1_MASK	0x1f8	/* type1 size */
+#define	SBAM_ADINT1_SHIFT	3
+#define	SBAM_ADINT2_MASK	0x1f8	/* type2 size */
+#define	SBAM_ADINT2_SHIFT	3
+#define	SBAM_ADEN		0x400	/* enable */
+#define	SBAM_ADNEG		0x800	/* negative decode */
+#define	SBAM_BASE0_MASK	0xffffff00	/* type0 base address */
+#define	SBAM_BASE0_SHIFT	8
+#define	SBAM_BASE1_MASK	0xfffff000	/* type1 base address for the core */
+#define	SBAM_BASE1_SHIFT	12
+#define	SBAM_BASE2_MASK	0xffff0000	/* type2 base address for the core */
+#define	SBAM_BASE2_SHIFT	16
+
+/* sbtmconfiglow */
+#define SBTMCONFIGLOW	0xB8		/* offset */
+#define	SBTMCL_CD_MASK	0xff		/* clock divide */
+#define	SBTMCL_CO_MASK	0xf800		/* clock offset */
+#define	SBTMCL_CO_SHIFT	11
+#define	SBTMCL_IF_MASK	0xfc0000	/* interrupt flags */
+#define	SBTMCL_IF_SHIFT	18
+#define	SBTMCL_IM_MASK	0x3000000	/* interrupt mode */
+#define	SBTMCL_IM_SHIFT	24
+
+/* sbtmconfighigh */
+#define SBTMCONFIGHIGH	0xBC		/* offset */
+#define	SBTMCH_BM_MASK	0x3		/* busy mode */
+#define	SBTMCH_RM_MASK	0x3		/* retry mode */
+#define	SBTMCH_RM_SHIFT	2
+#define	SBTMCH_SM_MASK	0x30		/* stop mode */
+#define	SBTMCH_SM_SHIFT	4
+#define	SBTMCH_EM_MASK	0x300		/* sb error mode */
+#define	SBTMCH_EM_SHIFT	8
+#define	SBTMCH_IM_MASK	0xc00		/* int mode */
+#define	SBTMCH_IM_SHIFT	10
+
+/* sbbconfig */
+#define SBBCONFIG	0xC0		/* offset */
+#define	SBBC_LAT_MASK	0x3		/* sb latency */
+#define	SBBC_MAX0_MASK	0xf0000		/* maxccntr0 */
+#define	SBBC_MAX0_SHIFT	16
+#define	SBBC_MAX1_MASK	0xf00000	/* maxccntr1 */
+#define	SBBC_MAX1_SHIFT	20
+
+/* sbbstate */
+#define SBBSTATE	0xC8		/* offset */
+#define	SBBS_SRD	0x1		/* st reg disable */
+#define	SBBS_HRD	0x2		/* hold reg disable */
+
+/* sbactcnfg */
+#define SBACTCNFG	0xD8		/* offset */
+
+/* sbflagst */
+#define	SBFLAGST	0xE8		/* offset */
+
+/* sbidlow */
+#define SBIDLOW		0xF8		/* offset */
+#define	SBIDL_CS_MASK	0x3		/* config space */
+#define	SBIDL_AR_MASK	0x38		/* # address ranges supported */
+#define	SBIDL_AR_SHIFT	3
+#define	SBIDL_SYNCH	0x40		/* sync */
+#define	SBIDL_INIT	0x80		/* initiator */
+#define	SBIDL_MINLAT_MASK	0xf00	/* minimum backplane latency */
+#define	SBIDL_MINLAT_SHIFT	8
+#define	SBIDL_MAXLAT	0xf000		/* maximum backplane latency */
+#define	SBIDL_MAXLAT_SHIFT	12
+#define	SBIDL_FIRST	0x10000		/* this initiator is first */
+#define	SBIDL_CW_MASK	0xc0000		/* cycle counter width */
+#define	SBIDL_CW_SHIFT	18
+#define	SBIDL_TP_MASK	0xf00000	/* target ports */
+#define	SBIDL_TP_SHIFT	20
+#define	SBIDL_IP_MASK	0xf000000	/* initiator ports */
+#define	SBIDL_IP_SHIFT	24
+
+/* sbidhigh */
+#define SBIDHIGH	0xFC		/* offset */
+#define	SBIDH_RC_MASK	0xf		/* revision code*/
+#define	SBIDH_CC_MASK	0xfff0		/* core code */
+#define	SBIDH_CC_SHIFT	4
+#define	SBIDH_VC_MASK	0xffff0000	/* vendor code */
+#define	SBIDH_VC_SHIFT	16
+
+/* core codes */
+#define	SB_ILINE20	0x801		/* iline20 core */
+#define	SB_SDRAM	0x803		/* sdram core */
+#define	SB_PCI		0x804		/* pci core */
+#define	SB_MIPS		0x805		/* mips core */
+#define	SB_ENET		0x806		/* enet mac core */
+#define	SB_CODEC	0x807		/* v90 codec core */
+#define	SB_USB		0x808		/* usb core */
+#define	SB_ILINE100	0x80a		/* iline100 core */
+#define	SB_EXTIF	0x811		/* external interface core */
+
+struct sbmap {
+	LM_UINT32 id;
+	LM_UINT32 coreunit;
+	LM_UINT32 sbaddr;
+};
+
+#define SBID_SDRAM		0
+#define SBID_PCI_MEM		1
+#define SBID_PCI_CFG		2
+#define SBID_PCI_DMA		3
+#define	SBID_SDRAM_SWAPPED	4
+#define SBID_ENUM		5
+#define SBID_REG_SDRAM		6
+#define SBID_REG_ILINE20	7
+#define SBID_REG_EMAC		8
+#define SBID_REG_CODEC		9
+#define SBID_REG_USB		10
+#define SBID_REG_PCI		11
+#define SBID_REG_MIPS		12
+#define SBID_REG_EXTIF		13
+#define	SBID_EXTIF		14
+#define	SBID_EJTAG		15
+#define	SBID_MAX		16
+
+/*
+ * Host Interface Registers
+ */
+typedef volatile struct _bcmenettregs {
+	/* Device and Power Control */
+	LM_UINT32	devcontrol;
+	LM_UINT32	PAD[2];
+	LM_UINT32	biststatus;
+	LM_UINT32	wakeuplength;
+	LM_UINT32	PAD[3];
+	
+	/* Interrupt Control */
+	LM_UINT32	intstatus;
+	LM_UINT32	intmask;
+	LM_UINT32	gptimer;
+	LM_UINT32	PAD[23];
+
+	/* Ethernet MAC Address Filtering Control */
+	LM_UINT32	PAD[2];
+	LM_UINT32	enetftaddr;
+	LM_UINT32	enetftdata;
+	LM_UINT32	PAD[2];
+
+	/* Ethernet MAC Control */
+	LM_UINT32	emactxmaxburstlen;
+	LM_UINT32	emacrxmaxburstlen;
+	LM_UINT32	emaccontrol;
+	LM_UINT32	emacflowcontrol;
+
+	LM_UINT32	PAD[20];
+
+	/* DMA Lazy Interrupt Control */
+	LM_UINT32	intrecvlazy;
+	LM_UINT32	PAD[63];
+
+	/* DMA engine */
+	dmaregs_t	dmaregs;
+	LM_UINT32	PAD[116];
+
+	/* EMAC Registers */
+	LM_UINT32 rxconfig;
+	LM_UINT32 rxmaxlength;
+	LM_UINT32 txmaxlength;
+	LM_UINT32 PAD;
+	LM_UINT32 mdiocontrol;
+	LM_UINT32 mdiodata;
+	LM_UINT32 emacintmask;
+	LM_UINT32 emacintstatus;
+	LM_UINT32 camdatalo;
+	LM_UINT32 camdatahi;
+	LM_UINT32 camcontrol;
+	LM_UINT32 enetcontrol;
+	LM_UINT32 txcontrol;
+	LM_UINT32 txwatermark;
+	LM_UINT32 mibcontrol;
+	LM_UINT32 PAD[49];
+
+	/* EMAC MIB counters */
+	bcmenetmib_t	mib;
+
+	LM_UINT32	PAD[585];
+
+	/* Sonics SiliconBackplane config registers */
+	sbconfig_t	sbconfig;
+} bcmenetregs_t;
+
+/* device control */
+#define	DC_PM		((LM_UINT32)1 << 7)	/* pattern filtering enable */
+#define	DC_IP		((LM_UINT32)1 << 10)	/* internal ephy present (rev >= 1) */
+#define	DC_ER		((LM_UINT32)1 << 15)	/* ephy reset */
+#define	DC_MP		((LM_UINT32)1 << 16)	/* mii phy mode enable */
+#define	DC_CO		((LM_UINT32)1 << 17)	/* mii phy mode: enable clocks */
+#define	DC_PA_MASK	0x7c0000		/* mii phy mode: mdc/mdio phy address */
+#define	DC_PA_SHIFT	18
+
+/* wakeup length */
+#define	WL_P0_MASK	0x7f			/* pattern 0 */
+#define	WL_D0		((LM_UINT32)1 << 7)
+#define	WL_P1_MASK	0x7f00			/* pattern 1 */
+#define	WL_P1_SHIFT	8
+#define	WL_D1		((LM_UINT32)1 << 15)
+#define	WL_P2_MASK	0x7f0000		/* pattern 2 */
+#define	WL_P2_SHIFT	16
+#define	WL_D2		((LM_UINT32)1 << 23)
+#define	WL_P3_MASK	0x7f000000		/* pattern 3 */
+#define	WL_P3_SHIFT	24
+#define	WL_D3		((LM_UINT32)1 << 31)
+
+/* intstatus and intmask */
+#define	I_PME		((LM_UINT32)1 << 6)	/* power management event */
+#define	I_TO		((LM_UINT32)1 << 7)	/* general purpose timeout */
+#define	I_PC		((LM_UINT32)1 << 10)	/* descriptor error */
+#define	I_PD		((LM_UINT32)1 << 11)	/* data error */
+#define	I_DE		((LM_UINT32)1 << 12)	/* descriptor protocol error */
+#define	I_RU		((LM_UINT32)1 << 13)	/* receive descriptor underflow */
+#define	I_RO		((LM_UINT32)1 << 14)	/* receive fifo overflow */
+#define	I_XU		((LM_UINT32)1 << 15)	/* transmit fifo underflow */
+#define	I_RI		((LM_UINT32)1 << 16)	/* receive interrupt */
+#define	I_XI		((LM_UINT32)1 << 24)	/* transmit interrupt */
+#define	I_EM		((LM_UINT32)1 << 26)	/* emac interrupt */
+#define	I_MW		((LM_UINT32)1 << 27)	/* mii write */
+#define	I_MR		((LM_UINT32)1 << 28)	/* mii read */
+
+#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
+#define	DEF_INTMASK	(I_TO | I_XI | I_RI | I_ERRORS)
+
+/* emaccontrol */
+#define	EMC_CG		((LM_UINT32)1 << 0)	/* crc32 generation enable */
+#define	EMC_EP		((LM_UINT32)1 << 2)	/* onchip ephy: powerdown (rev >= 1) */
+#define	EMC_ED		((LM_UINT32)1 << 3)	/* onchip ephy: energy detected (rev >= 1) */
+#define	EMC_LC_MASK	0xe0			/* onchip ephy: led control (rev >= 1) */
+#define	EMC_LC_SHIFT	5
+
+/* emacflowcontrol */
+#define	EMF_RFH_MASK	0xff			/* rx fifo hi water mark */
+#define	EMF_PG		((LM_UINT32)1 << 15)	/* enable pause frame generation */
+
+/* interrupt receive lazy */
+#define	IRL_TO_MASK	0x00ffffff		/* timeout */
+#define	IRL_FC_MASK	0xff000000		/* frame count */
+#define	IRL_FC_SHIFT	24			/* frame count */
+
+/* emac receive config */
+#define	ERC_DB		((LM_UINT32)1 << 0)	/* disable broadcast */
+#define	ERC_AM		((LM_UINT32)1 << 1)	/* accept all multicast */
+#define	ERC_RDT		((LM_UINT32)1 << 2)	/* receive disable while transmitting */
+#define	ERC_PE		((LM_UINT32)1 << 3)	/* promiscuous enable */
+#define	ERC_LE		((LM_UINT32)1 << 4)	/* loopback enable */
+#define	ERC_EF		((LM_UINT32)1 << 5)	/* enable flow control */
+#define	ERC_UF		((LM_UINT32)1 << 6)	/* accept unicast flow control frame */
+#define	ERC_RF		((LM_UINT32)1 << 7)	/* reject filter */
+
+/* emac mdio control */
+#define	MC_MF_MASK	0x7f			/* mdc frequency */
+#define	MC_PE		((LM_UINT32)1 << 7)	/* mii preamble enable */
+
+/* emac mdio data */
+#define	MD_DATA_MASK	0xffffL			/* r/w data */
+#define	MD_TA_MASK	0x30000L		/* turnaround value */
+#define	MD_TA_SHIFT	16
+#define	MD_TA_VALID	(2L << MD_TA_SHIFT)	/* valid ta */
+#define	MD_RA_MASK	0x7c0000L		/* register address */
+#define	MD_RA_SHIFT	18
+#define	MD_PMD_MASK	0xf800000L		/* physical media device */
+#define	MD_PMD_SHIFT	23
+#define	MD_OP_MASK	0x30000000L		/* opcode */
+#define	MD_OP_SHIFT	28
+#define	MD_OP_WRITE	(1L << MD_OP_SHIFT)	/* write op */
+#define	MD_OP_READ	(2L << MD_OP_SHIFT)	/* read op */
+#define	MD_SB_MASK	0xc0000000L		/* start bits */
+#define	MD_SB_SHIFT	30
+#define	MD_SB_START	(0x1L << MD_SB_SHIFT)	/* start of frame */
+
+/* emac intstatus and intmask */
+#define	EI_MII		((LM_UINT32)1 << 0)	/* mii mdio interrupt */
+#define	EI_MIB		((LM_UINT32)1 << 1)	/* mib interrupt */
+#define	EI_FLOW		((LM_UINT32)1 << 2)	/* flow control interrupt */
+
+/* emac cam data high */
+#define	CD_V		((LM_UINT32)1 << 16)	/* valid bit */
+
+/* emac cam control */
+#define	CC_CE		((LM_UINT32)1 << 0)	/* cam enable */
+#define	CC_MS		((LM_UINT32)1 << 1)	/* mask select */
+#define	CC_RD		((LM_UINT32)1 << 2)	/* read */
+#define	CC_WR		((LM_UINT32)1 << 3)	/* write */
+#define	CC_INDEX_MASK	0x3f0000		/* index */
+#define	CC_INDEX_SHIFT	16
+#define	CC_CB		((LM_UINT32)1 << 31)	/* cam busy */
+
+/* emac ethernet control */
+#define	EC_EE		((LM_UINT32)1 << 0)	/* emac enable */
+#define	EC_ED		((LM_UINT32)1 << 1)	/* emac disable */
+#define	EC_ES		((LM_UINT32)1 << 2)	/* emac soft reset */
+#define	EC_EP		((LM_UINT32)1 << 3)	/* external phy select */
+
+/* emac transmit control */
+#define	EXC_FD		((LM_UINT32)1 << 0)	/* full duplex */
+#define	EXC_FM		((LM_UINT32)1 << 1)	/* flowmode */
+#define	EXC_SB		((LM_UINT32)1 << 2)	/* single backoff enable */
+#define	EXC_SS		((LM_UINT32)1 << 3)	/* small slottime */
+
+/* emac mib control */
+#define	EMC_RZ		((LM_UINT32)1 << 0)	/* autoclear on read */
+
+/*
+ * The Ethernet MAC core returns an 8-byte Receive Frame Data Header
+ * with every frame consisting of
+ * 16bits of frame length, followed by
+ * 16bits of EMAC rx descriptor info, followed by 32bits of undefined.
+ */
+typedef volatile struct {
+	LM_UINT16	len;
+	LM_UINT16	flags;
+	LM_UINT16	pad[12];
+} bcmenetrxh_t;
+
+#define	RXHDR_LEN	28
+
+#define	RXF_L		((LM_UINT16)1 << 11)	/* last buffer in a frame */
+#define	RXF_MISS	((LM_UINT16)1 << 7)	/* received due to promisc mode */
+#define	RXF_BRDCAST	((LM_UINT16)1 << 6)	/* dest is broadcast address */
+#define	RXF_MULT	((LM_UINT16)1 << 5)	/* dest is multicast address */
+#define	RXF_LG		((LM_UINT16)1 << 4)	/* frame length > rxmaxlength */
+#define	RXF_NO		((LM_UINT16)1 << 3)	/* odd number of nibbles */
+#define	RXF_RXER	((LM_UINT16)1 << 2)	/* receive symbol error */
+#define	RXF_CRC		((LM_UINT16)1 << 1)	/* crc error */
+#define	RXF_OV		((LM_UINT16)1 << 0)	/* fifo overflow */
+
+#define RXF_ERRORS (RXF_NO | RXF_RXER | RXF_CRC | RXF_OV)
+
+/* Sonics side: PCI core and host control registers */
+typedef struct sbpciregs {
+	LM_UINT32 control;		/* PCI control */
+	LM_UINT32 PAD[3];
+	LM_UINT32 arbcontrol;	/* PCI arbiter control */
+	LM_UINT32 PAD[3];
+	LM_UINT32 intstatus;	/* Interrupt status */
+	LM_UINT32 intmask;		/* Interrupt mask */
+	LM_UINT32 sbtopcimailbox;	/* Sonics to PCI mailbox */
+	LM_UINT32 PAD[9];
+	LM_UINT32 bcastaddr;	/* Sonics broadcast address */
+	LM_UINT32 bcastdata;	/* Sonics broadcast data */
+	LM_UINT32 PAD[42];
+	LM_UINT32 sbtopci0;	/* Sonics to PCI translation 0 */
+	LM_UINT32 sbtopci1;	/* Sonics to PCI translation 1 */
+	LM_UINT32 sbtopci2;	/* Sonics to PCI translation 2 */
+	LM_UINT32 PAD[445];
+	LM_UINT16 sprom[36];	/* SPROM shadow Area */
+	LM_UINT32 PAD[46];
+} sbpciregs_t;
+
+/* PCI control */
+#define PCI_RST_OE	0x01	/* When set, drives PCI_RESET out to pin */
+#define PCI_RST		0x02	/* Value driven out to pin */
+#define PCI_CLK_OE	0x04	/* When set, drives clock as gated by PCI_CLK out to pin */
+#define PCI_CLK		0x08	/* Gate for clock driven out to pin */	
+
+/* PCI arbiter control */
+#define PCI_INT_ARB	0x01	/* When set, use an internal arbiter */
+#define PCI_EXT_ARB	0x02	/* When set, use an external arbiter */
+#define PCI_PARKID_MASK	0x06	/* Selects which agent is parked on an idle bus */
+#define PCI_PARKID_SHIFT   1
+#define PCI_PARKID_LAST	   0	/* Last requestor */
+#define PCI_PARKID_4710	   1	/* 4710 */
+#define PCI_PARKID_EXTREQ0 2	/* External requestor 0 */
+#define PCI_PARKID_EXTREQ1 3	/* External requestor 1 */
+
+/* Interrupt status/mask */
+#define PCI_INTA	0x01	/* PCI INTA# is asserted */
+#define PCI_INTB	0x02	/* PCI INTB# is asserted */
+#define PCI_SERR	0x04	/* PCI SERR# has been asserted (write one to clear) */
+#define PCI_PERR	0x08	/* PCI PERR# has been asserted (write one to clear) */
+#define PCI_PME		0x10	/* PCI PME# is asserted */
+
+/* (General) PCI/SB mailbox interrupts, two bits per pci function */
+#define	MAILBOX_F0_0	0x100	/* function 0, int 0 */
+#define	MAILBOX_F0_1	0x200	/* function 0, int 1 */
+#define	MAILBOX_F1_0	0x400	/* function 1, int 0 */
+#define	MAILBOX_F1_1	0x800	/* function 1, int 1 */
+#define	MAILBOX_F2_0	0x1000	/* function 2, int 0 */
+#define	MAILBOX_F2_1	0x2000	/* function 2, int 1 */
+#define	MAILBOX_F3_0	0x4000	/* function 3, int 0 */
+#define	MAILBOX_F3_1	0x8000	/* function 3, int 1 */
+
+/* Sonics broadcast address */
+#define BCAST_ADDR_MASK	0xff	/* Broadcast register address */
+
+/* Sonics to PCI translation types */
+#define SBTOPCI0_MASK	0xfc000000
+#define SBTOPCI1_MASK	0xfc000000
+#define SBTOPCI2_MASK	0xc0000000
+#define SBTOPCI_MEM	0
+#define SBTOPCI_IO	1
+#define SBTOPCI_CFG0	2
+#define SBTOPCI_CFG1	3
+#define	SBTOPCI_PREF	0x4	/* prefetch enable */
+#define	SBTOPCI_BURST	0x8	/* burst enable */
+
+/* PCI side: Reserved PCI configuration registers (see pcicfg.h) */
+#define cap_list	rsvd_a[0]
+#define bar0_window	dev_dep[0x80 - 0x40]
+#define bar1_window	dev_dep[0x84 - 0x40]
+#define sprom_control	dev_dep[0x88 - 0x40]
+
+#define	PCI_BAR0_WIN		0x80
+#define	PCI_BAR1_WIN		0x84
+#define	PCI_SPROM_CONTROL	0x88
+#define	PCI_BAR1_CONTROL	0x8c
+
+#define	PCI_BAR0_SPROM_OFFSET	4096	/* top 4K of bar0 accesses external sprom */
+
+/* PCI clock must be active and stable to read SPROM */
+#ifdef MIPSEL
+#define pci_host(sprom) ((sprom[0] == 1) && (sprom[2] == 0x4710) && (sprom[8] == 0xf))
+#else
+#define pci_host(sprom) ((sprom[1] == 1) && (sprom[3] == 0x4710) && (sprom[9] == 0xf))
+#endif
+
+DECLARE_QUEUE_TYPE(LM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT);
+DECLARE_QUEUE_TYPE(LM_TX_PACKET_Q, MAX_TX_PACKET_DESC_COUNT);
+
+typedef struct _LM_PACKET {
+    /* Set in LM. */
+    LM_STATUS PacketStatus;
+
+    /* Set in LM for Rx, in UM for Tx. */
+    LM_UINT32 PacketSize;
+
+    union {
+        /* Send info. */
+        struct {
+            /* Set up by UM. */
+            LM_UINT32 FragCount;
+
+        } Tx;
+
+        /* Receive info. */
+        struct {
+            /* Receive buffer size */
+            LM_UINT32 RxBufferSize;
+
+            /* Virtual and physical address of the receive buffer. */
+	    LM_UINT8 *pRxBufferVirt;
+	    LM_PHYSICAL_ADDRESS RxBufferPhy;
+            
+        } Rx;
+    } u;
+} LM_PACKET;
+
+typedef struct _LM_DEVICE_BLOCK 
+{
+    /* Memory view. */
+    bcmenetregs_t *pMemView;
+    LM_UINT8 *pMappedMemBase;
+
+    PLM_VOID pPacketDescBase;
+
+    LM_UINT32 RxPacketDescCnt;
+    LM_UINT32 MaxRxPacketDescCnt;
+    LM_UINT32 TxPacketDescCnt;
+
+    LM_RX_PACKET_Q RxPacketFreeQ;
+    LM_RX_PACKET_Q RxPacketReceivedQ;
+    LM_TX_PACKET_Q TxPacketFreeQ;
+    LM_TX_PACKET_Q TxPacketActiveQ;
+    LM_TX_PACKET_Q TxPacketXmittedQ;
+
+    LM_PACKET *RxPacketArr[DMAMAXRINGSZ / sizeof(dmadd_t)];
+    LM_PACKET *TxPacketArr[DMAMAXRINGSZ / sizeof(dmadd_t)];
+
+    atomic_t SendDescLeft;
+
+    /* Current node address. */
+    LM_UINT8 NodeAddress[6];
+
+    /* The adapter's node address. */
+    LM_UINT8 PermanentNodeAddress[6];
+
+    /* Multicast address list. */
+    LM_UINT32 McEntryCount;
+    LM_UINT8 McTable[LM_MAX_MC_TABLE_SIZE][LM_MC_ENTRY_SIZE];
+
+    LM_UINT16 PciVendorId;
+    LM_UINT16 PciDeviceId;
+    LM_UINT16 PciSubvendorId;
+    LM_UINT16 PciSubsystemId;
+    LM_UINT8  PciRevId;
+    LM_UINT8  Reserved1[3];
+
+    LM_UINT32 corerev;
+    LM_UINT32 coreunit;
+    LM_UINT32 pcirev;
+
+    LM_UINT32 PhyAddr;
+    LM_UINT32 MdcPort;
+
+    dmadd_t *pRxDesc;
+    LM_PHYSICAL_ADDRESS RxDescPhy;
+
+    dmadd_t *pTxDesc;
+    LM_PHYSICAL_ADDRESS TxDescPhy;
+
+    LM_UINT32 ddoffset;
+    LM_UINT32 dataoffset;
+    LM_UINT32 rxoffset;
+
+    LM_UINT32 rxin;
+    LM_UINT32 rxout;
+
+    LM_UINT32 txin;
+    LM_UINT32 txout;
+
+    LM_UINT32 lazyrxfc;
+    LM_UINT32 lazyrxmult;
+    LM_UINT32 lazytxfc;
+    LM_UINT32 lazytxmult;
+
+    struct sbmap *sbmap;
+
+    LM_LINE_SPEED RequestedLineSpeed;
+    LM_DUPLEX_MODE RequestedDuplexMode;
+
+    LM_LINE_SPEED LineSpeed;
+    LM_DUPLEX_MODE DuplexMode;
+
+    LM_FLOW_CONTROL FlowControlCap;
+    LM_FLOW_CONTROL FlowControl;
+
+    LM_UINT32 Advertising;
+
+    LM_UINT32 DisableAutoNeg;
+
+    LM_STATUS LinkStatus;
+
+    LM_UINT32 ReceiveMask;
+
+    LM_BOOL InitDone;
+
+    LM_BOOL mibgood;
+
+    LM_BOOL ShuttingDown;
+
+    LM_BOOL QueueRxPackets;
+
+    LM_UINT32 intstatus;
+    LM_UINT32 intmask;
+
+    LM_COUNTER tx_good_octets;
+    LM_COUNTER tx_good_pkts;
+    LM_COUNTER tx_octets;
+    LM_COUNTER tx_pkts;
+    LM_COUNTER tx_broadcast_pkts;
+    LM_COUNTER tx_multicast_pkts;
+    LM_COUNTER tx_len_64;
+    LM_COUNTER tx_len_65_to_127;
+    LM_COUNTER tx_len_128_to_255;
+    LM_COUNTER tx_len_256_to_511;
+    LM_COUNTER tx_len_512_to_1023;
+    LM_COUNTER tx_len_1024_to_max;
+    LM_COUNTER tx_jabber_pkts;
+    LM_COUNTER tx_oversize_pkts;
+    LM_COUNTER tx_fragment_pkts;
+    LM_COUNTER tx_underruns;
+    LM_COUNTER tx_total_cols;
+    LM_COUNTER tx_single_cols;
+    LM_COUNTER tx_multiple_cols;
+    LM_COUNTER tx_excessive_cols;
+    LM_COUNTER tx_late_cols;
+    LM_COUNTER tx_defered;
+    LM_COUNTER tx_carrier_lost;
+    LM_COUNTER tx_pause_pkts;
+
+    LM_COUNTER rx_good_octets;
+    LM_COUNTER rx_good_pkts;
+    LM_COUNTER rx_octets;
+    LM_COUNTER rx_pkts;
+    LM_COUNTER rx_broadcast_pkts;
+    LM_COUNTER rx_multicast_pkts;
+    LM_COUNTER rx_len_64;
+    LM_COUNTER rx_len_65_to_127;
+    LM_COUNTER rx_len_128_to_255;
+    LM_COUNTER rx_len_256_to_511;
+    LM_COUNTER rx_len_512_to_1023;
+    LM_COUNTER rx_len_1024_to_max;
+    LM_COUNTER rx_jabber_pkts;
+    LM_COUNTER rx_oversize_pkts;
+    LM_COUNTER rx_fragment_pkts;
+    LM_COUNTER rx_missed_pkts;
+    LM_COUNTER rx_crc_align_errs;
+    LM_COUNTER rx_undersize;
+    LM_COUNTER rx_crc_errs;
+    LM_COUNTER rx_align_errs;
+    LM_COUNTER rx_symbol_errs;
+    LM_COUNTER rx_pause_pkts;
+    LM_COUNTER rx_nonpause_pkts;
+
+    char PartNo[32];
+
+} LM_DEVICE_BLOCK;
+
+/******************************************************************************/
+/* NIC register read/write macros. */
+/******************************************************************************/
+
+#define REG_RD(pDevice, OffsetName)                                         \
+        __raw_readl(&((pDevice)->pMemView->##OffsetName))
+
+#define REG_WR(pDevice, OffsetName, Value32)                                \
+        (void) __raw_writel(Value32, &((pDevice)->pMemView->##OffsetName))
+
+#define REG_RD_OFFSET(pDevice, Offset)                                      \
+    __raw_readl(((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+#define REG_WR_OFFSET(pDevice, Offset, Value32)                             \
+    __raw_writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset))
+
+#define REG_OR(pDevice, OffsetName, Value32)                                \
+    REG_WR(pDevice, OffsetName, REG_RD(pDevice, OffsetName) | Value32)
+
+#define REG_AND(pDevice, OffsetName, Value32)                                \
+    REG_WR(pDevice, OffsetName, REG_RD(pDevice, OffsetName) & Value32)
+
+#define SPINWAIT(exp, us) { \
+	LM_UINT32 countdown = (us) + 9; \
+	while ((exp) && (countdown >= 10)) {\
+		b44_MM_Wait(10); \
+		countdown -= 10; \
+	} \
+}
+
+#endif /* B44_H */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44lm.c orig/drivers/net/bcm4400/b44lm.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44lm.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/b44lm.c	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,1765 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM4400 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/******************************************************************************/
+
+#include "b44mm.h"
+
+
+
+/******************************************************************************/
+/* Local functions. */
+/******************************************************************************/
+
+LM_STATUS b44_LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_SetFlowControl(PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd);
+static LM_UINT32 b44_GetPhyAdFlowCntrlSettings(PLM_DEVICE_BLOCK pDevice);
+
+STATIC LM_STATUS b44_LM_ResetChip(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS b44_LM_DisableChip(PLM_DEVICE_BLOCK pDevice);
+void b44_LM_ClearStats(LM_DEVICE_BLOCK *pDevice);
+void b44_LM_WriteCam(LM_DEVICE_BLOCK *pDevice, LM_UINT8 *ea,
+    LM_UINT32 camindex);
+
+LM_UINT32 b44_LM_getsbaddr(LM_DEVICE_BLOCK *pDevice, LM_UINT32 id,
+    LM_UINT32 coreunit);
+void b44_LM_sb_core_disable(LM_DEVICE_BLOCK *pDevice);
+LM_UINT32 b44_LM_sb_pci_setup(LM_DEVICE_BLOCK *pDevice, LM_UINT32 cores);
+LM_UINT32 b44_LM_sb_coreunit(LM_DEVICE_BLOCK *pDevice);
+void b44_LM_sb_core_reset(LM_DEVICE_BLOCK *pDevice);
+LM_UINT32 b44_LM_sb_coreid(LM_DEVICE_BLOCK *pDevice);
+LM_UINT32 b44_LM_sb_corerev(LM_DEVICE_BLOCK *pDevice);
+LM_UINT32 b44_LM_sb_iscoreup(LM_DEVICE_BLOCK *pDevice);
+
+#define BCM4710_PCI_DMA		0x40000000	/* Client Mode PCI memory access space (1 GB) */
+#define BCM4710_ENUM		0x18000000	/* Beginning of core enumeration space */
+
+struct sbmap bcm4402[] = {
+	{SBID_PCI_DMA,		0,	BCM4710_PCI_DMA},
+	{SBID_ENUM,		0,	BCM4710_ENUM},
+	{SBID_REG_EMAC,		0,	0x18000000},
+	{SBID_REG_CODEC,	0,	0x18001000},
+	{SBID_REG_PCI,		0,	0x18002000}
+};
+
+/******************************************************************************/
+/* External functions. */
+/******************************************************************************/
+
+LM_UINT32
+b44_LM_ByteSwap(LM_UINT32 Value32)
+{
+    return ((Value32 & 0xff) << 24)| ((Value32 & 0xff00) << 8)|
+        ((Value32 & 0xff0000) >> 8) | ((Value32 >> 24) & 0xff);
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+b44_LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+	PLM_PACKET pPacket;
+	LM_PHYSICAL_ADDRESS pa;
+	LM_UINT32 rxout = pDevice->rxout;
+	LM_UINT32 ctrl;
+
+	pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+	while(pPacket) {
+
+		/* Initialize the receive buffer pointer */
+		b44_MM_MapRxDma(pDevice, pPacket, &pa);
+
+		*((LM_UINT32 *) pPacket->u.Rx.pRxBufferVirt) = 0;
+
+		/* prep the descriptor control value */
+		ctrl = pPacket->u.Rx.RxBufferSize;
+		if (rxout == (pDevice->MaxRxPacketDescCnt - 1))
+			ctrl |= CTRL_EOT;
+
+		/* init the rx descriptor */
+		pDevice->pRxDesc[rxout].ctrl = ctrl;
+		pDevice->pRxDesc[rxout].addr = pa + pDevice->dataoffset;
+
+		pDevice->RxPacketArr[rxout] = pPacket;
+		rxout = (rxout + 1) & (pDevice->MaxRxPacketDescCnt - 1);
+
+		pPacket = (PLM_PACKET)
+			QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+	} /* while */
+
+	pDevice->rxout = rxout;
+	wmb();
+
+	REG_WR(pDevice, dmaregs.rcvptr, rxout * sizeof(dmadd_t));
+	return LM_STATUS_SUCCESS;
+} /* LM_QueueRxPackets */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+b44_LM_EepromReadBlock(PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 offset, LM_UINT16 *pData, LM_UINT32 size)
+{
+	int off, nw;
+//	LM_UINT8 chk8;
+	int i;
+	LM_UINT16 *buf;
+
+	off = offset;
+	nw = ROUNDUP(size, 2);
+	buf = (LM_UINT16 *) pData;
+
+	/* read the sprom */
+	for (i = 0; i < nw; i += 2)
+		buf[i/2] = REG_RD_OFFSET(pDevice, 4096 + off + i);
+
+	return LM_STATUS_SUCCESS;
+} /* b44_LM_EepromRead */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine initializes default parameters and reads the PCI           */
+/*    configurations.                                                         */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_GetAdapterInfo(
+PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT8 eprom[128];
+    LM_STATUS Status;
+    LM_UINT32 Value32;
+
+    /* Get Device Id and Vendor Id */
+    Status = b44_MM_ReadConfig32(pDevice, PCI_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciVendorId = (LM_UINT16) Value32;
+    pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16);
+
+    Status = b44_MM_ReadConfig32(pDevice, PCI_REV_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciRevId = (LM_UINT8) Value32;
+
+    /* Get subsystem vendor. */
+    Status = b44_MM_ReadConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    pDevice->PciSubvendorId = (LM_UINT16) Value32;
+
+    /* Get PCI subsystem id. */
+    pDevice->PciSubsystemId = (LM_UINT16) (Value32 >> 16);
+
+    Status = b44_MM_MapMemBase(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    /* Initialize the memory view pointer. */
+    pDevice->pMemView = (bcmenetregs_t *) pDevice->pMappedMemBase;
+
+    b44_LM_EepromReadBlock(pDevice, 0, (LM_UINT16 *) eprom, sizeof(eprom));
+    if (eprom[126] != 1)
+        return LM_STATUS_FAILURE;
+
+    pDevice->PermanentNodeAddress[0] = eprom[79];
+    pDevice->PermanentNodeAddress[1] = eprom[78];
+    pDevice->PermanentNodeAddress[2] = eprom[81];
+    pDevice->PermanentNodeAddress[3] = eprom[80];
+    pDevice->PermanentNodeAddress[4] = eprom[83];
+    pDevice->PermanentNodeAddress[5] = eprom[82];
+
+    memcpy(pDevice->NodeAddress, pDevice->PermanentNodeAddress, 6);
+
+    pDevice->PhyAddr = eprom[90] & 0x1f;
+    pDevice->MdcPort = (eprom[90] >> 14) & 0x1;
+
+    /* Initialize the default values. */
+    pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT;
+    pDevice->RxPacketDescCnt = DEFAULT_RX_PACKET_DESC_COUNT;
+    pDevice->MaxRxPacketDescCnt = DMAMAXRINGSZ / sizeof(dmadd_t);
+    pDevice->rxoffset = 30;
+    pDevice->lazyrxfc = 1;
+    pDevice->lazyrxmult = 0;
+    pDevice->lazytxfc = 0;
+    pDevice->lazytxmult = 0;
+    pDevice->intmask = DEF_INTMASK;
+    pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+
+    /* Change driver parameters. */
+    Status = b44_MM_GetConfig(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+    return LM_STATUS_SUCCESS;
+} /* LM_GetAdapterInfo */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets up receive/transmit buffer descriptions queues.       */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_InitializeAdapter(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_PHYSICAL_ADDRESS MemPhy, MemBasePhy;
+    LM_UINT8 *pMemVirt, *pMemBase;
+    PLM_PACKET pPacket;
+    LM_STATUS Status;
+    LM_UINT32 Size;
+    LM_UINT32 align, j;
+
+    /* Intialize the queues. */
+    QQ_InitQueue(&pDevice->RxPacketReceivedQ.Container, 
+        MAX_RX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
+        MAX_RX_PACKET_DESC_COUNT);
+
+    QQ_InitQueue(&pDevice->TxPacketFreeQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketActiveQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QQ_InitQueue(&pDevice->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT);
+
+    /* Allocate memory for packet descriptors. */
+    Size = (pDevice->RxPacketDescCnt + 
+        pDevice->TxPacketDescCnt) * B44_MM_PACKET_DESC_SIZE;
+    Status = b44_MM_AllocateMemory(pDevice, Size, (PLM_VOID *) &pPacket);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    for(j = 0; j < pDevice->TxPacketDescCnt; j++)
+    {
+        QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + B44_MM_PACKET_DESC_SIZE);
+    } /* for(j.. */
+
+    for(j = 0; j < pDevice->RxPacketDescCnt; j++)
+    {
+        /* Receive buffer size. */
+        pPacket->u.Rx.RxBufferSize = 1522 + pDevice->rxoffset;
+
+        /* Add the descriptor to RxPacketFreeQ. */
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + B44_MM_PACKET_DESC_SIZE);
+    } /* for */
+
+    /* Initialize the rest of the packet descriptors. */
+    Status = b44_MM_InitializeUmPackets(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    } /* if */
+
+    Size = (pDevice->MaxRxPacketDescCnt + pDevice->TxPacketDescCnt) *
+        sizeof(dmadd_t) + DMARINGALIGN;
+
+    Status = b44_MM_AllocateSharedMemory(pDevice, Size, (PLM_VOID) &pMemBase, &MemBasePhy);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    MemPhy = (MemBasePhy + (DMARINGALIGN - 1)) & ~(DMARINGALIGN - 1);
+    align = MemPhy - MemBasePhy;
+    pMemVirt = pMemBase + align;
+
+    pDevice->pRxDesc = (dmadd_t *) pMemVirt;
+    pDevice->RxDescPhy = MemPhy;
+
+    pMemVirt += pDevice->MaxRxPacketDescCnt * sizeof(dmadd_t);
+    MemPhy += pDevice->MaxRxPacketDescCnt * sizeof(dmadd_t);
+
+    pDevice->pTxDesc = (dmadd_t *) pMemVirt;
+    pDevice->TxDescPhy = MemPhy;
+
+    pMemVirt += pDevice->TxPacketDescCnt * sizeof(dmadd_t);
+    MemPhy += pDevice->MaxRxPacketDescCnt * sizeof(dmadd_t);
+
+    /* Initialize the hardware. */
+    Status = b44_LM_ResetAdapter(pDevice);
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* We are done with initialization. */
+    pDevice->InitDone = TRUE;
+
+    return LM_STATUS_SUCCESS;
+} /* LM_InitializeAdapter */
+
+
+LM_STATUS
+b44_LM_DisableChip(PLM_DEVICE_BLOCK pDevice)
+{
+    return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This function reinitializes the adapter.                                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_ResetAdapter(
+PLM_DEVICE_BLOCK pDevice)
+{
+
+    /* Disable interrupt. */
+    b44_LM_DisableInterrupt(pDevice);
+
+    /* Disable transmit and receive DMA engines.  Abort all pending requests. */
+    if(pDevice->InitDone)
+    {
+        b44_LM_Abort(pDevice);
+    }
+
+    pDevice->ShuttingDown = FALSE;
+
+    ASSERT(b44_LM_sb_coreid(pDevice) == SB_ENET);
+
+    pDevice->corerev = b44_LM_sb_corerev(pDevice);
+
+    pDevice->sbmap = bcm4402;
+
+    pDevice->coreunit = b44_LM_sb_coreunit(pDevice);
+
+    /* enable pci interrupts, bursts, and prefetch */
+    ASSERT((pDevice->coreunit == 0) || (pDevice->coreunit == 1));
+    pDevice->pcirev = b44_LM_sb_pci_setup(pDevice,
+        ((pDevice->coreunit == 0)? SBIV_ENET0: SBIV_ENET1));
+
+    pDevice->ddoffset = pDevice->dataoffset =
+        b44_LM_getsbaddr(pDevice, SBID_PCI_DMA, 0);
+
+    b44_LM_ResetChip(pDevice);
+
+#if 1
+    if (pDevice->InitDone != TRUE) {
+        if (pDevice->MdcPort == pDevice->coreunit) {
+            b44_LM_ResetPhy(pDevice);
+            b44_LM_SetupPhy(pDevice);
+        }
+    }
+#endif
+
+    b44_LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    /* enable crc32 generation */
+    REG_OR(pDevice, emaccontrol, EMC_CG);
+
+    REG_WR(pDevice, intrecvlazy, (pDevice->lazyrxfc << IRL_FC_SHIFT));
+    if (pDevice->lazyrxfc > 1)
+    {
+        REG_OR(pDevice, intrecvlazy, (pDevice->lazyrxmult * pDevice->lazyrxfc));
+    }
+
+    /* enable 802.3x tx flow control (honor received PAUSE frames) */
+//    REG_WR(pDevice, rxconfig, ERC_FE | ERC_UF);
+
+    b44_LM_SetReceiveMask(pDevice, pDevice->ReceiveMask);
+
+    /* set max frame lengths - account for possible vlan tag */
+    REG_WR(pDevice, rxmaxlength, MAX_ETHERNET_PACKET_SIZE + 32);
+    REG_WR(pDevice, txmaxlength, MAX_ETHERNET_PACKET_SIZE + 32);
+
+    /* set tx watermark */
+    REG_WR(pDevice, txwatermark, 56);
+
+    /* initialize the tx and rx dma channels */
+    /* clear tx descriptor ring */
+    memset((void*)pDevice->pTxDesc, 0, (pDevice->TxPacketDescCnt *
+        sizeof(dmadd_t)));
+
+    REG_WR(pDevice, dmaregs.xmtcontrol, XC_XE);
+    REG_WR(pDevice, dmaregs.xmtaddr, (pDevice->TxDescPhy +
+        pDevice->ddoffset));
+
+    /* clear rx descriptor ring */
+    memset((void*)pDevice->pRxDesc, 0, (pDevice->MaxRxPacketDescCnt *
+        sizeof(dmadd_t)));
+
+    REG_WR(pDevice, dmaregs.rcvcontrol, ((pDevice->rxoffset <<
+        RC_RO_SHIFT) | RC_RE));
+
+    REG_WR(pDevice, dmaregs.rcvaddr, (pDevice->RxDescPhy +
+        pDevice->ddoffset));
+
+    /* Queue Rx packet buffers. */
+    b44_LM_QueueRxPackets(pDevice);
+
+    /* turn on the emac */
+    REG_OR(pDevice, enetcontrol, EC_EE);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_ResetAdapter */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine disables the adapter from generating interrupts.           */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_DisableInterrupt(
+    PLM_DEVICE_BLOCK pDevice)
+{
+	REG_WR(pDevice, intmask, 0);
+	(void) REG_RD(pDevice, intmask);	/* sync readback */
+	return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine enables the adapter to generate interrupts.                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_EnableInterrupt(
+    PLM_DEVICE_BLOCK pDevice)
+{
+	REG_WR(pDevice, intmask, pDevice->intmask);
+	return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine puts a packet on the wire if there is a transmit DMA       */
+/*    descriptor available; otherwise the packet is queued for later          */
+/*    transmission.  If the second argue is NULL, this routine will put       */
+/*    the queued packet on the wire if possible.                              */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+	LM_UINT32 fragcount;
+	LM_UINT32 len, txout, ctrl;
+	LM_PHYSICAL_ADDRESS pa;
+	int first, next;
+
+	txout = pDevice->txout;
+
+	pDevice->TxPacketArr[txout] = pPacket;
+	for(fragcount = 0, first = 1, next = 1; next;
+		first = 0, fragcount++) {
+
+		ctrl = 0;
+		b44_MM_MapTxDma(pDevice, pPacket, &pa, &len, fragcount);
+		ctrl = len & CTRL_BC_MASK;
+
+		if (first)
+			ctrl |= CTRL_SOF;
+		if (fragcount == (pPacket->u.Tx.FragCount - 1)) {
+			ctrl |= CTRL_EOF;
+			next = 0;
+		}
+		if (txout == (pDevice->TxPacketDescCnt - 1)) {
+			ctrl |= CTRL_EOT;
+		}
+		ctrl |= CTRL_IOC;
+
+		/* init the tx descriptor */
+		pDevice->pTxDesc[txout].ctrl = ctrl;
+		pDevice->pTxDesc[txout].addr = pa + pDevice->dataoffset;
+
+		txout = (txout + 1) & (pDevice->TxPacketDescCnt - 1);
+
+	}
+
+	atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendDescLeft);
+
+	pDevice->txout = txout;
+
+	wmb();
+
+	REG_WR(pDevice, dmaregs.xmtptr, (txout * sizeof(dmadd_t)));
+	REG_WR(pDevice, dmaregs.xmtptr, (txout * sizeof(dmadd_t)));
+
+	return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This routine sets the receive control register according to ReceiveMask */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask)
+{
+    LM_UINT32 ReceiveMask;
+    LM_UINT32 j;
+    LM_UINT32 idx = 0;
+
+    ReceiveMask = Mask;
+
+    if(Mask & LM_ACCEPT_UNICAST)
+    {
+        Mask &= ~LM_ACCEPT_UNICAST;
+    }
+
+    if(Mask & LM_ACCEPT_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_ALL_MULTICAST)
+    {
+        Mask &= ~LM_ACCEPT_ALL_MULTICAST;
+    }
+
+    if(Mask & LM_ACCEPT_BROADCAST)
+    {
+        Mask &= ~LM_ACCEPT_BROADCAST;
+    }
+
+    if(Mask & LM_PROMISCUOUS_MODE)
+    {
+        Mask &= ~LM_PROMISCUOUS_MODE;
+    }
+
+    /* Make sure all the bits are valid before committing changes. */
+    if(Mask)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+	if (ReceiveMask & LM_PROMISCUOUS_MODE)
+		REG_OR(pDevice, rxconfig, ERC_PE);
+	else {
+		REG_WR(pDevice, camcontrol, 0);
+		/* our local address */
+		b44_LM_WriteCam(pDevice, pDevice->NodeAddress, idx++);
+
+		/* allmulti or a list of discrete multicast addresses */
+		if (ReceiveMask & LM_ACCEPT_ALL_MULTICAST)
+			REG_OR(pDevice, rxconfig, ERC_AM);
+		else if (ReceiveMask & LM_ACCEPT_MULTICAST) {
+			for(j = 0; j < pDevice->McEntryCount; j++) {
+				b44_LM_WriteCam(pDevice, pDevice->McTable[j],
+					idx++);
+			}
+		}
+
+		/* enable cam */
+		REG_OR(pDevice, camcontrol, CC_CE);
+	}
+
+	return LM_STATUS_SUCCESS;
+} /* LM_SetReceiveMask */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Disable the interrupt and put the transmitter and receiver engines in   */
+/*    an idle state.  Also aborts all pending send requests and receive       */
+/*    buffers.                                                                */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_Abort(
+PLM_DEVICE_BLOCK pDevice)
+{
+    PLM_PACKET pPacket;
+    LM_UINT32 rxin;
+
+    b44_LM_DisableInterrupt(pDevice);
+
+    b44_LM_DisableChip(pDevice);
+
+    /* Abort packets that have already queued to go out. */
+    pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    while(pPacket)
+    {
+
+        pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED;
+
+        atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendDescLeft);
+
+        QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+
+        pPacket = (PLM_PACKET) 
+            QQ_PopHead(&pDevice->TxPacketActiveQ.Container);
+    }
+
+    if(!pDevice->ShuttingDown)
+    {
+        /* Indicate packets to the protocol. */
+        b44_MM_IndicateTxPackets(pDevice);
+
+        /* Indicate received packets to the protocols. */
+        b44_MM_IndicateRxPackets(pDevice);
+    }
+    else
+    {
+        /* Move the receive packet descriptors in the ReceivedQ to the */
+        /* free queue. */
+        for(; ;)
+        {
+            pPacket = (PLM_PACKET) QQ_PopHead(
+                &pDevice->RxPacketReceivedQ.Container);
+            if(pPacket == NULL)
+            {
+                break;
+            }
+            QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+        }
+    }
+
+    /* Clean up the Receive desc ring. */
+
+    rxin = pDevice->rxin;
+    while(rxin != pDevice->rxout) {
+        pPacket = pDevice->RxPacketArr[rxin];
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+        rxin = (rxin + 1) & (pDevice->MaxRxPacketDescCnt - 1);
+    } /* while */
+
+    pDevice->rxin = rxin;
+    return LM_STATUS_SUCCESS;
+} /* LM_Abort */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    Disable the interrupt and put the transmitter and receiver engines in   */
+/*    an idle state.  Aborts all pending send requests and receive buffers.   */
+/*    Also free all the receive buffers.                                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_Halt(PLM_DEVICE_BLOCK pDevice)
+{
+    PLM_PACKET pPacket;
+    LM_UINT32 EntryCnt;
+
+    b44_LM_Abort(pDevice);
+
+    /* Get the number of entries in the queue. */
+    EntryCnt = QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container);
+
+    /* Make sure all the packets have been accounted for. */
+    for(EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++)
+    {
+        pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+        if (pPacket == 0)
+            break;
+
+        b44_MM_FreeRxBuffer(pDevice, pPacket);
+
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+
+    b44_LM_ResetChip(pDevice);
+
+    /* Reprogram the MAC address. */
+    b44_LM_SetMacAddress(pDevice, pDevice->NodeAddress);
+
+    return LM_STATUS_SUCCESS;
+} /* LM_Halt */
+
+
+STATIC LM_STATUS
+b44_LM_ResetChip(LM_DEVICE_BLOCK *pDevice)
+{
+	if (!b44_LM_sb_iscoreup(pDevice)) {
+		b44_LM_sb_pci_setup(pDevice, 
+			((pDevice->coreunit == 0)? SBIV_ENET0: SBIV_ENET1));	
+		/* power on reset: reset the enet core */
+		b44_LM_sb_core_reset(pDevice);
+		goto chipinreset;
+	}
+
+	/* read counters before resetting the chip */
+	if (pDevice->mibgood)
+		b44_LM_StatsUpdate(pDevice);
+
+	REG_WR(pDevice, intrecvlazy, 0);
+
+	/* disable emac */
+	REG_WR(pDevice, enetcontrol, EC_ED);
+	SPINWAIT((REG_RD(pDevice, enetcontrol) & EC_ED), 100);
+
+	/* reset the dma engines */
+	REG_WR(pDevice, dmaregs.xmtcontrol, 0);
+	pDevice->txin = pDevice->txout = 0;
+	atomic_set(&pDevice->SendDescLeft, pDevice->TxPacketDescCnt - 1);
+
+	if (REG_RD(pDevice, dmaregs.rcvstatus) & RS_RE_MASK) {
+		/* wait until channel is idle or stopped */
+		SPINWAIT(!(REG_RD(pDevice, dmaregs.rcvstatus) & RS_RS_IDLE),
+			100);
+	}
+
+	REG_WR(pDevice, dmaregs.rcvcontrol, 0);
+	pDevice->rxin = pDevice->rxout = 0;
+
+	b44_LM_sb_core_reset(pDevice);
+
+chipinreset:
+	b44_LM_ClearStats(pDevice);
+
+	/*
+	 * We want the phy registers to be accessible even when
+	 * the driver is "downed" so initialize MDC preamble, frequency,
+	 * and whether internal or external phy here.
+	 */
+		/* 4402 has 62.5Mhz SB clock and internal phy */
+	REG_WR(pDevice, mdiocontrol, 0x8d);
+
+	/* some chips have internal phy, some don't */
+	if (!(REG_RD(pDevice, devcontrol) & DC_IP)) {
+		REG_WR(pDevice, enetcontrol, EC_EP);
+	} else if (REG_RD(pDevice, devcontrol) & DC_ER) {
+		REG_AND(pDevice, devcontrol, ~DC_ER);
+
+		b44_MM_Wait(100);
+
+	}
+
+	/* clear persistent sw intstatus */
+	pDevice->intstatus = 0;
+	return LM_STATUS_SUCCESS;
+}
+
+void
+b44_LM_ClearStats(LM_DEVICE_BLOCK *pDevice)
+{
+	/* must clear mib registers by hand */
+	REG_WR(pDevice, mibcontrol, EMC_RZ);
+	(void) REG_RD(pDevice, mib.tx_good_octets);
+	(void) REG_RD(pDevice, mib.tx_good_pkts);
+	(void) REG_RD(pDevice, mib.tx_octets);
+	(void) REG_RD(pDevice, mib.tx_pkts);
+	(void) REG_RD(pDevice, mib.tx_broadcast_pkts);
+	(void) REG_RD(pDevice, mib.tx_multicast_pkts);
+	(void) REG_RD(pDevice, mib.tx_len_64);
+	(void) REG_RD(pDevice, mib.tx_len_65_to_127);
+	(void) REG_RD(pDevice, mib.tx_len_128_to_255);
+	(void) REG_RD(pDevice, mib.tx_len_256_to_511);
+	(void) REG_RD(pDevice, mib.tx_len_512_to_1023);
+	(void) REG_RD(pDevice, mib.tx_len_1024_to_max);
+	(void) REG_RD(pDevice, mib.tx_jabber_pkts);
+	(void) REG_RD(pDevice, mib.tx_oversize_pkts);
+	(void) REG_RD(pDevice, mib.tx_fragment_pkts);
+	(void) REG_RD(pDevice, mib.tx_underruns);
+	(void) REG_RD(pDevice, mib.tx_total_cols);
+	(void) REG_RD(pDevice, mib.tx_single_cols);
+	(void) REG_RD(pDevice, mib.tx_multiple_cols);
+	(void) REG_RD(pDevice, mib.tx_excessive_cols);
+	(void) REG_RD(pDevice, mib.tx_late_cols);
+	(void) REG_RD(pDevice, mib.tx_defered);
+	(void) REG_RD(pDevice, mib.tx_carrier_lost);
+	(void) REG_RD(pDevice, mib.tx_pause_pkts);
+	(void) REG_RD(pDevice, mib.rx_good_octets);
+	(void) REG_RD(pDevice, mib.rx_good_pkts);
+	(void) REG_RD(pDevice, mib.rx_octets);
+	(void) REG_RD(pDevice, mib.rx_pkts);
+	(void) REG_RD(pDevice, mib.rx_broadcast_pkts);
+	(void) REG_RD(pDevice, mib.rx_multicast_pkts);
+	(void) REG_RD(pDevice, mib.rx_len_64);
+	(void) REG_RD(pDevice, mib.rx_len_65_to_127);
+	(void) REG_RD(pDevice, mib.rx_len_128_to_255);
+	(void) REG_RD(pDevice, mib.rx_len_256_to_511);
+	(void) REG_RD(pDevice, mib.rx_len_512_to_1023);
+	(void) REG_RD(pDevice, mib.rx_len_1024_to_max);
+	(void) REG_RD(pDevice, mib.rx_jabber_pkts);
+	(void) REG_RD(pDevice, mib.rx_oversize_pkts);
+	(void) REG_RD(pDevice, mib.rx_fragment_pkts);
+	(void) REG_RD(pDevice, mib.rx_missed_pkts);
+	(void) REG_RD(pDevice, mib.rx_crc_align_errs);
+	(void) REG_RD(pDevice, mib.rx_undersize);
+	(void) REG_RD(pDevice, mib.rx_crc_errs);
+	(void) REG_RD(pDevice, mib.rx_align_errs);
+	(void) REG_RD(pDevice, mib.rx_symbol_errs);
+	(void) REG_RD(pDevice, mib.rx_pause_pkts);
+	(void) REG_RD(pDevice, mib.rx_nonpause_pkts);
+	pDevice->mibgood = TRUE;
+}
+
+void
+b44_LM_ServiceRxInterrupt(LM_DEVICE_BLOCK *pDevice)
+{
+	LM_UINT32 rxin, curr, rxdmask;
+	unsigned int len;
+	int skiplen = 0;
+	bcmenetrxh_t *rxh;
+	LM_PACKET *pPacket;
+
+	curr = (REG_RD(pDevice, dmaregs.rcvstatus) & RS_CD_MASK);
+	curr = curr / sizeof(dmadd_t);
+	rxdmask = pDevice->MaxRxPacketDescCnt - 1;
+	for (rxin = pDevice->rxin; rxin != curr; rxin = (rxin + 1) & rxdmask)
+	{
+		pPacket = pDevice->RxPacketArr[rxin];
+		if (skiplen > 0) {
+			pPacket->PacketStatus = LM_STATUS_FAILURE;
+			skiplen -= pPacket->u.Rx.RxBufferSize;
+			if (skiplen < 0)
+				skiplen = 0;
+			goto rx_err;
+		}
+		rxh = (bcmenetrxh_t *) pPacket->u.Rx.pRxBufferVirt;
+		len = cpu_to_le16(rxh->len);
+		if (len > (pPacket->u.Rx.RxBufferSize - pDevice->rxoffset)) {
+			pPacket->PacketStatus = LM_STATUS_FAILURE;
+			skiplen = len - (pPacket->u.Rx.RxBufferSize -
+				pDevice->rxoffset);
+		}
+		else {
+			int i = 0;
+
+			if (len == 0) {
+				while ((len == 0) && (i < 5)) {
+					b44_MM_Wait(2);
+					len = cpu_to_le16(rxh->len);
+					i++;
+				}
+				if (len == 0) {
+					pPacket->PacketStatus =
+						LM_STATUS_FAILURE;
+					goto rx_err;
+				}
+			}
+			if (cpu_to_le16(rxh->flags) & RXF_ERRORS) {
+				pPacket->PacketStatus = LM_STATUS_FAILURE;
+			}
+			else {
+				pPacket->PacketStatus = LM_STATUS_SUCCESS;
+			}
+			pPacket->PacketSize = len - 4;
+		}
+rx_err:
+		QQ_PushTail(&pDevice->RxPacketReceivedQ.Container,
+			pPacket);
+		curr = (REG_RD(pDevice, dmaregs.rcvstatus) & RS_CD_MASK) /
+			sizeof(dmadd_t);
+	}
+	pDevice->rxin = curr;
+}
+
+void
+b44_LM_ServiceTxInterrupt(LM_DEVICE_BLOCK *pDevice)
+{
+	LM_UINT32 txin, curr, txdmask;
+	LM_PACKET *pPacket;
+
+	curr = (REG_RD(pDevice, dmaregs.xmtstatus) & XS_CD_MASK);
+	curr = curr / sizeof(dmadd_t);
+	txdmask = pDevice->TxPacketDescCnt - 1;
+	for (txin = pDevice->txin; txin != curr; txin = (txin + 1) & txdmask)
+	{
+		if ((pPacket = pDevice->TxPacketArr[txin])) {
+			QQ_PushTail(&pDevice->TxPacketXmittedQ.Container,
+				pPacket);
+			pDevice->TxPacketArr[txin] = 0;
+			atomic_add(pPacket->u.Tx.FragCount,
+				&pDevice->SendDescLeft);
+		}
+	}
+	pDevice->txin = curr;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*    This is the interrupt event handler routine. It acknowledges all        */
+/*    pending interrupts and process all pending events.                      */
+/*                                                                            */
+/* Return:                                                                    */
+/*    LM_STATUS_SUCCESS                                                       */
+/******************************************************************************/
+LM_STATUS
+b44_LM_ServiceInterrupts(PLM_DEVICE_BLOCK pDevice)
+{
+	LM_UINT32 intstatus, intmask;
+
+	while (1) {
+		intstatus = REG_RD(pDevice, intstatus);
+		intmask = REG_RD(pDevice, intmask);
+
+		/* defer unsolicited interrupts */
+		intstatus &= intmask;
+
+		/* if not for us */
+		if (intstatus == 0)
+			return LM_STATUS_SUCCESS;
+
+		REG_WR(pDevice, intstatus, intstatus);
+
+		if (intstatus & I_RI) {
+			b44_LM_ServiceRxInterrupt(pDevice);
+		}
+
+		if (intstatus & (I_XI | I_TO)) {
+			b44_LM_ServiceTxInterrupt(pDevice);
+			REG_WR(pDevice, gptimer, 0);
+		}
+		if (intstatus & I_ERRORS) {
+			b44_LM_ResetAdapter(pDevice);
+		}
+		if (!QQ_Empty(&pDevice->RxPacketReceivedQ.Container)) {
+			b44_MM_IndicateRxPackets(pDevice);
+		}
+		if (!QQ_Empty(&pDevice->TxPacketXmittedQ.Container)) {
+			b44_MM_IndicateTxPackets(pDevice);
+		}
+	}
+	return LM_STATUS_SUCCESS;
+} /* LM_ServiceInterrupts */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+b44_LM_MulticastAdd(
+PLM_DEVICE_BLOCK pDevice,
+PLM_UINT8 pMcAddress) {
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, increment the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1;
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+    
+    if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE)
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    pEntry = pDevice->McTable[pDevice->McEntryCount];
+
+    COPY_ETH_ADDRESS(pMcAddress, pEntry);
+    pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1;
+
+    pDevice->McEntryCount++;
+
+    b44_LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* b44_LM_MulticastAdd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+b44_LM_MulticastDel(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress)
+{
+    PLM_UINT8 pEntry;
+    LM_UINT32 j;
+
+    pEntry = pDevice->McTable[0];
+    for(j = 0; j < pDevice->McEntryCount; j++)
+    {
+        if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress))
+        {
+            /* Found a match, decrement the instance count. */
+            pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1;
+
+            /* No more instance left, remove the address from the table. */
+            /* Move the last entry in the table to the delete slot. */
+            if(pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 &&
+                pDevice->McEntryCount > 1)
+            {
+
+                COPY_ETH_ADDRESS(
+                    pDevice->McTable[pDevice->McEntryCount-1], pEntry);
+                pEntry[LM_MC_INSTANCE_COUNT_INDEX] =
+                    pDevice->McTable[pDevice->McEntryCount-1]
+                    [LM_MC_INSTANCE_COUNT_INDEX];
+            }
+            pDevice->McEntryCount--;
+
+            /* Update the receive mask if the table is empty. */
+            if(pDevice->McEntryCount == 0)
+            {
+                b44_LM_SetReceiveMask(pDevice, 
+                    pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+            }
+
+            return LM_STATUS_SUCCESS;
+        }
+
+        pEntry += LM_MC_ENTRY_SIZE;
+    }
+
+    return LM_STATUS_FAILURE;
+} /* b44_LM_MulticastDel */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+b44_LM_MulticastClear(
+PLM_DEVICE_BLOCK pDevice) {
+    pDevice->McEntryCount = 0;
+
+    b44_LM_SetReceiveMask(pDevice, pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+} /* b44_LM_MulticastClear */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+b44_LM_SetMacAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress)
+{
+    return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+b44_LM_SetFlowControl(
+    PLM_DEVICE_BLOCK pDevice,
+    LM_UINT32 LocalPhyAd,
+    LM_UINT32 RemotePhyAd)
+{
+    LM_FLOW_CONTROL FlowCap;
+
+    /* Resolve flow control. */
+    FlowCap = LM_FLOW_CONTROL_NONE;
+
+    /* See Table 28B-3 of 802.3ab-1999 spec. */
+    if(pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE)
+    {
+        if(LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE)
+        {
+            if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+                else if(RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+            else
+            {
+                if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE)
+                {
+                    FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+                        LM_FLOW_CONTROL_RECEIVE_PAUSE;
+                }
+            }
+        }
+        else if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE)
+        {
+            if((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) &&
+                (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE))
+            {
+                FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+            }
+        }
+    }
+    else
+    {
+        FlowCap = pDevice->FlowControlCap;
+    }
+
+    /* Enable/disable rx PAUSE. */
+    if(FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+        REG_WR(pDevice, rxconfig, ERC_EF);
+
+    }
+
+    /* Enable/disable tx PAUSE. */
+    if(FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE &&
+        (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE ||
+        pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))
+    {
+        pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+        REG_WR(pDevice, emacflowcontrol, EMF_PG | (0xc0 & EMF_RFH_MASK));
+
+    }
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+b44_LM_SetupPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+	LM_UINT32 Value32;
+	LM_UINT32 Adv, FCAdv, Ctrl;
+	int RestartAuto = 0;
+
+	/* enable activity led */
+	b44_LM_ReadPhy(pDevice, 26, &Value32);
+	b44_LM_WritePhy(pDevice, 26, Value32 & 0x7fff);
+
+	/* enable traffic meter led mode */
+	b44_LM_ReadPhy(pDevice, 27, &Value32);
+	b44_LM_WritePhy(pDevice, 27, Value32 | (1 << 6));
+	if (!pDevice->DisableAutoNeg) {
+		if (pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) {
+			Adv = PHY_AN_AD_ALL_SPEEDS;
+		}
+		else if (pDevice->RequestedLineSpeed == LM_LINE_SPEED_10MBPS) {
+			if (pDevice->RequestedDuplexMode ==
+				LM_DUPLEX_MODE_FULL) {
+				Adv = PHY_AN_AD_10BASET_FULL;
+			}
+			else {
+				Adv = PHY_AN_AD_10BASET_HALF;
+			}
+		}
+		else if (pDevice->RequestedLineSpeed == LM_LINE_SPEED_100MBPS) {
+			if (pDevice->RequestedDuplexMode ==
+				LM_DUPLEX_MODE_FULL) {
+				Adv = PHY_AN_AD_100BASETX_FULL;
+			}
+			else {
+				Adv = PHY_AN_AD_100BASETX_HALF;
+			}
+		}
+		else {
+			Adv = PHY_AN_AD_ALL_SPEEDS;
+		}
+
+		if ((pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) ||
+			(pDevice->RequestedDuplexMode == LM_DUPLEX_MODE_FULL)) {
+			FCAdv = b44_GetPhyAdFlowCntrlSettings(pDevice);
+			Value32 &= PHY_AN_AD_ASYM_PAUSE |
+				PHY_AN_AD_PAUSE_CAPABLE;
+			if (FCAdv != Value32) {
+				RestartAuto = 1;
+				Adv |= FCAdv;
+				goto restart_auto_neg;
+			}
+		}
+
+		b44_LM_ReadPhy(pDevice, PHY_CTRL_REG, &Ctrl);
+		if (!(Ctrl & PHY_CTRL_AUTO_NEG_ENABLE)) {
+			RestartAuto = 1;
+			goto restart_auto_neg;
+		}
+		b44_LM_ReadPhy(pDevice, PHY_AN_AD_REG, &Value32);
+		if ((Value32 & PHY_AN_AD_ALL_SPEEDS) != Adv) {
+			RestartAuto = 1;
+		}
+restart_auto_neg:
+		if (RestartAuto) {
+			Adv |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
+			b44_LM_WritePhy(pDevice, PHY_AN_AD_REG, Adv);
+			b44_LM_WritePhy(pDevice, PHY_CTRL_REG,
+				PHY_CTRL_AUTO_NEG_ENABLE |
+				PHY_CTRL_RESTART_AUTO_NEG);
+		}
+		pDevice->Advertising = Adv;
+	}
+	else {
+		b44_LM_ReadPhy(pDevice, PHY_CTRL_REG, &Ctrl);
+		Ctrl &= ~(PHY_CTRL_SPEED_SELECT_100MBPS |
+			PHY_CTRL_FULL_DUPLEX_MODE | PHY_CTRL_AUTO_NEG_ENABLE);
+		if (pDevice->RequestedLineSpeed == LM_LINE_SPEED_100MBPS) {
+			Ctrl |= PHY_CTRL_SPEED_SELECT_100MBPS;
+		}
+		if (pDevice->RequestedDuplexMode == LM_DUPLEX_MODE_FULL) {
+			Ctrl |= PHY_CTRL_FULL_DUPLEX_MODE;
+		}
+		b44_LM_WritePhy(pDevice, PHY_CTRL_REG, Ctrl);
+		if (pDevice->RequestedDuplexMode == LM_DUPLEX_MODE_FULL) {
+			pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE;
+			b44_LM_SetFlowControl(pDevice, 0, 0);
+		}
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_LM_ResetPhy(LM_DEVICE_BLOCK *pDevice)
+{
+	LM_UINT32 value32;
+
+	b44_LM_WritePhy(pDevice, 0, PHY_CTRL_PHY_RESET);
+	b44_MM_Wait(100);
+	b44_LM_ReadPhy(pDevice, 0, &value32);
+	if (value32 & PHY_CTRL_PHY_RESET) {
+		printf(KERN_ALERT "Phy reset not complete\n");
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+b44_LM_ReadPhy(
+PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, LM_UINT32 *pData32)
+{
+	/* clear mii_int */
+	REG_WR(pDevice, emacintstatus, EI_MII);
+
+	/* issue the read */
+	REG_WR(pDevice, mdiodata, (MD_SB_START | MD_OP_READ |
+		(pDevice->PhyAddr << MD_PMD_SHIFT)
+		| (PhyReg << MD_RA_SHIFT) | MD_TA_VALID));
+
+	/* wait for it to complete */
+	SPINWAIT(((REG_RD(pDevice, emacintstatus) & EI_MII) == 0), 100);
+	if ((REG_RD(pDevice, emacintstatus) & EI_MII) == 0) {
+		printf("LM_ReadPhy: did not complete\n");
+	}
+
+	*pData32 = REG_RD(pDevice, mdiodata) & MD_DATA_MASK;
+} /* LM_ReadPhy */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+b44_LM_WritePhy(
+PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, LM_UINT32 Data32)
+{
+	/* clear mii_int */
+	REG_WR(pDevice, emacintstatus, EI_MII);
+	ASSERT((REG_RD(pDevice, emacintstatus) & EI_MII) == 0);
+
+	/* issue the write */
+	REG_WR(pDevice, mdiodata, (MD_SB_START | MD_OP_WRITE |
+		(pDevice->PhyAddr << MD_PMD_SHIFT)
+		| (PhyReg << MD_RA_SHIFT) | MD_TA_VALID | Data32));
+
+	/* wait for it to complete */
+	SPINWAIT(((REG_RD(pDevice, emacintstatus) & EI_MII) == 0), 100);
+	if ((REG_RD(pDevice, emacintstatus) & EI_MII) == 0) {
+		printf("b44_LM_WritePhy: did not complete\n");
+	}
+} /* LM_WritePhy */
+
+
+LM_STATUS
+b44_LM_StatsUpdate(LM_DEVICE_BLOCK *pDevice)
+{
+	pDevice->tx_good_octets += REG_RD(pDevice, mib.tx_good_octets);
+	pDevice->tx_good_pkts += REG_RD(pDevice, mib.tx_good_pkts);
+	pDevice->tx_octets += REG_RD(pDevice, mib.tx_octets);
+	pDevice->tx_pkts += REG_RD(pDevice, mib.tx_pkts);
+	pDevice->tx_broadcast_pkts += REG_RD(pDevice, mib.tx_broadcast_pkts);
+	pDevice->tx_multicast_pkts += REG_RD(pDevice, mib.tx_multicast_pkts);
+	pDevice->tx_len_64 += REG_RD(pDevice, mib.tx_len_64);
+	pDevice->tx_len_65_to_127 += REG_RD(pDevice, mib.tx_len_65_to_127);
+	pDevice->tx_len_128_to_255 += REG_RD(pDevice, mib.tx_len_128_to_255);
+	pDevice->tx_len_256_to_511 += REG_RD(pDevice, mib.tx_len_256_to_511);
+	pDevice->tx_len_512_to_1023 += REG_RD(pDevice, mib.tx_len_512_to_1023);
+	pDevice->tx_len_1024_to_max += REG_RD(pDevice, mib.tx_len_1024_to_max);
+	pDevice->tx_jabber_pkts += REG_RD(pDevice, mib.tx_jabber_pkts);
+	pDevice->tx_oversize_pkts += REG_RD(pDevice, mib.tx_oversize_pkts);
+	pDevice->tx_fragment_pkts += REG_RD(pDevice, mib.tx_fragment_pkts);
+	pDevice->tx_underruns += REG_RD(pDevice, mib.tx_underruns);
+	pDevice->tx_total_cols += REG_RD(pDevice, mib.tx_total_cols);
+	pDevice->tx_single_cols += REG_RD(pDevice, mib.tx_single_cols);
+	pDevice->tx_multiple_cols += REG_RD(pDevice, mib.tx_multiple_cols);
+	pDevice->tx_excessive_cols += REG_RD(pDevice, mib.tx_excessive_cols);
+	pDevice->tx_late_cols += REG_RD(pDevice, mib.tx_late_cols);
+	pDevice->tx_defered += REG_RD(pDevice, mib.tx_defered);
+	pDevice->tx_carrier_lost += REG_RD(pDevice, mib.tx_carrier_lost);
+	pDevice->tx_pause_pkts += REG_RD(pDevice, mib.tx_pause_pkts);
+
+	pDevice->rx_good_octets += REG_RD(pDevice, mib.rx_good_octets);
+	pDevice->rx_good_pkts += REG_RD(pDevice, mib.rx_good_pkts);
+	pDevice->rx_octets += REG_RD(pDevice, mib.rx_octets);
+	pDevice->rx_pkts += REG_RD(pDevice, mib.rx_pkts);
+	pDevice->rx_broadcast_pkts += REG_RD(pDevice, mib.rx_broadcast_pkts);
+	pDevice->rx_multicast_pkts += REG_RD(pDevice, mib.rx_multicast_pkts);
+	pDevice->rx_len_64 += REG_RD(pDevice, mib.rx_len_64);
+	pDevice->rx_len_65_to_127 += REG_RD(pDevice, mib.rx_len_65_to_127);
+	pDevice->rx_len_128_to_255 += REG_RD(pDevice, mib.rx_len_128_to_255);
+	pDevice->rx_len_256_to_511 += REG_RD(pDevice, mib.rx_len_256_to_511);
+	pDevice->rx_len_512_to_1023 += REG_RD(pDevice, mib.rx_len_512_to_1023);
+	pDevice->rx_len_1024_to_max += REG_RD(pDevice, mib.rx_len_1024_to_max);
+	pDevice->rx_jabber_pkts += REG_RD(pDevice, mib.rx_jabber_pkts);
+	pDevice->rx_oversize_pkts += REG_RD(pDevice, mib.rx_oversize_pkts);
+	pDevice->rx_fragment_pkts += REG_RD(pDevice, mib.rx_fragment_pkts);
+	pDevice->rx_missed_pkts += REG_RD(pDevice, mib.rx_missed_pkts);
+	pDevice->rx_crc_align_errs += REG_RD(pDevice, mib.rx_crc_align_errs);
+	pDevice->rx_undersize += REG_RD(pDevice, mib.rx_undersize);
+	pDevice->rx_crc_errs += REG_RD(pDevice, mib.rx_crc_errs);
+	pDevice->rx_align_errs += REG_RD(pDevice, mib.rx_align_errs);
+	pDevice->rx_symbol_errs += REG_RD(pDevice, mib.rx_symbol_errs);
+	pDevice->rx_pause_pkts += REG_RD(pDevice, mib.rx_pause_pkts);
+	pDevice->rx_nonpause_pkts += REG_RD(pDevice, mib.rx_nonpause_pkts);
+
+	return LM_STATUS_SUCCESS;
+}
+
+void
+b44_LM_WriteCam(LM_DEVICE_BLOCK *pDevice, LM_UINT8 *ea, LM_UINT32 camindex)
+{
+	LM_UINT32 w;
+
+	w = ((LM_UINT32)ea[2] << 24) | ((LM_UINT32)ea[3] << 16) |
+		((LM_UINT32) ea[4] << 8) | ea[5];
+	REG_WR(pDevice, camdatalo, w);
+	w = CD_V | ((LM_UINT32)ea[0] << 8) | ea[1];
+	REG_WR(pDevice, camdatahi, w);
+	REG_WR(pDevice, camcontrol, (((LM_UINT32) camindex << CC_INDEX_SHIFT) |
+		CC_WR));
+
+	/* spin until done */
+	SPINWAIT((REG_RD(pDevice, camcontrol) & CC_CB), 100);
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+static LM_UINT32
+b44_GetPhyAdFlowCntrlSettings(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+
+    Value32 = 0;
+
+    /* Auto negotiation flow control only when autonegotiation is enabled. */
+    if(pDevice->DisableAutoNeg == FALSE ||
+        pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO)
+    {
+        /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */
+        if((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) ||
+            ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
+            (pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_ASYM_PAUSE;
+        }
+        else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)
+        {
+            Value32 |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
+        }
+    }
+
+    return Value32;
+}
+
+
+LM_STATUS
+b44_LM_GetStats(PLM_DEVICE_BLOCK pDevice)
+{
+    return LM_STATUS_SUCCESS;
+}
+
+void
+b44_LM_PollLink(LM_DEVICE_BLOCK *pDevice)
+{
+	LM_UINT32 status, aux;
+	LM_UINT32 txcontrol;
+	LM_UINT32 LocalAdv, RemoteAdv;
+
+	b44_LM_ReadPhy(pDevice, 1, &status);
+	b44_LM_ReadPhy(pDevice, 24, &aux);
+
+	/* check for bad mdio read */
+	if (status == 0xffff) {
+		return;
+	}
+
+	/* update current speed and duplex */
+	if (aux & AUX_SPEED)
+		pDevice->LineSpeed = LM_LINE_SPEED_100MBPS;
+	else
+		pDevice->LineSpeed = LM_LINE_SPEED_10MBPS;
+	if (aux & AUX_DUPLEX)
+		pDevice->DuplexMode = LM_DUPLEX_MODE_FULL;
+	else
+		pDevice->DuplexMode = LM_DUPLEX_MODE_HALF;
+
+	/* monitor link state */
+	if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) &&
+		(status & STAT_LINK)) {
+
+		/* keep emac txcontrol duplex bit consistent with current */
+		/* phy duplex */
+		txcontrol = REG_RD(pDevice, txcontrol);
+		if ((pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) &&
+			!(txcontrol & EXC_FD)) {
+
+			REG_OR(pDevice, txcontrol, EXC_FD);
+		}
+		else if ((pDevice->DuplexMode == LM_DUPLEX_MODE_HALF) &&
+			(txcontrol & EXC_FD)) {
+
+			REG_AND(pDevice, txcontrol, ~EXC_FD);
+		}
+		if (!pDevice->DisableAutoNeg && (pDevice->DuplexMode ==
+			LM_DUPLEX_MODE_FULL)) {
+
+			b44_LM_ReadPhy(pDevice, PHY_AN_AD_REG, &LocalAdv);
+			b44_LM_ReadPhy(pDevice, PHY_LINK_PARTNER_ABILITY_REG,
+				&RemoteAdv);
+			b44_LM_SetFlowControl(pDevice, LocalAdv, RemoteAdv);
+		}
+
+		pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE;
+		b44_MM_IndicateStatus(pDevice, LM_STATUS_LINK_ACTIVE);
+	}
+	else if ((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) &&
+		!(status & STAT_LINK)) {
+
+		pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+		b44_MM_IndicateStatus(pDevice, LM_STATUS_LINK_DOWN);
+	}
+
+
+	/* check for remote fault error */
+	if (status & STAT_REMFAULT) {
+		printf("remote fault\n");
+	}
+
+	/* check for jabber error */
+	if (status & STAT_JAB) {
+		printf("jabber\n");
+	}
+}
+
+/* reset and re-enable a core */
+void
+b44_LM_sb_core_reset(LM_DEVICE_BLOCK *pDevice)
+{
+	volatile LM_UINT32 dummy;
+
+	/*
+	 * Must do the disable sequence first to work for arbitrary current core state.
+	 */
+	b44_LM_sb_core_disable(pDevice);
+
+	/*
+	 * Now do the initialization sequence.
+	 */
+
+	/* set reset while enabling the clock and forcing them on throughout the core */
+	REG_WR(pDevice, sbconfig.sbtmstatelow,
+		(SBTML_FGC | SBTML_CLK | SBTML_RESET));
+
+	dummy = REG_RD(pDevice, sbconfig.sbtmstatelow);
+	b44_MM_Wait(1);
+
+	/* PR3158 workaround - not fixed in any chip yet */
+	if (REG_RD(pDevice, sbconfig.sbtmstatehigh) & SBTMH_SERR) {
+		printf("SBTMH_SERR; clearing...\n");
+		REG_WR(pDevice, sbconfig.sbtmstatehigh, 0);
+		ASSERT(0);
+	}
+	if ((dummy = REG_RD(pDevice, sbconfig.sbimstate)) &
+		(SBIM_IBE | SBIM_TO)) {
+
+		REG_AND(pDevice, sbconfig.sbimstate, ~(SBIM_IBE | SBIM_TO));
+		ASSERT(0);
+	}
+
+	/* clear reset and allow it to propagate throughout the core */
+	REG_WR(pDevice, sbconfig.sbtmstatelow, (SBTML_FGC | SBTML_CLK));
+	dummy = REG_RD(pDevice, sbconfig.sbtmstatelow);
+	b44_MM_Wait(1);
+
+	/* leave clock enabled */
+	REG_WR(pDevice, sbconfig.sbtmstatelow, SBTML_CLK);
+	dummy = REG_RD(pDevice, sbconfig.sbtmstatelow);
+	b44_MM_Wait(1);
+}
+
+void
+b44_LM_sb_core_disable(LM_DEVICE_BLOCK *pDevice)
+{
+	volatile LM_UINT32 dummy;
+
+	/* must return if core is already in reset */
+	if (REG_RD(pDevice, sbconfig.sbtmstatelow) & SBTML_RESET)
+		return;
+	
+	/* set the reject bit */
+	REG_WR(pDevice, sbconfig.sbtmstatelow, (SBTML_CLK | SBTML_REJ));
+
+	/* spin until reject is set */
+	while ((REG_RD(pDevice, sbconfig.sbtmstatelow) & SBTML_REJ) == 0)
+		b44_MM_Wait(1);
+
+	/* spin until sbtmstatehigh.busy is clear */
+	while (REG_RD(pDevice, sbconfig.sbtmstatehigh) & SBTMH_BUSY)
+		b44_MM_Wait(1);
+
+	/* set reset and reject while enabling the clocks */
+	REG_WR(pDevice, sbconfig.sbtmstatelow,
+		(SBTML_FGC | SBTML_CLK | SBTML_REJ | SBTML_RESET));
+
+	dummy = REG_RD(pDevice, sbconfig.sbtmstatelow);
+	b44_MM_Wait(10);
+
+	/* leave reset and reject asserted */
+	REG_WR(pDevice, sbconfig.sbtmstatelow, (SBTML_REJ | SBTML_RESET));
+	b44_MM_Wait(1);
+}
+
+/*
+ * Configure the pci core for pci client (NIC) action
+ * and return the pci core revision.
+ */
+LM_UINT32
+b44_LM_sb_pci_setup(LM_DEVICE_BLOCK *pDevice, LM_UINT32 cores)
+{
+	LM_UINT32 bar0window;
+	sbpciregs_t *pciregs;
+	LM_UINT32 pcirev;
+
+	pciregs = (sbpciregs_t *) pDevice->pMemView;
+
+	/* save bar0window */
+	b44_MM_ReadConfig32(pDevice, PCI_BAR0_WIN, &bar0window);
+	/* point bar0 at pci core registers */
+	b44_MM_WriteConfig32(pDevice, PCI_BAR0_WIN, b44_LM_getsbaddr(pDevice,
+		SBID_REG_PCI, 0));
+
+	ASSERT(b44_LM_sb_coreid(pDevice) == SB_PCI);
+
+	pcirev = b44_LM_sb_corerev(pDevice);
+
+	/* enable sb->pci interrupts */
+	REG_OR(pDevice, sbconfig.sbintvec, cores);
+
+	/* enable prefetch and bursts for sonics-to-pci translation 2 */
+	REG_WR_OFFSET(pDevice, OFFSETOF(sbpciregs_t, sbtopci2),
+		REG_RD_OFFSET(pDevice, OFFSETOF(sbpciregs_t, sbtopci2)) |
+		(SBTOPCI_PREF|SBTOPCI_BURST));
+
+	/* restore bar0window */
+	b44_MM_WriteConfig32(pDevice, PCI_BAR0_WIN, bar0window);
+
+	return (pcirev);
+}
+
+/*
+ * Return the SB address corresponding to core <id> instance <coreunit>.
+ * Provide a layer of indirection between SB address map elements
+ * and the individual chip maps.
+ */
+LM_UINT32
+b44_LM_getsbaddr(LM_DEVICE_BLOCK *pDevice, LM_UINT32 id, LM_UINT32 coreunit)
+{
+	struct sbmap *sbmap;
+	int i;
+
+	sbmap = pDevice->sbmap;
+	ASSERT(sbmap);
+
+	for (i = 0; i < SBID_MAX; i++)
+		if ((id == sbmap[i].id) && (coreunit == sbmap[i].coreunit))
+			return (sbmap[i].sbaddr);
+
+	ASSERT(0);
+	return (0xdeadbeef);
+}
+
+LM_UINT32
+b44_LM_sb_base(LM_UINT32 admatch)
+{
+	LM_UINT32 base;
+	LM_UINT32 type;
+
+	type = admatch & SBAM_TYPE_MASK;
+	ASSERT(type < 3);
+
+	base = 0;
+
+	if (type == 0) {
+		base = admatch & SBAM_BASE0_MASK;
+	} else if (type == 1) {
+		ASSERT(admatch & SBAM_ADEN);
+		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
+		base = admatch & SBAM_BASE1_MASK;
+	} else if (type == 2) {
+		ASSERT(admatch & SBAM_ADEN);
+		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
+		base = admatch & SBAM_BASE2_MASK;
+	}
+
+	return (base);
+}
+
+LM_UINT32
+b44_LM_sb_size(LM_UINT32 admatch)
+{
+	LM_UINT32 size;
+	LM_UINT32 type;
+
+	type = admatch & SBAM_TYPE_MASK;
+	ASSERT(type < 3);
+
+	size = 0;
+
+	if (type == 0) {
+		size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1);
+	} else if (type == 1) {
+		ASSERT(admatch & SBAM_ADEN);
+		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
+		size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1);
+	} else if (type == 2) {
+		ASSERT(admatch & SBAM_ADEN);
+		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
+		size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1);
+	}
+
+	return (size);
+}
+
+/* return the core instance number of this core */
+LM_UINT32
+b44_LM_sb_coreunit(LM_DEVICE_BLOCK *pDevice)
+{
+	struct sbmap *sbmap;
+	LM_UINT32 base;
+	int i;
+
+	sbmap = pDevice->sbmap;
+	ASSERT(sbmap);
+
+	base = b44_LM_sb_base(REG_RD(pDevice, sbconfig.sbadmatch0));
+
+	for (i = 0; i < SBID_MAX; i++)
+		if (base == sbmap[i].sbaddr)
+			return (sbmap[i].coreunit);
+
+	ASSERT(0);
+	return (0xdeadbeef);
+}
+
+
+LM_UINT32
+b44_LM_sb_clock(LM_DEVICE_BLOCK *pDevice, LM_UINT32 extifva)
+{
+	ASSERT(0);	/* XXX TBD */
+	return (0);
+}
+
+LM_UINT32
+b44_LM_sb_coreid(LM_DEVICE_BLOCK *pDevice)
+{
+	return ((REG_RD(pDevice, sbconfig.sbidhigh) &
+		SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
+}
+
+LM_UINT32
+b44_LM_sb_corerev(LM_DEVICE_BLOCK *pDevice)
+{
+	return (REG_RD(pDevice, sbconfig.sbidhigh) & SBIDH_RC_MASK);
+}
+
+LM_UINT32
+b44_LM_sb_iscoreup(LM_DEVICE_BLOCK *pDevice)
+{
+	return ((REG_RD(pDevice, sbconfig.sbtmstatelow) &
+		(SBTML_RESET | SBTML_REJ | SBTML_CLK)) == SBTML_CLK);
+}
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44lm.h orig/drivers/net/bcm4400/b44lm.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44lm.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/b44lm.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,402 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM4400 Linux Network Driver, Copyright (c) 2002 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef B44LM_H
+#define B44LM_H
+
+#include "b44queue.h"
+
+
+
+/******************************************************************************/
+/* Basic types. */
+/******************************************************************************/
+
+typedef char           LM_CHAR,    *PLM_CHAR;
+typedef unsigned int   LM_UINT,    *PLM_UINT;
+typedef unsigned char  LM_UINT8,   *PLM_UINT8;
+typedef unsigned short LM_UINT16,  *PLM_UINT16;
+typedef unsigned int   LM_UINT32,  *PLM_UINT32;
+typedef unsigned long  LM_COUNTER, *PLM_COUNTER;
+typedef void           LM_VOID,    *PLM_VOID;
+typedef char           LM_BOOL,    *PLM_BOOL;
+
+typedef LM_UINT32 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS;
+
+#ifndef TRUE
+#define TRUE           1
+#endif /* TRUE */
+
+#ifndef FALSE
+#define FALSE          0
+#endif /* FALSE */
+
+#ifndef NULL
+#define NULL                ((void *) 0)
+#endif /* NULL */
+
+#ifndef OFFSETOF
+#define OFFSETOF(_s, _m)    (B44_MM_PTR(&(((_s *) 0)->_m)))
+#endif /* OFFSETOF */
+
+
+
+/******************************************************************************/
+/* Simple macros. */
+/******************************************************************************/
+
+#define IS_ETH_BROADCAST(_pEthAddr)                                         \
+    (((unsigned char *) (_pEthAddr))[0] == ((unsigned char) 0xff))
+
+#define IS_ETH_MULTICAST(_pEthAddr)                                         \
+    (((unsigned char *) (_pEthAddr))[0] & ((unsigned char) 0x01))
+
+#define IS_ETH_ADDRESS_EQUAL(_pEtherAddr1, _pEtherAddr2)                    \
+    ((((unsigned char *) (_pEtherAddr1))[0] ==                              \
+    ((unsigned char *) (_pEtherAddr2))[0]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[1] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[1]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[2] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[2]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[3] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[3]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[4] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[4]) &&                               \
+    (((unsigned char *) (_pEtherAddr1))[5] ==                               \
+    ((unsigned char *) (_pEtherAddr2))[5]))
+
+#define COPY_ETH_ADDRESS(_Src, _Dst)                                        \
+    ((unsigned char *) (_Dst))[0] = ((unsigned char *) (_Src))[0];          \
+    ((unsigned char *) (_Dst))[1] = ((unsigned char *) (_Src))[1];          \
+    ((unsigned char *) (_Dst))[2] = ((unsigned char *) (_Src))[2];          \
+    ((unsigned char *) (_Dst))[3] = ((unsigned char *) (_Src))[3];          \
+    ((unsigned char *) (_Dst))[4] = ((unsigned char *) (_Src))[4];          \
+    ((unsigned char *) (_Dst))[5] = ((unsigned char *) (_Src))[5];
+
+
+
+/******************************************************************************/
+/* Constants. */
+/******************************************************************************/
+
+#define ETHERNET_ADDRESS_SIZE           6
+#define ETHERNET_PACKET_HEADER_SIZE     14
+#define MIN_ETHERNET_PACKET_SIZE        64      /* with 4 byte crc. */
+#define MAX_ETHERNET_PACKET_SIZE        1518    /* with 4 byte crc. */
+#define MIN_ETHERNET_PACKET_SIZE_NO_CRC 60
+#define MAX_ETHERNET_PACKET_SIZE_NO_CRC 1514
+#define MAX_ETHERNET_PACKET_BUFFER_SIZE 1536    /* A nice even number. */
+
+#ifndef LM_MAX_MC_TABLE_SIZE
+#define LM_MAX_MC_TABLE_SIZE            32
+#endif /* LM_MAX_MC_TABLE_SIZE */
+#define LM_MC_ENTRY_SIZE                (ETHERNET_ADDRESS_SIZE+1)
+#define LM_MC_INSTANCE_COUNT_INDEX      (LM_MC_ENTRY_SIZE-1)
+
+
+/* Receive filter masks. */
+#define LM_ACCEPT_UNICAST               0x0001
+#define LM_ACCEPT_MULTICAST             0x0002
+#define LM_ACCEPT_ALL_MULTICAST         0x0004
+#define LM_ACCEPT_BROADCAST             0x0008
+#define LM_ACCEPT_ERROR_PACKET          0x0010
+
+#define LM_PROMISCUOUS_MODE             0x10000
+
+
+
+/******************************************************************************/
+/* PCI registers. */
+/******************************************************************************/
+
+#define PCI_VENDOR_ID_REG               0x00
+#define PCI_DEVICE_ID_REG               0x02
+
+#define PCI_COMMAND_REG                 0x04
+#define PCI_IO_SPACE_ENABLE             0x0001
+#define PCI_MEM_SPACE_ENABLE            0x0002
+#define PCI_BUSMASTER_ENABLE            0x0004
+#define PCI_MEMORY_WRITE_INVALIDATE     0x0010
+#define PCI_PARITY_ERROR_ENABLE         0x0040
+#define PCI_SYSTEM_ERROR_ENABLE         0x0100
+#define PCI_FAST_BACK_TO_BACK_ENABLE    0x0200
+
+#define PCI_STATUS_REG                  0x06
+#define PCI_REV_ID_REG                  0x08
+
+#define PCI_CACHE_LINE_SIZE_REG         0x0c
+
+#define PCI_IO_BASE_ADDR_REG            0x10
+#define PCI_IO_BASE_ADDR_MASK           0xfffffff0
+
+#define PCI_MEM_BASE_ADDR_LOW           0x10
+#define PCI_MEM_BASE_ADDR_HIGH          0x14
+
+#define PCI_SUBSYSTEM_VENDOR_ID_REG     0x2c
+#define PCI_SUBSYSTEM_ID_REG            0x2e
+#define PCI_INT_LINE_REG                0x3c
+
+#define PCIX_CAP_REG                    0x40
+#define PCIX_ENABLE_RELAXED_ORDERING    BIT_17
+
+/******************************************************************************/
+/* Fragment structure. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT32 FragSize;
+    LM_PHYSICAL_ADDRESS FragBuf;
+} LM_FRAG, *PLM_FRAG;
+
+typedef struct {
+    /* FragCount is initialized for the caller to the maximum array size, on */
+    /* return FragCount is the number of the actual fragments in the array. */
+    LM_UINT32 FragCount;
+
+    /* Total buffer size. */
+    LM_UINT32 TotalSize;
+
+    /* Fragment array buffer. */
+    LM_FRAG Fragments[1];
+} LM_FRAG_LIST, *PLM_FRAG_LIST;
+
+#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \
+    typedef struct {                                                         \
+        LM_FRAG_LIST FragList;                                               \
+        LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1];                           \
+    } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME
+
+
+
+/******************************************************************************/
+/* Status codes. */
+/******************************************************************************/
+
+#define LM_STATUS_SUCCESS                                       0
+#define LM_STATUS_FAILURE                                       1
+
+#define LM_STATUS_INTERRUPT_ACTIVE                              2
+#define LM_STATUS_INTERRUPT_NOT_ACTIVE                          3
+
+#define LM_STATUS_LINK_ACTIVE                                   4
+#define LM_STATUS_LINK_DOWN                                     5
+#define LM_STATUS_LINK_SETTING_MISMATCH                         6
+
+#define LM_STATUS_TOO_MANY_FRAGMENTS                            7
+#define LM_STATUS_TRANSMIT_ABORTED                              8
+#define LM_STATUS_TRANSMIT_ERROR                                9
+#define LM_STATUS_RECEIVE_ABORTED                               10
+#define LM_STATUS_RECEIVE_ERROR                                 11
+#define LM_STATUS_INVALID_PACKET_SIZE                           12
+#define LM_STATUS_OUT_OF_MAP_REGISTERS                          13
+#define LM_STATUS_UNKNOWN_ADAPTER                               14
+
+typedef LM_UINT LM_STATUS, *PLM_STATUS;
+
+
+/******************************************************************************/
+/* Line speed. */
+/******************************************************************************/
+
+#define LM_LINE_SPEED_UNKNOWN                                   0
+#define LM_LINE_SPEED_AUTO                  LM_LINE_SPEED_UNKNOWN
+#define LM_LINE_SPEED_10MBPS                                    10
+#define LM_LINE_SPEED_100MBPS                                   100
+
+typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED;
+
+
+
+/******************************************************************************/
+/* Duplex mode. */
+/******************************************************************************/
+
+#define LM_DUPLEX_MODE_UNKNOWN                                  0
+#define LM_DUPLEX_MODE_HALF                                     1
+#define LM_DUPLEX_MODE_FULL                                     2
+
+typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE;
+
+
+
+/******************************************************************************/
+/* Power state. */
+/******************************************************************************/
+
+#define LM_POWER_STATE_D0       0
+#define LM_POWER_STATE_D1       1
+#define LM_POWER_STATE_D2       2
+#define LM_POWER_STATE_D3       3
+
+typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE;
+
+
+
+/******************************************************************************/
+/* Task offloading. */
+/******************************************************************************/
+
+#define LM_TASK_OFFLOAD_NONE                    0x0000
+#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM          0x0001
+#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM          0x0002
+#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM         0x0004
+#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM         0x0008
+#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM         0x0010
+#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM         0x0020
+#define LM_TASK_OFFLOAD_TCP_SEGMENTATION        0x0040
+
+typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD;
+
+
+
+/******************************************************************************/
+/* Flow control. */
+/******************************************************************************/
+
+#define LM_FLOW_CONTROL_NONE                    0x00
+#define LM_FLOW_CONTROL_RECEIVE_PAUSE           0x01
+#define LM_FLOW_CONTROL_TRANSMIT_PAUSE          0x02
+#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \
+    LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+
+/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE.  If the */
+/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */
+/* bits are set, then flow control is enabled regardless of link partner's */
+/* flow control capability. */
+#define LM_FLOW_CONTROL_AUTO_PAUSE              0x80000000
+
+typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL;
+
+
+
+/******************************************************************************/
+/* Wake up mode. */
+/******************************************************************************/
+
+#define LM_WAKE_UP_MODE_NONE                    0
+#define LM_WAKE_UP_MODE_MAGIC_PACKET            1
+#define LM_WAKE_UP_MODE_NWUF                    2
+#define LM_WAKE_UP_MODE_LINK_CHANGE             4
+
+typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE;
+
+
+
+/******************************************************************************/
+/* Counters. */
+/******************************************************************************/
+
+#define LM_COUNTER_FRAMES_XMITTED_OK                            0
+#define LM_COUNTER_FRAMES_RECEIVED_OK                           1
+#define LM_COUNTER_ERRORED_TRANSMIT_COUNT                       2
+#define LM_COUNTER_ERRORED_RECEIVE_COUNT                        3
+#define LM_COUNTER_RCV_CRC_ERROR                                4
+#define LM_COUNTER_ALIGNMENT_ERROR                              5
+#define LM_COUNTER_SINGLE_COLLISION_FRAMES                      6
+#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES                    7
+#define LM_COUNTER_FRAMES_DEFERRED                              8
+#define LM_COUNTER_MAX_COLLISIONS                               9
+#define LM_COUNTER_RCV_OVERRUN                                  10
+#define LM_COUNTER_XMIT_UNDERRUN                                11
+#define LM_COUNTER_UNICAST_FRAMES_XMIT                          12
+#define LM_COUNTER_MULTICAST_FRAMES_XMIT                        13
+#define LM_COUNTER_BROADCAST_FRAMES_XMIT                        14
+#define LM_COUNTER_UNICAST_FRAMES_RCV                           15
+#define LM_COUNTER_MULTICAST_FRAMES_RCV                         16
+#define LM_COUNTER_BROADCAST_FRAMES_RCV                         17
+
+typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE;
+
+
+
+/******************************************************************************/
+/* Forward definition. */
+/******************************************************************************/
+
+typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK;
+typedef struct _LM_PACKET *PLM_PACKET;
+
+
+
+/******************************************************************************/
+/* Function prototypes. */
+/******************************************************************************/
+
+LM_STATUS b44_LM_GetAdapterInfo(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_InitializeAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_ResetAdapter(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_DisableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_EnableInterrupt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS b44_LM_ServiceInterrupts(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask);
+LM_STATUS b44_LM_Halt(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_Abort(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_MulticastAdd(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS b44_LM_MulticastDel(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress);
+LM_STATUS b44_LM_MulticastClear(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_SetMacAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress);
+LM_STATUS b44_LM_LoopbackAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress);
+
+LM_WAKE_UP_MODE b44_LM_PMCapabilities(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_SetPowerState(PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel);
+
+LM_VOID b44_LM_ReadPhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    PLM_UINT32 pData32);
+LM_VOID b44_LM_WritePhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg,
+    LM_UINT32 Data32);
+
+LM_STATUS b44_LM_SetupPhy(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_ResetPhy(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_GetStats(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_NvramRead(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 *pData);
+LM_STATUS b44_LM_NvramWriteBlock(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 *pData, LM_UINT32 Size);
+void b44_LM_PollLink(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_LM_StatsUpdate(PLM_DEVICE_BLOCK pDevice);
+
+
+/******************************************************************************/
+/* These are the OS specific functions called by LMAC. */
+/******************************************************************************/
+
+LM_STATUS b44_MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT16 *pValue16);
+LM_STATUS b44_MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT16 Value16);
+LM_STATUS b44_MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 *pValue32);
+LM_STATUS b44_MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+    LM_UINT32 Value32);
+LM_STATUS b44_MM_MapMemBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_MM_MapIoBase(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS b44_MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+LM_STATUS b44_MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, 
+    PLM_VOID *pMemoryBlockVirt);
+LM_STATUS b44_MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+    PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy);
+LM_STATUS b44_MM_GetConfig(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status);
+LM_STATUS b44_MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS b44_MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+
+
+#endif /* B44LM_H */
+
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44mm.h orig/drivers/net/bcm4400/b44mm.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44mm.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/b44mm.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,309 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM4400 Linux Network Driver, Copyright (c) 2002 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef B44MM_H
+#define B44MM_H
+
+#include <linux/config.h>
+#if defined(CONFIG_SMP) && ! defined(__SMP__)
+#define __SMP__
+#endif
+#if defined(CONFIG_MODVERSIONS) && defined(MODULE) && ! defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+
+#ifndef B44UM
+#define __NO_VERSION__
+#endif
+#include <linux/version.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#define SET_MODULE_OWNER(dev)
+#define MODULE_DEVICE_TABLE(pci, pci_tbl)
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <asm/processor.h>		/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/time.h>
+#if (LINUX_VERSION_CODE >= 0x020400)
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+#endif
+#ifdef CONFIG_PROC_FS
+#include <linux/smp_lock.h>
+#include <linux/proc_fs.h>
+#define BCM_PROC_FS 1
+#endif
+
+#ifdef __BIG_ENDIAN
+#define BIG_ENDIAN_HOST 1
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020327)
+#define __raw_readl readl
+#define __raw_writel writel
+#endif
+
+#include "b44lm.h"
+#include "b44queue.h"
+#include "b44.h"
+
+#if DBG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+extern int b44_Packet_Desc_Size;
+
+#define B44_MM_PACKET_DESC_SIZE b44_Packet_Desc_Size
+
+DECLARE_QUEUE_TYPE(UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT+1);
+
+#define MAX_MEM 16
+
+#if (LINUX_VERSION_CODE < 0x020211)
+typedef u32 dma_addr_t;
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032a)
+#define pci_map_single(dev, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(dev, dma_addr, size, dir)
+#endif
+
+#if MAX_SKB_FRAGS
+#if (LINUX_VERSION_CODE >= 0x02040d)
+
+typedef dma_addr_t dmaaddr_high_t;
+
+#else
+
+#if defined(CONFIG_HIGHMEM) && defined(CONFIG_X86)
+
+#if defined(CONFIG_HIGHMEM64G)
+typedef unsigned long long dmaaddr_high_t;
+#else
+typedef dma_addr_t dmaaddr_high_t;
+#endif
+
+#ifndef pci_map_page
+#define pci_map_page bcm_pci_map_page
+#endif
+
+static inline dmaaddr_high_t
+bcm_pci_map_page(struct pci_dev *dev, struct page *page,
+		    int offset, size_t size, int dir)
+{
+	dmaaddr_high_t phys;
+
+	phys = (page-mem_map) *	(dmaaddr_high_t) PAGE_SIZE + offset;
+
+	return phys;
+}
+
+#ifndef pci_unmap_page
+#define pci_unmap_page(dev, map, size, dir)
+#endif
+
+#else /* #if defined(CONFIG_HIGHMEM) && defined(CONFIG_X86) */
+
+typedef dma_addr_t dmaaddr_high_t;
+
+/* Warning - This may not work for all architectures if HIGHMEM is defined */
+
+#ifndef pci_map_page
+#define pci_map_page(dev, page, offset, size, dir) \
+	pci_map_single(dev, page_address(page) + (offset), size, dir)
+#endif
+#ifndef pci_unmap_page
+#define pci_unmap_page(dev, map, size, dir) \
+	pci_unmap_single(dev, map, size, dir)
+#endif
+
+#endif /* #if defined(CONFIG_HIGHMEM) && defined(CONFIG_X86)*/
+
+#endif /* #if (LINUX_VERSION_CODE >= 0x02040d)*/
+#endif /* #if MAX_SKB_FRAGS*/
+
+#if defined (CONFIG_X86)
+#define NO_PCI_UNMAP 1
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020412)
+#if ! defined (NO_PCI_UNMAP)
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME;
+
+#define pci_unmap_addr(PTR, ADDR_NAME)	\
+	((PTR)->ADDR_NAME)
+
+#define pci_unmap_len(PTR, LEN_NAME)	\
+	((PTR)->LEN_NAME)
+
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	\
+	(((PTR)->ADDR_NAME) = (VAL))
+
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	\
+	(((PTR)->LEN_NAME) = (VAL))
+#else
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(ADDR_NAME)
+
+#define pci_unmap_addr(PTR, ADDR_NAME)	0
+#define pci_unmap_len(PTR, LEN_NAME)	0
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02030e)
+#define net_device device
+#define netif_carrier_on(dev)
+#define netif_carrier_off(dev)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+#define tasklet_struct			tq_struct
+#endif
+
+typedef struct _UM_DEVICE_BLOCK {
+	LM_DEVICE_BLOCK lm_dev;
+	struct net_device *dev;
+	struct pci_dev *pdev;
+	struct net_device *next_module;
+	char *name;
+#ifdef BCM_PROC_FS
+	struct proc_dir_entry *pfs_entry;
+	char pfs_name[32];
+#endif
+	void *mem_list[MAX_MEM];
+	dma_addr_t dma_list[MAX_MEM];
+	int mem_size_list[MAX_MEM];
+	int mem_list_num;
+	int index;
+	int opened;
+	int delayed_link_ind; /* Delay link status during initial load */
+	int timer_interval;
+	int link_interval;
+	int tx_full;
+	int tx_queued;
+	int line_speed;		/* in Mbps, 0 if link is down */
+	UM_RX_PACKET_Q rx_out_of_buf_q;
+	int rx_out_of_buf;
+	int rx_buf_repl_thresh;
+	int rx_buf_repl_panic_thresh;
+	int rx_buf_align;
+	struct timer_list timer;
+	int do_global_lock;
+	spinlock_t global_lock;
+	volatile unsigned long interrupt;
+	atomic_t intr_sem;
+	int tasklet_pending;
+	volatile unsigned long tasklet_busy;
+	struct tasklet_struct tasklet;
+	struct net_device_stats stats;
+	uint rx_misc_errors;
+} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK;
+
+typedef struct _UM_PACKET {
+	LM_PACKET lm_packet;
+	struct sk_buff *skbuff;
+#if MAX_SKB_FRAGS
+	DECLARE_PCI_UNMAP_ADDR(map[MAX_SKB_FRAGS + 1])
+	DECLARE_PCI_UNMAP_LEN(map_len[MAX_SKB_FRAGS + 1])
+#else
+	DECLARE_PCI_UNMAP_ADDR(map[1])
+	DECLARE_PCI_UNMAP_LEN(map_len[1])
+#endif
+} UM_PACKET, *PUM_PACKET;
+
+
+static inline void b44_MM_MapRxDma(PLM_DEVICE_BLOCK pDevice,
+	struct _LM_PACKET *pPacket,
+	LM_UINT32 *paddr)
+{
+	dma_addr_t map;
+
+	map = pci_map_single(((struct _UM_DEVICE_BLOCK *)pDevice)->pdev,
+			pPacket->u.Rx.pRxBufferVirt,
+			pPacket->u.Rx.RxBufferSize,
+			PCI_DMA_FROMDEVICE);
+	pci_unmap_addr_set(((struct _UM_PACKET *) pPacket), map[0], map);
+	*paddr = (LM_UINT32) map;
+}
+
+static inline void b44_MM_MapTxDma(PLM_DEVICE_BLOCK pDevice,
+	struct _LM_PACKET *pPacket,
+	LM_UINT32 *paddr, LM_UINT32 *len, int frag)
+{
+	dma_addr_t map;
+	struct sk_buff *skb = ((struct _UM_PACKET *) pPacket)->skbuff;
+
+	map = pci_map_single(((struct _UM_DEVICE_BLOCK *)pDevice)->pdev,
+		skb->data,
+		skb->len,
+		PCI_DMA_TODEVICE);
+	pci_unmap_addr_set(((struct _UM_PACKET *)pPacket), map[0], map);
+	*paddr = (LM_UINT32) map;
+	*len = skb->len;
+}
+
+#define B44_MM_PTR(_ptr)   ((unsigned long) (_ptr))
+
+#if (BITS_PER_LONG == 64)
+#define B44_MM_GETSTATS(_Ctr) \
+	(unsigned long) (_Ctr).Low + ((unsigned long) (_Ctr).High << 32)
+#else
+#define B44_MM_GETSTATS(_Ctr) \
+	(unsigned long) (_Ctr).Low
+#endif
+
+
+#define printf(fmt, args...) printk(KERN_DEBUG fmt, ##args)
+
+#define DbgPrint(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
+#if defined(CONFIG_X86)
+#define DbgBreakPoint() __asm__("int $129")
+#else
+#define DbgBreakPoint()
+#endif
+#define b44_MM_Wait(time) udelay(time)
+
+#define ASSERT(expr)							\
+	if (!(expr)) {							\
+		printk(KERN_DEBUG "ASSERT failed: %s\n", #expr);	\
+	}
+#endif
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44proc.c orig/drivers/net/bcm4400/b44proc.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44proc.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/b44proc.c	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,276 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM4400 Linux Network Driver, Copyright (c) 2000 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* /proc file system handling code.                                           */
+/*                                                                            */
+/******************************************************************************/
+
+#include "b44mm.h"
+#ifdef BCM_PROC_FS
+
+#define NICINFO_PROC_DIR "nicinfo"
+
+static struct proc_dir_entry *bcm4400_procfs_dir;
+
+extern char bcm4400_driver[], bcm4400_version[];
+
+static char *na_str = "n/a";
+static char *pause_str = "pause ";
+static char *asym_pause_str = "asym_pause ";
+static char *on_str = "on";
+static char *off_str = "off";
+static char *up_str = "up";
+static char *down_str = "down";
+
+static struct proc_dir_entry *
+proc_getdir(char *name, struct proc_dir_entry *proc_dir)
+{
+	struct proc_dir_entry *pde = proc_dir;
+
+	lock_kernel();
+	for (pde=pde->subdir; pde; pde = pde->next) {
+		if (pde->namelen && (strcmp(name, pde->name) == 0)) {
+			/* directory exists */
+			break;
+		}
+	}
+	if (pde == (struct proc_dir_entry *) 0)
+	{
+		/* create the directory */
+#if (LINUX_VERSION_CODE > 0x20300)
+		pde = proc_mkdir(name, proc_dir);
+#else
+		pde = create_proc_entry(name, S_IFDIR, proc_dir);
+#endif
+		if (pde == (struct proc_dir_entry *) 0) {
+			unlock_kernel();
+			return (pde);
+		}
+	}
+	unlock_kernel();
+	return (pde);
+}
+
+int
+bcm4400_proc_create(void)
+{
+	bcm4400_procfs_dir = proc_getdir(NICINFO_PROC_DIR, proc_net);
+
+	if (bcm4400_procfs_dir == (struct proc_dir_entry *) 0) {
+		printk(KERN_DEBUG "Could not create procfs nicinfo directory %s\n", NICINFO_PROC_DIR);
+		return -1;
+	}
+	return 0;
+}
+
+void
+b44_get_speed_adv(PUM_DEVICE_BLOCK pUmDevice, char *str)
+{
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (pDevice->DisableAutoNeg == TRUE) {
+		strcpy(str, na_str);
+		return;
+	}
+	str[0] = 0;
+	if (pDevice->Advertising & PHY_AN_AD_10BASET_HALF) {
+		strcat(str, "10half ");
+	}
+	if (pDevice->Advertising & PHY_AN_AD_10BASET_FULL) {
+		strcat(str, "10full ");
+	}
+	if (pDevice->Advertising & PHY_AN_AD_100BASETX_HALF) {
+		strcat(str, "100half ");
+	}
+	if (pDevice->Advertising & PHY_AN_AD_100BASETX_FULL) {
+		strcat(str, "100full ");
+	}
+}
+
+void
+b44_get_fc_adv(PUM_DEVICE_BLOCK pUmDevice, char *str)
+{
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (pDevice->DisableAutoNeg == TRUE) {
+		strcpy(str, na_str);
+		return;
+	}
+	str[0] = 0;
+	if (pDevice->Advertising & PHY_AN_AD_PAUSE_CAPABLE) {
+		strcat(str, pause_str);
+	}
+	if (pDevice->Advertising & PHY_AN_AD_ASYM_PAUSE) {
+		strcat(str, asym_pause_str);
+	}
+}
+
+int
+bcm4400_read_pfs(char *page, char **start, off_t off, int count,
+	int *eof, void *data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+	int len = 0;
+	unsigned long rx_mac_errors, rx_crc_errors, rx_align_errors;
+	unsigned long rx_runt_errors, rx_frag_errors, rx_long_errors;
+	unsigned long rx_overrun_errors, rx_jabber_errors;
+	char str[64];
+
+	len += sprintf(page+len, "Description\t\t\t%s\n", pUmDevice->name);
+	len += sprintf(page+len, "Driver_Name\t\t\t%s\n", bcm4400_driver);
+	len += sprintf(page+len, "Driver_Version\t\t\t%s\n", bcm4400_version);
+	len += sprintf(page+len, "PCI_Vendor\t\t\t0x%04x\n", pDevice->PciVendorId);
+	len += sprintf(page+len, "PCI_Device_ID\t\t\t0x%04x\n",
+		pDevice->PciDeviceId);
+	len += sprintf(page+len, "PCI_Subsystem_Vendor\t\t0x%04x\n",
+		pDevice->PciSubvendorId);
+	len += sprintf(page+len, "PCI_Subsystem_ID\t\t0x%04x\n",
+		pDevice->PciSubsystemId);
+	len += sprintf(page+len, "PCI_Revision_ID\t\t\t0x%02x\n",
+		pDevice->PciRevId);
+	len += sprintf(page+len, "PCI_Slot\t\t\t%d\n",
+		PCI_SLOT(pUmDevice->pdev->devfn));
+	len += sprintf(page+len, "PCI_Bus\t\t\t\t%d\n",
+		pUmDevice->pdev->bus->number);
+
+	len += sprintf(page+len, "Memory\t\t\t\t0x%lx\n", pUmDevice->dev->base_addr);
+	len += sprintf(page+len, "IRQ\t\t\t\t%d\n", dev->irq);
+	len += sprintf(page+len, "System_Device_Name\t\t%s\n", dev->name);
+	len += sprintf(page+len, "Current_HWaddr\t\t\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+	len += sprintf(page+len,
+		"Permanent_HWaddr\t\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+		pDevice->NodeAddress[0], pDevice->NodeAddress[1],
+		pDevice->NodeAddress[2], pDevice->NodeAddress[3],
+		pDevice->NodeAddress[4], pDevice->NodeAddress[5]);
+	len += sprintf(page+len, "Part_Number\t\t\t%s\n\n", pDevice->PartNo);
+
+	len += sprintf(page+len, "Link\t\t\t\t%s\n", 
+		(pUmDevice->opened == 0) ? "unknown" :
+    		((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) ? up_str :
+		down_str));
+	len += sprintf(page+len, "Auto_Negotiate\t\t\t%s\n", 
+    		(pDevice->DisableAutoNeg == TRUE) ? off_str : on_str);
+	b44_get_speed_adv(pUmDevice, str);
+	len += sprintf(page+len, "Speed_Advertisement\t\t%s\n", str);
+	b44_get_fc_adv(pUmDevice, str);
+	len += sprintf(page+len, "Flow_Control_Advertisement\t%s\n", str);
+	len += sprintf(page+len, "Speed\t\t\t\t%s\n", 
+    		((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
+		(pUmDevice->opened == 0)) ? na_str :
+    		((pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) ? "100" :
+    		(pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) ? "10" : na_str));
+	len += sprintf(page+len, "Duplex\t\t\t\t%s\n", 
+    		((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
+		(pUmDevice->opened == 0)) ? na_str :
+		((pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) ? "full" :
+			"half"));
+	len += sprintf(page+len, "Flow_Control\t\t\t%s\n", 
+    		((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
+		(pUmDevice->opened == 0)) ? na_str :
+		((pDevice->FlowControl == LM_FLOW_CONTROL_NONE) ? off_str :
+		(((pDevice->FlowControl & LM_FLOW_CONTROL_RX_TX_PAUSE) ==
+			LM_FLOW_CONTROL_RX_TX_PAUSE) ? "receive/transmit" :
+		(pDevice->FlowControl & LM_FLOW_CONTROL_RECEIVE_PAUSE) ?
+			"receive" : "transmit")));
+	len += sprintf(page+len, "State\t\t\t\t%s\n", 
+    		(dev->flags & IFF_UP) ? up_str : down_str);
+	len += sprintf(page+len, "MTU_Size\t\t\t%d\n\n", dev->mtu);
+	len += sprintf(page+len, "Rx_Packets\t\t\t%lu\n", pDevice->rx_pkts);
+
+	len += sprintf(page+len, "Tx_Packets\t\t\t%lu\n", pDevice->tx_pkts);
+	len += sprintf(page+len, "Rx_Bytes\t\t\t%lu\n", pDevice->rx_octets);
+	len += sprintf(page+len, "Tx_Bytes\t\t\t%lu\n", pDevice->tx_octets);
+	rx_align_errors = pDevice->rx_align_errs;
+	rx_crc_errors = pDevice->rx_crc_errs;
+	rx_runt_errors = pDevice->rx_undersize;
+	rx_frag_errors = pDevice->rx_fragment_pkts;
+	rx_long_errors = pDevice->rx_oversize_pkts;
+	rx_overrun_errors = pDevice->rx_missed_pkts;
+	rx_jabber_errors = pDevice->rx_jabber_pkts;
+	rx_mac_errors = rx_crc_errors + rx_align_errors + rx_runt_errors +
+		rx_frag_errors + rx_long_errors + rx_jabber_errors;
+	len += sprintf(page+len, "Rx_Errors\t\t\t%lu\n",
+		rx_mac_errors + rx_overrun_errors);
+	len += sprintf(page+len, "Tx_Errors\t\t\t%lu\n",
+		pDevice->tx_jabber_pkts + pDevice->tx_oversize_pkts +
+		pDevice->tx_underruns + pDevice->tx_excessive_cols +
+		pDevice->tx_late_cols);
+	len += sprintf(page+len, "\nTx_Carrier_Errors\t\t%lu\n",
+		pDevice->tx_carrier_lost);
+	len += sprintf(page+len, "Tx_Abort_Excess_Coll\t\t%lu\n",
+		pDevice->tx_excessive_cols);
+	len += sprintf(page+len, "Tx_Abort_Late_Coll\t\t%lu\n",
+		pDevice->tx_late_cols);
+	len += sprintf(page+len, "Tx_Deferred_Ok\t\t\t%lu\n",
+		pDevice->tx_defered);
+	len += sprintf(page+len, "Tx_Single_Coll_Ok\t\t%lu\n",
+		pDevice->tx_single_cols);
+	len += sprintf(page+len, "Tx_Multi_Coll_Ok\t\t%lu\n",
+		pDevice->tx_multiple_cols);
+	len += sprintf(page+len, "Tx_Total_Coll_Ok\t\t%lu\n",
+		pDevice->tx_total_cols);
+	len += sprintf(page+len, "\nRx_CRC_Errors\t\t\t%lu\n", 
+		rx_crc_errors);
+	len += sprintf(page+len, "Rx_Short_Fragment_Errors\t%lu\n",
+		rx_frag_errors);
+	len += sprintf(page+len, "Rx_Short_Length_Errors\t\t%lu\n",
+		rx_runt_errors);
+	len += sprintf(page+len, "Rx_Long_Length_Errors\t\t%lu\n",
+		rx_long_errors);
+	len += sprintf(page+len, "Rx_Align_Errors\t\t\t%lu\n",
+		rx_align_errors);
+	len += sprintf(page+len, "Rx_Overrun_Errors\t\t%lu\n",
+		rx_overrun_errors);
+	len += sprintf(page+len, "\nTx_MAC_Errors\t\t\t%lu\n",
+		pDevice->tx_underruns);
+	len += sprintf(page+len, "Rx_MAC_Errors\t\t\t%lu\n\n",
+		rx_mac_errors);
+
+	len += sprintf(page+len, "Tx_Desc_Count\t\t\t%u\n",
+		pDevice->TxPacketDescCnt);
+	len += sprintf(page+len, "Rx_Desc_Count\t\t\t%u\n",
+		pDevice->RxPacketDescCnt);
+
+	*eof = 1;
+	return len;
+}
+
+int
+bcm4400_proc_create_dev(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+
+	if (!bcm4400_procfs_dir)
+		return -1;
+
+	sprintf(pUmDevice->pfs_name, "%s.info", dev->name);
+	pUmDevice->pfs_entry = create_proc_entry(pUmDevice->pfs_name,
+		S_IFREG, bcm4400_procfs_dir);
+	if (pUmDevice->pfs_entry == 0)
+		return -1;
+	pUmDevice->pfs_entry->read_proc = bcm4400_read_pfs;
+	pUmDevice->pfs_entry->data = dev;
+	return 0;
+}
+int
+bcm4400_proc_remove_dev(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+
+	remove_proc_entry(pUmDevice->pfs_name, bcm4400_procfs_dir);
+	return 0;
+}
+
+#endif
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44queue.h orig/drivers/net/bcm4400/b44queue.h
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44queue.h	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/b44queue.h	2003-01-21 16:03:43.000000000 -0500
@@ -0,0 +1,342 @@
+
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM4400 Linux Network Driver, Copyright (c) 2002 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/* Queue functions.                                                           */
+/*    void          QQ_InitQueue(PQQ_CONTAINER pQueue)                        */
+/*    char          QQ_Full(PQQ_CONTAINER pQueue)                             */
+/*    char          QQ_Empty(PQQ_CONTAINER pQueue)                            */
+/*    unsigned int QQ_GetSize(PQQ_CONTAINER pQueue)                          */
+/*    unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue)                      */
+/*    char          QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
+/*    char          QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
+/*    PQQ_ENTRY     QQ_PopHead(PQQ_CONTAINER pQueue)                          */
+/*    PQQ_ENTRY     QQ_PopTail(PQQ_CONTAINER pQueue)                          */
+/*    PQQ_ENTRY     QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx)       */
+/*    PQQ_ENTRY     QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx)       */
+/*                                                                            */
+/*                                                                            */
+/* History:                                                                   */
+/*    02/25/00 Hav Khauv        Initial version.                              */
+/******************************************************************************/
+
+#ifndef BCM_QUEUE_H
+#define BCM_QUEUE_H
+
+
+
+/******************************************************************************/
+/* Queue definitions. */
+/******************************************************************************/
+
+/* Entry for queueing. */
+typedef void *PQQ_ENTRY;
+
+
+/* Queue header -- base type. */
+typedef struct {
+    unsigned int Head;
+    unsigned int Tail;
+    unsigned int Size;
+    atomic_t EntryCnt;
+    PQQ_ENTRY Array[1];
+} QQ_CONTAINER, *PQQ_CONTAINER;
+
+
+/* Declare queue type macro. */
+#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE)            \
+                                                                \
+    typedef struct {                                            \
+        QQ_CONTAINER Container;                                 \
+        PQQ_ENTRY EntryBuffer[_QUEUE_SIZE];                     \
+    } _QUEUE_TYPE, *P##_QUEUE_TYPE
+
+
+
+/******************************************************************************/
+/* Compilation switches. */
+/******************************************************************************/
+
+#if DBG
+#undef QQ_NO_OVERFLOW_CHECK
+#undef QQ_NO_UNDERFLOW_CHECK
+#endif /* DBG */
+
+#ifdef QQ_USE_MACROS
+/* notdone */
+#else
+
+#ifdef QQ_NO_INLINE
+#define __inline
+#endif /* QQ_NO_INLINE */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static void 
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+    pQueue->Head = 0;
+    pQueue->Tail = 0;
+    pQueue->Size = QueueSize+1;
+    atomic_set(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+    unsigned int NewHead;
+
+    NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+    return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+    return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static unsigned int 
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+    return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static unsigned int 
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+    return atomic_read(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_PushHead(
+PQQ_CONTAINER pQueue, 
+PQQ_ENTRY pEntry) {
+    unsigned int Head;
+
+    Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[pQueue->Head] = pEntry;
+    wmb();
+    pQueue->Head = Head;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+__inline static char 
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Tail;
+
+    Tail = pQueue->Tail;
+    if(Tail == 0) {
+        Tail = pQueue->Size;
+    } /* if */
+    Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[Tail] = pEntry;
+    wmb();
+    pQueue->Tail = Tail;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+    unsigned int Head;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    if(Head == 0) {
+        Head = pQueue->Size;
+    } /* if */
+    Head--;
+
+    Entry = pQueue->Array[Head];
+    mb();
+    pQueue->Head = Head;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    Entry = pQueue->Array[Tail];
+    mb();
+    pQueue->Tail = (Tail + 1) % pQueue->Size;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_GetHead(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    if(pQueue->Head > Idx)
+    {
+        Idx = pQueue->Head - Idx;
+    }
+    else
+    {
+        Idx = pQueue->Size - (Idx - pQueue->Head);
+    }
+    Idx--;
+
+    return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+__inline static PQQ_ENTRY
+QQ_GetTail(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    Idx += pQueue->Tail;
+    if(Idx >= pQueue->Size)
+    {
+        Idx = Idx - pQueue->Size;
+    }
+
+    return pQueue->Array[Idx];
+}
+
+#endif /* QQ_USE_MACROS */
+
+
+
+#endif /* QUEUE_H */
diff -uNr linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44um.c orig/drivers/net/bcm4400/b44um.c
--- linux-2.4.21_pre3-gss-r2/drivers/net/bcm4400/b44um.c	1969-12-31 19:00:00.000000000 -0500
+++ orig/drivers/net/bcm4400/b44um.c	2003-01-21 16:38:24.000000000 -0500
@@ -0,0 +1,1627 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM4400 Linux Network Driver, Copyright (c) 2002 Broadcom         */
+/* Corporation.                                                               */
+/* All rights reserved.                                                       */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, located in the file LICENSE.                 */
+/*                                                                            */
+/******************************************************************************/
+
+
+char bcm4400_driver[] = "bcm4400";
+char bcm4400_version[] = "1.0.1";
+char bcm4400_date[] = "(08/26/02)";
+
+#define B44UM
+#include "b44mm.h"
+
+/* A few user-configurable values. */
+
+#define MAX_UNITS 16
+/* Used to pass the full-duplex flag, etc. */
+static int line_speed[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static int auto_speed[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int full_duplex[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+static int rx_flow_control[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static int tx_flow_control[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static int auto_flow_control[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
+static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
+	{TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
+	TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
+	TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
+	TX_DESC_CNT};
+
+#define RX_DESC_CNT DEFAULT_RX_PACKET_DESC_COUNT
+static unsigned int rx_pkt_desc_cnt[MAX_UNITS] =
+	{RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
+	RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
+	RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
+	RX_DESC_CNT };
+
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+
+#if (LINUX_VERSION_CODE < 0x02030d)
+#define pci_resource_start(dev, bar)	(dev->base_address[bar] & PCI_BASE_ADDRESS_MEM_MASK)
+#elif (LINUX_VERSION_CODE < 0x02032b)
+#define pci_resource_start(dev, bar)	(dev->resource[bar] & PCI_BASE_ADDRESS_MEM_MASK)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+#define dev_kfree_skb_irq(skb)  dev_kfree_skb(skb)
+#define netif_wake_queue(dev)	clear_bit(0, &dev->tbusy); mark_bh(NET_BH)
+#define netif_stop_queue(dev)	set_bit(0, &dev->tbusy)
+
+static inline void netif_start_queue(struct net_device *dev)
+{
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+}
+
+#define netif_queue_stopped(dev)	dev->tbusy
+#define netif_running(dev)		dev->start
+
+static inline void tasklet_schedule(struct tasklet_struct *tasklet)
+{
+	queue_task(tasklet, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+static inline void tasklet_init(struct tasklet_struct *tasklet,
+				void (*func)(unsigned long),
+				unsigned long data)
+{
+        tasklet->next = NULL;
+        tasklet->sync = 0;
+        tasklet->routine = (void (*)(void *))func;
+        tasklet->data = (void *)data;
+}
+
+#define tasklet_kill(tasklet)
+
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020300)
+struct pci_device_id {
+	unsigned int vendor, device;		/* Vendor and device ID or PCI_ANY_ID */
+	unsigned int subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
+	unsigned int class, class_mask;		/* (class,subclass,prog-if) triplet */
+	unsigned long driver_data;		/* Data private to the driver */
+};
+
+#define PCI_ANY_ID		0
+
+#define pci_set_drvdata(pdev, dev)
+#define pci_get_drvdata(pdev) 0
+
+#define pci_enable_device(pdev) 0
+
+#define __devinit		__init
+#define __devinitdata		__initdata
+#define __devexit
+
+#define SET_MODULE_OWNER(dev)
+#define MODULE_DEVICE_TABLE(pci, pci_tbl)
+
+#endif
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(license)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032a)
+static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
+					 dma_addr_t *dma_handle)
+{
+	void *virt_ptr;
+
+	/* Maximum in slab.c */
+	if (size > 131072)
+		return 0;
+
+	virt_ptr = kmalloc(size, GFP_KERNEL);
+	*dma_handle = virt_to_bus(virt_ptr);
+	return virt_ptr;
+}
+#define pci_free_consistent(dev, size, ptr, dma_ptr)	kfree(ptr)
+
+#endif /*#if (LINUX_VERSION_CODE < 0x02032a) */
+
+
+#if (LINUX_VERSION_CODE < 0x020329)
+#define pci_set_dma_mask(pdev, mask) (0)
+#else
+#if (LINUX_VERSION_CODE < 0x020403)
+int
+pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
+{
+    if(! pci_dma_supported(dev, mask))
+        return -EIO;
+
+    dev->dma_mask = mask;
+
+    return 0;
+}
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020402)
+#define pci_request_regions(pdev, name) (0)
+#define pci_release_regions(pdev)
+#endif
+
+void
+bcm4400_intr_off(PUM_DEVICE_BLOCK pUmDevice)
+{
+	atomic_inc(&pUmDevice->intr_sem);
+	b44_LM_DisableInterrupt(&pUmDevice->lm_dev);
+	synchronize_irq();
+}
+
+void
+bcm4400_intr_on(PUM_DEVICE_BLOCK pUmDevice)
+{
+	if (atomic_dec_and_test(&pUmDevice->intr_sem)) {
+		b44_LM_EnableInterrupt(&pUmDevice->lm_dev);
+	}
+}
+
+int b44_Packet_Desc_Size = sizeof(UM_PACKET);
+
+#if defined(MODULE)
+MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
+MODULE_DESCRIPTION("BCM4400 Driver");
+MODULE_LICENSE("GPL");
+MODULE_PARM(line_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(auto_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(tx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(auto_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(tx_pkt_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_pkt_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+
+#define RUN_AT(x) (jiffies + (x))
+
+
+#define PCI_SUPPORT_VER2
+
+#if ! defined(CAP_NET_ADMIN)
+#define capable(CAP_XXX) (suser())
+#endif
+
+
+STATIC int bcm4400_open(struct net_device *dev);
+STATIC void bcm4400_timer(unsigned long data);
+STATIC void bcm4400_tx_timeout(struct net_device *dev);
+STATIC int bcm4400_start_xmit(struct sk_buff *skb, struct net_device *dev);
+STATIC void bcm4400_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+#ifdef BCM_TASKLET
+STATIC void bcm4400_tasklet(unsigned long data);
+#endif
+STATIC int bcm4400_close(struct net_device *dev);
+STATIC struct net_device_stats *bcm4400_get_stats(struct net_device *dev);
+STATIC int bcm4400_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+STATIC void bcm4400_set_rx_mode(struct net_device *dev);
+STATIC int bcm4400_set_mac_addr(struct net_device *dev, void *p);
+STATIC int bcm4400_rxfill(PUM_DEVICE_BLOCK pUmDevice);
+STATIC int bcm4400_freemem(struct net_device *dev);
+
+
+/* A list of all installed bcm4400 devices. */
+static struct net_device *root_bcm4400_dev = NULL;
+
+typedef enum {
+	BCM4401 = 0,
+} board_t;
+
+
+/* indexed by board_t, above */
+static struct {
+	char *name;
+} board_info[] __devinitdata = {
+	{ "Broadcom BCM4401 100Base-T" },
+	{ 0 },
+	};
+
+static struct pci_device_id bcm4400_pci_tbl[] __devinitdata = {
+	{0x14e4, 0x4401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM4401 },
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, bcm4400_pci_tbl);
+
+#ifdef BCM_PROC_FS
+extern int bcm4400_proc_create(void);
+extern int bcm4400_proc_create_dev(struct net_device *dev);
+extern int bcm4400_proc_remove_dev(struct net_device *dev);
+#endif
+
+static int __devinit bcm4400_init_board(struct pci_dev *pdev,
+					struct net_device **dev_out,
+					int board_idx)
+{
+	struct net_device *dev;
+	PUM_DEVICE_BLOCK pUmDevice;
+	PLM_DEVICE_BLOCK pDevice;
+	int rc;
+
+	*dev_out = NULL;
+
+	/* dev zeroed in init_etherdev */
+	dev = init_etherdev(NULL, sizeof(*pUmDevice));
+	if (dev == NULL) {
+		printk (KERN_ERR "%s: unable to alloc new ethernet\n",
+			bcm4400_driver);
+		return -ENOMEM;
+	}
+	SET_MODULE_OWNER(dev);
+	pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+
+	/* enable device (incl. PCI PM wakeup), and bus-mastering */
+	rc = pci_enable_device (pdev);
+	if (rc)
+		goto err_out;
+
+	rc = pci_request_regions(pdev, bcm4400_driver);
+	if (rc)
+		goto err_out;
+
+	pci_set_master(pdev);
+
+	if (pci_set_dma_mask(pdev, ~(0UL)) != 0) {
+		printk(KERN_ERR "System does not support DMA\n");
+		pci_release_regions(pdev);
+		goto err_out;
+	}
+
+	pUmDevice->dev = dev;
+	pUmDevice->pdev = pdev;
+	pUmDevice->mem_list_num = 0;
+	pUmDevice->next_module = root_bcm4400_dev;
+	pUmDevice->index = board_idx;
+	root_bcm4400_dev = dev;
+
+	pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+	if (b44_LM_GetAdapterInfo(pDevice) != LM_STATUS_SUCCESS) {
+		printk(KERN_ERR "Get Adapter info failed\n");
+		rc = -ENODEV;
+		goto err_out_unmap;
+	}
+
+	pUmDevice->rx_buf_align = 2;
+	dev->mem_start = pci_resource_start(pdev, 0);
+	dev->mem_end = dev->mem_start + sizeof(bcmenetregs_t) + 128; 
+	dev->irq = pdev->irq;
+
+	*dev_out = dev;
+	return 0;
+
+err_out_unmap:
+	pci_release_regions(pdev);
+	bcm4400_freemem(dev);
+
+err_out:
+	unregister_netdev(dev);
+	kfree (dev);
+	return rc;
+}
+
+static int __devinit
+bcm4400_print_ver(void)
+{
+	printk(KERN_INFO "Broadcom 4401 Ethernet Driver %s ",
+		bcm4400_driver);
+	printk("ver. %s %s\n", bcm4400_version, bcm4400_date);
+	return 0;
+}
+
+static int __devinit
+bcm4400_init_one(struct pci_dev *pdev,
+				       const struct pci_device_id *ent)
+{
+	struct net_device *dev = NULL;
+	PUM_DEVICE_BLOCK pUmDevice;
+	PLM_DEVICE_BLOCK pDevice;
+	int i;
+	static int board_idx = -1;
+	static int printed_version = 0;
+	struct pci_dev *amd_dev;
+
+	board_idx++;
+
+	if (!printed_version) {
+		bcm4400_print_ver();
+#ifdef BCM_PROC_FS
+		bcm4400_proc_create();
+#endif
+		printed_version = 1;
+	}
+
+	i = bcm4400_init_board(pdev, &dev, board_idx);
+	if (i < 0) {
+		return i;
+	}
+
+	if (dev == NULL)
+		return -ENOMEM;
+
+	dev->open = bcm4400_open;
+	dev->hard_start_xmit = bcm4400_start_xmit;
+	dev->stop = bcm4400_close;
+	dev->get_stats = bcm4400_get_stats;
+	dev->set_multicast_list = bcm4400_set_rx_mode;
+	dev->do_ioctl = bcm4400_ioctl;
+	dev->set_mac_address = &bcm4400_set_mac_addr;
+#if (LINUX_VERSION_CODE >= 0x20400)
+	dev->tx_timeout = bcm4400_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#endif
+
+	pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+	dev->base_addr = pci_resource_start(pdev, 0);
+	dev->irq = pdev->irq;
+
+	pci_set_drvdata(pdev, dev);
+
+	memcpy(dev->dev_addr, pDevice->NodeAddress, 6);
+	pUmDevice->name = board_info[ent->driver_data].name,
+	printk(KERN_INFO "%s: %s found at mem %lx, IRQ %d, ",
+		dev->name, pUmDevice->name, dev->base_addr,
+		dev->irq);
+	printk("node addr ");
+	for (i = 0; i < 6; i++) {
+		printk("%2.2x", dev->dev_addr[i]);
+	}
+	printk("\n");
+
+#ifdef BCM_PROC_FS
+	bcm4400_proc_create_dev(dev);
+#endif
+#ifdef BCM_TASKLET
+	tasklet_init(&pUmDevice->tasklet, bcm4400_tasklet,
+		(unsigned long) pUmDevice);
+#endif
+	if ((amd_dev = pci_find_device(0x1022, 0x700c, NULL))) {
+		u32 val;
+
+		/* Found AMD 762 North bridge */
+		pci_read_config_dword(amd_dev, 0x4c, &val);
+		if ((val & 0x02) == 0) {
+			pci_write_config_dword(amd_dev, 0x4c, val | 0x02);
+			printk(KERN_INFO "%s: Setting AMD762 Northbridge to enable PCI ordering compliance\n", bcm4400_driver);
+		}
+	}
+	return 0;
+
+}
+
+
+static void __devexit
+bcm4400_remove_one (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+
+#ifdef BCM_PROC_FS
+	bcm4400_proc_remove_dev(dev); 
+#endif
+	unregister_netdev(dev);
+
+	if (pUmDevice->lm_dev.pMappedMemBase)
+		iounmap(pUmDevice->lm_dev.pMappedMemBase);
+
+	pci_release_regions(pdev);
+
+	kfree(dev);
+
+	pci_set_drvdata(pdev, NULL);
+
+/*	pci_power_off(pdev, -1);*/
+
+}
+
+
+
+STATIC int
+bcm4400_open(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+	pUmDevice->delayed_link_ind = (4 * HZ) / pUmDevice->timer_interval;
+
+	if (request_irq(dev->irq, &bcm4400_interrupt, SA_SHIRQ, dev->name, dev)) {
+		return -EAGAIN;
+	}
+
+	pUmDevice->opened = 1;
+	if (b44_LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
+		free_irq(dev->irq, dev);
+		bcm4400_freemem(dev);
+		return -EAGAIN;
+	}
+
+	if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
+		b44_LM_SetMacAddress(pDevice, dev->dev_addr);
+	}
+
+	QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
+        MAX_RX_PACKET_DESC_COUNT);
+	netif_start_queue(dev);
+
+#if (LINUX_VERSION_CODE < 0x020300)
+	MOD_INC_USE_COUNT;
+#endif
+
+	init_timer(&pUmDevice->timer);
+	pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
+	pUmDevice->timer.data = (unsigned long)dev;
+	pUmDevice->timer.function = &bcm4400_timer;
+	add_timer(&pUmDevice->timer);
+
+	atomic_set(&pUmDevice->intr_sem, 0);
+	b44_LM_EnableInterrupt(pDevice);
+
+	return 0;
+}
+
+
+STATIC void
+bcm4400_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (!pUmDevice->opened)
+		return;
+
+	if (atomic_read(&pUmDevice->intr_sem)) {
+		pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
+		add_timer(&pUmDevice->timer);
+		return;
+	}
+
+	if (pUmDevice->delayed_link_ind > 0) {
+		pUmDevice->delayed_link_ind--;
+		if (pUmDevice->delayed_link_ind == 0) {
+			b44_MM_IndicateStatus(pDevice, pDevice->LinkStatus);
+		}
+	}
+	if (!pUmDevice->interrupt) {
+		if (REG_RD(pDevice, intstatus) & I_XI) {
+			REG_WR(pDevice, gptimer, 2);
+		}
+#if (LINUX_VERSION_CODE < 0x02032b)
+		if ((QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) !=
+			pDevice->TxPacketDescCnt) &&
+			((jiffies - dev->trans_start) > TX_TIMEOUT)) {
+
+			printk(KERN_WARNING "%s: Tx hung\n", dev->name);
+			bcm4400_tx_timeout(dev);
+		}
+#endif
+	}
+	if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container) >
+		pUmDevice->rx_buf_repl_panic_thresh) {
+		/* Generate interrupt and let isr allocate buffers */
+	}
+
+	if (pUmDevice->link_interval == 0) {
+		b44_LM_PollLink(pDevice);
+		if (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)
+			b44_LM_StatsUpdate(pDevice);
+		pUmDevice->link_interval = HZ / pUmDevice->timer_interval;
+	}
+	else {
+		pUmDevice->link_interval--;
+	}
+
+	b44_LM_GetStats(pDevice);
+
+	pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
+	add_timer(&pUmDevice->timer);
+}
+
+STATIC void
+bcm4400_tx_timeout(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+	netif_stop_queue(dev);
+	bcm4400_intr_off(pUmDevice);
+	b44_LM_ResetAdapter(pDevice);	
+	if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
+		b44_LM_SetMacAddress(pDevice, dev->dev_addr);
+	}
+	atomic_set(&pUmDevice->intr_sem, 1);
+	bcm4400_intr_on(pUmDevice);
+	netif_wake_queue(dev);
+}
+
+STATIC int
+bcm4400_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+
+	if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) || !pDevice->InitDone)
+	{
+		dev_kfree_skb(skb);
+		return 0;
+	}
+	
+#if (LINUX_VERSION_CODE < 0x02032b)
+	if (test_and_set_bit(0, &dev->tbusy)) {
+		return 1;
+	}
+#endif
+
+	pPacket = (PLM_PACKET)
+		QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
+	if (pPacket == 0) {
+		netif_stop_queue(dev);
+		pUmDevice->tx_full = 1;
+		if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container)) {
+			netif_wake_queue(dev);
+			pUmDevice->tx_full = 0;
+		}
+		return 1;
+	}
+	pUmPacket = (PUM_PACKET) pPacket;
+	pUmPacket->skbuff = skb;
+
+	if (atomic_read(&pDevice->SendDescLeft) == 0) {
+		netif_stop_queue(dev);
+		pUmDevice->tx_full = 1;
+		QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+		if (atomic_read(&pDevice->SendDescLeft)) {
+			netif_wake_queue(dev);
+			pUmDevice->tx_full = 0;
+		}
+		return 1;
+	}
+
+	pPacket->u.Tx.FragCount = 1;
+
+	b44_LM_SendPacket(pDevice, pPacket);
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+	netif_wake_queue(dev);
+#endif
+	dev->trans_start = jiffies;
+	return 0;
+}
+
+
+STATIC void
+bcm4400_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)dev_instance;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+#ifdef BCM_TASKLET
+	int repl_buf_count;
+#endif
+
+	if (!pDevice->InitDone)
+		return;
+
+	if (atomic_read(&pUmDevice->intr_sem))
+		return;
+
+	if (test_and_set_bit(0, (void*)&pUmDevice->interrupt)) {
+		printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by "
+			   "processor %d.\n",
+			   dev->name, hard_smp_processor_id());
+		return;
+	}
+
+
+	b44_LM_ServiceInterrupts(pDevice);
+
+#ifdef BCM_TASKLET
+	repl_buf_count = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container);
+	if (repl_buf_count > pUmDevice->rx_buf_repl_thresh) {
+		if ((repl_buf_count > pUmDevice->rx_buf_repl_panic_thresh) &&
+			(!test_and_set_bit(0, &pUmDevice->tasklet_busy))) {
+			bcm4400_rxfill(pUmDevice);
+			clear_bit(0, (void*)&pUmDevice->tasklet_busy);
+		}
+		else if (!pUmDevice->tasklet_pending) {
+			pUmDevice->tasklet_pending = 1;
+			tasklet_schedule(&pUmDevice->tasklet);
+		}
+	}
+#else
+	if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+		bcm4400_rxfill(pUmDevice);
+	}
+
+	if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container)) {
+		b44_LM_QueueRxPackets(pDevice);
+	}
+#endif
+
+	clear_bit(0, (void*)&pUmDevice->interrupt);
+	if (pUmDevice->tx_queued) {
+		pUmDevice->tx_queued = 0;
+		netif_wake_queue(dev);
+	}
+	return;
+}
+
+
+#ifdef BCM_TASKLET
+STATIC void
+bcm4400_tasklet(unsigned long data)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)data;
+
+	/* RH 7.2 Beta 3 tasklets are reentrant */
+	if (test_and_set_bit(0, &pUmDevice->tasklet_busy)) {
+		pUmDevice->tasklet_pending = 0;
+		return;
+	}
+
+	pUmDevice->tasklet_pending = 0;
+	bcm4400_rxfill(pUmDevice);
+	clear_bit(0, &pUmDevice->tasklet_busy);
+}
+#endif
+
+STATIC int
+bcm4400_close(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+	dev->start = 0;
+#endif
+	netif_stop_queue(dev);
+	pUmDevice->opened = 0;
+
+	bcm4400_intr_off(pUmDevice);
+	netif_carrier_off(dev);
+#ifdef BCM_TASKLET
+//	tasklet_disable(&pUmDevice->tasklet);
+	tasklet_kill(&pUmDevice->tasklet);
+#endif
+	b44_LM_Halt(pDevice);
+	pDevice->InitDone = 0;
+	del_timer(&pUmDevice->timer);
+
+	free_irq(dev->irq, dev);
+#if (LINUX_VERSION_CODE < 0x020300)
+	MOD_DEC_USE_COUNT;
+#endif
+	bcm4400_freemem(dev);
+
+	return 0;
+}
+
+STATIC int
+bcm4400_freemem(struct net_device *dev)
+{
+	int i;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+
+	for (i = 0; i < pUmDevice->mem_list_num; i++) {
+		if (pUmDevice->mem_size_list[i] == 0) {
+			kfree(pUmDevice->mem_list[i]);
+		}
+		else {
+			pci_free_consistent(pUmDevice->pdev,
+				(size_t) pUmDevice->mem_size_list[i],
+				pUmDevice->mem_list[i],
+				pUmDevice->dma_list[i]);
+		}
+	}
+	pUmDevice->mem_list_num = 0;
+	return 0;
+}
+
+STATIC struct net_device_stats *
+bcm4400_get_stats(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+	struct net_device_stats *p_netstats = &pUmDevice->stats;
+
+	p_netstats->rx_packets = pDevice->rx_pkts;
+	p_netstats->tx_packets = pDevice->tx_pkts;
+	p_netstats->rx_bytes = pDevice->rx_octets;
+	p_netstats->tx_bytes = pDevice->tx_octets;
+	p_netstats->tx_errors = pDevice->tx_jabber_pkts +
+		pDevice->tx_oversize_pkts + pDevice->tx_underruns +
+		pDevice->tx_excessive_cols + pDevice->tx_late_cols;
+	p_netstats->multicast = pDevice->tx_multicast_pkts;
+	p_netstats->collisions = pDevice->tx_total_cols;
+	p_netstats->rx_length_errors = pDevice->rx_oversize_pkts +
+		pDevice->rx_undersize;
+	p_netstats->rx_over_errors = pDevice->rx_missed_pkts;
+	p_netstats->rx_frame_errors = pDevice->rx_align_errs;
+	p_netstats->rx_crc_errors = pDevice->rx_crc_errs;
+	p_netstats->rx_errors = pDevice->rx_jabber_pkts +
+		pDevice->rx_oversize_pkts + pDevice->rx_missed_pkts +
+		pDevice->rx_crc_align_errs + pDevice->rx_undersize +
+		pDevice->rx_crc_errs + pDevice->rx_align_errs +
+		pDevice->rx_symbol_errs;
+	p_netstats->tx_aborted_errors = pDevice->tx_underruns;
+	p_netstats->tx_carrier_errors = pDevice->tx_carrier_lost;
+	return p_netstats;
+}
+
+#ifdef SIOCETHTOOL
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct ethtool_cmd ethcmd;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+		
+	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+		return -EFAULT;
+
+        switch (ethcmd.cmd) {
+#ifdef ETHTOOL_GDRVINFO
+        case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+
+		strcpy(info.driver,  bcm4400_driver);
+		strcpy(info.version, bcm4400_version);
+		strcpy(info.bus_info, pUmDevice->pdev->slot_name);
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+#endif
+        case ETHTOOL_GSET: {
+		ethcmd.supported =
+			(SUPPORTED_10baseT_Half |
+			SUPPORTED_10baseT_Full |
+			SUPPORTED_100baseT_Half |
+			SUPPORTED_100baseT_Full |
+			SUPPORTED_Autoneg);
+			ethcmd.supported |= SUPPORTED_TP;
+			ethcmd.port = PORT_TP;
+
+		ethcmd.transceiver = XCVR_INTERNAL;
+		ethcmd.phy_address = 0;
+
+		if (pUmDevice->line_speed == 100)
+			ethcmd.speed = SPEED_100;
+		else if (pUmDevice->line_speed == 10)
+			ethcmd.speed = SPEED_10;
+		else
+			ethcmd.speed = 0;
+
+		if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+			ethcmd.duplex = DUPLEX_FULL;
+		else
+			ethcmd.duplex = DUPLEX_HALF;
+
+		if (pDevice->DisableAutoNeg == FALSE) {
+			ethcmd.autoneg = AUTONEG_ENABLE;
+			ethcmd.advertising = ADVERTISED_Autoneg;
+			ethcmd.advertising |=
+				ADVERTISED_TP;
+			if (pDevice->Advertising &
+				PHY_AN_AD_10BASET_HALF) {
+
+				ethcmd.advertising |=
+					ADVERTISED_10baseT_Half;
+			}
+			if (pDevice->Advertising &
+				PHY_AN_AD_10BASET_FULL) {
+
+				ethcmd.advertising |=
+					ADVERTISED_10baseT_Full;
+			}
+			if (pDevice->Advertising &
+				PHY_AN_AD_100BASETX_HALF) {
+
+				ethcmd.advertising |=
+					ADVERTISED_100baseT_Half;
+			}
+			if (pDevice->Advertising &
+				PHY_AN_AD_100BASETX_FULL) {
+
+				ethcmd.advertising |=
+					ADVERTISED_100baseT_Full;
+			}
+		}
+		else {
+			ethcmd.autoneg = AUTONEG_DISABLE;
+			ethcmd.advertising = 0;
+		}
+
+		if(copy_to_user(useraddr, &ethcmd, sizeof(ethcmd)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SSET: {
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (ethcmd.autoneg == AUTONEG_ENABLE) {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+			pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
+			pDevice->DisableAutoNeg = FALSE;
+		}
+		else {
+			if (ethcmd.speed == SPEED_1000) {
+				return -EINVAL;
+			}
+			else if (ethcmd.speed == SPEED_100) {
+				pDevice->RequestedLineSpeed =
+					LM_LINE_SPEED_100MBPS;
+			}
+			else if (ethcmd.speed == SPEED_10) {
+				pDevice->RequestedLineSpeed =
+					LM_LINE_SPEED_10MBPS;
+			}
+			else {
+				return -EINVAL;
+			}
+
+			pDevice->DisableAutoNeg = TRUE;
+			if (ethcmd.duplex == DUPLEX_FULL) {
+				pDevice->RequestedDuplexMode =
+					LM_DUPLEX_MODE_FULL;
+			}
+			else {
+				pDevice->RequestedDuplexMode =
+					LM_DUPLEX_MODE_HALF;
+			}
+		}
+		b44_LM_SetupPhy(pDevice);
+		return 0;
+	}
+#ifdef ETHTOOL_GLINK
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+
+		if (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)
+			edata.data =  1;
+		else
+			edata.data =  0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+#endif
+#ifdef ETHTOOL_NWAY_RST
+	case ETHTOOL_NWAY_RST: {
+		LM_UINT32 phyctrl;
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (pDevice->DisableAutoNeg) {
+			return -EINVAL;
+		}
+		b44_LM_ReadPhy(pDevice, PHY_CTRL_REG, &phyctrl);
+		b44_LM_WritePhy(pDevice, PHY_CTRL_REG, phyctrl |
+			PHY_CTRL_AUTO_NEG_ENABLE |
+			PHY_CTRL_RESTART_AUTO_NEG);
+		return 0;
+	}
+#endif
+
+	}
+	
+	return -EOPNOTSUPP;
+}
+#endif
+
+/* Provide ioctl() calls to examine the MII xcvr state. */
+STATIC int bcm4400_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	u16 *data = (u16 *)&rq->ifr_data;
+	u32 value;
+
+	switch(cmd) {
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		data[0] = pDevice->PhyAddr;
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		b44_LM_ReadPhy(pDevice, data[1] & 0x1f, (LM_UINT32 *) &value);
+		data[3] = value & 0xffff;
+		return 0;
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		b44_LM_WritePhy(pDevice, data[1] & 0x1f, data[2]);
+		return 0;
+#ifdef SIOCETHTOOL
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+#endif
+	default:
+		return -EOPNOTSUPP;
+	}
+	return -EOPNOTSUPP;
+}
+
+STATIC void bcm4400_set_rx_mode(struct net_device *dev)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	int i;
+	struct dev_mc_list *mclist;
+
+	b44_LM_MulticastClear(pDevice);
+	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+			 i++, mclist = mclist->next) {
+		b44_LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr);
+	}
+	if (dev->flags & IFF_ALLMULTI) {
+		if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) {
+			b44_LM_SetReceiveMask(pDevice,
+				pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
+		}
+	}
+	else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) {
+		b44_LM_SetReceiveMask(pDevice,
+			pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST);
+	}
+	if (dev->flags & IFF_PROMISC) {
+		if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) {
+			b44_LM_SetReceiveMask(pDevice,
+				pDevice->ReceiveMask | LM_PROMISCUOUS_MODE);
+		}
+	}
+	else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) {
+		b44_LM_SetReceiveMask(pDevice,
+			pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE);
+	}
+}
+
+/*
+ * Set the hardware MAC address.
+ */
+STATIC int bcm4400_set_mac_addr(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr=p;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) dev->priv;
+
+	if (netif_running(dev))
+		return -EBUSY;
+	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+	b44_LM_SetMacAddress(pDevice, dev->dev_addr);
+	return 0;
+}
+
+
+#if (LINUX_VERSION_CODE < 0x020300)
+
+int
+bcm4400_probe(struct net_device *dev)
+{
+	int cards_found = 0;
+	struct pci_dev *pdev = NULL;
+	struct pci_device_id *pci_tbl;
+	u16 ssvid, ssid;
+
+	if ( ! pci_present())
+		return -ENODEV;
+
+	pci_tbl = bcm4400_pci_tbl;
+	while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
+		int idx;
+
+		pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &ssvid);
+		pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &ssid);
+		for (idx = 0; pci_tbl[idx].vendor; idx++) {
+			if ((pci_tbl[idx].vendor == PCI_ANY_ID ||
+				pci_tbl[idx].vendor == pdev->vendor) &&
+				(pci_tbl[idx].device == PCI_ANY_ID ||
+				pci_tbl[idx].device == pdev->device) &&
+				(pci_tbl[idx].subvendor == PCI_ANY_ID ||
+				pci_tbl[idx].subvendor == ssvid) &&
+				(pci_tbl[idx].subdevice == PCI_ANY_ID ||
+				pci_tbl[idx].subdevice == ssid))
+			{
+
+				break;
+			}
+		}
+		if (pci_tbl[idx].vendor == 0)
+			continue;
+
+
+		if (bcm4400_init_one(pdev, &pci_tbl[idx]) == 0)
+			cards_found++;
+	}
+
+	return cards_found ? 0 : -ENODEV;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return bcm4400_probe(NULL);
+}
+
+void cleanup_module(void)
+{
+	struct net_device *next_dev;
+	PUM_DEVICE_BLOCK pUmDevice;
+
+	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	while (root_bcm4400_dev) {
+		pUmDevice = (PUM_DEVICE_BLOCK)root_bcm4400_dev->priv;
+#ifdef BCM_PROC_FS
+		bcm4400_proc_remove_dev(root_bcm4400_dev); 
+#endif
+		next_dev = pUmDevice->next_module;
+		unregister_netdev(root_bcm4400_dev);
+		if (pUmDevice->lm_dev.pMappedMemBase)
+			iounmap(pUmDevice->lm_dev.pMappedMemBase);
+		kfree(root_bcm4400_dev);
+		root_bcm4400_dev = next_dev;
+	}
+}
+
+#endif  /* MODULE */
+#else	/* LINUX_VERSION_CODE < 0x020300 */
+
+#if (LINUX_VERSION_CODE >= 0x020406)
+static int bcm4400_suspend (struct pci_dev *pdev, u32 state)
+#else
+static void bcm4400_suspend (struct pci_dev *pdev)
+#endif
+{
+	struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+	if (!netif_running(dev))
+#if (LINUX_VERSION_CODE >= 0x020406)
+		return 0;
+#else
+		return;
+#endif
+
+	bcm4400_intr_off(pUmDevice);
+	netif_carrier_off(dev);
+	netif_device_detach (dev);
+
+	/* Disable interrupts, stop Tx and Rx. */
+	b44_LM_Halt(pDevice);
+
+/*	pci_power_off(pdev, -1);*/
+#if (LINUX_VERSION_CODE >= 0x020406)
+		return 0;
+#endif
+}
+
+
+#if (LINUX_VERSION_CODE >= 0x020406)
+static int bcm4400_resume(struct pci_dev *pdev)
+#else
+static void bcm4400_resume(struct pci_dev *pdev)
+#endif
+{
+	struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+	PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
+
+	if (!netif_running(dev))
+#if (LINUX_VERSION_CODE >= 0x020406)
+		return 0;
+#else
+		return;
+#endif
+/*	pci_power_on(pdev);*/
+	netif_device_attach(dev);
+	b44_LM_InitializeAdapter(pDevice);
+	if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
+		b44_LM_SetMacAddress(pDevice, dev->dev_addr);
+	}
+	atomic_set(&pUmDevice->intr_sem, 0);
+	b44_LM_EnableInterrupt(pDevice);
+#if (LINUX_VERSION_CODE >= 0x020406)
+	return 0;
+#endif
+}
+
+
+static struct pci_driver bcm4400_pci_driver = {
+	name:		bcm4400_driver,
+	id_table:	bcm4400_pci_tbl,
+	probe:		bcm4400_init_one,
+	remove:		bcm4400_remove_one,
+	suspend:	bcm4400_suspend,
+	resume:		bcm4400_resume,
+};
+
+
+static int __init bcm4400_init_module (void)
+{
+	return pci_module_init(&bcm4400_pci_driver);
+}
+
+
+static void __exit bcm4400_cleanup_module (void)
+{
+	pci_unregister_driver(&bcm4400_pci_driver);
+}
+
+
+module_init(bcm4400_init_module);
+module_exit(bcm4400_cleanup_module);
+#endif
+
+/*
+ * Middle Module
+ *
+ */
+
+
+LM_STATUS
+b44_MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT16 *pValue16)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_read_config_word(pUmDevice->pdev, Offset, (u16 *) pValue16);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT32 *pValue32)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_read_config_dword(pUmDevice->pdev, Offset, (u32 *) pValue32);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT16 Value16)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_write_config_word(pUmDevice->pdev, Offset, Value16);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
+	LM_UINT32 Value32)
+{
+	UM_DEVICE_BLOCK *pUmDevice;
+
+	pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+	pci_write_config_dword(pUmDevice->pdev, Offset, Value32);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+	PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy)
+{
+	PLM_VOID pvirt;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	dma_addr_t mapping;
+
+	pvirt = pci_alloc_consistent(pUmDevice->pdev, BlockSize,
+					       &mapping);
+	if (!pvirt) {
+		return LM_STATUS_FAILURE;
+	}
+	pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+	pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
+	pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+	memset(pvirt, 0, BlockSize);
+	*pMemoryBlockVirt = (PLM_VOID) pvirt;
+	*pMemoryBlockPhy = (LM_PHYSICAL_ADDRESS) mapping;
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+	PLM_VOID *pMemoryBlockVirt)
+{
+	PLM_VOID pvirt;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+
+
+	/* Maximum in slab.c */
+	if (BlockSize > 131072) {
+		goto b44_MM_Alloc_error;
+	}
+
+	pvirt = kmalloc(BlockSize, GFP_KERNEL);
+	if (!pvirt) {
+		goto b44_MM_Alloc_error;
+	}
+	pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+	pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
+	pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = 0;
+	/* mem_size_list[i] == 0 indicates that the memory should be freed */
+	/* using kfree */
+	memset(pvirt, 0, BlockSize);
+	*pMemoryBlockVirt = pvirt;
+	return LM_STATUS_SUCCESS;
+
+b44_MM_Alloc_error:
+	printk(KERN_WARNING "%s: Memory allocation failed - buffer parameters may be set too high\n", pUmDevice->dev->name);
+	return LM_STATUS_FAILURE;
+}
+
+LM_STATUS
+b44_MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+
+	pDevice->pMappedMemBase = ioremap_nocache(
+		pci_resource_start(pUmDevice->pdev, 0),
+			sizeof(bcmenetregs_t) + 128);
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
+{
+	int i;
+	struct sk_buff *skb;
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	PUM_PACKET pUmPacket;
+	PLM_PACKET pPacket;
+
+	for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
+		pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+		pUmPacket = (PUM_PACKET) pPacket;
+		if (pPacket == 0) {
+			printk(KERN_DEBUG "Bad RxPacketFreeQ\n");
+		}
+		skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize);
+		if (skb == 0) {
+			pUmPacket->skbuff = 0;
+			QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+			continue;
+		}
+		pUmPacket->skbuff = skb;
+		pPacket->u.Rx.pRxBufferVirt = skb->tail;
+		skb->dev = pUmDevice->dev;
+		skb_reserve(skb, pDevice->rxoffset);
+		QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+	}
+	if (1) {
+		/* reallocate buffers in the ISR */
+		pUmDevice->rx_buf_repl_thresh = 0;
+		pUmDevice->rx_buf_repl_panic_thresh = 0;
+	}
+	else {
+		pUmDevice->rx_buf_repl_thresh = pDevice->RxPacketDescCnt / 4;
+		pUmDevice->rx_buf_repl_panic_thresh =
+			pDevice->RxPacketDescCnt / 2;
+
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	int index = pUmDevice->index;
+
+	if (auto_speed[index] == 0)
+		pDevice->DisableAutoNeg = TRUE;
+	else
+		pDevice->DisableAutoNeg = FALSE;
+
+	if (line_speed[index] == 0) {
+		pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+		pDevice->DisableAutoNeg = FALSE;
+	}
+	else {
+		if (full_duplex[index]) {
+			pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
+		}
+		else {
+			pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_HALF;
+		}
+
+		if (line_speed[index] == 100) {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_100MBPS;
+		}
+		else if (line_speed[index] == 10) {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_10MBPS;
+		}
+		else {
+			pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+			pDevice->DisableAutoNeg = FALSE;
+			printk(KERN_WARNING "%s: Invalid line_speed parameter (%d), using 0\n", pUmDevice->dev->name, line_speed[index]);
+		}
+
+	}
+	pDevice->FlowControlCap = 0;
+	if (rx_flow_control[index] != 0) {
+		pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+	}
+	if (tx_flow_control[index] != 0) {
+		pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+	}
+	if (auto_flow_control[index] != 0) {
+		if (pDevice->DisableAutoNeg == FALSE) {
+
+			pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
+			if ((tx_flow_control[index] == 0) &&
+				(rx_flow_control[index] == 0)) {
+
+				pDevice->FlowControlCap |=
+					LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+					LM_FLOW_CONTROL_RECEIVE_PAUSE;
+			}
+		}
+		else {
+			printk(KERN_WARNING "%s: Conflicting auto_flow_control parameter (%d), using 0\n",
+				pUmDevice->dev->name, auto_flow_control[index]);
+		}
+
+	}
+
+	pUmDevice->timer_interval = HZ / 10;
+	pUmDevice->link_interval = HZ / pUmDevice->timer_interval;
+
+	if ((tx_pkt_desc_cnt[index] == 0) ||
+		(tx_pkt_desc_cnt[index] > MAX_TX_PACKET_DESC_COUNT)) {
+
+		printk(KERN_WARNING "%s: Invalid tx_pkt_desc_cnt parameter (%d), using %d\n",
+			pUmDevice->dev->name, tx_pkt_desc_cnt[index],
+			DEFAULT_TX_PACKET_DESC_COUNT);
+
+		tx_pkt_desc_cnt[index] = DEFAULT_TX_PACKET_DESC_COUNT;
+	}
+	pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
+	if ((rx_pkt_desc_cnt[index] == 0) ||
+		(rx_pkt_desc_cnt[index] >= MAX_RX_PACKET_DESC_COUNT)) {
+
+		printk(KERN_WARNING "%s: Invalid rx_pkt_desc_cnt parameter (%d), using %d\n",
+			pUmDevice->dev->name, rx_pkt_desc_cnt[index],
+			DEFAULT_RX_PACKET_DESC_COUNT);
+
+		rx_pkt_desc_cnt[index] = DEFAULT_RX_PACKET_DESC_COUNT;
+	}
+	pDevice->RxPacketDescCnt = rx_pkt_desc_cnt[index];
+
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+	struct sk_buff *skb;
+	int size;
+
+	while (1) {
+		pPacket = (PLM_PACKET)
+			QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
+		if (pPacket == 0)
+			break;
+		pUmPacket = (PUM_PACKET) pPacket;
+#if ! defined(NO_PCI_UNMAP)
+		pci_unmap_single(pUmDevice->pdev,
+				pci_unmap_addr(pUmPacket, map[0]),
+				pPacket->u.Rx.RxBufferSize,
+				PCI_DMA_FROMDEVICE);
+#endif
+		if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
+			((size = pPacket->PacketSize) > 1518)) {
+
+			/* reuse skb */
+#ifdef BCM_TASKLET
+			QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+#else
+			QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+#endif
+			pUmDevice->rx_misc_errors++;
+			continue;
+		}
+		skb = pUmPacket->skbuff;
+		skb_put(skb, size);
+		skb->pkt_type = 0;
+		skb->protocol = eth_type_trans(skb, skb->dev);
+		skb->ip_summed = CHECKSUM_NONE;
+		netif_rx(skb);
+
+#ifdef BCM_TASKLET
+		pUmPacket->skbuff = 0;
+		QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+#else
+		skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize);
+		if (skb == 0) {
+			pUmPacket->skbuff = 0;
+			QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+		}
+		else {
+			pUmPacket->skbuff = skb; 
+			pPacket->u.Rx.pRxBufferVirt = skb->tail;
+			skb->dev = pUmDevice->dev;
+			skb_reserve(skb, pDevice->rxoffset);
+			QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+		}
+#endif
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+/* Returns 1 if not all buffers are allocated */
+STATIC int
+bcm4400_rxfill(PUM_DEVICE_BLOCK pUmDevice)
+{
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+	PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+	struct sk_buff *skb;
+	int queue_rx = 0;
+	int ret = 0;
+
+	while ((pUmPacket = (PUM_PACKET)
+		QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
+		pPacket = (PLM_PACKET) pUmPacket;
+		if (pUmPacket->skbuff) {
+			/* reuse an old skb */
+			QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+			queue_rx = 1;
+			continue;
+		}
+		if ((skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize)) == 0) {
+			QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,
+				pPacket);
+			ret = 1;
+			break;
+		}
+		pUmPacket->skbuff = skb;
+		pPacket->u.Rx.pRxBufferVirt = skb->tail;
+		skb->dev = pUmDevice->dev;
+		skb_reserve(skb, pDevice->rxoffset);
+		QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+		queue_rx = 1;
+	}
+	if (queue_rx) {
+		b44_LM_QueueRxPackets(pDevice);
+	}
+	return ret;
+}
+
+LM_STATUS
+b44_MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	PLM_PACKET pPacket;
+	PUM_PACKET pUmPacket;
+	struct sk_buff *skb;
+#if ! defined(NO_PCI_UNMAP) && MAX_SKB_FRAGS
+	int i;
+#endif
+
+	while (1) {
+		pPacket = (PLM_PACKET)
+			QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
+		if (pPacket == 0)
+			break;
+		pUmPacket = (PUM_PACKET) pPacket;
+		skb = pUmPacket->skbuff;
+#if ! defined(NO_PCI_UNMAP)
+		pci_unmap_single(pUmDevice->pdev,
+				pci_unmap_addr(pUmPacket, map[0]),
+				pci_unmap_len(pUmPacket, map_len[0]),
+				PCI_DMA_TODEVICE);
+#endif
+		dev_kfree_skb_irq(skb);
+		pUmPacket->skbuff = 0;
+		QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+	}
+	if (pUmDevice->tx_full) {
+		if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
+			(pDevice->TxPacketDescCnt >> 1)) {
+
+			pUmDevice->tx_full = 0;
+			netif_wake_queue(pUmDevice->dev);
+		}
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
+{
+	PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+	struct net_device *dev = pUmDevice->dev;
+	LM_FLOW_CONTROL flow_control;
+
+	if (!pUmDevice->opened)
+		return LM_STATUS_SUCCESS;
+
+	if (pUmDevice->delayed_link_ind > 0) {
+		return LM_STATUS_SUCCESS;
+	}
+	else {
+		if (Status == LM_STATUS_LINK_DOWN) {
+			pUmDevice->line_speed = 0;
+			netif_carrier_off(dev);
+			printk(KERN_ERR "%s: %s NIC Link is Down\n", bcm4400_driver, dev->name);
+		}
+		else if (Status == LM_STATUS_LINK_ACTIVE) {
+			netif_carrier_on(dev);
+			printk(KERN_INFO "%s: %s NIC Link is Up, ", bcm4400_driver, dev->name);
+		}
+	}
+
+	if (Status == LM_STATUS_LINK_ACTIVE) {
+		if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
+			pUmDevice->line_speed = 100;
+		else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+			pUmDevice->line_speed = 10;
+
+		printk("%d Mbps ", pUmDevice->line_speed);
+
+		if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+			printk("full duplex");
+		else
+			printk("half duplex");
+
+		flow_control = pDevice->FlowControl &
+			(LM_FLOW_CONTROL_RECEIVE_PAUSE |
+			LM_FLOW_CONTROL_TRANSMIT_PAUSE);
+		if (flow_control) {
+			if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
+				printk(", receive ");
+				if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+					printk("& transmit ");
+			}
+			else {
+				printk(", transmit ");
+			}
+			printk("flow control ON");
+		}
+		printk("\n");
+	}
+	return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+b44_MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+	PUM_PACKET pUmPacket;
+	struct sk_buff *skb;
+
+	if (pPacket == 0)
+		return LM_STATUS_SUCCESS;
+	pUmPacket = (PUM_PACKET) pPacket;
+	if ((skb = pUmPacket->skbuff))
+		dev_kfree_skb(skb);
+	pUmPacket->skbuff = 0;
+	return LM_STATUS_SUCCESS;
+}
+
+
