HP NC10xx/67xx/77xx/150x/320x/325x Gigabit Ethernet NIC Driver for Linux
authorMarc Fiuczynski <mef@cs.princeton.edu>
Fri, 20 Jan 2006 04:23:45 +0000 (04:23 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Fri, 20 Jan 2006 04:23:45 +0000 (04:23 +0000)
26 files changed:
configs/kernel-2.6.12-i686-planetlab.config
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/bcm5700/5701rls.c [new file with mode: 0644]
drivers/net/bcm5700/5701rls.h [new file with mode: 0644]
drivers/net/bcm5700/DISTRIB.TXT [new file with mode: 0755]
drivers/net/bcm5700/LICENSE [new file with mode: 0755]
drivers/net/bcm5700/Makefile [new file with mode: 0755]
drivers/net/bcm5700/README.TXT [new file with mode: 0644]
drivers/net/bcm5700/RELEASE.TXT [new file with mode: 0755]
drivers/net/bcm5700/autoneg.c [new file with mode: 0644]
drivers/net/bcm5700/autoneg.h [new file with mode: 0644]
drivers/net/bcm5700/b57diag.c [new file with mode: 0644]
drivers/net/bcm5700/b57proc.c [new file with mode: 0644]
drivers/net/bcm5700/b57um.c [new file with mode: 0644]
drivers/net/bcm5700/bcm5700.4 [new file with mode: 0644]
drivers/net/bcm5700/bits.h [new file with mode: 0644]
drivers/net/bcm5700/fw_lso05.h [new file with mode: 0644]
drivers/net/bcm5700/fw_stkoffld.h [new file with mode: 0644]
drivers/net/bcm5700/lm.h [new file with mode: 0644]
drivers/net/bcm5700/mm.h [new file with mode: 0644]
drivers/net/bcm5700/nicext.h [new file with mode: 0644]
drivers/net/bcm5700/queue.h [new file with mode: 0644]
drivers/net/bcm5700/tcp_seg.c [new file with mode: 0644]
drivers/net/bcm5700/tigon3.c [new file with mode: 0644]
drivers/net/bcm5700/tigon3.h [new file with mode: 0644]

index 241cc9b..39207d1 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-1.1_1390_FC4.1.planetlab.2005.08.04
-# Thu Aug 11 15:24:29 2005
+# Linux kernel version: 2.6.12-1.1398_FC4.4.planetlab
+# Thu Jan 19 15:15:51 2006
 #
 CONFIG_X86=y
 CONFIG_MMU=y
@@ -34,7 +34,6 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_OOM_PANIC=y
 # CONFIG_EMBEDDED is not set
-# CONFIG_DELAY_ACCT is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
@@ -798,6 +797,7 @@ CONFIG_SK98LIN=m
 CONFIG_VIA_VELOCITY=m
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
+CONFIG_BCM5700=m
 
 #
 # Ethernet (10000 Mbit)
@@ -1271,7 +1271,6 @@ CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
index f08e01b..ecd68fa 100644 (file)
@@ -2041,6 +2041,36 @@ config BNX2
          To compile this driver as a module, choose M here: the module
          will be called bnx2.  This is recommended.
 
+config BCM5700
+       tristate "Broadcom 57xx support"
+       depends on PCI
+       ---help---
+         This driver supports the Broadcom (HP NC10xx/67xx/77xx/150x/320x/325x) Gigabit 
+         family adapters.  Specifically, it supports:
+               HP NC1020 Gigabit Server Adapter
+               HP NC6770 Gigabit Server Adapter
+               HP NC7760 Gigabit Server Adapter
+               HP Embedded NC7761 Gigabit Server Adapter
+               HP NC7770 Gigabit Server Adapter
+               HP NC7771 Gigabit Server Adapter
+               HP NC7780 Gigabit Server Adapter
+               HP NC7781 Gigabit Server Adapter
+               HP NC7782 Embedded Gigabit Server
+               HP ProLiant NC150T PCI 4-Port Gigabit Combo Switch Adapter
+               HP NC320i Integrated Gigabit Server Adapter
+               HP NC325i Integrated Dual Port PCI Express Gigabit Server Adapter
+               HP NC320T Gigabit Server Adapter
+               HP NC324i Integrated Dual Port PCI Express Gigabit Server Adapter
+               HP NC326i Integrated Dual Port PCI Express Gigabit Server Adapter
+
+         The source for this driver was obtained from 
+         <http://h18000.www1.hp.com/support/files/networking/us/download/23968.html>
+
+         To compile this driver as a module, choose M here and read
+         <file:Documentation/networking/net-modules.txt>.  The module
+         will be called bcm5700.
+
+
 config GIANFAR
        tristate "Gianfar Ethernet"
        depends on 85xx || 83xx
index 30c7567..6f54eff 100644 (file)
@@ -6,6 +6,7 @@ ifeq ($(CONFIG_ISDN_PPP),y)
   obj-$(CONFIG_ISDN) += slhc.o
 endif
 
+obj-$(CONFIG_BCM5700) += bcm5700/
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IBM_EMAC) += ibm_emac/
 obj-$(CONFIG_IXGB) += ixgb/
diff --git a/drivers/net/bcm5700/5701rls.c b/drivers/net/bcm5700/5701rls.c
new file mode 100644 (file)
index 0000000..6b7d49c
--- /dev/null
@@ -0,0 +1,46 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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:                                                                   */
+/*                                                                            */
+/******************************************************************************/
+
+#ifdef 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 --git a/drivers/net/bcm5700/5701rls.h b/drivers/net/bcm5700/5701rls.h
new file mode 100644 (file)
index 0000000..793726d
--- /dev/null
@@ -0,0 +1,198 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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 --git a/drivers/net/bcm5700/DISTRIB.TXT b/drivers/net/bcm5700/DISTRIB.TXT
new file mode 100755 (executable)
index 0000000..2c4ba7d
--- /dev/null
@@ -0,0 +1,166 @@
+\r
+           Additional Installation Notes for Various Linux Distributions\r
+                       Broadcom BCM5700 Linux Driver\r
+                              Version 8.3.14\r
+                                11/02/2005\r
+\r
+                          Broadcom Corporation\r
+                          16215 Alton Parkway,\r
+                          Irvine, CA 92619-7013\r
+\r
+                Copyright (c) 2000-2005 Broadcom Corporation\r
+                           All rights reserved\r
+\r
+\r
+Table of Contents\r
+=================\r
+\r
+  Introduction\r
+  Limitations\r
+  Prerequisites\r
+  Enable Loadable Module Support on Turbolinux 10\r
+  Remove tg3 Driver\r
+  Edit /etc/modules.conf\r
+  Patching PCI Files (Red Hat - Optional)\r
+  Patching module-info Files (Red Hat - Optional)\r
+  Network Installation (Red Hat)\r
+  Message-"no version for "struct_module" found"\r
+\r
+Introduction\r
+============\r
+\r
+This file contains additional installation notes for the Broadcom NetXtreme\r
+bcm5700 Linux driver that are specific to certain Linux distributions. General\r
+installation notes are contained in README.TXT.\r
+\r
+\r
+Limitations\r
+===========\r
+\r
+The current version of the driver has been tested on selected Linux\r
+distributions for i386, ia64, and x86_64. Limited testing has also\r
+been done on PPC64 systems. Testing is normally focused on the\r
+following distributions:\r
+\r
+   Red Hat 4.0 and 3.0AS\r
+   SuSE 9\r
\r
+\r
+Prerequisites\r
+=============\r
+\r
+In order to compile your Broadcom NetXtreme Linux driver, you must first\r
+have a properly compiled kernel source tree which matches your running\r
+kernel.  You must also have a working C/C++ compiler and all the associated\r
+dependencies installed before attempting to compile the driver.\r
\r
+On Red Hat distributions, if you have opted for a custom installation, you\r
+need to select "Development Tools" and "Kernel Development" to install\r
+the necessary tools and kernel source tree.\r
+   \r
+On Linux distributions, you must change the software packages\r
+installed by default when presented with the Installation Settings.  Under\r
+software selelction, select "Detailed Selection".  In this area ensure that\r
+"C/C++ Compiler and Tools" is selected.  This should install the C/C++\r
+compiler as well as the kernel-source files.\r
+   \r
+For further assistance, please review your Linux documentation. \r
+    \r
+      \r
+Enable Loadable Module Support on Turboilinux 10 \r
+================================================\r
+\r
+When attempting to compile the driver, the following message may be displayed:\r
+\r
+   The present kernel configuration has modules disabled. Type 'make config'\r
+   and enable loadable module support. Then build a kernel with module\r
+   support enabled.\r
+\r
+Do the following to enable loadable module support:\r
+\r
+   cp /usr/src/configs/kernel-x.x.x-i586.config /usr/src/.config\r
+\r
+\r
+Remove tg3 Driver\r
+=================\r
+                                               \r
+Many newer distributions and newer kernels may already contain and use the\r
+tg3 driver by default for Broadcom BCM5700 series devices. While tg3 is a fully\r
+functioning driver written by Red Hat, Broadcom recommends users to use\r
+the bcm5700 driver written and tested by Broadcom.\r
+                                               \r
+1. Use ifconfig to bring down all interfaces used by tg3, then use `rmmod` to\r
+   remove the module if loaded.  The following assumes eth0 and eth1 are both\r
+   Broadcom devices using the tg3 driver.\r
+\r
+   ifconfig eth0 down\r
+   ifconfig eth1 down\r
+   rmmod tg3\r
+                                                                   \r
+2. Now it may be necessary to manually edit your /etc/modules.conf file to\r
+   allow the bcm5700 driver to load at boot time instead of the tg3 driver.  See\r
+   below.\r
+\r
+\r
+Edit /etc/modules.conf\r
+======================\r
+                                                                       \r
+If there is an alias entry in your /etc/modules.conf file referencing the\r
+tg3 driver, make sure that you replace tg3 with bcm5700.  Otherwise, add the\r
+entry below if necessary.\r
+                                                                        \r
+Example:\r
+\r
+alias eth0 bcm5700\r
+                                                                              \r
+\r
+Patching PCI Files (Red Hat - Optional)\r
+=======================================\r
+\r
+To use the Red Hat kudzu hardware detection utility, and to list the\r
+BCM5700 series devices by name using lspci, a script has been included\r
+in the bcm_sup-<version>.tar.gz package.\r
+The /bin/bash script to update the Red Hat PCI device list and patch\r
+files for the latest kernels by running this script. \r
+\r
+For example, on Red Hat 3 i386, apply the script in the following way:\r
+\r
+   ./update_ids.sh\r
+\r
+Run kudzu:\r
+\r
+   kudzu\r
+\r
+\r
+Network Installation (Red Hat)\r
+==============================\r
+\r
+For network installations through NFS, FTP, or HTTP (using a network boot disk\r
+or PXE), a driver diskette that contains the bcm5700 driver is needed.  The\r
+driver diskette images for the most recent Red Hat versions are included. Boot\r
+drivers for other Linux versions can be compiled by modifying the Makefile and\r
+the make environment. Further information is available from Red Hat's website.\r
+\r
+To create the driver diskette, select the appropriate image file, gunzip it,\r
+and do the following:\r
+\r
+dd if=dd.img of=/dev/fd0H1440.\r
+\r
+\r
+Message -"no version for "struct_module" found"\r
+==============================================\r
+If you see this message, bring the kernel version.h file up to date by \r
+executing the following command, then remake the bcm5700 module.\r
+\r
+(cd /usr/src/linux; make include/linux/version.h)\r
+\r
+\r
+'rpm -e' does not uninstall the bcm5700 module\r
+==============================================\r
+On some linux installations, the bcm5700 module comes as part of the kernel\r
+package.  In these cases, the administrator will have to install a newer\r
+version of the module by using the --force flag.  While this flag does\r
+allow the newer version module to be installed, it does not change the\r
+ownership of the file to the newer package.  Consequently, the 'rpm -e'\r
+command will not remove the file, since it is not associated with that\r
+package.\r
diff --git a/drivers/net/bcm5700/LICENSE b/drivers/net/bcm5700/LICENSE
new file mode 100755 (executable)
index 0000000..44e50a4
--- /dev/null
@@ -0,0 +1,290 @@
+
+
+
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+
diff --git a/drivers/net/bcm5700/Makefile b/drivers/net/bcm5700/Makefile
new file mode 100755 (executable)
index 0000000..2096995
--- /dev/null
@@ -0,0 +1,33 @@
+################################################################################
+#
+# Makefile for building Linux Broadcom Gigabit ethernet driver as a module.
+#
+################################################################################
+
+obj-$(CONFIG_BCM5700) = bcm5700.o
+
+bcm5700-objs    := b57um.o b57proc.o tigon3.o autoneg.o 5701rls.o tcp_seg.o b57diag.o
+
+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 $(NETDUMP_CFLAG)
+ifeq ($(ARCH),x86_64)
+  CFLAGS+=-mno-red-zone -mcmodel=kernel -pipe -finline-limit=2000
+endif
+
+ifeq ($(ARCH),ia64)
+  CFLAGS+=-pipe -ffixed-r13 -mfixed-range=f10-f15,f32-f127 -falign-functions=32
+endif
+
+ifeq ($(ARCH),ppc64)
+  CFLAGS+=-m64 
+  CFLAGS+=-fno-strict-aliasing -fno-common -fomit-frame-pointer -msoft-float -pipe -mminimal-toc -fno-builtin 
+endif
+
+ifdef DBG
+  CFLAGS += -DTIGON3_DEBUG=2
+endif
+
+ifdef SMALL
+  CFLAGS += -Os -DBCM_SMALL_DRV=1
+else
+  CFLAGS += -O2
+endif
diff --git a/drivers/net/bcm5700/README.TXT b/drivers/net/bcm5700/README.TXT
new file mode 100644 (file)
index 0000000..3555ef5
--- /dev/null
@@ -0,0 +1,566 @@
+
+                           Installation Notes
+                       Broadcom BCM5700 Linux Driver
+                              Version 8.3.14
+                                11/02/2005
+
+                          Broadcom Corporation
+                          16215 Alton Parkway,
+                          Irvine, CA 92619-7013
+
+                Copyright (c) 2000-2005 Broadcom Corporation
+                           All rights reserved
+
+
+Table of Contents
+=================
+
+  Introduction
+  Limitations
+  Packaging
+  Installing Source RPM Package
+  Building Driver From TAR File
+  Patching Driver Into Kernel
+  Unloading and Removing Driver
+  Module Parameters
+  Driver Messages
+  Statistics
+  
+
+Introduction
+============
+
+This file describes the Linux driver for the Broadcom NetXtreme BCM5700
+series 10/100/1000 Mbps PCI/PCI-X/PCI Express Ethernet Network Controllers.
+
+
+Limitations
+===========
+
+The current version of the driver has been tested on the latest Red Hat, SuSE,
+and other Linux distributions for i386, ia64, and x86_64 CPU architectures 
+using 2.4.x and 2.6.x kernels. The driver has been tested up to kernel
+version 2.4.31 and 2.6.13.
+
+The driver should work on other little endian or big endian CPU architectures,
+but only very limited testing has been done on some of these machines. The
+Makefile may have to be modified to include architecture specific compile
+switches, and some minor changes in the source files may also be required.
+On these machines, patching the driver into the kernel is recommended (see
+below for instructions).
+
+
+Packaging
+=========
+
+The driver is released in two packaging formats: source RPM and compressed tar
+formats. The file names for the two packages are bcm5700-<version>.src.rpm and
+bcm5700-<version>.tar.gz respectively. Identical source files to build the
+driver are included in both packages. bcm_sup-<version> is a seperate tar file 
+that contains additional utilities such as patches and driver diskette images 
+for network installation.
+
+
+Installing Source RPM Package
+=============================
+
+The following are general guidelines for installing the driver. Refer to
+DISTRIB.TXT for additional installation notes for various Linux distributions.
+
+1. Install the source RPM package:
+
+   rpm -ivh bcm5700-<version>.src.rpm
+
+2. CD to the RPM path and build the binary driver for your kernel:
+
+   cd /usr/src/{redhat,OpenLinux,turbo,packages,rpm ..}
+
+   rpm -bb SPECS/bcm5700.spec
+
+or
+
+   rpmbuild -bb SPECS/bcm5700.spec (for RPM version 4.x.x)
+
+Note that the RPM path is different for different Linux distributions.
+
+3. Install the newly built package (driver and man page):
+
+   rpm -ivh RPMS/i386/bcm5700-<version>.i386.rpm
+
+Note that the --force option is needed if installing on Red Hat 7.2, 7.3,
+2.1AS and others that already contain an older version of the driver.
+
+The driver will be installed in the following path:
+
+2.2.x kernels:
+
+    /lib/modules/<kernel_version>/net/bcm5700.o
+
+2.4.x kernels:
+
+    /lib/modules/<kernel_version>/kernel/drivers/net/bcm5700.o
+
+2.4.x kernels with bcm5700 as an addon driver (e.g. Red Hat 7.3, 2.1AS):
+
+    /lib/modules/<kernel_version>/kernel/drivers/net/bcm/bcm5700.o
+
+or
+
+    /lib/modules/<kernel_version>/kernel/drivers/addon/bcm5700/bcm5700.o
+
+2.6.x kernels:
+
+    /lib/modules/<kernel_version>/kernel/drivers/net/bcm5700.ko
+
+2.6.x kernels with bcm5700 as an addon driver (e.g. SuSE 9 SLES):
+
+    /lib/modules/<kernel_version>/kernel/drivers/net/bcm/bcm5700.ko
+
+4. Load the driver:
+
+   modprobe bcm5700
+
+If loading the driver on Red Hat 3 update 4, 2.1 AS or other newer kernels with the
+tg3 driver, refer to the "Removing tg3 Driver" in DISTRIB.TXT before loading
+the driver.
+
+5. To configure network protocol and address, refer to various Linux
+documentations.
+
+
+Building Driver From TAR File
+=============================
+
+The following are general guidelines for installing the driver. Refer to
+DISTRIB.TXT for additional installation notes for various Linux distributions.
+
+1. Create a directory and extract the files:
+
+   tar xvzf bcm5700-<version>.tar.gz
+
+2. Build the driver bcm5700.o as a loadable module for the running kernel:
+
+   cd src
+   make
+
+3. Test the driver by loading it: 
+
+   insmod bcm5700.o
+or
+   insmod bcm5700.ko (on 2.6.x kernels)
+
+If loading the driver on Red Hat 3 update 4, 2.1 AS or other newer kernels with the
+tg3 driver, refer to the "Removing tg3 Driver" in DISTRIB.TXT before loading
+the driver.
+
+4. Install the driver and man page:
+
+   make install
+
+See RPM instructions above for the location of the installed driver.
+
+5. To configure network protocol and address, refer to various Linux
+documentations.
+
+
+Patching Driver Into Kernel (Optional)
+======================================
+
+Patch files are included for patching the driver into some of the latest
+2.4.x and 2.6.x kernel source trees. This step is optional and can be done
+by users familiar with configuring and building the kernel. The patch
+will modify the orginal kernel's source code.
+
+The following steps may allow you to patch the driver into a kernel:
+
+1. Select the patch file that matches your kernel and apply the patch:
+
+   patch -p1 -d <kernel_src_root> < bcm5700-<version>-2.4.<x>.patch
+   patch -p1 -d <kernel_src_root> < bcm5700-<version>-2.6.<x>.patch
+
+where <version> is the version of the bcm5700 driver and 2.4.<x> is the
+version of the kernel to patch (e.g. 2.4.31).
+
+Note: <kernel_src_root> is usually /usr/src/linux or /usr/src/linux-2.4.<x>
+Note: <kernel_src_root> is usually /usr/src/linux or /usr/src/linux-2.6.<x>
+
+2. Configure the kernel to include the bcm5700 driver. It can be found
+under Network Device Support ---> Ethernet (1000 Mbit) ---> Broadcom BCM5700
+support when make menuconfig is run. Select built-in or module for the driver:
+
+   cd <kernel_src_root>
+   make menuconfig 
+
+3. Compile the kernel:
+
+   make dep
+   make clean
+   ....
+   ....
+
+
+Unloading and Removing Driver
+=============================
+
+To unload the driver, use ifconfig to bring down all eth# interfaces opened
+by the driver, then do the following:
+
+rmmod bcm5700
+
+
+If the driver was installed using rpm, do the following to remove it:
+
+rpm -e bcm5700
+
+
+If the driver was installed using make install from the tar file, the driver
+bcm5700.o has to be manually deleted from the system. Refer to the section
+"Installing Source RPM Package" for the location of the installed driver.
+
+
+Module Parameters
+=================
+
+Optional parameters for the driver can be supplied as command line arguments 
+to the insmod command. Typically, these parameters are set in the file
+/etc/modules.conf (see the man page for modules.conf). These parameters take
+the form
+
+    <parameter>=value[,value,...]
+
+where the multiple values for the same parameter are for multiple NICs
+installed in the system.
+
+Note that default or other meaningful values will be used when invalid values
+are selected. Some combinations of parameter values may conflict and lead to
+failures. The driver cannot detect all such conflicting combinations.
+
+All the parameters are listed below.
+
+line_speed
+
+    Selects the line speed of the link. This parameter is used together with
+    full_duplex and auto_speed to select the speed and duplexity of the link
+    and the setting of autonegotiation.
+    
+    The valid values are:
+    
+    0      Autonegotiate for highest speed supported by link partner (default)
+    10     10 Mbps
+    100    100 Mbps
+    1000   1000 Mbps
+
+    If line_speed is set to 10, 100, or 1000, the NIC will autonegotiate for
+    the selected speed (and selected duplexity) if auto_speed is set to 1.
+    If auto_speed is set to 0, the selected speed and duplexity will be
+    set without autonegotiation. Note that 1000 Mbps must be negotiated for
+    copper twisted pair links.
+
+auto_speed
+
+    Enables or disables autonegotiation. The valid values are:
+
+    0      Autonegotiation disabled
+    1      Autonegotiation enabled (default)
+
+    Note that this parameter is ignored and assumed 1 if line_speed is set
+    to 0.
+    
+full_duplex
+
+    Selects the duplexity of the link. This paramter is used together with
+    line_speed to select the speed and duplexity of the link. Note that this
+    parameter is ignored if line_speed is 0.
+    
+    The valid values are:
+    
+    0      half duplex
+    1      full duplex (default)
+    
+    
+rx_flow_control
+
+    Enables or disables receiving flow control (pause) frames. This parameter
+    is used together with auto_flow_control. The valid values are:
+    
+    0      pause receive disabled
+    1      pause receive enabled if auto_flow_control is set to 0, or
+           pause receive advertised if auto_flow_control is set to 1 (default)
+
+tx_flow_control
+
+    Enables or disables transmitting flow control (pause) frames. This parameter
+    is used together with auto_flow_control. The valid values are:
+    
+    0      pause transmit disabled
+    1      pause transmit enabled if auto_flow_control is set to 0, or
+           pause transmit advertised if auto_flow_control is set to 1 (default)
+
+auto_flow_control
+
+    Enables or disables autonegotiation of flow control. This parameter is used
+    together with rx_flow_control and tx_flow_control to determine the
+    advertised flow control capability. The valid values are:
+    
+    0      flow control autonegotiation disabled
+    1      flow control autonegotiation enabled with capability specified in
+           rx_flow_control and tx_flow_control (only valid if line_speed is
+           set to 0 or auto_speed is set to 1) (default)
+
+mtu
+
+    Enables jumbo frames up to the specified MTU size. The valid range for
+    this parameter is 1500 to 9000. Default is 1500 which is standard
+    ethernet (non-jumbo) MTU size. Note that the MTU size excludes the
+    ethernet header size of 14 bytes. Actual frame size is MTU size + 14 bytes.
+    Jumbo MTU sizes are not supported on BCM5705 chips.
+
+    The MTU size can also be changed using ifconfig after the driver is loaded.
+    See the ifconfig man page for details.
+
+tx_checksum
+
+    Enables or disables hardware transmit TCP/UDP checksum. The valid values
+    are:
+
+    0      checksum disabled
+    1      checksum enabled (default)
+
+rx_checksum
+
+    Enables or disables hardware receive TCP/UDP checksum validation. The
+    valid values are:
+
+    0      checksum disabled
+    1      checksum enabled (default)
+
+scatter_gather
+
+    Enables or disables scatter-gather and 64-bit DMA on x86. This option is
+    only useful when running on TUX-enabled kernels or newer kernels with
+    zero-copy TCP. The valid values are:
+
+    0      scatter-gather and 64-bit DMA on x86 disabled
+    1      scatter-gather and 64-bit DMA on x86 enabled (default)
+
+nic_tx_bd
+
+    Enables either NIC based or host based transmit buffer descriptors (Tx BDs).
+    NIC based Tx BDs may be slightly faster on certain machines on earlier
+    2.4 kernels where each transmit packet is usually entirely contiguous. On
+    later kernels with scatter-gather and TCP segmentation option, host based
+    Tx BDs using DMA transfer are usually faster. NIC based Tx BDs are not
+    supported on 5705 and later family controllers. The valid values are:
+
+    0      NIC based transmit buffer descriptors disabled (using host based
+           transmit buffer descriptors) (default)
+    1      NIC based transmit buffer descriptors enabled (not supported
+           on 5705 family controllers)
+
+tx_pkt_desc_cnt
+
+    Configures the number of transmit descriptors. Default is 120. The
+    valid range is from 1 to 511. Note that the driver may not be able to
+    allocate the required amount of memory if this parameter is set too high.
+    Depending on kernel and CPU architecture, each descriptor may require up
+    to about 268 bytes. This parameter should not be set less than 80 if
+    adaptive_coalesce (see below) is enabled.
+
+rx_std_desc_cnt
+
+    Configures the number of receive descriptors for frames up to 1528 bytes.
+    Default is 200. The valid range is from 1 to 511. This parameter should
+    not be set less than 80 on systems with high network traffic. Setting this
+    parameter higher allows the NIC to buffer larger bursts of network
+    traffic without dropping frames, especially on slower systems. Note that
+    the driver may not be able to allocate the required amount of memory if
+    this parameter is set too high. Depending on kernel and CPU architecture,
+    each descriptor may require up to about 268 bytes. Each descriptor also
+    requires a socket buffer of at least 1536 bytes. This parameter should not
+    be set less than 50 if adaptive_coalesce (see below) is enabled.
+
+rx_jumbo_desc_cnt
+
+    Configures the number of receive descriptors for jumbo frames larger
+    than 1528 bytes. Default is 128 and valid range is from 1 to 255.
+    When jumbo frames larger than 1528 bytes are used, this parameter should
+    not be set lower than 60 on systems with high network traffic. Setting
+    this parameter higher allows the NIC to buffer larger bursts of jumbo
+    traffic without dropping frames, especially on slower systems. Depending
+    on kernel and CPU architecture, each descriptor may require up to about
+    268 bytes. Each descriptor also requires a socket buffer the size of a
+    maximum jumbo frame. On systems with insufficient memory, it may be
+    necessary to reduce this parameter. This parameter should not be set less
+    than 50 if adaptive_coalesce (see below) is enabled. When the maximum
+    frame size is 1528 or smaller (MTU size 1514 or smaller), this parameter
+    is not used and is always 0.
+
+adaptive_coalesce
+
+    Enables or disables adaptive adjustments to the various interrupt
+    coalescing parameters. Enabling it allows the driver to dynamically
+    adjust the interrupt coalescing parameters to achieve high throughput
+    during heavy traffic and low latency during light traffic.
+    rx_std_desc_cnt, (and rx_jumbo_desc_cnt if using jumbo frames) should not
+    be set less than 50, and tx_pkt_desc_cnt should not be set less than 80
+    when this parameter is enabled. Note that if the kernel supports the NAPI
+    receive polling mode, interrupt coalescing will be handled in a different
+    way and this parameter will not be used. The valid values are:
+
+    0      disabled (always disabled in NAPI mode)
+    1      enabled (default)
+
+rx_coalesce_ticks
+
+    Configures the number of 1 usec ticks before the NIC generates receive
+    interrupt after receiving a frame. This parameter works in conjunction
+    with the rx_max_coalesce_frames parameter. Interrupt will be generated
+    when either of these thresholds is exceeded. 0 means this parameter is
+    ignored and interrupt will be generated when the rx_max_coalesce_frames
+    threshold is reached. The valid range is from 0 to 500, and default is
+    60 (18 if using NAPI mode). This parameter is not used and will be
+    adjusted automatically if adaptive_coalesce is set to 1.
+
+rx_max_coalesce_frames
+
+    Configures the number of received frames before the NIC generates receive
+    interrupt. The valid range is from 0 to 100, and default is 15 (6 if using
+    NAPI mode). This parameter and rx_coalesce_ticks cannot be both 0,
+    otherwise no receive interrupts will be generated. It should also be set
+    lower than rx_std_desc_cnt (and rx_jumbo_desc_cnt if using jumbo frames).
+    This parameter is not used and will be adjusted automatically if
+    adaptive_coalesce is set to 1.
+
+tx_coalesce_ticks
+
+    Configures the number of 1 usec ticks before the NIC generates transmit
+    interrupt after transmitting a frame. This parameter works in conjunction
+    with the tx_max_coalesce_frames parameter. Interrupt will be generated
+    when either of these thresholds is exceeded. 0 means this
+    parameter is ignored and interrupt will be generated when the
+    tx_max_coalesce_frames threshold is reached. The valid range is from 0 to
+    500, and default is 200. This parameter is not used and will be adjusted
+    automatically if adaptive_coalesce is set to 1.
+
+tx_max_coalesce_frames
+
+    Configures the number of transmitted frames before the NIC generates
+    transmit interrupt. The valid range is from 0 to 100, and default is 35.
+    This parameter and tx_coalesce_ticks cannot be both 0, otherwise no
+    transmit completion interrupt will be generated. This parameter should
+    always be set lower than tx_pkt_desc_cnt. This parameter is not used and
+    will be adjusted automatically if adaptive_coalesce is set to 1.
+
+stats_coalesce_ticks
+
+    Configures the number of 1 usec ticks between periodic statistics updates 
+    (DMAs). The valid range is from 100 to 3600000000, and default is 1000000
+    (1 sec.). 0 is also valid and is used to disable statistics updates.
+    This parameter is not used and will be set to default if adaptive_coalesce
+    is set to 1. Please note that the valid range may vary by kernel version.
+
+enable_wol
+
+    Enables or disables magic packet Wake-On-LAN when the system is shutdown.
+    Note that not all systems support Wake-On-LAN. The valid values are:
+
+    0    magic packet Wake-On-LAN disabled (default)
+    1    magic packet Wake-On-LAN enabled
+
+enable_tso
+
+    Enables or disables TCP Segmentation Option (TSO) when using kernels that
+    support it. This parameter is only defined on newer kernels that support
+    TSO. The valid values are:
+
+    0    TSO disabled
+    1    TSO enabled (default)
+
+disable_msi
+
+    Enables or disables message signal interrupts (MSI) when using kernels that
+    support it. This parameter is only defined on newer kernels that support
+    MSI. The valid values are:
+
+    1    MSI disabled
+    0    MSI enabled (default)
+    Note: Only applies to the latest devices.
+
+vlan_tag_mode
+
+    This parameter controls the stripping of VLAN tags on incoming packets,
+    and is used to allow VLAN tagged ASF or IPMI packets to be received
+    properly. The valid values are:
+
+    0    Auto mode (default)
+    1    Normal strip mode
+    2    Forced strip mode
+
+    In normal mode, VLAN tags are only stripped if VLANs are registered
+    by the 802.1q VLAN module or BASP. In forced strip mode, VLAN tags
+    are always stripped. Auto mode will select normal strip mode if ASF/IPMI
+    is disabled, or forced strip mode if ASF/IPMI is enabled.
+
+delay_link
+
+    If set to 1, this parameter will cause the driver to return 
+    -EOPNOTSUPP when the SIOCGMIIREG or ETHTOOL_GLINK ioctls are called
+    during the first 6 seconds after driver reset. When the driver resets
+    the NIC during ifconfig, the link will drop and it may take several
+    seconds for the link to come up after autonegotiation completes. Some
+    applications, such as ifup, may not wait long enough for the link
+    before giving up. Setting this parameter to 1 may get around such
+    problems. The default value is 0, which means that the driver will
+    always return true link states to all ioctl calls, when applicable.
+
+disable_d3hot
+
+    If set to 1, this parameter will cause the driver to never
+    put the device in D3Hot power state when the NIC is shutdown or
+    suspended. If set, this parameter will also disable the Wake-On-Lan
+    setting. A rare D3Hot related problem was seen during repeated
+    shutdown of PCI Express devices on systems running 2.6 kernels.
+
+Driver Messages
+===============
+
+The following are the most common sample messages that may be logged in the file
+/var/log/messages. Use dmesg -n <level> to control the level at which messages
+will appear on the console. Most systems are set to level 6 by default.
+
+Broadcom Gigabit Ethernet Driver bcm5700 with Broadcom NIC Extension (NICE)
+ver. 8.3.14 (11/02/05)
+
+    Driver signon
+
+
+eth#: Broadcom BCM5704 1000Base-T found at mem faff0000, IRQ 16, node addr 0010180402d8
+eth#: Broadcom BCM5704 Integrated Copper transceiver found
+eth#: Scatter-gather ON, 64-bit DMA ON, Tx Checksum ON, Rx Checksum ON, 802.1Q VLAN ON, TSO ON, NAPI ON
+
+    NIC detected
+
+
+bcm5700: eth# NIC Link is Up, 1000 Mbps full duplex, receive and transmit flow control ON
+
+    Link up and speed indication
+
+
+bcm5700: eth# NIC Link is Down
+
+    Link down indication
+
+bcm5700: eth# Using Message Signaled Interrupt (MSI) 
+
+    The driver is in MSI mode 
+
+bcm5700: eth# Using PCI INTX interrupt 
+
+    The driver is in IRQ mode
+
+Statistics
+==========
+
+Detailed statistics and configuration information can be viewed in the file
+/proc/net/nicinfo/eth#.info.
+
diff --git a/drivers/net/bcm5700/RELEASE.TXT b/drivers/net/bcm5700/RELEASE.TXT
new file mode 100755 (executable)
index 0000000..abfc21c
--- /dev/null
@@ -0,0 +1,3687 @@
+\r
+                              Release Notes\r
+                       Broadcom BCM5700 Linux Driver\r
+                              Version 8.3.14\r
+                                11/02/2005\r
+\r
+                          Broadcom Corporation\r
+                          16215 Alton Parkway,\r
+                          Irvine, CA 92619-7013\r
+\r
+                Copyright (c) 2000-2005 Broadcom Corporation\r
+                           All rights reserved\r
+\r
+\r
+v8.3.14 (November 02, 2005)\r
+===========================\r
+    Fixes:\r
+    ------\r
+    1. Problem : (CQ14546) Montara A2 devices cannot write to ST flash\r
+                 parts.\r
+       Cause   : ST parts require an additional "write enable" command\r
+                 to be executed before any write operations can\r
+                 commence.  Montara A2 devices do not issue this\r
+                 command on behalf of the driver.\r
+       Change  : Code already exists in the driver to issue the\r
+                 "write enable" command, but the code is only enabled\r
+                 on an opt-in basis.  The 5714 family devices have\r
+                 been added to the list of devices that explicitly\r
+                 issue this command.\r
+       Impact  : This fix only impacts 5714 family of devices.\r
+\r
+\r
+v8.3.13 (October 28, 2005)\r
+==========================\r
+    Fixes:\r
+    ------\r
+    1. Problem : CQ13326 NETDEV Watchdog timeout followed by kernel panic.\r
+       Cause   : A NETDEV watchdog timeout was occurring because writes to the\r
+                 indirect memory register were not being flushed when setting\r
+                 the watchdog timer's keep alive bit.\r
+       Change  : Changed the driver to use direct memory writes instead of\r
+                 indirect memory writes when setting the keep alive bit.\r
+       Impact  : This fix impacts any PCI-E device that has ASF/IPMI enabled.\r
+\r
+\r
+\r
+v8.3.11 (October 20, 2005)\r
+==========================\r
+    Fixes:\r
+    ------\r
+    1. Problem : CQ13326 NETDEV Watchdog timeout followed by kernel panic. \r
+                 Some systems would generate NMI's followed by NETDEV Watchdog\r
+                 timeouts and eventually panic when running a stress test using\r
+                 multiple NIC's in a BASP team with ASF/IPMI enabled.\r
+       Cause   : The NMI was caused by the ASF/IPMI firmware reseting the NIC\r
+                 while the driver was operational because of a watchdog timeout. \r
+                 The watchdog timeout was occurring because the keep alive\r
+                 handshake between the driver and firmware would fail\r
+                 occasionally for the same reason as documented in CQ13369 in\r
+                 v8.3.1. In this case, the driver was using pci config writes to\r
+                 set the keep alive flag when ASF/IPMI was enabled. Pci config\r
+                 writes made by the driver while it is running can result in the\r
+                 chipset misrouting the write to another device. When this\r
+                 happens, the firmware does not see the keep alive bit being set\r
+                 by the driver and concludes that the driver had failed and\r
+                 resets the chip accordingly. \r
+       Change  : There are two methods available to workaround this problem. One\r
+                 workaround is to set the pci=nommconfig switch when starting\r
+                 the kernel. This switch is available only with newer kernels\r
+                 (2.6) and on systems that support PCI-E (i.e. ICH6-7). Starting\r
+                 the kernel with this switch will disable memory mapped config\r
+                 cycles from being used by the kernel, so the kernel instead\r
+                 uses the standard 0xcf8/0xcfc i/o ports to generate pci config\r
+                 cycles. The other method is to upgrade to this driver which\r
+                 avoids using pci config cycles when updating the keep alive\r
+                 flag and uses memory writes cycles instead.\r
+       Impact  : This problem occurs on devices that have ASF/IPMI enabled and \r
+                 are running on a 2.6 kernel and in a system that is PCI-E\r
+                 capable. Similarly, this patch is executed only on systems with\r
+                 an Intel ICH4 or newer chipsets and when ASF/IPMI is enable.\r
+                 The patch is not executed if ASF is disable. Also, the old\r
+                 method of using pci config writes to update the keep alive flag\r
+                 is used when the chipset is older than ICH4.\r
+\r
+    2. Problem : Broadcom Teaming driver would not fail over when controller\r
+                speed was forced to 100 half duplex.\r
+        Cause  : The driver did not indicate a link down state when necessary.\r
+                 The LineSpeed variable was not being set properly in the NICE\r
+                 interface for teaming.\r
+        Change : The driver indicates the proper link state in the NICE interface.\r
+        Impact : Broadcom Teaming driver will failover properly.\r
+\r
+\r
+v8.3.11 (October 18, 2005)\r
+==========================\r
+\r
+Note: Removal of support for 5714S, 5715S, 5755, 5787 controllers.\r
+\r
+\r
+\r
+v8.3.10 (October 14, 2005)\r
+==========================\r
+    Fixes:\r
+    ------\r
+\r
+    1. Problem : CQ13716 Netdump does not work on RH4EL U1 with bcm5700 \r
+                 driver. When intentionally crashing the system to test the \r
+                 netdump application, the bcm5700 driver would hang on the \r
+                 client and so the dump file would not be created on the netdump\r
+                 server. \r
+       Cause   : The interface to the driver poll function called by netdump\r
+                 when the system crashes changed slightly between RHEL3 and\r
+                 RHEL4. For RHEL4, the poll function in the driver called by\r
+                 netdump (poll_bcm5700) no longer has to call the bcm_poll() as\r
+                 it had previously. This is because the netdump controller calls\r
+                 the bcm_poll() function from outside the driver. Calling \r
+                 bcm_poll() from within the driver results in recursively \r
+                 re-entering netdump, hanging the application.\r
+       Change  : The driver was modified to detect the version of Redhat it's \r
+                 being built for and to use the appropriate algorithm in\r
+                 poll_bcm5700(). \r
+       Impact  : This change applies specifically to Redhat and Fedora OS's, and\r
+                 is independent of the device type.\r
+\r
+    2. Problem : CQ14274 Linux bcm5700 build errors on SUSE 10.2.6.13-15.\r
+       Cause   : The driver was using "#if"'s instead of "#ifdef"'s on variables\r
+                 that could remain undefined. This caused the compiler\r
+                 distributed with SUSE to issue compiler warnings when building\r
+                 the bcm5700 driver.\r
+       Change  : Two categories of changes made to the driver to fix this\r
+                 problem. First, if the variable causing the warning was used\r
+                 such that it either simply was "defined" or "not defined", then\r
+                 the "#if" was changed to "#ifdef" in the driver. However, if\r
+                 the variable usage was such that it could either be\r
+                 "not defined" or a number from 0-n, then a conditional was\r
+                 added into the header file to define the variable and set its\r
+                 value to 0 whenever it was not defined. This allowed the code\r
+                 in the driver to still use the "#if" and not have to change\r
+       Impact  : This change was applied to the driver in general and applies to\r
+                 all linux distributions, not just SUSE. These changes do not\r
+                 apply to a specific NIC, though they are used enable and\r
+                 disable specific features in the driver, such as, software\r
+                 workarounds for 570x, enabling Jumbo Frames, TBI support and\r
+                 PCI-X software workarounds.\r
+\r
+\r
+v8.3.9 (September 30, 2005)\r
+===========================\r
+    Fixes:\r
+    ------\r
+       Problem :The PHY registers can become corrupted on all 5714S,\r
+                5715S, and 5780S devices.\r
+        Cause  :The periodic link check code does not acquire the phy\r
+                lock before performing its task.\r
+        Change :Add phy lock acquisition and release code around\r
+                the link check function call.\r
+        Impact : 5714/5715/5780 fiber.\r
+\r
+\r
+v8.3.8 (September 29, 2005)\r
+===========================\r
+    Fixes:\r
+    ------\r
+       Problem :CQ14155 5714 fiber occasionally does not get link.\r
+        Cause  :This problem occurs when the duplex and line_speed\r
+                parameters are used with the 5714 fiber controller.\r
+                The driver allowed autonegotiation with only half\r
+                duplex advertised. Some switches do not support 1G fiber at half\r
+                duplex.\r
+        Change :If the controller is fiber, autonegotiation has full and half \r
+                duplex advertised regardless of parameter settings.\r
+        Impact : 5714/5715/5780 fiber.\r
+\r
+    Note: Removed support for 5903F that was introducd in v8.3.2. \r
+\r
+v8.3.7 (September 27, 2005)\r
+===========================\r
+    Fixes:\r
+    ------\r
+    1. Problem : The 5780 fiber ports on an IBM Maui PPC Blade server would stop\r
+                 receiving packets during a simple ping test.\r
+       Cause   : The RX DMA Engine (RDE) was not being re-enabled after the RX\r
+                 MAC was reset. This happens only after driver v8.3.2.\r
+       Change  : The sequence of reseting the Rx MAC was changed so that the RDE\r
+                 is enabled after the Rx MAC is reset.\r
+       Impact  : This change was made to specifically correct a problem seen on\r
+                 5780 and 5714 fiber devices. However, it should be noted that\r
+                 the implementation applies the change to all fiber devices.\r
+    \r
+    2. Problem : CQ 13980 BCM5780S can't pass link test with bcm5700 v8.3.2. \r
+       Cause   : The link test would fail when running "ethtool -t ethx" on \r
+                 fiber links that were in forced fallback mode. The test failed \r
+                 because the PHY_FIBER_FALLBACK flag in the PhyFlags variable\r
+                 was not being reinitialized when the PHY was reset. This caused\r
+                 the driver to think it was already in forced fallback mode when\r
+                 it wasn't. Running ethtool -t would reset the PHY and the\r
+                 driver would autoneg the link. When autoneg would fail, the\r
+                 driver wouldn't force the link because the force fallback flag \r
+                 (PHY_FIBER_FALLBACK) was already set from the initial PHY reset\r
+                 and hence the driver though it had already fallen back. \r
+       Change  : Changing the driver to clear the PHY_FIBER_FALLBACK flag in\r
+                 the PhyFlags variable whenever 1) auto-neg is initiated or\r
+                 2) whenever the PHY is reset fixed this problem.\r
+       Impact  : This problem only occurred on 5780, 5714 and 5715 devices with\r
+                 fiber phys attached to a switch that forces the link to gigabit\r
+                 speed (e.g a switch that doesn't auto negotiate the link).\r
+\r
+\r
+v8.3.6 (September 22, 2005)\r
+===========================\r
+    Fixes:\r
+    ------\r
+    1. Problem :CQ14069 5714s causes NMI when bringing interface down \r
+                with ASFIPMI enabled.\r
+        Cause  :5714 Switching to VAUX power on certain systems caused\r
+                NMI to occur.\r
+        Change :The 5714/5715 will not switch to VAUX power.\r
+        Impact :5714/5715 controllers.\r
\r
+    2. Problem :CQ14119 Using 5714 fiber a linking loop occurs when restrictive\r
+                autoneg is used.\r
+        Cause  :The driver continually configures the fiber link causing \r
+                continual phy interrupts. Only when user forces link.\r
+        Change :The driver reconfigures the phy when requested configuration\r
+                differs from current configuration.\r
+        Impact :5714/5715 fiber.\r
\r
+\r
+v8.3.5 (September 19, 2005)\r
+==========================\r
+    Fixes:\r
+    ------\r
+    1. Problem :CQ14063 parameter nic_tx_bd not getting set.\r
+        Cause  :5705 and later controllers do not support this\r
+                feature.\r
+        Change :README.TXT was updated to include the description\r
+                "and later"\r
+        Impact :None.\r
+\r
+    2. Problem :CQ14054 Two adapter names for each lom in Linux.\r
+        Cause  :The driver displayed a different integrated phy\r
+                number than the controller type.\r
+        Change :Changed the code to ensure the correct phy number\r
+                is displayed.\r
+        Impact :5780 SERDES only.\r
+\r
+    3. Problem :CQ13971 5714S stops passing traffic after a few seconds.\r
+        Cause  :The Rx Mac Mode reset was causing this to occur.\r
+        Change :No longer reset RxMode for 5714 SERDES.\r
+        Impact :5714/5715 SERDES.\r
+  \r
+\r
+v8.3.4 (September 15, 2005)\r
+==========================\r
+\r
+\r
+    Enhancements:\r
+    ============\r
+    1. Added basic support for 5755 and 5787 to driver.\r
+       - Added device, asic and phy ids for 5755/5787 devices.\r
+       - Modified the id macros to include these new devices.\r
+       - Added code to recognize the new phy id.\r
+       - Changed the PCI-E detection algorithm to use the kernel api.\r
+    2. Enabled hardware fix for CQ12384 and CQ12156 on 5755 and 5787.\r
+       - The 5751/5752/5753 devices may assert #INTA before writting\r
+         the corresponding status block to host memory.\r
+       - A software workaround for this problem was first implemented in\r
+         v8.1.10 of the driver (change #1 in release.txt).\r
+       - A hardware workaround to this problem has also been implemented\r
+         in 5755 and 5787 devices.\r
+       - This change enables the hardware workaround to this problem by\r
+         setting bit-29 in register 0x4c00 on 5755 and 5787 devices.\r
+    3. Enabled full hardware checksum offloading on 5755 and 5787.\r
+       - Use NETIF_F_HW_CSUM instead of NETIF_F_IP_CSUM on 5755/5787 \r
+         devices.\r
+    4. Added TSO support for 5755 and 5787 to the driver.\r
+       - The definition of the L3/L4 header length field in the send\r
+         buffer descriptor has been changed on 5755/5787 devices.\r
+       - The driver was modified to use a new algorithm to calculate\r
+         the L3/L4 header length for 5755/5787 devices.\r
+    5. Added fix for ECD13216 for the SERDES cross link problem.\r
+\r
+\r
+\r
+v8.3.3 (September 7, 2005)\r
+==========================\r
+    Fixes:\r
+    ------\r
+    1. Problem : CQ13626 Wrong message is displayed on the console when jumbo\r
+                 frames are enabled.\r
+       Cause   : Redo of fix #2 in 8.3.1. \r
+       Change  : Reordered some of the printk's in the driver so that the \r
+                 messages will be displayed correctly for all options.\r
+       Impact  : This bug is cosmetic, though it will cause some confusion \r
+                 regarding whether TSO or jumbo frames has been enabled on \r
+                 adapters other than the 5714 family.\r
+\r
+    2. Problem : 5714, 5715, and 5780 devices do not work with ST flash\r
+                 parts.\r
+       Cause   : The NVRAM discovery code was using the legacy\r
+                 discovery method instead of the 5750 method.\r
+       Change  : Change code to use the 5750 NVRAM discovery method.\r
+       Impact  : ST NVRAM parts operate correctly.\r
+\r
+    3. Problem : CQ13846 Call Trace When Jumbo Frames Are Enabled.\r
+       Cause   : When jumbo frames are enabled the driver will use vmalloc\r
+                 and vfree to setup the jumbo packet descriptors.  \r
+                 vfree/vmalloc can only be used in user context (open/close/ioctle)\r
+                 and enterrupts must be enabled. The driver was using vfree with \r
+                 interrupts disabled causing the call trace.\r
+       Change  : The vmalloc/vfree was replaced with kmalloc/kfree.\r
+       Impact : None.\r
+\r
+    4. Problem : CQ13660 Ethtool Offline Test, intermittently Fails Loopback Test.      \r
+        Cause  : The driver did not reset the RX mode in the mac causing the \r
+                 phy to drop the first few packets. This only occured in\r
+                 the 5780/5714/5715 devices. Other serdes devices have the rx\r
+                 mode reset in the code.\r
+        Change : Added  rx mode reset to ensure the phy is in sync with the mac.\r
+        Impact : Only 5780/5714/5715.\r
+\r
+\r
+\r
+v8.3.2 (August 26, 2005)\r
+=======================\r
+    Fixes:\r
+    ------\r
+    1. Problem : CQ13025 Unable to force speed on legacy serdes (5704,03,etc).\r
+        Cause  : Failed in ethtool due to code that did not include 5704/3\r
+                 fiber properly.\r
+        Change : Changed code to allow fiber to be forced to 1000Mbs.\r
+        Impact : All Serdes adapters.\r
+\r
+    2. Problem : CQ13533 Cannot compile on PPC w/SuSe 8.\r
+        Cause  : Missing #include <linux\vmalloc>. This problem\r
+                 was originally reported in driver v8.2.14 as \r
+                 vmalloc() was introduced. The vmalloc was removed at that \r
+                 time.  \r
+        Change : Added missing include.\r
+        Impact : none.\r
+\r
+  Enhancements :\r
+  =============\r
+     Added support for 5903M and 5903F adapters.\r
+\r
+\r
+\r
+v8.3.1 (August 23, 2005)\r
+=======================\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ13369 Kernel panic occurs under stress with large 802.3ad\r
+                 teams.\r
+       Cause   : The kernel panic was caused by the ICH6 rev. C2 misdirecting\r
+                 pci config reads to the wrong device. The driver was using pci\r
+                 config cycle to read the low-priority mailbox of the 5703\r
+                 attached to the 5714's expansion bus. The driver was using\r
+                 indirect pci config cycles to read the MB to apply a special\r
+                 cycle  workaround needed for 5703-A1/2 and 5704-A0 when they\r
+                 are  connected to the PCI-X bus of an ICH1-ICH4.\r
+       Change  : This workaround is really only needed when the 5703/4 is\r
+                 directly attached to older ICH chips. This problem was resolved\r
+                 by modifying the driver to only apply the workaround when a\r
+                 5703-A1/2 or 5704-A0 is directly attached to an ICH1-ICH4\r
+                 chipset. This problem can also be worked around by setting the\r
+                 switch pci=nommconfig when starting the kernel. This switch is\r
+                 available only with newer kernels (2.6) and on systems with\r
+                 PCI-E (i.e. ICH6-7). Starting the kernel with the above switch\r
+                 disables memory mapped config cycles being used by the kernel,\r
+                 so the kernel instead uses the standard 0xcf8/0xcfc i/o ports\r
+                 to generate pci config cycles.\r
+       Impact  : This problem and the fix only applies to 5703-A1/A2 or 5704-A0\r
+                 connect to a PCI-X bus in systems with an ICH6 or ICH7 chipset.\r
+\r
+    2. Problem : CQ13626 Wrong message is displayed on the console when jumbo\r
+                 frames are enabled.\r
+       Cause   : The 5714 family of adapters cannot support both jumbo frames\r
+                 and TSO at the same time. When the driver detects that a user\r
+                 is trying to enable both features on a 5714, it will disable\r
+                 TSO, enable jumbo frames, and log a message to the syslog.\r
+                 There was a bug in the driver logic that caused it to log a\r
+                 message saying jumbo frames and TSO cannot simultaneously\r
+                 be supported even if the adapter could support both features\r
+                 being enabled at the same time.\r
+       Change  : The driver logic was changed to only log this message when the\r
+                 adapter is a member of the 5714 family of controllers.\r
+       Impact  : This bug is cosmetic, though it will cause some confusion \r
+                 regarding whether TSO or jumbo frames has been enabled on \r
+                 adapters other than the 5714 family.\r
+\r
+    3. Problem : CQ13658 stats_coalesce_ticks parameter does not default to \r
+                 the correct number.\r
+       Cause   : If the parameter value is set by the user and it is below \r
+                 the minimum supported value, then the parameter value used\r
+                 will be the minimum supported value for this parameter.\r
+                 When the value exceeds the maximum supported \r
+                 value, then the value will become the default value.\r
+       Change  : The driver will not validate this paremeter if the \r
+                 adaptive_coalesce parameter is set.\r
+       Impact  : The driver will display a message when stats_coalesce_ticks\r
+                 and adaptive_coalesce parameters are set.\r
+\r
+    4. Problem : CQ13025 Unable to force speed on legacy serdes (5704,03,etc).\r
+       Cause   : A bug in the driver prevented the user from forcing speed on\r
+                 serdes adapters. The speed parameter was not being checked\r
+                 properly.\r
+       Change  : The driver checks the speed input correctly.\r
+       Impact  : All legacy serdes adapters can now be forced to 1000.\r
+\r
+    5. Problem : CQ13612 Rx_Jumbo_Packets counter does not increment on 5780.\r
+       Cause   : The adapters 5705 and later do not have the jumbo packet \r
+                 counters.\r
+       Change  : The driver does not display the jumbo packets counter.\r
+       Impact  : 5705 and new adapters will not display the counter.\r
+\r
+    6. Problem : CQ13263 5780 fiber intermittently fails to link properly with \r
+                 3COM 4900 SX switch.\r
+       Cause   : Occasionally the 4900 switch and the 5780 fiber will not\r
+                 autonegotiate.\r
+       Change  : A delay was put in the driver to allow better autonegotiation.\r
+       Impact  : 5780 Serdes only.\r
\r
+    7. Problem : CQ13759 bcm5700 corrupts memory when doing ethtool -t eth0.\r
+       Cause   : The driver was using a wrong value in the driver self test\r
+                 allowing  data writes to user space.\r
+       Change  : The test value was changed to the correct value. This bug\r
+                 was found and fixed by York Chung.\r
+       Impact  : All adapters when running this test.\r
+       \r
+\r
+    Enhancements:\r
+    ============\r
+    1. Added support for 5714/5715 family of adapters.\r
+    2. Added the 5714/5714 performance fix for CQ13140.\r
+    3. Added new IPMI handshake.\r
+\r
+\r
+v8.2.18 (August 1, 2005)\r
+========================\r
+    Fixes:\r
+    ======\r
+       Problem : CQ13578 Linux i386 2.4:insmod bcm5700 8.2.XX with tg3\r
+                 already loaded causes panic.\r
+       Cause   : The netdevice_notifier was being registered to the bcm\r
+                 driver code and the code did not unregister the notifier\r
+                 callback routine when the bcm device was not present.\r
+                 This bug was introduced in driver v8.2.6 cq10262.\r
+       Change  : Registering of notifier is done when a device is found.\r
+       Impact  : 2.4 kernel\r
+\r
+\r
+v8.2.17 (July 29, 2005)\r
+======================\r
+    Fixes:\r
+    ======\r
+       Problem : CQ13550 Linux 8.2.12+ driver fails BASP Automation.\r
+       Cause   : A bug was introduced in v8.2.12 that prevented the\r
+                 5703 from getting proper link after closing and opening\r
+                 the driver interface.\r
+       Change  : The code was modified to ensure 5703 is configured\r
+                 properly after each interface open.\r
+       Impact  : 5703 copper nics using using v8.2.12 upto v8.2.16.\r
+\r
+\r
+v8.2.16 (July 27, 2005)\r
+======================\r
+    Enhancement:\r
+    ============\r
+    Added the skb_cloned_header check for tco support in 2.6.12 kernels.\r
+\r
+\r
+v8.2.15 (July 26, 2005)\r
+=======================\r
+    Fixes:\r
+    ======\r
+\r
+    1. Problem : CQ13533 Cannot compile on PPC w/SuSe 8.\r
+       Cause   : vmalloc is not in the SuSe 8 library.\r
+                 vamalloc was introduced into the driver in v8.2.13.\r
+       Change  : Replaced vmalloc with kmalloc.\r
+       Impact  : Problem resolved on SuSe 8 PPC.\r
+\r
+    2. Problem : CQ13525 Missing items in supplemental tar file.\r
+       Cause   : latest patch file was not included, nor was disk image.\r
+       Change  : included patch files and disk image.\r
+       Impact  : None.\r
+\r
+    3. Problem : CQ13519 Jumbo enabled causes call trace.\r
+       Cause   : vmalloc was being used outsie of init or close functions.\r
+       Change  : Replaced vmalloc with kmalloc.\r
+       Impact  : None.\r
+\r
+\r
+v8.2.14 (July 21, 2005)\r
+=======================\r
+\r
+This version does not have support for 5714/5715 controllers.\r
+\r
+\r
+v8.2.13 (July 21, 2005)\r
+=======================\r
+    1. Problem : CQ 13381 5715s: Driver incorrectly reports the PCI-X bus\r
+                 speed is 33 MHz instead of 133 MHz.\r
+       Cause   : The driver was incorrectly using just the Bond ID (and not\r
+                 the ASIC IC) to determine if chip was a 5704CIOBE. On a\r
+                 5714Cu, the Bond ID by luck matched the CIOBE which led the\r
+                 driver to conclude that the PCI-X bus speed was 133 MHz. On\r
+                 a 5714S, the Bond ID did NOT match the CIOBE, and so the\r
+                 driver used the bits 0-4 (=0) in the Clock Control register\r
+                 (0x70) to incorrectly conclude that the PCI-X bus speed was\r
+                 33 MHz.\r
+       Change  : The driver was hardcoded to display the PCI-X bus speed as\r
+                 133 MHz when 1) both the ASIC Id AND the Bond Id both\r
+                 identify the chip as a 5704CIOBE, or 2) the ASIC ID is a\r
+                 5714, 5715 or 5780.\r
+       Impact  : This change is only cosmetic and will not have any impact\r
+                 on system performance or functionality. The change was only to\r
+                 correctly display the bus speed stored in /proc/net/nicinfo.\r
+                 The code that was changed is used by all PCI-X devices,\r
+                 in particular CIOBE, 5714, 5715 and 57890.\r
+\r
+    2. Problem : CQ 13431 B57LDIAG nictest fails on 5780/5714/5715.\r
+        Cause  : The driver was not restoring the MSI state properly\r
+                 after resets. This bug was introduced in driver v8.2.12.\r
+        Change : Save the MSI state before reset and retore it after\r
+                 reset.\r
+        Impact : All msi supported drivers.\r
+\r
+   Enhancement : 5703 DMA read water mark was to 512 in pcix mode as\r
+                 the proper value for the workaround below after\r
+                 tests determined this setting to be the optimal value.\r
+\r
+\r
+v8.2.12 (July 20, 2005)\r
+=======================\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ13208 Kernel panics when using ethtool on an\r
+                 inactive interface.\r
+       Cause   : The ethtool command executes LM_SetupPhy(), which\r
+                 dereferences the device's status block.  When an\r
+                 interface is not active though, the status block\r
+                 memory will have been freed / will be NULL.  The\r
+                 crash is due to a NULL pointer dereference.\r
+       Change  : Avoid calling LM_SetupPhy() if the interface is not\r
+                 active.\r
+       Impact  : None.\r
+\r
+    2. Problem : A 5703 or 5704 can hang when connected to a PCI-X bus if the\r
+                 DMA Read Watermark register is not programmed correctly. This\r
+                 problem typically manifests itself as a watchdog timeout and\r
+                 possible loss of a TCP session. The driver monitors watchdog\r
+                 timeout events and will automatically recovers from these\r
+                 events by reseting the chip.\r
+       Cause   : This problem was documented in the hardware errata for the\r
+                 5703 chips, though it was not implemented in prior driver\r
+                 releases.\r
+       Change  : When a 5703 or 5704 is connected to a PCI-X bus, the DMA Read\r
+                 Watermark is programmed as follows:\r
+\r
+                 Max Read Byte Count = PCI Config. Reg. 0x42, bits 3-2\r
+                 DMA Read Watermark  = PCI Config. Reg. 0x6C, bits 18-16\r
+\r
+                 Max Read Byte Count  Allowable DMA Read Watermark Values\r
+                 -------------------  -----------------------------------\r
+                 00 =  512 bytes      0-4\r
+                 01 = 1024 bytes      0-5\r
+                 10 = 2048 bytes      0-7\r
+\r
+       Impact  : Systems using a 5703 or 5704 chip in a PCI-X bus may\r
+                 experience NETDEV watchdog timouts without this change.\r
+                 Upgrading the driver to this version should fix this problem.\r
+                 No other system components need to be changed.\r
+\r
+    3. Problem : ethtool -t causing oops when interface is down.\r
+        Cause  : Driver code would attempt to free  memory based\r
+                 on the index of the receive packet queue after the\r
+                 queue memory had already been freed.\r
+        Change : The re-initializeation of the receive packet queue at driver\r
+                 close to clear the index.\r
+        Impact : none.\r
+\r
+    4. Problem : CQ13263 5780 fiber occasionally looses link on 3com 4900sx.\r
+        Cause  : Phy link would go down during reset and the reset phy\r
+                 function was not waiting long enough.\r
+        Change : Added longer delay in Reset Phy driver code and the driver\r
+                 does not toggle the gigabit setting in Mac.\r
+        Impact : 5780 fiber only.\r
+\r
+\r
+    Enhancement: Added loopback mode support for testing.\r
+\r
+\r
+v8.2.11 (July 01, 2005)\r
+=======================\r
+\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ13321 Driver does not build.\r
+       Cause   : Undefined constant.\r
+       Change  : Recode so that the constant is no longer needed.\r
+       Impact  : None.\r
+\r
+\r
+v8.2.10 (July 01, 2005)\r
+=======================\r
+\r
+    1. Problem : CQ12559 Call trace occurs when enslaving interface.\r
+       Cause   : The bonding driver can call the bcm5700 in a context\r
+                 where preemption is disabled. Some kernels will\r
+                 issue a call trace when an interface function involves\r
+                 a sleep thread when there should be none.\r
+       Change  : The driver was changed to detect if a call was being\r
+                 made to it in a non sleep context and it uses the\r
+                 appropriate copy function.\r
+                 ( the prior implementation of this fix was incorrect )\r
+       Impact  : All adapters with this version driver and kernel 2.6.x\r
+                 and above.\r
+                 There is still a call trace when the bonding driver is\r
+                 brought down, but it occurs with the tg3 driver as well.\r
+\r
+    2. Problem : CQ13280 5780 displays incorrect speed and duplex\r
+                 advertisements in the procfile.\r
+       Cause   : The 5780 uses new phy code, which did not include\r
+                 filling in the "advertising" field of our device\r
+                 structure.  This field is used to construct strings\r
+                 for the procfile.\r
+       Change  : Add code to properly construct speed advertisement\r
+                 strings for the 5780.\r
+       Impact  : None.\r
+\r
+\r
+v8.2.9 (June 28, 2005)\r
+=======================\r
+\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ13274 5780 cannot get link on copper PHYs.\r
+       Cause   : The 5780 uses the same PHY, but a different PHY mode\r
+                 when configured as a serdes device.  The different\r
+                 PHY mode requires the use of a different PHY register\r
+                 set.  The driver was coded to always use the alternate\r
+                 PHY mode when setting the flow control advertisement.\r
+       Change  : Change the code to use the alternate PHY mode only\r
+                 when on a 5714 family serdes device.\r
+       Impact  : None.\r
+\r
+\r
+v8.2.8 (June 24, 2005)\r
+=======================\r
+\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ13202 Shasta C1 fails ethtool -t test and stops\r
+                 responding.\r
+       Cause   : The new HaltCpu code was improperly attempting to\r
+                 halt a non-existant Tx Cpu.  This is because the\r
+                 T3_HAS_TWO_CPUS bit was somehow set.\r
+       Change  : Explicitly turn off T3_HAS_TWO_CPUS before detecting\r
+                 devices that actually have two CPUS.\r
+       Impact  : All non-two-cpu devices.\r
+\r
+    2. Problem : CQ13205 5714 fiber boards repeatedly display message\r
+         of link down.\r
+    Cause  : RH 4 seems to continually open and close the interface\r
+         of one of the ports of the 5714. If the cable of that\r
+         port is not linked, the message will be displayed.\r
+    Change : The driver will report link status when it changes.\r
+    Impact : All 5714 family fiber.\r
+\r
+\r
+v8.2.7 (June 21, 2005)\r
+=======================\r
+\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ13011 5714s/5715s does not link when switch is forced\r
+                 to a 1000 and not set to Auto Negotiation.\r
+       Cause   : The speed forcing code for 5714s was not in place.\r
+       Change  : Code was added to the driver to allow forcing the\r
+                 speed to 1000Mbs and the driver will fall back to\r
+         1000Mbs when connection is sensed but autonegotiation\r
+         is disabled on the switch.\r
+       Impact  : 5714s/5715s/5780s\r
+\r
+    2. Problem : CQ13051 5714s/5715s does have flow control function.\r
+       Cause   : The code for flow control  was not in place.\r
+       Change  : Code was added to the driver to allow flow control.\r
+       Impact  : 5714s/5715s/5780s\r
+\r
+    3. Problem : CQ13072 Do not switch to VAUX power on 5714/5715.\r
+       Cause   : Power consumption is excessive.\r
+       Change  : Code was added to the driver to ensure VAUX power is\r
+         not consumed.\r
+       Impact  : 5714s/5715s\r
+\r
+    4. Problem : CQ12559 Call trace occurs when enslaving interface.\r
+       Cause   : The bonding driver can call the bcm5700 in a context\r
+         where preemption is disabled. Some kernels will\r
+         issue a call trace when an interface function involves\r
+         a sleep thread when there should be none.\r
+       Change  : The driver was changed to detect if a call was being\r
+         made to it in a non sleep context and it uses the\r
+         appropriate copy function.\r
+       Impact  : All adapters with this version driver and kernel 2.6.x\r
+         and above.\r
+\r
+\r
+\r
+v8.2.6 (June 13, 2005)\r
+=======================\r
+\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ10262 iThe /proc/net/nicinfo filename does\r
+                 not match the device name in the output of\r
+                 ifconfig.\r
+       Cause   : No mechanism existed to notify the driver when the\r
+                 administrator changes the name of the device.\r
+       Change  : Added a callback function to respond to name change\r
+                 events.  When a name change event occurs, the proc\r
+                 filesystem entry is torn down and rebuilt.\r
+       Impact  : None.\r
+\r
+    2. Problem : CQ12637 When running 'ethtool -t <interface>', the\r
+                 system becomes unresponsive for a several seconds.\r
+       Cause   : On uniprocessor systems, the kernel is busy performing\r
+                 the ethtool test.  This processing comes at the\r
+                 expense of servicing user events.\r
+       Change  : Added a message before the test begins notifying the\r
+                 administrator that the test will take some time.\r
+                 Littered the code with sleep() calls so that the\r
+                 kernel can service user events in between tests.\r
+       Impact  : None.\r
+\r
+    3. Problem : CQ12972 Kernel panics when ethtool test is run after\r
+                 being up'd and down'd.\r
+       Cause   : When attempting to restore the previous power state\r
+                 (D3), the code dereferences a NULL status block\r
+                 pointer.\r
+       Change  : Detect if the status block pointer is NULL.  If so,\r
+                 forgo any packet ring cleanups.\r
+       Impact  : None.\r
+\r
+    4. Problem : CQ12969 During 'ethtool -t <interface>' tests, the\r
+                 kernel issues "transmit timed out" messages.\r
+       Cause   : In normal operation, MM_IndicateStatus turns on and\r
+                 off the kernel transmit queues.  When the transmit\r
+                 queues are on, a packet must be transmitted within a\r
+                 certain amount of time, or else these warnings will\r
+                 appear.  During ethtool tests, the device is suspended\r
+                 and all kernel transmit queues are turned off.  It is\r
+                 possible however, for MM_IndicateStatus to be called\r
+                 after suspending the device.  In this scenario, on\r
+                 link up, MM_IndicateStatus would reenable the transmit\r
+                 queue during the ethtool test.  The end result is the\r
+                 above messages.\r
+       Change  : Modify the MM_IndicateStatus() function to only toggle\r
+                 the kernel queues if we are not suspended.\r
+       Impact  : None.\r
+\r
+    5. Problem : CQ12215 Ethtool failures during ethtool test.\r
+       Cause   : There is a race condition between the driver and the\r
+                 firmware with respect to nvram lock acquisition.\r
+                 There can be cases where a terminated firmware\r
+                 acquires the NVRAM lock post-mortem.\r
+       Change  : Modify LM_HaltCpu() to free the nvram lock on behalf\r
+                 of the firmware whenever we can.  Flag the error\r
+                 otherwise.\r
+       Impact  : None.\r
+\r
+    6. Problem : CQ12884 Linux DMA problem with ldiag.\r
+       Cause   : Some new distributions do not allow user space apps\r
+         access to memory allocated by a kernel process.\r
+       Change  : The driver will map/unmap memory that was allocated\r
+                 in user space.\r
+       Impact  : Ldiag application only.\r
+\r
+    7. Problem : CQ12427 Enabling TSO causes random link down/up.\r
+    Cause  : Oversized message stress tests may impact TSO in\r
+         some machines causing NETDEV Timeouts.\r
+    Change : Added code to disable TSO if Timeouts detected\r
+         with TSO enabled.\r
+    Impact : 575x\r
+\r
+v8.2.5 (May 20, 2005)\r
+=======================\r
+\r
+    Fixes :\r
+    -------\r
+    1. Problem : CQ12806 Random kernel panics with 5714A1\r
+                 the kernel.\r
+                 CQ12827 Load/Unload with MSI enabled causes\r
+                 "nobody cared! (screaming interrupt)"\r
+\r
+       Cause   : MSI enable bit in MSI capability block\r
+                 is cleared during GRC reset.\r
+\r
+       Change  : Added software work-around to restore\r
+                 the state of this bit after a GRC reset\r
+\r
+       Impact  : None.\r
+\r
+\r
+v8.2.4 (May 16, 2005)\r
+=======================\r
+\r
+    Enhancements :\r
+    --------------\r
+    1. Change  : Added support for new HP NC32Xi products.\r
+       Impact  : None.\r
+\r
+\r
+v8.2.3 (May 13, 2005)\r
+=======================\r
+\r
+   Fix:\r
+   ----\r
+    1. Problem : CQ12133 Ethtool reports the wrong link speed.\r
+       Cause   : When the driver forces the link, the link will\r
+                 many times be acquired before finishing the\r
+                 SetupCopperPhy() call.  This, in turn, will\r
+                 cause MM_IndicateStatus() _not_ to be called.\r
+                 MM_IndicateStatus() updates the line_speed\r
+                 variable which is used to report the link\r
+                 speed when using the ethtool method.  In effect,\r
+                 the ethtool query reports a stale link speed.\r
+        Change : Code the driver to obtain the link speed from\r
+                 the pDevice->LinkSpeed field instead.  Removed\r
+                 the line_speed member from the device structure.\r
+        Impact : None.\r
+\r
+    2. Problem : CQ12831 Bootcode version string missing device\r
+                 name for 5714 devices.\r
+        Cause  : The GetBootCodeVersion function tests the value\r
+                 of an instruction it read from NVRAM to determine\r
+                 whether it should use the new version extraction\r
+                 routines or the old extraction routines.  The test\r
+                 was overly restrictive, which would force the\r
+                 driver to use the old method.\r
+        Change : Change the test to only inspect the opcode portion\r
+                 of the instruction.  The rest of the bits are\r
+                 offset bits which can and do change between\r
+                 firmware versions.\r
+        Impact : None.\r
+\r
+\r
+v8.2.2 (May 10, 2005)\r
+=======================\r
+\r
+   Fix:\r
+   ----\r
+    1.Problem : CQ12784 hogging interrupts message seen with 5714.\r
+       Cause  : The device was not initializing properly due to the\r
+                the driver putting the device into slow clock mode.\r
+       Change : The driver keeps the device in full power mode.\r
+       Impact : This impacts the 5714/15 and 5780.\r
+\r
+    2.Problem : CQ12785 NMI seen using 5714.\r
+    Cause : Same as above.\r
+\r
+    3.Problem : CQ12786 5715 cannot get link.\r
+        Cause : Sambe as above.\r
+\r
+    4.Problem : CQ12824 5714 removing driver from bonding team and\r
+                basp team results in kernel panic.\r
+        Cause : Same as above.\r
+\r
+ Enhancement\r
+ -----------\r
+    Added msi support for 5780.\r
+\r
+\r
+v8.2.1 (April 29, 2005)\r
+=======================\r
+\r
+   Fix:\r
+   ----\r
+    1.Problem : CQ12781 5714C stops passing traffic after ifup/down.\r
+       Cause  : The driver puts the device into slow clock mode when\r
+                shutting down the interface to conserve power and this\r
+                occasionally creates an inability for the device to\r
+                transmit when brought back up. The real problem may\r
+                lay in the driver initialization code of the device\r
+                clock speed on power up. This driver release is to allow\r
+                internal testing to contine, until debug is completed.\r
+      Change  : The driver does not slow the clock when shutting down\r
+                the interface.\r
+      Impact  : 5714/5715 should function as expected.\r
+\r
+    2.Problem : CQ12469 Add 5780 Device IDs.\r
+       Cause  : The 5780 copper and fiber have PCI Device IDs of 0x166a\r
+                and 0x166b respectively.\r
+       Change : Added the ids.\r
+       Impact : 5780.\r
+\r
+\r
+v8.2.0 (April 22, 2005)\r
+========================\r
+\r
+  Enhancements\r
+  ------------\r
+   1. Change : Added support for 5714\r
+\r
+   2. Change : CQ12081 Added MSI support for 5714.\r
+      Impact : Only 5714.\r
+\r
+   3. Change : Added support in Makefile for PPC and SuSE.\r
+      Impact : Only in PPC machines.\r
+\r
+  Fix:\r
+  ----\r
+     Problem : CQ12677 "$" character appended to device name.\r
+       Cause : Typo in script file.\r
+      Change : Deleted extra character.\r
+      Impact : Only visual.\r
+\r
+\r
+v8.1.55 (April 8, 2005)\r
+========================\r
+\r
+  Enhancement: Using the updated GPHY BIAS for 5752.\r
+  ------------\r
+      Change : The code was changed to include a setting to the GPHY\r
+               to ensure a high quality network link over long cable\r
+               lengths. No problems have been reported with the\r
+               previous GPHY BIAS setting.\r
+\r
+      Impact : 5752 has no noticable impact.\r
+\r
+\r
+v8.1.54 (April 8, 2005)\r
+=======================\r
+\r
+   Fix:\r
+   ----\r
+     Problem : CQ12639 Latest driver causes panic on DELL 6650.\r
+       Cause : A bug introduced in driver v8.1.50 created a timing\r
+               window on the 5700 where a releasing spinlock\r
+               was out of sync with the acquiring spinlock.\r
+               This problem was specific to the 5700 and only\r
+               seen on the 6650 integrated 5700 device.\r
+      Change : The driver code was changed to ensure the 5700\r
+               spinlock is not released before is is acquired.\r
+      Impact : 5700 only.\r
+\r
+\r
+\r
+v8.1.53 (April 6, 2005)\r
+=======================\r
+\r
+   Fix:\r
+   ----\r
+   1.Problem : CQ12628 Driver does not compile on Beta SuSE 9.3\r
+      Cause  : A coding bug in the driver code accessed only\r
+               by kernel versions greater than 2.6.10. This bug\r
+               was introduced in driver v8.1.10.\r
+      Change : This bug was a typo that was corrected.\r
+      Impact : None.\r
+\r
+\r
+   2.Problem : CQ12450 bcm5700 does not compile on PPC64 RHEL3 U3.\r
+      Cause  : Additional Makefile switches were needed to compile on\r
+               the RHEL3 U3 PPC64.\r
+      Change : The Makefile was updated to include a makefile\r
+               switch and an LD line to allow PPC64 compilation on\r
+               RHEL3 U3 PPC64.\r
+      Impact : May no longer  build on older PPC64 kernels.\r
+\r
+\r
+v8.1.52 (April 1, 2005)\r
+============================\r
+\r
+   Fix:\r
+   ----\r
+     Problem1: CQ12549 Error 63 getting the ASF configuration table.\r
+      Cause  : The NVRAM was not being read properly.\r
+      Change : The NVRAM access code was changed to properly access\r
+               NVRAM.\r
+      Impact : None.\r
+\r
+     Problem2: CQ12467 System hanging after unloading driver.\r
+      Cause  : The driver accessed reserved registers.\r
+      Change : Removed the code that accessed the reserved registers.\r
+      Impact : None.\r
+\r
+\r
+v8.1.51 (March 29, 2005)\r
+============================\r
+\r
+   Fix:\r
+   ----\r
+     Problem : CQ12549 Error writing to ASF config table in NVRAM.\r
+      Cause  : The 5752 will not allow an NVRAM to write above 64k.\r
+      Change : The reported size of the NVRAM was changed to 64k.\r
+      Impact : None.\r
+\r
+   Removed support for that 5714 ASIC revision.\r
+\r
+v8.1.50 (March 16, 2005)\r
+============================\r
+\r
+   Fix:\r
+   ----\r
+      Problem : CQ11136 GPIOs need to be configured to outputs.\r
+       Cause  : 5752 GPIOs default to inputs.\r
+       Change : Added code to enable GPIO output.\r
+       Impact : None.\r
+\r
+\r
+   Added support for ASIC revisions 5752, 5714.\r
+\r
+\r
+v8.1.11 (March 11, 2005)\r
+============================\r
+\r
+   Fix:\r
+   ----\r
+      Problem : CQ12400 Removing driver causes a kernel panic\r
+       Cause  : The statistics timer was not being disabled at\r
+                shutdown.\r
+       Change : Disable statistics timer at shutdown.\r
+       Impact : None.\r
+\r
+\r
+v8.1.10 (March 10, 2005)\r
+============================\r
+\r
+   Fix:\r
+   ----\r
+      Problem : CQ12156 ATI transmit timeout-"NETDEV WATCHDOG".\r
+       Cause  : The ATI chipset did not call the driver ISR\r
+                after the ISR did not service an INTx interrupt.\r
+       Change : The driver will check a register to determine if\r
+                the INTx should be claimed if the status block has\r
+                not been updated on ISR entry.\r
+       Impact : This fix may improve system performance on some\r
+                systems as it reduces the amount of spurious or\r
+                unclaimed interrupts.\r
+\r
+  Enhancemnts\r
+  -----------\r
+\r
+   1. Problem : Users want command line parameters.\r
+\r
+      Change  : All the parameters are accessible on the command line.\r
+        The code uses MODULE_PARAM for new kernels.\r
+\r
+   2. Problem : MSI support needs to test for older non-msi supported\r
+        machines running kernels with MSI support enabled.\r
+      Change  : Added MSI validity test.\r
+\r
+   3. Problem : Jumbo frame support on some systems caused device\r
+        counters to increment CRC errors.\r
+      Change  : Added additional setting to PHY.\r
+      Impact  : None.\r
+\r
+   4. Problem : pci_find_device() will be deprecated.\r
+      Change  : Added pci_dev_present() and pci_get_device() where\r
+        pci_find_device() is.\r
+\r
+   5. Change  : Added mmiowb() in tx/rx paths.\r
+\r
+   6. Change  : Changed makefile for netdump service build to not\r
+        rely on #define RED_HAT_LINUX_KERNEL.\r
+\r
+   7. Change  : Added code to better scale the timer intervals\r
+        dependent on device.\r
+\r
+\r
+v8.1.9 (March 1, 2005)\r
+============================\r
+\r
+   Support for ASIC revisions 5752, 5714 and 5715 was taken out of\r
+   the driver.\r
+\r
+\r
+v8.1.8 (February 28, 2005)\r
+============================\r
+   Fixes:\r
+   ------\r
+\r
+   1. Problem : CQ11788 5721 not receiving probes in Intel team.\r
+       Cause  : Statistics do not get updated fast enough.\r
+       Change : Connect the stats_coalesce_ticks module parameter\r
+                to the actual statistics update frequency.\r
+       Impact : System behaves as expected.\r
+\r
+\r
+   2. Problem : CQ12273 "MODULE_PARM is deprecated" messages are\r
+                displayed when compiling on Red Hat 4.0.\r
+\r
+        Cause : Drivers using the deprecated macro MODULE_PARM will\r
+                cause compile warnings to be displayed in systems\r
+                using RedHat 4. The bcm5700 driver was still using\r
+                the MODULE_PARM as the parameter interface.\r
+\r
+       Change : The driver now uses ethtool for passing most parameters.\r
+\r
+       Impact : The driver operating in environments with kernel versions\r
+                of 2.6.5 and above requires the use of ethtool to set\r
+                parameters. When the driver is used with a kernel version\r
+                older than 2.6.5 it will accept all command line parameters.\r
+\r
+                The only parameters accepted from the command line in\r
+                kernel versions 2.6.5 and later are:\r
+\r
+                                            nic_tx_bd\r
+                                            delay_link\r
+                                            disable_d3hot\r
+                                            disable_msi\r
+\r
+   3. Problem : CQ12278 Make driver errors on Suse 9.\r
+\r
+        Cause : The MODULE_PARAM macro is defined differently in kernel\r
+                versions below 2.6.10 than they are in the 2.6.10\r
+                kernel verion. The driver did not account for the\r
+                different macro definitions and the driver code path\r
+                was flawed for 2.4.x kernels when declaring\r
+                MODULE_PARM.\r
+\r
+       Change : The driver parameters are declared in three ways and all\r
+                the original parameters are still used when the driver\r
+                is operating in systems with kernel versions below 2.6.5.\r
+\r
+       Impact : The driver operating in systems with kernel versions\r
+                of 2.6.5 and above requires the use of ethtool to set\r
+                parameters. The driver accepts all parameters from\r
+                the command line when running in systems with kernel\r
+                versions older than 2.6.5.\r
+\r
+                The only parameters accepted from the command line in\r
+                kernel versions 2.6.5 and later are:\r
+\r
+                                            nic_tx_bd\r
+                                            delay_link\r
+                                            disable_d3hot\r
+                                            disable_msi\r
+\r
+\r
+\r
+v8.1.7 (February 25, 2005)\r
+============================\r
+   Fixes:\r
+   ------\r
+\r
+   1. Problem : CQ12168 Running ethtool -d <interface> causes\r
+                system to hang or panic.\r
+       Cause  : Driver stores two copies of memory allocated for\r
+                register data.  One copy gets incremented as it\r
+                gets filled.  The other does not.  The driver was\r
+                using the incremented pointer to free the memory\r
+                instead of the non-incremented pointer.\r
+       Change : Pass the original pointer value to kfree().\r
+       Impact : System behaves as expected.\r
+\r
+   2. Problem : External loopback test not working with 5752 devices.\r
+       Cause  : 5752 ISR was dereferencing an invalid packet\r
+                descriptor pointer.\r
+       Change : Turn off interrupts when loopback tests are running.\r
+       Impact : System behaves as expected.\r
+\r
+   3. Problem : CQ11916 HTLE has intermittent problem passing traffic.\r
+       Cause  : The HTLE seems to have a problem with low clock speed.\r
+       Change : The driver will not slow the clock down when unloading\r
+                for HTLE.\r
+       Impact : None.\r
+\r
+   4. Problem : CQ12080 TSO should be disabled by the driver when\r
+                jumbo frames are used with the 5714.\r
+       Cause  : The driver did not disable TSO when running\r
+                jumbo frames on the 5714\r
+       Change : Added code to disable TSO when 5714 is running in\r
+                jumbo frame mode.\r
+       Impact : None.\r
+\r
+   5. Problem : CQ12209 5714 Fiber would not pass traffic with IPMI\r
+                enabled.\r
+       Cause  : The fiber would not get initialized due to the driver\r
+                using the wrong phy type.\r
+       Change : The driver now checks for the correct phy id when\r
+                IPMI is loaded.\r
+       Impact : None.\r
+\r
+   6. Problem : CQ12166 Running ethtool -t fails register and memory\r
+                tests on 5752.\r
+       Cause  : Test was performing tests for this device.\r
+       Change : Change code to use 5705 register and memory tests.\r
+       Impact : None.\r
+\r
+\r
+\r
+v8.1.6 (February 23, 2005)\r
+============================\r
+   Fixes:\r
+   ------\r
+\r
+   1. Problem : CQ12128 5701 locks up system when driver loads.\r
+       Cause  : The driver used the wrong NVRAM access type.\r
+       Change : The driver code was changed to use the correct\r
+                NVRAM type to access the NVRAM.\r
+       Impact : 5701 will not lock up the system.\r
+\r
+   2. Problem : CQ12212 Unwanted information is displayed.\r
+       Cause  : The driver displayed debug information.\r
+       Change : The debug information was removed from the driver.\r
+       Imapct : None.\r
+\r
+\r
+  Enhancements\r
+  ------------\r
+\r
+   1. Problem : CQ11650 Driver does not show ASF / IPMI version.\r
+      Change  : Added code to extract ASF / IPMI version info from\r
+                NVRAM.\r
+      Impact  : None.\r
+\r
+\r
+\r
+v8.1.5 (February 18, 2005)\r
+============================\r
+\r
+   Fixes:\r
+   -----\r
+    1. Problem : CQ12097 Unable to link with  5714S.\r
+        Cause  : The v8.1.4 driver did not fully support 5714S.\r
+       Change  : Added support for the 5714S.\r
+       Impact  : 5714S is functional w/v8.1.5.\r
+\r
+\r
+    2. Problem : CQ11807 Driver will not pass traffic with\r
+                 forced speed.\r
+        Cause  : The driver default setting of gigabit mode\r
+                 was interferring with the forced settings.\r
+       Change  : The gigabit mode setting is now cleared until used.\r
+       Impact  : None.\r
+\r
+\r
+   3. Problem  : CQ12104 VPD Read error on 5714 LOM.\r
+        Cause  : The race condition described CQ11951.\r
+       Change  : Change is described in v8.1.3. and actually\r
+                 fixed in v8.1.3.\r
+       Impact  : None.\r
+\r
+\r
+\r
+v8.1.4 (February 16, 2005)\r
+============================\r
+\r
+   Fixes:\r
+   -----\r
+    1. Problem : CQ11918 Customer reported problem with kernel dump.\r
+        Cause  : When the driver was using the NAPI POLL function, it\r
+                 did not have a way for the kernel dump to function.\r
+        Change : The driver NAPI POLL function code was change so that\r
+                 it now will call the driver ISR to allow the kernel\r
+                 dump function to run when the kernel dump feature\r
+                 is enabled in the kernel.\r
+        Impact : None.\r
+\r
+    2. Problem : CQ12114 The MSI state machine on the device is not\r
+                 disabled on the in the event that the system\r
+                 call to enable msi fails.\r
+        Change : The driver will disable the MSI state machine\r
+                 when the call to pci_enable_msi() fails.\r
+        Impact : None.\r
+\r
+\r
+\r
+\r
+v8.1.3 (February 15, 2005)\r
+============================\r
+\r
+   Fixes:\r
+   -----\r
+\r
+    1. Problem : (CQ11951) "Failed to access NVRAM" messages are\r
+                 showing up in the message file.\r
+       Cause   : Because EEPROM accesses are much slower than flash\r
+                 accesses, the bootcode can take that much longer to\r
+                 initialize the hardware.  The problem here was that\r
+                 Linux was downloading the LSO firmware to the NIC\r
+                 before the bootcode had a chance to complete it's\r
+                 task.  As a result, the firmware would crash, while\r
+                 still holding the NVRAM lock.\r
+       Change  : Acquire the NVRAM lock before halting the CPU and\r
+                 downloading the LSO firmware.\r
+       Impact  : None.\r
+\r
+    2. Problem : (CQ12096) MODULE_PARM deprecated warnings.\r
+       Cause   : Linux is moving to a new module parameter declaration\r
+                 format.  The kernel has deprecated the older\r
+                 parameter declaration style.\r
+       Change  : For those module parameters that do not have a\r
+                 configuration tool equivalent, the parameter\r
+                 declarations have been converted to the new style.\r
+                 All other module parameters have been dropped in\r
+                 favor of their configuration tool equivalents.\r
+       Impact  : None.\r
+\r
+\r
+   Enhancements:\r
+   -------------\r
+\r
+   1. Problem : (CQ10408) Driver does not issue a "Link is DOWN"\r
+                message when bringing the interface down.\r
+      Change  : Issue a "Link down" message upon device closure.\r
+      Impact  : None.\r
+\r
+   2. Problem : (CQ10828) The driver needs a way to isolate\r
+                loopback testing.\r
+      Change  : Added a NICE command to invoke loopback tests.\r
+      Impact  : None.\r
+\r
+   3. Problem : CQ12159 Older silicon has memory location 0xd38 uninitialized\r
+                and bits 17,18 may be set which causes the capacitive\r
+                coupling and pre-emphasis settings to be enabled by mistake.\r
+      Change  : Validate memory location 0xd38 before using it.\r
+                The patch is similiar to a patch done in tg3.\r
+      Impact  : none.\r
+\r
+   4. Problem : Added changed asic revs for 5714 family.\r
+\r
+\r
+\r
+v8.1.2 (February 1, 2005)\r
+============================\r
+   Fixes:\r
+   -----\r
+\r
+   1. Problem : (CQ12046)Does not compile on some supported distrobutions.\r
+       Cause  : The disable_msi switch was declared but then used within\r
+                #defines\r
+       Change : The disable_msi switch is declared within the same defines\r
+                as where it is used.\r
+\r
+   Impact: None.\r
+\r
+   2. Problem: (CQ12045)Unable to pass traffic on the 5714.\r
+      Cause  : The disable_msi switch seems to have caused compile problems.\r
+      Change : The above change resolves this problem too.\r
+\r
+   Impact: None.\r
+\r
+   Enhancment: Added support for the 5751_C0.\r
+\r
+\r
+v8.1.1 (February 1, 2005)\r
+============================\r
+   Enhancements:\r
+   ------------\r
+   Change: MAC address is read from NVRAM on 5714s for now.\r
+\r
+   Impact: None.\r
+\r
+\r
+v8.1.0.5 (January 28, 2005)\r
+============================\r
+   Enhancement:\r
+   ------------\r
+   Change: Jumbo frames are supported on the 5714.\r
+           msi is supported on the 5714\r
+           NVRAM support code was enhanced.\r
+\r
+   Impact: None.\r
+\r
+   Note: This is a preliminary driver for internal testing only.\r
+\r
+\r
+8.1.0.4.msi (January 1, 2005)\r
+============================\r
+   Enhancement:\r
+   ------------\r
+   Change: Additional tweeking to support 5752 & 5714/5715 including:\r
+           -msi is enabled for 5752 only.\r
+           -detection of 5752 & 5714 is fixed.\r
+\r
+   Impact: None.\r
+\r
+   Note: This is still a preliminary driver release for internal\r
+         testing only.\r
+\r
+\r
+\r
+v8.1.0.2 (December 16, 2004)\r
+============================\r
+   Enhancement:\r
+   ------------\r
+   Change: PCI IDs were added to support the 5752\r
+\r
+   Impact: None.\r
+\r
+   Note: This is a very preliminary and internal release for internal\r
+         testing only.\r
+\r
+\r
+\r
+v8.1.0.1 (December 14, 2004)\r
+============================\r
+   Enhancement:\r
+   ------------\r
+   Change: PCI IDs were added to support the 5714 and 1515.\r
+\r
+   Impact: None.\r
+\r
+   Note: This is an alpha release for support of the 5714 & 5715\r
+\r
+\r
+v7.4.10 (December 3, 2004)\r
+=========================\r
+\r
+   1. Problem : (CQ11042)ASF IP Monitoring cannot update config table.\r
+\r
+      Cause   : The NVRAM on 5750 LOM systems could not be written as\r
+                the NVRAM write protection was not being cleared by\r
+                the driver.\r
+\r
+      Change  : The driver now  correctly uses the write protection\r
+                capabilities of the 5750 LOM NVRAM.\r
+\r
+      Impact  : The driver can write to the NVRAM for 5750 LOMs.\r
+\r
+\r
+\r
+v7.4.9 (December 1, 2004)\r
+=========================\r
+\r
+   1. Problem : EEPROM_ExecuteCommand warnings showing up on the console.\r
+\r
+      Cause   : Code incorrectly uses old EEPROM routines.\r
+\r
+      Change  : Use new nvram routines when available.\r
+\r
+      Impact  : Flash works as expected.\r
+\r
+   2. Problem : (CQ11472)Add PLL workaround.\r
+\r
+      Cause   : Occasionally a problem occurs when the device is put\r
+                into D3 cold. The problem can result in a chip lockup.\r
+                This only occurs on 5750 AX/BX chips.\r
+\r
+      Change  : Added the workaroud to code, which is to keep the\r
+                power clks ticking when transitioning to d3 cold/hot.\r
+\r
+      Impact  : D3 transition is robust.\r
+\r
+\r
+v7.4.8 (November 24, 2004)\r
+=========================\r
+\r
+   1. Problem : Vpd cannot be read on 5704 and other legacy devices.\r
+\r
+      Cause   : Code incorrectly identifies flash type.\r
+\r
+      Change  : Ignore bits 24 and 25 on Config1 for legacy devices.\r
+\r
+      Impact  : Flash works as expected.\r
+\r
+\r
+   2. Problem : (CQ11402) Driver crashes while obtaining chip size on 5701.\r
+\r
+      Cause   : Code uses incorrect read routine.  Chipsize was not\r
+                initialized which caused a divide by zero.\r
+\r
+      Change  : Change code to use correct read routine.  Made sure\r
+                to set the chipsize to a valid chipsize (nonzero)\r
+                before calling the read routine.\r
+\r
+      Impact  : EEPROM works as expected.\r
+\r
+\r
+   3. Problem : Firmware version not correct for 5721 devices.\r
+\r
+      Cause   : Offset calculation error for Atmel parts.\r
+\r
+      Change  : Fix calculation error.\r
+\r
+      Impact  : Firmware version correct.\r
+\r
+\r
+v7.4.7 (November 18, 2004)\r
+=========================\r
+\r
+   1. Problem : Firmware version not displaying on BCM5753 devices.\r
+\r
+      Cause   : Reads being performed before the NVRAM is locked.\r
+\r
+      Change  : Lock the NVRAM before performing any reads.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   2. Problem : (CQ11142) OOPS occuring on PPC750\r
+\r
+      Cause   : Statistic and status memory pointers were initialized\r
+                even after driver shutdown and memory deallocation\r
+                causing OOPS to occur when statistics were probed.\r
+\r
+      Change  : Reset pointers to zero after shutdown.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   3. Problem : (CQ11115) Driver allows for invalid user adminstered\r
+                MAC address.\r
+\r
+      Cause   : Driver did not check for valid address.\r
+\r
+      Change  : Driver checks for valid MAC address.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   4. Problem : (CQ10598) Driver occasionally cannot get link on certain\r
+                machines.\r
+\r
+      Cause   : The certain machines had interrupt sharing between many\r
+                devices and occasionally the driver would lose the\r
+                link change interrupt.\r
+\r
+      Change  : The ISR was modified to ensure the interrupt being cleared\r
+        has been serviced properly.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   5. Problem : (CQ11117) Need SERDES pre-emphasis support.\r
+\r
+        Cause : Certain 5704 designs have requested that certain bits be\r
+                set in SERDES configuration registers.\r
+\r
+       Change : Changes made use presupplied value for SERDES configuration.\r
+\r
+       Impact : None.\r
+\r
+\r
+  Enhancement :\r
+  -------------\r
+\r
+   1. Change  : GPIO2 will not have an output for the 5753 family.\r
+\r
+   2. Change  : Added code to support more flash (and EEPROM) types.\r
+                The flash write code has been separated into buffered\r
+                and unbuffered versions.  The flash and EEPROM read\r
+                code has been modified to support sub-32bit word reads.\r
+                New nvram sizing functions have been introduced.\r
+\r
+\r
+v7.4.6 (October 25, 2004)\r
+=========================\r
+\r
+   1. Problem : (CQ11088) Remove the ability to set speed & duplex on the 150T\r
+\r
+       Cause  : The switch on the 150T nic is set to autoneg. The line speed\r
+                on the 5705 should only be set to auto for proper link to\r
+                be established with the internal switch.\r
+\r
+      Change  : Added code in b57um.c line 4316 to check for this nic and\r
+                always set it to auto.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   2. Problem : (CQ11102) NMI occurs during load/unload w/ASF enabled.\r
+\r
+       Cause  : The 5753 drove GPIO2 as an output, which did not allow\r
+                ASF to use it to sense main power properly.\r
+\r
+      Change  : The driver does not driver GPIO2.\r
+\r
+      Impact  : None.\r
+\r
+\r
+v7.4.5 (October 11, 2004)\r
+========================\r
+   Enhancement:\r
+   ------------\r
+   Change: PCI IDs were added to support the 5753, 5753M, 5753F and 5789.\r
+\r
+   Impact: None.\r
+\r
+\r
+v7.4.4 (October 4, 2004)\r
+=======================\r
+\r
+   1. Problem : (CQ10955) DELL 6650 kernel panic during negotiation\r
+        using 5700 lom.\r
+\r
+       Cause  : Spinlock deadlock during reset & link up.\r
+\r
+      Change  : Removed the spinlock contention.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   2. Problem : (CQ10436)Man page needs update.\r
+\r
+       Cause  : bcm5700.ko was not noted in man page.\r
+\r
+      Change  : Modified man page.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   3. Problem : (CQ10396) Cannot ping when Dell PowerEdge 6650(#459)\r
+                is configured for 10half forced.\r
+\r
+      Cause   : 5411 PHY does not require a PHY reset before being set\r
+                up to 10 half, or a PHY reset was being called without\r
+                sufficient delay before the PHY was being set up.\r
+\r
+                The code in LM_ResetAdapter()calls\r
+                LM_ResetPhy()(on line 3479 in tigon3.c) immediately before\r
+                calling LM_SetupPhy().\r
+                If a 2 second delay is placed between these two functions,\r
+                then 10half forced will function, or when LM_ResetPhy()\r
+                is removed, 10half forced will again function.\r
+\r
+                It is not clear why This delay is needed or why\r
+                LM_ResetPhy()is needed here as the MII control reg shows\r
+                the same values for a successful or failed case.\r
+                LM_ResetPhy() is not called for the 5401 PHY for the\r
+                same reason this problem occurs.\r
+                A request for assistance was emailed to HWEng  with no\r
+                response.\r
+\r
+      Change  : Removed unnecessary PHY reset for 5411 PHY.\r
+\r
+      Impact  : Forcing 5411 PHY to 10 half will function as expected.\r
+\r
+\r
+\r
+v7.4.3 (August 26, 2004)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem : (CQ10437) Driver is installed in a directory other\r
+                than the directory noted in the README.TXT file.\r
+\r
+       Cause  : Note omission.\r
+\r
+       Change : Added a line in the README.TXT file diclosing an\r
+                alternative install directory\r
+                (/lib/modules/<kernel_version>/kernel/drivers/net/bcm/)\r
+                for SLES9 installations.\r
+\r
+       Impact : Problem resolved.\r
+\r
+   2. Problem : (CQ10396) Cannot ping when Dell PowerEdge 6650(#459)\r
+                is configured for 10half forced.\r
+\r
+      Cause   : 5411 PHY does not require a PHY reset before being\r
+                forced to 10 half.\r
+\r
+      Change  : Removed unnecessary PHY reset for 5411 PHY.\r
+\r
+      Impact  : Forcing 5411 PHY to 10 half will function as expected.\r
+\r
+\r
+   3. Problem : (CQ10540)Max value for "stats_coalesce_ticks" is\r
+                rejected in 2.6 kernels.\r
+\r
+       Cause  : 2.6 kernels are using a different parameter interface\r
+                that limits the value range.\r
+\r
+       Change : README.TXT was changed to inform the user that the\r
+                value range for this parameter may very by kernel version.\r
+\r
+      Impact  : None.\r
+\r
+\r
+   4. Problem : (CQ9804)5751 freezes in certain platforms under heavy\r
+                stress.\r
+\r
+       Cause  : A logic bug in clearing interrupts caused this to occur.\r
+                See previous entry for CQ9804.\r
+\r
+      Change  : Setting Bit 29 in 0x7c00 (TLP control reg) prevents\r
+        the lock-up from occurring and was set as a safeguard.\r
+\r
+       Impact : None.\r
+\r
+\r
+   Enhancement: (CQ10355) Ethtool -i shows no value for "firmware-version"\r
+   ------------\r
+      Change  : Added bootcode version value to Ethtool driver info structure.\r
+\r
+      Impact  : None.\r
+\r
+\r
+\r
+\r
+v7.4.2 (July 29, 2004)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem:(CQ10695) System screen froze after third port.\r
+\r
+       Cause: Third port was pci and driver was treating it\r
+          as a pciexpress. Bug introduced v7.4.1.\r
+\r
+       Change:Driver checks for PCIE or PCI and then executes\r
+          PCIE code only on PCIE adapter.\r
+\r
+       Impact:Problem resolved.\r
+\r
+   2. Problem:(CQ10627)Remove 5751-A0 support.\r
+\r
+       Cause: 5751-A0 is not shipping.\r
+\r
+       Change:Driver checks for 5751 A0 then fails if found.\r
+\r
+       Impact:Driver will not load on 5751-A0\r
+\r
+\r
+v7.4.1 (July 27, 2004)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem:(CQ10602) FSC 1899 system may freeze/reboot when bringing the\r
+        initerface up/down with ASF enabled.\r
+\r
+      Cause:  Handshake between ASF & driver disrupted by 7.4.0 extra\r
+          delay, allowing the driver to enable D3 state before ASF\r
+          was ready.\r
+\r
+      Change: Delay was moved to immediately before enabling D3.\r
+\r
+      Impact: Driver will not freeze or reboot system.\r
+\r
+   2. Problem:(CQ10481)Driver displays gigabit speed on adapter\r
+          that only supports 10/100.\r
+\r
+      Cause:  The Driver displayed support for 10/100/1000 link\r
+              do to an error in the code.\r
+\r
+      Change: Code changed to display correct link support\r
+          values.\r
+\r
+      Impact: Driver displays correct supported link speeds.\r
+\r
+\r
+v7.4.0 (July 12, 2004)\r
+======================\r
+   Enhancement:\r
+   ------------\r
+   Change: Added extra delay after GRC reset to make the\r
+           firmware D3hot workaround in 3.29i effective.\r
+\r
+   Impact: None.\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ10549) "BCM_DRV: command not found" when compiling\r
+               the source RPM.\r
+\r
+      Cause: $(BCM_DRV) not substituted properly.\r
+\r
+      Change: Changed all $(BCM_DRV) to $BCM_DRV in bcm5700.spec.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ10468) Driver not working properly in bridging environment\r
+               after changing mtu.\r
+\r
+      Cause: Promiscuous mode not preserved after changing mtu.\r
+\r
+      Change: Fixed by setting the rx mode after mtu change.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: (CQ10557) Kernel panics with 17 or more devices installed.\r
+\r
+      Cause: Driver parameters checking logic assumes maximum of 16\r
+             devices.\r
+\r
+      Change: Added logic to skip parameter processing if the device\r
+              index is higher than or equal to 16.\r
+\r
+      Impact: This will prevent the kernel panic and the driver will load with\r
+              any number of devices in the system. Driver parameters will\r
+              only work for the first 16 devices.\r
+\r
+   4. Problem: Changing mtu may cause the kernel to print a warning message:\r
+               sleeping function called from invalid context at mm/slab.c.\r
+\r
+      Cause: Calling kmalloc with GFP_KERNEL from invalid context.\r
+\r
+      Change: Changed to GFP_ATOMIC.\r
+\r
+      Impact: None.\r
+\r
+v7.3.5 (June 23, 2004)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ10407) Linux 2.6 kernel fails to get IP address using DHCP\r
+               on 5751 A1.\r
+\r
+      Cause: When DHCP fails, ifup script will shutdown the NIC and it\r
+             will go to D3hot state. On 2.6 kernels, the config write\r
+             to put device in D3hot will be written using mmconfig with\r
+             a mmconfig read of register 0 to flush the write. The\r
+             read immediately following the write when the device is\r
+             transitioning to L1 link state may cause problems. The symptom\r
+             is that the device will lose the memory space bit in the\r
+             PCI command register. When ifup brings up the NIC again\r
+             to retry DHCP, the device will not be functional.\r
+\r
+     Change: The fix for the problem is in bootcode 3.29 which will\r
+             greatly reduce if not eliminate this problem from happening.\r
+             To further reduce the risk, 2 changes were made to the driver.\r
+             1. Add a parameter to disable D3hot (disable_d3hot).\r
+             2. Check PCI command register and re-enable the memory space\r
+                and other bits multiple times until the bits are set\r
+                or up to a maximum during driver init.\r
+\r
+      Impact: None.\r
+\r
+v7.3.4 (June 18, 2004)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ10312) System Hangs when loading and unloading the driver\r
+               continuously with 5705.\r
+\r
+      Cause: Hang was caused by infinite retry soon after writing to register\r
+             0x74 to speed up the core clock.\r
+\r
+      Change: Implemented a 2-step sequence to speed up the core clock on\r
+              5705 and shasta devices.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: System crashes occasionally when loading and unloading the\r
+               driver.\r
+\r
+      Cause: System may be unable to map memory.\r
+\r
+      Change: Added error check on memory mapping and gracefully fail\r
+              the driver load.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: (CQ10364) System hangs when issuing reset from b57ldiag.\r
+\r
+      Cause: Deadlock when trying to get a spinlock.\r
+\r
+      Change: Removed the deadlock.\r
+\r
+      Impact: None.\r
+\r
+   4. Problem: (CQ10379) Driver allows jumbo frames on 5751/5721 devices\r
+               using ifconfig.\r
+\r
+      Cause: Missing validity check for mtu on shasta devices.\r
+\r
+      Change: Added checks.\r
+\r
+      Impact: None.\r
+\r
+   5. Problem: (CQ#10110) ethtool -d still hangs on some systems.\r
+\r
+      Cause: Chip does not respond to reserved registers, causing\r
+             some machines to hang.\r
+\r
+      Change: More changes to only dump the valid registers in the\r
+              memory space.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added Capacitive coupling phy support.\r
+\r
+v7.3.3 (June 03, 2004)\r
+======================\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added support for 5789.\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: 5704 may run on Vaux during normal operations.\r
+\r
+      Cause: Depending on the sequence of shutdown, the first port\r
+             of a 5704 may be brought up and run on Vaux due to\r
+             a programming error.\r
+\r
+      Change: Corrected the GPIO programming sequence to take\r
+              both ports of the 5704 into account.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: NC150T not identified.\r
+\r
+      Change: Added OEM string.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: (CQ #10340) NC1020 identified as NC7722.\r
+\r
+      Cause: String not updated.\r
+\r
+      Change: Updated OEM string.\r
+\r
+      Impact: None.\r
+\r
+v7.3.2 (June 03, 2004)\r
+======================\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added support for 5751F.\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #10145) IBM PPC64 PBlade crashes after many hours.\r
+\r
+      Cause: Speculative execution path reading an old descriptor, causing\r
+             the wrong buffer to be freed.\r
+\r
+      Change: Added read memory barriers to prevent this.\r
+\r
+      Impact: None\r
+\r
+   2. Problem: 5701 does not link up intermittently.\r
+\r
+      Cause: Concurrent register writes when adding multicast address and\r
+             sevicing link change interrupt. This is a chip bug.\r
+\r
+      Change: Added locking to prevent this one case of concurrent register\r
+              access.\r
+\r
+      Impact: None.\r
+\r
+v7.3.1 (May 27, 2004)\r
+=====================\r
+   Fixes:\r
+   ------\r
+   1. Change: Added workaround for 5750 A3 to disable the CPU after\r
+              reset.\r
+\r
+      Impact: None.\r
+\r
+v7.3.0 (May 21, 2004)\r
+=====================\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added support for 5751M devices.\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ#10109) CIOBE hangs machine after many hours of heavy traffic.\r
+\r
+      Cause: New hw errata on 5704 PCIX multi-split mode.\r
+\r
+      Change: Disabled multi-split on CIOBE.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ#10110) ethtool -d hangs on some systems.\r
+\r
+      Cause: Chip does not respond to reserved registers, causing\r
+             some machines to hang.\r
+\r
+      Change: Changed code to only dump the valis registers in the\r
+              memory space.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: Driver contains unresolved genapic symbol when compiled\r
+               on some kernels.\r
+\r
+      Cause: genapic may be referenced by hard_smp_processor_id.\r
+\r
+      Change: Removed hard_smp_processor_id which is purely for\r
+              debugging and not needed.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: (CQ#9959) ethtool returns wrong flow control settings.\r
+\r
+      Cause: Minor bug.\r
+\r
+      Impact: None.\r
+\r
+v7.2.24 (April 23, 2004)\r
+========================\r
+   Enhancements:\r
+   -------------\r
+   1. Change: (CQ #9955) Remove support for 5751M devices.\r
+\r
+      Impact: None.\r
+\r
+   2. Change: Added support for cache line aligned write DMA on PPC64.\r
+              This feature is only supported on 5700/5701.\r
+\r
+      Impact: None.\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: ASF doesn't run properly after ifdown on 5750 chips.\r
+\r
+      Cause: Driver sets device to run on slow core clock during\r
+             shutdown. ASF cannot run on slow clock.\r
+\r
+      Change: Added check to skip slowing the core clock if ASF\r
+              is running on 5750 chips.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: TSO doesn't work on non-x86 architectures.\r
+\r
+      Cause: U32 misdefined.\r
+\r
+      Impact: None.\r
+\r
+v7.2.23 (April 19, 2004)\r
+========================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #9782) ethtool link test fails on 5703 intermittently.\r
+\r
+      Cause: Not waiting long enough for link up.\r
+\r
+      Change: Added 3 more seconds if copper link is still down.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added PHY workaround for 5705/5750 to improve bit error rate.\r
+\r
+      Impact: None.\r
+\r
+v7.2.22 (April 14, 2004)\r
+========================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #9804) PCIE system freezes under heavy stress.\r
+\r
+      Cause: 2 problems - 1. Logic in poll routine prematurely clears\r
+             the next interrupt, causing tx timeout. 2. Bug in reset\r
+             logic causing hang.\r
+\r
+      Change: Made changes to the logic that reenables rx interrupt\r
+              in the poll routine. Fixed the tx timeout reset routine.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ #9836) 5700 LOMs not recognising link down.\r
+\r
+      Cause: 5700 in 66 MHz or higher bus speeds will go through\r
+             chip reset instead of the normal link down interrupt\r
+             when link goes down at gigabit link speed. There is\r
+             a bug in the reset logic that causes the link down\r
+             event to be unreported.\r
+\r
+      Change: Simple change in the reset logic.\r
+\r
+      Impact: None.\r
+\r
+\r
+v7.2.21 (April 08, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #9645) Unable to pass traffic on 5701 with long cable.\r
+\r
+      Cause: Phy register 0x18 shadow 0 not set correctly.\r
+\r
+      Change: Changed the code to do read-modify-write on that register\r
+              to preserve the contents of that register.\r
+\r
+      Impact: None.\r
+\r
+v7.2.20 (Mar. 31, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: Poor performance in NAPI mode in certain test cases.\r
+\r
+      Cause: Stale packets not processed by the driver after polling\r
+             completes. This is caused by rx interrupt being\r
+             enabled right after a new status block is already\r
+             initiated and pending DMA.\r
+\r
+      Change: Implemented a new scheme to detect possible missed\r
+              packets after rx interrupt is enabled. Also set\r
+              the "during-int" coalescing parameters to be the\r
+              same as the normal coalescing parameters.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: Driver unable to identify the PHY intermittently.\r
+\r
+      Cause: In some cases, both boot code and driver\r
+             cannot read the proper PHY ID from the PHY. Driver\r
+             relies on either the PHY ID read by boot code or\r
+             directly read from the PHY register to idendify the PHY.\r
+\r
+      Change: Changed the PHY detection logic to make it more\r
+              robust by doing PHY reset when boot code and PHY\r
+              registers return invalid PHY ID.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: LEDs not working perfectly on shasta devices.\r
+\r
+      Cause: Some new shasta LED modes require driver to update\r
+             register 0x450.\r
+\r
+      Change: Added necessary code to update register 0x450.\r
+              Also changed driver to program register 0x40c\r
+              instead of relying on boot code to program it.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: Driver does not compile on kernels not supporting\r
+               NAPI.\r
+\r
+      Cause: Minor syntax error.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added a new OEM ID and string.\r
+\r
+v7.2.19 (Mar. 11, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ9188) Gigabit link light still does not work on 5751.\r
+\r
+      Cause: bug in implementation.\r
+\r
+      Change: Cleaned up the LED code in the driver and let the\r
+              bootcode program the LEDs on shasta (575x/572x) devices.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: CRC errors reported on 5700 using 5411 PHYs.\r
+\r
+      Cause: PHY register 0x18 shadow register 0 not programmed\r
+             correctly.\r
+\r
+      Change: Fixed code to use the same setting as 5401.\r
+\r
+      Impact: None.\r
+\r
+   3. Change: Enabled hw bug fix for 5703/04 PCI-X write DMA bug.\r
+\r
+      Impact: None.\r
+\r
+   4. Problem: ethtool -t fails nvram test in big endian systems.\r
+\r
+      Cause: Endian bug in calculating CRC in nvram.\r
+\r
+      Change: Simple fix by swapping data.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: (CQ8586) Added some missing stats counters to\r
+              ETHTOOL_GSTATS\r
+\r
+      Impact: None\r
+\r
+v7.2.18 (Feb. 24, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Change: Changed driver for 5751 A1 by disabling PCIE reset\r
+              during GRC reset.\r
+\r
+      Impact: None.\r
+\r
+   2. Change: Changed driver for 5751 A1 by enabing PCIE data\r
+              fifo bug fix in the chip.\r
+\r
+      Impact: None.\r
+\r
+v7.2.16 (Feb. 20, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ9188) Gigabit link light does not work on 5751.\r
+\r
+      Cause: Driver did not support the new shasta LED modes.\r
+\r
+      Change: Added support for the new shasta LED modes.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ9418) 5700 NIC fails to pass traffic at 10Mbps\r
+               half duplex when connected to a switch port forced\r
+               to the same speed setting.\r
+\r
+      Cause: The 5401 PHY requires a long delay after PHY reset\r
+             before the PHY can be confiured.\r
+\r
+      Change: Changed code to skip PHY reset if it is 5401.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: (CQ9430) RPM build errors occur on 2.6.x kernels.\r
+\r
+      Cause: spec file was not handling 2.6 kernels with the new\r
+             kernel build mechanism properly.\r
+\r
+      Change: Modified the spec file.\r
+\r
+      Impact: None.\r
+\r
+   4. Problem: (CQ9410 & CQ9393) Delayed link report to MII and\r
+               ETHTOOL ioctls causing problems.\r
+\r
+      Cause: Workaround for ifup problem (see v6.2.11, CQ7791 bug\r
+             fix descript for details) causing problems in\r
+             other applications that require accurate link information.\r
+\r
+      Change: Changed driver so that the delayed link workaround is\r
+              enabled using a delay_link driver parameter. The parameter\r
+              is disabled be default.\r
+\r
+      Impact: ifup may not be able to obtain IP address using DHCP.\r
+              Use the delay_link parameter or modify the ifup script\r
+              to increase the wait time for link up.\r
+\r
+v7.2.15 (Feb. 12, 2004)\r
+=======================\r
+   Enhancement:\r
+   ------------\r
+   1. Change:  Added diagnostics functions to support ethtool -t.\r
+\r
+      Impact: None.\r
+\r
+v7.2.12 (Feb. 05, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: Tx timeout reset may crash when hardware is unreliable.\r
+\r
+      Cause: Reset routine relies on a valid rx consumer index in status\r
+             block to free the rx buffers. (related to problem #1\r
+             fixed in 7.2.10)\r
+\r
+      Change: Changed logic to not rely on the hw rx consumer index.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: Driver not running in NAPI mode\r
+\r
+      Cause: see Problem #1 fixed in 7.2.10.\r
+\r
+      Change: Fixed NAPI code so that it will also run in single-threaded\r
+              mode.\r
+      Impact: None.\r
+\r
+   3. Problem: (CQ 9293) Driver hangs intermittently during ifdown.\r
+\r
+      Cause: Writing to Nic's memory when memory arbiter is disabled.\r
+\r
+      Change: Changed code to write firmware mailbox signatures before\r
+              memory arbiter is disabled.\r
+\r
+      Impact: None.\r
+\r
+   4. Problem: PHY's extended packet length bit not set when using\r
+               jumbo frames.\r
+\r
+      Change: Added change to always set this bit on NICs that\r
+              support jumbo frames.\r
+\r
+      Impact: None, but testing required.\r
+\r
+   5. Problem: Posted writes not flushed before delay loop, causing\r
+               the delay to be less than intended in duration.\r
+\r
+      Change: Added register read back to flush the writes before delay\r
+              loop, where appropriate.\r
+\r
+      Impact: None.\r
+\r
+   6. Problem: (CQ 9263) ethtool -a returning wrong autonegotiation\r
+                status.\r
+\r
+      Cause: Minor bug.\r
+\r
+      Change: Minor change.\r
+\r
+      Impact: None.\r
+\r
+   Enhancement:\r
+   ------------\r
+   1. Change: Implemented TSO for 5788 and changed name to NetLink\r
+\r
+      Impact: None.\r
+\r
+v7.2.11 (Jan. 21, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ#9207) ASF does not work when driver is loaded on 5751.\r
+\r
+      Cause:  Driver/ASF handshake problem caused by a long delay after\r
+              GRC reset.\r
+\r
+      Change: Added the new Driver/ASF handshake mechanism.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ#9179) Driver allows jumbo frames on 575x.\r
+\r
+      Change: Minor change to disallow setting jumbo frames on 575x.\r
+\r
+      Impact: None.\r
+\r
+v7.2.10 (Jan. 13, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ#9181) Panic on IBM PCIE system running chariot.\r
+\r
+      Cause: The panic was caused by a problem in the tx timeout\r
+             reset logic that assumed a good rx BD consumer index\r
+             can always be read from the chip during reset. When\r
+             something is wrong with the chip and a bogus rx BD\r
+             consumer is read, the system panics when trying to\r
+             recycle a wrong BD.\r
+\r
+             The tx timeout itself was caused by buggy single-threaded\r
+             workaround code and register read back code originally\r
+             implemented for the 5700 and 5701.\r
+\r
+      Change: Fixed the single-threaded and register read back\r
+              workaround. The fix was implemented for non-NAPI\r
+              mode only as the fix for NAPI will take more time.\r
+              The driver will only run in non-NAPI mode.\r
+\r
+      Impact: Minor.\r
+\r
+   2. Problem: ASF does not run on 5751.\r
+\r
+      Cause: FTQ reset after chip reset.\r
+\r
+      Change: Removed FTQ reset.\r
+\r
+      Impact: Should be none, but need to be tested on all 570x chips.\r
+\r
+   3. Problem: (CQ#9170) NMI occurs intermittently when doing ifconfig down.\r
+\r
+      Cause: HW bug when programming 5751 to low power mode.\r
+\r
+      Change: Removed low power mode setting for 5751.\r
+\r
+      Impact: Wol will not work on 5751.\r
+\r
+   4. Change: Changed delay after GRC reset to 500 msec.\r
+\r
+   5. Change: Changed shasta_smp_fix to 1 (enabled) be default.\r
+\r
+v7.2.9 (Jan. 09, 2004)\r
+======================\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added parameter shasta_smp_fix to enable/disable\r
+              SMP workaround (see fix #2 in v7.2.8). Default\r
+              is workaround disabled.\r
+\r
+      Impact: None.\r
+\r
+v7.2.8 (Jan. 05, 2004)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ#9096) Data corruption with large ping packets.\r
+\r
+      Cause: Mbuf pool start and length registers overwritten by\r
+             driver.\r
+\r
+      Change: Fixed code so that the 2 mbuf registers will not be\r
+              overwritten for the 5750.\r
+\r
+      Impact: None.\r
+\r
+   2. Change: Added register read back and single-threaded workaround\r
+              for 5750 PCIE.\r
+\r
+      Impact: Lower performance.\r
+\r
+v7.2.7 (Dec. 24, 2003)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Change: Changed delay to 300msec after GRC reset for 5751/5721 A0 PCI\r
+              Express devices.\r
+\r
+      Impact: None.\r
+\r
+v7.2.6 (Dec. 10, 2003)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: Driver does not receive interrupts on some PCI\r
+               Express systems.\r
+\r
+      Cause: A register bit could not be set using config. cycles.\r
+\r
+      Change: Changed to memory write cycle to write the register.\r
+\r
+      Impact: None.\r
+\r
+v7.2.5 (Dec. 02, 2003)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: Driver crashes during transmit timeout reset.\r
+\r
+      Cause: Driver was calling schedule_timeout which is a\r
+             blocking function and cannot be called in interrupt\r
+             context.\r
+\r
+      Change: Changed to udelay.\r
+\r
+      Impact: None.\r
+\r
+v7.2.4 (Nov. 24, 2003)\r
+======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #8908) System freezes when 5751 PCI Express device\r
+               is brought up.\r
+\r
+      Cause: PCI Express device was not detected properly.\r
+\r
+      Change: Corrected the PCI Express detection logic.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ #8910) PCI_Bus_Speed is misreported for PCI Express\r
+               device.\r
+\r
+      Cause: Old logic did not take PCI Express into account.\r
+\r
+      Change: Made simple change to account for PCI Express device.\r
+\r
+      Impact: None.\r
+\r
+v7.2.1 (Nov. 18, 2003)\r
+======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Made some changes to make 5751 work on PCIE 1.0 systems.\r
+\r
+v7.2.0 (Nov. 17, 2003)\r
+======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added support for 575x and 572x PCI and PCIE chips.\r
+\r
+v7.1.21 (Jan. 05, 2004)\r
+=======================\r
+   Fixes:\r
+   ------\r
+   1. Problem: ASF stops working after driver is loaded if PXE ran\r
+               and did not shutdown properly.\r
+\r
+      Cause: The wait time to gain NVRAM arbitration was not long\r
+             enough in 5704 using serial eprom. As a result, a\r
+             reset can happen to one channel of a 5704 while\r
+             the other channel is still loading boot code. This\r
+             will cause ASF to subsequently hang waiting forever\r
+             for NVRAM arbitration.\r
+\r
+      Change: Changed the wait time to cover the worst case\r
+              serial eprom boot code load time plus a safety margin.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ#8890) Receive errors on 5700 NICs.\r
+\r
+      Cause: Incorrect PHY settings on the 5401 introduced in 6.2.18\r
+             when PHY loopback was implemented.\r
+\r
+      Change: Fixed the PHY settings.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: Driver does not compile on some 2.4 kernels.\r
+\r
+      Cause: Driver not compatible with some older ethtool.h files.\r
+\r
+      Change: Added #ifdef to fix the problem.\r
+\r
+      Impact: None.\r
+\r
+v7.1.20 (Dec. 24, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: ASF stops working after driver is loaded if PXE is enabled.\r
+\r
+      Cause: The fix for the PXE problem in version 7.1.18 (fix #3, see below)\r
+             has a flaw that causes reset to always occur if PXE is enabled.\r
+             This reset causes ASF to stop functioning.\r
+\r
+      Change: Fixed the flawed logic.\r
+\r
+      Imapct: None.\r
+\r
+v7.1.19 (Dec. 10, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #8961) Interrupt test fails intermitently.\r
+\r
+      Cause: A race condition between the ioctl and interrupt\r
+             service routine can cause the interrupt test to fail.\r
+\r
+      Change: Added code to regenerate the interrupt in the loop\r
+              that waits for interrupt to complete.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Changed Makefile to use ppc64 compiler and linker\r
+              if compiling on ppc64 environment.\r
+\r
+      Impact: None.\r
+\r
+v7.1.18 (Nov. 21, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: IPMI firmware receiving VLAN tagged packets stops working\r
+               after ifconfig up.\r
+\r
+      Cause: Driver sets NIC to keep VLAN tags by default.\r
+\r
+      Change: Added code and driver parameter vlan_tag_mode to control whether\r
+              VLAN tags will be stripped or not. By default, the driver will\r
+              always strip VLAN tags if ASF/IPMI firmware is enabled.\r
+\r
+      Imapct: If ASF is enabled, the NIC may not work properly when VLAN\r
+              and bonding are used together. Sniffer applications that\r
+              wants to receive raw VLAN-tagged frames will also be affected.\r
+\r
+   2. Problem: IPMI firmware stops working after ifconfig up on PPC64 machine.\r
+\r
+      Cause: Timing differences on PPC cause the driver to reset a certain\r
+             chip block after firmware has enabled it. Timing difference\r
+             is due to very slow config cycles on the PPC.\r
+\r
+      Change: Rearranged some code in LM_ResetAdapter to get around the problem.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: Driver does not load if PXE ran previously and did not shutdown\r
+               the chip.\r
+\r
+      Cause: Driver does not work properly as it expects the chip to be\r
+             disabled during reset.\r
+\r
+      Change: Added code to check if the chip is enabled and reset it\r
+              if necessary before setup.\r
+\r
+      Imapct: None.\r
+\r
+   4. Problem: Driver takes a long time to reset if the bootcode is\r
+               disabled on the PPC.\r
+\r
+      Cause: Config cycles are very slow on the PPC and the loop\r
+             to check for the firmware signature is too tight.\r
+\r
+      Change: Loosened the loop to check for the firmeare signature\r
+              after reset. Also made the maximum loop count smaller\r
+              if it is using flash NVRAM.\r
+\r
+      Imapct: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added ETHTOOL_GRINGPARAM ioctl\r
+\r
+      Imapct: None.\r
+\r
+   2. Change: Added PPC64 specific compile switches in Makefile to allow\r
+              the driver to be compiled as a standalone module.\r
+\r
+      Imapct: None.\r
+\r
+v7.1.11 (Nov. 05, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: Running b57ldiag on PPC system crashes after a while.\r
+\r
+      Cause: PCI addresses not properly unmapped during diagnostics\r
+             suspend operation.\r
+\r
+      Change: Added code to unmap PCI addresses in rx buffers during\r
+              suspend.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Driver doesn't load on SerDes and 5704 devices when\r
+               the NVRAM is blank or corrupted. Driver needs to load\r
+               to support diagnostics.\r
+\r
+      Cause: 5704 NVRAM cannot be reliably accessed when boot code is\r
+             not running, so driver cannot get proper MAC address\r
+             and proper PHY ID.\r
+\r
+      Change: Changed code to allow driver to load with warnings when\r
+              even when NVRAM cannot be accessed.\r
+\r
+      Impact: When boot code is blank, driver will load with a bogus\r
+              MAC address.\r
+\r
+   2. Problem: Driver cannot reliably read/write NVRAM when NVRAM\r
+               is corrupted or blank.\r
+\r
+      Cause: When bootcode is not running, the NVRAM interface state\r
+             machines will get locked up.\r
+\r
+      Change: Added code to reset the NVRAM interfaces of both\r
+              ports in 5704.\r
+\r
+      Impact: None.\r
+\r
+   3. Change: Added ioctl to get and clear statistics block.\r
+\r
+      Impact: None.\r
+\r
+v7.1.9 (Nov. 03, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: Driver does not load on 5704S devices if the eeprom is\r
+               blank.\r
+\r
+      Cause: 5704S defaults to an unsupported device ID when eeprom\r
+             is blank.\r
+\r
+      Change: Added the default 5704S device ID.\r
+\r
+      Impact: None.\r
+\r
+\r
+v7.1.8 (Oct. 31, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: ASF/IPMI stops passing traffic after driver is loaded.\r
+\r
+      Cause: GRC mode control register overwritten when driver loads.\r
+\r
+      Change: Changed driver to preserve the relevant bit in the GRC\r
+              mode control register during driver load.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Changed memory allocation ioctl to support diagnostics\r
+              program doing DMA tests.\r
+              Added a new ioctl to force Nvram write protect on/off\r
+              in case the write protect setting is wrong in the nvram.\r
+\r
+      Impact: None.\r
+\r
+v7.1.6 (Oct. 27, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #8732) Unloading bcm5700.ko in 2.6 kernels causes\r
+               segmentation fault.\r
+\r
+      Cause: Driver uses init_etherdev which has been deprecated by\r
+             alloc_etherdev and register_netdev.\r
+\r
+      Change: Changed to use the new APIs in 2.6 kernels.\r
+\r
+      Impact: None.\r
+\r
+v7.1.5 (Oct. 21, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: Driver does not compile on 2.5+ kernels.\r
+\r
+      Cause:  mem_map_reserve/mem_unmap_reserve no longer defined in 2.5+\r
+              kernels.\r
+\r
+      Change: Changed to SetPageReserved/ClearPageReserved (More testing\r
+              is needed to make sure this works on 2.5+ kernels)\r
+\r
+      Impact: No impact on normal driver operations. The memory\r
+              allocation ioctl that supports diagnostics may be impacted.\r
+\r
+v7.1.4 (Oct. 17, 2003)\r
+======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added memory allocation ioctl to allow user apps to mmap it\r
+              for dma tests.\r
+\r
+      Imapct: None.\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: Driver does not load on ia64 with register_ioctl32_conversion\r
+               undefined.\r
+\r
+      Cause:   register_ioctl32_conversion not defined for ia64.\r
+\r
+      Change:  Removed this routine for ia64.\r
+\r
+      Imapct: None.\r
+\r
+v7.1.2 (Oct. 13, 2003)\r
+======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added OEM string.\r
+\r
+      Impact: None.\r
+\r
+v7.1.1 (Oct. 07, 2003)\r
+======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Change: Added a few more diagnostics ioctl commands.\r
+\r
+      Impact: None.\r
+\r
+   2. Change: (CQ #8428) Added nic_tx_bd parameter.\r
+\r
+      Impact: None.\r
+\r
+   3. Change: Added ETHTOOL_GTSO and ETHTOL_STSO ioctl commands and\r
+              changed TSO to be enabled by default (when supported\r
+              by the NIC and the kernel)\r
+\r
+      Impact: None.\r
+\r
+   4. Problem: (CQ #8469) Mandrake 9.1 has new module path.\r
+\r
+      Change: Modified Makefile to install driver in the new 3rdparty path.\r
+\r
+      Impact: None.\r
+\r
+   5. Problem: (CQ #8438) Some parameters do not assume default values\r
+               as documented.\r
+\r
+      Cause: When running in NAPI mode, some coalescing parameters have\r
+             different default values.\r
+\r
+      Change: Updated documentation and man page.\r
+\r
+      Impact: None.\r
+\r
+\r
+v7.1.0 (Sep. 22, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: SIOCNICE ioctl does not work in 64-bit systems when\r
+               the calling application is 32-bit.\r
+\r
+      Cause: The 32-bit ifreq data structure is converted by the\r
+             kernel to 64-bit, messing up the nice_req structure.\r
+\r
+      Change: Added 32-bit ioctl conversion routine to handle the\r
+              proper conversion.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Ethtool -e does not output the same data on big\r
+               and little endian systems.\r
+\r
+      Change: Change swapping scheme so that nvram read/write routines\r
+              will work with the same byte-stream data in big and little\r
+              endian systems.\r
+\r
+      Impact: None.\r
+\r
+    2. Change: Added support for 5705F.\r
+\r
+       Impact: None.\r
+\r
+v7.0.0 (Aug. 14, 2003)\r
+======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Phy ADC and gamma fix not applied properly to all\r
+               relevant PHY cores.\r
+\r
+      Change: Made appropriate changes to apply the fix to the\r
+              relevant PHYs after PHY reset.\r
+\r
+   2. Problem: 5704 SerDes drive transmission level not set properly.\r
+\r
+      Change: Changed 5704 SerDes' drive transmission level to 1.2V.\r
+\r
+v6.2.20 (Aug. 08, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #8275) 5704B0 NICs not working properly on HP rx2600\r
+               PCIX systems\r
+\r
+      Cause: Problem in one of the hardware fixes in 5704 B0.\r
+\r
+      Change: Disable the h/w fix.\r
+\r
+      Impact: None.\r
+\r
+v6.2.19 (July 31, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: Repeated ifup/ifdown hangs systems using iommu's.\r
+\r
+      Cause: Rx buffers not properly unmapped during ifdown.\r
+\r
+      Change: Fixed driver to unmap all buffers during ifdown.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ# 8232) Copper NICs drop packets when connected\r
+               to some switches.\r
+\r
+      Cause: Phy register 0x18 (aux. ctrl) shadow 0 not set up\r
+             properly. This bug was introduced when adding\r
+             external loop back function in v6.2.18.\r
+\r
+      Change: Fixed the phy register setting.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Not setting up dma mask (pci_set_dma_mask) according to\r
+      Documentation/DMA-mapping.txt.\r
+\r
+      Change: Made the required changes when calling pci_set_dma_mask.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: Driver does not restore line speed settings after\r
+               external loopback.\r
+\r
+      Change: Added code to save line_speed settings before ext.\r
+              loopback and to restore the settings afterward.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: Makefile does not compile driver properly on 2.5+ kernels.\r
+\r
+      Change: Modified Makefile to support 2.4 anf 2.5+ kernels\r
+              transparently. (More work needs to be done)\r
+\r
+      Impact: None.\r
+\r
+v6.2.18 (July 25, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: TSO doesn't work on ia64 and big endian machines.\r
+\r
+      Cause: U32 typedef as unsigned long and TSO firmware was not\r
+             downloaded properly on big endian machines.\r
+\r
+      Change: Fixed U32 typedef and big endian code for firmware\r
+              downloading. Also made additional cleanup and testing\r
+              on the big endian code.\r
+\r
+      Impact: None.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: TSO performance slightly below (< 10%) non-TSO\r
+               performance on 5703/5704.\r
+\r
+      Change: Optimized firmware to narrow the performance gap.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: (CQ #8184) Driver limits the number of Multicast addresses\r
+               to 32.\r
+\r
+      Change: Changed scheme to allow unlimited Multicast addresses by\r
+              by just keeping the Hash values.\r
+\r
+      Impact: None.\r
+\r
+   3. Problem: (CQ #7822) Driver does not support ETHTOOL_GSTRINGS,\r
+               ETHTOOL_GSTATS, ETHTOOL_GREGS, ETHTOOL_PHYS_ID ioctls.\r
+\r
+      Change: Added these ioctls.\r
+\r
+      Impact: None.\r
+\r
+   4. Problem: Driver does not support 5704 B0.\r
+\r
+      Change: Added support for 5704 B0.\r
+\r
+      Impact: None.\r
+\r
+v6.2.17 (July 14, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ8125) ethtool -e hangs system\r
+\r
+      Cause: ethtool tries to read 1Mbytes of data from the slow\r
+             nvram.\r
+\r
+      Change: Changed maximum size of nvram to 128K and added a 1K\r
+              limit to ETHTOOL_GEEPROM ioctl.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: Driver does not work properly on the latest 2.5 kernels\r
+               and generates "irq xx: nobody cared!" message.\r
+\r
+      Cause: Interrupt service routine needs to return value to indicate\r
+             whether interrupt was serviced or not in the latest 2.5\r
+             kernels.\r
+\r
+      Change: Made the necessary change in the ISR.\r
+\r
+      Impact: None. Still compatible with 2.4 and older kernels.\r
+\r
+v6.2.16 (July 11, 2003)\r
+=======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Link polling interval for 5703S NICs is too long.\r
+\r
+      Change: Decreased the link polling interval to 1/4 second.\r
+\r
+      Impact: None.\r
+\r
+v6.2.15 (July 10, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ7987) Blade NIC link toggles up and down under network\r
+               stress.\r
+\r
+      Cause: PCS SYNC signal appears to be unstable in some cases\r
+             under stress.\r
+\r
+      Change: Changed driver to poll for link changes instead of using\r
+              interrupts. Also added code to proceed with PHY setup\r
+              only if PCS SYNC or SIGNAL DETECT are down. These changes\r
+              allow the NIC to run with minimal interruption when the NIC\r
+              occasionally loses PCS SYNC for short periods of time.\r
+\r
+      Impact: May slightly affect link change/autoneg behavior.\r
+\r
+v6.2.14 (July 01, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: Driver panics when loading on 2.4.20-18.7 RH kernel.\r
+\r
+      Cause: Makefile compiles driver with kgcc, making the driver\r
+             incompatible with the kernel that was compiled with gcc.\r
+\r
+      Change: Modified Makefile to choose kgcc only if the kernel\r
+              was compiled with kgcc.\r
+\r
+      Impact: None.\r
+\r
+   2. Problem: Link error when compiling driver into kernel with\r
+               CONFIG_HOTPLUG not defined.\r
+\r
+      Cause: __devexit_p not used in the bcm5700_remove_one pointer.\r
+\r
+      Change: Added __devexit_p for the bcm5700_remove_one pointer.\r
+\r
+      Impact: None.\r
+\r
+v6.2.11 (May 16, 2003)\r
+======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: CQ#7791 Driver cannot consistently lease DHCP address.\r
+\r
+      Cause: The Broadcom NICs sometimes takes longer to link up\r
+             when connected to certain switches. This may cause\r
+             the ifup script to conclude that link is down and not\r
+             proceed to obtain an IP address using DHCP.\r
+\r
+      Change: The workaround is done in the driver to return error when the\r
+              mii-tool or ethtool getlink ioctl interfaces are called during\r
+              the first 6 seconds after driver reset. When the driver returns\r
+              error, the ifup script will assume link is up and proceed with\r
+              the DHCP request. After 6 seconds, these ioctl interfaces will\r
+              return the true link states at the time they are called.\r
+\r
+      Impact: ifup always proceeds with DHCP request whether link is up\r
+              or down.\r
+\r
+v6.2.7 (May 14, 2003)\r
+=====================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Driver does not have OEM strings for some 5703 B0 NICs.\r
+\r
+      Change: Added OEM sub IDs and description strings.\r
+\r
+\r
+v6.2.6 (May 09, 2003)\r
+=======================\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Driver does not support 5901 A2/A3.\r
+\r
+      Change: Added support for 5901 A2/A3.\r
+\r
+\r
+v6.2.5 (May 05, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: Driver intermittently won't load when ASF is enabled.\r
+\r
+      Cause: Driver's init function's PHY routines contend with ASF.\r
+\r
+      Change: Removed PHY access routines in init function when ASF is\r
+              enabled. Using the latest firmware (2.33) will guarantee\r
+              that the proper PHY ID will be obtained by the driver.\r
+\r
+   Enhancements:\r
+   -------------\r
+   1. Problem: Driver does not support 5901.\r
+\r
+      Change: Added support for 5901.\r
+\r
+v6.2.4 (April 29, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: The PHY lockup problem described in v6.2.3 Fix #4 below\r
+               theoretically can affect other PHY cores in 5703 and 5705.\r
+\r
+      Cause: Hardware bug in the PHY core. Probability of lockup is\r
+             extremely small.\r
+\r
+      Change: Expanded the lockup detection and recovery code to 5703,\r
+              5704, and 5705. Also changed the driver to do a PHY reset\r
+              on link down on all versions of 5705. Also added PHY reset\r
+              before restart autoneg in ethtool for 5703, 04, and 05.\r
+\r
+v6.2.3 (April 18, 2003)\r
+=======================\r
+\r
+   Fixes:\r
+   ------\r
+   1. Problem: (CQ #7518) Using ethtool to set speed before ifup crashes\r
+               the system when using fiber NICs.\r
+\r
+      Cause: ethtool ioctl may access the status block which is not\r
+             initialized before ifup.\r
+\r
+      Change: Added check before proceeding with some ethtool ioctls.\r
+\r
+      Impact: Only impact certain ethtool commands.\r
+\r
+\r
+   2. Problem: (CQ #7577) Cannot receive traffic in some rare situations\r
+               after loading the driver.\r
+\r
+      Cause: In some rare situations when running in NAPI mode, the chip\r
+             generates a receive interrupt before the interface state is\r
+             up. The driver then disables rx interrupt and schedules the\r
+             polling function which fails because the interface is not up.\r
+             This polling function will not be called and no rx packets\r
+             will be processed.\r
+\r
+      Change: Added check for the return value of netif_rx_schedule_prep()\r
+              and will only disable rx interrupt if it returns success.\r
+\r
+      Impact: Receive code path in NAPI mode.\r
+\r
+\r
+   3. Problem: ethtool -r (restart autoneg) does not work on 5704S.\r
+\r
+      Cause: LM_SetupPhy does not restart autoneg if autoneg is already\r
+             set for 5704S.\r
+\r
+      Change: Added code to first disable autoneg and then reneable it.\r
+\r
+      Impact: Only affects ethtool -r for fiber NICs.\r
+\r
+\r
+   4. Problem: In some extremely rare situations, 5704 Copper NICs\r
+               may not link up after a PHY reset.\r
+\r
+      Cause: On some 5704 PHY cores, there is a small probability of\r
+             lock up after a PHY reset.\r
+\r
+      Change: Added code to detect PHY lock up after a PHY reset and\r
+              reset again if lock up is detected.\r
+\r
+      Impact: The added lock up detection and recovery code affects\r
+              driver reset and link down events where PHY resets are\r
+              performed.\r
+\r
+\r
+v6.2.2 (04/09/03)\r
+\r
+- Fixed the problem of intermittently using a MAC address of all zeros.\r
+- Added support for BASP in NAPI mode.\r
+- Added polling mode to support netdump.\r
+\r
+v6.2.1 (03/25/03)\r
+\r
+- Added NAPI.\r
+\r
+v6.2.0 (03/18/03)\r
+\r
+- Added support for 5788.\r
+- Changed locking functions into macros to avoid passing the flags.\r
+\r
+v6.0.3 (02/25/03)\r
+\r
+- Fixed the problem of 5704S not linking when it is set to autoneg. and the\r
+  link partner has autoneg. disabled.\r
+\r
+v6.0.2 (02/14/03)\r
+\r
+- Fixed the problem of T3_CHIP_ID_5705_A2 not defined in tigon3.h\r
+\r
+v6.0.1 (02/11/03)\r
+\r
+- Fixed some minor bugs in the adaptive coalescing logic.\r
+\r
+v6.0.0 (02/10/03)\r
+\r
+- Fixed another ASF problem that occurred when WOL was disabled in firmware\r
+  but enabled in the driver.\r
+\r
+- Added new device IDs for 5705 A2/A3 and made necessary changes to support\r
+  5705 A3.\r
+\r
+v5.0.22 (02/07/03)\r
+\r
+- Fixed the problem of ASF malfunction when the device is shutdown.\r
+\r
+v5.0.21 (02/06/03)\r
+\r
+- Fixed the problem of ifup (mii-tool) always detecting link down on 5704S.\r
+- Fixed the problem of high CPU utilization when receiving line-rate traffic\r
+  from Smartbits or Ixia by limiting the number of buffers allocated in the ISR.\r
+\r
+v5.0.20 (02/05/03)\r
+\r
+- Fixed a bad IP checksum problem in the 5702/03/04 TSO firmware.\r
+\r
+v5.0.19 (01/23/03)\r
+\r
+- Changed Makefile to include proper compiler switches for x86_64 architectures.\r
+- Fixed a bug in the adaptive coalescing function. Some variables were not\r
+  properly initialized after ifdown and ifup and this bug may cause\r
+  low performance especially when using jumbo frames.\r
+- Tweaked the adaptive coalescing parameters slightly to improve netperf\r
+  performance.\r
+\r
+v5.0.17 (01/10/03)\r
+\r
+- Made changes for 5705 A2.\r
+- Added autoneg. workaround for 5704S.\r
+\r
+v5.0.16 (01/03/03)\r
+\r
+- Fixed the hang problem on 5700 during ifdown.\r
+\r
+v5.0.15 (01/03/03)\r
+\r
+- Fixed some WOL issues.\r
+- Fixed TSO problems on 5702/03/04.\r
+- Fixed problems with the network_install dd images.\r
+\r
+v5.0.14 (12/19/02)\r
+\r
+- Made flow control work better.\r
+- Added 10Mbps limit for 5704 WOL.\r
+- Removed 5901 and 5705MFE support.\r
+\r
+v5.0.12 (12/12/02)\r
+\r
+- Added diagnostics ioctls.\r
+- Enabled flow control by default.\r
+\r
+v5.0.11 (12/06/02)\r
+\r
+- Fixed data corruption problem on 5705 with TSO enabled.\r
+- Fixed 5701 lockup during initialization.\r
+\r
+v5.0.10 (11/20/02)\r
+\r
+- Added support for 5705MFE and 5901.\r
+- Added TSO for 5705 A1.\r
+- Fixed ifconfig hang on Intel McKinley.\r
+\r
+v5.0.9  (11/08/02)\r
+\r
+- Made changes for 5705 A1 chips.\r
+\r
+v5.0.8  (11/05/02)\r
+\r
+- Fixed ASF problem on 5705.\r
+- Fixed problem with changing MAC address.\r
+- Added MTU change using ifconfig.\r
+- Fixed problem running on AMD X86_64 machines.\r
+\r
+v5.0.7  (10/11/02)\r
+\r
+- Fixed 5704S link related problems.\r
+- Improved performance slightly on some PCIX machines.\r
+- Fixed GEEPROM to allow full access to NVRAM.\r
+\r
+v5.0.6  (10/03/02)\r
+\r
+- Fixed problem of 5704S not linking up.\r
+- Added code to support autoneg in 5704S hardware.\r
+\r
+v5.0.5  (09/24/02)\r
+\r
+- Fine-tuned some parameters for improved performance.\r
+- Added TSO.\r
+- Fixed WOL problems on 5704.\r
+- Fixed the problem of not enabling ASF on the fly.\r
+- Fixed incorrect PCIX speed in proc file.\r
+- Added 5704S support.\r
+- Fixed incorrect PCIX speed in proc file.\r
+- Fixed the initialization failure on 5701 LOMs.\r
+\r
+v3.0.12 (08/22/02)\r
+\r
+- Fixed the problem of not loading on CIOBE A1.\r
+- Fixed intermittent hang problem when configuring 802.1q VLAN.\r
+\r
+v3.0.11 (08/21/02)\r
+\r
+- Added DIAG_SUSPEND/DIAG_RESUME ioctls.\r
+- Added some workarounds for 5705.\r
+- Added vlan tag size adjustment when receiving vlan tagged packets.\r
+\r
+v3.0.10 (08/07/02)\r
+\r
+- Fixed NVRAM write corruption.\r
+- Added check to not allow jumbo MTUs on 5705.\r
+- Added WOL on OEM 5703 Fiber LOM.\r
+\r
+v3.0.9 (08/05/02)\r
+\r
+- Added support for 5705.\r
+\r
+v3.0.8 (07/25/02)\r
+\r
+- Fixed VLAN problem with BASP.\r
+- Added new 5704 IDs.\r
+- Added support for 5702FE.\r
+\r
+v3.0.7 (07/17/02)\r
+\r
+- Changed to enable VLAN tag stripping only when VLAN or BASP is registered.\r
+- Fixed problem of sending bad zero-copy packets.\r
+- Added additional workaround for systems with AMD762.\r
+- Adjusted EEPROM delay loop.\r
+\r
+v3.0.6 (06/25/02)\r
+\r
+- Fixed an ASF failure.\r
+- Added 802.1Q VLAN\r
+- Added a locking scheme for PHY access.\r
+- Fixed an intermittent crash problem with fiber NICs.\r
+- Adjusted fiber autoneg. logic to work with 3Com 4900SX switch.\r
+- Added netif_carrier_on and netif_carrier_off.\r
+\r
+v3.0.5 (05/30/02)\r
+\r
+- Fixed occasional hang during load and unload.\r
+- Fixed non-zero statistics when stats_coalesce_ticks is 0.\r
+\r
+v3.0.4 (05/15/02)\r
+\r
+- Fixed 10Mbps line speed setting bug.\r
+- Fixed problem with jumbo packets.\r
+- Fixed a compile warning on Red Hat 7.3\r
+\r
+v3.0.3 (05/13/02)\r
+\r
+- Added support for ASF.\r
+- Added 64-bit counters for 64-bit machines.\r
+- Reduced code size.\r
+- Fixed intermittent VPD failures.\r
+\r
+v3.0.2 (05/03/02)\r
+\r
+- Fixed a bug on PCIX systems.\r
+\r
+v3.0.1 (05/02/02)\r
+\r
+- Added workaround for Intel ICH and ICH0 chipsets.\r
+- Fixed 5704 related problems.\r
+\r
+v3.0.0 (04/22/02)\r
+\r
+- Added 5704 support\r
+- Reduced some overhead in the upper/lower driver interface.\r
+\r
+v2.2.19 (04/10/02)\r
+\r
+- Fixed a panic problem on 5700 under heavy traffic on certain machines.\r
+- Reduced code size slightly.\r
+- Added necessary delays after changes to GPIO.\r
+\r
+v2.2.18 (04/03/02)\r
+\r
+- Added new OEM subsystem IDs.\r
+- Fixed some ethtool problems.\r
+\r
+v2.2.17 (04/02/02)\r
+\r
+- Adjusted some delay loops to avoid hangs during intermittent failures.\r
+\r
+v2.3.0 (03/29/02)\r
+\r
+- Special version with external memory and Mini ring support.\r
+\r
+v2.2.12 (03/27/02)\r
+\r
+- Minor fix for some fiber related issues.\r
+\r
+v2.2.11 (03/23/02)\r
+\r
+- Adjusted fiber autoneg scheme to be consistent with other Broadcom\r
+  drivers.\r
+\r
+v2.2.10 (03/21/02)\r
+\r
+- Changed Fiber LED to software control.\r
+- Fixed 4 GByte boundary check for 5700.\r
+\r
+v2.2.9 (03/13/02)\r
+\r
+- Fixed a hang problem on 5703S with cable disconnected.\r
+\r
+v2.2.8 (03/07/02)\r
+\r
+- More changes to fiber autonegotiation - interrupt with polling backup\r
+  for fiber link changes.\r
+\r
+v2.2.7 (03/06/02)\r
+\r
+- Made some changes to autonegotiation of fiber.\r
+\r
+v2.2.6 (03/05/02)\r
+\r
+- Added fix for 5703S.\r
+- Improved adaptive interrupt coalescing.\r
+- Fixed a problem in WOL.\r
+\r
+v2.2.5 (02/27/02)\r
+\r
+- Fixed a big endian problem.\r
+\r
+v2.2.4 (02/27/02)\r
+\r
+- Added new device IDs for 5703/5702.\r
+- Fixed parity error NMIs with 5703 on PCIX systems.\r
+- Added Ethernet@WireSpeed.\r
+\r
+v2.2.3 (02/07/02)\r
+\r
+- Fixed EEPROM corruption during repeated load/unload of the driver.\r
+- Changed driver to use polling for fiber link changes.\r
+\r
+v2.2.1 (01/23/02)\r
+\r
+- Increased eeprom timing delays for slower clocks.\r
+\r
+v2.2.0 (01/22/02)\r
+\r
+- First release for 5702/5703 A1.\r
+\r
+v2.0.34 (01/04/02)\r
+\r
+- Fixed data corruption problem on PCIX systems under heavy traffic.\r
+\r
+v2.0.32 (01/02/02)\r
+\r
+- No change.\r
+\r
+v2.0.31 (12/14/01)\r
+\r
+- Changed i/o accesses to use writel/readl macros.\r
+- Fixed problem when loading driver on an OEM LOM with no cable attached.\r
+- Fixed problem of setting IFF_ALLMULTI.\r
+- Changed to use pci_map_page to map the zero copy transmit fragments.\r
+\r
+v2.0.28 (11/05/01)\r
+\r
+- Added SIOCETHTOOL ioctl support.\r
+\r
+v2.0.27 (10/26/01)\r
+\r
+- Fixed a link up problem for an OEM LOM.\r
+\r
+v2.0.26 (10/25/01)\r
+\r
+- Added 5702 support.\r
+\r
+v2.0.25 (10/22/01)\r
+\r
+- Added Rx_Short_Fragments and other counters.\r
+- Added code to detect AMD762 Northbridge and enable PCI ordering on that chip.\r
+\r
+v2.0.24 (09/19/01)\r
+\r
+- Fixed intermittent link failures.\r
+\r
+v2.0.21 (09/14/01)\r
+\r
+- Fixed zero copy failure.\r
+\r
+v2.0.19 (09/11/01)\r
+\r
+- Fixed the problem of over reporting CRC errors.\r
+- Fixed the problem of late collisions in 1000Mbps half duplex.\r
+\r
+v2.0.18 (08/24/01)\r
+\r
+- Added same fix in 2.0.17 for the latest A3 chips.\r
+\r
+v2.0.17 (08/22/01)\r
+\r
+- Fixed a lock-up problem when loading fibre card with no cable attached.\r
+\r
+v2.0.16 (08/18/01)\r
+\r
+- Fixed a panic caused by an interrupt before the NIC is fully initialized.\r
+\r
+v2.0.15 (08/14/01)\r
+\r
+- Fixed a problem that caused unnecessary resets to the chip during\r
+heavy traffic.\r
+\r
+v2.0.14 (08/09/01)\r
+\r
+- Lowered core clock freq. in latest 5701 chip in 100Mbps WOL mode.\r
+\r
+v2.0.12 (08/02/01)\r
+\r
+- Fixed a 100Mbps fixed speed problem.\r
+- Fixed the accidental clearing of RX stats during link changes.\r
+- Added reentrancy protection in tasklet so that it will work on RH7.2 beta3.\r
+\r
+v2.0.11 (07/19/01)\r
+\r
+- Fixed some fiber autonegotiation problems.\r
+\r
+v2.0.10 (07/13/01)\r
+\r
+- Added promiscuous mode support.\r
+- Improved performance, especially on 5700 chips.\r
+\r
+v2.0.9 (07/04/01)\r
+\r
+- Fixed IA64 DMA alignment problem.\r
+\r
+v2.0.8 (07/03/01)\r
+\r
+- Fixed panic during ifdown.\r
+\r
+v2.0.7 (07/01/01)\r
+\r
+- Fixed problems with fibre cards.\r
+- Added 100Mbps WOL for 5701 B2 chip.\r
+\r
+v2.0.6 (06/22/01)\r
+\r
+- Improved adaptive receive interrupt coalescing.\r
+- Added LED blinking ioctl.\r
+- Added support for new boards.\r
+- Fixed hang problem when cable is not attached.\r
+\r
+v2.0.5 (06/18/01)\r
+\r
+- Some performance improvements.\r
+- Added adaptive receive interrupt coalescing.\r
+- Preliminary release for IA64.\r
+\r
+v2.0.4 (06/01/01)\r
+\r
+- Fixed a problem with multiple cards using jumbo frames.\r
+\r
+v2.0.3 (05/22/01)\r
+\r
+- Fixed panic during hotplug.\r
+- Fixed RPM error on Mandrake.\r
+\r
+v2.0.2 (05/21/01)\r
+\r
+- Fixed a spin lock problem.\r
+\r
+v2.0.1 (05/18/01)\r
+\r
+- Fixed memory leak when unloading driver.\r
+\r
+v1.5.6 (05/11/01)\r
+\r
+- Added additional OEM support.\r
+- Added Wake-On-LAN support.\r
+\r
+v1.5.4 (05/04/01)\r
+\r
+- Fixed interrupt and TX hung problem on 5701.\r
+- Added OEM strings.\r
+\r
+v1.5.3 (04/26/01)\r
+\r
+- Fixed parameter defaults.\r
+- Added /proc filesystem reporting.\r
+\r
+v1.5.2 (04/18/01)\r
+\r
+- Fixed bug in transmit IP checksum.\r
+\r
+v1.5.1 (04/15/01)\r
+\r
+- Added scatter/gather, HIGHMEM DMA, and IP transmit checksum offload for the\r
+  TUX kernel.\r
+- Added support of BCM5701.\r
+\r
+v1.5.0 (03/14/01)\r
+\r
+- Added Fibre transceiver support.\r
+\r
+v1.4.6 (02/14/01)\r
+\r
+- Fixed the problem of dropping VLAN tagged 802.2/802.3 frames.\r
+- Fixed Makefile to work in non Red Hat environments.\r
+- Fixed the problem of over-counting receive errors.\r
+\r
+v1.4.5 (01/31/01)\r
+\r
+- Added PCI-X support for BCM5700.\r
+- Fixed Jumbo frame problems by modifying some thresholds and increased\r
+Jumbo frame size to 9K.\r
+\r
+v1.4.4 (01/18/01)\r
+\r
+- Fixed the problem of transmit congestion during very heavy traffic in pre-\r
+2.4.0 kernels.\r
+\r
+v1.4.3 (01/10/01)\r
+\r
+- Changed driver to use new PCI DMA functions in 2.4 kernel.\r
+\r
+v1.4.2 (01/03/01)\r
+\r
+- Changed driver to use spin locks for SMP machines.\r
+- Added spin locks around PRIVATE ioctls for MII registers .\r
+\r
+v1.4.1 (12/26/00)\r
+\r
+- Made changes for B1 chips.\r
+\r
+v1.4.0 (12/19/00)\r
+\r
+- Made changes for 2.4.0 kernel.\r
+\r
+v1.3.8 (12/13/00)\r
+\r
+- Fixed the problem of setting a user assigned MAC address.\r
+- Added VLAN support for BASP.\r
+\r
+v1.3.7 (12/01/00)\r
+\r
+- Added code to handle BCM5401 B0 phy chips.\r
+\r
+v1.3.6 (11/22/00)\r
+\r
+- Fixed LED problems.\r
+\r
+v1.3.5 (11/21/00)\r
+\r
+- Fixed some flow control auto negotiation problems.\r
+\r
+v1.3.4 (11/17/00)\r
+\r
+- Fixed a problem of missing interrupts.\r
+- Resolved all fixed speed related problems.\r
+\r
+v1.3.3 (11/13/00)\r
+\r
+- Fixed the problem of memory allocation failure in some machines.\r
+\r
+v1.3.2 (11/09/00)\r
+\r
+- Made more changes regarding fixed speeds. Also removed manual selection\r
+  of 1000 Mbps.\r
+- Made a SRPM package.\r
+\r
+v1.03b (10/31/00)\r
+\r
+- Fixed problems #452, #441, #364, and other speed related problems in the\r
+  Lower Module.\r
+\r
+v1.03 (10/30/00)\r
+\r
+- Released Lower Module as tigon3.o.\r
+\r
+v1.02c (10/27/00)\r
+\r
+- Fixed the fixed speed problem in Lower Module.\r
+\r
+v1.02b (10/24/00)\r
+\r
+- Added new parameters for flow control settings.\r
+- Fixed problem with uninitialized statistics counters (problem #338).\r
+\r
+v1.02  (10/16/00)\r
+\r
+- Modified for B0 chips, should also work for other chips.\r
+- Reenabled TCP/UDP receive hardware checksums.\r
+\r
+v1.01b (10/09/00)\r
+\r
+- Changed driver to use pci* routines instead of pcibios* routines to obtain\r
+  the correct IRQ on some MP machines.\r
+- Resolved Problems #253, #257.\r
+\r
+v1.01 (09/27/00)\r
+\r
+- Added statistics collection function.\r
+- Added jumbo frames support.\r
+- Added MII related ioctl calls.\r
+- Disabled UDP/TCP receive checksum offload to workaround a memory corruption\r
+  problem in A1 chips.\r
+- Fixed interrupt sharing problem.\r
+\r
+v1.00 (09/13/00)\r
+\r
+-First release of the driver for BCM5700 A1 chips.\r
+\r
diff --git a/drivers/net/bcm5700/autoneg.c b/drivers/net/bcm5700/autoneg.c
new file mode 100644 (file)
index 0000000..d467f03
--- /dev/null
@@ -0,0 +1,438 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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:                                                                   */
+/******************************************************************************/
+
+#ifdef 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 --git a/drivers/net/bcm5700/autoneg.h b/drivers/net/bcm5700/autoneg.h
new file mode 100644 (file)
index 0000000..5d9be87
--- /dev/null
@@ -0,0 +1,418 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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 --git a/drivers/net/bcm5700/b57diag.c b/drivers/net/bcm5700/b57diag.c
new file mode 100644 (file)
index 0000000..e21fbe0
--- /dev/null
@@ -0,0 +1,774 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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.                 */
+/*                                                                            */
+/* ethtool -t selftest code.                                                  */
+/*                                                                            */
+/******************************************************************************/
+
+#include "mm.h"
+
+#ifdef NICE_SUPPORT
+#include "nicext.h"
+#endif
+
+#ifdef ETHTOOL_TEST
+
+typedef struct reg_entry
+{
+       LM_UINT16   offset;
+       LM_UINT16   flags;
+#define BCM5705_ONLY           1
+#define NOT_FOR_BCM5705                2
+#define NOT_FOR_BCM5788                4
+       LM_UINT32   read_mask;
+       LM_UINT32   write_mask;
+} reg_entry_t;
+
+typedef struct mem_entry
+{
+       LM_UINT32   offset;
+       LM_UINT32   len;
+} mem_entry_t;
+
+/* Returns 1 on success, 0 on failure */
+int
+b57_test_registers(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       int ret;
+       int i, bcm5705;
+       LM_UINT32 offset, read_mask, write_mask, val, save_val, read_val;
+       static reg_entry_t reg_tbl[] = {
+               /* MAC block */
+               { 0x0400, 0x0002, 0x00000000, 0x00ef6f8c },
+               { 0x0400, 0x0001, 0x00000000, 0x01ef6b8c },     /* 5705 */
+               { 0x0404, 0x0002, 0x03800107, 0x00000000 },
+               { 0x0404, 0x0001, 0x03800100, 0x00000000 },     /* 5705 */
+               { 0x0408, 0x0002, 0x00000000, 0x07c01400 },
+               { 0x0408, 0x0001, 0x00000000, 0x07c01000 },     /* 5705 */
+               { 0x040c, 0x0000, 0x00000000, 0xfff8007f },
+               { 0x0410, 0x0000, 0x00000000, 0x0000ffff },
+               { 0x0414, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0418, 0x0000, 0x00000000, 0x0000ffff },
+               { 0x041c, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0420, 0x0000, 0x00000000, 0x0000ffff },
+               { 0x0424, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0428, 0x0000, 0x00000000, 0x0000ffff },
+               { 0x042c, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0430, 0x0002, 0x00000000, 0xffffffff },
+               { 0x0430, 0x0001, 0x00000000, 0x0fff03ff },     /* 5705 */
+               { 0x0434, 0x0002, 0x00000000, 0x0fffffff },
+               { 0x0434, 0x0001, 0x00000000, 0x000001ff },     /* 5705 */
+               { 0x043c, 0x0000, 0x00000000, 0x0000ffff },
+               { 0x0454, 0x0000, 0x00000000, 0x00000010 },
+               { 0x045c, 0x0000, 0x00000000, 0x00000070 },
+               { 0x0464, 0x0000, 0x00000000, 0x00003fff },
+               { 0x0468, 0x0002, 0x00000000, 0x000007fc },
+               { 0x0468, 0x0001, 0x00000000, 0x000007dc },     /* 5705 */
+               { 0x0470, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0474, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0478, 0x0000, 0x00000000, 0xffffffff },
+               { 0x047c, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0480, 0x0002, 0x00000000, 0xffffffff },
+               { 0x0480, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x0484, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0488, 0x0002, 0x00000000, 0xffffffff },
+               { 0x0488, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x048c, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0490, 0x0002, 0x00000000, 0xffffffff },
+               { 0x0490, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x0494, 0x0000, 0x00000000, 0xffffffff },
+               { 0x0498, 0x0002, 0x00000000, 0xffffffff },
+               { 0x0498, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x049c, 0x0000, 0x00000000, 0xffffffff },
+               { 0x04a0, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04a0, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x04a4, 0x0000, 0x00000000, 0xffffffff },
+               { 0x04a8, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04a8, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x04ac, 0x0000, 0x00000000, 0xffffffff },
+               { 0x04b0, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04b0, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x04b4, 0x0000, 0x00000000, 0xffffffff },
+               { 0x04b8, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04b8, 0x0001, 0x00000000, 0xe7ffffff },     /* 5705 */
+               { 0x04bc, 0x0000, 0x00000000, 0xffffffff },
+               { 0x04c0, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04c4, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04c8, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04cc, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04d0, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04d4, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04d8, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04dc, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04e0, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04e4, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04e8, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04ec, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04f0, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04f4, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04f8, 0x0002, 0x00000000, 0xffffffff },
+               { 0x04fc, 0x0002, 0x00000000, 0xffffffff },
+               { 0x0500, 0x0002, 0x00000000, 0x000000f8 },
+               { 0x0500, 0x0001, 0x00000000, 0x00000008 },     /* 5705 */
+
+               /* Send Data Initiator Control Registers */
+               { 0x0c00, 0x0000, 0x00000000, 0x00000006 },
+               { 0x0c04, 0x0000, 0x00000004, 0x00000000 },
+               { 0x0c08, 0x0000, 0x00000000, 0x0000001b },
+               { 0x0c0c, 0x0002, 0x00000000, 0x00ffffff },
+               { 0x0c0c, 0x0001, 0x00000000, 0x00000001 },
+               { 0x0c80, 0x0000, 0x000003ff, 0x00000000 },
+               { 0x0c84, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0c88, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0c8c, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0c90, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0c94, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0c98, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0c9c, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0ca0, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0ca4, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0ca8, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cac, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cb0, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cb4, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cb8, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cbc, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cc0, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cc4, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cc8, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0ccc, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cd0, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cd4, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cd8, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0cdc, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x0ce0, 0x0001, 0x00000000, 0xffffffff },     /* 5705 */
+               { 0x0ce4, 0x0001, 0x00000000, 0xffffffff },     /* 5705 */
+               { 0x0ce8, 0x0001, 0x00000000, 0x00ffffff },     /* 5705 */
+               { 0x0cec, 0x0001, 0x00000000, 0x000efcf7 },     /* 5705 */
+               { 0x0cf0, 0x0001, 0x00000000, 0x0000ffff },     /* 5705 */
+               { 0x0cf4, 0x0001, 0x00000000, 0x20000000 },     /* 5705 */
+
+               /* SDC Control Registers */
+               { 0x1000, 0x0000, 0x00000000, 0x00000002 },
+               { 0x1008, 0x0001, 0x00000000, 0x40000000 },     /* 5705 */
+
+               /* Send BD Ring Selector Control Registers. */
+               { 0x1400, 0x0000, 0x00000000, 0x00000006 },
+               { 0x1404, 0x0000, 0x00000004, 0x00000000 },
+               { 0x1408, 0x0000, 0x0000ffff, 0x00000000 },
+               { 0x1440, 0x0000, 0x0000000f, 0x00000000 },
+               { 0x1444, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1448, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x144c, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1450, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1454, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1458, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x145c, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1460, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1464, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1468, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x146c, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1470, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1474, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x1478, 0x0002, 0x0000000f, 0x00000000 },
+               { 0x147c, 0x0002, 0x0000000f, 0x00000000 },
+
+               /* Send BD Inititor Control Registers.*/
+               { 0x1800, 0x0000, 0x00000000, 0x00000006 },
+               { 0x1804, 0x0000, 0x00000004, 0x00000000 },
+               { 0x1808, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x180c, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1810, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1814, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1818, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x181c, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1820, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1824, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1828, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x182c, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1830, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1834, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1838, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x183c, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1840, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x1844, 0x0002, 0xffffffff, 0x00000000 },
+
+               /* Send BD Completion Control Registers */
+               { 0x1c00, 0x0000, 0x00000000, 0x00000002 },
+
+               /* Receive List Placement Control Registers. */
+               { 0x2000, 0x0000, 0x00000000, 0x0000001e },
+               { 0x2004, 0x0000, 0x0000001c, 0x00000000 },
+               { 0x2010, 0x0002, 0x00000000, 0x00007fff },
+               { 0x2010, 0x0001, 0x00000000, 0x000060ff },     /* 5705 */
+               { 0x2014, 0x0000, 0x00000000, 0x00000001 },
+               { 0x2200, 0x0000, 0x000003ff, 0x00000000 },
+               { 0x2204, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2208, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x220c, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2210, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2214, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2218, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x221c, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2220, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2224, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2228, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x222c, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2230, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2234, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2238, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x223c, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2240, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2244, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x2248, 0x0002, 0x000003ff, 0x00000000 },
+               { 0x224c, 0x0000, 0x000003ff, 0x00000000 },
+               { 0x2250, 0x0000, 0x000003ff, 0x00000000 },
+               { 0x2254, 0x0000, 0x000003ff, 0x00000000 },
+               { 0x2258, 0x0002, 0x000003ff, 0x00000000 },
+
+               /* Receive Data and Receive BD Initiator Control Registers. */
+               { 0x2400, 0x0002, 0x00000000, 0x0000001e },
+               { 0x2400, 0x0001, 0x00000000, 0x0000001a },     /* 5705 */
+               { 0x2404, 0x0000, 0x0000001c, 0x00000000 },
+               { 0x2408, 0x0002, 0x00000000, 0x0000ffff },
+               { 0x2440, 0x0002, 0x00000000, 0xffffffff },
+               { 0x2444, 0x0002, 0x00000000, 0xffffffff },
+               { 0x2448, 0x0002, 0x00000000, 0x00000003 },
+               { 0x244c, 0x0002, 0x00000000, 0xffffffff },
+               { 0x2450, 0x0000, 0x00000000, 0xffffffff },
+               { 0x2454, 0x0000, 0x00000000, 0xffffffff },
+               { 0x2458, 0x0000, 0x00000000, 0xffff0002 },
+               { 0x245c, 0x0000, 0x00000000, 0xffffffff },
+               { 0x2470, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x2474, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x2478, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x2480, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x2484, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x2488, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x248c, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x2490, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x2494, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x2498, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x249c, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24a0, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24a4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24a8, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24ac, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24b0, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24b4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24b8, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24bc, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x24c0, 0x0000, 0xffffffff, 0x00000000 },
+       
+               /* Receive Data Completion Control Registers */
+               { 0x2800, 0x0000, 0x00000000, 0x00000002 },
+
+               /* Receive BD Initiator Control Registers. */
+               { 0x2c00, 0x0000, 0x00000000, 0x00000006 },
+               { 0x2c04, 0x0000, 0x00000004, 0x00000000 },
+               { 0x2c18, 0x0002, 0x00000000, 0xffffffff },
+               { 0x2c18, 0x0001, 0x00000000, 0x000003ff },     /* 5705 */
+               { 0x2c1c, 0x0002, 0x00000000, 0xffffffff },
+       
+               /* Receive BD Completion Control Registers. */
+               { 0x3000, 0x0000, 0x00000000, 0x00000006 },
+               { 0x3004, 0x0000, 0x00000004, 0x00000000 },
+               { 0x3008, 0x0002, 0x00000000, 0x000000ff },
+               { 0x300c, 0x0000, 0x00000000, 0x000001ff },
+
+               /* Host Coalescing Control Registers. */
+               { 0x3c00, 0x0002, 0x00000000, 0x00000004 },
+               { 0x3c00, 0x0001, 0x00000000, 0x000000f6 },     /* 5705 */
+               { 0x3c04, 0x0000, 0x00000004, 0x00000000 },
+               { 0x3c08, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c08, 0x0001, 0x00000000, 0x000003ff },     /* 5705 */
+               { 0x3c0c, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c0c, 0x0001, 0x00000000, 0x000003ff },     /* 5705 */
+               { 0x3c10, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c10, 0x0005, 0x00000000, 0x000000ff },     /* 5705 */
+               { 0x3c14, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c14, 0x0005, 0x00000000, 0x000000ff },     /* 5705 */
+               { 0x3c18, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c1c, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c20, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c20, 0x0005, 0x00000000, 0x000000ff },     /* 5705 */
+               { 0x3c24, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c24, 0x0005, 0x00000000, 0x000000ff },     /* 5705 */
+               { 0x3c28, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c30, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c34, 0x0002, 0x00000000, 0xffffffff },
+               { 0x3c38, 0x0000, 0x00000000, 0xffffffff },
+               { 0x3c3c, 0x0000, 0x00000000, 0xffffffff },
+               { 0x3c40, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x3c44, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x3c50, 0x0002, 0x00000000, 0x000000ff },
+               { 0x3c54, 0x0000, 0x00000000, 0x000000ff },
+               { 0x3c80, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3c80, 0x0001, 0x00000000, 0x000001ff },     /* 5705 */
+               { 0x3c84, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3c88, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3c8c, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3c90, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3c94, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3c98, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3c9c, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3ca0, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3ca4, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3ca8, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3cac, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3cb0, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3cb4, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3cb8, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3cbc, 0x0002, 0x00000000, 0x000007ff },
+               { 0x3cc0, 0x0000, 0x00000000, 0x000001ff },
+               { 0x3cc4, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cc8, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3ccc, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cd0, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cd4, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cd8, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cdc, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3ce0, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3ce4, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3ce8, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cec, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cf0, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cf4, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cf8, 0x0002, 0x00000000, 0x000001ff },
+               { 0x3cfc, 0x0002, 0x00000000, 0x000001ff },
+
+               /* Memory Arbiter Registers */
+               { 0x4000, 0x0002, 0x00000000, 0x001ffffe },
+               { 0x4000, 0x0001, 0x00000000, 0x38111e7e },
+               { 0x4004, 0x0002, 0x001ffffc, 0x00000000 },
+               { 0x4004, 0x0002, 0x00111dfc, 0x00000000 },
+               { 0x4008, 0x0000, 0x00000000, 0x001fffff },
+               { 0x400c, 0x0000, 0x00000000, 0x001fffff },
+
+               /* Buffer Manager Control Registers. */
+               { 0x4400, 0x0000, 0x00000000, 0x0000001c },
+               { 0x4404, 0x0000, 0x00000014, 0x00000000 },
+               { 0x4408, 0x0000, 0x00000000, 0x007fff80 },
+               { 0x440c, 0x0000, 0x00000000, 0x007fffff },
+               { 0x4410, 0x0000, 0x00000000, 0x0000003f },
+               { 0x4414, 0x0000, 0x00000000, 0x000001ff },
+               { 0x4418, 0x0000, 0x00000000, 0x000001ff },
+               { 0x4420, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x4428, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x442c, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x4430, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x4440, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x4448, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x444c, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x4450, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x4454, 0x0000, 0xffffffff, 0x00000000 },
+               { 0x4458, 0x0001, 0x00000000, 0x000001ff },     /* 5705 */
+       
+               { 0x4800, 0x0002, 0x00000000, 0x000003fe },
+               { 0x4800, 0x0001, 0x00000000, 0xc00003fe },     /* 5705 */
+               { 0x4804, 0x0000, 0x000003fc, 0x00000000 },
+               { 0x4c00, 0x0002, 0x00000000, 0x000003fc },
+               { 0x4c00, 0x0001, 0x00000000, 0x000007fc },     /* 5705 */
+               { 0x4c04, 0x0000, 0x000003fc, 0x00000000 },
+
+               /* Mailbox Registers */
+               { 0x5804, 0x0000, 0x00000000, 0xffffffff },
+               { 0x586c, 0x0000, 0x00000000, 0x000001ff },
+               { 0x5874, 0x0002, 0x00000000, 0x000001ff },
+               { 0x5884, 0x0000, 0x00000000, 0x000007ff },
+               { 0x5904, 0x0000, 0x00000000, 0x000001ff },
+               { 0x5984, 0x0002, 0x00000000, 0x000001ff },
+               { 0x5a04, 0x0000, 0x00000000, 0xffffffff },
+               { 0x5a0c, 0x0000, 0x00000000, 0xffffffff },
+
+               /* Flow Through Queues. */
+               { 0x5c14, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c24, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c34, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c44, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c54, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c64, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c74, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c84, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5c94, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5ca4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5cb4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5cc4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5cd4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5ce4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5cf4, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5d04, 0x0002, 0xffffffff, 0x00000000 },
+               { 0x5d14, 0x0002, 0xffffffff, 0x00000000 },
+               { 0xffff, 0x0000, 0x00000000, 0x00000000 },
+       };
+
+    if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
+               bcm5705 = 1;
+       }
+       else {
+               bcm5705 = 0;
+       }
+
+       ret = 1;
+       for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
+               if (bcm5705 && (reg_tbl[i].flags & NOT_FOR_BCM5705))
+                       continue;
+               if (!bcm5705 && (reg_tbl[i].flags & BCM5705_ONLY))
+                       continue;
+               if ((pDevice->Flags & BCM5788_FLAG) &&
+                       (reg_tbl[i].flags & NOT_FOR_BCM5788))
+                       continue;
+               offset = (LM_UINT32) reg_tbl[i].offset;
+               read_mask = reg_tbl[i].read_mask;
+               write_mask = reg_tbl[i].write_mask;
+
+               /* Save the original register content */
+               save_val = LM_RegRd(pDevice, offset);
+
+               /* Determine the read-only value. */
+               read_val = save_val & read_mask;
+
+               /* Write zero to the register, then make sure the read-only bits
+                  are not changed and the read/write bits are all zeros. */
+               LM_RegWr(pDevice, offset, 0, FALSE);
+
+               val = LM_RegRd(pDevice, offset);
+
+               /* Test the read-only and read/write bits. */
+               if (((val & read_mask) != read_val) ||
+                       (val & write_mask)) {
+
+                       ret = 0;
+                       LM_RegWr(pDevice, offset, save_val, FALSE);
+                       break;
+               }
+
+
+               /* Write ones to all the bits defined by RdMask and WrMask, then
+                  make sure the read-only bits are not changed and the
+                  read/write bits are all ones. */
+               LM_RegWr(pDevice, offset, read_mask | write_mask, FALSE);
+
+               val = LM_RegRd(pDevice, offset);
+
+               /* Test the read-only bits. */
+               if ((val & read_mask) != read_val) {
+                       ret = 0;
+                       LM_RegWr(pDevice, offset, save_val, FALSE);
+                       break;
+               }
+
+               /* Test the read/write bits. */
+               if ((val & write_mask) != write_mask) {
+                       ret = 0;
+                       LM_RegWr(pDevice, offset, save_val, FALSE);
+                       break;
+               }
+
+               LM_RegWr(pDevice, offset, save_val, FALSE);
+       }
+
+       return ret;
+}
+
+
+/* Returns 1 on success, 0 on failure */
+int
+b57_do_memory_test(LM_DEVICE_BLOCK *pDevice, LM_UINT32 start, LM_UINT32 size)
+{
+       const LM_UINT32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
+               0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa };
+       LM_UINT32 offset;
+       int i;
+
+       for (i = 0; i < sizeof(test_pattern)/sizeof(LM_UINT32); i++) {
+               for (offset = 0; offset < size; offset += 4) {
+
+                       LM_MemWrInd(pDevice, start + offset, test_pattern[i]);
+
+                       if (LM_MemRdInd(pDevice, start + offset) !=
+                               test_pattern[i]) {
+                               return 0;
+                       }
+               }
+       }
+       return 1;
+}
+
+/* Returns 1 on success, 0 on failure */
+int
+b57_test_memory(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       int ret = 0;
+       int i;
+       mem_entry_t *mem_tbl;
+
+       static mem_entry_t mem_tbl_570x[] = {
+               { 0x00000000, 0x01000},
+               { 0x00002000, 0x1c000},
+               { 0xffffffff, 0x00000}
+       };
+       static mem_entry_t mem_tbl_5705[] = {
+               { 0x00000100, 0x0000c},
+               { 0x00000200, 0x00008},
+               { 0x00000b50, 0x00400},
+               { 0x00004000, 0x00800},
+               { 0x00006000, 0x01000},
+               { 0x00008000, 0x02000},
+               { 0x00010000, 0x0e000},
+               { 0xffffffff, 0x00000}
+       };
+
+    if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
+               mem_tbl = mem_tbl_5705;
+       }
+       else {
+               mem_tbl = mem_tbl_570x;
+       }
+       for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
+               if ((ret = b57_do_memory_test(pDevice, mem_tbl[i].offset,
+                       mem_tbl[i].len)) == 0) {
+                       return ret;
+               }
+       }
+       
+       return ret;
+}
+
+#define EEPROM_SIZE 0x100
+
+/* Returns 1 on success, 0 on failure */
+int
+b57_test_nvram(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       LM_UINT32 buf[EEPROM_SIZE/4];
+       LM_UINT8 *pdata = (LM_UINT8 *) buf;
+       int i;
+       LM_UINT32 magic, csum;
+
+       for (i = 0; i < EEPROM_SIZE; i += 4) {
+               if (LM_NvramRead(pDevice, i, (LM_UINT32 *) (pdata + i)) !=
+                       LM_STATUS_SUCCESS) {
+                       break;
+               }
+       }
+       if (i < EEPROM_SIZE) {
+               return 0;
+       }
+
+        magic = MM_SWAP_BE32(buf[0]);
+       if (magic != 0x669955aa) {
+               return 0;
+       }
+
+       csum = ComputeCrc32(pdata, 16);
+       if(csum != MM_SWAP_LE32(buf[0x10/4])) {
+               return 0;
+       }
+
+       csum = ComputeCrc32(&pdata[0x74], 136);
+       if (csum != MM_SWAP_LE32(buf[0xfc/4])) {
+               return 0;
+       }
+
+       return 1;
+}
+
+/* Returns 1 on success, 0 on failure */
+int
+b57_test_link(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       LM_UINT32 phy_reg;
+
+       if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
+               if (REG_RD(pDevice, MacCtrl.Status) &
+                       (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DETECTED)) {
+                       return 1;
+               }
+               return 0;
+       }
+       LM_ReadPhy(pDevice, PHY_STATUS_REG, &phy_reg);
+       LM_ReadPhy(pDevice, PHY_STATUS_REG, &phy_reg);
+       if (phy_reg & PHY_STATUS_LINK_PASS)
+               return 1;
+       return 0;
+}
+
+#endif
+
+#if defined(ETHTOOL_TEST) || defined(NICE_SUPPORT)
+
+#if (LINUX_VERSION_CODE < 0x020605)
+#define pci_dma_sync_single_for_cpu pci_dma_sync_single
+#endif
+
+/* Returns 1 on success, 0 on failure */
+int
+b57_test_loopback(UM_DEVICE_BLOCK *pUmDevice, int testtype, int linespeed)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       struct sk_buff *skb, *rx_skb;
+       unsigned char *packet;
+       dma_addr_t map;
+       LM_UINT32 value32;
+       LM_UINT32 send_idx, rx_start_idx, rx_idx;
+       int num_pkts, pkt_size, i, ret;
+       LM_PACKET *pPacket;
+       UM_PACKET *pUmPacket;
+       T3_SND_BD *pSendBd;
+       T3_RCV_BD *pRcvBd;
+
+       ret = 0;
+       if (!pUmDevice->opened)
+               return ret;
+       LM_ResetAdapter(pDevice);
+       LM_HaltCpu(pDevice,T3_RX_CPU_ID | T3_TX_CPU_ID);
+       switch (testtype) {
+               case NICE_LOOPBACK_TESTTYPE_MAC:
+                       LM_EnableMacLoopBack(pDevice);
+                       break;
+               case NICE_LOOPBACK_TESTTYPE_PHY:
+                       LM_EnablePhyLoopBack(pDevice);
+                       break;
+               case NICE_LOOPBACK_TESTTYPE_EXT:
+                       LM_EnableExtLoopBack(pDevice, linespeed);
+
+                       /* Wait 4 seconds for link to come up. */
+                       for (i = 0; i < 4; i++) {
+                               LM_ReadPhy(pDevice, PHY_STATUS_REG, &value32);
+                               LM_ReadPhy(pDevice, PHY_STATUS_REG, &value32);
+                               if (value32 & PHY_STATUS_LINK_PASS) {
+                                       LM_SetupPhy(pDevice);
+                                       break;
+                               }
+                               MM_Sleep(pDevice,1000);
+                       }
+                       if (!(value32 & PHY_STATUS_LINK_PASS))
+                               return ret;
+       }
+       pkt_size = 1514;
+       skb = dev_alloc_skb(pkt_size);
+       packet = skb_put(skb, pkt_size);
+       memcpy(packet, pDevice->NodeAddress, 6);
+       memset(packet + 6, 0x0, 8);
+
+       for (i = 14; i < pkt_size; i++)
+               packet[i] = (unsigned char) (i & 0xff);
+
+       map = pci_map_single(pUmDevice->pdev, skb->data, pkt_size,
+               PCI_DMA_TODEVICE);
+
+       REG_WR(pDevice, HostCoalesce.Mode,
+               pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
+                       HOST_COALESCE_NOW);
+       MM_Wait(10);
+       rx_start_idx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+
+       send_idx = 0;
+       num_pkts = 0;
+       pSendBd = &pDevice->pSendBdVirt[send_idx];
+       if (pDevice->Flags & NIC_SEND_BD_FLAG) {
+               T3_64BIT_HOST_ADDR HostAddr;
+
+               MM_SetT3Addr(&HostAddr, map);
+               MM_MEMWRITEL(&(pSendBd->HostAddr.High), HostAddr.High);
+               MM_MEMWRITEL(&(pSendBd->HostAddr.Low), HostAddr.Low);
+               MM_MEMWRITEL(&(pSendBd->u1.Len_Flags),
+                            (pkt_size << 16) | SND_BD_FLAG_END);
+               send_idx++;
+               num_pkts++;
+               MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, send_idx);
+               if (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) {
+                       MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low,
+                               send_idx);
+               }
+               MB_REG_RD(pDevice, Mailbox.SendNicProdIdx[0].Low);
+       }
+       else {
+               MM_SetT3Addr(&pSendBd->HostAddr, map);
+                pSendBd->u1.Len_Flags = (pkt_size << 16) | SND_BD_FLAG_END;
+               MM_WMB();
+               send_idx++;
+               num_pkts++;
+               MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, send_idx);
+               if (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) {
+                       MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low,
+                               send_idx);
+               }
+               MB_REG_RD(pDevice, Mailbox.SendHostProdIdx[0].Low);
+       }
+
+       MM_Wait(100);
+
+       REG_WR(pDevice, HostCoalesce.Mode,
+               pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
+                       HOST_COALESCE_NOW);
+
+       MM_Sleep(pDevice, 1000);
+
+       pci_unmap_single(pUmDevice->pdev, map, pkt_size, PCI_DMA_TODEVICE);
+       dev_kfree_skb_irq(skb);
+
+       if (pDevice->pStatusBlkVirt->Idx[0].SendConIdx != send_idx) {
+               goto loopback_test_done;
+       }
+
+       rx_idx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+       if (rx_idx != rx_start_idx + num_pkts) {
+               goto loopback_test_done;
+       }
+
+       pRcvBd = &pDevice->pRcvRetBdVirt[rx_start_idx];
+       pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) +
+               MM_UINT_PTR(pRcvBd->Opaque));
+
+       pUmPacket = (UM_PACKET *) pPacket;
+
+       if (pRcvBd->ErrorFlag &&
+               pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) {
+               goto loopback_test_done;
+       }
+       if ((pRcvBd->Len - 4) != pkt_size) {
+               goto loopback_test_done;
+       }
+       rx_skb = pUmPacket->skbuff;
+
+       pci_dma_sync_single_for_cpu(pUmDevice->pdev,
+               pci_unmap_addr(pUmPacket, map[0]),
+               pPacket->u.Rx.RxBufferSize,
+               PCI_DMA_FROMDEVICE);
+
+       for (i = 14; i < pkt_size; i++) {
+               if (*(rx_skb->data + i) != (unsigned char) (i & 0xff)) {
+                       goto loopback_test_done;
+               }
+       }
+       ret = 1;
+
+loopback_test_done:
+       switch (testtype) {
+               case NICE_LOOPBACK_TESTTYPE_MAC:
+                       LM_DisableMacLoopBack(pDevice);
+                       break;
+               case NICE_LOOPBACK_TESTTYPE_PHY:
+                       LM_DisablePhyLoopBack(pDevice);
+                       break;
+               case NICE_LOOPBACK_TESTTYPE_EXT:
+                       LM_DisableExtLoopBack(pDevice);
+                       break;
+       }
+       return ret;
+}
+#endif
+
diff --git a/drivers/net/bcm5700/b57proc.c b/drivers/net/bcm5700/b57proc.c
new file mode 100644 (file)
index 0000000..fd3bce4
--- /dev/null
@@ -0,0 +1,482 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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 int bcm5700_open(struct net_device *dev);
+
+extern uint64_t bcm5700_crc_count(PUM_DEVICE_BLOCK pUmDevice);
+extern uint64_t bcm5700_rx_err_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";
+
+int bcm5700_proc_create_dev(struct net_device *dev);
+int bcm5700_proc_remove_dev(struct net_device *dev);
+
+static int bcm5700_netdev_event(struct notifier_block * this, unsigned long event, void * ptr)
+{
+       struct net_device * event_dev = (struct net_device *)ptr;
+
+       if (event == NETDEV_CHANGENAME) {
+               if (event_dev->open == bcm5700_open) {
+                       bcm5700_proc_remove_dev(event_dev);
+                       bcm5700_proc_create_dev(event_dev);
+               }
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block bcm5700_netdev_notifier = {
+       .notifier_call = bcm5700_netdev_event
+};
+
+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;
+       }
+       register_netdevice_notifier(&bcm5700_netdev_notifier);
+       return 0;
+}
+
+int
+bcm5700_proc_remove_notifier(void)
+{
+       unregister_netdevice_notifier(&bcm5700_netdev_notifier);
+       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->TbiFlags & ENABLE_TBI_FLAG) {
+               strcpy(str, "1000full");
+               return;
+       }
+       if (pDevice->PhyFlags & PHY_IS_FIBER) {
+               if (pDevice->RequestedDuplexMode != LM_DUPLEX_MODE_HALF)
+                       strcpy(str, "1000full");
+               else
+                       strcpy(str, "1000half");
+               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->TbiFlags & ENABLE_TBI_FLAG) {
+               if(pDevice->DisableAutoNeg == FALSE ||
+                       pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) {
+                       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);
+       if( pDevice->IPMICodeVer[0] != 0 )
+               len += sprintf(page+len, "ASF_IPMI_Version\t\t%s\n", pDevice->IPMICodeVer);
+       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 T3_JUMBO_RCV_RCB_ENTRY_COUNT
+       if ((dev->mtu > 1500) && !T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
+               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)));
+       }
+#endif
+       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 = (unsigned long) 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 = (unsigned long) bcm5700_rx_err_count(pUmDevice);
+       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));
+
+#ifdef BCM_NIC_SEND_BD
+       len += sprintf(page+len, "NIC_Tx_BDs\t\t\t%s\n",
+               (pDevice->Flags & NIC_SEND_BD_FLAG) ? on_str : off_str);
+#endif
+       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);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+       len += sprintf(page+len, "Rx_Jumbo_Desc_Count\t\t%u\n",
+               pDevice->RxJumboDescCnt);
+#endif
+#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);
+
+#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 --git a/drivers/net/bcm5700/b57um.c b/drivers/net/bcm5700/b57um.c
new file mode 100644 (file)
index 0000000..78af33b
--- /dev/null
@@ -0,0 +1,5659 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2005 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[] = "8.3.14a";
+char bcm5700_date[] = "(11/2/05)";
+
+#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};
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+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. */
+#endif
+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 };
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+#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 };
+#endif
+
+#ifdef BCM_INT_COAL
+#ifdef BCM_NAPI_RXPOLL
+static unsigned int adaptive_coalesce[MAX_UNITS] =
+       {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#else
+static unsigned int adaptive_coalesce[MAX_UNITS] =
+       {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+#endif
+
+#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
+#ifdef BCM_TSO
+static int enable_tso[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+#endif
+#ifdef BCM_NIC_SEND_BD
+static int nic_tx_bd[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#endif
+#ifdef BCM_ASF
+static int vlan_tag_mode[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#endif
+static int delay_link[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static int disable_d3hot[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+static int disable_msi[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static int bcm_msi_chipset_bug = 0;
+#endif
+
+#define BCM_TIMER_GRANULARITY  (1000000 / HZ)
+
+/* 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
+
+#if (LINUX_VERSION_CODE < 0x020411)
+#ifndef __devexit_p
+#define __devexit_p(x) x
+#endif
+#endif
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(license)
+#endif
+
+#ifndef IRQ_RETVAL
+typedef void irqreturn_t;
+#define IRQ_RETVAL(x)
+#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 < 0x02040d)
+
+#if (LINUX_VERSION_CODE >= 0x020409) && defined(RED_HAT_LINUX_KERNEL)
+
+#define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL)
+#define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL)
+
+#else
+/* pci_set_dma_mask is using dma_addr_t */
+
+#define BCM_32BIT_DMA_MASK ((dma_addr_t) 0xffffffff)
+#define BCM_64BIT_DMA_MASK ((dma_addr_t) 0xffffffff)
+
+#endif
+
+#else /* (LINUX_VERSION_CODE < 0x02040d) */
+
+#define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL)
+#define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL)
+#endif
+
+#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 < 0x020547)
+#define pci_set_consistent_dma_mask(pdev, mask) (0)
+#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
+
+#define BCM5700_LOCK(pUmDevice, flags)                                 \
+       if ((pUmDevice)->do_global_lock) {                              \
+               spin_lock_irqsave(&(pUmDevice)->global_lock, flags);    \
+       }
+
+#define BCM5700_UNLOCK(pUmDevice, flags)                               \
+       if ((pUmDevice)->do_global_lock) {                              \
+               spin_unlock_irqrestore(&(pUmDevice)->global_lock, flags);\
+       }
+
+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);
+       }
+}
+
+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 at broadcom dot com> and Gary Zambrano <zambrano at broadcom dot com>");
+MODULE_DESCRIPTION("BCM5700 Driver");
+MODULE_LICENSE("GPL");
+
+#if (LINUX_VERSION_CODE < 0x020605)
+
+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");
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+MODULE_PARM(mtu, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+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");
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+MODULE_PARM(rx_jumbo_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+#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
+#ifdef BCM_TSO
+MODULE_PARM(enable_tso, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+#ifdef BCM_NIC_SEND_BD
+MODULE_PARM(nic_tx_bd, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+#ifdef BCM_ASF
+MODULE_PARM(vlan_tag_mode, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+MODULE_PARM(delay_link, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(disable_d3hot, "1-" __MODULE_STRING(MAX_UNITS) "i");
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+MODULE_PARM(disable_msi, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+
+#else /* parms*/
+
+#if (LINUX_VERSION_CODE >= 0x020605) && (LINUX_VERSION_CODE < 0x02060a)
+
+static int var;
+
+#define numvar var
+
+#endif
+
+#if (LINUX_VERSION_CODE >= 0x2060a)
+
+#define numvar NULL
+
+#endif
+
+module_param_array(line_speed, int, numvar, 0);
+module_param_array(auto_speed, int, numvar, 0);
+module_param_array(full_duplex, int, numvar, 0);
+module_param_array(rx_flow_control, int, numvar, 0);
+module_param_array(tx_flow_control, int, numvar, 0);
+module_param_array(auto_flow_control, int, numvar, 0);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+module_param_array(mtu, int, numvar, 0);
+#endif
+module_param_array(tx_checksum, int, numvar, 0);
+module_param_array(rx_checksum, int, numvar, 0);
+module_param_array(scatter_gather, int, numvar, 0);
+module_param_array(tx_pkt_desc_cnt, int, numvar, 0);
+module_param_array(rx_std_desc_cnt, int, numvar, 0);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+module_param_array(rx_jumbo_desc_cnt, int, numvar, 0);
+#endif
+#ifdef BCM_INT_COAL
+module_param_array(adaptive_coalesce, int, numvar, 0);
+module_param_array(rx_coalesce_ticks, int, numvar, 0);
+module_param_array(rx_max_coalesce_frames, int, numvar, 0);
+module_param_array(tx_coalesce_ticks, int, numvar, 0);
+module_param_array(tx_max_coalesce_frames, int, numvar, 0);
+module_param_array(stats_coalesce_ticks, int, numvar, 0);
+#endif
+#ifdef BCM_WOL
+module_param_array(enable_wol, int, numvar, 0);
+#endif
+#ifdef BCM_TSO
+module_param_array(enable_tso, int, numvar, 0);
+#endif
+#ifdef BCM_NIC_SEND_BD
+module_param_array(nic_tx_bd, int, numvar, 0);
+#endif
+#ifdef BCM_ASF
+module_param_array(vlan_tag_mode, int, numvar, 0);
+#endif
+module_param_array(delay_link, int, numvar, 0);
+module_param_array(disable_d3hot, int, numvar, 0);
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+module_param_array(disable_msi, int, numvar, 0);
+#endif
+
+
+#endif /* params */
+
+
+#endif
+
+#define RUN_AT(x) (jiffies + (x))
+
+char kernel_version[] = UTS_RELEASE;
+
+#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
+
+
+int bcm5700_open(struct net_device *dev);
+STATIC void bcm5700_timer(unsigned long data);
+STATIC void bcm5700_stats_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 irqreturn_t 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_do_rx_mode(struct net_device *dev);
+STATIC void bcm5700_set_rx_mode(struct net_device *dev);
+STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p);
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu);
+#endif
+#ifdef BCM_NAPI_RXPOLL
+STATIC int bcm5700_poll(struct net_device *dev, int *budget);
+#endif
+STATIC int replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice, int max);
+STATIC int bcm5700_freemem(struct net_device *dev);
+#ifdef NICE_SUPPORT
+STATIC int bcm5700_freemem2(UM_DEVICE_BLOCK *pUmDevice, int index);
+#endif
+#ifdef BCM_INT_COAL
+#ifndef BCM_NAPI_RXPOLL
+STATIC int bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice);
+#endif
+#endif
+STATIC void bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice);
+STATIC int bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice);
+#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(UM_DEVICE_BLOCK *pUmDevice, int *param,
+       char *param_name, int min, int max, int deflt);
+
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+STATIC void poll_bcm5700(struct net_device *dev);
+#endif
+
+/* A list of all installed bcm5700 devices. */
+static struct net_device *root_tigon3_dev = NULL;
+
+#if defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) ||defined(CONFIG_PPC64)
+
+#ifdef NICE_SUPPORT
+#if (LINUX_VERSION_CODE < 0x20500)
+extern int register_ioctl32_conversion(unsigned int cmd,
+       int (*handler)(unsigned int, unsigned int, unsigned long,
+       struct file *));
+int unregister_ioctl32_conversion(unsigned int cmd);
+#else
+#include <linux/ioctl32.h>
+#endif
+
+#define BCM_IOCTL32 1
+
+atomic_t bcm5700_load_count = ATOMIC_INIT(0);
+
+static int
+bcm5700_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg,
+       struct file *filep)
+{
+       struct ifreq rq;
+       struct net_device *tmp_dev = root_tigon3_dev;
+       int ret;
+       struct nice_req* nrq;
+       struct ifreq_nice32 {
+               char ifnr_name[16];
+               __u32 cmd;
+               __u32 nrq1;
+               __u32 nrq2;
+               __u32 nrq3;
+       } nrq32;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       if (mm_copy_from_user(&nrq32, (char *) arg, 32))
+               return -EFAULT;
+
+       memcpy(rq.ifr_name, nrq32.ifnr_name, 16);
+
+       nrq = (struct nice_req*) &rq.ifr_ifru;
+       nrq->cmd = nrq32.cmd;
+       if (nrq->cmd == NICE_CMD_GET_STATS_BLOCK) {
+               nrq->nrq_stats_useraddr = (void *) ((__u64) nrq32.nrq1);
+               nrq->nrq_stats_size = nrq32.nrq2;
+       }
+       else {
+               memcpy(&nrq->nrq_speed, &nrq32.nrq1, 12);
+       }
+       while (tmp_dev) {
+               if (strcmp(rq.ifr_name, tmp_dev->name) == 0) {
+                       ret = bcm5700_ioctl(tmp_dev, &rq, cmd);
+                       if (ret == 0) {
+                               if (nrq->cmd == NICE_CMD_GET_STATS_BLOCK)
+                                       return ret;
+
+                               memcpy(&nrq32.nrq1, &nrq->nrq_speed, 12);
+                               if (mm_copy_to_user((char *) arg, &nrq32, 32))
+                                       return -EFAULT;
+                       }
+                       return ret;
+               }
+               tmp_dev = ((UM_DEVICE_BLOCK *)(tmp_dev->priv))->next_module;
+       }
+       return -ENODEV;
+}
+#endif /* NICE_SUPPORT */
+#endif
+
+typedef enum {
+       BCM5700A6 = 0,
+       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,
+       NC1020,
+       NC150T,
+       NC7760,
+       NC7761,
+       NC7770,
+       NC7771,
+       NC7780,
+       NC7781,
+       NC7772,
+       NC7782,
+       NC7783,
+       NC320T,
+       NC320I,
+       NC325I,
+       NC324I,
+       NC326I,
+       BCM5704CIOBE,
+       BCM5704,
+       BCM5704S,
+       BCM5705,
+       BCM5705M,
+       BCM5705F,
+       BCM5901,
+       BCM5782,
+       BCM5788,
+       BCM5789,
+       BCM5750,
+       BCM5750M,
+       BCM5720,
+       BCM5751,
+       BCM5751M,
+       BCM5751F,
+       BCM5721,
+       BCM5753,
+       BCM5753M,
+       BCM5753F,
+       BCM5781,
+       BCM5752,
+       BCM5752M,
+       BCM5714,
+       BCM5780,
+       BCM5780S,
+       BCM5715,
+       BCM5903M
+} board_t;
+
+
+/* indexed by board_t, above */
+static struct {
+       char *name;
+} board_info[] __devinitdata = {
+       { "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 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" },
+       { "HP NC6770 Gigabit Server Adapter" },
+       { "NC1020 HP ProLiant Gigabit Server Adapter 32 PCI" },
+       { "HP ProLiant NC 150T PCI 4-port Gigabit Combo Switch Adapter" },
+       { "HP NC7760 Gigabit Server Adapter" },
+       { "HP NC7761 Gigabit Server Adapter" },
+       { "HP NC7770 Gigabit Server Adapter" },
+       { "HP NC7771 Gigabit Server Adapter" },
+       { "HP NC7780 Gigabit Server Adapter" },
+       { "HP NC7781 Gigabit Server Adapter" },
+       { "HP NC7772 Gigabit Server Adapter" },
+       { "HP NC7782 Gigabit Server Adapter" },
+       { "HP NC7783 Gigabit Server Adapter" },
+       { "HP ProLiant NC 320T PCI Express Gigabit Server Adapter" },
+       { "HP ProLiant NC 320i PCI Express Gigabit Server Adapter" },
+       { "HP NC325i Integrated Dual Port PCI Express Gigabit Server Adapter" },
+       { "HP NC324i Integrated Dual Port PCI Express Gigabit Server Adapter" },
+       { "HP NC326i Integrated Dual Port PCI Express 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 570x 10/100 Integrated Controller" },
+       { "Broadcom BCM5901 100Base-TX" },
+       { "Broadcom NetXtreme Gigabit Ethernet for hp" },
+       { "Broadcom BCM5788 NetLink 1000Base-T" },
+       { "Broadcom BCM5789 NetLink 1000Base-T PCI Express" },
+       { "Broadcom BCM5750 1000Base-T PCI" },
+       { "Broadcom BCM5750M 1000Base-T PCI" },
+       { "Broadcom BCM5720 1000Base-T PCI" },
+       { "Broadcom BCM5751 1000Base-T PCI Express" },
+       { "Broadcom BCM5751M 1000Base-T PCI Express" },
+       { "Broadcom BCM5751F 100Base-TX PCI Express" },
+       { "Broadcom BCM5721 1000Base-T PCI Express" },
+       { "Broadcom BCM5753 1000Base-T PCI Express" },
+       { "Broadcom BCM5753M 1000Base-T PCI Express" },
+       { "Broadcom BCM5753F 100Base-TX PCI Express" },
+       { "Broadcom BCM5781 NetLink 1000Base-T PCI Express" },
+       { "Broadcom BCM5752 1000Base-T PCI Express" },
+       { "Broadcom BCM5752M 1000Base-T PCI Express" },
+       { "Broadcom BCM5714 1000Base-T " },
+       { "Broadcom BCM5780 1000Base-T" },
+       { "Broadcom BCM5780S 1000Base-SX" },
+       { "Broadcom BCM5715 1000Base-T " },
+       { "Broadcom BCM5903M Gigabit Ethernet " },
+       { 0 }
+       };
+
+static struct pci_device_id bcm5700_pci_tbl[] __devinitdata = {
+       {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, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
+       {0x14e4, 0x16c7, 0x0e11, 0xca, 0, 0, NC7771 },
+       {0x14e4, 0x16c7, 0x0e11, 0xcb, 0, 0, NC7781 },
+       {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, 0x1649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
+       {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, 0x0e11, 0x00e3, 0, 0, NC7761 },
+       {0x14e4, 0x1653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
+       {0x14e4, 0x1654, 0x0e11, 0x00e3, 0, 0, NC7761 },
+       {0x14e4, 0x1654, 0x103c, 0x3100, 0, 0, NC1020 },
+       {0x14e4, 0x1654, 0x103c, 0x3226, 0, 0, NC150T },
+       {0x14e4, 0x1654, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
+       {0x14e4, 0x165d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
+       {0x14e4, 0x165e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
+       {0x14e4, 0x166e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705F },
+       {0x14e4, 0x1696, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5782 },
+       {0x14e4, 0x169c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5788 },
+       {0x14e4, 0x169d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5789 },
+       {0x14e4, 0x170d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
+       {0x14e4, 0x170e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
+       {0x14e4, 0x1676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750 },
+       {0x14e4, 0x167c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750M },
+       {0x14e4, 0x1677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751 },
+       {0x14e4, 0x167d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751M },
+       {0x14e4, 0x167e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751F },
+       {0x14e4, 0x1658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5720 },
+       {0x14e4, 0x1659, 0x103c, 0x7031, 0, 0, NC320T },
+       {0x14e4, 0x1659, 0x103c, 0x7032, 0, 0, NC320T },
+       {0x14e4, 0x166a, 0x103c, 0x7035, 0, 0, NC325I },
+       {0x14e4, 0x166b, 0x103c, 0x7036, 0, 0, NC325I },
+       {0x14e4, 0x1668, 0x103c, 0x7039, 0, 0, NC324I },
+       {0x14e4, 0x1669, 0x103c, 0x703a, 0, 0, NC324I },
+       {0x14e4, 0x1678, 0x103c, 0x703e, 0, 0, NC326I },
+       {0x14e4, 0x1679, 0x103c, 0x703c, 0, 0, NC326I },
+       {0x14e4, 0x1659, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5721 },
+       {0x14e4, 0x16f7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753 },
+       {0x14e4, 0x16fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753M },
+       {0x14e4, 0x16fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753F },
+       {0x14e4, 0x16dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5781 },
+       {0x14e4, 0x1600, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752 },
+       {0x14e4, 0x1601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752M },
+       {0x14e4, 0x1668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5714 },
+       {0x14e4, 0x166a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780 },
+       {0x14e4, 0x166b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780S },
+       {0x14e4, 0x1678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5715 },
+       {0x14e4, 0x16ff, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5903M },
+       {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);
+extern int bcm5700_proc_remove_notifier(void);
+#endif
+
+#if (LINUX_VERSION_CODE >= 0x2060a)
+       static struct pci_device_id pci_AMD762id[]={
+               { PCI_DEVICE(PCI_VENDOR_ID_AMD,
+                       PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+               { }
+       };
+#endif
+
+/*******************************************************************************
+ *******************************************************************************
+*/
+
+int get_csum_flag(LM_UINT32 ChipRevId)
+{
+        return NETIF_F_IP_CSUM;
+}
+
+/*******************************************************************************
+ *******************************************************************************
+
+   This function returns true if the device passed to it is attached to an
+   ICH-ICH4. If the chip is not attached to an ICH, or is attached to an ICH5
+   or newer, it returns false.
+
+   This function determines which bridge it is attached to by scaning the pci
+   bus looking for bridge chips (hdr_type=1). When a bridge chip is detected,
+   the bridge's subordinate's secondary bus number is compared with this
+   devices bus number. If they match, then the device is attached to this
+   bridge. The bridge's device id is compared to a list of known device ids for
+   ICH-ICH4. Since many older ICH's (ICH2-ICH7) share the same device id, the
+   chip revision must also be checked to determine if the chip is older than an
+   ICH5.
+
+   To scan the bus, one of two functions is used depending on the kernel
+   version. For 2.4 kernels, the pci_find_device function is used. This
+   function has been depricated in the 2.6 kernel and replaced with the
+   fucntion pci_get_device. The macro walk_pci_bus determines which function to
+   use when the driver is built.
+*/
+
+#if (LINUX_VERSION_CODE >= 0x2060a)
+#define walk_pci_bus(d)                while ((d = pci_get_device( \
+                                       PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+
+#define unwalk_pci_bus(d)      pci_dev_put(d)
+
+#else
+#define walk_pci_bus(d)                while ((d = pci_find_device( \
+                                       PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+#define unwalk_pci_bus(d)
+
+#endif
+
+#define ICH5_CHIP_VERSION      0xc0
+
+static struct pci_device_id pci_ICHtable[] = {
+       {0x8086, 0x2418}, /* PCI_DEVICE_ID_INTEL_82801AA_8  */
+       {0x8086, 0x2428}, /* PCI_DEVICE_ID_INTEL_82801AB_8  */
+       {0x8086, 0x244e}, /* PCI_DEVICE_ID_INTEL_82801BA_6  */
+       {0x8086, 0x2448}, /* PCI_DEVICE_ID_INTEL_82801BA_11 */
+       {0, 0}
+};
+
+int attached_to_ICH4_or_older( struct pci_dev *pdev)
+{
+       struct pci_dev *tmp_pdev = NULL;
+       struct pci_device_id *ich_table;
+       u8 chip_rev;
+
+       walk_pci_bus (tmp_pdev) {
+               if ((tmp_pdev->hdr_type == 1) &&
+                  (tmp_pdev->subordinate != NULL) &&
+                  (tmp_pdev->subordinate->secondary == pdev->bus->number)) {
+
+                       ich_table = pci_ICHtable;
+
+                       while (ich_table->vendor) {
+                               if ((ich_table->vendor == tmp_pdev->vendor) &&
+                                   (ich_table->device == tmp_pdev->device)) {
+
+                                       pci_read_config_byte( tmp_pdev,
+                                               PCI_REVISION_ID, &chip_rev);
+
+                                       if (chip_rev < ICH5_CHIP_VERSION) {
+                                               unwalk_pci_bus( tmp_pdev);
+                                               return 1;
+                                       }
+                               }
+                               ich_table++;
+                       }
+               }
+       }
+       return 0;
+}
+
+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 */
+#if (LINUX_VERSION_CODE >= 0x20600)
+       dev = alloc_etherdev(sizeof(*pUmDevice));
+#else
+       dev = init_etherdev(NULL, sizeof(*pUmDevice));
+#endif
+       if (dev == NULL) {
+               printk (KERN_ERR "%s: unable to alloc new ethernet\n",
+                       bcm5700_driver);
+               return -ENOMEM;
+       }
+       SET_MODULE_OWNER(dev);
+#if (LINUX_VERSION_CODE >= 0x20600)
+       SET_NETDEV_DEV(dev, &pdev->dev);
+#endif
+       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, BCM_64BIT_DMA_MASK) == 0) {
+               pUmDevice->using_dac = 1;
+               if (pci_set_consistent_dma_mask(pdev, BCM_64BIT_DMA_MASK) != 0)
+               {
+                       printk(KERN_ERR "pci_set_consistent_dma_mask failed\n");
+                       pci_release_regions(pdev);
+                       goto err_out;
+               }
+       }
+       else if (pci_set_dma_mask(pdev, BCM_32BIT_DMA_MASK) == 0) {
+               pUmDevice->using_dac = 0;
+       }
+       else {
+               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->Flags = 0;
+       pDevice->FunctNum = PCI_FUNC(pUmDevice->pdev->devfn);
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+       if (board_idx < MAX_UNITS) {
+               bcm5700_validate_param_range(pUmDevice, &mtu[board_idx], "mtu", 1500, 9000, 1500);
+               dev->mtu = mtu[board_idx];
+       }
+#endif
+       /* If we're attached to an ICH4 or older, we may need to implement a
+          workaround for special cycles described in the BCM5704/357 Errata.
+          This workaround is only need on 5703-A1/2 or 5704-A0 chips that
+          are attached to a PCI-X bus. The NIC chip type and bus are checked
+          later in the driver and the flag cleared if the workaround is not
+          needed. The workaround is enabled by setting the flag UNDI_FIX_FLAG
+          which casues the driver to use indirect pci-config cycles when
+          accessing the low-priority mailboxes (MB_REG_WR/RD).
+       */
+
+       if (attached_to_ICH4_or_older( pdev)) {
+               pDevice->Flags |= UNDI_FIX_FLAG;
+       }
+
+#if (LINUX_VERSION_CODE >= 0x2060a)
+       if(pci_dev_present(pci_AMD762id)){
+               pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
+               pDevice->Flags &= ~NIC_SEND_BD_FLAG;
+       }
+#else
+       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->Flags |= FLUSH_POSTED_WRITE_FLAG;
+               pDevice->Flags &= ~NIC_SEND_BD_FLAG;
+       }
+#endif
+       if (LM_GetAdapterInfo(pDevice) != LM_STATUS_SUCCESS) {
+               rc = -ENODEV;
+               goto err_out_unmap;
+       }
+
+       if ( (pDevice->Flags & JUMBO_CAPABLE_FLAG) == 0 ) {
+               if (dev->mtu > 1500) {
+                       dev->mtu = 1500;
+                       printk(KERN_WARNING "%s-%d: Jumbo mtu sizes not supported, using mtu=1500\n", bcm5700_driver, pUmDevice->index);
+               }
+       }
+
+       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->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:
+#if (LINUX_VERSION_CODE < 0x020600)
+       unregister_netdev(dev);
+       kfree(dev);
+#else
+       free_netdev(dev);
+#endif
+       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 *pci_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;
+
+#ifdef BCM_IOCTL32
+       if (atomic_read(&bcm5700_load_count) == 0) {
+               register_ioctl32_conversion(SIOCNICE, bcm5700_ioctl32);
+       }
+       atomic_inc(&bcm5700_load_count);
+#endif
+       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;
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+       dev->change_mtu = &bcm5700_change_mtu;
+#endif
+#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
+#ifdef BCM_NAPI_RXPOLL
+       dev->poll = bcm5700_poll;
+       dev->weight = 64;
+#endif
+
+       pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
+       pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+
+       dev->base_addr = pci_resource_start(pdev, 0);
+       dev->irq = pdev->irq;
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+       dev->poll_controller = poll_bcm5700;
+#endif
+
+#if (LINUX_VERSION_CODE >= 0x20600)
+       if ((i = register_netdev(dev))) {
+               printk(KERN_ERR "%s: Cannot register net device\n",
+                       bcm5700_driver);
+               if (pUmDevice->lm_dev.pMappedMemBase)
+                       iounmap(pUmDevice->lm_dev.pMappedMemBase);
+               pci_release_regions(pdev);
+               bcm5700_freemem(dev);
+               free_netdev(dev);
+               return i;
+       }
+#endif
+
+
+       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->TbiFlags & ENABLE_TBI_FLAG)) {
+               printk("Broadcom BCM5701 Integrated Copper ");
+       }
+       else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) {
+               printk("Broadcom BCM5703 Integrated ");
+               if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+                       printk("SerDes ");
+               else
+                       printk("Copper ");
+       }
+       else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5704_PHY_ID) {
+               printk("Broadcom BCM5704 Integrated ");
+               if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+                       printk("SerDes ");
+               else
+                       printk("Copper ");
+       }
+        else if (pDevice->PhyFlags & PHY_IS_FIBER){
+            if(( pDevice->PhyId & PHY_ID_MASK ) == PHY_BCM5780_PHY_ID)
+                printk("Broadcom BCM5780S Integrated Serdes ");
+
+        }        
+       else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5705_PHY_ID)
+               printk("Broadcom BCM5705 Integrated Copper ");
+       else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5750_PHY_ID)
+               printk("Broadcom BCM5750 Integrated Copper ");
+
+        else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5714_PHY_ID)
+                printk("Broadcom BCM5714 Integrated Copper ");
+        else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5780_PHY_ID)
+                printk("Broadcom BCM5780 Integrated Copper ");
+
+       else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5752_PHY_ID)
+               printk("Broadcom BCM5752 Integrated Copper ");
+       else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
+               printk("Broadcom BCM8002 SerDes ");
+       else if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
+               if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) {
+                       printk("Broadcom BCM5703 Integrated SerDes ");
+               }
+               else 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");
+
+#if (LINUX_VERSION_CODE >= 0x20400)
+       if (scatter_gather[board_idx]) {
+               dev->features |= NETIF_F_SG;
+               if (pUmDevice->using_dac && !(pDevice->Flags & BCM5788_FLAG))
+                       dev->features |= NETIF_F_HIGHDMA;
+       }
+       if ((pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM) &&
+               tx_checksum[board_idx]) {
+
+               dev->features |= get_csum_flag( pDevice->ChipRevId);
+       }
+#ifdef BCM_VLAN
+       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+#endif
+#ifdef BCM_TSO
+       /* On 5714/15/80 chips, Jumbo Frames and TSO cannot both be enabled at
+          the same time. Since only one of these features can be enable at a
+           time, we'll enable only Jumbo Frames and disable TSO when the user
+          tries to enable both.
+       */
+       dev->features &= ~NETIF_F_TSO;
+
+       if ((pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION) &&
+           (enable_tso[board_idx])) {
+               if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
+                  (dev->mtu > 1500)) {
+                       printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
+               } else {
+                       dev->features |= NETIF_F_TSO;
+               }
+       }
+#endif
+       printk(KERN_INFO "%s: Scatter-gather %s, 64-bit DMA %s, Tx Checksum %s, ",
+                       dev->name,
+                       (char *) ((dev->features & NETIF_F_SG) ? "ON" : "OFF"),
+                       (char *) ((dev->features & NETIF_F_HIGHDMA) ? "ON" : "OFF"),
+                       (char *) ((dev->features & get_csum_flag( pDevice->ChipRevId)) ? "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");
+       }
+       else
+#endif
+#ifdef BCM_NAPI_RXPOLL
+       printk(", NAPI ON");
+#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 (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);
+               }
+       }
+
+#if (LINUX_VERSION_CODE > 0x20605)
+
+       if ((pci_dev = pci_get_device(0x1022, 0x700c, NULL))) {
+#else
+       if ((pci_dev = pci_find_device(0x1022, 0x700c, NULL))) {
+#endif
+               u32 val;
+
+               /* Found AMD 762 North bridge */
+               pci_read_config_dword(pci_dev, 0x4c, &val);
+               if ((val & 0x02) == 0) {
+                       pci_write_config_dword(pci_dev, 0x4c, val | 0x02);
+                       printk(KERN_INFO "%s: Setting AMD762 Northbridge to enable PCI ordering compliance\n", bcm5700_driver);
+               }
+       }
+
+#if (LINUX_VERSION_CODE > 0x20605)
+
+       pci_dev_put(pci_dev);
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+
+       if ((pci_dev = pci_get_device(0x1066, 0x0017, NULL))) {
+               bcm_msi_chipset_bug = 1;
+       }
+       pci_dev_put(pci_dev);
+#endif
+#endif
+
+       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
+#ifdef BCM_IOCTL32
+       atomic_dec(&bcm5700_load_count);
+       if (atomic_read(&bcm5700_load_count) == 0)
+               unregister_ioctl32_conversion(SIOCNICE);
+#endif
+       unregister_netdev(dev);
+
+       if (pUmDevice->lm_dev.pMappedMemBase)
+               iounmap(pUmDevice->lm_dev.pMappedMemBase);
+
+       pci_release_regions(pdev);
+
+#if (LINUX_VERSION_CODE < 0x020600)
+       kfree(dev);
+#else
+       free_netdev(dev);
+#endif
+
+       pci_set_drvdata(pdev, NULL);
+
+}
+
+int b57_test_intr(UM_DEVICE_BLOCK *pUmDevice);
+
+int
+bcm5700_open(struct net_device *dev)
+{
+       PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+       PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+       int rc;
+
+       if (pUmDevice->suspended){
+            return -EAGAIN;
+        }
+       /* delay for 6 seconds */
+       pUmDevice->delayed_link_ind = (6 * HZ) / pUmDevice->timer_interval;
+
+#ifdef BCM_INT_COAL
+#ifndef BCM_NAPI_RXPOLL
+       pUmDevice->adaptive_expiry = HZ / pUmDevice->timer_interval;
+#endif
+#endif
+
+#ifdef INCLUDE_TBI_SUPPORT
+       if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+               (pDevice->TbiFlags & TBI_POLLING_FLAGS)) {
+               pUmDevice->poll_tbi_interval = HZ / pUmDevice->timer_interval;
+               if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) {
+                       pUmDevice->poll_tbi_interval /= 4;
+               }
+               pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_interval;
+       }
+#endif
+       /* set this timer for 2 seconds */
+       pUmDevice->asf_heartbeat = (2 * HZ) / pUmDevice->timer_interval;
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+
+
+       if ( (  (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ) &&
+               (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5714_A0 ) &&
+               (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_AX ) &&
+               (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_BX ) ) &&
+               !bcm_msi_chipset_bug    ){
+
+               if (disable_msi[pUmDevice->index]==1){
+                       /* do nothing-it's not turned on */
+               }else{
+                       pDevice->Flags |= USING_MSI_FLAG;
+
+                        REG_WR(pDevice, Msi.Mode,  2 );
+
+                       rc = pci_enable_msi(pUmDevice->pdev);
+
+                       if(rc!=0){
+                               pDevice->Flags &= ~ USING_MSI_FLAG;
+                               REG_WR(pDevice, Msi.Mode,  1 );
+                       }
+               }
+       }
+
+
+#endif
+
+       if ((rc= request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt, SA_SHIRQ, dev->name, dev)))
+       {
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+
+               if(pDevice->Flags & USING_MSI_FLAG)  {
+
+                       pci_disable_msi(pUmDevice->pdev);
+                       pDevice->Flags &= ~USING_MSI_FLAG;
+                               REG_WR(pDevice, Msi.Mode,  1 );
+
+               }
+#endif
+               return rc;
+       }
+
+       pUmDevice->opened = 1;
+       if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
+               pUmDevice->opened = 0;
+               free_irq(dev->irq, dev);
+               bcm5700_freemem(dev);
+               return -EAGAIN;
+       }
+
+       bcm5700_set_vlan_mode(pUmDevice);
+       bcm5700_init_counters(pUmDevice);
+
+       if (pDevice->Flags & UNDI_FIX_FLAG) {
+               printk(KERN_INFO "%s: Using indirect register access\n", dev->name);
+       }
+
+       if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6))
+       {
+               /* Do not use invalid eth addrs: any multicast & all zeros */
+               if( is_valid_ether_addr(dev->dev_addr) ){
+                       LM_SetMacAddress(pDevice, dev->dev_addr);
+               }
+               else
+               {
+                       printk(KERN_INFO "%s: Invalid administered node address\n",dev->name);
+                       memcpy(dev->dev_addr, pDevice->NodeAddress, 6);
+               }
+       }
+
+       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);
+
+
+#if (LINUX_VERSION_CODE < 0x020300)
+       MOD_INC_USE_COUNT;
+#endif
+
+       atomic_set(&pUmDevice->intr_sem, 0);
+
+       LM_EnableInterrupt(pDevice);
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+
+       if (pDevice->Flags & USING_MSI_FLAG){
+
+               /* int test to check support on older machines */
+               if (b57_test_intr(pUmDevice) != 1) {
+
+                       LM_DisableInterrupt(pDevice);
+                       free_irq(pUmDevice->pdev->irq, dev);
+                       pci_disable_msi(pUmDevice->pdev);
+                        REG_WR(pDevice, Msi.Mode,  1 );
+                       pDevice->Flags &= ~USING_MSI_FLAG;
+
+                       rc = LM_ResetAdapter(pDevice);
+printk(KERN_ALERT " The MSI support in this system is not functional.\n");
+
+                       if (rc == LM_STATUS_SUCCESS)
+                               rc = 0;
+                       else
+                               rc = -ENODEV;
+
+                       if(rc == 0){
+                               rc = request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt,
+                                           SA_SHIRQ, dev->name, dev);
+                       }
+
+                       if(rc){
+                               LM_Halt(pDevice);
+                               bcm5700_freemem(dev);
+                               pUmDevice->opened = 0;
+                               return rc;
+                       }
+
+
+                       pDevice->InitDone = TRUE;
+                       atomic_set(&pUmDevice->intr_sem, 0);
+                       LM_EnableInterrupt(pDevice);
+               }
+       }
+#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);
+
+       if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
+               init_timer(&pUmDevice->statstimer);
+               pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval);
+               pUmDevice->statstimer.data = (unsigned long)dev;
+               pUmDevice->statstimer.function = &bcm5700_stats_timer;
+               add_timer(&pUmDevice->statstimer);
+       }
+
+       if(pDevice->Flags & USING_MSI_FLAG)
+               printk(KERN_INFO "%s: Using Message Signaled Interrupt (MSI)  \n", dev->name);
+       else
+               printk(KERN_INFO "%s: Using PCI INTX interrupt \n", dev->name);
+
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+
+STATIC void
+bcm5700_stats_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 = 0;
+
+       if (!pUmDevice->opened)
+               return;
+
+       if (!atomic_read(&pUmDevice->intr_sem) &&
+           !pUmDevice->suspended              &&
+          (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)) {
+               BCM5700_LOCK(pUmDevice, flags);
+               LM_GetStats(pDevice);
+               BCM5700_UNLOCK(pUmDevice, flags);
+       }
+
+       pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval);
+
+       add_timer(&pUmDevice->statstimer);
+}
+
+
+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 = 0;
+       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;
+       }
+
+#ifdef INCLUDE_TBI_SUPPORT
+       if ((pDevice->TbiFlags & TBI_POLLING_FLAGS) &&
+               (--pUmDevice->poll_tbi_expiry <= 0)) {
+
+               BCM5700_PHY_LOCK(pUmDevice, flags);
+               value32 = REG_RD(pDevice, MacCtrl.Status);
+               if (((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) &&
+                       ((value32 & (MAC_STATUS_LINK_STATE_CHANGED |
+                               MAC_STATUS_CFG_CHANGED)) ||
+                       !(value32 & MAC_STATUS_PCS_SYNCED)))
+                       ||
+                       ((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) &&
+                       (value32 & (MAC_STATUS_PCS_SYNCED |
+                               MAC_STATUS_SIGNAL_DETECTED))))
+               {
+                       LM_SetupPhy(pDevice);
+               }
+               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+               pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_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->crc_counter_expiry > 0)
+               pUmDevice->crc_counter_expiry--;
+
+       if (!pUmDevice->interrupt) {
+               if (!(pDevice->Flags & USE_TAGGED_STATUS_FLAG)) {
+                       BCM5700_LOCK(pUmDevice, flags);
+                       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
+#ifndef BCM_NAPI_RXPOLL
+       if (pUmDevice->adaptive_coalesce) {
+               pUmDevice->adaptive_expiry--;
+               if (pUmDevice->adaptive_expiry == 0) {
+                       pUmDevice->adaptive_expiry = HZ /
+                               pUmDevice->timer_interval;
+                       bcm5700_adapt_coalesce(pUmDevice);
+               }
+       }
+#endif
+#endif
+       if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container) >
+               (unsigned int) 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->AsfFlags & ASF_ENABLED) {
+               pUmDevice->asf_heartbeat--;
+               if (pUmDevice->asf_heartbeat == 0) {
+                       if( (pDevice->Flags & UNDI_FIX_FLAG) || 
+                           (pDevice->Flags & ENABLE_PCIX_FIX_FLAG)) {
+                               MEM_WR_OFFSET(pDevice, T3_CMD_MAILBOX,
+                                       T3_CMD_NICDRV_ALIVE2);
+                               MEM_WR_OFFSET(pDevice, T3_CMD_LENGTH_MAILBOX,
+                                       4);
+                               MEM_WR_OFFSET(pDevice, T3_CMD_DATA_MAILBOX, 5);
+                       } else {
+                               LM_RegWr(pDevice, 
+                                        (T3_NIC_MBUF_POOL_ADDR + 
+                                         T3_CMD_MAILBOX), 
+                                        T3_CMD_NICDRV_ALIVE2, 1);
+                               LM_RegWr(pDevice, 
+                                        (T3_NIC_MBUF_POOL_ADDR + 
+                                         T3_CMD_LENGTH_MAILBOX),4,1);
+                               LM_RegWr(pDevice, 
+                                        (T3_NIC_MBUF_POOL_ADDR + 
+                                         T3_CMD_DATA_MAILBOX),5,1);
+                       }
+
+                       value32 = REG_RD(pDevice, Grc.RxCpuEvent);
+                       REG_WR(pDevice, Grc.RxCpuEvent, value32 | BIT_14);
+                       pUmDevice->asf_heartbeat = (2 * HZ) /
+                               pUmDevice->timer_interval;
+               }
+       }
+#endif
+
+       if (pDevice->PhyFlags & PHY_IS_FIBER){
+               BCM5700_PHY_LOCK(pUmDevice, flags);
+               LM_5714_FamFiberCheckLink(pDevice);
+               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+       }
+
+       pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
+       add_timer(&pUmDevice->timer);
+}
+
+STATIC int
+bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice)
+{
+#ifdef BCM_INT_COAL
+#ifndef BCM_NAPI_RXPOLL
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+
+       pUmDevice->rx_curr_coalesce_frames = pDevice->RxMaxCoalescedFrames;
+       pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
+       pUmDevice->tx_curr_coalesce_frames = pDevice->TxMaxCoalescedFrames;
+       pUmDevice->rx_last_cnt = 0;
+       pUmDevice->tx_last_cnt = 0;
+#endif
+#endif
+       pUmDevice->phy_crc_count = 0;
+#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
+#ifdef BCM_TSO
+       pUmDevice->tso_pkt_count = 0;
+#endif
+       return 0;
+}
+
+#ifdef BCM_INT_COAL
+#ifndef BCM_NAPI_RXPOLL
+STATIC int
+bcm5700_do_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice,
+       int rx_frames, int rx_ticks, int tx_frames, int rx_frames_intr)
+{
+       unsigned long flags = 0;
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+
+       if (pUmDevice->do_global_lock) {
+               if (spin_is_locked(&pUmDevice->global_lock))
+                       return 0;
+               spin_lock_irqsave(&pUmDevice->global_lock, flags);
+       }
+       pUmDevice->rx_curr_coalesce_frames = rx_frames;
+       pUmDevice->rx_curr_coalesce_ticks = rx_ticks;
+       pUmDevice->tx_curr_coalesce_frames = tx_frames;
+       pUmDevice->rx_curr_coalesce_frames_intr = rx_frames_intr;
+       REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames, rx_frames);
+
+       REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, rx_ticks);
+
+       REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames, tx_frames);
+
+       REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt,
+               rx_frames_intr);
+
+       BCM5700_UNLOCK(pUmDevice, flags);
+       return 0;
+}
+
+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;
+
+       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 < ADAPTIVE_LO_PKT_THRESH) {
+               if (pUmDevice->rx_curr_coalesce_frames !=
+                       ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES) {
+
+                       bcm5700_do_adapt_coalesce(pUmDevice,
+                               ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES,
+                               ADAPTIVE_LO_RX_COALESCING_TICKS,
+                               ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES,
+                               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) {
+
+                       bcm5700_do_adapt_coalesce(pUmDevice,
+                               DEFAULT_RX_MAX_COALESCED_FRAMES,
+                               DEFAULT_RX_COALESCING_TICKS,
+                               DEFAULT_TX_MAX_COALESCED_FRAMES,
+                               DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT);
+               }
+       }
+       else {
+               if (pUmDevice->rx_curr_coalesce_frames !=
+                       ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES) {
+
+                       bcm5700_do_adapt_coalesce(pUmDevice,
+                               ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES,
+                               ADAPTIVE_HI_RX_COALESCING_TICKS,
+                               ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES,
+                               ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES_DURING_INT);
+               }
+       }
+       return 0;
+}
+#endif
+#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;
+
+#ifdef BCM_TSO
+
+       if( (dev->features & NETIF_F_TSO) &&
+               (pUmDevice->tx_full) )     {
+
+               dev->features &= ~NETIF_F_TSO;
+       }
+#endif
+
+       netif_stop_queue(dev);
+       bcm5700_intr_off(pUmDevice);
+       BCM5700_PHY_LOCK(pUmDevice, flags);
+       LM_ResetAdapter(pDevice);
+       pDevice->InitDone = TRUE;
+       bcm5700_do_rx_mode(dev);
+       bcm5700_set_vlan_mode(pUmDevice);
+       bcm5700_init_counters(pUmDevice);
+       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);
+}
+
+STATIC void
+bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       LM_UINT32 ReceiveMask = pDevice->ReceiveMask;
+       int vlan_tag_mode = pUmDevice->vlan_tag_mode;
+
+       if (vlan_tag_mode == VLAN_TAG_MODE_AUTO_STRIP) {
+               if (pDevice->AsfFlags & ASF_ENABLED) {
+                       vlan_tag_mode = VLAN_TAG_MODE_FORCED_STRIP;
+               }
+               else {
+                       vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP;
+               }
+       }
+       if (vlan_tag_mode == VLAN_TAG_MODE_NORMAL_STRIP) {
+               ReceiveMask |= LM_KEEP_VLAN_TAG;
+#ifdef BCM_VLAN
+               if (pUmDevice->vlgrp)
+                       ReceiveMask &= ~LM_KEEP_VLAN_TAG;
+#endif
+#ifdef NICE_SUPPORT
+               if (pUmDevice->nice_rx)
+                       ReceiveMask &= ~LM_KEEP_VLAN_TAG;
+#endif
+       }
+       else if (vlan_tag_mode == VLAN_TAG_MODE_FORCED_STRIP) {
+               ReceiveMask &= ~LM_KEEP_VLAN_TAG;
+       }
+       if (ReceiveMask != pDevice->ReceiveMask)
+       {
+               LM_SetReceiveMask(pDevice, ReceiveMask);
+       }
+}
+
+static void
+bcm5700_poll_wait(UM_DEVICE_BLOCK *pUmDevice)
+{
+#ifdef BCM_NAPI_RXPOLL
+       while (pUmDevice->lm_dev.RxPoll) {
+               current->state = TASK_INTERRUPTIBLE;
+               schedule_timeout(1);
+       }
+#endif
+}
+
+
+#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;
+
+       bcm5700_intr_off(pUmDevice);
+       bcm5700_poll_wait(pUmDevice);
+       pUmDevice->vlgrp = vlgrp;
+       bcm5700_set_vlan_mode(pUmDevice);
+       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);
+       bcm5700_poll_wait(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 = 0;
+       int frag_no;
+#ifdef NICE_SUPPORT
+       vlan_tag_t *vlan_tag;
+#endif
+#ifdef BCM_TSO
+       LM_UINT32 mss = 0 ;
+       uint16_t ip_tcp_len, tcp_opt_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)) {
+
+#if (LINUX_VERSION_CODE >= 0x02060c)
+
+               if (skb_header_cloned(skb) &&
+                       pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+
+                       dev_kfree_skb(skb);
+                       return 0;
+               }
+#endif
+               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;
+
+               if ( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ){
+                       skb->h.th->check = 0;
+                       pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
+               }
+               else {
+                       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 (tcp_opt_len || (skb->nh.iph->ihl > 5)) {
+                       if ( T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId) ){
+                               tcp_seg_flags =
+                                       ((skb->nh.iph->ihl - 5) +
+                                       (tcp_opt_len >> 2)) << 11;
+                       }
+                       else {
+                               pPacket->Flags |=
+                                       ((skb->nh.iph->ihl - 5) +
+                                       (tcp_opt_len >> 2)) << 12;
+                       }
+               }
+               pPacket->u.Tx.MaxSegmentSize = mss | tcp_seg_flags;
+       }
+       else
+       {
+               pPacket->u.Tx.MaxSegmentSize = 0;
+       }
+#endif
+       BCM5700_LOCK(pUmDevice, flags);
+       LM_SendPacket(pDevice, pPacket);
+       BCM5700_UNLOCK(pUmDevice, flags);
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+       netif_wake_queue(dev);
+#endif
+       dev->trans_start = jiffies;
+
+
+       return 0;
+}
+
+#ifdef BCM_NAPI_RXPOLL
+STATIC int
+bcm5700_poll(struct net_device *dev, int *budget)
+{
+       int orig_budget = *budget;
+       int work_done;
+       UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) dev->priv;
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       unsigned long flags = 0;
+       LM_UINT32 tag;
+
+       if (orig_budget > dev->quota)
+               orig_budget = dev->quota;
+
+       BCM5700_LOCK(pUmDevice, flags);
+       work_done = LM_ServiceRxPoll(pDevice, orig_budget);
+       *budget -= work_done;
+       dev->quota -= work_done;
+
+       if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+               replenish_rx_buffers(pUmDevice, 0);
+       }
+       BCM5700_UNLOCK(pUmDevice, flags);
+       if (work_done) {
+               MM_IndicateRxPackets(pDevice);
+               BCM5700_LOCK(pUmDevice, flags);
+               LM_QueueRxPackets(pDevice);
+               BCM5700_UNLOCK(pUmDevice, flags);
+       }
+       if ((work_done < orig_budget) || atomic_read(&pUmDevice->intr_sem) ||
+               pUmDevice->suspended) {
+
+               netif_rx_complete(dev);
+               BCM5700_LOCK(pUmDevice, flags);
+               REG_WR(pDevice, Grc.Mode, pDevice->GrcMode);
+               pDevice->RxPoll = FALSE;
+               if (pDevice->RxPoll) {
+                       BCM5700_UNLOCK(pUmDevice, flags);
+                       return 0;
+               }
+               /* Take care of possible missed rx interrupts */
+               REG_RD_BACK(pDevice, Grc.Mode); /* flush the register write */
+               tag = pDevice->pStatusBlkVirt->StatusTag;
+               if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
+                       (pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx !=
+                       pDevice->RcvRetConIdx)) {
+
+                       REG_WR(pDevice, HostCoalesce.Mode,
+                               pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
+                               HOST_COALESCE_NOW);
+               }
+               /* If a new status block is pending in the WDMA state machine */
+               /* before the register write to enable the rx interrupt,      */
+               /* the new status block may DMA with no interrupt. In this    */
+               /* scenario, the tag read above will be older than the tag in */
+               /* the pending status block and writing the older tag will    */
+               /* cause interrupt to be generated.                           */
+               else if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) {
+                       MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low,
+                               tag << 24);
+                       /* Make sure we service tx in case some tx interrupts */
+                       /* are cleared */
+                       if (atomic_read(&pDevice->SendBdLeft) <
+                               (T3_SEND_RCB_ENTRY_COUNT / 2)) {
+                               REG_WR(pDevice, HostCoalesce.Mode,
+                                       pDevice->CoalesceMode |
+                                       HOST_COALESCE_ENABLE |
+                                       HOST_COALESCE_NOW);
+                       }
+               }
+               BCM5700_UNLOCK(pUmDevice, flags);
+               return 0;
+       }
+       return 1;
+}
+#endif /* BCM_NAPI_RXPOLL */
+
+STATIC irqreturn_t
+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, max_intr_loop;
+#ifdef BCM_TASKLET
+       int repl_buf_count;
+#endif
+       unsigned int handled = 1;
+
+       if (!pDevice->InitDone) {
+               handled = 0;
+               return IRQ_RETVAL(handled);
+       }
+
+       bcm5700_intr_lock(pUmDevice);
+       if (atomic_read(&pUmDevice->intr_sem)) {
+               MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+               bcm5700_intr_unlock(pUmDevice);
+               handled = 0;
+               return IRQ_RETVAL(handled);
+       }
+
+       if (test_and_set_bit(0, (void*)&pUmDevice->interrupt)) {
+               printk(KERN_ERR "%s: Duplicate entry of the interrupt handler\n",
+                       dev->name);
+               bcm5700_intr_unlock(pUmDevice);
+               handled = 0;
+               return IRQ_RETVAL(handled);
+       }
+
+       if ((pDevice->Flags & USING_MSI_FLAG) ||
+               (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
+               !(REG_RD(pDevice,PciCfg.PciState) & T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) )
+       {
+
+               if (pUmDevice->intr_test) {
+                       if (!(REG_RD(pDevice, PciCfg.PciState) &
+                                       T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) ||
+                                               pDevice->Flags & USING_MSI_FLAG ) {
+                               pUmDevice->intr_test_result = 1;
+                       }
+                       pUmDevice->intr_test = 0;
+               }
+
+#ifdef BCM_NAPI_RXPOLL
+               max_intr_loop = 1;
+#else
+               max_intr_loop = 50;
+#endif
+               if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) {
+                       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 > max_intr_loop)) {
+                                       MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, oldtag << 24);
+                                       pDevice->LastTag = oldtag;
+                                       if (pDevice->Flags & UNDI_FIX_FLAG) {
+                                               REG_WR(pDevice, Grc.LocalCtrl,
+                                               pDevice->GrcLocalCtrl | 0x2);
+                                       }
+                                       break;
+                               }
+                               oldtag = newtag;
+                       }
+               }
+               else
+               {
+                       i = 0;
+                       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);
+                               i++;
+                       }
+                       while ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) &&
+                               (i < max_intr_loop));
+
+                       if (pDevice->Flags & UNDI_FIX_FLAG) {
+                               REG_WR(pDevice, Grc.LocalCtrl,
+                               pDevice->GrcLocalCtrl | 0x2);
+                       }
+               }
+       }
+       else
+       {
+               /* not my interrupt */
+               handled = 0;
+       }
+
+#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, pUmDevice->rx_buf_repl_isr_limit);
+               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
+#ifdef BCM_NAPI_RXPOLL
+       if (!pDevice->RxPoll &&
+               QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+               pDevice->RxPoll = 1;
+               MM_ScheduleRxPoll(pDevice);
+       }
+#else
+       if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+               replenish_rx_buffers(pUmDevice, 0);
+       }
+
+       if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container) ||
+               pDevice->QueueAgain) {
+
+               LM_QueueRxPackets(pDevice);
+       }
+#endif
+#endif
+
+       clear_bit(0, (void*)&pUmDevice->interrupt);
+       bcm5700_intr_unlock(pUmDevice);
+       if (pUmDevice->tx_queued) {
+               pUmDevice->tx_queued = 0;
+               netif_wake_queue(dev);
+       }
+       return IRQ_RETVAL(handled);
+}
+
+
+#ifdef BCM_TASKLET
+STATIC void
+bcm5700_tasklet(unsigned long data)
+{
+       PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)data;
+       unsigned long flags = 0;
+
+       /* 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;
+       if (pUmDevice->opened && !pUmDevice->suspended) {
+               BCM5700_LOCK(pUmDevice, flags);
+               replenish_rx_buffers(pUmDevice, 0);
+               BCM5700_UNLOCK(pUmDevice, flags);
+       }
+
+       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;
+
+#ifdef BCM_ASF
+       if( !(pDevice->AsfFlags & ASF_ENABLED) )
+#endif
+#ifdef BCM_WOL
+               if( enable_wol[pUmDevice->index] == 0 )
+#endif
+                       printk(KERN_INFO "%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name);
+
+       if (tigon3_debug > 1)
+               printk(KERN_DEBUG "%s: Shutting down Tigon3\n",
+                          dev->name);
+
+       LM_MulticastClear(pDevice);
+       bcm5700_shutdown(pUmDevice);
+
+       if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
+               del_timer_sync(&pUmDevice->statstimer);
+       }
+
+       del_timer_sync(&pUmDevice->timer);
+
+       free_irq(pUmDevice->pdev->irq, dev);
+
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+
+       if(pDevice->Flags & USING_MSI_FLAG) {
+               pci_disable_msi(pUmDevice->pdev);
+                REG_WR(pDevice, Msi.Mode,  1 );
+               pDevice->Flags &= ~USING_MSI_FLAG;
+       }
+
+#endif
+
+
+#if (LINUX_VERSION_CODE < 0x020300)
+       MOD_DEC_USE_COUNT;
+#endif
+       {
+
+               LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
+       }
+
+       bcm5700_freemem(dev);
+
+       QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
+                       MAX_RX_PACKET_DESC_COUNT);
+
+       return 0;
+}
+
+STATIC int
+bcm5700_freemem(struct net_device *dev)
+{
+       int i;
+       PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+       LM_DEVICE_BLOCK  *pDevice = &pUmDevice->lm_dev;
+
+       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]);
+               }
+       }
+
+       pDevice->pStatusBlkVirt = 0;
+       pDevice->pStatsBlkVirt  = 0;
+       pUmDevice->mem_list_num = 0;
+
+#ifdef NICE_SUPPORT
+       if (!pUmDevice->opened) {
+               for (i = 0; i < MAX_MEM2; i++) {
+                       if (pUmDevice->mem_size_list2[i]) {
+                               bcm5700_freemem2(pUmDevice, i);
+                       }
+               }
+       }
+#endif
+       return 0;
+}
+
+#ifdef NICE_SUPPORT
+/* Frees consistent memory allocated through ioctl */
+/* The memory to be freed is in mem_list2[index] */
+STATIC int
+bcm5700_freemem2(UM_DEVICE_BLOCK *pUmDevice, int index)
+{
+#if (LINUX_VERSION_CODE >= 0x020400)
+       void *ptr;
+       struct page *pg, *last_pg;
+
+       /* Probably won't work on some architectures */
+       ptr = pUmDevice->mem_list2[index],
+       pg = virt_to_page(ptr);
+       last_pg = virt_to_page(ptr + pUmDevice->mem_size_list2[index] - 1);
+       for (; ; pg++) {
+#if (LINUX_VERSION_CODE > 0x020500)
+               ClearPageReserved(pg);
+#else
+               mem_map_unreserve(pg);
+#endif
+               if (pg == last_pg)
+                       break;
+       }
+       pci_free_consistent(pUmDevice->pdev,
+               (size_t) pUmDevice->mem_size_list2[index],
+               pUmDevice->mem_list2[index],
+               pUmDevice->dma_list2[index]);
+       pUmDevice->mem_size_list2[index] = 0;
+#endif
+       return 0;
+}
+#endif
+
+uint64_t
+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->TbiFlags & ENABLE_TBI_FLAG)) {
+
+               if (!pUmDevice->opened || !pDevice->InitDone)
+               {
+
+                       return 0;
+               }
+
+               /* regulate MDIO access during run time */
+               if (pUmDevice->crc_counter_expiry > 0)
+                       return pUmDevice->phy_crc_count;
+
+               pUmDevice->crc_counter_expiry = (5 * HZ) /
+                       pUmDevice->timer_interval;
+
+               BCM5700_PHY_LOCK(pUmDevice, flags);
+               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)
+                       pUmDevice->phy_crc_count += Value32;
+               return pUmDevice->phy_crc_count;
+       }
+       else if (pStats == 0) {
+               return 0;
+       }
+       else {
+               return (MM_GETSTATS64(pStats->dot3StatsFCSErrors));
+       }
+}
+
+uint64_t
+bcm5700_rx_err_count(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       T3_STATS_BLOCK *pStats = (T3_STATS_BLOCK *) pDevice->pStatsBlkVirt;
+
+       if (pStats == 0)
+               return 0;
+       return (bcm5700_crc_count(pUmDevice) +
+               MM_GETSTATS64(pStats->dot3StatsAlignmentErrors) +
+               MM_GETSTATS64(pStats->etherStatsUndersizePkts) +
+               MM_GETSTATS64(pStats->etherStatsFragments) +
+               MM_GETSTATS64(pStats->dot3StatsFramesTooLong) +
+               MM_GETSTATS64(pStats->etherStatsJabbers));
+}
+
+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 = (unsigned long)
+               bcm5700_crc_count(pUmDevice);
+       p_netstats->rx_errors = (unsigned long)
+               bcm5700_rx_err_count(pUmDevice);
+
+       p_netstats->tx_aborted_errors = MM_GETSTATS(pStats->ifOutDiscards);
+       p_netstats->tx_carrier_errors =
+               MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors);
+
+       return p_netstats;
+}
+
+void
+b57_suspend_chip(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+
+       if (pUmDevice->opened) {
+               bcm5700_intr_off(pUmDevice);
+               netif_carrier_off(pUmDevice->dev);
+               netif_stop_queue(pUmDevice->dev);
+#ifdef BCM_TASKLET
+               tasklet_kill(&pUmDevice->tasklet);
+#endif
+               bcm5700_poll_wait(pUmDevice);
+       }
+       pUmDevice->suspended = 1;
+       LM_ShutdownChip(pDevice, LM_SUSPEND_RESET);
+}
+
+void
+b57_resume_chip(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+
+       if (pUmDevice->suspended) {
+               pUmDevice->suspended = 0;
+               if (pUmDevice->opened) {
+                       bcm5700_reset(pUmDevice->dev);
+               }
+               else {
+                       LM_ShutdownChip(pDevice, LM_SHUTDOWN_RESET);
+               }
+       }
+}
+
+/* Returns 0 on failure, 1 on success */
+int
+b57_test_intr(UM_DEVICE_BLOCK *pUmDevice)
+{
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+       int j;
+
+       if (!pUmDevice->opened)
+               return 0;
+       pUmDevice->intr_test_result = 0;
+       pUmDevice->intr_test = 1;
+
+       REG_WR(pDevice, HostCoalesce.Mode,
+               pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
+               HOST_COALESCE_NOW);
+
+       for (j = 0; j < 10; j++) {
+               if (pUmDevice->intr_test_result){
+                       break;
+               }
+
+               REG_WR(pDevice, HostCoalesce.Mode,
+               pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
+               HOST_COALESCE_NOW);
+
+               MM_Sleep(pDevice, 1);
+       }
+
+       return pUmDevice->intr_test_result;
+
+}
+
+#ifdef SIOCETHTOOL
+
+#ifdef ETHTOOL_GSTRINGS
+
+#define ETH_NUM_STATS 30
+#define RX_CRC_IDX 5
+#define RX_MAC_ERR_IDX 14
+
+struct {
+       char string[ETH_GSTRING_LEN];
+} bcm5700_stats_str_arr[ETH_NUM_STATS] = {
+       { "rx_unicast_packets" },
+       { "rx_multicast_packets" },
+       { "rx_broadcast_packets" },
+       { "rx_bytes" },
+       { "rx_fragments" },
+       { "rx_crc_errors" },    /* this needs to be calculated */
+       { "rx_align_errors" },
+       { "rx_xon_frames" },
+       { "rx_xoff_frames" },
+       { "rx_long_frames" },
+       { "rx_short_frames" },
+       { "rx_jabber" },
+       { "rx_discards" },
+       { "rx_errors" },
+       { "rx_mac_errors" },    /* this needs to be calculated */
+       { "tx_unicast_packets" },
+       { "tx_multicast_packets" },
+       { "tx_broadcast_packets" },
+       { "tx_bytes" },
+       { "tx_deferred" },
+       { "tx_single_collisions" },
+       { "tx_multi_collisions" },
+       { "tx_total_collisions" },
+       { "tx_excess_collisions" },
+       { "tx_late_collisions" },
+       { "tx_xon_frames" },
+       { "tx_xoff_frames" },
+       { "tx_internal_mac_errors" },
+       { "tx_carrier_errors" },
+       { "tx_errors" },
+};
+
+#define STATS_OFFSET(offset_name) ((OFFSETOF(T3_STATS_BLOCK, offset_name)) / sizeof(uint64_t))
+
+#ifdef __BIG_ENDIAN
+#define SWAP_DWORD_64(x) (x)
+#else
+#define SWAP_DWORD_64(x) ((x << 32) | (x >> 32))
+#endif
+
+unsigned long bcm5700_stats_offset_arr[ETH_NUM_STATS] = {
+       STATS_OFFSET(ifHCInUcastPkts),
+       STATS_OFFSET(ifHCInMulticastPkts),
+       STATS_OFFSET(ifHCInBroadcastPkts),
+       STATS_OFFSET(ifHCInOctets),
+       STATS_OFFSET(etherStatsFragments),
+       0,
+       STATS_OFFSET(dot3StatsAlignmentErrors),
+       STATS_OFFSET(xonPauseFramesReceived),
+       STATS_OFFSET(xoffPauseFramesReceived),
+       STATS_OFFSET(dot3StatsFramesTooLong),
+       STATS_OFFSET(etherStatsUndersizePkts),
+       STATS_OFFSET(etherStatsJabbers),
+       STATS_OFFSET(ifInDiscards),
+       STATS_OFFSET(ifInErrors),
+       0,
+       STATS_OFFSET(ifHCOutUcastPkts),
+       STATS_OFFSET(ifHCOutMulticastPkts),
+       STATS_OFFSET(ifHCOutBroadcastPkts),
+       STATS_OFFSET(ifHCOutOctets),
+       STATS_OFFSET(dot3StatsDeferredTransmissions),
+       STATS_OFFSET(dot3StatsSingleCollisionFrames),
+       STATS_OFFSET(dot3StatsMultipleCollisionFrames),
+       STATS_OFFSET(etherStatsCollisions),
+       STATS_OFFSET(dot3StatsExcessiveCollisions),
+       STATS_OFFSET(dot3StatsLateCollisions),
+       STATS_OFFSET(outXonSent),
+       STATS_OFFSET(outXoffSent),
+       STATS_OFFSET(dot3StatsInternalMacTransmitErrors),
+       STATS_OFFSET(dot3StatsCarrierSenseErrors),
+       STATS_OFFSET(ifOutErrors),
+};
+
+#endif /* ETHTOOL_GSTRINGS */
+
+#ifdef ETHTOOL_TEST
+#define ETH_NUM_TESTS 6
+struct {
+       char string[ETH_GSTRING_LEN];
+} bcm5700_tests_str_arr[ETH_NUM_TESTS] = {
+       { "register test (offline)" },
+       { "memory test (offline)" },
+       { "loopback test (offline)" },
+       { "nvram test (online)" },
+       { "interrupt test (online)" },
+       { "link test (online)" },
+};
+
+extern LM_STATUS b57_test_registers(UM_DEVICE_BLOCK *pUmDevice);
+extern LM_STATUS b57_test_memory(UM_DEVICE_BLOCK *pUmDevice);
+extern LM_STATUS b57_test_nvram(UM_DEVICE_BLOCK *pUmDevice);
+extern LM_STATUS b57_test_link(UM_DEVICE_BLOCK *pUmDevice);
+extern LM_STATUS b57_test_loopback(UM_DEVICE_BLOCK *pUmDevice, int looptype, int linespeed);
+#endif
+
+#ifdef ETHTOOL_GREGS
+#if (LINUX_VERSION_CODE >= 0x02040f)
+static void
+bcm5700_get_reg_blk(UM_DEVICE_BLOCK *pUmDevice, u32 **buf, u32 start, u32 end,
+               int reserved)
+{
+       u32 offset;
+       LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
+
+       if (reserved) {
+               memset(*buf, 0, end - start);
+               *buf = *buf + (end - start)/4;
+               return;
+       }
+       for (offset = start; offset < end; offset+=4, *buf = *buf + 1) {
+               if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
+                       if (((offset >= 0x3400) && (offset < 0x3c00)) ||
+                               ((offset >= 0x5400) && (offset < 0x5800)) ||
+                               ((offset >= 0x6400) && (offset < 0x6800))) {
+                               **buf = 0;
+                               continue;
+                       }
+               }
+               **buf = REG_RD_OFFSET(pDevice, offset);
+       }
+}
+#endif
+#endif
+
+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 (mm_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);
+#ifdef 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.fw_version, pDevice->BootCodeVer);
+               strcpy(info.version, bcm5700_version);
+#if (LINUX_VERSION_CODE <= 0x020422)
+               strcpy(info.bus_info, pUmDevice->pdev->slot_name);
+#else
+               strcpy(info.bus_info, pci_name(pUmDevice->pdev));
+#endif
+
+
+
+#ifdef ETHTOOL_GEEPROM
+               BCM_EEDUMP_LEN(&info, pDevice->NvramSize);
+#endif
+#ifdef ETHTOOL_GREGS
+               /* dump everything, including holes in the register space */
+               info.regdump_len = 0x6c00;
+#endif
+#ifdef ETHTOOL_GSTATS
+               info.n_stats = ETH_NUM_STATS;
+#endif
+#ifdef ETHTOOL_TEST
+               info.testinfo_len = ETH_NUM_TESTS;
+#endif
+               if (mm_copy_to_user(useraddr, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+#endif
+        case ETHTOOL_GSET: {
+               if ((pDevice->TbiFlags & ENABLE_TBI_FLAG)||
+                       (pDevice->PhyFlags & PHY_IS_FIBER)) {
+                       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 (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS)
+                       ethcmd.speed = SPEED_1000;
+               else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
+                       ethcmd.speed = SPEED_100;
+               else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+                       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->TbiFlags & ENABLE_TBI_FLAG) ||
+                               (pDevice->PhyFlags & PHY_IS_FIBER)) {
+                               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(mm_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 &&
+                               pDevice->PhyFlags & PHY_NO_GIGABIT)
+                                       return -EINVAL;
+
+                       if (ethcmd.speed == SPEED_1000 &&
+                           (pDevice->TbiFlags & ENABLE_TBI_FLAG ||
+                            pDevice->PhyFlags & PHY_IS_FIBER ) ) {
+
+                               pDevice->RequestedLineSpeed =
+                                       LM_LINE_SPEED_1000MBPS;
+
+                               pDevice->RequestedDuplexMode =
+                                       LM_DUPLEX_MODE_FULL;
+                       }
+                       else if (ethcmd.speed == SPEED_100 &&
+                               !(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+                               !(pDevice->PhyFlags & PHY_IS_FIBER)) {
+
+                               pDevice->RequestedLineSpeed =
+                                       LM_LINE_SPEED_100MBPS;
+                       }
+                       else if (ethcmd.speed == SPEED_10  &&
+                               !(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+                               !(pDevice->PhyFlags & PHY_IS_FIBER)) {
+
+                                pDevice->RequestedLineSpeed =
+                                       LM_LINE_SPEED_10MBPS;
+                       }
+                       else {
+                               return -EINVAL;
+                       }
+
+                       pDevice->DisableAutoNeg = TRUE;
+                       if (ethcmd.duplex == DUPLEX_FULL) {
+                               pDevice->RequestedDuplexMode =
+                                       LM_DUPLEX_MODE_FULL;
+                       }
+                       else {
+                               if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+                                   !(pDevice->PhyFlags & PHY_IS_FIBER)  ) {
+
+                                       pDevice->RequestedDuplexMode =
+                                                       LM_DUPLEX_MODE_HALF;
+                               }
+                       }
+               }
+               if (netif_running(dev)) {
+                       BCM5700_PHY_LOCK(pUmDevice, flags);
+                       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->TbiFlags & ENABLE_TBI_FLAG) &&
+                       !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) ||
+                       (pDevice->Flags & DISABLE_D3HOT_FLAG)) {
+                       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 (mm_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 (mm_copy_from_user(&wol, useraddr, sizeof(wol)))
+                       return -EFAULT;
+               if ((((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+                       !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) ||
+                       (pDevice->Flags & DISABLE_D3HOT_FLAG)) &&
+                       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};
+
+               /* workaround for DHCP using ifup script */
+               /* ifup only waits for 5 seconds for link up */
+               /* NIC may take more than 5 seconds to establish link */
+               if ((pUmDevice->delayed_link_ind > 0) &&
+                       delay_link[pUmDevice->index])
+                       return -EOPNOTSUPP;
+
+               if (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) {
+                       edata.data =  1;
+               }
+               else {
+                       edata.data =  0;
+               }
+               if (mm_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;
+               }
+               if (!netif_running(dev))
+                       return -EAGAIN;
+               BCM5700_PHY_LOCK(pUmDevice, flags);
+               if (pDevice->TbiFlags & ENABLE_TBI_FLAG) { 
+                       pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS;
+                       pDevice->DisableAutoNeg = TRUE;
+                       LM_SetupPhy(pDevice);
+
+                       pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+                       pDevice->DisableAutoNeg = FALSE;
+                       LM_SetupPhy(pDevice);
+               }
+               else {
+                       if ((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))
+                       {
+                               LM_ResetPhy(pDevice);
+                               LM_SetupPhy(pDevice);
+                       }
+                       pDevice->PhyFlags &= ~PHY_FIBER_FALLBACK;
+                       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 (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+                       return -EFAULT;
+
+               if (eeprom.offset >= pDevice->NvramSize)
+                       return -EFAULT;
+
+               /* maximum data limited */
+               /* to read more, call again with a different offset */
+               if (eeprom.len > 0x800) {
+                       eeprom.len = 0x800;
+                       if (mm_copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
+                               return -EFAULT;
+               }
+
+               if (eeprom.len > 64) {
+                       buf = kmalloc(eeprom.len, GFP_KERNEL);
+                       if (!buf)
+                               return -ENOMEM;
+               }
+               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 = mm_copy_to_user(useraddr, buf, eeprom.len);
+               }
+               if (eeprom.len > 64) {
+                       kfree(buf);
+               }
+               if ((j < len) || 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 (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+                       return -EFAULT;
+
+               if ((eeprom.offset & 3) || (eeprom.len & 3) ||
+                       (eeprom.offset >= pDevice->NvramSize)) {
+                       return -EFAULT;
+               }
+
+               if ((eeprom.offset + eeprom.len) >= pDevice->NvramSize) {
+                       eeprom.len = pDevice->NvramSize - 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 (mm_copy_from_user(&buf, useraddr, i))
+                               return -EFAULT;
+
+                       bcm5700_intr_off(pUmDevice);
+                       /* Prevent race condition on Grc.Mode register */
+                       bcm5700_poll_wait(pUmDevice);
+
+                       if (LM_NvramWriteBlock(pDevice, offset, buf, i/4) !=
+                               LM_STATUS_SUCCESS) {
+                               bcm5700_intr_on(pUmDevice);
+                               return -EFAULT;
+                       }
+                       bcm5700_intr_on(pUmDevice);
+                       len -= i;
+                       offset += i;
+                       useraddr += i;
+               }
+               return 0;
+       }
+#endif
+#ifdef ETHTOOL_GREGS
+#if (LINUX_VERSION_CODE >= 0x02040f)
+       case ETHTOOL_GREGS: {
+               struct ethtool_regs eregs;
+               LM_UINT32 *buf, *buf1;
+               unsigned int i;
+
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               if (pDevice->Flags & UNDI_FIX_FLAG)
+                       return -EOPNOTSUPP;
+               if (mm_copy_from_user(&eregs, useraddr, sizeof(eregs)))
+                       return -EFAULT;
+               if (eregs.len > 0x6c00)
+                       eregs.len = 0x6c00;
+               eregs.version = 0x0;
+               if (mm_copy_to_user(useraddr, &eregs, sizeof(eregs)))
+                       return -EFAULT;
+               buf = buf1 = kmalloc(eregs.len, GFP_KERNEL);
+               if (!buf)
+                       return -ENOMEM;
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0,      0xb0,   0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0xb0,   0x200,  1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x200,  0x8f0,  0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x8f0,  0xc00,  1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0xc00,  0xce0,  0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0xce0,  0x1000, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1000, 0x1004, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1004, 0x1400, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1400, 0x1480, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1480, 0x1800, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1800, 0x1848, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1848, 0x1c00, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c00, 0x1c04, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c04, 0x2000, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x2000, 0x225c, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x225c, 0x2400, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x2400, 0x24c4, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x24c4, 0x2800, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x2800, 0x2804, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x2804, 0x2c00, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c00, 0x2c20, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c20, 0x3000, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3000, 0x3014, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3014, 0x3400, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3400, 0x3408, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3408, 0x3800, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3800, 0x3808, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3808, 0x3c00, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3c00, 0x3d00, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x3d00, 0x4000, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4000, 0x4010, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4010, 0x4400, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4400, 0x4458, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4458, 0x4800, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4800, 0x4808, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4808, 0x4c00, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c00, 0x4c08, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c08, 0x5000, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x5000, 0x5050, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x5050, 0x5400, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x5400, 0x5450, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x5450, 0x5800, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x5800, 0x5a10, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x5a10, 0x6000, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x6000, 0x600c, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x600c, 0x6400, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x6400, 0x6404, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x6404, 0x6800, 1);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x6800, 0x6848, 0);
+               bcm5700_get_reg_blk(pUmDevice, &buf, 0x6848, 0x6c00, 1);
+
+               i = mm_copy_to_user(useraddr + sizeof(eregs), buf1, eregs.len);
+               kfree(buf1);
+               if (i)
+                       return -EFAULT;
+               return 0;
+       }
+#endif
+#endif
+#ifdef ETHTOOL_GPAUSEPARAM
+       case ETHTOOL_GPAUSEPARAM: {
+               struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM };
+
+               if (!pDevice->DisableAutoNeg) {
+                       epause.autoneg = (pDevice->FlowControlCap &
+                               LM_FLOW_CONTROL_AUTO_PAUSE) != 0;
+               }
+               else {
+                       epause.autoneg = 0;
+               }
+               epause.rx_pause =
+                       (pDevice->FlowControl &
+                       LM_FLOW_CONTROL_RECEIVE_PAUSE) != 0;
+               epause.tx_pause =
+                       (pDevice->FlowControl &
+                       LM_FLOW_CONTROL_TRANSMIT_PAUSE) != 0;
+               if (mm_copy_to_user(useraddr, &epause, sizeof(epause)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       case ETHTOOL_SPAUSEPARAM: {
+               struct ethtool_pauseparam epause;
+               unsigned long flags;
+
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               if (mm_copy_from_user(&epause, useraddr, sizeof(epause)))
+                       return -EFAULT;
+               pDevice->FlowControlCap = 0;
+               if (epause.autoneg && !pDevice->DisableAutoNeg) {
+                       pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
+               }
+               if (epause.rx_pause)  {
+                       pDevice->FlowControlCap |=
+                               LM_FLOW_CONTROL_RECEIVE_PAUSE;
+               }
+               if (epause.tx_pause)  {
+                       pDevice->FlowControlCap |=
+                               LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+               }
+               if (netif_running(dev)) {
+                       BCM5700_PHY_LOCK(pUmDevice, flags);
+                       LM_SetupPhy(pDevice);
+                       BCM5700_PHY_UNLOCK(pUmDevice, flags);
+               }
+
+               return 0;
+       }
+#endif
+#ifdef ETHTOOL_GRXCSUM
+       case ETHTOOL_GRXCSUM: {
+               struct ethtool_value edata = { ETHTOOL_GRXCSUM };
+
+               edata.data =
+                       (pDevice->TaskToOffload &
+                       LM_TASK_OFFLOAD_RX_TCP_CHECKSUM) != 0;
+               if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       case ETHTOOL_SRXCSUM: {
+               struct ethtool_value edata;
+
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
+                       return -EFAULT;
+               if (edata.data) {
+                       if (!(pDevice->TaskOffloadCap &
+                               LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
+
+                               return -EINVAL;
+                       }
+                       pDevice->TaskToOffload |=
+                               LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+                               LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+               }
+               else {
+                       pDevice->TaskToOffload &=
+                               ~(LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+                               LM_TASK_OFFLOAD_RX_UDP_CHECKSUM);
+               }
+               return 0;
+       }
+       case ETHTOOL_GTXCSUM: {
+               struct ethtool_value edata = { ETHTOOL_GTXCSUM };
+
+               edata.data =
+                       (dev->features & get_csum_flag( pDevice->ChipRevId)) != 0;
+               if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       case ETHTOOL_STXCSUM: {
+               struct ethtool_value edata;
+
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
+                       return -EFAULT;
+               if (edata.data) {
+                       if (!(pDevice->TaskOffloadCap &
+                               LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
+
+                               return -EINVAL;
+                       }
+                       dev->features |= get_csum_flag( pDevice->ChipRevId);
+                       pDevice->TaskToOffload |=
+                               LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+                               LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
+               }
+               else {
+                       dev->features &= ~get_csum_flag( pDevice->ChipRevId);
+                       pDevice->TaskToOffload &=
+                               ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+                               LM_TASK_OFFLOAD_TX_UDP_CHECKSUM);
+               }
+               return 0;
+       }
+       case ETHTOOL_GSG: {
+               struct ethtool_value edata = { ETHTOOL_GSG };
+
+               edata.data =
+                       (dev->features & NETIF_F_SG) != 0;
+               if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
+                       return -EFAULT;
+               return 0;
+       }
+       case ETHTOOL_SSG: {
+               struct ethtool_value edata;
+
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
+                       return -EFAULT;
+               if (edata.data) {
+                       dev->features |= NETIF_F_SG;
+               }
+               else {
+                       dev->features &= ~NETIF_F_SG;
+               }
+               return 0;
+       }
+#endif
+#ifdef ETHTOOL_GRINGPARAM
+       case ETHTOOL_GRINGPARAM: {
+               struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM };
+
+               ering.rx_max_pending = T3_STD_RCV_RCB_ENTRY_COUNT - 1;
+               ering.rx_pending = pDevice->RxStdDescCnt;
+               ering.rx_mini_max_pending = 0;
+               ering.rx_mini_pending = 0;
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+               ering.rx_jumbo_max_pending = T3_JUMBO_RCV_RCB_ENTRY_COUNT - 1;
+               ering.rx_jumbo_pending = pDevice->RxJumboDescCnt;
+#else
+               ering.rx_jumbo_max_pending = 0;
+               ering.rx_jumbo_pending = 0;
+#endif
+               ering.tx_max_pending = MAX_TX_PACKET_DESC_COUNT - 1;
+               ering.tx_pending = pDevice->TxPacketDescCnt;
+               if (mm_copy_to_user(useraddr, &ering, sizeof(ering)))
+                       return -EFAULT;
+               return 0;
+       }
+#endif
+#ifdef ETHTOOL_PHYS_ID
+       case ETHTOOL_PHYS_ID: {
+               struct ethtool_value edata;
+
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
+                       return -EFAULT;
+               if (LM_BlinkLED(pDevice, edata.data) == LM_STATUS_SUCCESS)
+                       return 0;
+               return -EINTR;
+       }
+#endif
+#ifdef ETHTOOL_GSTRINGS
+       case ETHTOOL_GSTRINGS: {
+               struct ethtool_gstrings egstr = { ETHTOOL_GSTRINGS };
+
+               if (mm_copy_from_user(&egstr, useraddr, sizeof(egstr)))
+                       return -EFAULT;
+               switch(egstr.string_set) {
+#ifdef ETHTOOL_GSTATS
+               case ETH_SS_STATS:
+                       egstr.len = ETH_NUM_STATS;
+                       if (mm_copy_to_user(useraddr, &egstr, sizeof(egstr)))
+                               return -EFAULT;
+                       if (mm_copy_to_user(useraddr + sizeof(egstr),
+                               bcm5700_stats_str_arr,
+                               sizeof(bcm5700_stats_str_arr)))
+                               return -EFAULT;
+                       return 0;
+#endif
+#ifdef ETHTOOL_TEST
+               case ETH_SS_TEST:
+                       egstr.len = ETH_NUM_TESTS;
+                       if (mm_copy_to_user(useraddr, &egstr, sizeof(egstr)))
+                               return -EFAULT;
+                       if (mm_copy_to_user(useraddr + sizeof(egstr),
+                               bcm5700_tests_str_arr,
+                               sizeof(bcm5700_tests_str_arr)))
+                               return -EFAULT;
+                       return 0;
+#endif
+               default:
+                       return -EOPNOTSUPP;
+               }
+               }
+#endif
+#ifdef ETHTOOL_GSTATS
+       case ETHTOOL_GSTATS: {
+               struct ethtool_stats estats = { ETHTOOL_GSTATS };
+               uint64_t stats[ETH_NUM_STATS];
+               int i;
+               uint64_t *pStats =
+                       (uint64_t *) pDevice->pStatsBlkVirt;
+
+               estats.n_stats = ETH_NUM_STATS;
+               if (pStats == 0) {
+                       memset(stats, 0, sizeof(stats));
+               }
+               else {
+
+                       for (i = 0; i < ETH_NUM_STATS; i++) {
+                               if (bcm5700_stats_offset_arr[i] != 0) {
+                                       stats[i] = SWAP_DWORD_64(*(pStats +
+                                               bcm5700_stats_offset_arr[i]));
+                               }
+                               else if (i == RX_CRC_IDX) {
+                                       stats[i] =
+                                               bcm5700_crc_count(pUmDevice);
+                               }
+                               else if (i == RX_MAC_ERR_IDX) {
+                                       stats[i] =
+                                               bcm5700_rx_err_count(pUmDevice);
+                               }
+                       }
+               }
+               if (mm_copy_to_user(useraddr, &estats, sizeof(estats))) {
+                       return -EFAULT;
+               }
+               if (mm_copy_to_user(useraddr + sizeof(estats), &stats,
+                       sizeof(stats))) {
+                       return -EFAULT;
+               }
+               return 0;
+       }
+#endif
+#ifdef ETHTOOL_TEST
+       case ETHTOOL_TEST: {
+               struct ethtool_test etest;
+               uint64_t tests[ETH_NUM_TESTS] = {0, 0, 0, 0, 0, 0};
+               LM_POWER_STATE old_power_level;
+
+               printk( KERN_ALERT "Performing ethtool test.\n"
+                                  "This test will take a few seconds to complete.\n" );
+
+               if (mm_copy_from_user(&etest, useraddr, sizeof(etest)))
+                       return -EFAULT;
+
+               etest.len = ETH_NUM_TESTS;
+               old_power_level = pDevice->PowerLevel;
+               if (old_power_level != LM_POWER_STATE_D0) {
+                       LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+                       LM_SwitchClocks(pDevice);
+               }
+               MM_Sleep(pDevice, 1000);
+               if (etest.flags & ETH_TEST_FL_OFFLINE) {
+                       b57_suspend_chip(pUmDevice);
+                       MM_Sleep(pDevice, 1000);
+                       LM_HaltCpu(pDevice,T3_RX_CPU_ID | T3_TX_CPU_ID);
+                       MM_Sleep(pDevice, 1000);
+                       if (b57_test_registers(pUmDevice) == 0) {
+                               etest.flags |= ETH_TEST_FL_FAILED;
+                               tests[0] = 1;
+                       }
+                       MM_Sleep(pDevice, 1000);
+                       if (b57_test_memory(pUmDevice) == 0) {
+                               etest.flags |= ETH_TEST_FL_FAILED;
+                               tests[1] = 1;
+                       }
+                       MM_Sleep(pDevice, 1000);
+                       if (b57_test_loopback(pUmDevice, NICE_LOOPBACK_TESTTYPE_MAC, 0) == 0) {
+                               etest.flags |= ETH_TEST_FL_FAILED;
+                               tests[2] = 1;
+                       }
+                       MM_Sleep(pDevice, 1000);
+                       b57_resume_chip(pUmDevice);
+                       /* wait for link to come up for the link test */
+                       MM_Sleep(pDevice, 4000);
+                       if ((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) &&
+                               !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
+
+                               /* wait a little longer for linkup on copper */
+                               MM_Sleep(pDevice, 3000);
+                       }
+               }
+               if (b57_test_nvram(pUmDevice) == 0) {
+                       etest.flags |= ETH_TEST_FL_FAILED;
+                       tests[3] = 1;
+               }
+               MM_Sleep(pDevice, 1000);
+               if (b57_test_intr(pUmDevice) == 0) {
+                       etest.flags |= ETH_TEST_FL_FAILED;
+                       tests[4] = 1;
+               }
+               MM_Sleep(pDevice, 1000);
+               if (b57_test_link(pUmDevice) == 0) {
+                       etest.flags |= ETH_TEST_FL_FAILED;
+                       tests[5] = 1;
+               }
+               MM_Sleep(pDevice, 1000);
+               if (old_power_level != LM_POWER_STATE_D0) {
+                       LM_SetPowerState(pDevice, old_power_level);
+               }
+               if (mm_copy_to_user(useraddr, &etest, sizeof(etest))) {
+                       return -EFAULT;
+               }
+               if (mm_copy_to_user(useraddr + sizeof(etest), tests,
+                       sizeof(tests))) {
+                       return -EFAULT;
+               }
+               return 0;
+       }
+#endif
+#ifdef ETHTOOL_GTSO
+       case ETHTOOL_GTSO: {
+               struct ethtool_value edata = { ETHTOOL_GTSO };
+
+#ifdef BCM_TSO
+               edata.data =
+                       (dev->features & NETIF_F_TSO) != 0;
+#else
+               edata.data = 0;
+#endif
+               if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
+                       return -EFAULT;
+               return 0;
+       }
+#endif
+#ifdef ETHTOOL_STSO
+       case ETHTOOL_STSO: {
+#ifdef BCM_TSO
+               struct ethtool_value edata;
+
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+
+               if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
+                       return -EFAULT;
+
+               if (!(pDevice->TaskToOffload &
+                       LM_TASK_OFFLOAD_TCP_SEGMENTATION)) {
+                       return -EINVAL;
+               }
+
+               dev->features &= ~NETIF_F_TSO;
+
+               if (edata.data) {
+                       if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
+                          (dev->mtu > 1500)) {
+                               printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
+                       return -EINVAL;
+                       } else {
+                               dev->features |= NETIF_F_TSO;
+                       }
+               }
+               return 0;
+#else
+               return -EINVAL;
+#endif
+       }
+#endif
+       }
+
+       return -EOPNOTSUPP;
+}
+#endif /* #ifdef SIOCETHTOOL */
+
+#if (LINUX_VERSION_CODE >= 0x20400) && (LINUX_VERSION_CODE < 0x20600)
+#include <linux/iobuf.h>
+#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. */
+               if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+                       return -EOPNOTSUPP;
+
+               /* workaround for DHCP using ifup script */
+               /* ifup only waits for 5 seconds for link up */
+               /* NIC may take more than 5 seconds to establish link */
+               if ((pUmDevice->delayed_link_ind > 0) &&
+                       delay_link[pUmDevice->index]) {
+                       return -EOPNOTSUPP;
+               }
+
+               BCM5700_PHY_LOCK(pUmDevice, flags);
+               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;
+
+               if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+                       return -EOPNOTSUPP;
+
+               BCM5700_PHY_LOCK(pUmDevice, flags);
+               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;
+#ifdef BCM_NAPI_RXPOLL
+                       nrq->nrq_support_rx_napi = 1;
+#endif
+                       return 0;
+               }
+#ifdef BCM_NAPI_RXPOLL
+               else if( nrq->cmd == NICE_CMD_SET_RX_NAPI )
+#else
+               else if( nrq->cmd == NICE_CMD_SET_RX )
+#endif
+               {
+                       pUmDevice->nice_rx = nrq->nrq_rx;
+                       pUmDevice->nice_ctx = nrq->nrq_ctx;
+                       bcm5700_set_vlan_mode(pUmDevice);
+                       return 0;
+               }
+#ifdef BCM_NAPI_RXPOLL
+               else if( nrq->cmd == NICE_CMD_GET_RX_NAPI )
+#else
+               else if( nrq->cmd == NICE_CMD_GET_RX )
+#endif
+               {
+                       nrq->nrq_rx = pUmDevice->nice_rx;
+                       nrq->nrq_ctx = pUmDevice->nice_ctx;
+                       return 0;
+               }
+               else if( nrq->cmd == NICE_CMD_GET_SPEED ) {
+                       if(pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE){
+                               nrq->nrq_speed = 0;
+                       }
+                       else if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) {
+                               nrq->nrq_speed = SPEED_1000;
+                       } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) {
+                               nrq->nrq_speed = SPEED_100;
+                       } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) {
+                               nrq->nrq_speed = SPEED_100;
+                       } else {
+                               nrq->nrq_speed = 0;
+                       }
+                       return 0;
+               }
+               else {
+                       if (!pUmDevice->opened)
+                               return -EINVAL;
+
+                       switch (nrq->cmd) {
+                       case NICE_CMD_BLINK_LED:
+                               if (LM_BlinkLED(pDevice, nrq->nrq_blink_time) ==
+                                       LM_STATUS_SUCCESS) {
+                                       return 0;
+                               }
+                               return -EINTR;
+
+                       case NICE_CMD_DIAG_SUSPEND:
+                               b57_suspend_chip(pUmDevice);
+                               return 0;
+
+                       case NICE_CMD_DIAG_RESUME:
+                               b57_resume_chip(pUmDevice);
+                               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_REG_READ_DIRECT:
+                       case NICE_CMD_REG_WRITE_DIRECT:
+                               if ((nrq->nrq_offset >= 0x10000) ||
+                                       (pDevice->Flags & UNDI_FIX_FLAG)) {
+                                       return -EINVAL;
+                               }
+
+                               if (nrq->cmd == NICE_CMD_REG_READ_DIRECT) {
+                                       nrq->nrq_data = REG_RD_OFFSET(pDevice,
+                                               nrq->nrq_offset);
+                               }
+                               else {
+                                       REG_WR_OFFSET(pDevice, nrq->nrq_offset,
+                                                       nrq->nrq_data);
+                               }
+                               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_CFG_READ32:
+                               pci_read_config_dword(pUmDevice->pdev,
+                                       nrq->nrq_offset, (u32 *)&nrq->nrq_data);
+                               return 0;
+
+                       case NICE_CMD_CFG_READ16:
+                               pci_read_config_word(pUmDevice->pdev,
+                                       nrq->nrq_offset, (u16 *)&nrq->nrq_data);
+                               return 0;
+
+                       case NICE_CMD_CFG_READ8:
+                               pci_read_config_byte(pUmDevice->pdev,
+                                       nrq->nrq_offset, (u8 *)&nrq->nrq_data);
+                               return 0;
+
+                       case NICE_CMD_CFG_WRITE32:
+                               pci_write_config_dword(pUmDevice->pdev,
+                                       nrq->nrq_offset, (u32)nrq->nrq_data);
+                               return 0;
+
+                       case NICE_CMD_CFG_WRITE16:
+                               pci_write_config_word(pUmDevice->pdev,
+                                       nrq->nrq_offset, (u16)nrq->nrq_data);
+                               return 0;
+
+                       case NICE_CMD_CFG_WRITE8:
+                               pci_write_config_byte(pUmDevice->pdev,
+                                       nrq->nrq_offset, (u8)nrq->nrq_data);
+                               return 0;
+
+                       case NICE_CMD_RESET:
+                               bcm5700_reset(dev);
+                               return 0;
+
+                       case NICE_CMD_ENABLE_MAC_LOOPBACK:
+                               if (pDevice->LoopBackMode != 0) {
+                                       return -EINVAL;
+                               }
+
+                               BCM5700_PHY_LOCK(pUmDevice, flags);
+                               LM_EnableMacLoopBack(pDevice);
+                               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+                               return 0;
+
+                       case NICE_CMD_DISABLE_MAC_LOOPBACK:
+                               if (pDevice->LoopBackMode !=
+                                       LM_MAC_LOOP_BACK_MODE) {
+                                       return -EINVAL;
+                               }
+
+                               BCM5700_PHY_LOCK(pUmDevice, flags);
+                               LM_DisableMacLoopBack(pDevice);
+                               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+                               return 0;
+
+                       case NICE_CMD_ENABLE_PHY_LOOPBACK:
+                               if (pDevice->LoopBackMode != 0) {
+                                       return -EINVAL;
+                               }
+
+                               BCM5700_PHY_LOCK(pUmDevice, flags);
+                               LM_EnablePhyLoopBack(pDevice);
+                               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+                               return 0;
+
+                       case NICE_CMD_DISABLE_PHY_LOOPBACK:
+                               if (pDevice->LoopBackMode !=
+                                       LM_PHY_LOOP_BACK_MODE) {
+                                       return -EINVAL;
+                               }
+
+                               BCM5700_PHY_LOCK(pUmDevice, flags);
+                               LM_DisablePhyLoopBack(pDevice);
+                               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+                               return 0;
+
+                       case NICE_CMD_ENABLE_EXT_LOOPBACK:
+                               if (pDevice->LoopBackMode != 0) {
+                                       return -EINVAL;
+                               }
+
+                               if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
+                                       if (nrq->nrq_speed != 1000)
+                                               return -EINVAL;
+                               }
+                               else {
+                                       if ((nrq->nrq_speed != 1000) &&
+                                               (nrq->nrq_speed != 100) &&
+                                               (nrq->nrq_speed != 10)) {
+                                               return -EINVAL;
+                                       }
+                               }
+                               BCM5700_PHY_LOCK(pUmDevice, flags);
+                               LM_EnableExtLoopBack(pDevice, nrq->nrq_speed);
+                               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+                               return 0;
+
+                       case NICE_CMD_DISABLE_EXT_LOOPBACK:
+                               if (pDevice->LoopBackMode !=
+                                       LM_EXT_LOOP_BACK_MODE) {
+                                       return -EINVAL;
+                               }
+
+                               BCM5700_PHY_LOCK(pUmDevice, flags);
+                               LM_DisableExtLoopBack(pDevice);
+                               BCM5700_PHY_UNLOCK(pUmDevice, flags);
+                               return 0;
+
+                       case NICE_CMD_INTERRUPT_TEST:
+                               nrq->nrq_intr_test_result =
+                                       b57_test_intr(pUmDevice);
+                               return 0;
+
+                       case NICE_CMD_LOOPBACK_TEST:
+                               value = 0;
+                               switch (nrq->nrq_looptype) {
+                                       case NICE_LOOPBACK_TESTTYPE_EXT:
+                                               if ((nrq->nrq_loopspeed & ~NICE_LOOPBACK_TEST_SPEEDMASK) ||
+                                                  !(nrq->nrq_loopspeed & NICE_LOOPBACK_TEST_SPEEDMASK))
+                                                       break;
+                                               switch (nrq->nrq_loopspeed) {
+                                                       case NICE_LOOPBACK_TEST_10MBPS:
+                                                               value = LM_LINE_SPEED_10MBPS;
+                                                               break;
+                                                       case NICE_LOOPBACK_TEST_100MBPS:
+                                                               value = LM_LINE_SPEED_100MBPS;
+                                                               break;
+                                                       case NICE_LOOPBACK_TEST_1000MBPS:
+                                                               value = LM_LINE_SPEED_1000MBPS;
+                                                               break;
+                                               }
+                                               /* Fall through */
+
+                                       case NICE_LOOPBACK_TESTTYPE_MAC:
+                                       case NICE_LOOPBACK_TESTTYPE_PHY:
+                                               b57_suspend_chip(pUmDevice);
+                                               value = b57_test_loopback(pUmDevice,
+                                                                         nrq->nrq_looptype, value);
+                                               b57_resume_chip(pUmDevice);
+                                               break;
+                               }
+
+                               if (value == 1) {
+                                       /* A '1' indicates success */
+                                       value = 0;
+                               } else {
+                                       value = -EINTR;
+                               }
+
+                               return value;
+
+                       case NICE_CMD_KMALLOC_PHYS: {
+#if (LINUX_VERSION_CODE >= 0x020400)
+                                dma_addr_t mapping;
+                                __u64 cpu_pa;
+                                void *ptr;
+                                int i;
+                                struct page *pg, *last_pg;
+
+                                for (i = 0; i < MAX_MEM2; i++) {
+                                        if (pUmDevice->mem_size_list2[i] == 0)
+                                                break;
+                                }
+                                if (i >= MAX_MEM2)
+                                        return -EFAULT;
+                                ptr = pci_alloc_consistent(pUmDevice->pdev,
+                                        nrq->nrq_size, &mapping);
+                                if (!ptr) {
+                                        return -EFAULT;
+                                }
+                                pUmDevice->mem_size_list2[i] = nrq->nrq_size;
+                                pUmDevice->mem_list2[i] = ptr;
+                                pUmDevice->dma_list2[i] = mapping;
+
+                                /* put pci mapping at the beginning of buffer */
+                                *((__u64 *) ptr) = (__u64) mapping;
+
+                                /* Probably won't work on some architectures */
+                                /* get CPU mapping */
+                                cpu_pa = (__u64) virt_to_phys(ptr);
+                                pUmDevice->cpu_pa_list2[i] = cpu_pa;
+                                nrq->nrq_phys_addr_lo = (__u32) cpu_pa;
+                                nrq->nrq_phys_addr_hi = (__u32) (cpu_pa >> 32);
+
+                                pg = virt_to_page(ptr);
+                                last_pg = virt_to_page(ptr + nrq->nrq_size - 1);
+                                for (; ; pg++) {
+#if (LINUX_VERSION_CODE > 0x020500)
+                                        SetPageReserved(pg);
+#else
+                                        mem_map_reserve(pg);
+#endif
+                                        if (pg == last_pg)
+                                                break;
+                                }
+                                return 0;
+#else
+                                return -EOPNOTSUPP;
+#endif
+                       }
+
+                       case NICE_CMD_KFREE_PHYS: {
+                                int i;
+                                __u64 cpu_pa;
+
+                                cpu_pa = (__u64) nrq->nrq_phys_addr_lo +
+                                        ((__u64) nrq->nrq_phys_addr_hi << 32);
+                                for (i = 0; i < MAX_MEM2; i++) {
+                                        if (pUmDevice->cpu_pa_list2[i] ==
+                                                cpu_pa)
+                                        {
+                                                break;
+                                        }
+                                }
+                                if (i >= MAX_MEM2)
+                                        return -EFAULT;
+
+                                bcm5700_freemem2(pUmDevice, i);
+                                return 0;
+                       }
+
+                       case NICE_CMD_SET_WRITE_PROTECT:
+                               if (nrq->nrq_write_protect)
+                                       pDevice->Flags |= EEPROM_WP_FLAG;
+                               else
+                                       pDevice->Flags &= ~EEPROM_WP_FLAG;
+                               return 0;
+                       case NICE_CMD_GET_STATS_BLOCK: {
+                               PT3_STATS_BLOCK pStats =
+                                       (PT3_STATS_BLOCK)pDevice->pStatsBlkVirt;
+                               if (mm_copy_to_user(nrq->nrq_stats_useraddr,
+                                       pStats, nrq->nrq_stats_size)) {
+                                       return -EFAULT;
+                               }
+                               return 0;
+                       }
+                       case NICE_CMD_CLR_STATS_BLOCK: {
+                               int j;
+                               PT3_STATS_BLOCK pStats =
+                                       (PT3_STATS_BLOCK)pDevice->pStatsBlkVirt;
+
+                               memset(pStats, 0, sizeof(T3_STATS_BLOCK));
+                               if (T3_ASIC_REV(pDevice->ChipRevId) ==
+                                       T3_ASIC_REV_5705) {
+                                       return 0;
+                               }
+                               for(j = 0x0300; j < 0x0b00; j = j + 4) {
+                                       MEM_WR_OFFSET(pDevice, j, 0);
+                               }
+
+                               return 0;
+                       }
+
+                       }
+               }
+               return -EOPNOTSUPP;
+       }
+#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_do_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);
+       }
+
+}
+
+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;
+       unsigned long flags;
+
+       BCM5700_PHY_LOCK(pUmDevice, flags);
+
+       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);
+       }
+
+       BCM5700_PHY_UNLOCK(pUmDevice, flags);
+}
+
+/*
+ * 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;
+
+       if(is_valid_ether_addr(addr->sa_data)){
+
+           memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+           if (pUmDevice->opened)
+               LM_SetMacAddress(pDevice, dev->dev_addr);
+            return 0;
+        }
+       return -EINVAL;
+}
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+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 ( !(pDevice->Flags & JUMBO_CAPABLE_FLAG)    &&
+               (pkt_size > MAX_ETHERNET_PACKET_SIZE_NO_CRC) ) {
+
+               return -EINVAL;
+       }
+       if (pUmDevice->suspended)
+               return -EAGAIN;
+
+       if (pUmDevice->opened && (new_mtu != dev->mtu) &&
+               (pDevice->Flags & JUMBO_CAPABLE_FLAG)) {
+               reinit = 1;
+       }
+
+       BCM5700_PHY_LOCK(pUmDevice, flags);
+       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 if (pDevice->Flags & JUMBO_CAPABLE_FLAG){
+               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;
+
+#ifdef BCM_TSO
+       if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
+          (dev->mtu > 1514) ) {
+               if (dev->features & NETIF_F_TSO) {
+                       dev->features &= ~NETIF_F_TSO;
+                       printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
+               }
+       }
+#endif
+
+       if (reinit) {
+               LM_InitializeAdapter(pDevice);
+               bcm5700_do_rx_mode(dev);
+               bcm5700_set_vlan_mode(pUmDevice);
+               bcm5700_init_counters(pUmDevice);
+               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;
+}
+#endif
+
+
+#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;
+
+#ifdef BCM_PROC_FS
+       bcm5700_proc_remove_notifier();
+#endif
+       /* 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);
+#if (LINUX_VERSION_CODE < 0x020600)
+               kfree(root_tigon3_dev);
+#else
+               free_netdev(root_tigon3_dev);
+#endif
+               root_tigon3_dev = next_dev;
+       }
+#ifdef BCM_IOCTL32
+       unregister_ioctl32_conversion(SIOCNICE);
+#endif
+}
+
+#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:         __devexit_p(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)
+{
+#ifdef BCM_PROC_FS
+       bcm5700_proc_remove_notifier();
+#endif
+       pci_unregister_driver(&bcm5700_pci_driver);
+}
+
+
+module_init(bcm5700_init_module);
+module_exit(bcm5700_cleanup_module);
+#endif
+
+/*
+ * Middle Module
+ *
+ */
+
+
+#ifdef BCM_NAPI_RXPOLL
+LM_STATUS
+MM_ScheduleRxPoll(LM_DEVICE_BLOCK *pDevice)
+{
+       struct net_device *dev = ((UM_DEVICE_BLOCK *) pDevice)->dev;
+
+       if (netif_rx_schedule_prep(dev)) {
+               __netif_rx_schedule(dev);
+               return LM_STATUS_SUCCESS;
+       }
+       return LM_STATUS_FAILURE;
+}
+#endif
+
+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_ATOMIC);
+       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));
+       if (pDevice->pMappedMemBase == 0)
+               return LM_STATUS_FAILURE;
+
+       return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
+{
+       unsigned 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;
+               pUmDevice->rx_buf_repl_isr_limit = 0;
+       }
+       else {
+               pUmDevice->rx_buf_repl_thresh = pDevice->RxPacketDescCnt / 8;
+               pUmDevice->rx_buf_repl_panic_thresh =
+                       pDevice->RxPacketDescCnt  * 7 / 8;
+
+               /* This limits the time spent in the ISR when the receiver */
+               /* is in a steady state of being overrun. */
+               pUmDevice->rx_buf_repl_isr_limit = pDevice->RxPacketDescCnt / 8;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+               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;
+                       }
+               }
+#endif
+       }
+       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;
+
+       if (index >= MAX_UNITS)
+               return LM_STATUS_SUCCESS;
+
+#if LINUX_KERNEL_VERSION < 0x0020609
+
+       bcm5700_validate_param_range(pUmDevice, &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(pUmDevice, &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->PhyFlags & PHY_NO_GIGABIT) {
+                               pDevice->RequestedLineSpeed =
+                                       LM_LINE_SPEED_100MBPS;
+                               printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (1000), using 100\n", bcm5700_driver, index);
+                       }
+                       else {
+                               if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+                                       !full_duplex[index]) {
+                                       printk(KERN_WARNING "%s-%d: Invalid full_duplex parameter (0) for fiber, using 1\n", bcm5700_driver, index);
+                                       pDevice->RequestedDuplexMode =
+                                               LM_DUPLEX_MODE_FULL;
+                               }
+
+                               if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+                                       !auto_speed[index] && !(pDevice->PhyFlags & PHY_IS_FIBER) ) {
+                                       printk(KERN_WARNING "%s-%d: Invalid auto_speed parameter (0) for copper, using 1\n", bcm5700_driver, index);
+                                       pDevice->DisableAutoNeg = FALSE;
+                               }
+                       }
+               }
+               else if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) ||
+                         (pDevice->PhyFlags & PHY_IS_FIBER)){
+                        pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+                        pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
+                        pDevice->DisableAutoNeg = FALSE;
+                        printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using auto\n", bcm5700_driver, index, line_speed[index]);
+               }
+               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-%d: Invalid line_speed parameter (%d), using 0\n", bcm5700_driver, index, line_speed[index]);
+               }
+
+       }
+
+#endif /* LINUX_KERNEL_VERSION */
+
+       /* This is an unmanageable switch nic and will have link problems if
+          not set to auto
+       */
+       if(pDevice->SubsystemVendorId==0x103c && pDevice->SubsystemId==0x3226)
+       {
+           if(pDevice->RequestedLineSpeed != LM_LINE_SPEED_AUTO)
+           {
+               printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using 0\n",
+                       bcm5700_driver, index, line_speed[index]);
+           }
+           pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
+           pDevice->DisableAutoNeg = FALSE;
+       }
+
+#if LINUX_KERNEL_VERSION < 0x0020609
+
+       pDevice->FlowControlCap = 0;
+       bcm5700_validate_param_range(pUmDevice, &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(pUmDevice, &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(pUmDevice, &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) {
+#ifdef BCM_TSO
+               if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
+                  (dev->features & NETIF_F_TSO)) {
+                               dev->features &= ~NETIF_F_TSO;
+                               printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
+               }
+#endif
+               pDevice->RxMtu = dev->mtu + 14;
+       }
+
+       if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+               !(pDevice->Flags & BCM5788_FLAG)) {
+               pDevice->Flags |= USE_TAGGED_STATUS_FLAG;
+               pUmDevice->timer_interval = HZ;
+               if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) &&
+                       (pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
+                       pUmDevice->timer_interval = HZ/4;
+               }
+       }
+       else {
+               pUmDevice->timer_interval = HZ/10;
+       }
+
+       bcm5700_validate_param_range(pUmDevice, &tx_pkt_desc_cnt[index],
+               "tx_pkt_desc_cnt", 1, MAX_TX_PACKET_DESC_COUNT-1, TX_DESC_CNT);
+       pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
+       bcm5700_validate_param_range(pUmDevice, &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];
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+       bcm5700_validate_param_range(pUmDevice, &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 if(!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
+               pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
+        }
+#endif
+
+#ifdef BCM_INT_COAL
+       bcm5700_validate_param_range(pUmDevice, &adaptive_coalesce[index],
+               "adaptive_coalesce", 0, 1, 1);
+#ifdef BCM_NAPI_RXPOLL
+       if (adaptive_coalesce[index]) {
+               printk(KERN_WARNING "%s-%d: adaptive_coalesce not used in NAPI mode\n", bcm5700_driver, index);
+               adaptive_coalesce[index] = 0;
+
+       }
+#endif
+       pUmDevice->adaptive_coalesce = adaptive_coalesce[index];
+       if (!pUmDevice->adaptive_coalesce) {
+               bcm5700_validate_param_range(pUmDevice,
+                       &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-%d: Conflicting rx_coalesce_ticks (0) and rx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
+                               bcm5700_driver, index, RX_COAL_TK, RX_COAL_FM);
+
+                       rx_coalesce_ticks[index] = RX_COAL_TK;
+                       rx_max_coalesce_frames[index] = RX_COAL_FM;
+               }
+               pDevice->RxCoalescingTicks = pUmDevice->rx_curr_coalesce_ticks =
+                       rx_coalesce_ticks[index];
+#ifdef BCM_NAPI_RXPOLL
+               pDevice->RxCoalescingTicksDuringInt = rx_coalesce_ticks[index];
+#endif
+
+               bcm5700_validate_param_range(pUmDevice,
+                       &rx_max_coalesce_frames[index],
+                       "rx_max_coalesce_frames", 0,
+                       MAX_RX_MAX_COALESCED_FRAMES, RX_COAL_FM);
+
+               pDevice->RxMaxCoalescedFrames =
+                       pUmDevice->rx_curr_coalesce_frames =
+                       rx_max_coalesce_frames[index];
+#ifdef BCM_NAPI_RXPOLL
+               pDevice->RxMaxCoalescedFramesDuringInt =
+                       rx_max_coalesce_frames[index];
+#endif
+
+               bcm5700_validate_param_range(pUmDevice,
+                       &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-%d: Conflicting tx_coalesce_ticks (0) and tx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
+                               bcm5700_driver, index, 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(pUmDevice,
+                       &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(pUmDevice,
+                       &stats_coalesce_ticks[index], "stats_coalesce_ticks",
+                       0, MAX_STATS_COALESCING_TICKS, ST_COAL_TK);
+               if (adaptive_coalesce[index]) {
+                       printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter set with with adaptive_coalesce parameter. Using adaptive_coalesce.\n", bcm5700_driver, index);
+               }else{
+                       if ((stats_coalesce_ticks[index] > 0) &&
+                               (stats_coalesce_ticks[index] < 100)) {
+                               printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter (%u), using 100\n", bcm5700_driver, index, (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
+
+       if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
+               unsigned int tmpvar;
+
+               tmpvar = pDevice->StatsCoalescingTicks / BCM_TIMER_GRANULARITY;
+
+               /*
+                * If the result is zero, the request is too demanding.
+                */
+               if (tmpvar == 0) {
+                       tmpvar = 1;
+               }
+
+               pDevice->StatsCoalescingTicks = tmpvar * BCM_TIMER_GRANULARITY;
+
+               pUmDevice->statstimer_interval = tmpvar;
+       }
+
+#ifdef BCM_WOL
+       bcm5700_validate_param_range(pUmDevice, &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 INCLUDE_TBI_SUPPORT
+       if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
+               if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) ||
+                       (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)) {
+                       /* just poll since we have hardware autoneg. in 5704 */
+                       pDevice->TbiFlags |= TBI_PURE_POLLING_FLAG;
+               }
+               else {
+                       pDevice->TbiFlags |= TBI_POLLING_INTR_FLAG;
+               }
+       }
+#endif
+       bcm5700_validate_param_range(pUmDevice, &scatter_gather[index],
+               "scatter_gather", 0, 1, 1);
+       bcm5700_validate_param_range(pUmDevice, &tx_checksum[index],
+               "tx_checksum", 0, 1, 1);
+       bcm5700_validate_param_range(pUmDevice, &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-%d: Checksum offload not available on this NIC\n", bcm5700_driver, index);
+               }
+       }
+       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->Flags |= NO_TX_PSEUDO_HDR_CSUM_FLAG;
+               }
+       }
+#ifdef BCM_TSO
+       bcm5700_validate_param_range(pUmDevice, &enable_tso[index],
+               "enable_tso", 0, 1, 1);
+
+       /* Always enable TSO firmware if supported */
+       /* This way we can turn it on or off on the fly */
+       if (pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
+       {
+               pDevice->TaskToOffload |=
+                       LM_TASK_OFFLOAD_TCP_SEGMENTATION;
+       }
+       if (enable_tso[index] &&
+               !(pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION))
+       {
+               printk(KERN_WARNING "%s-%d: TSO not available on this NIC\n", bcm5700_driver, index);
+       }
+#endif
+#ifdef BCM_ASF
+       bcm5700_validate_param_range(pUmDevice, &vlan_tag_mode[index],
+               "vlan_strip_mode", 0, 2, 0);
+       pUmDevice->vlan_tag_mode = vlan_tag_mode[index];
+#else
+       pUmDevice->vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP;
+#endif
+
+#endif /* LINUX_KERNEL_VERSION */
+
+#ifdef BCM_NIC_SEND_BD
+       bcm5700_validate_param_range(pUmDevice, &nic_tx_bd[index], "nic_tx_bd",
+               0, 1, 0);
+       if (nic_tx_bd[index])
+               pDevice->Flags |= NIC_SEND_BD_FLAG;
+       if ((pDevice->Flags & ENABLE_PCIX_FIX_FLAG) ||
+               (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)) {
+               if (pDevice->Flags & NIC_SEND_BD_FLAG) {
+                       pDevice->Flags &= ~NIC_SEND_BD_FLAG;
+                       printk(KERN_WARNING "%s-%d: Nic Send BDs not available on this NIC or not possible on this system\n", bcm5700_driver, index);
+               }
+       }
+#endif
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
+       bcm5700_validate_param_range(pUmDevice, &disable_msi[pUmDevice->index],
+               "disable_msi", 0, 1, 0);
+#endif
+
+       bcm5700_validate_param_range(pUmDevice, &delay_link[index],
+               "delay_link", 0, 1, 0);
+
+       bcm5700_validate_param_range(pUmDevice, &disable_d3hot[index],
+               "disable_d3hot", 0, 1, 0);
+       if (disable_d3hot[index]) {
+
+#ifdef BCM_WOL
+               if (enable_wol[index]) {
+                       pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
+                       pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE;
+                       printk(KERN_WARNING "%s-%d: Wake-On-Lan disabled because D3Hot is disabled\n", bcm5700_driver, index);
+               }
+#endif
+               pDevice->Flags |= DISABLE_D3HOT_FLAG;
+       }
+
+    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)) {
+
+#ifdef BCM_NAPI_RXPOLL
+                               vlan_hwaccel_receive_skb(skb, pUmDevice->vlgrp,
+                                       pPacket->VlanTag);
+#else
+                               vlan_hwaccel_rx(skb, pUmDevice->vlgrp,
+                                       pPacket->VlanTag);
+#endif
+                       }
+                       else
+#endif
+                       {
+#ifdef BCM_NAPI_RXPOLL
+                               netif_receive_skb(skb);
+#else
+                               netif_rx(skb);
+#endif
+                       }
+               }
+               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, int max)
+{
+       PLM_PACKET pPacket;
+       PUM_PACKET pUmPacket;
+       PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+       struct sk_buff *skb;
+       int queue_rx = 0;
+       int alloc_cnt = 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 (max > 0) {
+                       alloc_cnt++;
+                       if (alloc_cnt >= max)
+                               break;
+               }
+       }
+       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;
+       int speed = 0;
+
+       if (!pUmDevice->opened)
+               return LM_STATUS_SUCCESS;
+
+       if (!pUmDevice->suspended) {
+               if (Status == LM_STATUS_LINK_DOWN) {
+                       netif_carrier_off(dev);
+               }
+               else if (Status == LM_STATUS_LINK_ACTIVE) {
+                       netif_carrier_on(dev);
+               }
+       }
+
+       if (pUmDevice->delayed_link_ind > 0) {
+               pUmDevice->delayed_link_ind = 0;
+               if (Status == LM_STATUS_LINK_DOWN) {
+                       printk(KERN_ERR "%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name);
+               }
+               else if (Status == LM_STATUS_LINK_ACTIVE) {
+                       printk(KERN_INFO "%s: %s NIC Link is UP, ", bcm5700_driver, dev->name);
+               }
+       }
+       else {
+               if (Status == LM_STATUS_LINK_DOWN) {
+                       printk(KERN_ERR "%s: %s NIC Link is Down\n", bcm5700_driver, dev->name);
+               }
+               else if (Status == LM_STATUS_LINK_ACTIVE) {
+                       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)
+                       speed = 1000;
+               else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
+                       speed = 100;
+               else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+                       speed = 10;
+
+               printk("%d Mbps ", 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;
+}
+
+void
+MM_UnmapRxDma(LM_DEVICE_BLOCK *pDevice, LM_PACKET *pPacket)
+{
+#if ! defined(NO_PCI_UNMAP)
+       UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+       UM_PACKET *pUmPacket = (UM_PACKET *) pPacket;
+
+       if (!pUmPacket->skbuff)
+               return;
+
+       pci_unmap_single(pUmDevice->pdev,
+                       pci_unmap_addr(pUmPacket, map[0]),
+                       pPacket->u.Rx.RxBufferSize,
+                       PCI_DMA_FROMDEVICE);
+#endif
+}
+
+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)) {
+               /* DMA address already unmapped */
+               dev_kfree_skb(skb);
+       }
+       pUmPacket->skbuff = 0;
+       return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_Sleep(LM_DEVICE_BLOCK *pDevice, LM_UINT32 msec)
+{
+       current->state = TASK_INTERRUPTIBLE;
+       if (schedule_timeout(HZ * msec / 1000) != 0) {
+               return LM_STATUS_FAILURE;
+       }
+       if (signal_pending(current))
+               return LM_STATUS_FAILURE;
+
+       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);
+#ifdef BCM_TASKLET
+       tasklet_kill(&pUmDevice->tasklet);
+#endif
+       bcm5700_poll_wait(pUmDevice);
+
+       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;
+       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) {
+
+                       MM_UnmapRxDma(pDevice, (LM_PACKET *) pUmPacket);
+                       MM_FreeRxBuffer(pDevice, &pUmPacket->lm_packet);
+                       QQ_PushTail(&pDevice->RxPacketFreeQ.Container,
+                               pUmPacket);
+               }
+       }
+}
+
+void
+bcm5700_validate_param_range(UM_DEVICE_BLOCK *pUmDevice, 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-%d: Invalid %s parameter (%u), using %u\n", bcm5700_driver, pUmDevice->index, 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);
+}
+
+int MM_FindCapability(LM_DEVICE_BLOCK *pDevice, int capability)
+{
+       UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+       return (pci_find_capability(pUmDevice->pdev, capability));
+}
+
+#if defined(HAVE_POLL_CONTROLLER)||defined(CONFIG_NET_POLL_CONTROLLER)
+STATIC void
+poll_bcm5700(struct net_device *dev)
+{
+       UM_DEVICE_BLOCK *pUmDevice = dev->priv;
+
+#if defined(RED_HAT_LINUX_KERNEL) && (LINUX_VERSION_CODE < 0x020605)
+       if (netdump_mode) {
+               bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL);
+#ifdef BCM_NAPI_RXPOLL
+               if (dev->poll_list.prev) {
+                       int budget = 64;
+
+                       bcm5700_poll(dev, &budget);
+               }
+#endif
+       }
+       else
+#endif
+       {
+               disable_irq(pUmDevice->pdev->irq);
+               bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL);
+               enable_irq(pUmDevice->pdev->irq);
+       }
+}
+#endif
diff --git a/drivers/net/bcm5700/bcm5700.4 b/drivers/net/bcm5700/bcm5700.4
new file mode 100644 (file)
index 0000000..1549000
--- /dev/null
@@ -0,0 +1,535 @@
+.\" Copyright (c) 2000-2005 Broadcom Corporation
+.\" This is free documentation; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation.
+.\"
+.\" bcm5700.4,v 5.9 
+.\"
+.TH BCM5700 4 "10/28/05" "Broadcom Corporation"
+.\"
+.\" NAME part
+.\"
+.SH NAME
+bcm5700 \- Broadcom NetXtreme BCM5700 series Gigabit Ethernet device driver
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.B insmod bcm5700.o
+.RB [ line_speed=\c
+.IR n,... ]
+.RB [ auto_speed=\c
+.IR n,... ]
+.RB [ full_duplex=\c
+.IR n,... ]
+.RB [ rx_flow_control=\c
+.IR n,... ]
+.RB [ tx_flow_control=\c
+.IR n,... ]
+.RB [ auto_flow_control=\c
+.IR n,... ]
+.RB [ mtu=\c
+.IR n,... ]
+.RB [ tx_checksum=\c
+.IR n,... ]
+.RB [ rx_checksum=\c
+.IR n,... ]
+.RB [ scatter_gather=\c
+.IR n,... ]
+.RB [ nic_tx_bd=\c
+.IR n,... ]
+.RB [ tx_pkt_desc_cnt=\c
+.IR n,... ]
+.RB [ rx_std_desc_cnt=\c
+.IR n,... ]
+.RB [ rx_jumbo_desc_cnt=\c
+.IR n,... ]
+.RB [ adaptive_coalesce=\c
+.IR n,... ]
+.RB [ rx_coalesce_ticks=\c
+.IR n,... ]
+.RB [ rx_max_coalesce_frames=\c
+.IR n,... ]
+.RB [ tx_coalesce_ticks=\c
+.IR n,... ]
+.RB [ tx_max_coalesce_frames=\c
+.IR n,... ]
+.RB [ stats_coalesce_ticks=\c
+.IR n,... ]
+.RB [ enable_wol=\c
+.IR n,... ]
+.RB [ enable_tso=\c
+.IR n,... ]
+.RB [ vlan_tag_mode=\c
+.IR n,... ]
+.RB [ delay_link=\c
+.IR n,... ]
+.RB [ disable_d3hot=\c
+.IR n,... ]
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.I bcm5700
+is the low-level device driver for the Broadcom
+.B NetXtreme BCM5700
+series PCI/PCI-X and PCI Express Gigabit Ethernet NIC. The driver has
+been tested on most 2.4.x and 2.6.x kernels up to 2.4.27 and 2.6.8 for
+i386, ia64, and x86_64 systems.
+It should also work on other big-endian and little-endian CPU platforms,
+but only very limited testing has been done and minor modifications to the
+Makefile and source files may be required.
+.PP
+The driver supports up to 16 NICs and allocates the next available ethernet
+device (eth0..eth#) for each NIC found. The driver is available as a loadable
+module or can be compiled into the kernel. The loadable module binary
+\fBbcm5700.o\fP or \fBbcm5700.ko\fP is installed in the following path:
+.PP
+2.2.x kernels:
+.RS
+/lib/modules/<kernel_version>/net/bcm5700.o
+.RE
+.PP
+2.4.x kernels:
+.RS
+/lib/modules/<kernel_version>/kernel/drivers/net/bcm5700.o
+.RE
+.PP
+2.4.x kernels with bcm5700 as an addon driver (e.g. Red Hat 7.3, 2.1AS):
+.RS
+/lib/modules/<kernel_version>/kernel/drivers/net/bcm/bcm5700.o
+.PP
+or
+.PP
+/lib/modules/<kernel_version>/kernel/drivers/addon/bcm5700/bcm5700.o
+.RE
+.PP
+2.6.x kernels:
+.RS
+/lib/modules/<kernel_version>/kernel/drivers/net/bcm5700.ko
+.RE
+.PP
+2.6.x kernels with bcm5700 as an addon driver (e.g. SusE 9 SLES):
+.RS
+/lib/modules/<kernel_version>/kernel/drivers/net/bcm/bcm5700.ko
+.RE
+.PP
+
+Note: If loading the driver on Red Hat 7.3, 2.1AS or other newer kernels
+with the tg3 driver, it may be necessary to unload the tg3 driver first if
+it is loaded. While tg3 is a fully functioning driver written by Red Hat et al,
+Broadcom recommends users to use the bcm5700 driver written and tested by
+Broadcom. Use ifconfig to bring down all eth# interfaces used by tg3
+and use rmmod to unload tg3.
+It may also be necessary to manually edit the file /etc/modules.conf to
+change interface alias names from tg3 to bcm5700. See the man page for
+modules.conf for more details.
+
+.PP
+Refer to various Linux documentations
+on how to configure network protocol and address.
+.\"
+.\" PARAMETER part
+.\"
+.SH PARAMETERS
+Optional parameters for the driver can be supplied as command line arguments 
+to the insmod command. These parameters can also be set in the file
+/etc/modules.conf (see the man page for modules.conf). These parameters take
+the form
+.PP
+.B <parameter>=n1[,n2,...]
+.PP
+where the multiple values n1,n2,... are for multiple NICs installed in the
+system.
+.PP
+Note that default or other meaningful values will be used when invalid values
+are selected. Some combinations of parameters may conflict and lead to
+failures. The driver cannot detect all such conflicting combinations.
+.PP
+All the parameters are listed below.
+.TP
+.B line_speed
+Selects the line speed of the link. This parameter is used together with
+\fBfull_duplex\fP and \fBauto_speed\fP to select the speed and
+duplexity of the link and the setting of autonegotiation. The valid values are:
+.RS
+.TP
+.B 0
+Autonegotiate for highest speed supported by link partner (default)
+.TP
+.B 10
+10 Mbps
+.TP
+.B 100
+100 Mbps
+.TP
+.B 1000
+1000 Mbps
+.PP
+If \fBline_speed\fP is set to \fB10\fP, \fB100\fP, or \fB1000\fP,
+the NIC will autonegotiate for
+the selected speed (and selected duplexity) if \fBauto_speed\fP is set to
+\fB1\fP. If \fBauto_speed\fP is set to \fB0\fP, the selected speed and
+duplexity will be set without autonegotiation. Note that 1000 Mbps must be
+negotiated for copper twisted pair links.
+.RE
+.TP
+.B auto_speed
+Enables or disables autonegotiation. The valid values are:
+.RS
+.TP
+.B 0
+Autonegotiation disabled
+.TP
+.B 1
+Autonegotiation enabled (default)
+.PP
+Note that this parameter is ignored and assumed \fB1\fP if \fBline_speed\fP is
+set to \fB0\fP.
+.RE
+.TP    
+.B full_duplex
+Selects the duplexity of the link. This paramter is used together with
+\fBline_speed\fP to select the speed and duplexity of the link. Note that this
+parameter is ignored if \fBline_speed\fP is \fB0\fP. The valid values are:
+.RS
+.TP
+.B 0
+half duplex
+.TP
+.B 1
+full duplex (default)
+.RE
+.TP
+.B rx_flow_control
+Enables or disables receiving flow control (pause) frames. This parameter
+is used together with \fBauto_flow_control\fP. The valid values are:
+.RS
+.TP
+.B 0
+pause receive disabled
+.TP
+.B 1
+pause receive enabled if \fBauto_flow_control\fP is set to \fB0\fP, or pause
+receive advertised if \fBauto_flow_control\fP is set to \fB1\fP (default)
+.RE
+.TP
+.B tx_flow_control
+Enables or disables transmitting flow control (pause) frames. This parameter
+is used together with \fBauto_flow_control\fP. The valid values are:
+.RS
+.TP
+.B 0
+pause transmit disabled
+.TP
+.B 1
+pause transmit enabled if \fBauto_flow_control\fP is set to \fB0\fP, or pause
+transmit advertised if \fBauto_flow_control\fP is set to \fB1\fP (default)
+.RE
+.TP
+.B auto_flow_control
+Enables or disables autonegotiation of flow control. This parameter is used
+together with \fBrx_flow_control\fP and \fBtx_flow_control\fP to determine the
+advertised flow control capability. The valid values are:
+.RS
+.TP
+.B 0
+flow control autonegotiation disabled
+.TP
+.B 1
+flow control autonegotiation enabled with capability specified in
+\fBrx_flow_control\fP and \fBtx_flow_control\fP (only valid if \fBline_speed\fP
+is set to \fB0\fP or \fBauto_speed\fP is set to \fB1\fP) (default)
+.RE
+.TP
+.B mtu
+Enables jumbo frames up to the specified MTU size. The valid range for
+this parameter is 1500 to 9000. Default is 1500 which is standard
+ethernet (non-jumbo) MTU size. Note that the MTU size excludes the
+ethernet header size of 14 bytes. Actual frame size is MTU size + 14 bytes.
+Jumbo MTU sizes are not supported on BCM5705 chips.
+
+.RS
+The MTU size can also be changed using ifconfig after the driver is loaded.
+See the ifconfig man page for details.
+.RE
+.TP
+.B tx_checksum
+Enables or disables hardware transmit TCP/UDP checksum. The valid values
+are:
+.RS
+.TP
+.B 0
+checksum disabled
+.TP
+.B 1
+checksum enabled (default)
+.RE
+.TP
+.B rx_checksum
+Enables or disables hardware receive TCP/UDP checksum validation. The
+valid values are:
+.RS
+.TP
+.B 0
+checksum disabled
+.TP
+.B 1
+checksum enabled (default)
+.RE
+.TP
+.B
+scatter_gather
+Enables or disables scatter-gather and 64-bit DMA on x86. This option is only
+useful when running on TUX-enabled kernels or newer kernels with zero-copy TCP.
+The valid values are:
+.RS
+.TP
+.B 0
+scatter-gather and 64-bit DMA on x86 disabled
+.TP
+.B 1
+scatter-gather and 64-bit DMA on x86 enabled (default)
+.RE
+.TP
+.B
+nic_tx_bd
+Enables either NIC based or host based transmit buffer descriptors (Tx BDs).
+NIC based Tx BDs may be slightly faster on certain machines on earlier
+2.4 kernels where each transmit packet is usually entirely contiguous. On
+later kernels with scatter-gather and TCP segmentation option, host based
+Tx BDs using DMA transfer are usually faster. NIC based Tx BDs are not
+supported on 5705 family controllers. The valid values are:
+.RS
+.TP
+.B 0
+NIC based transmit buffer descriptors disabled (using host based
+transmit buffer descriptors) (default)
+.TP
+.B 1
+NIC based transmit buffer descriptors enabled (not supported
+on 5705 family controllers)
+.RE
+.TP
+.B tx_pkt_desc_cnt
+Configures the number of transmit descriptors. Default is 120. The
+valid range is from 1 to 511. Note that the driver may not be able to
+allocate the required amount of memory if this parameter is set too high.
+Depending on kernel and CPU architecture, each descriptor may require up
+to about 268 bytes. This parameter should not be set less than \fB80\fP if
+\fBadaptive_coalesce\fP (see below) is enabled.
+
+.TP
+.B rx_std_desc_cnt
+Configures the number of receive descriptors for frames up to 1528 bytes.
+Default is 200. The valid range is from 1 to 511. This parameter should
+not be set less than \fB80\fP on systems with high network traffic. Setting this
+parameter higher allows the NIC to buffer larger bursts of network
+traffic without dropping frames, especially on slower systems. Note that
+the driver may not be able to allocate the required amount of memory if
+this parameter is set too high. Depending on kernel and CPU architecture,
+each descriptor may require up to about 268 bytes. Each descriptor also
+requires a socket buffer of at least 1536 bytes. This parameter should not
+be set less than \fB50\fP if \fBadaptive_coalesce\fP (see below) is enabled.
+
+.TP
+.B rx_jumbo_desc_cnt
+Configures the number of receive descriptors for jumbo frames larger
+than 1528 bytes. Default is 128 and valid range is from 1 to 255.
+When jumbo frames larger than 1528 bytes are used, this parameter should
+not be set lower than \fB60\fP on systems with high network traffic. Setting
+this parameter higher allows the NIC to buffer larger bursts of jumbo
+traffic without dropping frames, especially on slower systems. Depending
+on kernel and CPU architecture, each descriptor may require up to about
+268 bytes. Each descriptor also requires a socket buffer the size of a
+maximum jumbo frame. On systems with insufficient memory, it may be
+necessary to reduce this parameter. This parameter should not be set less
+than \fB50\fP if \fBadaptive_coalesce\fP (see below) is enabled. When the maximum
+frame size is 1528 or smaller (MTU size 1514 or smaller), this parameter
+is not used and is always 0.
+
+.TP
+.B adaptive_coalesce
+Enables or disables adaptive adjustments to the various interrupt
+coalescing parameters. Enabling it allows the driver to dynamically
+adjust the interrupt coalescing parameters to achieve high throughput
+during heavy traffic and low latency during light traffic. 
+\fBrx_std_desc_cnt\fP, (and \fBrx_jumbo_desc_cnt\fP if using jumbo frames)
+should not be set less than \fB50\fP, and \fBtx_pkt_desc_cnt\fP should not be
+set less than \fB80\fP when this parameter is enabled. Note that if the
+kernel supports the NAPI receive polling mode, interrupt coalescing will
+be handled in a different way and this parameter will not be used. The valid
+values are:
+.RS
+.TP
+.B 0
+disabled (always disabled in NAPI mode)
+.TP
+.B 1
+enabled (default)
+.RE
+.TP
+.B rx_coalesce_ticks
+Configures the number of 1 usec ticks before the NIC
+generates receive interrupt after receiving a frame. This parameter works
+in conjunction with the \fBrx_max_coalesce_frames\fP parameter. Interrupt will
+be generated when either of these thresholds is exceeded. \fB0\fP means this
+parameter is ignored and interrupt will be generated when the
+\fBrx_max_coalesce_frames\fP threshold is reached. The valid range is from 0
+to 500, and default is 60 (18 if using NAPI mode). This parameter is not
+used and will be adjusted
+automatically if \fBadaptive_coalesce\fP is set to \fB1\fP.
+.TP
+.B rx_max_coalesce_frames
+Configures the number of received frames before the
+NIC generates receive interrupt. The valid range is from 0 to 100, and default
+is 15 (6 if using NAPI mode). This parameter and
+\fBrx_coalesce_ticks\fP cannot be both \fB0\fP,
+otherwise no receive interrupts will be generated. It should also be set
+lower than \fBrx_std_desc_cnt\fP (and \fBrx_jumbo_desc_cnt\fP
+if using jumbo frames). This parameter is not
+used and will be adjusted automatically if
+\fBadaptive_coalesce\fP is set to \fB1\fP.
+.TP
+.B tx_coalesce_ticks
+Configures the number of 1 usec ticks before the NIC
+generates transmit interrupt after transmitting a frame. This parameter
+works in conjunction with the \fBtx_max_coalesce_frames\fP parameter. Interrupt
+will be generated when either of these thresholds is exceeded. \fB0\fP means
+this parameter is ignored and interrupt will be generated when the
+\fBtx_max_coalesce_frames\fP threshold is reached. The valid range is from 0 to
+500, and default is 200. This parameter is not used and will be adjusted
+automatically if \fBadaptive_coalesce\fP is set to \fB1\fP.
+.TP
+.B tx_max_coalesce_frames
+Configures the number of transmitted frames before
+the NIC generates transmit interrupt. The valid range is from 0 to 100, and
+default is 35. This parameter and \fBtx_coalesce_ticks\fP cannot be both
+\fB0\fP, otherwise no transmit completion interrupts will be generated. This
+parameter should always be set lower than \fBtx_pkt_desc_cnt\fP.
+This parameter is not used and will be adjusted
+automatically if \fBadaptive_coalesce\fP is set to \fB1\fP.
+.TP
+.B stats_coalesce_ticks
+Configures the number of 1 usec ticks between
+periodic statistics block DMAs. The valid range is from 100 to 3600000000, and
+default is 1000000 (1 sec.). 0 is also valid and is used to disable
+statistics updates. This parameter is not used and will be set to default
+if \fBadaptive_coalesce\fP is set to \fB1\fP.
+.TP
+.B enable_wol
+Enables or disables magic packet Wake-On-LAN when the system is shutdown.
+Note that not all systems support Wake-On-LAN. The valid values are:
+.RS
+.TP
+.B 0
+magic packet Wake-On-LAN disabled (default)
+.TP
+.B 1
+magic packet Wake-On-LAN enabled
+.RE
+.TP
+.B enable_tso
+Enables or disables TCP Segmentation Option (TSO) when using kernels that
+support it. This parameter is only defined on newer kernels that support
+TSO. The valid values are:
+.RS
+.TP
+.B 0
+TSO disabled
+.TP
+.B 1
+TSO enabled (default)
+.RE
+.TP
+.B vlan_tag_mode
+This parameter controls the stripping of VLAN tags on incoming packets,
+and is used to allow VLAN tagged ASF or IPMI packets to be received
+properly. The valid values are:
+.RS
+.TP
+.B 0
+Auto mode (default)
+.TP
+.B 1
+Normal strip mode
+.TP
+.B 2
+Forced strip mode
+.PP
+In normal mode, VLAN tags are only stripped if VLANs are registered
+by the 802.1q VLAN module or BASP. In forced strip mode, VLAN tags
+are always stripped. Auto mode will select normal strip mode if ASF/IPMI
+is disabled, or forced strip mode if ASF/IPMI is enabled.
+.RE    
+.TP
+.B delay_link
+If set to 1, this parameter will cause the driver to return 
+-EOPNOTSUPP when the SIOCGMIIREG or ETHTOOL_GLINK ioctls are called
+during the first 6 seconds after driver reset. When the driver resets
+the NIC during ifconfig, the link will drop and it may take several
+seconds for the link to come up after autonegotiation completes. Some
+applications, such as ifup, may not wait long enough for the link
+before giving up. Setting this parameter to 1 may get around such
+problems. The default value is 0, which means that the driver will
+always return true link states to all ioctl calls, when applicable.
+.TP
+.B disable_d3hot
+If set to 1, this parameter will cause the driver to never
+put the device in D3Hot power state when the NIC is shutdown or
+suspended. If set, this parameter will also disable the Wake-On-Lan
+setting. A rare D3Hot related problem was seen during repeated shutdown of
+PCI Express devices on systems running 2.6 kernels.
+
+.\"
+.\" DRIVER MESSAGES part
+.\"
+.SH DRIVER MESSAGES
+The following are the most common sample messages that may be logged in the file
+/var/log/messages. Use dmesg -n <level> to control the level at which messages
+will appear on the console. Most systems are set to level 6 by default.
+.PP
+.B Broadcom Gigabit Ethernet Driver bcm5700 with Broadcom NIC Extension (NICE) ver. 8.3.9 (09/30/05)
+.RS
+Driver signon
+.RE
+.PP
+.B eth#: Broadcom BCM5704 1000Base-T found at mem faff0000, IRQ 16, node addr 0010180402d8
+.PP
+.B eth#: Broadcom BCM5704 Integrated Copper transceiver found
+.PP
+.B eth#: Scatter-gather ON, 64-bit DMA ON, Tx Checksum ON, Rx Checksum ON, 802.1Q VLAN ON, NAPI ON
+.RS
+NIC detected
+.RE
+.PP
+.B bcm5700: eth# NIC Link is Up, 1000 Mbps full duplex, receive & transmit flow control ON
+.RS
+Link up and speed indication
+.RE
+.PP
+.B bcm5700: eth# NIC Link is Down
+.RS
+ Link down indication
+.RE
+.\"
+.\" FILES part
+.\"
+.SH FILES
+.I /proc/net/nicinfo/eth#.info
+.RS
+Detailed statistics and configuration file.
+.RE
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTHOR
+Michael Chan \- mchan@broadcom.com
+.\"
+.\" SEE ALSO part
+.\"
+.SH SEE ALSO
+.BR ifconfig (8),
+.BR insmod (8),
+.BR modules.conf (5).
+
diff --git a/drivers/net/bcm5700/bits.h b/drivers/net/bcm5700/bits.h
new file mode 100644 (file)
index 0000000..cd97e84
--- /dev/null
@@ -0,0 +1,61 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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 --git a/drivers/net/bcm5700/fw_lso05.h b/drivers/net/bcm5700/fw_lso05.h
new file mode 100644 (file)
index 0000000..cfe6a9c
--- /dev/null
@@ -0,0 +1,289 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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.                 */
+/*                                                                            */
+/* (c) COPYRIGHT 2001-2004 Broadcom Corporation, ALL RIGHTS RESERVED.         */
+/*                                                                            */
+/*  Name: F W _ L S O 0 5. H                                                  */
+/*  Author : Kevin Tran                                                       */
+/*  Version: 1.2                                                              */
+/*                                                                            */
+/* Module Description:  This file contains firmware binary code of TCP        */
+/* Segmentation firmware (BCM5705).                                           */
+/*                                                                            */
+/* History:                                                                   */
+/*    08/10/02 Kevin Tran       Incarnation.                                  */
+/*    02/02/04 Kevin Tran       Added Support for BCM5788.                    */
+/******************************************************************************/
+
+#ifndef __FW_LSO05_H__ 
+#define __FW_LSO05_H__ 
+
+int t3StkOffLd05FwReleaseMajor = 0x1;
+int t3StkOffLd05FwReleaseMinor = 0x2;
+int t3StkOffLd05FwReleaseFix = 0x0;
+U32 t3StkOffLd05FwStartAddr = 0x00010000;
+U32 t3StkOffLd05FwTextAddr = 0x00010000;
+int t3StkOffLd05FwTextLen = 0xe90;
+U32 t3StkOffLd05FwRodataAddr = 0x00010e90;
+int t3StkOffLd05FwRodataLen = 0x50;
+U32 t3StkOffLd05FwDataAddr = 0x00010f00;
+int t3StkOffLd05FwDataLen = 0x20;
+U32 t3StkOffLd05FwSbssAddr = 0x00010f20;
+int t3StkOffLd05FwSbssLen = 0x28;
+U32 t3StkOffLd05FwBssAddr = 0x00010f50;
+int t3StkOffLd05FwBssLen = 0x88;
+U32 t3StkOffLd05FwText[(0xe90/4) + 1] = {
+0xc004003, 0x0, 0x10f04, 
+0x0, 0x10000003, 0x0, 0xd, 
+0xd, 0x3c1d0001, 0x37bde000, 0x3a0f021, 
+0x3c100001, 0x26100000, 0xc004010, 0x0, 
+0xd, 0x27bdffe0, 0x3c04fefe, 0xafbf0018, 
+0xc0042e8, 0x34840002, 0xc004364, 0x0, 
+0x3c030001, 0x90630f34, 0x24020002, 0x3c040001, 
+0x24840e9c, 0x14620003, 0x24050001, 0x3c040001, 
+0x24840e90, 0x24060002, 0x3821, 0xafa00010, 
+0xc004378, 0xafa00014, 0xc00402c, 0x0, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 
+0x0, 0x27bdffe0, 0xafbf001c, 0xafb20018, 
+0xafb10014, 0xc0042d4, 0xafb00010, 0x3c128000, 
+0x24110001, 0x8f706810, 0x32020400, 0x10400007, 
+0x0, 0x8f641008, 0x921024, 0x14400003, 
+0x0, 0xc004064, 0x0, 0x3c020001, 
+0x90420f56, 0x10510003, 0x32020200, 0x1040fff1, 
+0x0, 0xc0041b4, 0x0, 0x8004034, 
+0x0, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe0, 
+0x3c040001, 0x24840eb0, 0x2821, 0x3021, 
+0x3821, 0xafbf0018, 0xafa00010, 0xc004378, 
+0xafa00014, 0xd021, 0x24020130, 0xaf625000, 
+0x3c010001, 0xa4200f50, 0x3c010001, 0xa0200f57, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 
+0x0, 0x3c030001, 0x24630f60, 0x90620000, 
+0x27bdfff0, 0x14400003, 0x80c021, 0x8004073, 
+0x4821, 0x3c022000, 0x3021024, 0x10400003, 
+0x24090002, 0x8004073, 0xa0600000, 0x24090001, 
+0x181040, 0x30431f80, 0x346f8008, 0x1520004b, 
+0x25eb0028, 0x3c040001, 0x832021, 0x8c848010, 
+0x3c050001, 0x24a50f7a, 0x41402, 0xa0a20000, 
+0x3c010001, 0xa0240f7b, 0x3c020001, 0x431021, 
+0x94428014, 0x3c010001, 0xa0220f7c, 0x3c0c0001, 
+0x1836021, 0x8d8c8018, 0x304200ff, 0x24420008, 
+0x220c3, 0x24020001, 0x3c010001, 0xa0220f60, 
+0x124102b, 0x1040000c, 0x3821, 0x24a6000e, 
+0x1602821, 0x8ca20000, 0x8ca30004, 0x24a50008, 
+0x24e70001, 0xacc20000, 0xacc30004, 0xe4102b, 
+0x1440fff8, 0x24c60008, 0x3821, 0x3c080001, 
+0x25080f7b, 0x91060000, 0x3c020001, 0x90420f7c, 
+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, 0xac220f80, 0x3c050001, 
+0x24a50f7c, 0x90a20000, 0x3c0c0001, 0x1836021, 
+0x8d8c8018, 0x220c2, 0x1080000e, 0x3821, 
+0x1603021, 0x24a5000c, 0x8ca20000, 0x8ca30004, 
+0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 
+0xe4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 
+0x24a50f7c, 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, 0x90420f7c, 0x3c030001, 0x90630f7a, 
+0xe2c823, 0x3c020001, 0x90420f7b, 0x24630028, 
+0x1e34021, 0x24420028, 0x15200012, 0x1e23021, 
+0x94c2000c, 0x3c010001, 0xa4220f78, 0x94c20004, 
+0x94c30006, 0x3c010001, 0xa4200f76, 0x3c010001, 
+0xa4200f72, 0x21400, 0x431025, 0x3c010001, 
+0xac220f6c, 0x95020004, 0x3c010001, 0x8004124, 
+0xa4220f70, 0x3c020001, 0x94420f70, 0x3c030001, 
+0x94630f72, 0x431021, 0xa5020004, 0x3c020001, 
+0x94420f6c, 0xa4c20004, 0x3c020001, 0x8c420f6c, 
+0xa4c20006, 0x3c040001, 0x94840f72, 0x3c020001, 
+0x94420f70, 0x3c0a0001, 0x954a0f76, 0x441821, 
+0x3063ffff, 0x62182a, 0x24020002, 0x1122000b, 
+0x832023, 0x3c030001, 0x94630f78, 0x30620009, 
+0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 
+0x94420f78, 0x30420009, 0x1425023, 0x24020001, 
+0x1122001b, 0x29220002, 0x50400005, 0x24020002, 
+0x11200007, 0x31a2ffff, 0x8004197, 0x0, 
+0x1122001d, 0x24020016, 0x8004197, 0x31a2ffff, 
+0x3c0e0001, 0x95ce0f80, 0x10800005, 0x1806821, 
+0x1c42021, 0x41c02, 0x3082ffff, 0x627021, 
+0xe1027, 0xa502000a, 0x3c030001, 0x90630f7b, 
+0x31a2ffff, 0xe21021, 0x800418d, 0x432023, 
+0x3c020001, 0x94420f80, 0x442021, 0x41c02, 
+0x3082ffff, 0x622021, 0x807021, 0x41027, 
+0x8004185, 0xa502000a, 0x3c050001, 0x24a50f7a, 
+0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 
+0x90a20000, 0xe21023, 0xa5020002, 0x3c030001, 
+0x94630f80, 0x3c020001, 0x94420f5a, 0x30e5ffff, 
+0x641821, 0x451023, 0x622023, 0x41c02, 
+0x3082ffff, 0x622021, 0x41027, 0xa502000a, 
+0x3c030001, 0x90630f7c, 0x24620001, 0x14a20005, 
+0x807021, 0x1631021, 0x90420000, 0x8004185, 
+0x26200, 0x24620002, 0x14a20003, 0x306200fe, 
+0x4b1021, 0x944c0000, 0x3c020001, 0x94420f82, 
+0x3183ffff, 0x3c040001, 0x90840f7b, 0x431021, 
+0xe21021, 0x442023, 0x8a2021, 0x41c02, 
+0x3082ffff, 0x622021, 0x41402, 0x822021, 
+0x806821, 0x41027, 0xa4c20010, 0x31a2ffff, 
+0xe1c00, 0x431025, 0x3c040001, 0x24840f72, 
+0xade20010, 0x94820000, 0x3c050001, 0x94a50f76, 
+0x3c030001, 0x8c630f6c, 0x24420001, 0xb92821, 
+0xa4820000, 0x3322ffff, 0x622021, 0x83182b, 
+0x3c010001, 0xa4250f76, 0x10600003, 0x24a2ffff, 
+0x3c010001, 0xa4220f76, 0x3c024000, 0x3021025, 
+0x3c010001, 0xac240f6c, 0xaf621008, 0x3e00008, 
+0x27bd0010, 0x3c030001, 0x90630f56, 0x27bdffe8, 
+0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 
+0x8f620cf4, 0x2442ffff, 0x3042007f, 0x21100, 
+0x8c434000, 0x3c010001, 0xac230f64, 0x8c434008, 
+0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 
+0x24020088, 0x24020008, 0x3c010001, 0xa4220f68, 
+0x30620004, 0x10400005, 0x24020001, 0x3c010001, 
+0xa0220f57, 0x80041d5, 0x31402, 0x3c010001, 
+0xa0200f57, 0x31402, 0x3c010001, 0xa4220f54, 
+0x9483000c, 0x24020001, 0x3c010001, 0xa4200f50, 
+0x3c010001, 0xa0220f56, 0x3c010001, 0xa4230f62, 
+0x24020001, 0x1342001e, 0x0, 0x13400005, 
+0x24020003, 0x13420067, 0x0, 0x80042cf, 
+0x0, 0x3c020001, 0x94420f62, 0x241a0001, 
+0x3c010001, 0xa4200f5e, 0x3c010001, 0xa4200f52, 
+0x304407ff, 0x21bc2, 0x31823, 0x3063003e, 
+0x34630036, 0x21242, 0x3042003c, 0x621821, 
+0x3c010001, 0xa4240f58, 0x832021, 0x24630030, 
+0x3c010001, 0xa4240f5a, 0x3c010001, 0xa4230f5c, 
+0x3c060001, 0x24c60f52, 0x94c50000, 0x94c30002, 
+0x3c040001, 0x94840f5a, 0x651021, 0x44102a, 
+0x10400013, 0x3c108000, 0xa31021, 0xa4c20000, 
+0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 
+0x8f641008, 0x901024, 0x14400003, 0x0, 
+0xc004064, 0x0, 0x8f620cf4, 0x501024, 
+0x104000b7, 0x0, 0x800420f, 0x0, 
+0x3c030001, 0x94630f50, 0x851023, 0xa4c40000, 
+0x621821, 0x3042ffff, 0x3c010001, 0xa4230f50, 
+0xaf620ce8, 0x3c020001, 0x94420f68, 0x34420024, 
+0xaf620cec, 0x94c30002, 0x3c020001, 0x94420f50, 
+0x14620012, 0x3c028000, 0x3c108000, 0x3c02a000, 
+0xaf620cf4, 0x3c010001, 0xa0200f56, 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, 0x24e70f50, 0x94e20000, 
+0x3821021, 0xaf620ce0, 0x3c020001, 0x8c420f64, 
+0xaf620ce4, 0x3c050001, 0x94a50f54, 0x94e30000, 
+0x3c040001, 0x94840f58, 0x3c020001, 0x94420f5e, 
+0xa32823, 0x822023, 0x30a6ffff, 0x3083ffff, 
+0xc3102b, 0x14400043, 0x0, 0x3c020001, 
+0x94420f5c, 0x21400, 0x621025, 0xaf620ce8, 
+0x94e20000, 0x3c030001, 0x94630f54, 0x441021, 
+0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 
+0x3c020001, 0x90420f57, 0x10400006, 0x3c03000c, 
+0x3c020001, 0x94420f68, 0x34630624, 0x800427c, 
+0xd021, 0x3c020001, 0x94420f68, 0x3c030008, 
+0x34630624, 0x431025, 0xaf620cec, 0x3c108000, 
+0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 
+0x8f641008, 0x901024, 0x14400003, 0x0, 
+0xc004064, 0x0, 0x8f620cf4, 0x501024, 
+0x10400015, 0x0, 0x8004283, 0x0, 
+0x3c030001, 0x94630f68, 0x34420624, 0x3c108000, 
+0x621825, 0x3c028000, 0xaf630cec, 0xaf620cf4, 
+0x8f641008, 0x901024, 0x14400003, 0x0, 
+0xc004064, 0x0, 0x8f620cf4, 0x501024, 
+0x1440fff7, 0x0, 0x3c010001, 0x80042cf, 
+0xa4200f5e, 0x3c020001, 0x94420f5c, 0x21400, 
+0xc21025, 0xaf620ce8, 0x3c020001, 0x90420f57, 
+0x10400009, 0x3c03000c, 0x3c020001, 0x94420f68, 
+0x34630624, 0xd021, 0x431025, 0xaf620cec, 
+0x80042c1, 0x3c108000, 0x3c020001, 0x94420f68, 
+0x3c030008, 0x34630604, 0x431025, 0xaf620cec, 
+0x3c020001, 0x94420f5e, 0x451021, 0x3c010001, 
+0xa4220f5e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 
+0x3c010001, 0xa0200f56, 0x8f641008, 0x901024, 
+0x14400003, 0x0, 0xc004064, 0x0, 
+0x8f620cf4, 0x501024, 0x1440fff7, 0x0, 
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 
+0x0, 0x27bdffe0, 0x3c040001, 0x24840ec0, 
+0x2821, 0x3021, 0x3821, 0xafbf0018, 
+0xafa00010, 0xc004378, 0xafa00014, 0xd021, 
+0x24020130, 0xaf625000, 0x3c010001, 0xa4200f50, 
+0x3c010001, 0xa0200f57, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 
+0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 
+0xaf626804, 0x8f634000, 0x24020b50, 0x3c010001, 
+0xac220f20, 0x24020b78, 0x3c010001, 0xac220f30, 
+0x34630002, 0xaf634000, 0xc004315, 0x808021, 
+0x3c010001, 0xa0220f34, 0x304200ff, 0x24030002, 
+0x14430005, 0x0, 0x3c020001, 0x8c420f20, 
+0x8004308, 0xac5000c0, 0x3c020001, 0x8c420f20, 
+0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 
+0x3c010001, 0xac220f28, 0x3c010001, 0xac230f38, 
+0x3c010001, 0xac240f24, 0x8fbf0014, 0x8fb00010, 
+0x3e00008, 0x27bd0018, 0x3e00008, 0x24020001, 
+0x27bdfff8, 0x18800009, 0x2821, 0x8f63680c, 
+0x8f62680c, 0x1043fffe, 0x0, 0x24a50001, 
+0xa4102a, 0x1440fff9, 0x0, 0x3e00008, 
+0x27bd0008, 0x8f634450, 0x3c020001, 0x8c420f28, 
+0x31c02, 0x43102b, 0x14400008, 0x3c038000, 
+0x3c040001, 0x8c840f38, 0x8f624450, 0x21c02, 
+0x83102b, 0x1040fffc, 0x3c038000, 0xaf634444, 
+0x8f624444, 0x431024, 0x1440fffd, 0x0, 
+0x8f624448, 0x3e00008, 0x3042ffff, 0x3082ffff, 
+0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 
+0x8004347, 0x2402ffff, 0x822025, 0xaf645c38, 
+0x8f625c30, 0x30420002, 0x1440fffc, 0x1021, 
+0x3e00008, 0x0, 0x8f624450, 0x3c030001, 
+0x8c630f24, 0x8004350, 0x3042ffff, 0x8f624450, 
+0x3042ffff, 0x43102b, 0x1440fffc, 0x0, 
+0x3e00008, 0x0, 0x27bdffe0, 0x802821, 
+0x3c040001, 0x24840ed0, 0x3021, 0x3821, 
+0xafbf0018, 0xafa00010, 0xc004378, 0xafa00014, 
+0x800435f, 0x0, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x3c020001, 0x3442d600, 0x3c030001, 
+0x3463d600, 0x3c040001, 0x3484ddff, 0x3c010001, 
+0xac220f40, 0x24020040, 0x3c010001, 0xac220f44, 
+0x3c010001, 0xac200f3c, 0xac600000, 0x24630004, 
+0x83102b, 0x5040fffd, 0xac600000, 0x3e00008, 
+0x0, 0x804821, 0x8faa0010, 0x3c020001, 
+0x8c420f3c, 0x3c040001, 0x8c840f44, 0x8fab0014, 
+0x24430001, 0x44102b, 0x3c010001, 0xac230f3c, 
+0x14400003, 0x4021, 0x3c010001, 0xac200f3c, 
+0x3c020001, 0x8c420f3c, 0x3c030001, 0x8c630f40, 
+0x91240000, 0x21140, 0x431021, 0x481021, 
+0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, 
+0x25290001, 0x3c020001, 0x8c420f3c, 0x3c030001, 
+0x8c630f40, 0x8f64680c, 0x21140, 0x431021, 
+0xac440008, 0xac45000c, 0xac460010, 0xac470014, 
+0xac4a0018, 0x3e00008, 0xac4b001c, 0x0, 
+0x0, 0x0 };
+U32 t3StkOffLd05FwRodata[(0x50/4) + 1] = {
+0x4d61696e, 
+0x43707542, 0x0, 0x4d61696e, 0x43707541, 
+0x0, 0x0, 0x0, 0x73746b6f, 
+0x66666c64, 0x0, 0x0, 0x73746b6f, 
+0x66666c64, 0x0, 0x0, 0x66617461, 
+0x6c457272, 0x0, 0x0, 0x0 };
+U32 t3StkOffLd05FwData[(0x20/4) + 1] = {
+0x0, 
+0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 
+0x0, 0x0, 0x0, 0x0 };
+
+#endif /* __FW_LSO05_H__   */
diff --git a/drivers/net/bcm5700/fw_stkoffld.h b/drivers/net/bcm5700/fw_stkoffld.h
new file mode 100644 (file)
index 0000000..119a17b
--- /dev/null
@@ -0,0 +1,519 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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.                 */
+/*                                                                            */
+/* (c) COPYRIGHT 2000-2003 Broadcom Corporation, ALL RIGHTS RESERVED.         */
+/*                                                                            */
+/*  Name: F W _ S T K O F F L D . H                                           */
+/*  Author  : Kevin Tran                                                      */
+/*  Version : 1.6                                                             */
+/*                                                                            */
+/* 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.      */
+/*    12/01/02 Kevin Tran       Fixed a problem where firmware might lockup   */
+/*                              in a certain test scenario with BCM5704.      */
+/*    12/10/02 Kevin Tran       Fixed a problem where IP checksum might be    */
+/*                              incorrectly calculated in some corner cases.  */
+/*                              This problem should ONLY happen with BCM5702/ */
+/*                              BCM5703/BCM5704 ASICs.                        */
+/*    06/20/03 Kevin Tran       Optimized performance so that pre-DMA code    */
+/*                              doesn't have to wait until the first packet   */
+/*                              is completely DMAed before it can setup DMAs  */
+/*                              for subsequent packets.  This requires host   */
+/*                              driver to pass IP/TCP option lengths if any   */
+/*                              to F/W via bit 15..12 of Send BD flag.        */
+/*    08/12/03 Kevin Tran       Fixed a problem where UDP checksum doesn't    */
+/*                              work when the host driver seeds pseudo        */
+/*                              checksum.                                     */
+/*    12/24/03 Kevin Tran       Fixed a problem where VLAN tag is not         */
+/*                              inserted correctly in LSO mode.               */
+/*    01/16/04 Kevin Tran       Fixed a problem where Ethernet Type is not    */
+/*                              set to 0x8870 when the outgoing LSO packet is */
+/*                              jumbo frame with SNAP encapsulation.          */
+/******************************************************************************/
+
+#ifndef __FW_STKOFFLD_H__ 
+#define __FW_STKOFFLD_H__ 
+
+typedef LM_UINT32 U32;
+
+int t3StkOffLdFwReleaseMajor = 0x1;
+int t3StkOffLdFwReleaseMinor = 0x6;
+int t3StkOffLdFwReleaseFix = 0x0;
+U32 t3StkOffLdFwStartAddr = 0x08000000;
+U32 t3StkOffLdFwTextAddr = 0x08000000;
+int t3StkOffLdFwTextLen = 0x1aa0;
+U32 t3StkOffLdFwRodataAddr = 0x08001aa0;
+int t3StkOffLdFwRodataLen = 0x60;
+U32 t3StkOffLdFwDataAddr = 0x08001b20;
+int t3StkOffLdFwDataLen = 0x30;
+U32 t3StkOffLdFwSbssAddr = 0x08001b50;
+int t3StkOffLdFwSbssLen = 0x2c;
+U32 t3StkOffLdFwBssAddr = 0x08001b80;
+int t3StkOffLdFwBssLen = 0x894;
+U32 t3StkOffLdFwText[(0x1aa0/4) + 1] = {
+0xe000003, 0x0, 0x8001b24, 
+0x0, 0x10000003, 0x0, 0xd, 
+0xd, 0x3c1d0800, 0x37bd4000, 0x3a0f021, 
+0x3c100800, 0x26100000, 0xe000010, 0x0, 
+0xd, 0x27bdffe0, 0x3c04fefe, 0xafbf0018, 
+0xe0005d8, 0x34840002, 0xe000668, 0x0, 
+0x3c030800, 0x90631b68, 0x24020002, 0x3c040800, 
+0x24841aac, 0x14620003, 0x24050001, 0x3c040800, 
+0x24841aa0, 0x24060006, 0x3821, 0xafa00010, 
+0xe00067c, 0xafa00014, 0x8f625c50, 0x34420001, 
+0xaf625c50, 0x8f625c90, 0x34420001, 0xaf625c90, 
+0x2402ffff, 0xe000034, 0xaf625404, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x0, 0x0, 
+0x0, 0x27bdffe0, 0xafbf001c, 0xafb20018, 
+0xafb10014, 0xe00005b, 0xafb00010, 0x24120002, 
+0x24110001, 0x8f706820, 0x32020100, 0x10400003, 
+0x0, 0xe0000bb, 0x0, 0x8f706820, 
+0x32022000, 0x10400004, 0x32020001, 0xe0001f0, 
+0x24040001, 0x32020001, 0x10400003, 0x0, 
+0xe0000a3, 0x0, 0x3c020800, 0x90421b98, 
+0x14520003, 0x0, 0xe0004c0, 0x0, 
+0xa00003c, 0xaf715028, 0x8fbf001c, 0x8fb20018, 
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020, 
+0x27bdffe0, 0x3c040800, 0x24841ac0, 0x2821, 
+0x3021, 0x3821, 0xafbf0018, 0xafa00010, 
+0xe00067c, 0xafa00014, 0x3c040800, 0x248423d8, 
+0xa4800000, 0x3c010800, 0xa0201b98, 0x3c010800, 
+0xac201b9c, 0x3c010800, 0xac201ba0, 0x3c010800, 
+0xac201ba4, 0x3c010800, 0xac201bac, 0x3c010800, 
+0xac201bb8, 0x3c010800, 0xac201bbc, 0x8f624434, 
+0x3c010800, 0xac221b88, 0x8f624438, 0x3c010800, 
+0xac221b8c, 0x8f624410, 0xac80f7a8, 0x3c010800, 
+0xac201b84, 0x3c010800, 0xac2023e0, 0x3c010800, 
+0xac2023c8, 0x3c010800, 0xac2023cc, 0x3c010800, 
+0xac202400, 0x3c010800, 0xac221b90, 0x8f620068, 
+0x24030007, 0x21702, 0x10430005, 0x0, 
+0x8f620068, 0x21702, 0x14400004, 0x24020001, 
+0x3c010800, 0xa000097, 0xac20240c, 0xac820034, 
+0x3c040800, 0x24841acc, 0x3c050800, 0x8ca5240c, 
+0x3021, 0x3821, 0xafa00010, 0xe00067c, 
+0xafa00014, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
+0x27bdffe0, 0x3c040800, 0x24841ad8, 0x2821, 
+0x3021, 0x3821, 0xafbf0018, 0xafa00010, 
+0xe00067c, 0xafa00014, 0xe00005b, 0x0, 
+0xe0000b4, 0x2021, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x24020001, 0x8f636820, 0x821004, 
+0x21027, 0x621824, 0x3e00008, 0xaf636820, 
+0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, 
+0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 
+0xafb00010, 0x8f675c5c, 0x3c030800, 0x24631bbc, 
+0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 
+0x90421b98, 0x14400119, 0x3c0200ff, 0x3442fff8, 
+0xe28824, 0xac670000, 0x111902, 0x306300ff, 
+0x30e20003, 0x211c0, 0x622825, 0xa04021, 
+0x71602, 0x3c030800, 0x90631b98, 0x3044000f, 
+0x14600036, 0x804821, 0x24020001, 0x3c010800, 
+0xa0221b98, 0x51100, 0x821025, 0x3c010800, 
+0xac201b9c, 0x3c010800, 0xac201ba0, 0x3c010800, 
+0xac201ba4, 0x3c010800, 0xac201bac, 0x3c010800, 
+0xac201bb8, 0x3c010800, 0xac201bb0, 0x3c010800, 
+0xac201bb4, 0x3c010800, 0xa42223d8, 0x9622000c, 
+0x30437fff, 0x3c010800, 0xa4222410, 0x30428000, 
+0x3c010800, 0xa4231bc6, 0x10400005, 0x24020001, 
+0x3c010800, 0xac2223f4, 0xa000102, 0x2406003e, 
+0x24060036, 0x3c010800, 0xac2023f4, 0x9622000a, 
+0x3c030800, 0x94631bc6, 0x3c010800, 0xac2023f0, 
+0x3c010800, 0xac2023f8, 0x21302, 0x21080, 
+0xc21021, 0x621821, 0x3c010800, 0xa42223d0, 
+0x3c010800, 0xa000115, 0xa4231b96, 0x9622000c, 
+0x3c010800, 0xa42223ec, 0x3c040800, 0x24841b9c, 
+0x8c820000, 0x21100, 0x3c010800, 0x220821, 
+0xac311bc8, 0x8c820000, 0x21100, 0x3c010800, 
+0x220821, 0xac271bcc, 0x8c820000, 0x25030001, 
+0x306601ff, 0x21100, 0x3c010800, 0x220821, 
+0xac261bd0, 0x8c820000, 0x21100, 0x3c010800, 
+0x220821, 0xac291bd4, 0x96230008, 0x3c020800, 
+0x8c421bac, 0x432821, 0x3c010800, 0xac251bac, 
+0x9622000a, 0x30420004, 0x14400018, 0x61100, 
+0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, 
+0x3c02c000, 0x8f630c14, 0x3c020800, 0x8c421b40, 
+0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 
+0x2c620002, 0x1040fff7, 0x3c02c000, 0xe21825, 
+0xaf635c5c, 0x8f625c50, 0x30420002, 0x10400014, 
+0x0, 0xa000147, 0x0, 0x3c030800, 
+0x8c631b80, 0x3c040800, 0x94841b94, 0x1221025, 
+0x3c010800, 0xa42223da, 0x24020001, 0x3c010800, 
+0xac221bb8, 0x24630001, 0x85202a, 0x3c010800, 
+0x10800003, 0xac231b80, 0x3c010800, 0xa4251b94, 
+0x3c060800, 0x24c61b9c, 0x8cc20000, 0x24420001, 
+0xacc20000, 0x28420080, 0x14400005, 0x0, 
+0xe000656, 0x24040002, 0xa0001e6, 0x0, 
+0x3c020800, 0x8c421bb8, 0x10400078, 0x24020001, 
+0x3c050800, 0x90a51b98, 0x14a20072, 0x0, 
+0x3c150800, 0x96b51b96, 0x3c040800, 0x8c841bac, 
+0x32a3ffff, 0x83102a, 0x1440006c, 0x0, 
+0x14830003, 0x0, 0x3c010800, 0xac2523f0, 
+0x1060005c, 0x9021, 0x24d60004, 0x60a021, 
+0x24d30014, 0x8ec20000, 0x28100, 0x3c110800, 
+0x2308821, 0xe000625, 0x8e311bc8, 0x402821, 
+0x10a00054, 0x0, 0x9628000a, 0x31020040, 
+0x10400005, 0x2407180c, 0x8e22000c, 0x2407188c, 
+0x21400, 0xaca20018, 0x3c030800, 0x701821, 
+0x8c631bd0, 0x3c020800, 0x501021, 0x8c421bd4, 
+0x31d00, 0x21400, 0x621825, 0xaca30014, 
+0x8ec30004, 0x96220008, 0x432023, 0x3242ffff, 
+0x3083ffff, 0x431021, 0x282102a, 0x14400002, 
+0x2b23023, 0x803021, 0x8e620000, 0x30c4ffff, 
+0x441021, 0xae620000, 0x8e220000, 0xaca20000, 
+0x8e220004, 0x8e63fff4, 0x431021, 0xaca20004, 
+0xa4a6000e, 0x8e62fff4, 0x441021, 0xae62fff4, 
+0x96230008, 0x43102a, 0x14400005, 0x2469021, 
+0x8e62fff0, 0xae60fff4, 0x24420001, 0xae62fff0, 
+0xaca00008, 0x3242ffff, 0x14540008, 0x24020305, 
+0x31020080, 0x54400001, 0x34e70010, 0x24020905, 
+0xa4a2000c, 0xa0001cb, 0x34e70020, 0xa4a2000c, 
+0x3c020800, 0x8c4223f0, 0x10400003, 0x3c024b65, 
+0xa0001d3, 0x34427654, 0x3c02b49a, 0x344289ab, 
+0xaca2001c, 0x30e2ffff, 0xaca20010, 0xe0005a2, 
+0xa02021, 0x3242ffff, 0x54102b, 0x1440ffa9, 
+0x0, 0x24020002, 0x3c010800, 0xa0001e6, 
+0xa0221b98, 0x8ec2083c, 0x24420001, 0xa0001e6, 
+0xaec2083c, 0xe0004c0, 0x0, 0x8fbf002c, 
+0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 
+0x27bd0030, 0x27bdffd0, 0xafbf0028, 0xafb30024, 
+0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 
+0x3c0200ff, 0x3442fff8, 0x3c070800, 0x24e71bb4, 
+0x2428824, 0x9623000e, 0x8ce20000, 0x431021, 
+0xace20000, 0x8e220010, 0x30420020, 0x14400011, 
+0x809821, 0xe00063b, 0x2202021, 0x3c02c000, 
+0x2421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 
+0x1040011e, 0x0, 0xaf635c9c, 0x8f625c90, 
+0x30420002, 0x10400119, 0x0, 0xa00020d, 
+0x0, 0x8e240008, 0x8e230014, 0x41402, 
+0x231c0, 0x31502, 0x304201ff, 0x2442ffff, 
+0x3042007f, 0x31942, 0x30637800, 0x21100, 
+0x24424000, 0x624821, 0x9522000a, 0x3084ffff, 
+0x30420008, 0x104000b0, 0x429c0, 0x3c020800, 
+0x8c422400, 0x14400024, 0x24c50008, 0x94c20014, 
+0x3c010800, 0xa42223d0, 0x8cc40010, 0x41402, 
+0x3c010800, 0xa42223d2, 0x3c010800, 0xa42423d4, 
+0x94c2000e, 0x3083ffff, 0x431023, 0x3c010800, 
+0xac222408, 0x94c2001a, 0x3c010800, 0xac262400, 
+0x3c010800, 0xac322404, 0x3c010800, 0xac2223fc, 
+0x3c02c000, 0x2421825, 0xaf635c9c, 0x8f625c90, 
+0x30420002, 0x104000e5, 0x0, 0xaf635c9c, 
+0x8f625c90, 0x30420002, 0x104000e0, 0x0, 
+0xa000246, 0x0, 0x94c2000e, 0x3c030800, 
+0x946323d4, 0x434023, 0x3103ffff, 0x2c620008, 
+0x1040001c, 0x0, 0x94c20014, 0x24420028, 
+0xa22821, 0x31042, 0x1840000b, 0x2021, 
+0x24e60848, 0x403821, 0x94a30000, 0x8cc20000, 
+0x24840001, 0x431021, 0xacc20000, 0x87102a, 
+0x1440fff9, 0x24a50002, 0x31020001, 0x1040001f, 
+0x3c024000, 0x3c040800, 0x248423fc, 0xa0a00001, 
+0x94a30000, 0x8c820000, 0x431021, 0xa000285, 
+0xac820000, 0x8f626800, 0x3c030010, 0x431024, 
+0x10400009, 0x0, 0x94c2001a, 0x3c030800, 
+0x8c6323fc, 0x431021, 0x3c010800, 0xac2223fc, 
+0xa000286, 0x3c024000, 0x94c2001a, 0x94c4001c, 
+0x3c030800, 0x8c6323fc, 0x441023, 0x621821, 
+0x3c010800, 0xac2323fc, 0x3c024000, 0x2421825, 
+0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 
+0x0, 0x9522000a, 0x30420010, 0x1040009b, 
+0x0, 0x3c030800, 0x946323d4, 0x3c070800, 
+0x24e72400, 0x8ce40000, 0x8f626800, 0x24630030, 
+0x832821, 0x3c030010, 0x431024, 0x1440000a, 
+0x0, 0x94a20004, 0x3c040800, 0x8c842408, 
+0x3c030800, 0x8c6323fc, 0x441023, 0x621821, 
+0x3c010800, 0xac2323fc, 0x3c040800, 0x8c8423fc, 
+0x41c02, 0x3082ffff, 0x622021, 0x41402, 
+0x822021, 0x41027, 0xa4a20006, 0x3c030800, 
+0x8c632404, 0x3c0200ff, 0x3442fff8, 0x628824, 
+0x96220008, 0x24050001, 0x24034000, 0x231c0, 
+0x801021, 0xa4c2001a, 0xa4c0001c, 0xace00000, 
+0x3c010800, 0xac251b60, 0xaf635cb8, 0x8f625cb0, 
+0x30420002, 0x10400003, 0x0, 0x3c010800, 
+0xac201b60, 0x8e220008, 0xaf625cb8, 0x8f625cb0, 
+0x30420002, 0x10400003, 0x0, 0x3c010800, 
+0xac201b60, 0x3c020800, 0x8c421b60, 0x1040ffec, 
+0x0, 0x3c040800, 0xe00063b, 0x8c842404, 
+0xa00032a, 0x0, 0x3c030800, 0x90631b98, 
+0x24020002, 0x14620003, 0x3c034b65, 0xa0002e1, 
+0x8021, 0x8e22001c, 0x34637654, 0x10430002, 
+0x24100002, 0x24100001, 0xc02021, 0xe000350, 
+0x2003021, 0x24020003, 0x3c010800, 0xa0221b98, 
+0x24020002, 0x1202000a, 0x24020001, 0x3c030800, 
+0x8c6323f0, 0x10620006, 0x0, 0x3c020800, 
+0x944223d8, 0x21400, 0xa00031f, 0xae220014, 
+0x3c040800, 0x248423da, 0x94820000, 0x21400, 
+0xae220014, 0x3c020800, 0x8c421bbc, 0x3c03c000, 
+0x3c010800, 0xa0201b98, 0x431025, 0xaf625c5c, 
+0x8f625c50, 0x30420002, 0x10400009, 0x0, 
+0x2484f7e2, 0x8c820000, 0x431025, 0xaf625c5c, 
+0x8f625c50, 0x30420002, 0x1440fffa, 0x0, 
+0x3c020800, 0x24421b84, 0x8c430000, 0x24630001, 
+0xac430000, 0x8f630c14, 0x3063000f, 0x2c620002, 
+0x1440000c, 0x3c024000, 0x8f630c14, 0x3c020800, 
+0x8c421b40, 0x3063000f, 0x24420001, 0x3c010800, 
+0xac221b40, 0x2c620002, 0x1040fff7, 0x0, 
+0x3c024000, 0x2421825, 0xaf635c9c, 0x8f625c90, 
+0x30420002, 0x1440fffc, 0x0, 0x12600003, 
+0x0, 0xe0004c0, 0x0, 0x8fbf0028, 
+0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 
+0x3e00008, 0x27bd0030, 0x8f634450, 0x3c040800, 
+0x24841b88, 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, 0x14c00011, 
+0x256e0008, 0x3c020800, 0x8c4223f4, 0x10400007, 
+0x24020016, 0x3c010800, 0xa42223d2, 0x2402002a, 
+0x3c010800, 0xa000364, 0xa42223d4, 0x8d670010, 
+0x71402, 0x3c010800, 0xa42223d2, 0x3c010800, 
+0xa42723d4, 0x3c040800, 0x948423d4, 0x3c030800, 
+0x946323d2, 0x95cf0006, 0x3c020800, 0x944223d0, 
+0x832023, 0x1e2c023, 0x3065ffff, 0x24a20028, 
+0x1c24821, 0x3082ffff, 0x14c0001a, 0x1226021, 
+0x9582000c, 0x3042003f, 0x3c010800, 0xa42223d6, 
+0x95820004, 0x95830006, 0x3c010800, 0xac2023e4, 
+0x3c010800, 0xac2023e8, 0x21400, 0x431025, 
+0x3c010800, 0xac221bc0, 0x95220004, 0x3c010800, 
+0xa4221bc4, 0x95230002, 0x1e51023, 0x43102a, 
+0x10400010, 0x24020001, 0x3c010800, 0xa000398, 
+0xac2223f8, 0x3c030800, 0x8c6323e8, 0x3c020800, 
+0x94421bc4, 0x431021, 0xa5220004, 0x3c020800, 
+0x94421bc0, 0xa5820004, 0x3c020800, 0x8c421bc0, 
+0xa5820006, 0x3c020800, 0x8c4223f0, 0x3c0d0800, 
+0x8dad23e4, 0x3c0a0800, 0x144000e5, 0x8d4a23e8, 
+0x3c020800, 0x94421bc4, 0x4a1821, 0x3063ffff, 
+0x62182b, 0x24020002, 0x10c2000d, 0x1435023, 
+0x3c020800, 0x944223d6, 0x30420009, 0x10400008, 
+0x0, 0x9582000c, 0x3042fff6, 0xa582000c, 
+0x3c020800, 0x944223d6, 0x30420009, 0x1a26823, 
+0x3c020800, 0x8c4223f8, 0x1040004a, 0x1203821, 
+0x3c020800, 0x944223d2, 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, 0xa00047d, 
+0x30c6ffff, 0x24020002, 0x14c20081, 0x0, 
+0x3c020800, 0x8c42240c, 0x14400007, 0x0, 
+0x3c020800, 0x944223d2, 0x95230002, 0x1e21023, 
+0x10620077, 0x0, 0x3c020800, 0x944223d2, 
+0x1e21023, 0xa5220002, 0x3c020800, 0x8c42240c, 
+0x1040001a, 0x31e3ffff, 0x8dc70010, 0x3c020800, 
+0x94421b96, 0xe04021, 0x72c02, 0xaa2021, 
+0x431023, 0x823823, 0x72402, 0x30e2ffff, 
+0x823821, 0x71027, 0xa522000a, 0x3102ffff, 
+0x3c040800, 0x948423d4, 0x453023, 0xe02821, 
+0x641823, 0x6d1821, 0xc33021, 0x61c02, 
+0x30c2ffff, 0xa00047d, 0x623021, 0x1203821, 
+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, 0x948423d4, 0x621821, 0xc33021, 
+0x61c02, 0x30c2ffff, 0x623021, 0x61c02, 
+0x3c020800, 0x944223d0, 0xc34821, 0x441023, 
+0x21fc2, 0x431021, 0x21043, 0x18400010, 
+0x3021, 0x402021, 0x94e20000, 0x24e70002, 
+0xc23021, 0x30e2007f, 0x14400006, 0x25080001, 
+0x8d630000, 0x3c02007f, 0x3442ff80, 0x625824, 
+0x25670008, 0x104102a, 0x1440fff3, 0x0, 
+0x3c020800, 0x944223ec, 0xc23021, 0x3122ffff, 
+0xc23021, 0x61c02, 0x30c2ffff, 0x623021, 
+0x61402, 0xc23021, 0xc04021, 0x61027, 
+0xa5820010, 0xadc00014, 0xa00049d, 0xadc00000, 
+0x8dc70010, 0xe04021, 0x11400007, 0x72c02, 
+0xaa3021, 0x61402, 0x30c3ffff, 0x433021, 
+0x61402, 0xc22821, 0x51027, 0xa522000a, 
+0x3c030800, 0x946323d4, 0x3102ffff, 0x1e21021, 
+0x433023, 0xcd3021, 0x61c02, 0x30c2ffff, 
+0x623021, 0x61402, 0xc23021, 0xc04021, 
+0x61027, 0xa5820010, 0x3102ffff, 0x51c00, 
+0x431025, 0xadc20010, 0x3c020800, 0x8c4223f4, 
+0x10400005, 0x2de205eb, 0x14400002, 0x25e2fff2, 
+0x34028870, 0xa5c20034, 0x3c030800, 0x246323e8, 
+0x8c620000, 0x24420001, 0xac620000, 0x3c040800, 
+0x8c8423e4, 0x3c020800, 0x8c421bc0, 0x3303ffff, 
+0x832021, 0x431821, 0x62102b, 0x3c010800, 
+0xac2423e4, 0x10400003, 0x2482ffff, 0x3c010800, 
+0xac2223e4, 0x3c010800, 0xac231bc0, 0x3e00008, 
+0x27bd0020, 0x27bdffb8, 0x3c050800, 0x24a51b96, 
+0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 
+0xafb50034, 0xafb40030, 0xafb3002c, 0xafb20028, 
+0xafb10024, 0xafb00020, 0x94a90000, 0x3c020800, 
+0x944223d0, 0x3c030800, 0x8c631bb0, 0x3c040800, 
+0x8c841bac, 0x1221023, 0x64182a, 0xa7a9001e, 
+0x106000be, 0xa7a20016, 0x24be0022, 0x97b6001e, 
+0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 
+0x0, 0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 
+0x431021, 0x82202a, 0x148000b0, 0x0, 
+0x97d50818, 0x32a2ffff, 0x104000a3, 0x9021, 
+0x40a021, 0x8821, 0xe000625, 0x0, 
+0x403021, 0x14c00007, 0x0, 0x3c020800, 
+0x8c4223dc, 0x24420001, 0x3c010800, 0xa000596, 
+0xac2223dc, 0x3c100800, 0x2118021, 0x8e101bc8, 
+0x9608000a, 0x31020040, 0x10400005, 0x2407180c, 
+0x8e02000c, 0x2407188c, 0x21400, 0xacc20018, 
+0x31020080, 0x54400001, 0x34e70010, 0x3c020800, 
+0x511021, 0x8c421bd0, 0x3c030800, 0x711821, 
+0x8c631bd4, 0x21500, 0x31c00, 0x431025, 
+0xacc20014, 0x96040008, 0x3242ffff, 0x821021, 
+0x282102a, 0x14400002, 0x2b22823, 0x802821, 
+0x8e020000, 0x2459021, 0xacc20000, 0x8e020004, 
+0xc02021, 0x26310010, 0xac820004, 0x30e2ffff, 
+0xac800008, 0xa485000e, 0xac820010, 0x24020305, 
+0xe0005a2, 0xa482000c, 0x3242ffff, 0x54102b, 
+0x1440ffc5, 0x3242ffff, 0xa00058e, 0x0, 
+0x8e620000, 0x8e63fffc, 0x43102a, 0x10400067, 
+0x0, 0x8e62fff0, 0x28900, 0x3c100800, 
+0x2118021, 0xe000625, 0x8e101bc8, 0x403021, 
+0x14c00005, 0x0, 0x8e62082c, 0x24420001, 
+0xa000596, 0xae62082c, 0x9608000a, 0x31020040, 
+0x10400005, 0x2407180c, 0x8e02000c, 0x2407188c, 
+0x21400, 0xacc20018, 0x3c020800, 0x511021, 
+0x8c421bd0, 0x3c030800, 0x711821, 0x8c631bd4, 
+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, 0xa000571, 
+0xae62fff0, 0xae63fff4, 0xacc00008, 0x3242ffff, 
+0x10560003, 0x31020004, 0x10400006, 0x24020305, 
+0x31020080, 0x54400001, 0x34e70010, 0x34e70020, 
+0x24020905, 0xa4c2000c, 0x8ee30000, 0x8ee20004, 
+0x14620007, 0x3c02b49a, 0x8ee20860, 0x54400001, 
+0x34e70400, 0x3c024b65, 0xa000588, 0x34427654, 
+0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010, 
+0xe0005a2, 0xc02021, 0x3242ffff, 0x56102b, 
+0x1440ff9b, 0x0, 0x8e620000, 0x8e63fffc, 
+0x43102a, 0x1440ff48, 0x0, 0x8fbf0044, 
+0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034, 
+0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 
+0x8fb00020, 0x3e00008, 0x27bd0048, 0x27bdffe8, 
+0xafbf0014, 0xafb00010, 0x8f624450, 0x8f634410, 
+0xa0005b1, 0x808021, 0x8f626820, 0x30422000, 
+0x10400003, 0x0, 0xe0001f0, 0x2021, 
+0x8f624450, 0x8f634410, 0x3042ffff, 0x43102b, 
+0x1440fff5, 0x0, 0x8f630c14, 0x3063000f, 
+0x2c620002, 0x1440000b, 0x0, 0x8f630c14, 
+0x3c020800, 0x8c421b40, 0x3063000f, 0x24420001, 
+0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7, 
+0x0, 0xaf705c18, 0x8f625c10, 0x30420002, 
+0x10400009, 0x0, 0x8f626820, 0x30422000, 
+0x1040fff8, 0x0, 0xe0001f0, 0x2021, 
+0xa0005c4, 0x0, 0x8fbf0014, 0x8fb00010, 
+0x3e00008, 0x27bd0018, 0x0, 0x0, 
+0x0, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 
+0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 
+0xaf626804, 0x8f634000, 0x24020b50, 0x3c010800, 
+0xac221b54, 0x24020b78, 0x3c010800, 0xac221b64, 
+0x34630002, 0xaf634000, 0xe000605, 0x808021, 
+0x3c010800, 0xa0221b68, 0x304200ff, 0x24030002, 
+0x14430005, 0x0, 0x3c020800, 0x8c421b54, 
+0xa0005f8, 0xac5000c0, 0x3c020800, 0x8c421b54, 
+0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 
+0x3c010800, 0xac221b5c, 0x3c010800, 0xac231b6c, 
+0x3c010800, 0xac241b58, 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, 
+0x8c421b5c, 0x31c02, 0x43102b, 0x14400008, 
+0x3c038000, 0x3c040800, 0x8c841b6c, 0x8f624450, 
+0x21c02, 0x83102b, 0x1040fffc, 0x3c038000, 
+0xaf634444, 0x8f624444, 0x431024, 0x1440fffd, 
+0x0, 0x8f624448, 0x3e00008, 0x3042ffff, 
+0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 
+0x3c024000, 0xa000648, 0x2402ffff, 0x822025, 
+0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 
+0x1021, 0x3e00008, 0x0, 0x8f624450, 
+0x3c030800, 0x8c631b58, 0xa000651, 0x3042ffff, 
+0x8f624450, 0x3042ffff, 0x43102b, 0x1440fffc, 
+0x0, 0x3e00008, 0x0, 0x27bdffe0, 
+0x802821, 0x3c040800, 0x24841af0, 0x3021, 
+0x3821, 0xafbf0018, 0xafa00010, 0xe00067c, 
+0xafa00014, 0xa000660, 0x0, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x0, 0x0, 
+0x0, 0x3c020800, 0x34423000, 0x3c030800, 
+0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 
+0xac221b74, 0x24020040, 0x3c010800, 0xac221b78, 
+0x3c010800, 0xac201b70, 0xac600000, 0x24630004, 
+0x83102b, 0x5040fffd, 0xac600000, 0x3e00008, 
+0x0, 0x804821, 0x8faa0010, 0x3c020800, 
+0x8c421b70, 0x3c040800, 0x8c841b78, 0x8fab0014, 
+0x24430001, 0x44102b, 0x3c010800, 0xac231b70, 
+0x14400003, 0x4021, 0x3c010800, 0xac201b70, 
+0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74, 
+0x91240000, 0x21140, 0x431021, 0x481021, 
+0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, 
+0x25290001, 0x3c020800, 0x8c421b70, 0x3c030800, 
+0x8c631b74, 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[(0x30/4) + 1] = {
+0x0, 0x73746b6f, 0x66666c64, 
+0x5f76312e, 0x362e3000, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0 };
+
+#endif /* __FW_STKOFFLD_H__  */
diff --git a/drivers/net/bcm5700/lm.h b/drivers/net/bcm5700/lm.h
new file mode 100644 (file)
index 0000000..4f6fd7a
--- /dev/null
@@ -0,0 +1,469 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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;
+
+
+typedef LM_UINT32 LM_RESET_TYPE;
+#define LM_SHUTDOWN_RESET     0
+#define LM_INIT_RESET         1
+#define LM_SUSPEND_RESET      2
+
+/******************************************************************************/
+/* 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);
+#ifdef BCM_NAPI_RXPOLL
+int LM_ServiceRxPoll(PLM_DEVICE_BLOCK pDevice, int limit);
+#endif
+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_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_EnableExtLoopBack(PLM_DEVICE_BLOCK pDevice, LM_LINE_SPEED Speed);
+LM_STATUS LM_DisableExtLoopBack(PLM_DEVICE_BLOCK pDevice);
+
+LM_STATUS LM_SetupPhy(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS 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);
+LM_VOID LM_ResetPhy(PLM_DEVICE_BLOCK pDevice);
+LM_STATUS LM_ShutdownChip(PLM_DEVICE_BLOCK pDevice, LM_RESET_TYPE Mode);
+LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number);
+LM_UINT32 ComputeCrc32(LM_UINT8 *pBuffer, LM_UINT32 BufferSize);
+LM_STATUS LM_SwitchClocks(PLM_DEVICE_BLOCK pDevice);
+
+void LM_5714_FamForceFiber( PLM_DEVICE_BLOCK pDevice);
+void LM_5714_FamGoFiberAutoNeg( PLM_DEVICE_BLOCK pDevice);
+void LM_5714_FamFiberCheckLink( PLM_DEVICE_BLOCK pDevice);
+
+/******************************************************************************/
+/* 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);
+int MM_FindCapability(PLM_DEVICE_BLOCK pDevice, int capability);
+LM_VOID MM_UnmapRxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
+#ifdef BCM_NAPI_RXPOLL
+LM_STATUS MM_ScheduleRxPoll(PLM_DEVICE_BLOCK pDevice);
+#endif
+LM_STATUS MM_Sleep(PLM_DEVICE_BLOCK pDevice, LM_UINT32 msec);
+LM_STATUS LM_MbufWorkAround(PLM_DEVICE_BLOCK pDevice);
+
+#ifdef INCLUDE_5703_A0_FIX
+LM_STATUS LM_Load5703DmaWFirmware(PLM_DEVICE_BLOCK pDevice);
+#endif
+
+
+#endif /* LM_H */
+
diff --git a/drivers/net/bcm5700/mm.h b/drivers/net/bcm5700/mm.h
new file mode 100644 (file)
index 0000000..aeb4f88
--- /dev/null
@@ -0,0 +1,611 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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)
+#ifndef BCM_SMALL_DRV
+#define MODVERSIONS
+#endif
+#endif
+
+#ifndef B57UM
+#define __NO_VERSION__
+#endif
+#include <linux/version.h>
+
+#ifdef MODULE
+
+#if defined(MODVERSIONS) && (LINUX_VERSION_CODE < 0x020500)
+#ifndef BCM_SMALL_DRV
+#include <linux/modversions.h>
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020605)
+#include <linux/module.h>
+#else
+#include <linux/moduleparam.h>
+#endif
+
+#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>
+#include <asm/uaccess.h>
+#if (LINUX_VERSION_CODE >= 0x020400)
+#if (LINUX_VERSION_CODE < 0x020500)
+#include <linux/wrapper.h>
+#endif
+#include <linux/ethtool.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
+
+#ifndef LINUX_KERNEL_VERSION
+#define LINUX_KERNEL_VERSION   0
+#endif
+
+#ifndef MAX_SKB_FRAGS
+#define MAX_SKB_FRAGS  0
+#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
+
+#if HAVE_NETIF_RECEIVE_SKB
+#define BCM_NAPI_RXPOLL 1
+#undef BCM_TASKLET
+#endif
+
+#if defined(CONFIG_PPC64)
+#define BCM_DISCONNECT_AT_CACHELINE 1
+#endif
+
+#ifdef BCM_SMALL_DRV
+#undef BCM_PROC_FS
+#undef ETHTOOL_GEEPROM
+#undef ETHTOOL_SEEPROM
+#undef ETHTOOL_GREGS
+#undef ETHTOOL_GPAUSEPARAM
+#undef ETHTOOL_GRXCSUM
+#undef ETHTOOL_TEST
+#undef BCM_INT_COAL
+#undef BCM_NIC_SEND_BD
+#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)
+#define MM_SWAP_BE32(x) cpu_to_be32(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)
+
+
+#ifndef mmiowb
+#define mmiowb()
+#endif
+
+
+#define MM_MB() mb()
+#define MM_WMB() wmb()
+#define MM_RMB() rmb()
+#define MM_MMIOWB() mmiowb()
+
+#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
+#define MAX_MEM2 4
+
+#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;
+
+#ifdef NICE_SUPPORT
+       void *mem_list2[MAX_MEM2];              /* for diagnostics ioctl */
+       dma_addr_t dma_list2[MAX_MEM2];
+       __u64 cpu_pa_list2[MAX_MEM2];
+       int mem_size_list2[MAX_MEM2];
+#endif
+       int index;
+       int opened;
+       int suspended;
+       int using_dac;          /* dual address cycle */
+       int delayed_link_ind; /* Delay link status during initial load */
+       int adapter_just_inited; /* the first few seconds after init. */
+       int timer_interval;
+       int statstimer_interval;
+       int adaptive_expiry;
+       int crc_counter_expiry;
+       int poll_tbi_interval;
+       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_repl_isr_limit;
+       int rx_buf_align;
+       struct timer_list timer;
+       struct timer_list statstimer;
+       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;
+#endif /* NICE_SUPPORT */
+       int intr_test;
+       int intr_test_result;
+#ifdef NETIF_F_HW_VLAN_TX
+       struct vlan_group *vlgrp;
+#endif
+       int vlan_tag_mode;      /* Setting to allow ASF to work properly with */
+                               /* VLANs                                      */
+       #define VLAN_TAG_MODE_AUTO_STRIP              0
+       #define VLAN_TAG_MODE_NORMAL_STRIP            1
+       #define VLAN_TAG_MODE_FORCED_STRIP            2
+
+       /* Auto mode - VLAN TAGs are always stripped if ASF is enabled,   */
+       /*             If ASF is not enabled, it will be in normal mode.  */
+       /* Normal mode - VLAN TAGs are stripped when VLANs are registered */
+       /* Forced mode - VLAN TAGs are always stripped.                   */
+
+       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;
+       uint64_t phy_crc_count;
+       unsigned int spurious_int;
+} 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 BCM5700_PHY_LOCK(pUmDevice, flags) {                           \
+       spinlock_t *lock;                                               \
+       if ((pUmDevice)->do_global_lock) {                              \
+               lock = &(pUmDevice)->global_lock;                       \
+       }                                                               \
+       else {                                                          \
+               lock = &(pUmDevice)->phy_lock;                          \
+       }                                                               \
+       spin_lock_irqsave(lock, flags);                                 \
+}
+
+#define BCM5700_PHY_UNLOCK(pUmDevice, flags) {                         \
+       spinlock_t *lock;                                               \
+       if ((pUmDevice)->do_global_lock) {                              \
+               lock = &(pUmDevice)->global_lock;                       \
+       }                                                               \
+       else {                                                          \
+               lock = &(pUmDevice)->phy_lock;                          \
+       }                                                               \
+       spin_unlock_irqrestore(lock, flags);                            \
+}
+
+
+#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))
+
+#define MM_GETSTATS64(_Ctr) \
+       (uint64_t) (_Ctr).Low + ((uint64_t) (_Ctr).High << 32)
+
+#define MM_GETSTATS32(_Ctr) \
+       (uint32_t) (_Ctr).Low
+
+#if (BITS_PER_LONG == 64)
+#define MM_GETSTATS(_Ctr) (unsigned long) MM_GETSTATS64(_Ctr)
+#else
+#define MM_GETSTATS(_Ctr) (unsigned long) MM_GETSTATS32(_Ctr)
+#endif
+
+#if (LINUX_VERSION_CODE >= 0x020600)
+#define mm_copy_to_user( to, from, size ) \
+       (in_atomic() ? (memcpy((to),(from),(size)), 0) : copy_to_user((to),(from),(size)))
+#define mm_copy_from_user( to, from, size ) \
+       (in_atomic() ? (memcpy((to),(from),(size)), 0) : copy_from_user((to),(from),(size)))
+#else
+#define mm_copy_to_user( to, from, size )      \
+               copy_to_user((to),(from),(size) )
+#define mm_copy_from_user( to, from, size )    \
+               copy_from_user((to),(from),(size))
+#endif
+
+
+#define printf(fmt, args...) printk(KERN_WARNING fmt, ##args)
+
+#define DbgPrint(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
+#if defined(CONFIG_X86)
+#define DbgBreakPoint() __asm__("int $129")
+#else
+#define DbgBreakPoint()
+#endif
+#define MM_Wait(time) udelay(time)
+
+#endif
diff --git a/drivers/net/bcm5700/nicext.h b/drivers/net/bcm5700/nicext.h
new file mode 100644 (file)
index 0000000..a61c52f
--- /dev/null
@@ -0,0 +1,259 @@
+/****************************************************************************
+ * Copyright(c) 2000-2004 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 */
+        /* cmd = NICE_CMD_SET_RX_NAPI or NICE_CMD_GET_RX_NAPI */
+        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;
+            __u32 nrqus2_support_rx_napi:1;
+        } nrqu_nrqus2;
+#endif
+
+        void *align_ptr;  /* this field is not used, it is to align the union */
+                          /* in 64-bit user mode */
+
+        /* cmd = NICE_CMD_GET_SPEED - in Mbps or 0 if link down */
+        /* cmd = NICE_CMD_ENABLE_EXT_LOOPBACK  - in Mbps */
+        struct
+        {
+            unsigned int nrqus3_speed;   /* 1000 = Gb, 100 = 100mbs, 10 = 10mbs */
+        } 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 */
+        /* cmd = NICE_CMD_REG_READ_DIRECT */
+        /* cmd = NICE_CMD_REG_WRITE_DIRECT */
+        /* cmd = NICE_CMD_CFG_READ32 */
+        /* cmd = NICE_CMD_CFG_READ16 */
+        /* cmd = NICE_CMD_CFG_READ8 */
+        /* cmd = NICE_CMD_CFG_WRITE32 */
+        /* cmd = NICE_CMD_CFG_WRITE16 */
+        /* cmd = NICE_CMD_CFG_WRITE8 */
+        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;
+
+        /* cmd = NICE_CMD_KMALLOC_PHYS */
+        /* cmd = NICE_CMD_KFREE_PHYS */
+        /* These commands allow the diagnostics app. to allocate and free */
+        /* PCI consistent memory for DMA tests */
+       struct
+        {
+            unsigned int nrqus7_size; /* size(bytes) to allocate, not used    */
+                                      /* when cmd is NICE_CMD_KFREE_PHYS.     */
+            __u32 nrqus7_phys_addr_lo;/* CPU physical address allocated or    */
+            __u32 nrqus7_phys_addr_hi;/* to be freed.                         */
+                                      /* PCI physical address is contained in */
+                                      /* the 1st 64 bit of the allocated      */
+                                      /* buffer. Use open("/dev/mem")/lseek() */
+                                      /* and read()/write() to a access       */
+                                      /* buffer in user space.                */
+                                      /* mmap() only works on x86.            */
+        } nrqu_nrqus7;
+
+        /* cmd = NICE_CMD_SET_WRITE_PROTECT */
+        struct
+        {
+            unsigned int nrqus8_data; /* 1 == set write protect, 0 == clear write protect */
+        } nrqu_nrqus8;
+
+        /* cmd = NICE_CMD_GET_STATS_BLOCK */
+        struct
+        {
+            void *nrqus9_useraddr; /* user space address for the stats block */
+            unsigned int nrqus9_size;/* size (in bytes)                      */
+                                     /* (0x6c0 for the whole block)          */
+        } nrqu_nrqus9;
+
+        /* cmd = NICE_CMD_LOOPBACK_TEST */
+        struct
+        {
+            unsigned char nrqus10_looptype;
+            unsigned char nrqus10_loopspeed;
+        } nrqu_nrqus10;
+
+         /* cmd = NICE_CMD_KMAP_PHYS/KUNMAP_PHYS */
+        struct
+        {
+            int nrqus11_rw;          /* direction                            */
+           void *nrqus11_uaddr;      /* ptr to mem allocated in user space   */
+                                      /* when cmd is NICE_CMD_KFREE_PHYS.     */
+            __u32 nrqus11_phys_addr_lo;/* CPU physical address allocated or    */
+            __u32 nrqus11_phys_addr_hi;/* to be freed.                         */
+                                      /* PCI physical address is contained in */
+                                      /* the 1st 64 bit of the allocated      */
+                                      /* buffer. Use open("/dev/mem")/lseek() */
+                                      /* and read()/write() to a access       */
+                                      /* buffer in user space.                */
+                                      /* mmap() only works on x86.            */
+        } nrqu_nrqus11;
+   } 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_support_rx_napi nrq_nrqu.nrqu_nrqus2.nrqus2_support_rx_napi
+#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
+
+#define nrq_size         nrq_nrqu.nrqu_nrqus7.nrqus7_size
+#define nrq_phys_addr_lo nrq_nrqu.nrqu_nrqus7.nrqus7_phys_addr_lo
+#define nrq_phys_addr_hi nrq_nrqu.nrqu_nrqus7.nrqus7_phys_addr_hi
+
+#define nrq_rw           nrq_nrqu.nrqu_nrqus11.nrqus11_rw
+#define nrq_puaddr      nrq_nrqu.nrqu_nrqus11.nrqus11_uaddr
+#define nrq_phys_add_lo nrq_nrqu.nrqu_nrqus11.nrqus11_phys_addr_lo
+#define nrq_phys_add_hi nrq_nrqu.nrqu_nrqus11.nrqus11_phys_addr_hi
+
+#define nrq_write_protect nrq_nrqu.nrqu_nrqus8.nrqus8_data
+#define nrq_stats_useraddr nrq_nrqu.nrqu_nrqus9.nrqus9_useraddr
+#define nrq_stats_size    nrq_nrqu.nrqu_nrqus9.nrqus9_size
+
+#define nrq_looptype    nrq_nrqu.nrqu_nrqus10.nrqus10_looptype
+#define nrq_loopspeed   nrq_nrqu.nrqu_nrqus10.nrqus10_loopspeed
+
+/*
+ * magic constants
+ */
+#define NICE_REQUESTOR_MAGIC            0x4543494E // NICE in ascii
+#define NICE_DEVICE_MAGIC               0x4E494345 // ECIN in ascii
+
+#define NICE_LOOPBACK_TESTTYPE_MAC      0x1
+#define NICE_LOOPBACK_TESTTYPE_PHY      0x2
+#define NICE_LOOPBACK_TESTTYPE_EXT      0x4
+
+#define NICE_LOOPBACK_TEST_SPEEDMASK    0x3
+#define NICE_LOOPBACK_TEST_10MBPS       0x1
+#define NICE_LOOPBACK_TEST_100MBPS      0x2
+#define NICE_LOOPBACK_TEST_1000MBPS     0x3
+
+
+/*
+ * command field
+ */
+typedef enum {
+    NICE_CMD_QUERY_SUPPORT         = 0x00000001,
+    NICE_CMD_SET_RX                = 0x00000002,
+    NICE_CMD_GET_RX                = 0x00000003,
+    NICE_CMD_GET_SPEED             = 0x00000004,
+    NICE_CMD_BLINK_LED             = 0x00000005,
+    NICE_CMD_DIAG_SUSPEND          = 0x00000006,
+    NICE_CMD_DIAG_RESUME           = 0x00000007,
+    NICE_CMD_REG_READ              = 0x00000008,
+    NICE_CMD_REG_WRITE             = 0x00000009,
+    NICE_CMD_MEM_READ              = 0x0000000a,
+    NICE_CMD_MEM_WRITE             = 0x0000000b,
+    NICE_CMD_ENABLE_MAC_LOOPBACK   = 0x0000000c,
+    NICE_CMD_DISABLE_MAC_LOOPBACK  = 0x0000000d,
+    NICE_CMD_ENABLE_PHY_LOOPBACK   = 0x0000000e,
+    NICE_CMD_DISABLE_PHY_LOOPBACK  = 0x0000000f,
+    NICE_CMD_INTERRUPT_TEST        = 0x00000010,
+    NICE_CMD_SET_WRITE_PROTECT     = 0x00000011,
+    NICE_CMD_SET_RX_NAPI           = 0x00000012,
+    NICE_CMD_GET_RX_NAPI           = 0x00000013,
+    NICE_CMD_ENABLE_EXT_LOOPBACK   = 0x00000014,
+    NICE_CMD_DISABLE_EXT_LOOPBACK  = 0x00000015,
+    NICE_CMD_CFG_READ32            = 0x00000016,
+    NICE_CMD_CFG_READ16            = 0x00000017,
+    NICE_CMD_CFG_READ8             = 0x00000018,
+    NICE_CMD_CFG_WRITE32           = 0x00000019,
+    NICE_CMD_CFG_WRITE16           = 0x0000001a,
+    NICE_CMD_CFG_WRITE8            = 0x0000001b,
+
+    NICE_CMD_REG_READ_DIRECT       = 0x0000001e,
+    NICE_CMD_REG_WRITE_DIRECT      = 0x0000001f,
+    NICE_CMD_RESET                 = 0x00000020,
+    NICE_CMD_KMALLOC_PHYS          = 0x00000021,
+    NICE_CMD_KFREE_PHYS            = 0x00000022,
+    NICE_CMD_GET_STATS_BLOCK       = 0x00000023,
+    NICE_CMD_CLR_STATS_BLOCK       = 0x00000024,
+    NICE_CMD_LOOPBACK_TEST         = 0x00000025,
+    NICE_CMD_KMAP_PHYS            = 0x00000026,
+    NICE_CMD_KUNMAP_PHYS           = 0x00000027,
+    NICE_CMD_MAX
+} nice_cmds;
+
+#endif  // _nicext_h_
+
diff --git a/drivers/net/bcm5700/queue.h b/drivers/net/bcm5700/queue.h
new file mode 100644 (file)
index 0000000..c73be5e
--- /dev/null
@@ -0,0 +1,347 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 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;
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+    Tail = pQueue->Tail;
+
+    MM_MB();
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == 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 Head;
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+    Tail = pQueue->Tail;
+
+    MM_MB();
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == 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 >= (unsigned int) 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 >= (unsigned int) 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 --git a/drivers/net/bcm5700/tcp_seg.c b/drivers/net/bcm5700/tcp_seg.c
new file mode 100644 (file)
index 0000000..5a7c8f1
--- /dev/null
@@ -0,0 +1,106 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2002 - 2004 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"
+
+#ifdef 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_5750)
+  {
+      return 0;
+  }
+  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_IS_575X_PLUS(pDevice->ChipRevId))
+  {
+      return LM_STATUS_SUCCESS;
+  }
+  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 --git a/drivers/net/bcm5700/tigon3.c b/drivers/net/bcm5700/tigon3.c
new file mode 100644 (file)
index 0000000..6e0f3ce
--- /dev/null
@@ -0,0 +1,9889 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2005 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);
+static LM_VOID LM_PhyTapPowerMgmt(LM_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);
+#ifdef INCLUDE_TBI_SUPPORT
+STATIC LM_STATUS LM_SetupFiberPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_InitBcm800xPhy(PLM_DEVICE_BLOCK pDevice);
+#endif
+STATIC LM_STATUS LM_SetupCopperPhy(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_VOID LM_SetEthWireSpeed(LM_DEVICE_BLOCK *pDevice);
+STATIC LM_STATUS LM_PhyAdvertiseAll(LM_DEVICE_BLOCK *pDevice);
+STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid(LM_UINT16 Svid, LM_UINT16 Ssid);
+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_DisableChip(PLM_DEVICE_BLOCK pDevice);
+STATIC LM_STATUS LM_ResetChip(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);
+STATIC LM_VOID LM_WritePreResetSignatures(LM_DEVICE_BLOCK *pDevice,
+    LM_RESET_TYPE Mode);
+STATIC LM_VOID LM_WritePostResetSignatures(LM_DEVICE_BLOCK *pDevice,
+    LM_RESET_TYPE Mode);
+STATIC LM_VOID LM_WriteLegacySignatures(LM_DEVICE_BLOCK *pDevice,
+    LM_RESET_TYPE Mode);
+STATIC void LM_GetPhyId(LM_DEVICE_BLOCK *pDevice);
+
+/******************************************************************************/
+/* External functions. */
+/******************************************************************************/
+
+LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice);
+#ifdef INCLUDE_TCP_SEG_SUPPORT
+LM_STATUS LM_LoadStkOffLdFirmware(PLM_DEVICE_BLOCK pDevice);
+LM_UINT32 LM_GetStkOffLdFirmwareSize(PLM_DEVICE_BLOCK pDevice);
+#endif
+
+LM_UINT32
+LM_RegRd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register)
+{
+#ifdef PCIX_TARGET_WORKAROUND
+    if (pDevice->Flags & UNDI_FIX_FLAG)
+    {
+        return (LM_RegRdInd(pDevice, Register));
+    }
+    else
+#endif
+    {
+        return (REG_RD_OFFSET(pDevice, Register));
+    }
+}
+
+/* Mainly used to flush posted write before delaying */
+LM_VOID
+LM_RegRdBack(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register)
+{
+    LM_UINT32 dummy;
+
+#ifdef PCIX_TARGET_WORKAROUND
+    if (pDevice->Flags & ENABLE_PCIX_FIX_FLAG)
+    {
+        return;
+    }
+    else
+#endif
+    {
+        if (pDevice->Flags & REG_RD_BACK_FLAG)
+            return;
+
+        dummy = REG_RD_OFFSET(pDevice, Register);
+    }
+}
+
+LM_VOID
+LM_RegWr(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, LM_UINT32 Value32,
+    LM_UINT32 ReadBack)
+{
+#ifdef PCIX_TARGET_WORKAROUND
+    if (pDevice->Flags & ENABLE_PCIX_FIX_FLAG)
+    {
+        LM_RegWrInd(pDevice, Register, Value32);
+    }
+    else
+#endif
+    {
+        LM_UINT32 dummy;
+
+        REG_WR_OFFSET(pDevice, Register, Value32);
+        if (ReadBack && (pDevice->Flags & REG_RD_BACK_FLAG))
+        {
+            dummy = REG_RD_OFFSET(pDevice, Register);
+        }
+    }
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_RegRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register) {
+    LM_UINT32 Value32;
+
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32);
+    MM_RELEASE_UNDI_LOCK(pDevice);
+
+    return MM_SWAP_LE32(Value32);
+} /* LM_RegRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_RegWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 Register,
+LM_UINT32 Value32) {
+
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+    MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register);
+    MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, MM_SWAP_LE32(Value32));
+    MM_RELEASE_UNDI_LOCK(pDevice);
+} /* LM_RegWrInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+LM_MemRdInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr) {
+    LM_UINT32 Value32;
+
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_ReadConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32);
+    MM_RELEASE_UNDI_LOCK(pDevice);
+
+    return MM_SWAP_LE32(Value32);
+} /* LM_MemRdInd */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_VOID
+LM_MemWrInd(
+PLM_DEVICE_BLOCK pDevice,
+LM_UINT32 MemAddr,
+LM_UINT32 Value32) {
+    MM_ACQUIRE_UNDI_LOCK(pDevice);
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr);
+    MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, MM_SWAP_LE32(Value32));
+    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, Idx;
+    LM_UINT32 Diff = 0;
+
+    Lmstatus = LM_STATUS_SUCCESS;
+
+    if (pDevice->Flags & RX_BD_LIMIT_64_FLAG)
+    {
+        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. */
+                Idx = pDevice->RxJumboProdIdx;
+                pRcvBd = &pDevice->pRxJumboBdVirt[Idx];
+
+                pPacket->u.Rx.RcvRingProdIdx = Idx;
+                pDevice->RxJumboRing[Idx] = pPacket;
+                /* Update the producer index. */
+                pDevice->RxJumboProdIdx = (Idx + 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. */
+                Idx = pDevice->RxStdProdIdx;
+                pRcvBd = &pDevice->pRxStdBdVirt[Idx];
+
+                pPacket->u.Rx.RcvRingProdIdx = Idx;
+                pDevice->RxStdRing[Idx] = pPacket;
+                /* Update the producer index. */
+                pDevice->RxStdProdIdx = (Idx + 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->Flags & RX_BD_LIMIT_64_FLAG) &&
+            ((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->Flags & FLUSH_POSTED_WRITE_FLAG)
+        {
+            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->Flags & FLUSH_POSTED_WRITE_FLAG)
+        {
+            MB_REG_RD(pDevice, Mailbox.RcvJumboProdIdx.Low);
+        }
+    }
+#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */
+
+    return Lmstatus;
+} /* LM_QueueRxPackets */
+
+
+
+
+#define EEPROM_CMD_TIMEOUT  100000
+#define NVRAM_CMD_TIMEOUT   100000
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS LM_NVRAM_AcquireLock( PLM_DEVICE_BLOCK pDevice )
+{
+    LM_UINT         i;
+    LM_UINT32 value32;
+    LM_STATUS  status;
+
+    status = LM_STATUS_SUCCESS;
+
+    /* Request access to the flash interface. */
+    REG_WR( pDevice, Nvram.SwArb, SW_ARB_REQ_SET1 );
+
+    /*
+     * The worst case wait time for Nvram arbitration
+     * using serial eprom is about 45 msec on a 5704
+     * with the other channel loading boot code.
+     */
+    for( i = 0; i < NVRAM_CMD_TIMEOUT; i++ )
+    {
+        value32 = REG_RD( pDevice, Nvram.SwArb );
+        if( value32 & SW_ARB_GNT1 )
+        {
+            break;
+        }
+        MM_Wait(20);
+    }
+
+
+    return status;
+} /* LM_NVRAM_AcquireLock */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS LM_NVRAM_ReleaseLock( PLM_DEVICE_BLOCK pDevice )
+{
+    /* Relinquish nvram interface. */
+    REG_WR( pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1 );
+    REG_RD_BACK( pDevice, Nvram.SwArb );
+
+    return LM_STATUS_SUCCESS;
+} /* LM_NVRAM_ReleaseLock */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_EEPROM_ExecuteCommand( PLM_DEVICE_BLOCK pDevice, LM_UINT32 cmd )
+{
+    LM_UINT32       i;
+    LM_UINT32 value32;
+    LM_STATUS  status;
+
+    status = LM_STATUS_SUCCESS;
+
+    REG_WR( pDevice, Grc.EepromAddr, cmd );
+
+    for( i = 0; i < EEPROM_CMD_TIMEOUT; i++ )
+    {
+        value32 = REG_RD( pDevice, Grc.EepromAddr );
+        if( value32 & SEEPROM_ADDR_COMPLETE )
+        {
+            break;
+        }
+        MM_Wait(20);
+    }
+
+    if( i == EEPROM_CMD_TIMEOUT )
+    {
+        printk( KERN_WARNING "EEPROM command (0x%x) timed out!\n", cmd );
+        status = LM_STATUS_FAILURE;
+    }
+
+    return status;
+} /* LM_EEPROM_ExecuteCommand */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NVRAM_ExecuteCommand( PLM_DEVICE_BLOCK pDevice, LM_UINT32 cmd )
+{
+    LM_UINT32       i;
+    LM_UINT32 value32;
+    LM_STATUS  status;
+
+    status = LM_STATUS_SUCCESS;
+
+    REG_WR( pDevice, Nvram.Cmd, cmd );
+    REG_RD_BACK( pDevice, Nvram.Cmd );
+    MM_Wait(10);
+
+    /* Wait for the command to complete. */
+    for( i = 0; i < NVRAM_CMD_TIMEOUT; i++ )
+    {
+        value32 = REG_RD( pDevice, Nvram.Cmd );
+        if( value32 & NVRAM_CMD_DONE )
+        {
+            break;
+        }
+        MM_Wait(1);
+    }
+
+    if( i == NVRAM_CMD_TIMEOUT )
+    {
+        printk( KERN_WARNING "NVRAM command (0x%x) timed out!\n", cmd );
+        status = LM_STATUS_FAILURE;
+    }
+
+    return status;
+} /* LM_NVRAM_ExecuteCommand */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_EEPROM_Read_UINT32( PLM_DEVICE_BLOCK pDevice, LM_UINT32 offset,
+                                                 LM_UINT32 * data )
+{
+    LM_UINT32 value32;
+    LM_UINT32 Addr;
+    LM_UINT32 Dev;
+    LM_STATUS status;
+
+    Dev  = offset / pDevice->flashinfo.chipsize;
+    Addr = offset % pDevice->flashinfo.chipsize;
+    
+    value32 = REG_RD( pDevice, Grc.EepromAddr );
+    value32 &= ~(SEEPROM_ADDR_DEV_ID_MASK | SEEPROM_ADDR_ADDRESS_MASK  |
+                 SEEPROM_ADDR_RW_MASK);
+    value32 |= SEEPROM_ADDR_DEV_ID(Dev) | SEEPROM_ADDR_ADDRESS(Addr) |
+               SEEPROM_ADDR_START | SEEPROM_ADDR_READ;
+
+    status = LM_EEPROM_ExecuteCommand( pDevice, value32 );
+    if( status == LM_STATUS_SUCCESS )
+    {
+        value32 = REG_RD( pDevice, Grc.EepromData );
+
+        /* The endianess of the eeprom and flash interface is different */
+        *data = MM_SWAP_LE32( value32 );
+    }
+
+    return status;
+} /* LM_EEPROM_Read_UINT32 */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NVRAM_Read_UINT32( PLM_DEVICE_BLOCK pDevice, LM_UINT32 offset,
+                                                LM_UINT32 * data )
+{
+    LM_UINT32 physaddr;
+    LM_UINT32 ctrlreg;
+    LM_UINT32 value32;
+    LM_STATUS status;
+
+    if( pDevice->flashinfo.jedecnum == JEDEC_ATMEL &&
+        pDevice->flashinfo.buffered == TRUE )
+    {
+        /*
+         * One supported flash part has 9 address bits to address a
+         * particular page and another 9 address bits to address a
+         * particular byte within that page.
+         */
+        LM_UINT32 pagenmbr;
+
+        pagenmbr = offset / pDevice->flashinfo.pagesize;
+        pagenmbr = pagenmbr << ATMEL_AT45DB0X1B_PAGE_POS;
+
+        physaddr = pagenmbr + (offset % pDevice->flashinfo.pagesize);
+    }
+    else
+    {
+        physaddr = offset;
+    }
+
+    REG_WR( pDevice, Nvram.Addr, physaddr );
+
+    ctrlreg = NVRAM_CMD_DONE | NVRAM_CMD_DO_IT |
+              NVRAM_CMD_LAST | NVRAM_CMD_FIRST | NVRAM_CMD_RD;
+
+    status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+    if( status == LM_STATUS_SUCCESS )
+    {
+        value32 = REG_RD( pDevice, Nvram.ReadData );
+    
+        /*
+         * Data is swapped so that the byte stream is the same
+         * in big and little endian systems.  Caller will do
+         * additional swapping depending on how it wants to
+         * look at the data.
+         */
+        *data = MM_SWAP_BE32( value32 );
+    }
+
+    return status;
+} /* LM_NVRAM_Read_UINT32 */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NVRAM_ReadBlock( PLM_DEVICE_BLOCK   pDevice, LM_UINT32 offset,
+                    LM_UINT8         *    data, LM_UINT32   size )
+{
+    LM_STATUS status;
+    LM_UINT32 value32;
+    LM_UINT32 bytecnt;
+    LM_UINT8 * srcptr;
+
+    status = LM_STATUS_SUCCESS;
+
+    while( size > 0 )
+    {
+        /* Make sure the read is word aligned. */
+        value32 = offset & 0x3;
+        if( value32 )
+        {
+            bytecnt = sizeof(LM_UINT32) - value32;
+            offset -= value32;
+            srcptr  = (LM_UINT8 *)(&value32) + value32;
+        }
+        else
+        {
+            bytecnt = sizeof(LM_UINT32);
+            srcptr  = (LM_UINT8 *)(&value32);
+        }
+
+        if( bytecnt > size )
+        {
+            bytecnt = size;
+        }
+
+        if( T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 &&
+            T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701 )
+        {
+            status = LM_NVRAM_Read_UINT32( pDevice, offset, &value32 );
+        }
+        else
+        {
+            status = LM_EEPROM_Read_UINT32( pDevice, offset, &value32 );
+        }
+
+        if( status != LM_STATUS_SUCCESS )
+        {
+            break;
+        }
+
+        memcpy( data, srcptr, bytecnt );
+
+        offset += sizeof(LM_UINT32);
+        data   += bytecnt;
+        size   -= bytecnt;
+    }
+
+    return status;
+} /* LM_NVRAM_ReadBlock */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_VOID
+LM_EEPROM_ReadSize( PLM_DEVICE_BLOCK pDevice, LM_UINT32 * size )
+{
+    LM_UINT32 cursize;
+    LM_UINT32 value32;
+    LM_STATUS  status;
+
+    /*
+     * Initialize the chipsize to the largest EEPROM size we support.
+     * This will intentionally restrict our sizing operations to the
+     * first EEPROM chip.
+     */
+    pDevice->flashinfo.chipsize = ATMEL_AT24C512_CHIP_SIZE;
+
+    value32 = 0;
+
+    /* If anything fails, use the smallest chip as the default chip size. */
+    cursize = ATMEL_AT24C64_CHIP_SIZE;
+
+    status = LM_NvramRead(pDevice, 0, &value32);
+    if( status != LM_STATUS_SUCCESS )
+    {
+        goto done;
+    }
+
+    value32 = MM_SWAP_BE32(value32);
+    if( value32 != 0x669955aa )
+    {
+        goto done;
+    }
+
+    /*
+     * Size the chip by reading offsets at increasing powers of two.
+     * When we encounter our validation signature, we know the addressing
+     * has wrapped around, and thus have our chip size.
+     */
+    while( cursize < ATMEL_AT24C64_CHIP_SIZE )
+    {
+        status = LM_NvramRead(pDevice, cursize, &value32);
+        if( status != LM_STATUS_SUCCESS )
+        {
+            cursize = ATMEL_AT24C64_CHIP_SIZE;
+            break;
+        }
+
+        value32 = MM_SWAP_BE32(value32);
+        if( value32 == 0x669955aa )
+        {
+            break;
+        }
+        cursize <<= 1;
+    }
+
+done:
+
+    *size = cursize;
+    pDevice->flashinfo.pagesize = cursize;
+
+
+} /* LM_EEPROM_ReadSize */
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_FLASH_Atmel_Buffered_ReadSize( PLM_DEVICE_BLOCK pDevice, LM_UINT32 * size )
+{
+    LM_UINT32 config3;
+    LM_UINT32 value32;
+    LM_STATUS status;
+
+    /* Temporarily replace the read command with a "read ID" command. */
+    config3 = REG_RD( pDevice, Nvram.Config3 );
+    value32 = config3 & ~NVRAM_READ_COMMAND(NVRAM_COMMAND_MASK);
+    value32 |= NVRAM_READ_COMMAND(0x57);
+    REG_WR( pDevice, Nvram.Config3, value32 );
+
+    REG_WR( pDevice, Nvram.Addr, 0x0 );
+
+    status = LM_NVRAM_Read_UINT32(pDevice, 0x0, &value32);
+
+    /* Restore the original read command. */
+    REG_WR( pDevice, Nvram.Config3, config3 );
+    if( status == LM_STATUS_SUCCESS )
+    {
+        switch( value32 & 0x3c )
+      {
+            case 0x0c:
+                *size = (1 * (1<<20))/8;
+                break;
+            case 0x14:
+                *size = (2 * (1<<20))/8;
+                break;
+            case 0x1c:
+                *size = (4 * (1<<20))/8;
+                break;
+            case 0x24:
+                *size = (8 * (1<<20))/8;
+                break;
+        }
+    }
+
+    return status;
+} /* LM_FLASH_Atmel_Buffered_ReadSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_FLASH_ST_ReadSize( PLM_DEVICE_BLOCK pDevice, LM_UINT32 * size )
+{
+    LM_STATUS status;
+    LM_UINT32       i;
+    LM_UINT32 ctrlreg;
+    LM_UINT32 value32;
+    LM_UINT32 config1;
+
+    /* We need to get the size through pass-thru mode. */
+    config1 = REG_RD( pDevice, Nvram.Config1 );
+    value32 = config1 | FLASH_PASS_THRU_MODE;
+    REG_WR( pDevice, Nvram.Config1, value32 );
+
+    /* Issue the "read ID" command. */
+    REG_WR( pDevice, Nvram.WriteData, 0x9f );
+
+    ctrlreg = NVRAM_CMD_DO_IT | NVRAM_CMD_DONE | NVRAM_CMD_FIRST | NVRAM_CMD_WR;
+    status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+    if( status == LM_STATUS_FAILURE )
+    {
+        goto done;
+    }
+
+    /* Read in the "read ID" response. */
+    ctrlreg = NVRAM_CMD_DO_IT | NVRAM_CMD_DONE;
+
+    /* Discard the first three bytes. */
+    for( i = 0; i < 2; i++ )
+    {
+        status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+        if( status == LM_STATUS_FAILURE )
+        {
+            goto done;
+        }
+
+        value32 = REG_RD(pDevice, Nvram.ReadData);
+    }
+
+    ctrlreg |= NVRAM_CMD_LAST;
+
+    status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+    if( status == LM_STATUS_SUCCESS )
+    {
+        value32 = REG_RD(pDevice, Nvram.ReadData) & 0xff;
+        switch( value32 )
+        {
+            case 0x11:
+                *size = (1 * (1<<20)) / 8;
+                break;
+            case 0x12:
+                *size = (2 * (1<<20)) / 8;
+                break;
+            case 0x13:
+                *size = (4 * (1<<20)) / 8;
+                break;
+            case 0x14:
+                *size = (8 * (1<<20)) / 8;
+                break;
+        }
+    }
+
+done:
+
+    /* Restore the previous flash mode. */
+    REG_WR( pDevice, Nvram.Config1, config1 );
+
+    return status;
+} /* LM_FLASH_ST_ReadSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_FLASH_Saifun_ReadSize( PLM_DEVICE_BLOCK pDevice, LM_UINT32 * size )
+{
+    LM_UINT32 config3;
+    LM_UINT32 value32;
+    LM_STATUS status;
+
+    /* Temporarily replace the read command with a "read ID" command. */
+    config3 = REG_RD( pDevice, Nvram.Config3 );
+    value32 = config3 & ~NVRAM_READ_COMMAND(NVRAM_COMMAND_MASK);
+    value32 |= NVRAM_READ_COMMAND(0xab);
+    REG_WR( pDevice, Nvram.Config3, value32 );
+
+    REG_WR( pDevice, Nvram.Addr, 0x0 );
+
+    status = LM_NVRAM_Read_UINT32(pDevice, 0x0, &value32);
+
+    /* Restore the original read command. */
+    REG_WR( pDevice, Nvram.Config3, config3 );
+
+    if( status == LM_STATUS_SUCCESS )
+    {
+        switch( value32 & 0xff )
+        {
+            case 0x05:
+                *size = (512 * (1<<10)/8);
+                break;
+            case 0x10:
+                *size = (1 * (1<<20)/8);
+                break;
+            case 0x11:
+                *size = (2 * (1<<20)/8);
+                break;
+        }
+    }
+
+    return status;
+} /* LM_FLASH_Saifun_ReadSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_FLASH_ReadSize( PLM_DEVICE_BLOCK pDevice, LM_UINT32 * size )
+{
+    LM_UINT32 value32;
+    LM_STATUS status;
+
+    status = LM_NVRAM_AcquireLock( pDevice );
+    if( status == LM_STATUS_FAILURE )
+    {
+        return status;
+    }
+
+    if(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+    {
+        if( (pDevice->Flags &  PROTECTED_NVRAM_FLAG) == 0)
+        { 
+            value32  = REG_RD( pDevice, Nvram.NvmAccess );
+            value32 |= NVRAM_ACCESS_ENABLE | NVRAM_ACCESS_WRITE_ENABLE;
+            REG_WR( pDevice, Nvram.NvmAccess, value32 );
+        }
+    }
+
+    switch( pDevice->flashinfo.jedecnum )
+    {
+        case JEDEC_ST:
+            status = LM_FLASH_ST_ReadSize( pDevice, size );
+            break;
+        case JEDEC_ATMEL:
+            if( pDevice->flashinfo.buffered == TRUE )
+            {
+                status = LM_FLASH_Atmel_Buffered_ReadSize( pDevice, size );
+            }
+            else
+            {
+                status = LM_STATUS_FAILURE;
+            }
+            break;
+        case JEDEC_SAIFUN:
+            status = LM_FLASH_Saifun_ReadSize( pDevice, size );
+            break;
+        case JEDEC_SST:
+        default:
+            status = LM_STATUS_FAILURE;
+    }
+
+    if(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+    {
+       if( (pDevice->Flags & PROTECTED_NVRAM_FLAG) == 0)
+       { 
+            value32  = REG_RD( pDevice, Nvram.NvmAccess );
+            value32 &= ~(NVRAM_ACCESS_ENABLE | NVRAM_ACCESS_WRITE_ENABLE);
+            REG_WR( pDevice, Nvram.NvmAccess, value32 );
+        }
+    }
+
+    LM_NVRAM_ReleaseLock( pDevice );
+
+    return status;
+} /* LM_FLASH_ReadSize */
+
+STATIC LM_VOID LM_NVRAM_Detect_570X( PLM_DEVICE_BLOCK pDevice )
+{
+    LM_UINT32 value32;
+
+    value32 = REG_RD(pDevice, Nvram.Config1);
+
+    if( (value32 & FLASH_INTERFACE_ENABLE) == 0 )
+    {
+        pDevice->flashinfo.romtype = ROM_TYPE_EEPROM;
+    }
+    else
+    {
+        /*
+         * 5705 and older products do not have bits 24 and 25 defined.
+         * If we've gotten here, then we can guarantee the flash is
+         * an Atmel AT45DB011DB.
+         */
+        pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+        pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+        pDevice->flashinfo.pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
+        pDevice->flashinfo.buffered = TRUE;
+    }
+} /* LM_NVRAM_Detect_570X */
+
+STATIC LM_VOID LM_NVRAM_Detect_5750( PLM_DEVICE_BLOCK pDevice )
+{
+    LM_UINT32 value32;
+
+    value32 = REG_RD(pDevice, Nvram.Config1);
+
+    if( (value32 & FLASH_INTERFACE_ENABLE) == 0 )
+    {
+        pDevice->flashinfo.romtype = ROM_TYPE_EEPROM;
+        return;
+    }
+
+    pDevice->flashinfo.romtype = ROM_TYPE_FLASH;
+
+    switch( value32 & FLASH_PART_5750_TYPEMASK )
+    {
+        case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
+             pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+             pDevice->flashinfo.pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
+             pDevice->flashinfo.buffered = TRUE;
+             break;
+        case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED:
+             pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+             pDevice->flashinfo.pagesize = ATMEL_AT25F512_PAGE_SIZE;
+             pDevice->flashinfo.buffered = FALSE;
+             break;
+        case FLASH_VENDOR_ST:
+             pDevice->flashinfo.jedecnum = JEDEC_ST;
+             pDevice->flashinfo.pagesize = ST_M45PEX0_PAGE_SIZE;
+             pDevice->flashinfo.buffered = TRUE;
+             break;
+        case FLASH_VENDOR_SAIFUN:
+             pDevice->flashinfo.jedecnum = JEDEC_SAIFUN;
+             pDevice->flashinfo.pagesize = SAIFUN_SA25F0XX_PAGE_SIZE;
+             pDevice->flashinfo.buffered = FALSE;
+             break;
+        case FLASH_VENDOR_SST_SMALL:
+        case FLASH_VENDOR_SST_LARGE:
+             pDevice->flashinfo.jedecnum = JEDEC_SST;
+             pDevice->flashinfo.pagesize = SST_25VF0X0_PAGE_SIZE;
+             pDevice->flashinfo.buffered = FALSE;
+             break;
+        default:
+             printk( KERN_ALERT "bcm5700 : Unknown NVRAM type.\n" );
+             pDevice->flashinfo.jedecnum = 0;
+             pDevice->flashinfo.romtype  = 0;
+             pDevice->flashinfo.buffered = FALSE;
+             pDevice->flashinfo.pagesize = 0;
+    }
+} /* LM_NVRAM_Detect_5750 */
+
+STATIC LM_VOID LM_NVRAM_Detect_5752( PLM_DEVICE_BLOCK pDevice )
+{
+    LM_BOOL   supported;
+    LM_UINT32 value32;
+
+    supported = FALSE;
+
+    value32 = REG_RD(pDevice, Nvram.Config1);
+
+    if(value32 & BIT_27)
+        pDevice->Flags |= PROTECTED_NVRAM_FLAG;
+
+    switch( value32 & FLASH_PART_5752_TYPEMASK )
+    {
+        case FLASH_PART_5752_EEPROM_ATMEL_64K:
+             pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+             pDevice->flashinfo.romtype  = ROM_TYPE_EEPROM;
+             pDevice->flashinfo.buffered = FALSE;
+             pDevice->flashinfo.chipsize = (64 * (1<<10)/8);
+             supported = TRUE;
+             break;
+
+        case FLASH_PART_5752_EEPROM_ATMEL_376K:
+             pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+             pDevice->flashinfo.romtype  = ROM_TYPE_EEPROM;
+             pDevice->flashinfo.buffered = FALSE;
+             pDevice->flashinfo.chipsize = (512 * (1<<10)/8);
+             supported = TRUE;
+             break;
+
+        case FLASH_PART_5752_FLASH_ATMEL_AT45DB041:
+             pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+             pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+             pDevice->flashinfo.buffered = TRUE;
+             pDevice->flashinfo.chipsize = (4 * (1<<20)) / 8;
+             supported = TRUE;
+             break;
+
+        case FLASH_PART_5752_FLASH_ATMEL_AT25F512:
+             pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+             pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+             pDevice->flashinfo.buffered = FALSE;
+             pDevice->flashinfo.chipsize = (512 * (1<<10)/8);
+             supported = TRUE;
+             break;
+
+        case FLASH_PART_5752_FLASH_ST_M25P10A:
+             pDevice->flashinfo.jedecnum = JEDEC_ST;
+             pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+             pDevice->flashinfo.buffered = TRUE;
+             pDevice->flashinfo.chipsize = (1 * (1<<20)) / 8;
+             supported = TRUE;
+             break;
+        case FLASH_PART_5752_FLASH_ST_M25P05A:
+             pDevice->flashinfo.jedecnum = JEDEC_ST;
+             pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+             pDevice->flashinfo.buffered = TRUE;
+             pDevice->flashinfo.chipsize = (512 * (1<<10)/8);
+             supported = TRUE;
+             break;
+
+        case FLASH_PART_5752_FLASH_ST_M45PE10:
+             pDevice->flashinfo.jedecnum = JEDEC_ST;
+             pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+             pDevice->flashinfo.buffered = TRUE;
+             pDevice->flashinfo.chipsize = (1 * (1<<20)) / 8;
+             supported = TRUE;
+             break;
+
+        case FLASH_PART_5752_FLASH_ST_M45PE20:
+             pDevice->flashinfo.jedecnum = JEDEC_ST;
+             pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+             pDevice->flashinfo.buffered = TRUE;
+             pDevice->flashinfo.chipsize = (2 * (1<<20)) / 8;
+             supported = TRUE;
+             break;
+
+        case FLASH_PART_5752_FLASH_ST_M45PE40:
+             pDevice->flashinfo.jedecnum = JEDEC_ST;
+             pDevice->flashinfo.romtype  = ROM_TYPE_FLASH;
+             pDevice->flashinfo.buffered = TRUE;
+             pDevice->flashinfo.chipsize = (4 * (1<<20)) / 8;
+             supported = TRUE;
+             break;
+        default:
+             printk( KERN_ALERT "bcm5700 : Unknown NVRAM type.\n" );
+    }
+
+    if( pDevice->flashinfo.romtype == ROM_TYPE_FLASH )
+    {
+        switch( value32 & FLASH_PART_5752_PAGEMASK )
+        {
+            case FLASH_PART_5752_PAGE_SIZE_256B:
+                pDevice->flashinfo.pagesize = 256;
+                break;
+            case FLASH_PART_5752_PAGE_SIZE_512B:
+                pDevice->flashinfo.pagesize = 512;
+                break;
+            case FLASH_PART_5752_PAGE_SIZE_1K:
+                pDevice->flashinfo.pagesize = 1024;
+                break;
+            case FLASH_PART_5752_PAGE_SIZE_2K:
+                pDevice->flashinfo.pagesize = 2048;
+                break;
+            case FLASH_PART_5752_PAGE_SIZE_4K:
+                pDevice->flashinfo.pagesize = 4096;
+                break;
+            case FLASH_PART_5752_PAGE_SIZE_264B:
+                pDevice->flashinfo.pagesize = 264;
+                break;
+            default:
+                printk( KERN_ALERT "bcm5700 : Unknown NVRAM page size.\n" );
+                supported = FALSE;
+        }
+    }
+
+   if( supported != TRUE )
+    {
+        printk( KERN_ALERT "Flash type unsupported!!!\n" );
+        pDevice->flashinfo.jedecnum = 0;
+        pDevice->flashinfo.romtype  = 0;
+        pDevice->flashinfo.buffered = FALSE;
+        pDevice->flashinfo.pagesize = 0;
+    }
+
+
+} /* LM_NVRAM_Detect_5752 */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_VOID LM_NVRAM_Init( PLM_DEVICE_BLOCK pDevice )
+{
+    LM_UINT32 Value32;
+
+    pDevice->NvramSize = 0;
+
+    /* Intialize clock period and state machine. */
+    Value32 = SEEPROM_ADDR_CLK_PERD(SEEPROM_CLOCK_PERIOD) |
+              SEEPROM_ADDR_FSM_RESET;
+    REG_WR(pDevice, Grc.EepromAddr, Value32);
+    REG_RD_BACK(pDevice, Grc.EepromAddr);
+
+    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);
+
+    switch( T3_ASIC_REV(pDevice->ChipRevId) )
+    {
+        case T3_ASIC_REV_5700:
+        case T3_ASIC_REV_5701:
+             pDevice->flashinfo.romtype = ROM_TYPE_EEPROM;
+             break;
+        case T3_ASIC_REV_5752:
+             LM_NVRAM_Detect_5752(pDevice);
+             break;
+        case T3_ASIC_REV_5714_A0:
+        case T3_ASIC_REV_5780:
+        case T3_ASIC_REV_5714:
+        case T3_ASIC_REV_5750:
+             LM_NVRAM_Detect_5750(pDevice);
+             break;
+        default:
+             LM_NVRAM_Detect_570X(pDevice);
+    }
+
+    /* 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 &&
+        pDevice->flashinfo.romtype == ROM_TYPE_EEPROM        )
+    {
+        Value32 = REG_RD(pDevice, Nvram.Config1);
+
+        if( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+        {
+           if( (pDevice->Flags & PROTECTED_NVRAM_FLAG) == 0)
+           { 
+                REG_WR(pDevice, Nvram.NvmAccess,
+                   REG_RD(pDevice, Nvram.NvmAccess) | ACCESS_EN);
+           }
+        }
+
+        /* Use the new interface to read EEPROM. */
+        Value32 &= ~FLASH_COMPAT_BYPASS;
+
+        REG_WR(pDevice, Nvram.Config1, Value32);
+
+        if( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+        {
+            if( (pDevice->Flags & PROTECTED_NVRAM_FLAG) == 0)
+            { 
+                REG_WR(pDevice, Nvram.NvmAccess,
+                       REG_RD(pDevice, Nvram.NvmAccess) & ~ACCESS_EN);
+            }
+        }
+    }
+
+    if( !(T3_ASIC_5752(pDevice->ChipRevId)) )
+    {
+        if( pDevice->flashinfo.romtype == ROM_TYPE_EEPROM )
+        {
+            /* The only EEPROM we support is an ATMEL */
+            pDevice->flashinfo.jedecnum = JEDEC_ATMEL;
+            pDevice->flashinfo.pagesize = 0;
+            pDevice->flashinfo.buffered = FALSE;
+
+            LM_EEPROM_ReadSize( pDevice, &pDevice->flashinfo.chipsize );
+        }
+        else
+        {
+            LM_FLASH_ReadSize( pDevice, &pDevice->flashinfo.chipsize );
+            pDevice->Flags |= FLASH_DETECTED_FLAG;
+        }
+    }
+
+    pDevice->NvramSize  = pDevice->flashinfo.chipsize;
+
+//printk(KERN_ALERT "*nvram:size=0x%x jnum=0x%x page=0x%x buff=0x%x \n",pDevice->NvramSize,pDevice->flashinfo.jedecnum,pDevice->flashinfo.pagesize,pDevice->flashinfo.buffered);
+
+} /* LM_NVRAM_Init */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_NvramRead( PLM_DEVICE_BLOCK pDevice, LM_UINT32 offset, LM_UINT32 * data )
+{
+    LM_UINT32 value32;
+    LM_STATUS status;
+
+    if( offset >= pDevice->flashinfo.chipsize )
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    if( T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 )
+    {
+        status = LM_EEPROM_Read_UINT32( pDevice, offset, data );
+    }
+    else
+    {
+        status = LM_NVRAM_AcquireLock( pDevice );
+        if( status == LM_STATUS_FAILURE )
+        {
+            return status;
+        }
+
+       if(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+       {
+            if( (pDevice->Flags & PROTECTED_NVRAM_FLAG) == 0)
+            { 
+                value32  = REG_RD( pDevice, Nvram.NvmAccess );
+                value32 |= NVRAM_ACCESS_ENABLE;
+                REG_WR( pDevice, Nvram.NvmAccess, value32 );
+            }
+        }
+
+        status = LM_NVRAM_Read_UINT32(pDevice, offset, data);
+
+       if(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+       {
+            if( (pDevice->Flags & PROTECTED_NVRAM_FLAG) == 0)
+            { 
+               value32  = REG_RD( pDevice, Nvram.NvmAccess );
+               value32 &= ~NVRAM_ACCESS_ENABLE;
+               REG_WR( pDevice, Nvram.NvmAccess, value32 );
+            }
+       }
+
+        LM_NVRAM_ReleaseLock( pDevice );
+    }
+
+    return status;
+} /* LM_NvramRead */
+
+
+
+#ifdef ETHTOOL_SEEPROM
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_EEPROM_WriteBlock( PLM_DEVICE_BLOCK   pDevice, LM_UINT32 offset,
+                      LM_UINT8         *    data, LM_UINT32   size )
+{
+    LM_UINT8  * dstptr;
+    LM_UINT32  value32;
+    LM_UINT32  bytecnt;
+    LM_UINT32 subword1;
+    LM_UINT32 subword2;
+    LM_UINT32 Addr;
+    LM_UINT32 Dev;
+    LM_STATUS status;
+
+    if( offset > pDevice->flashinfo.chipsize )
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    status = LM_STATUS_SUCCESS;
+
+    if( size == 0 )
+    {
+        return status;
+    }
+
+    if( offset & 0x3 )
+    {
+        /*
+         * If our initial offset does not fall on a word boundary, we
+         * have to do a read / modify / write to preserve the
+         * preceding bits we are not interested in.
+         */
+        status = LM_EEPROM_Read_UINT32(pDevice, offset & ~0x3, &subword1);
+        if( status == LM_STATUS_FAILURE )
+        {
+            return status;
+        }
+    }
+
+    if( (offset + size) & 0x3 )
+    {
+        /*
+         * Likewise, if our ending offset does not fall on a word
+         * boundary, we have to do a read / modify / write to
+         * preserve the trailing bits we are not interested in.
+         */
+        status = LM_EEPROM_Read_UINT32( pDevice, (offset + size) & ~0x3,
+                                        &subword2 );
+        if( status == LM_STATUS_FAILURE )
+        {
+            return status;
+        }
+    }
+
+    /* Enable EEPROM write. */
+    if( pDevice->Flags & EEPROM_WP_FLAG )
+    {
+        REG_WR( pDevice, Grc.LocalCtrl,
+                pDevice->GrcLocalCtrl | GRC_MISC_LOCAL_CTRL_GPIO_OE1 );
+        REG_RD_BACK( pDevice, Grc.LocalCtrl );
+        MM_Wait(40);
+
+        value32 = REG_RD( pDevice, Grc.LocalCtrl );
+        if( value32 & GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 )
+        {
+            return LM_STATUS_FAILURE;
+        }
+    }
+
+    while( size > 0 )
+    {
+        value32 = offset & 0x3;
+        if( value32 )
+        {
+            /*
+             * We have to read / modify / write the data to
+             * preserve the flash contents preceding the offset.
+             */
+            offset &= ~0x3;
+    
+            dstptr  = ((LM_UINT8 *)(&value32)) + value32;
+            bytecnt = sizeof(LM_UINT32) - value32;
+            value32 = subword1;
+        }
+        else if( size < sizeof(LM_UINT32) )
+        {
+            dstptr  = (LM_UINT8 *)(&value32);
+            bytecnt = size;
+            value32 = subword2;
+        }
+        else
+        {
+            dstptr  = (LM_UINT8 *)(&value32);
+            bytecnt = sizeof(LM_UINT32);
+        }
+
+        if( size < bytecnt )
+        {
+            bytecnt = size;
+        }
+    
+        memcpy( dstptr, (void *)data, bytecnt );
+
+        data += bytecnt;
+        size -= bytecnt;
+
+        /*
+         * Swap the data so that the byte stream will be
+         * written the same in little and big endian systems.
+         */
+        value32 = MM_SWAP_LE32(value32);
+
+        /* Set the write value to the eeprom */    
+        REG_WR( pDevice, Grc.EepromData, value32 );  
+
+        Dev  = offset / pDevice->flashinfo.chipsize;
+        Addr = offset % pDevice->flashinfo.chipsize;
+
+        value32 = REG_RD( pDevice, Grc.EepromAddr );
+        value32 &= ~(SEEPROM_ADDR_DEV_ID_MASK | SEEPROM_ADDR_ADDRESS_MASK |
+                     SEEPROM_ADDR_RW_MASK);
+        value32 |= SEEPROM_ADDR_DEV_ID(Dev) | SEEPROM_ADDR_ADDRESS(Addr) |
+                   SEEPROM_ADDR_START | SEEPROM_ADDR_WRITE;
+
+        status = LM_EEPROM_ExecuteCommand( pDevice, value32 );
+        if( status != LM_STATUS_SUCCESS )
+        {
+            break;
+        }
+
+        offset += sizeof(LM_UINT32);
+    }
+
+    /* Write-protect EEPROM. */
+    if( pDevice->Flags & EEPROM_WP_FLAG )
+    {
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl        |
+                                       GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                                       GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+        REG_RD_BACK(pDevice, Grc.LocalCtrl);
+        MM_Wait(40);
+    }
+
+    return status;
+} /* LM_EEPROM_WriteBlock */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NVRAM_WriteBlockUnBuffered( PLM_DEVICE_BLOCK   pDevice, LM_UINT32 offset,
+                               LM_UINT8         *    data, LM_UINT32   size )
+{
+    LM_UINT          i;
+    LM_STATUS   status;
+    LM_UINT32   tgtoff;
+    LM_UINT32  value32;
+    LM_UINT32  ctrlreg;
+    LM_UINT32 pagesize;
+    LM_UINT32 pagemask;
+    LM_UINT32 physaddr;
+
+    /* Cache the pagesize. */
+    pagesize = pDevice->flashinfo.pagesize;
+
+    if( pDevice->flashinfo.jedecnum == JEDEC_SAIFUN )
+    {
+        /* Config2 = 0x500d8 */
+        /* Config3 = 0x3840253 */
+        /* Write1 = 0xaf000400 */
+
+        /* Configure the erase command to be "page erase". */
+        /* Configure the status command to be "read status register". */
+        value32 = REG_RD( pDevice, Nvram.Config2 );
+        value32 &= ~(NVRAM_STATUS_COMMAND( NVRAM_COMMAND_MASK ) |
+                     NVRAM_ERASE_COMMAND( NVRAM_COMMAND_MASK ));
+        value32 |= NVRAM_STATUS_COMMAND( SAIFUN_SA25F0XX_READ_STATUS_CMD ) |
+                   NVRAM_ERASE_COMMAND( SAIFUN_SA25F0XX_PAGE_ERASE_CMD );
+        REG_WR( pDevice, Nvram.Config2, value32 );
+
+        /* Configure the write command to be "page write". */
+        value32 = REG_RD( pDevice, Nvram.Config3 );
+        value32 &= ~NVRAM_WRITE_UNBUFFERED_COMMAND( NVRAM_COMMAND_MASK );
+        value32 |=  NVRAM_WRITE_UNBUFFERED_COMMAND( SAIFUN_SA25F0XX_PAGE_WRITE_CMD );
+        REG_WR( pDevice, Nvram.Config3, value32 );
+
+        /* Make sure the "write enable" command is correct. */
+        value32  = REG_RD( pDevice, Nvram.Write1 );
+        value32 &= ~NVRAM_WRITE1_WRENA_CMD( NVRAM_COMMAND_MASK );
+        value32 |=  NVRAM_WRITE1_WRENA_CMD( SAIFUN_SA25F0XX_WRENA_CMD );
+        REG_WR( pDevice, Nvram.Write1, value32 );
+
+        pagemask = SAIFUN_SA25F0XX_PAGE_MASK;
+    }
+    else
+    {
+        /* Unsupported flash type */
+        return LM_STATUS_FAILURE;
+    }
+
+    if( size == 0 )
+    {
+        status = LM_STATUS_SUCCESS;
+        goto done;
+    }
+
+    while( size > 0 )
+    {
+        /* Align the offset to a page boundary. */
+        physaddr = offset & ~pagemask;
+
+        status = LM_NVRAM_ReadBlock( pDevice, physaddr,
+                                     pDevice->flashbuffer,
+                                     pagesize );
+        if( status == LM_STATUS_FAILURE )
+        {
+            break;
+        }
+
+        /* Calculate the target index. */
+        tgtoff = offset & pagemask;
+
+        /* Copy the new data into the save buffer. */
+        for( i = tgtoff; i < pagesize && size > 0; i++ )
+        {
+            pDevice->flashbuffer[i] = *data++;
+            size--;
+        }
+
+        /* Move the offset to the next page. */
+        offset = offset + (pagesize - tgtoff);
+
+        /*
+         * The LM_NVRAM_ReadBlock() function releases
+         * the access enable bit.  Reacquire it.
+         */
+         if( (pDevice->Flags & PROTECTED_NVRAM_FLAG) == 0)
+              REG_WR(pDevice, Nvram.NvmAccess, NVRAM_ACCESS_ENABLE);
+             
+
+        /*
+         * Before we can erase the flash page, we need
+         * to issue a special "write enable" command.
+         */
+        ctrlreg = NVRAM_CMD_WRITE_ENABLE | NVRAM_CMD_DO_IT | NVRAM_CMD_DONE;
+
+        status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+        if( status == LM_STATUS_FAILURE )
+        {
+            break;
+        }
+
+        /* Erase the target page */
+        REG_WR(pDevice, Nvram.Addr, physaddr);
+
+        ctrlreg = NVRAM_CMD_DO_IT | NVRAM_CMD_DONE | NVRAM_CMD_WR   |
+                  NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE;
+
+        status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+        if( status == LM_STATUS_FAILURE )
+        {
+            break;
+        }
+
+        /* Issue another write enable to start the write. */
+        ctrlreg = NVRAM_CMD_WRITE_ENABLE | NVRAM_CMD_DO_IT | NVRAM_CMD_DONE;
+
+        status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+        if( status == LM_STATUS_FAILURE )
+        {
+            break;
+        }
+
+        /* Copy the data into our NIC's buffers. */
+        for( i = 0; i < pagesize; i+= 4 )
+        {
+            value32 = *((LM_UINT32 *)(&pDevice->flashbuffer[i]));
+            value32 = MM_SWAP_BE32( value32 );
+
+            /* Write the location we wish to write to. */
+            REG_WR( pDevice, Nvram.Addr, physaddr );
+
+            /* Write the data we wish to write. */
+            REG_WR( pDevice, Nvram.WriteData, value32 );
+
+            ctrlreg = NVRAM_CMD_DO_IT | NVRAM_CMD_DONE | NVRAM_CMD_WR;
+
+            if( i == 0 )
+            {
+                ctrlreg |= NVRAM_CMD_FIRST;
+            }
+            else if( i == (pagesize - 4) )
+            {
+                ctrlreg |= NVRAM_CMD_LAST;
+            }
+
+            status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+            if( status == LM_STATUS_FAILURE )
+            {
+                size = 0;
+                break;
+            }
+
+            physaddr += sizeof(LM_UINT32);
+        }
+    }
+
+    /* Paranoia.  Turn off the "write enable" flag. */
+    ctrlreg = NVRAM_CMD_WRITE_DISABLE | NVRAM_CMD_DO_IT | NVRAM_CMD_DONE;
+
+    status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+
+done:
+
+    return status;
+} /* LM_NVRAM_WriteBlockUnBuffered */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+STATIC LM_STATUS
+LM_NVRAM_WriteBlockBuffered( PLM_DEVICE_BLOCK   pDevice, LM_UINT32 offset,
+                             LM_UINT8         *    data, LM_UINT32   size )
+{
+    LM_STATUS   status;
+    LM_UINT32  value32;
+    LM_UINT32  bytecnt;
+    LM_UINT32  ctrlreg;
+    LM_UINT32  pageoff;
+    LM_UINT32 physaddr;
+    LM_UINT32 subword1;
+    LM_UINT32 subword2;
+    LM_UINT8 * dstptr;
+
+    if(T3_ASIC_5752(pDevice->ChipRevId) && 
+       (pDevice->flashinfo.jedecnum == JEDEC_ST ||
+        pDevice->flashinfo.jedecnum == JEDEC_ATMEL ))
+    {
+       /* Do nothing as the 5752 does will take care of it */
+    }
+    else if( pDevice->flashinfo.jedecnum == JEDEC_ST )
+    {
+        /*
+         * Program our chip to look at bit0 of the NVRAM's status
+         * register when polling the write or erase operation status.
+         */
+        value32  = REG_RD(pDevice, Nvram.Config1);
+        value32 &= ~FLASH_STATUS_BITS_MASK;
+        REG_WR( pDevice, Nvram.Config1, value32 );
+
+        /* Program the "read status" and "page erase" commands. */
+        value32 = NVRAM_STATUS_COMMAND( ST_M45PEX0_READ_STATUS_CMD ) |
+                  NVRAM_ERASE_COMMAND( ST_M45PEX0_PAGE_ERASE_CMD );
+        REG_WR( pDevice, Nvram.Config2, value32 );
+
+        /* Set the write command to be "page program". */
+        value32  = REG_RD(pDevice, Nvram.Config3); /* default = 0x03840a53 */
+        value32 &= ~NVRAM_WRITE_UNBUFFERED_COMMAND( NVRAM_COMMAND_MASK );
+        value32 |=  NVRAM_WRITE_UNBUFFERED_COMMAND( ST_M45PEX0_PAGE_PRGM_CMD );
+        REG_WR( pDevice, Nvram.Config3, value32 );
+
+        /* Set the "write enable" and "write disable" commands. */
+        value32 = NVRAM_WRITE1_WRENA_CMD( ST_M45PEX0_WRENA_CMD ) |
+                  NVRAM_WRITE1_WRDIS_CMD( ST_M45PEX0_WRDIS_CMD );
+        REG_WR( pDevice, Nvram.Write1, value32 );
+    }
+    else if( pDevice->flashinfo.jedecnum == JEDEC_ATMEL )
+    {
+        if( pDevice->flashinfo.romtype == ROM_TYPE_EEPROM )
+        {
+            #if 0
+            Config1 = 0x2008200
+            Config2 = 0x9f0081
+            Config3 = 0xa184a053
+            Write1  = 0xaf000400
+            #endif
+        }
+        else if( pDevice->flashinfo.buffered == TRUE )
+        {
+            /*
+             * Program our chip to look at bit7 of the NVRAM's status
+             * register when polling the write operation status.
+             */
+            value32  = REG_RD(pDevice, Nvram.Config1);
+            value32 |= FLASH_STATUS_BITS_MASK;
+            REG_WR( pDevice, Nvram.Config1, value32 );
+
+            /* Set the write command to be "page program". */
+            value32  = REG_RD(pDevice, Nvram.Config3); /* default = 0x03840a53 */
+            value32 &= ~NVRAM_WRITE_UNBUFFERED_COMMAND( NVRAM_COMMAND_MASK );
+            value32 |=  NVRAM_WRITE_UNBUFFERED_COMMAND( ATMEL_AT45DB0X1B_BUFFER_WRITE_CMD );
+            REG_WR( pDevice, Nvram.Config3, value32 );
+        /* Config1 = 0x2008273 */
+        /* Config2 = 0x00570081 */
+        /* Config3 = 0x68848353 */
+        }
+        else
+        {
+            /* NVRAM type unsupported. */
+            return LM_STATUS_FAILURE;
+        }
+    }
+    else
+    {
+        /* NVRAM type unsupported. */
+        return LM_STATUS_FAILURE;
+    }
+
+    status = LM_STATUS_SUCCESS;
+
+    if( offset & 0x3 )
+    {
+        /*
+         * If our initial offset does not fall on a word boundary, we
+         * have to do a read / modify / write to preserve the
+         * preceding bits we are not interested in.
+         */
+        status = LM_NVRAM_ReadBlock( pDevice, offset & ~0x3,
+                                     (LM_UINT8 *)&subword1,
+                                     sizeof(subword1) );
+        if( status == LM_STATUS_FAILURE )
+        {
+            return status;
+        }
+    }
+
+    if( (offset + size) & 0x3 )
+    {
+        /*
+         * Likewise, if our ending offset does not fall on a word
+         * boundary, we have to do a read / modify / write to
+         * preserve the trailing bits we are not interested in.
+         */
+        status = LM_NVRAM_ReadBlock( pDevice, (offset + size) & ~0x3,
+                                     (LM_UINT8 *)&subword2,
+                                     sizeof(subword2) );
+        if( status == LM_STATUS_FAILURE )
+        {
+            return status;
+        }
+    }
+
+    ctrlreg = NVRAM_CMD_FIRST;
+
+    while( size > 0 )
+    {
+        value32 = offset & 0x3;
+        if( value32 )
+        {
+            /*
+             * We have to read / modify / write the data to
+             * preserve the flash contents preceding the offset.
+             */
+            offset &= ~0x3;
+    
+            dstptr  = ((LM_UINT8 *)(&value32)) + value32;
+            bytecnt = sizeof(LM_UINT32) - value32;
+            value32 = subword1;
+        }
+        else if( size < sizeof(LM_UINT32) )
+        {
+            dstptr  = (LM_UINT8 *)(&value32);
+            bytecnt = size;
+            value32 = subword2;
+        }
+        else
+        {
+            dstptr  = (LM_UINT8 *)(&value32);
+            bytecnt = sizeof(LM_UINT32);
+        }
+
+        if( size < bytecnt )
+        {
+            bytecnt = size;
+        }
+    
+        memcpy( dstptr, (void *)data, bytecnt );
+
+        data += bytecnt;
+        size -= bytecnt;
+
+        /*
+         * Swap the data so that the byte stream will be
+         * written the same in little and big endian systems.
+         */
+        value32 = MM_SWAP_BE32(value32);
+
+        /* Set the desired write data value to the flash. */
+        REG_WR(pDevice, Nvram.WriteData, value32);
+
+        pageoff = offset % pDevice->flashinfo.pagesize;
+
+        /* Set the target address. */
+        if( pDevice->flashinfo.jedecnum == JEDEC_ATMEL &&
+            pDevice->flashinfo.romtype  == ROM_TYPE_FLASH )
+        {
+            /*
+             * If we're dealing with the special ATMEL part, we need to
+             * convert the submitted offset before it can be considered
+             * a physical address.
+             */
+            LM_UINT32 pagenmbr;
+
+            pagenmbr = offset / pDevice->flashinfo.pagesize;
+            pagenmbr = pagenmbr << ATMEL_AT45DB0X1B_PAGE_POS;
+
+            physaddr = pagenmbr + pageoff;
+        }
+        else
+        {
+            physaddr = offset;
+        }
+
+        REG_WR(pDevice, Nvram.Addr, physaddr);
+
+        ctrlreg |= (NVRAM_CMD_DO_IT | NVRAM_CMD_DONE | NVRAM_CMD_WR);
+
+        if( pageoff == 0 )
+        {
+            /* Set CMD_FIRST when we are at the beginning of a page. */
+            ctrlreg |= NVRAM_CMD_FIRST;
+        }
+        else if( pageoff == (pDevice->flashinfo.pagesize - 4) )
+        {
+            /*
+             * Enable the write to the current page
+             * before moving on to the next one.
+             */
+            ctrlreg |= NVRAM_CMD_LAST;
+        }
+
+        if( size == 0 )
+        {
+            ctrlreg |= NVRAM_CMD_LAST;
+        }
+
+        if( pDevice->flashinfo.jedecnum == JEDEC_ST &&
+            ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5750)  ||
+             (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5714)) &&
+             (ctrlreg & NVRAM_CMD_FIRST) )
+        {
+            LM_UINT32 wrencmd;
+
+            REG_WR(pDevice, Nvram.Write1, ST_M45PEX0_WRENA_CMD);
+
+            /* We need to issue a special "write enable" command first. */
+            wrencmd = NVRAM_CMD_WRITE_ENABLE | NVRAM_CMD_DO_IT | NVRAM_CMD_DONE;
+
+            status = LM_NVRAM_ExecuteCommand( pDevice, wrencmd );
+            if( status == LM_STATUS_FAILURE )
+            {
+                return status;
+            }
+        }
+
+        if( pDevice->flashinfo.romtype == ROM_TYPE_EEPROM )
+        {
+            /* We always do complete word writes to eeprom. */
+            ctrlreg |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST);
+        }
+
+        status = LM_NVRAM_ExecuteCommand( pDevice, ctrlreg );
+        if( status == LM_STATUS_FAILURE )
+        {
+            break;
+        }
+
+        offset += sizeof(LM_UINT32);
+        ctrlreg = 0;
+    }
+
+    return status;
+} /* LM_NVRAM_WriteBlockBuffered */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS LM_NVRAM_WriteBlock( PLM_DEVICE_BLOCK   pDevice, LM_UINT32 offset,
+                               LM_UINT8         *    data, LM_UINT32   size )
+{
+    LM_UINT32 value32;
+    LM_STATUS status;
+
+    if( offset > pDevice->flashinfo.chipsize ||
+       (offset + size) > pDevice->flashinfo.chipsize )
+    {
+        return LM_STATUS_FAILURE;
+    }
+
+    if( size == 0 )
+    {
+        return LM_STATUS_SUCCESS;
+    }
+
+    if( T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 )
+    {
+        status = LM_EEPROM_WriteBlock( pDevice, offset, data, size );
+    }
+    else
+    {
+        status = LM_NVRAM_AcquireLock( pDevice ); 
+        if( status == LM_STATUS_FAILURE )
+        {
+            return status;
+        }
+
+        if(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+        {
+            if( (pDevice->Flags &  PROTECTED_NVRAM_FLAG) == 0)
+            { 
+                value32 = REG_RD( pDevice, Nvram.NvmAccess );
+                value32 |= (NVRAM_ACCESS_ENABLE | NVRAM_ACCESS_WRITE_ENABLE);
+                REG_WR( pDevice, Nvram.NvmAccess, value32 );
+            }
+        }
+
+        /* Enable EEPROM write. */
+        if( pDevice->Flags & EEPROM_WP_FLAG )
+        {
+            REG_WR(pDevice, Grc.LocalCtrl,
+                   pDevice->GrcLocalCtrl | GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+            REG_RD_BACK(pDevice, Grc.LocalCtrl);
+            MM_Wait(40);
+
+            value32 = REG_RD(pDevice, Grc.LocalCtrl);
+            if( value32 & GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 )
+            {
+                status = LM_STATUS_FAILURE;
+                goto error;
+            }
+        }
+
+        value32  = REG_RD(pDevice, Grc.Mode);
+        value32 |= GRC_MODE_NVRAM_WRITE_ENABLE;
+        REG_WR(pDevice, Grc.Mode, value32);
+
+        if( pDevice->flashinfo.buffered == TRUE ||
+            pDevice->flashinfo.romtype  == ROM_TYPE_EEPROM )
+        {
+            status = LM_NVRAM_WriteBlockBuffered(pDevice, offset, data, size);
+        }
+        else
+        {
+            status = LM_NVRAM_WriteBlockUnBuffered(pDevice, offset, data, size);
+        }
+
+        value32  = REG_RD(pDevice, Grc.Mode);
+        value32 &= ~GRC_MODE_NVRAM_WRITE_ENABLE;
+        REG_WR(pDevice, Grc.Mode, value32);
+
+        if( pDevice->Flags & EEPROM_WP_FLAG )
+        {
+            REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl        |
+                                           GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                                           GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+            REG_RD_BACK(pDevice, Grc.LocalCtrl);
+            MM_Wait(40);
+        }
+
+error:
+
+        if(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId)) 
+        {
+            if( (pDevice->Flags &  PROTECTED_NVRAM_FLAG) == 0)
+            { 
+                value32 = REG_RD(pDevice, Nvram.NvmAccess);
+                value32 &= ~(NVRAM_ACCESS_ENABLE | NVRAM_ACCESS_WRITE_ENABLE);
+                REG_WR(pDevice, Nvram.NvmAccess, value32);
+            }
+        }
+
+        LM_NVRAM_ReleaseLock( pDevice );
+    }
+
+    return status;
+} /* LM_NVRAM_WriteBlock */
+
+
+LM_STATUS LM_NvramWriteBlock( PLM_DEVICE_BLOCK pDevice, LM_UINT32 offset,
+                              LM_UINT32 * data, LM_UINT32 size )
+{
+    return LM_NVRAM_WriteBlock( pDevice, offset, (LM_UINT8 *)data, size * 4 );
+}
+
+#endif /* ETHTOOL_SEEPROM */
+
+
+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) {
+            printf("VPD read failed\n");
+            return;
+        }
+        *Vpd_dptr = 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;
+    Value32 = MM_SWAP_BE32(Value32);
+    if (Value32 != 0x669955aa)
+        return;
+    if (LM_NvramRead(pDevice, 0xc, &offset) != LM_STATUS_SUCCESS)
+        return;
+
+    offset = MM_SWAP_BE32(offset);
+
+    if( (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701) &&
+        pDevice->flashinfo.jedecnum == JEDEC_ATMEL &&
+        pDevice->flashinfo.buffered == TRUE )
+    {
+            LM_UINT32 highaddr;
+
+            highaddr = offset >> ATMEL_AT45DB0X1B_PAGE_POS;
+            highaddr = highaddr * ATMEL_AT45DB0X1B_PAGE_SIZE;
+
+            offset = highaddr + (offset & ATMEL_AT45DB0X1B_PAGE_MASK);
+    }
+    if (LM_NvramRead(pDevice, offset, &Value32) != LM_STATUS_SUCCESS)
+        return;
+
+    Value32 = MM_SWAP_BE32(Value32);
+       Value32 &= 0xfc000000;
+    if ((Value32 == 0x0c000000) &&
+        (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 = MM_SWAP_BE32(ver_offset);
+        start_addr = MM_SWAP_BE32(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;
+            }
+            memcpy(&(pDevice->BootCodeVer[i]), &Value32, sizeof(Value32));
+        }
+    }
+    else {
+        char c;
+
+        if (LM_NvramRead(pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS)
+            return;
+
+        Value32 = MM_SWAP_BE32(Value32);
+        i = 0;
+        c = ((Value32 & 0xff00) >> 8);
+
+        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 & 0xff;
+        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_ReadIPMICodeVersion(PLM_DEVICE_BLOCK pDevice)
+{
+#ifdef BCM_PROC_FS
+       static char * present = "BRCM ASF present";
+    LM_UINT32 sig1, sig2;
+    LM_UINT32 value32, offset, asf_offset, ver_offset, start_addr;
+    int i;
+
+    if (LM_NvramRead(pDevice, 0x0, &value32) != LM_STATUS_SUCCESS)
+        return;
+    value32 = MM_SWAP_BE32(value32);
+    if (value32 != 0x669955aa)
+        return;
+
+       offset = 0x14 + 4;
+    for (i = 0; i < 8; i++) {
+        if (LM_NvramRead(pDevice, offset, &value32) != LM_STATUS_SUCCESS)
+            return;
+        value32 = MM_SWAP_BE32(value32) & 0xff000000;
+        if (value32 == 0x1000000)
+            break;
+               offset += 12;
+       }
+
+    if (i == 8)
+        return;
+
+    if (LM_NvramRead(pDevice, 0x14 + i * 12, &start_addr) != LM_STATUS_SUCCESS)
+        return;
+
+    start_addr = MM_SWAP_BE32(start_addr);
+
+       if (start_addr == 0xc0034000)
+               start_addr = 0x08000000;
+
+    if (LM_NvramRead(pDevice, 0x14 + i * 12 + 8, &asf_offset) != LM_STATUS_SUCCESS)
+        return;
+
+    asf_offset = MM_SWAP_BE32(asf_offset);
+
+    if (LM_NvramRead(pDevice, asf_offset, &sig1) != LM_STATUS_SUCCESS ||
+        LM_NvramRead(pDevice, asf_offset + 4, &sig2) != LM_STATUS_SUCCESS )
+        return;
+
+       sig1 = MM_SWAP_BE32(sig1);
+
+       if ((sig1 & 0xfc000000) != 0x0c000000 || sig2 != 0 ) {
+        memcpy(pDevice->IPMICodeVer, present, 17);
+        return;
+    }
+
+    if (LM_NvramRead(pDevice, asf_offset + 8, &ver_offset) != LM_STATUS_SUCCESS)
+        return;
+
+       ver_offset = MM_SWAP_BE32(ver_offset);
+
+    ver_offset -= start_addr;
+       ver_offset += asf_offset;
+
+    for (i = 0; i < 16; i += 4) {
+        if (LM_NvramRead(pDevice, ver_offset + i, &value32) != LM_STATUS_SUCCESS)
+            return;
+        memcpy(&(pDevice->IPMICodeVer[i]), &value32, sizeof(value32));
+    }
+#endif
+}
+
+STATIC void
+LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice)
+{
+#ifdef BCM_PROC_FS
+    LM_UINT32 PciState = pDevice->PciState;
+    LM_UINT32 ClockCtrl;
+    char *SpeedStr = "";
+
+    if (pDevice->Flags & PCI_EXPRESS_FLAG)
+    {
+        strcpy(pDevice->BusSpeedStr, "PCI Express");
+        return;
+    }
+    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 ");
+
+        // Theses devices have internal PCI-X buses. The driver
+        // is unable to use the ClockCtrl register to determine the
+        // bus speed, so we just hardcode the bus speed to 133MHz.
+        
+        if ( ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) &&
+              (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)) ||
+             (T3_ASIC_5714_FAMILY(pDevice->ChipRevId)))
+        {
+            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, LedCfg, Ver;
+    LM_STATUS Status;
+    LM_UINT32 EeSigFound;
+    LM_UINT32 EePhyTypeSerdes = 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;
+
+    /* determine if it is PCIE system */
+    if( (Value32 = MM_FindCapability(pDevice, T3_PCIE_CAPABILITY_ID)) != 0)
+    {
+        pDevice->Flags |= PCI_EXPRESS_FLAG;
+    }
+
+    /* 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);
+
+   /* Read bond id for baxter A0 since it has same rev id as hamilton A0*/
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5714_A0) {
+        MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, Value32 | MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS);
+
+        Value32 = LM_RegRdInd(pDevice, 0x6804);
+        Value32 &= GRC_MISC_BD_ID_MASK;
+
+        if((Value32 == 0)||(Value32 == 0x8000)) {
+            pDevice->ChipRevId = T3_CHIP_ID_5752_A0;
+        }else{
+            pDevice->ChipRevId = T3_CHIP_ID_5714_A0;
+        }
+
+       Status = MM_ReadConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32);
+       MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, Value32 & ~ MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS);
+    }
+
+
+    /* 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->Flags &= ~UNDI_FIX_FLAG;
+    }
+#ifndef PCIX_TARGET_WORKAROUND
+    pDevice->Flags &= ~UNDI_FIX_FLAG;
+#endif
+    /* Map the memory base to system address space. */
+    if (!(pDevice->Flags & UNDI_FIX_FLAG))
+    {
+        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_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) ||
+        (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5704_AX))
+    {
+        pDevice->Flags |= TX_4G_WORKAROUND_FLAG;
+    }
+    if ( (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) ||
+        (pDevice->Flags == PCI_EXPRESS_FLAG))
+    {
+        pDevice->Flags |= REG_RD_BACK_FLAG;
+    }
+
+    if(pDevice->ChipRevId==T3_CHIP_ID_5750_A0)
+       return LM_STATUS_UNKNOWN_ADAPTER;
+
+#ifdef PCIX_TARGET_WORKAROUND
+    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->Flags |= ENABLE_PCIX_FIX_FLAG;
+        }
+    }
+    if (pDevice->Flags & UNDI_FIX_FLAG)
+    {
+        pDevice->Flags |= ENABLE_PCIX_FIX_FLAG;
+    }
+#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;
+
+#ifdef PCIX_TARGET_WORKAROUND
+    /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR#
+        are enabled */
+    if (pDevice->Flags & ENABLE_PCIX_FIX_FLAG) {
+        Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE | 
+                    PCI_PARITY_ERROR_ENABLE);
+    }
+    if (pDevice->Flags & UNDI_FIX_FLAG)
+    {
+        Value32 &= ~PCI_MEM_SPACE_ENABLE;
+    }
+
+#endif
+
+    if (pDevice->Flags & ENABLE_MWI_FLAG)
+    {
+        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;
+    }
+
+    /* 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);
+
+    /* Set power state to D0. */
+    LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
+
+    /* Preserve HOST_STACK_UP bit in case ASF firmware is running */
+    Value32 = REG_RD(pDevice, Grc.Mode) & GRC_MODE_HOST_STACK_UP;
+#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);
+        REG_RD_BACK(pDevice, Grc.LocalCtrl);
+    }
+    MM_Wait(40);
+
+    /* Enable memory arbiter*/
+   if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId) )
+    {
+        Value32 = REG_RD(pDevice,MemArbiter.Mode);
+        REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE | Value32);
+    }
+    else
+    {
+        REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+    }
+
+
+    LM_SwitchClocks(pDevice);
+
+    REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0);
+
+    /* Check to see if PXE ran and did not shutdown properly */
+    if ((REG_RD(pDevice, DmaWrite.Mode) & DMA_WRITE_MODE_ENABLE) ||
+        !(REG_RD(pDevice, PciCfg.MiscHostCtrl) & MISC_HOST_CTRL_MASK_PCI_INT))
+    {
+        LM_DisableInterrupt(pDevice);
+        /* assume ASF is enabled */
+        pDevice->AsfFlags = ASF_ENABLED;
+        if (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+        {
+            pDevice->AsfFlags |= ASF_NEW_HANDSHAKE;
+        }
+        LM_ShutdownChip(pDevice, LM_SHUTDOWN_RESET);
+        pDevice->AsfFlags = 0;
+    }
+#ifdef PCIX_TARGET_WORKAROUND
+    MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32);
+    if (!(pDevice->Flags & ENABLE_PCIX_FIX_FLAG) &&
+        ((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->Flags |= ENABLE_PCIX_FIX_FLAG;
+            }
+        }
+    }
+#endif
+
+    LM_NVRAM_Init(pDevice);
+
+    Status = LM_STATUS_FAILURE;
+    /* 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)
+    {
+        int i;
+
+        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;
+
+        /* Check for null MAC address which can happen with older boot code */
+        for (i = 0; i < 6; i++)
+        {
+            if (pDevice->NodeAddress[i] != 0)
+            {
+                Status = LM_STATUS_SUCCESS;
+                break;
+            }
+        }
+    }
+
+    if (Status != LM_STATUS_SUCCESS)
+    {
+        int MacOffset;
+
+        MacOffset = 0x7c;
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704 ||
+           (T3_ASIC_5714_FAMILY(pDevice->ChipRevId)) )
+        {
+            if (REG_RD(pDevice, PciCfg.DualMacCtrl) & T3_DUAL_MAC_ID)
+            {
+                MacOffset = 0xcc;
+            }
+            /* workaround - need to reset nvram if */
+            /* the boot code is not running */
+            if (LM_NVRAM_AcquireLock(pDevice) != LM_STATUS_SUCCESS)
+            {
+                REG_WR(pDevice, Nvram.Cmd, NVRAM_CMD_RESET);
+            }
+            else
+            {
+                LM_NVRAM_ReleaseLock(pDevice);
+            }
+        }
+
+        Status = LM_NvramRead(pDevice, MacOffset, &Value32);
+        if(Status == LM_STATUS_SUCCESS)
+        {
+            LM_UINT8 *c = (LM_UINT8 *) &Value32;
+
+            pDevice->NodeAddress[0] = c[2];
+            pDevice->NodeAddress[1] = c[3];
+
+            Status = LM_NvramRead(pDevice, MacOffset + 4, &Value32);
+
+            c = (LM_UINT8 *) &Value32;
+            pDevice->NodeAddress[2] = c[0];
+            pDevice->NodeAddress[3] = c[1];
+            pDevice->NodeAddress[4] = c[2];
+            pDevice->NodeAddress[5] = c[3];
+        }
+    }
+
+    if(Status != LM_STATUS_SUCCESS)
+    {
+        Value32 = REG_RD(pDevice, MacCtrl.MacAddr[0].High);
+        pDevice->NodeAddress[0] = (Value32 >> 8) & 0xff;
+        pDevice->NodeAddress[1] = Value32 & 0xff;
+        Value32 = REG_RD(pDevice, MacCtrl.MacAddr[0].Low);
+        pDevice->NodeAddress[2] = (Value32 >> 24) & 0xff;
+        pDevice->NodeAddress[3] = (Value32 >> 16) & 0xff;
+        pDevice->NodeAddress[4] = (Value32 >> 8) & 0xff;
+        pDevice->NodeAddress[5] = Value32 & 0xff;
+        printf("WARNING: Cannot get MAC addr from NVRAM, using %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+            pDevice->NodeAddress[0], pDevice->NodeAddress[1],
+            pDevice->NodeAddress[2], pDevice->NodeAddress[3],
+            pDevice->NodeAddress[4], pDevice->NodeAddress[5]);
+    }
+
+    memcpy(pDevice->PermanentNodeAddress, pDevice->NodeAddress, 6);
+
+    /* Initialize the default values. */
+    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->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->PhyFlags = 0;
+
+    if (!(pDevice->Flags & PCI_EXPRESS_FLAG))
+        pDevice->Flags |= DELAY_PCI_GRANT_FLAG;
+
+    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;
+#ifdef INCLUDE_TBI_SUPPORT
+    pDevice->TbiFlags = 0;
+    pDevice->IgnoreTbiLinkChange = FALSE;
+#endif
+#ifdef 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) ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705))
+    {
+        pDevice->PhyFlags |= PHY_RESET_ON_LINKDOWN;
+        pDevice->PhyFlags |= PHY_CHECK_TAPS_AFTER_RESET;
+    }
+    if ((T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5703_AX) ||
+        (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5704_AX))
+    {
+        pDevice->PhyFlags |= PHY_ADC_FIX;
+    }
+    if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
+    {
+        pDevice->PhyFlags |= PHY_5704_A0_FIX;
+    }
+    if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        pDevice->PhyFlags |= PHY_5705_5750_FIX;
+    }
+    /* Ethernet@Wirespeed is supported on 5701,5702,5703,5704,5705a0,5705a1 */
+    if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+        !((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) &&
+        (pDevice->ChipRevId != T3_CHIP_ID_5705_A0) &&
+        (pDevice->ChipRevId != T3_CHIP_ID_5705_A1)))
+    {
+        pDevice->PhyFlags |= PHY_ETHERNET_WIRESPEED;
+    }
+
+    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;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+
+    if(T3_ASIC_IS_JUMBO_CAPABLE(pDevice->ChipRevId)){
+        if( ! T3_ASIC_5714_FAMILY(pDevice->ChipRevId))
+            pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+       pDevice->Flags |= JUMBO_CAPABLE_FLAG;
+    }
+
+#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->PhyFlags |= PHY_NO_GIGABIT;
+        }
+    }
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)
+    {
+        if ((pDevice->BondId == GRC_MISC_BD_ID_5788) ||
+            (pDevice->BondId == GRC_MISC_BD_ID_5788M))
+        {
+            pDevice->Flags |= BCM5788_FLAG;
+        }
+
+        if ((pDevice->PciDeviceId == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM5901)) ||
+            (pDevice->PciDeviceId == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM5901A2)) ||
+            (pDevice->PciDeviceId == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM5705F)))
+        {
+            pDevice->PhyFlags |= PHY_NO_GIGABIT;
+        }
+    }
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5750)
+    {
+        if ( (pDevice->PciDeviceId == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM5751F))||
+               (pDevice->PciDeviceId == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM5753F)))
+       {
+            pDevice->PhyFlags |= PHY_NO_GIGABIT;
+        }
+    }
+
+    /* CIOBE multisplit has a bug */
+#if 0
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) &&
+        (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE))
+    {
+        pDevice->Flags |= MULTI_SPLIT_ENABLE_FLAG;
+        pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ;
+    }
+#endif
+
+    /* 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);
+
+         /* For now the 5753 cannot drive gpio2 or ASF will blow */
+        if(Value32 & T3_NIC_GPIO2_NOT_AVAILABLE)
+        {
+                   pDevice->Flags |= GPIO2_DONOT_OUTPUT;
+        }
+
+        if (Value32 & T3_NIC_MINI_PCI)
+        {
+            pDevice->Flags |= MINI_PCI_FLAG;
+        }
+        /* 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;
+        }
+
+        if ( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+        {
+            LedCfg = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR2);
+            LedCfg = LedCfg & (T3_NIC_CFG_LED_MODE_MASK |
+                T3_SHASTA_EXT_LED_MODE_MASK);
+        }
+        else
+        {
+            /* Determine PHY led mode. for legacy devices */
+            LedCfg = Value32 & T3_NIC_CFG_LED_MODE_MASK;
+        }
+
+        switch (LedCfg)
+        {
+            default:
+            case T3_NIC_CFG_LED_PHY_MODE_1:
+                pDevice->LedCtrl = LED_CTRL_PHY_MODE_1;
+                break;
+
+            case T3_NIC_CFG_LED_PHY_MODE_2:
+                pDevice->LedCtrl = LED_CTRL_PHY_MODE_2;
+                break;
+
+            case T3_NIC_CFG_LED_MAC_MODE:
+                pDevice->LedCtrl = LED_CTRL_MAC_MODE;
+                break;
+
+           case T3_SHASTA_EXT_LED_SHARED_TRAFFIC_LINK_MODE:
+                pDevice->LedCtrl = LED_CTRL_SHARED_TRAFFIC_LINK;
+                if ((pDevice->ChipRevId != T3_CHIP_ID_5750_A0) &&
+                    (pDevice->ChipRevId != T3_CHIP_ID_5750_A1))
+                {
+                    pDevice->LedCtrl |= LED_CTRL_PHY_MODE_1 |
+                        LED_CTRL_PHY_MODE_2;
+               }
+                break;
+
+           case T3_SHASTA_EXT_LED_MAC_MODE:
+                pDevice->LedCtrl = LED_CTRL_SHASTA_MAC_MODE;
+                break;
+
+            case T3_SHASTA_EXT_LED_WIRELESS_COMBO_MODE:
+                pDevice->LedCtrl = LED_CTRL_WIRELESS_COMBO;
+                if (pDevice->ChipRevId != T3_CHIP_ID_5750_A0)
+                {
+                    pDevice->LedCtrl |= LED_CTRL_PHY_MODE_1 |
+                        LED_CTRL_PHY_MODE_2;
+                }
+                break;
+
+        }
+
+        if (((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+            T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)) &&
+            (pDevice->SubsystemVendorId == T3_SVID_DELL))
+        {
+            pDevice->LedCtrl = LED_CTRL_PHY_MODE_2;
+        }
+
+        if((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) ||
+            (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) ||
+            (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) )
+        {
+            /* Enable EEPROM write protection. */
+            if(Value32 & T3_NIC_EEPROM_WP)
+            {
+                pDevice->Flags |= EEPROM_WP_FLAG;
+            }
+        }
+        pDevice->AsfFlags = 0;
+#ifdef BCM_ASF
+        if (Value32 & T3_NIC_CFG_ENABLE_ASF)
+        {
+            pDevice->AsfFlags |= ASF_ENABLED;
+            if (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+            {
+                pDevice->AsfFlags |= ASF_NEW_HANDSHAKE;
+           }
+        }
+#endif
+        if (Value32 & T3_NIC_FIBER_WOL_CAPABLE)
+        {
+            pDevice->Flags |= FIBER_WOL_CAPABLE_FLAG;
+        }
+        if (Value32 & T3_NIC_WOL_LIMIT_10)
+        {
+            pDevice->Flags |= WOL_LIMIT_10MBPS_FLAG;
+        }
+
+        /* 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;
+            if (!EePhyTypeSerdes && !(pDevice->AsfFlags & ASF_ENABLED))
+            {
+                /* reset PHY if boot code couldn't read the PHY ID */
+                LM_ResetPhy(pDevice);
+            }
+        }
+
+        Ver = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_VER);
+        Ver >>= T3_NIC_DATA_VER_SHIFT;
+
+       Value32 = 0;
+        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_5703) &&
+           (Ver > 0) && (Ver < 0x100)){
+
+          Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR2);
+
+           if (Value32 & T3_NIC_CFG_CAPACITIVE_COUPLING)
+           {
+               pDevice->PhyFlags |= PHY_CAPACITIVE_COUPLING;
+           }
+
+           if (Value32 & T3_NIC_CFG_PRESERVE_PREEMPHASIS)
+           {
+               pDevice->TbiFlags |= TBI_DO_PREEMPHASIS;
+           }
+
+        }
+
+    }
+    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);
+    REG_RD_BACK(pDevice, MacCtrl.MiMode);
+    MM_Wait(80);
+
+    if (pDevice->AsfFlags & ASF_ENABLED)
+    {
+        /* Reading PHY registers will contend with ASF */
+        pDevice->PhyId = 0;
+    }
+    else
+    {
+        /* Get the PHY id. */
+        LM_GetPhyId(pDevice);
+    }
+
+    /* 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:
+        case PHY_BCM5750_PHY_ID:
+           break;
+        case PHY_BCM5714_PHY_ID:
+        case PHY_BCM5780_PHY_ID:
+           if(EePhyTypeSerdes == TRUE)
+           {
+               pDevice->PhyFlags |= PHY_IS_FIBER;  
+           }
+           break;
+        case PHY_BCM5752_PHY_ID:
+           break;
+
+        case PHY_BCM8002_PHY_ID:
+            pDevice->TbiFlags |= ENABLE_TBI_FLAG;
+            break;
+
+        default:
+
+            if (EeSigFound)
+            {
+                pDevice->PhyId = EePhyId;
+                
+                if (EePhyTypeSerdes && ((pDevice->PhyId == PHY_BCM5780_PHY_ID)) )
+                {
+                    pDevice->PhyFlags |= PHY_IS_FIBER;
+                }
+                else if (EePhyTypeSerdes)
+                {
+                    pDevice->TbiFlags |= ENABLE_TBI_FLAG;
+                }
+            }
+            else if ((pAdapterInfo = LM_GetAdapterInfoBySsid(
+                pDevice->SubsystemVendorId,
+                pDevice->SubsystemId)))
+            {
+                pDevice->PhyId = pAdapterInfo->PhyId;
+                if (pAdapterInfo->Serdes)
+                {
+                    pDevice->TbiFlags |= ENABLE_TBI_FLAG;
+                }
+            }
+            else
+           {
+                if (UNKNOWN_PHY_ID(pDevice->PhyId))
+                {
+                    LM_ResetPhy(pDevice);
+                    LM_GetPhyId(pDevice);
+                }
+            }
+            break;
+    }
+
+    if(UNKNOWN_PHY_ID(pDevice->PhyId) && 
+        !(pDevice->TbiFlags & ENABLE_TBI_FLAG))
+    {
+        pDevice->TbiFlags |= ENABLE_TBI_FLAG;
+        printf("PHY ID unknown, assume it is SerDes\n");
+    }
+
+    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;
+
+    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);
+    }
+
+#ifdef 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->AsfFlags & ASF_ENABLED)
+    {
+        if (!T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+        {
+                   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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        pDevice->Flags &= ~NIC_SEND_BD_FLAG;
+    }
+
+    /* Save the current phy link status. */
+    if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+        !(pDevice->AsfFlags & ASF_ENABLED))
+    {
+        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->PhyFlags & PHY_RESET_ON_INIT))
+        {
+
+            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);
+
+                if(!(pDevice->PhyFlags & PHY_NO_GIGABIT))
+                       Value32 = BCM540X_AN_AD_ALL_1G_SPEEDS ;
+               else
+                       Value32 =0;
+
+#ifdef 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);
+
+                LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE |
+                    PHY_CTRL_RESTART_AUTO_NEG);
+            }
+
+        }
+        LM_SetEthWireSpeed(pDevice);
+
+        LM_ReadPhy(pDevice, PHY_AN_AD_REG, &pDevice->advertising);
+        LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG,
+            &pDevice->advertising1000);
+
+    }
+    /* Currently 5401 phy only */
+    LM_PhyTapPowerMgmt(pDevice);
+
+#ifdef INCLUDE_TBI_SUPPORT
+    if(pDevice->TbiFlags & ENABLE_TBI_FLAG)
+    {
+        if (!(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG))
+        {
+            pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
+        }
+        pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY;
+        if (pDevice->TbiFlags & TBI_PURE_POLLING_FLAG)
+        {
+            pDevice->IgnoreTbiLinkChange = TRUE;
+        }
+    }
+    else
+    {
+        pDevice->TbiFlags = 0;
+    }
+
+#endif /* INCLUDE_TBI_SUPPORT */
+
+    /* UseTaggedStatus is only valid for 5701 and later. */
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) ||
+        ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) &&
+        ((pDevice->BondId == GRC_MISC_BD_ID_5788) ||
+        (pDevice->BondId == GRC_MISC_BD_ID_5788M))))
+    {
+        pDevice->Flags &= ~USE_TAGGED_STATUS_FLAG;
+        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->Flags & USE_TAGGED_STATUS_FLAG)
+    {
+        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;
+    }
+
+    if (!EeSigFound)
+    {
+        pDevice->LedCtrl = LED_CTRL_PHY_MODE_1;
+    }
+
+    if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701)
+    {
+        /* 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 &&
+#ifdef INCLUDE_TBI_SUPPORT
+            !(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+#endif
+            pDevice->LedCtrl == LED_CTRL_PHY_MODE_2)
+        {
+            pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT;
+            pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG;
+        }
+        if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+        {
+            pDevice->LedCtrl = LED_CTRL_PHY_MODE_1;
+        }
+    }
+
+#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->Flags & WOL_LIMIT_10MBPS_FLAG)
+        {
+            pDevice->WolSpeed = WOL_SPEED_10MB;
+        }
+       else
+        {
+            pDevice->WolSpeed = WOL_SPEED_100MB;
+        }
+    }
+#endif
+
+    pDevice->PciState = REG_RD(pDevice, PciCfg.PciState);
+
+    pDevice->DmaReadFifoSize = 0;
+    if (((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) &&
+        (pDevice->ChipRevId != T3_CHIP_ID_5705_A0)) ||
+        T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) )
+    {
+#ifdef INCLUDE_TCP_SEG_SUPPORT
+        if ((pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION) &&
+            ((pDevice->ChipRevId == T3_CHIP_ID_5705_A1) ||
+            (pDevice->ChipRevId == T3_CHIP_ID_5705_A2)))
+        {
+            pDevice->DmaReadFifoSize = DMA_READ_MODE_FIFO_SIZE_128;
+        }
+        else
+#endif
+        {
+            if (!(pDevice->PciState & T3_PCI_STATE_HIGH_BUS_SPEED) &&
+                !(pDevice->Flags & BCM5788_FLAG) &&
+                !(pDevice->Flags & PCI_EXPRESS_FLAG))
+            {
+                pDevice->DmaReadFifoSize = DMA_READ_MODE_FIFO_LONG_BURST;
+                if (pDevice->ChipRevId == T3_CHIP_ID_5705_A1)
+                {
+                    pDevice->Flags |= RX_BD_LIMIT_64_FLAG;
+                }
+                pDevice->Flags |= DMA_WR_MODE_RX_ACCELERATE_FLAG;
+            }
+           else if (pDevice->Flags & PCI_EXPRESS_FLAG)
+            {
+                pDevice->DmaReadFifoSize = DMA_READ_MODE_FIFO_LONG_BURST;
+            }
+        }
+    }
+
+    pDevice->Flags &= ~T3_HAS_TWO_CPUS;
+    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_5703 ||
+        T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+    {
+        pDevice->Flags |= T3_HAS_TWO_CPUS;
+    }
+
+    LM_ReadVPD(pDevice);
+    LM_ReadBootCodeVersion(pDevice);
+    LM_ReadIPMICodeVersion(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 },
+
+        { 0x1014, 0x0281, 0, 1 },
+    };
+    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;
+    LM_UINT32 DmaWrCmd, DmaRdCmd, DmaWrBdry, DmaRdBdry;
+
+    MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32);
+    j = 0;
+    while (((Value32 & 0x3ff) != (pDevice->PciCommandStatusWords & 0x3ff)) &&
+        (j < 1000))
+    {
+        /* On PCIE devices, there are some rare cases where the device */
+        /* is in the process of link-training at this point */
+        MM_Wait(200);
+        MM_WriteConfig32(pDevice, PCI_COMMAND_REG, pDevice->PciCommandStatusWords);
+        MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32);
+        j++;
+    }
+    MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl);
+    /* 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->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT);
+
+    if(T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId) )
+    {
+        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->Flags & NIC_SEND_BD_FLAG))
+    {
+        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;
+    }
+
+    DmaWrCmd = DMA_CTRL_WRITE_CMD;
+    DmaRdCmd = DMA_CTRL_READ_CMD;
+    DmaWrBdry = DMA_CTRL_WRITE_BOUNDARY_DISABLE;
+    DmaRdBdry = DMA_CTRL_READ_BOUNDARY_DISABLE;
+#ifdef BCM_DISCONNECT_AT_CACHELINE
+    /* This code is intended for PPC64 and other similar architectures */
+    /* Only the following chips support this */
+    if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) ||
+        (pDevice->Flags & PCI_EXPRESS_FLAG))
+    {
+        switch(pDevice->CacheLineSize * 4)
+        {
+            case 16:
+            case 32:
+            case 64:
+            case 128:
+                if (!(pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) &&
+                    !(pDevice->Flags & PCI_EXPRESS_FLAG))
+                {
+                    /* PCI-X */
+                    /* use 384 which is a multiple of 16,32,64,128 */
+                    DmaWrBdry = DMA_CTRL_WRITE_BOUNDARY_384_PCIX;
+                    break;
+                }
+                else if (pDevice->Flags & PCI_EXPRESS_FLAG)
+                {
+                    /* PCI Express */
+                    /* use 128 which is a multiple of 16,32,64,128 */
+                    DmaWrCmd = DMA_CTRL_WRITE_BOUNDARY_128_PCIE;
+                    break;
+                }
+                /* fall through */
+            case 256:
+                /* use 256 which is a multiple of 16,32,64,128,256 */
+                if ((pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) &&
+                    !(pDevice->Flags & PCI_EXPRESS_FLAG))
+                {
+                    /* PCI */
+                    DmaWrBdry = DMA_CTRL_WRITE_BOUNDARY_256;
+                }
+                else if (!(pDevice->Flags & PCI_EXPRESS_FLAG))
+                {
+                    /* PCI-X */
+                    DmaWrBdry = DMA_CTRL_WRITE_BOUNDARY_256_PCIX;
+                }
+                break;
+        }
+    }
+#endif
+    pDevice->DmaReadWriteCtrl = DmaWrCmd | DmaRdCmd | DmaWrBdry | DmaRdBdry;
+    /* Program DMA Read/Write */
+    if (pDevice->Flags & PCI_EXPRESS_FLAG)
+    {
+       
+       /* !=0 is 256 max or greater payload size so set water mark accordingly*/
+        Value32 = (REG_RD(pDevice, PciCfg.DeviceCtrl) & MAX_PAYLOAD_SIZE_MASK);
+       if (Value32)
+       {
+               pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_PCIE_H20MARK_256;
+       }else
+       {
+               pDevice->DmaReadWriteCtrl |=  DMA_CTRL_WRITE_PCIE_H20MARK_128;
+       }
+
+    }
+    else if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS)
+    {
+        if(T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+        {
+            pDevice->DmaReadWriteCtrl |= 0x003f0000;
+        }
+        else
+        {
+            pDevice->DmaReadWriteCtrl |= 0x003f000f;    
+        }
+    }
+    else /* pci-x */
+    {
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+        {
+               pDevice->DmaReadWriteCtrl |= 0x009f0000;
+        }
+       
+       if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)
+        {
+               pDevice->DmaReadWriteCtrl |= 0x009C0000;
+        }
+       
+        if( T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704 ||
+           T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703 )
+        {
+            Value32 = REG_RD(pDevice, PciCfg.ClockCtrl) & 0x1f;
+            if ((Value32 == 0x6) || (Value32 == 0x7))
+            {
+                pDevice->Flags |= ONE_DMA_AT_ONCE_FLAG;
+            }
+        }
+        else if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId) )
+        {
+            pDevice->DmaReadWriteCtrl &= ~DMA_CTRL_WRITE_ONE_DMA_AT_ONCE;
+            if( T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5780)
+                pDevice->DmaReadWriteCtrl |= (BIT_20 | BIT_18 | DMA_CTRL_WRITE_ONE_DMA_AT_ONCE);
+            else 
+                pDevice->DmaReadWriteCtrl |= (BIT_20 | BIT_18 | BIT_15);
+            /* bit 15 is the current  CQ 13140 Fix */
+        }
+        else
+        {
+            pDevice->DmaReadWriteCtrl |= 0x001b000f;    
+        }
+    }
+    if((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704))
+    {
+        pDevice->DmaReadWriteCtrl &= 0xfffffff0;
+    }
+
+    if (pDevice->Flags & ONE_DMA_AT_ONCE_FLAG)
+    {
+        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->Flags & NIC_SEND_BD_FLAG))
+    {
+        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. */
+        if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
+            (pDevice->RxJumboBufferSize) )
+        {
+            pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize;
+        }else{
+            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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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->AsfFlags & ASF_ENABLED)
+    {
+        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;
+
+    LM_WritePreResetSignatures(pDevice, LM_INIT_RESET);
+    /* Disable transmit and receive DMA engines.  Abort all pending requests. */
+    if(pDevice->InitDone)
+    {
+        LM_Abort(pDevice);
+    }
+
+    pDevice->ShuttingDown = FALSE;
+
+    LM_ResetChip(pDevice);
+
+    LM_WriteLegacySignatures(pDevice, LM_INIT_RESET);
+
+    /* Bug: Athlon fix for B3 silicon only.  This bit does not do anything */
+    /* in other chip revisions except 5750 */
+    if ((pDevice->Flags & DELAY_PCI_GRANT_FLAG) && 
+        !(pDevice->Flags & PCI_EXPRESS_FLAG))
+    {
+        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);
+        }
+    }
+    if (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5704_BX)
+    {
+        /* New bits defined in register 0x64 to enable some h/w fixes */
+        /* These new bits are 'write-only' */
+        Value32 = REG_RD(pDevice, PciCfg.MsiData);
+        REG_WR(pDevice, PciCfg.MsiData, Value32 | BIT_26 | BIT_28 | BIT_29);
+    }
+
+    /* Enable TaggedStatus mode. */
+    if (pDevice->Flags & USE_TAGGED_STATUS_FLAG)
+    {
+        pDevice->MiscHostCtrl |= MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE;
+    }
+
+    /* Restore PCI configuration registers. */
+    MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG,
+        pDevice->SavedCacheLineReg);
+    MM_WriteConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, 
+        (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId);
+
+    /* 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;
+       pDevice->pRxStdBdVirt[k].Flags = RCV_BD_FLAG_END;
+       if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId)  &&
+          (pDevice->RxJumboBufferSize) )
+          pDevice->pRxStdBdVirt[k].Len = pDevice->RxJumboBufferSize;
+       else
+           pDevice->pRxStdBdVirt[k].Len = MAX_STD_RCV_BUFFER_SIZE;
+    }       
+
+#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;
+        pDevice->pRxJumboBdVirt[k].Flags = RCV_BD_FLAG_END |
+            RCV_BD_FLAG_JUMBO_RING;
+        pDevice->pRxJumboBdVirt[k].Len = (LM_UINT16) pDevice->RxJumboBufferSize;
+    }
+#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->Flags & NIC_SEND_BD_FLAG))
+    {
+        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->Flags & NO_TX_PSEUDO_HDR_CSUM_FLAG)
+    {
+        Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    if (pDevice->Flags & NO_RX_PSEUDO_HDR_CSUM_FLAG)
+    {
+        Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM;
+    }
+
+    pDevice->GrcMode = Value32;
+    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)
+    {
+#ifdef 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 if (!T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+   {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+        {
+            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 if( T3_ASIC_5714_FAMILY(pDevice->ChipRevId)){
+
+        REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark,0);
+        REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark,0x4b);
+        REG_WR(pDevice, BufMgr.MbufHighWaterMark,0x96);
+    }
+    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;
+    }
+
+/* GRC reset will reset FTQ */
+#if 0
+    /* 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;
+    }
+#endif
+
+    /* 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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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_RD(pDevice, Mailbox.SendHostProdIdx[0].Low); 
+    MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, 0);
+    MB_REG_RD(pDevice, Mailbox.SendNicProdIdx[0].Low); 
+
+    /* Set up host or NIC based send RCB. */
+    if (!(pDevice->Flags & NIC_SEND_BD_FLAG))
+    {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+        {
+            /* 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_RD(pDevice, Mailbox.RcvStdProdIdx.Low);
+    MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low, 0);
+    MB_REG_RD(pDevice, Mailbox.RcvJumboProdIdx.Low);
+    MB_REG_WR(pDevice, Mailbox.RcvMiniProdIdx.Low, 0);
+    MB_REG_RD(pDevice, Mailbox.RcvMiniProdIdx.Low);
+
+#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 */
+    if ((pDevice->DmaReadFifoSize == DMA_READ_MODE_FIFO_LONG_BURST) &&
+        (pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION))
+    {
+        Value32 = REG_RD(pDevice, RcvListPlmt.StatsEnableMask);
+        Value32 &= ~T3_DISABLE_LONG_BURST_READ_DYN_FIX;
+        REG_WR(pDevice, RcvListPlmt.StatsEnableMask, Value32);
+    }
+    else
+    {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        /* Enable the Receive List Selector state machine. */
+        REG_WR(pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE |
+            RCV_LIST_SEL_MODE_ATTN_ENABLE);
+    }
+
+    /* Reset the Rx MAC State Machine.
+     *
+     * The Rx MAC State Machine must be reset when using fiber to prevent the
+     * first packet being lost. This is needed primarily so that the loopback
+     * test (which currently only sends one packet) doesn't fail.
+     *
+     * Also note that the Rx MAC State Machine (0x468) should be reset _before_
+     * writting to the MAC Mode register (0x400). Failures have been seen on
+     * 5780/5714's using fiber where they stopped receiving packets in a simple
+     * ping test when the Rx MAC State Machine was reset _after_ the MAC Mode
+     * register was set.
+     */
+
+    if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) ||
+        (pDevice->PhyFlags & PHY_IS_FIBER))
+    {
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_RESET);
+        REG_RD_BACK(pDevice, MacCtrl.RxMode);
+        MM_Wait(10);
+        REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode);
+        REG_RD_BACK(pDevice, MacCtrl.RxMode);
+    }
+
+    /* Clear the statistics block. */
+    for(j = 0x0300; j < 0x0b00; j = j + 4)
+    {
+        MEM_WR_OFFSET(pDevice, j, 0);
+    }
+
+    /* Set Mac Mode */
+    if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+    {
+        pDevice->MacMode = MAC_MODE_PORT_MODE_TBI;
+    }
+    else if(pDevice->PhyFlags & PHY_IS_FIBER)
+    {
+         pDevice->MacMode = MAC_MODE_PORT_MODE_GMII;
+    }
+    else
+    {
+        pDevice->MacMode = 0;
+    }
+
+    /* 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;
+    }
+    else if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) &&
+        !(pDevice->Flags & EEPROM_WP_FLAG))
+    {
+        /* Make sure we're on Vmain */
+        /* The other port may cause us to be on Vaux */
+        pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE2 |
+            GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2;
+    }
+
+    RAW_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);
+    MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
+    pDevice->LastTag = 0;
+
+    if(!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        /* 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 (pDevice->Flags & DMA_WR_MODE_RX_ACCELERATE_FLAG)
+    {
+        Value32 |= DMA_WRITE_MODE_RECEIVE_ACCELERATE;
+    }
+
+    if (pDevice->Flags & HOST_COALESCING_BUG_FIX)
+    {
+        Value32 |= (1 << 29);
+    }
+
+    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->Flags & MULTI_SPLIT_ENABLE_FLAG)
+            {
+                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->Flags & MULTI_SPLIT_ENABLE_FLAG)
+    {
+        Value32 |= DMA_READ_MODE_MULTI_SPLIT_ENABLE;
+    }
+
+    if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        Value32 |= pDevice->DmaReadFifoSize;
+    }
+#ifdef INCLUDE_TCP_SEG_SUPPORT
+    if (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+    {
+        Value32 |= BIT_27;
+    }
+#endif
+
+
+    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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        /* 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);
+
+#ifdef INCLUDE_TCP_SEG_SUPPORT
+    if (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+    {
+        REG_WR(pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE | 0x8);
+    }
+#endif
+
+    /* 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);
+
+#ifdef 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);
+
+    REG_WR(pDevice, MacCtrl.LedCtrl, pDevice->LedCtrl);
+    
+    /* Activate Link to enable MAC state machine */
+    REG_WR(pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN);
+
+    if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+    {
+        if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1)
+        {
+            REG_WR(pDevice, MacCtrl.SerdesCfg, 0x616000);
+        }
+        if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)
+        {
+
+            if(!(pDevice->TbiFlags & TBI_DO_PREEMPHASIS))
+            {
+                /* Set SerDes drive transmission level to 1.2V */
+                Value32 = REG_RD(pDevice, MacCtrl.SerdesCfg) & 0xfffff000;
+                REG_WR(pDevice, MacCtrl.SerdesCfg, Value32 | 0x880);
+            }
+        }
+    }
+
+    REG_WR(pDevice, MacCtrl.LowWaterMarkMaxRxFrame, 2);
+
+    /* ecd 13216 workaround for serdes */
+    if(pDevice->PhyFlags & PHY_IS_FIBER)
+    {
+        Value32 = REG_RD_OFFSET(pDevice, 0x5b0);
+        REG_WR_OFFSET(pDevice, 0x5b0, Value32 | BIT_10 );
+      
+        pDevice->GrcLocalCtrl |= BIT_4 ; 
+        pDevice->GrcLocalCtrl &= ~BIT_5 ; 
+
+        REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl);
+        Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+        MM_Wait(40);
+    }
+
+    if (!pDevice->InitDone)
+    {
+        pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+    }
+
+    if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
+        ( ((pDevice->PhyId & PHY_ID_MASK) != PHY_BCM5401_PHY_ID)&&
+        ((pDevice->PhyId & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) ))
+    {
+        /* 5401/5411 PHY needs a delay of about 1 second after PHY reset */
+        /* Without the delay, it has problem linking at forced 10 half */
+        /* So skip the reset... */
+        if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5780)
+            for(j =0; j<0x5000; j++)
+                MM_Wait(1);
+
+        LM_ResetPhy(pDevice);
+    }
+
+    /* Setup the phy chip. */
+    LM_SetupPhy(pDevice);
+
+    if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG)){
+        /* 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);
+
+#ifdef INCLUDE_TCP_SEG_SUPPORT
+    if (pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
+    {
+        if (LM_LoadStkOffLdFirmware(pDevice) == LM_STATUS_FAILURE)
+        {
+            return LM_STATUS_FAILURE;
+        }
+    }
+#endif
+    LM_WritePostResetSignatures(pDevice, LM_INIT_RESET);
+
+    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->Flags & FLUSH_POSTED_WRITE_FLAG)
+    {
+        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);
+    if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
+    {
+        MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
+    }
+
+    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);
+
+    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->Flags & NIC_SEND_BD_FLAG)
+        {
+            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;
+
+#ifdef INCLUDE_TCP_SEG_SUPPORT
+            if (Value32 & (SND_BD_FLAG_CPU_PRE_DMA | SND_BD_FLAG_CPU_POST_DMA))
+            {
+                if(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))  
+                {
+                    pSendBd->u2.s2.Reserved = pPacket->u.Tx.MaxSegmentSize;
+                }
+               else if (FragCount == 0)
+                {
+                    pSendBd->u2.s2.Reserved = pPacket->u.Tx.MaxSegmentSize;
+                }
+                else
+                {
+                    pSendBd->u2.s2.Reserved = 0;
+                    Value32 &= 0xffff0fff;
+                }
+            }
+#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->Flags & NIC_SEND_BD_FLAG))
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+
+            pDevice->SendRing[Idx] = 0;
+
+        } /* for */
+        if (pDevice->Flags & TX_4G_WORKAROUND_FLAG)
+        {
+            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. */
+    pDevice->SendRing[StartIdx] = pPacket;
+
+#ifdef BCM_NIC_SEND_BD
+    if (pDevice->Flags & NIC_SEND_BD_FLAG)
+    {
+        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->Flags & FLUSH_POSTED_WRITE_FLAG)
+        {
+            MB_REG_RD(pDevice, Mailbox.SendNicProdIdx[0].Low);
+        }
+         else
+        {
+            MM_MMIOWB();
+        }      
+    }
+    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->Flags & FLUSH_POSTED_WRITE_FLAG)
+        {
+            MB_REG_RD(pDevice, Mailbox.SendHostProdIdx[0].Low);
+        }
+        else
+        {
+            MM_MMIOWB();
+        }      
+    }
+
+    /* 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) &&
+            ((Base + 8 + Len) < Base))
+        {
+            return LM_STATUS_SUCCESS;
+        }
+        FragCount++;
+        if (FragCount >= pPacket->u.Tx.FragCount)
+        {
+            break;
+        }
+        pSendBd++;
+        if (!(pDevice->Flags & NIC_SEND_BD_FLAG))
+        {
+            Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
+            if (Idx == 0)
+            {
+                pSendBd = &pDevice->pSendBdVirt[0];
+            }
+        }
+    }
+    return LM_STATUS_FAILURE;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_UINT32
+ComputeCrc32(LM_UINT8 *pBuffer, LM_UINT32 BufferSize)
+{
+    LM_UINT32 Reg;
+    LM_UINT32 Tmp;
+    int 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)
+    {
+        for(k = 0; k < 4; k++)
+        {
+            REG_WR(pDevice, MacCtrl.HashReg[k], pDevice->MulticastHash[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_5714_FAMILY(pDevice->ChipRevId))
+    {
+        k = 16;
+    }
+    else if (!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        k = 16;
+    }
+    else
+    {
+        k = 8;
+    }
+#ifdef BCM_ASF
+    if (pDevice->AsfFlags & ASF_ENABLED)
+    {
+        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);
+
+    /*
+     * If we do not have a status block pointer, then
+     * the device hasn't really been opened.  Do not
+     * attempt to clean up packets.
+     */
+    if (pDevice->pStatusBlkVirt == NULL)
+        return LM_STATUS_SUCCESS;
+
+    /* Abort packets that have already queued to go out. */
+    Idx = pDevice->SendConIdx; 
+    for ( ; ; )
+    {
+        if ((pPacket = pDevice->SendRing[Idx]))
+        {
+            pDevice->SendRing[Idx] = 0;
+            pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED;
+            pDevice->TxCounters.TxPacketAbortedCnt++;
+
+            MM_ATOMIC_ADD(&pDevice->SendBdLeft, pPacket->u.Tx.FragCount);
+            Idx = (Idx + pPacket->u.Tx.FragCount) & 
+                T3_SEND_RCB_ENTRY_COUNT_MASK;
+
+            QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket);
+       }
+        else
+       {
+            break;
+       }
+    }
+
+    /* Cleanup the receive return rings. */
+#ifdef BCM_NAPI_RXPOLL
+    LM_ServiceRxPoll(pDevice, T3_RCV_RETURN_RCB_ENTRY_COUNT);
+#else
+    LM_ServiceRxInterrupt(pDevice);
+#endif
+
+    /* Indicate packets to the protocol. */
+    MM_IndicateTxPackets(pDevice);
+
+#ifdef BCM_NAPI_RXPOLL
+
+    /* 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;
+        }
+        MM_UnmapRxDma(pDevice, pPacket);
+        QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+#else
+    /* Indicate received packets to the protocols. */
+    MM_IndicateRxPackets(pDevice);
+#endif
+
+    /* Clean up the Std Receive Producer ring. */
+    /* Don't always trust the consumer idx in the status block in case of  */
+    /* hw failure */
+    Idx = 0;
+
+    while(Idx < T3_STD_RCV_RCB_ENTRY_COUNT)
+    {
+        if ((pPacket = pDevice->RxStdRing[Idx]))
+        {
+            MM_UnmapRxDma(pDevice, pPacket);
+            QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+            pDevice->RxStdRing[Idx] = 0;
+        }
+
+        Idx++;
+    } /* 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 = 0;
+
+    while(Idx < T3_JUMBO_RCV_RCB_ENTRY_COUNT)
+    {
+        if ((pPacket = pDevice->RxJumboRing[Idx]))
+        {
+            MM_UnmapRxDma(pDevice, pPacket);
+            QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+            pDevice->RxJumboRing[Idx] = 0;
+        }
+        Idx++;
+    } /* 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_DoHalt(LM_DEVICE_BLOCK *pDevice)
+{
+    PLM_PACKET pPacket;
+    LM_UINT32 EntryCnt;
+
+    LM_DisableFW(pDevice);
+
+    LM_WritePreResetSignatures(pDevice, LM_SHUTDOWN_RESET);
+    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);
+    LM_WriteLegacySignatures(pDevice, LM_SHUTDOWN_RESET);
+
+    /* 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_DoHalt */
+
+
+LM_STATUS
+LM_Halt(LM_DEVICE_BLOCK *pDevice)
+{
+    LM_STATUS status;
+
+    status = LM_DoHalt(pDevice);
+    LM_WritePostResetSignatures(pDevice, LM_SHUTDOWN_RESET);
+    return status;
+}
+
+
+STATIC LM_VOID
+LM_WritePreResetSignatures(LM_DEVICE_BLOCK *pDevice, LM_RESET_TYPE Mode)
+{
+    MEM_WR_OFFSET(pDevice, T3_FIRMWARE_MAILBOX,T3_MAGIC_NUM_FIRMWARE_INIT_DONE);
+#ifdef BCM_ASF
+    if (pDevice->AsfFlags & ASF_NEW_HANDSHAKE)
+    {
+        if (Mode == LM_INIT_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_START);
+        }
+       else if (Mode == LM_SHUTDOWN_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_UNLOAD);
+        }
+       else if (Mode == LM_SUSPEND_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_SUSPEND);
+        }
+    }
+#endif
+}
+
+STATIC LM_VOID
+LM_WritePostResetSignatures(LM_DEVICE_BLOCK *pDevice, LM_RESET_TYPE Mode)
+{
+#ifdef BCM_ASF
+    if (pDevice->AsfFlags & ASF_NEW_HANDSHAKE)
+    {
+        if (Mode == LM_INIT_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX,
+                T3_DRV_STATE_START_DONE);
+        }
+       else if (Mode == LM_SHUTDOWN_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX,
+                T3_DRV_STATE_UNLOAD_DONE);
+        }
+    }
+#endif
+}
+
+STATIC LM_VOID
+LM_WriteLegacySignatures(LM_DEVICE_BLOCK *pDevice, LM_RESET_TYPE Mode)
+{
+#ifdef BCM_ASF
+    if (pDevice->AsfFlags & ASF_ENABLED)
+    {
+        if (Mode == LM_INIT_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_START);
+        }
+       else if (Mode == LM_SHUTDOWN_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_UNLOAD);
+        }
+       else if (Mode == LM_SUSPEND_RESET)
+        {
+            MEM_WR_OFFSET(pDevice, T3_DRV_STATE_MAILBOX, T3_DRV_STATE_SUSPEND);
+        }
+    }
+#endif
+}
+
+STATIC LM_STATUS
+LM_ResetChip(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 Value32;
+    LM_UINT32 j, tmp1 = 0, tmp2 = 0;
+
+    /* 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. */
+        LM_NVRAM_AcquireLock(pDevice);
+    }
+
+    Value32 = GRC_MISC_CFG_CORE_CLOCK_RESET;
+    if (pDevice->Flags & PCI_EXPRESS_FLAG)
+    {
+        if (REG_RD_OFFSET(pDevice, 0x7e2c) == 0x60)    /* PCIE 1.0 system */
+        {
+            REG_WR_OFFSET(pDevice, 0x7e2c, 0x20);
+       }
+        if (pDevice->ChipRevId != T3_CHIP_ID_5750_A0)
+        {
+            /* This bit prevents PCIE link training during GRC reset */
+            REG_WR(pDevice, Grc.MiscCfg, BIT_29);    /* Write bit 29 first */
+            Value32 |= BIT_29;       /* and keep bit 29 set during GRC reset */
+        }
+    }
+    if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        Value32 |= GRC_MISC_GPHY_KEEP_POWER_DURING_RESET;
+    }
+
+    if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId) )
+    {
+        /* Save the MSI ENABLE bit (may need to save the message as well) */
+        tmp1 = LM_RegRd( pDevice, T3_PCI_MSI_ENABLE );
+    }
+
+    /* Global reset. */
+    RAW_REG_WR(pDevice, Grc.MiscCfg, Value32);
+    MM_Wait(120);
+
+    MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32);
+
+    MM_Wait(120);
+
+    /* 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 */
+    if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId) )
+    {
+        Value32 = REG_RD(pDevice,MemArbiter.Mode);
+        REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE | Value32);
+    }
+    else
+    {
+        REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE);
+    }
+
+    if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId))
+    {
+        /* restore the MSI ENABLE bit (may need to restore the message also) */
+        tmp2 = LM_RegRd( pDevice, T3_PCI_MSI_ENABLE );
+        tmp2 |= (tmp1 & (1 << 16));
+        LM_RegWr( pDevice, T3_PCI_MSI_ENABLE, tmp2, TRUE );
+        tmp2 = LM_RegRd( pDevice, T3_PCI_MSI_ENABLE );
+    }
+
+
+    if (pDevice->ChipRevId == T3_CHIP_ID_5750_A3)
+    {
+        /* Because of chip bug on A3, we need to kill the CPU */
+        LM_DisableFW(pDevice);
+        REG_WR_OFFSET(pDevice, 0x5000, 0x400);
+    }
+#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->Flags & MINI_PCI_FLAG) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705))
+    {
+        pDevice->ClockCtrl |= T3_PCI_CLKRUN_OUTPUT_EN;
+        if (pDevice->ChipRevId == T3_CHIP_ID_5705_A0)
+        {
+            pDevice->ClockCtrl |= T3_PCI_FORCE_CLKRUN;
+        }
+        REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl);
+    }
+
+    if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+    {
+        pDevice->MacMode = MAC_MODE_PORT_MODE_TBI;
+    }
+    else if(pDevice->PhyFlags & PHY_IS_FIBER)
+    {
+         pDevice->MacMode = MAC_MODE_PORT_MODE_GMII;
+    }
+    else
+    {
+        pDevice->MacMode = 0;
+    }
+
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    REG_RD_BACK(pDevice, MacCtrl.Mode);
+    MM_Wait(40);
+
+    /* Wait for the firmware to finish initialization. */
+    for(j = 0; j < 100000; j++)
+    {
+        MM_Wait(10);
+
+        if (j < 100)
+            continue;
+
+        Value32 = MEM_RD_OFFSET(pDevice, T3_FIRMWARE_MAILBOX);
+        if(Value32 == ~T3_MAGIC_NUM_FIRMWARE_INIT_DONE)
+        {
+            break;
+        }
+    }
+    if ((j >= 0x100000) && (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704))
+    {
+        /* workaround - need to reset nvram of both devices at the same time */
+        /* if the boot code is not running */
+        if (LM_NVRAM_AcquireLock(pDevice) != LM_STATUS_SUCCESS)
+        {
+            LM_DEVICE_BLOCK *pDevice2;
+
+            REG_WR(pDevice, Nvram.Cmd, NVRAM_CMD_RESET);
+            pDevice2 = MM_FindPeerDev(pDevice);
+            if (pDevice2 && !pDevice2->InitDone)
+            {
+                REG_WR(pDevice2, Nvram.Cmd, NVRAM_CMD_RESET);
+           }
+       }
+        else
+        {
+            LM_NVRAM_ReleaseLock(pDevice);
+        }
+    }
+
+
+    if ((pDevice->Flags & PCI_EXPRESS_FLAG) && 
+       (pDevice->ChipRevId != T3_CHIP_ID_5750_A0))
+    {
+        /* Enable PCIE bug fix */
+        Value32 = REG_RD_OFFSET(pDevice, 0x7c00);
+        REG_WR_OFFSET(pDevice, 0x7c00, Value32 | BIT_25 | BIT_29);
+    }
+
+#ifdef BCM_ASF
+    pDevice->AsfFlags = 0;
+    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->AsfFlags = ASF_ENABLED;
+            if (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+            {
+                pDevice->AsfFlags |= ASF_NEW_HANDSHAKE;
+           }
+        }
+    }
+#endif
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+LM_ShutdownChip(PLM_DEVICE_BLOCK pDevice, LM_RESET_TYPE Mode)
+{
+    LM_DisableFW(pDevice);
+    LM_WritePreResetSignatures(pDevice, Mode);
+    if (pDevice->InitDone)
+    {
+        LM_Abort(pDevice);
+    }
+    else
+    {
+        LM_DisableChip(pDevice);
+    }
+    LM_ResetChip(pDevice);
+    LM_WriteLegacySignatures(pDevice, Mode);
+    LM_WritePostResetSignatures(pDevice, Mode);
+    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)
+    {
+        pPacket = pDevice->SendRing[SwConIdx];
+        pDevice->SendRing[SwConIdx] = 0;
+
+        /* 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 */
+
+
+#ifdef BCM_NAPI_RXPOLL
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+int
+LM_ServiceRxPoll(PLM_DEVICE_BLOCK pDevice, int limit)
+{
+    PLM_PACKET pPacket=NULL;
+    PT3_RCV_BD pRcvBd;
+    LM_UINT32 HwRcvRetProdIdx;
+    LM_UINT32 SwRcvRetConIdx;
+    int received = 0;
+
+    /* Loop thru the receive return rings for received packets. */
+    HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+
+    SwRcvRetConIdx = pDevice->RcvRetConIdx;
+    MM_RMB();
+    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));
+
+        switch(pPacket->u.Rx.RcvProdRing) {
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        case T3_JUMBO_RCV_PROD_RING:        /* Jumbo Receive Ring. */
+            pDevice->RxJumboRing[pPacket->u.Rx.RcvRingProdIdx] = 0;
+           break;
+#endif
+        case T3_STD_RCV_PROD_RING:      /* Standard Receive Ring. */
+            pDevice->RxStdRing[pPacket->u.Rx.RcvRingProdIdx] = 0;
+           break;
+        }
+
+        /* 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;
+
+        if (++received >= limit)
+        {
+            break;
+        }
+    } /* while */
+
+    pDevice->RcvRetConIdx = SwRcvRetConIdx;
+
+    /* Update the receive return ring consumer index. */
+    MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx);
+    if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
+    {
+        MB_REG_RD(pDevice, Mailbox.RcvRetConIdx[0].Low);
+    }
+    else
+    {
+        MM_MMIOWB();
+    }
+    return received;
+} /* LM_ServiceRxPoll */
+#endif /* BCM_NAPI_RXPOLL */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+LM_ServiceRxInterrupt(PLM_DEVICE_BLOCK pDevice)
+{
+#ifndef BCM_NAPI_RXPOLL
+    PLM_PACKET pPacket;
+    PT3_RCV_BD pRcvBd;
+#endif
+    LM_UINT32 HwRcvRetProdIdx;
+    LM_UINT32 SwRcvRetConIdx;
+
+    /* Loop thru the receive return rings for received packets. */
+    HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx;
+
+    SwRcvRetConIdx = pDevice->RcvRetConIdx;
+#ifdef BCM_NAPI_RXPOLL
+    if (!pDevice->RxPoll)
+    {
+        if (SwRcvRetConIdx != HwRcvRetProdIdx)
+        {
+            if (MM_ScheduleRxPoll(pDevice) == LM_STATUS_SUCCESS)
+            {
+                pDevice->RxPoll = TRUE;
+                REG_WR(pDevice, Grc.Mode,
+                    pDevice->GrcMode | GRC_MODE_NO_INTERRUPT_ON_RECEIVE);
+            }
+        }
+    }
+#else
+    MM_RMB();
+    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));
+
+        switch(pPacket->u.Rx.RcvProdRing) {
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+        case T3_JUMBO_RCV_PROD_RING:        /* Jumbo Receive Ring. */
+            pDevice->RxJumboRing[pPacket->u.Rx.RcvRingProdIdx] = 0;
+           break;
+#endif
+        case T3_STD_RCV_PROD_RING:      /* Standard Receive Ring. */
+            pDevice->RxStdRing[pPacket->u.Rx.RcvRingProdIdx] = 0;
+           break;
+        }
+
+        /* 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;
+
+    } /* while */
+
+    pDevice->RcvRetConIdx = SwRcvRetConIdx;
+
+    /* Update the receive return ring consumer index. */
+    MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx);
+    if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
+    {
+        MB_REG_RD(pDevice, Mailbox.RcvRetConIdx[0].Low);
+    }
+    else
+    {
+        MM_MMIOWB();
+    }
+
+#endif
+} /* 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;
+        }
+    }
+#ifdef 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);
+        
+#ifndef BCM_NAPI_RXPOLL
+    /* No spinlock for this queue since this routine is serialized. */
+    if(!QQ_Empty(&pDevice->RxPacketReceivedQ.Container))
+    {
+        /* Indicate receive packets. */
+        MM_IndicateRxPackets(pDevice);
+    }
+#endif
+
+    /* 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:  Add a Multicast address. Note that MC addresses, once added, */
+/*               cannot be individually deleted. All addresses must be        */
+/*               cleared.                                                     */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastAdd(LM_DEVICE_BLOCK *pDevice, PLM_UINT8 pMcAddress)
+{
+
+    LM_UINT32 RegIndex;
+    LM_UINT32 Bitpos;
+    LM_UINT32 Crc32;
+
+    Crc32 = ComputeCrc32(pMcAddress, 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. */
+    pDevice->MulticastHash[RegIndex] |= (1 << Bitpos);
+
+    LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST);
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastDel(LM_DEVICE_BLOCK *pDevice, PLM_UINT8 pMcAddress)
+{
+    return LM_STATUS_FAILURE;
+} /* LM_MulticastDel */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_MulticastClear(LM_DEVICE_BLOCK *pDevice)
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+    {
+        pDevice->MulticastHash[i] = 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_5703) ||
+        (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704)) 
+    {
+        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;
+}
+
+LM_VOID
+LM_PhyTapPowerMgmt(LM_DEVICE_BLOCK *pDevice)
+{
+    /* Turn off tap power management. */
+    if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x4c20);
+        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);
+    }
+}
+
+/******************************************************************************/
+/* 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->PhyFlags & PHY_RESET_ON_LINKDOWN) &&
+        (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_PhyTapPowerMgmt(pDevice);
+
+            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_ResetPhy(pDevice);
+                }
+            }
+        }
+    }
+    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->LedCtrl == LED_CTRL_PHY_MODE_1)
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 
+                BCM540X_EXT_CTRL_LINK3_LED_MODE);
+        }
+        else
+        {
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 0);
+        }
+    }
+
+    if (pDevice->PhyFlags & PHY_CAPACITIVE_COUPLING)
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x4007);
+        LM_ReadPhy(pDevice, BCM5401_AUX_CTRL, &Value32);
+        if (!(Value32 & BIT_10))
+        {
+            /* set the bit and re-link */
+            LM_WritePhy(pDevice, BCM5401_AUX_CTRL, Value32 | BIT_10);
+            return LM_STATUS_LINK_SETTING_MISMATCH;
+        }
+    }
+
+    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(pDevice->PhyFlags & PHY_IS_FIBER){
+               LocalPhyAd &= ~(PHY_AN_AD_ASYM_PAUSE |
+                                PHY_AN_AD_PAUSE_CAPABLE);
+                RemotePhyAd &= ~(PHY_AN_AD_ASYM_PAUSE |
+                               PHY_AN_AD_PAUSE_CAPABLE);
+
+                if (LocalPhyAd & PHY_AN_AD_1000XPAUSE)
+                     LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE;
+                if (LocalPhyAd & PHY_AN_AD_1000XPSE_ASYM)
+                     LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE;
+                if (RemotePhyAd & PHY_AN_AD_1000XPAUSE)
+                     RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
+                if (RemotePhyAd & PHY_AN_AD_1000XPSE_ASYM)
+                     RemotePhyAd |= PHY_LINK_PARTNER_ASYM_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;
+}
+
+
+#ifdef 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;
+    LM_FLOW_CONTROL PreviousFlowControl = pDevice->FlowControl;
+
+
+    if (pDevice->LoopBackMode == LM_MAC_LOOP_BACK_MODE)
+    {
+        pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE;
+        MM_IndicateStatus(pDevice, LM_STATUS_LINK_ACTIVE);
+        return LM_STATUS_SUCCESS;
+    }
+
+
+    if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5704) &&
+        (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) && pDevice->InitDone)
+    {
+        MacStatus = REG_RD(pDevice, MacCtrl.Status);
+        if ((MacStatus & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DETECTED |
+            MAC_STATUS_CFG_CHANGED | MAC_STATUS_RECEIVING_CFG))
+            == (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DETECTED))
+        {
+      
+            REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED |
+                MAC_STATUS_CFG_CHANGED);
+            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);
+
+    pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    MM_Wait(10);
+
+    /* 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 SerdesCfg = 0;
+        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;
+            }
+
+            if(pDevice->TbiFlags & TBI_DO_PREEMPHASIS)
+            {
+                /* Save voltage reg bits & bits 14:0 */
+                SerdesCfg = REG_RD(pDevice, MacCtrl.SerdesCfg) &
+                              (BIT_23 | BIT_22 | BIT_21 | BIT_20 | 0x7fff );
+
+            }
+            else
+            { 
+                /* preserve the voltage regulator bits */
+                SerdesCfg = REG_RD(pDevice, MacCtrl.SerdesCfg) &
+                                   (BIT_23 | BIT_22 | BIT_21 | BIT_20);
+            }
+        }
+        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)
+                {
+                    if(pDevice->TbiFlags & TBI_DO_PREEMPHASIS)
+                    {
+                         REG_WR(pDevice, MacCtrl.SerdesCfg, 0xc011000 | SerdesCfg);                   
+                    }
+                    else
+                    {
+                        REG_WR(pDevice, MacCtrl.SerdesCfg, 0xc011880 | SerdesCfg);
+                    }
+                }
+                REG_WR(pDevice, MacCtrl.SgDigControl, ExpectedSgDigCtrl |
+                    BIT_30);
+                REG_RD_BACK(pDevice, MacCtrl.SgDigControl);
+               MM_Wait(5);
+                REG_WR(pDevice, MacCtrl.SgDigControl, ExpectedSgDigCtrl);
+                pDevice->AutoNegJustInited = TRUE;
+            }
+            /* If autoneg is off, you only get SD when link is up */
+            else if(MacStatus & (MAC_STATUS_PCS_SYNCED |
+                MAC_STATUS_SIGNAL_DETECTED))
+            {
+                SgDigStatus = REG_RD(pDevice, MacCtrl.SgDigStatus);
+                if ((SgDigStatus & BIT_1) &&
+                    (MacStatus & MAC_STATUS_PCS_SYNCED))
+                {
+                    /* autoneg. completed */
+                    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;
+                    pDevice->AutoNegJustInited = FALSE;
+                }
+                else if (!(SgDigStatus & BIT_1))
+                {
+                    if (pDevice->AutoNegJustInited == TRUE)
+                    {
+                        /* we may be checking too soon, so check again */
+                        /* at the next poll interval */
+                        pDevice->AutoNegJustInited = FALSE;
+                    }
+                    else
+                    {
+                        /* autoneg. failed */
+                        if (WorkAround)
+                        {
+                            if (PortA)
+                            {
+                                if(pDevice->TbiFlags & TBI_DO_PREEMPHASIS)
+                                {
+                                    REG_WR(pDevice, MacCtrl.SerdesCfg,
+                                        0xc010000 | (SerdesCfg & ~0x00001000));
+                                }
+                                else
+                                {
+                                    REG_WR(pDevice, MacCtrl.SerdesCfg,
+                                        0xc010880 | SerdesCfg);
+                                }
+                            }
+                            else
+                            {
+                                if(pDevice->TbiFlags & TBI_DO_PREEMPHASIS)
+                                {
+                                    REG_WR(pDevice, MacCtrl.SerdesCfg,
+                                        0x4010000 | (SerdesCfg & ~0x00001000));
+                                }
+                                else
+                                {
+                                    REG_WR(pDevice, MacCtrl.SerdesCfg,
+                                        0x4010880 | SerdesCfg);
+                                }
+                            }
+                        }
+                        /* turn off autoneg. to allow traffic to pass */
+                        REG_WR(pDevice, MacCtrl.SgDigControl, 0x01388400);
+                        REG_RD_BACK(pDevice, MacCtrl.SgDigControl);
+                        MM_Wait(40);
+                        MacStatus = REG_RD(pDevice, MacCtrl.Status);
+                        if ((MacStatus & MAC_STATUS_PCS_SYNCED) && !(MacStatus & MAC_STATUS_RECEIVING_CFG)) 
+                        {
+                            LM_SetFlowControl(pDevice, 0, 0);
+                            CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (SgDigCtrl & BIT_31) {
+                if (WorkAround)
+                {
+                    if (PortA)
+                    {
+
+                       if(pDevice->TbiFlags & TBI_DO_PREEMPHASIS)
+                       {
+                           REG_WR(pDevice, MacCtrl.SerdesCfg,
+                                  0xc010000 | (SerdesCfg & ~0x00001000));
+                       }
+                       else
+                       {
+                            REG_WR(pDevice, MacCtrl.SerdesCfg,
+                                 0xc010880 | SerdesCfg);
+                       }
+                    }
+                    else
+                    {
+                       if(pDevice->TbiFlags & TBI_DO_PREEMPHASIS)
+                       {
+                           REG_WR(pDevice, MacCtrl.SerdesCfg,
+                                0x4010000 | (SerdesCfg & ~0x00001000));
+                       }
+                       else
+                       {
+                           REG_WR(pDevice, MacCtrl.SerdesCfg,
+                               0x4010880 | SerdesCfg);
+                       }
+                    }
+                }
+                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);
+                REG_RD_BACK(pDevice, MacCtrl.Mode);
+                MM_Wait(20);
+
+                REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode |
+                    MAC_MODE_SEND_CONFIGS);
+                REG_RD_BACK(pDevice, MacCtrl.Mode);
+
+                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);
+                REG_RD_BACK(pDevice, MacCtrl.Status);
+                MM_Wait(20);
+                if ((REG_RD(pDevice, MacCtrl.Status) &
+                    (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0)
+                    break;
+            }
+            if (pDevice->TbiFlags & TBI_POLLING_FLAGS)
+            {
+                Value32 = REG_RD(pDevice, MacCtrl.Status);
+                if (Value32 & MAC_STATUS_RECEIVING_CFG)
+                {
+                    pDevice->IgnoreTbiLinkChange = TRUE;
+                }
+                else if (pDevice->TbiFlags & TBI_POLLING_INTR_FLAG)
+                {
+                    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);
+        REG_RD_BACK(pDevice, MacCtrl.Status);
+        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);
+            REG_RD_BACK(pDevice, MacCtrl.Mode);
+            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, pDevice->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, pDevice->LedCtrl |
+            LED_CTRL_OVERRIDE_LINK_LED |
+            LED_CTRL_OVERRIDE_TRAFFIC_LED);
+    }
+
+    /* Indicate link status. */
+    if ((pDevice->LinkStatus != CurrentLinkStatus) ||
+        ((CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) &&
+        (PreviousFlowControl != pDevice->FlowControl)))
+    {
+        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);
+    REG_RD_BACK(pDevice, MacCtrl.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->LoopBackMode == LM_PHY_LOOP_BACK_MODE) ||
+        (pDevice->LoopBackMode == LM_MAC_LOOP_BACK_MODE))
+    {
+        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+        if(!(Value32 & PHY_CTRL_LOOPBACK_MODE) &&
+            (pDevice->LoopBackMode == LM_PHY_LOOP_BACK_MODE))
+        {
+            /* 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);
+            REG_RD_BACK(pDevice, MacCtrl.Mode);
+            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->LedCtrl == LED_CTRL_PHY_MODE_2) ||
+             (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;
+        }
+    }
+
+    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);
+    }
+    /* if using MAC led mode and not using auto polling, need to configure */
+    /* mi status register */
+    else if ((pDevice->LedCtrl &
+            (LED_CTRL_PHY_MODE_1 | LED_CTRL_PHY_MODE_2)) == 0)
+    {
+        if (CurrentLinkStatus != LM_STATUS_LINK_ACTIVE)
+        {
+            REG_WR(pDevice, MacCtrl.MiStatus, 0);
+        }
+        else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+        {
+            REG_WR(pDevice, MacCtrl.MiStatus,
+                MI_STATUS_ENABLE_LINK_STATUS_ATTN | MI_STATUS_10MBPS);
+        }
+        else
+        {
+            REG_WR(pDevice, MacCtrl.MiStatus,
+                MI_STATUS_ENABLE_LINK_STATUS_ATTN);
+        }
+    }
+
+    /* 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 */
+
+
+void
+LM_5714_FamForceFiber(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    u32 Creg, new_bmcr;
+    LM_ReadPhy(pDevice, PHY_CTRL_REG, &Creg);
+
+    new_bmcr = Creg & ~PHY_CTRL_AUTO_NEG_ENABLE; 
+    if ( pDevice->RequestedDuplexMode == 0 ||
+        pDevice->RequestedDuplexMode == LM_DUPLEX_MODE_FULL){
+
+        new_bmcr |= PHY_CTRL_FULL_DUPLEX_MODE;
+    }
+
+    if(Creg == new_bmcr)
+        return;
+
+    new_bmcr |= PHY_CTRL_SPEED_SELECT_1000MBPS; /* Reserve bit */
+
+    /* Force a linkdown */
+    LM_WritePhy(pDevice, PHY_AN_AD_REG, 0);
+    LM_WritePhy(pDevice, PHY_CTRL_REG, new_bmcr | 
+                         PHY_CTRL_RESTART_AUTO_NEG |
+                         PHY_CTRL_AUTO_NEG_ENABLE  |
+                         PHY_CTRL_SPEED_SELECT_1000MBPS);
+    MM_Wait(10);
+
+    /* Force it */
+    LM_WritePhy(pDevice, PHY_CTRL_REG, new_bmcr);
+    MM_Wait(10);
+
+    return;
+
+}/* LM_5714_FamForceFiber */
+
+
+void
+LM_5714_FamGoFiberAutoNeg(
+       PLM_DEVICE_BLOCK pDevice)
+{
+    u32 adv,Creg,new;
+
+    LM_ReadPhy(pDevice, PHY_CTRL_REG, &Creg);
+    LM_ReadPhy(pDevice,PHY_AN_AD_REG, &adv);
+
+    new = adv & ~(  PHY_AN_AD_1000XFULL | 
+                    PHY_AN_AD_1000XHALF |
+                    PHY_AN_AD_1000XPAUSE |
+                    PHY_AN_AD_1000XPSE_ASYM |
+                    0x1f);
+
+    new |= PHY_AN_AD_1000XPAUSE;
+
+    new |=  PHY_AN_AD_1000XFULL; 
+    new |=  PHY_AN_AD_1000XHALF;
+
+    if ((new != adv) || !(Creg & PHY_CTRL_AUTO_NEG_ENABLE)){
+        LM_WritePhy(pDevice, PHY_AN_AD_REG, new);
+        MM_Wait(5);
+        pDevice->AutoNegJustInited=1;
+        LM_WritePhy(pDevice, PHY_CTRL_REG, (Creg | 
+            PHY_CTRL_RESTART_AUTO_NEG | 
+            PHY_CTRL_SPEED_SELECT_1000MBPS |
+            PHY_CTRL_AUTO_NEG_ENABLE) );
+    }
+
+    return;
+} /* 5714_FamGoFiberAutoNeg */
+
+void
+LM_5714_FamDoFiberLoopback(PLM_DEVICE_BLOCK pDevice)
+{
+    u32 Value32;
+    
+    LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+
+    if( !(Value32 & PHY_CTRL_LOOPBACK_MODE) )
+    {
+        LM_WritePhy(pDevice, PHY_CTRL_REG, 0x4140);
+
+        /* Prevent the interrupt handling from being called. */
+        pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED |
+                 (pDevice->pStatusBlkVirt->Status &
+                 ~STATUS_BLOCK_LINK_CHANGED_STATUS);
+    }
+  
+    pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE;
+    MM_IndicateStatus(pDevice, LM_STATUS_LINK_ACTIVE);
+  
+    return; 
+
+}/* 5714_FamDoFiberLoopBack */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+
+LM_STATUS
+LM_SetupNewFiberPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS LmStatus = LM_STATUS_SUCCESS;
+    u32 Creg,Sreg,rsav;
+
+    rsav = pDevice->LinkStatus;
+
+    pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; 
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    MM_Wait(40);
+
+     /* 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);
+       
+
+    if( (pDevice->PhyFlags & PHY_FIBER_FALLBACK) &&  
+        ( pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) ){
+
+        /* do nothing */
+    }else if ( pDevice->LoopBackMode == LM_MAC_LOOP_BACK_MODE){
+
+        LM_5714_FamDoFiberLoopback(pDevice);
+        goto fiberloopbackreturn;
+
+    } else if( pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) { 
+
+        LM_5714_FamGoFiberAutoNeg(pDevice);
+
+
+    }else {
+
+        LM_5714_FamForceFiber(pDevice);
+    }
+    LM_ReadPhy(pDevice, PHY_STATUS_REG, &Sreg);
+    LM_ReadPhy(pDevice, PHY_STATUS_REG, &Sreg);
+
+    if(Sreg & PHY_STATUS_LINK_PASS){
+
+        pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE;
+        pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS;
+
+        LM_ReadPhy(pDevice, PHY_CTRL_REG, &Creg);
+
+        if(Creg & PHY_CTRL_FULL_DUPLEX_MODE) {
+            pDevice->DuplexMode = LM_DUPLEX_MODE_FULL;
+        }else{
+            pDevice->DuplexMode = LM_DUPLEX_MODE_HALF;
+            pDevice->MacMode |= MAC_MODE_HALF_DUPLEX; 
+            REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+        }
+
+        if(Creg & PHY_CTRL_AUTO_NEG_ENABLE){
+            u32 ours,partner;
+
+            LM_ReadPhy(pDevice,PHY_AN_AD_REG, &ours);
+            LM_ReadPhy(pDevice,PHY_LINK_PARTNER_ABILITY_REG, &partner);
+            LM_SetFlowControl(pDevice, ours, partner);
+        }
+
+    }else{     
+        pDevice->LinkStatus = LM_STATUS_LINK_DOWN;
+        pDevice->LineSpeed = 0;
+    }
+
+    if(rsav != pDevice->LinkStatus)
+        MM_IndicateStatus(pDevice, pDevice->LinkStatus);
+
+fiberloopbackreturn:
+    pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII;
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    MM_Wait(40);
+    /* Enable link change interrupt. */
+    REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN);
+
+    return LmStatus;
+} /* Setup New phy */
+
+void
+LM_5714_FamFiberCheckLink(
+    PLM_DEVICE_BLOCK pDevice)
+{
+
+    if(pDevice->AutoNegJustInited){
+        pDevice->AutoNegJustInited=0;
+        return;
+    }
+
+    if ((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) &&
+        (pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO) &&
+       !(pDevice->PhyFlags &  PHY_FIBER_FALLBACK)){
+        u32 bmcr;
+
+        LM_ReadPhy(pDevice, PHY_CTRL_REG, &bmcr);
+        if (bmcr & PHY_CTRL_AUTO_NEG_ENABLE) {
+            u32 phy1, phy2;
+
+            LM_WritePhy(pDevice, 0x1c, 0x7c00);
+            LM_ReadPhy(pDevice, 0x1c, &phy1);
+
+            LM_WritePhy(pDevice, 0x17, 0x0f01);
+            LM_ReadPhy(pDevice, 0x15, &phy2);
+            LM_ReadPhy(pDevice, 0x15, &phy2);
+
+            if ((phy1 & 0x10) && !(phy2 & 0x20)) {
+
+                /* We have signal detect and not receiving
+                 * configs.
+                 */
+
+                pDevice->PhyFlags |= PHY_FIBER_FALLBACK;
+               LM_5714_FamForceFiber(pDevice);
+            }
+        }
+    }
+    else if ( (pDevice->PhyFlags & PHY_FIBER_FALLBACK) &&
+              (pDevice->RequestedLineSpeed == LM_LINE_SPEED_AUTO)) {
+            u32 phy2;
+
+            LM_WritePhy(pDevice, 0x17, 0x0f01);
+            LM_ReadPhy(pDevice, 0x15, &phy2);
+            if (phy2 & 0x20) {
+                /* Receiving configs. */
+
+                pDevice->PhyFlags &= ~PHY_FIBER_FALLBACK;
+                LM_5714_FamGoFiberAutoNeg(pDevice);
+        }
+    }
+
+} /* LM_5714_FamFiberCheckLink */
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+LM_STATUS
+LM_SetupPhy(
+    PLM_DEVICE_BLOCK pDevice)
+{
+    LM_STATUS LmStatus;
+    LM_UINT32 Value32;
+
+    if(pDevice->PhyFlags & PHY_IS_FIBER)
+    {
+       LmStatus = LM_SetupNewFiberPhy(pDevice);
+    }else 
+#ifdef INCLUDE_TBI_SUPPORT
+    if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+    {
+        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(!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        if (pDevice->LinkStatus == LM_STATUS_LINK_DOWN)
+        {
+            REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks, 0);
+        }
+        else
+        {
+            REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks,
+                pDevice->StatsCoalescingTicks);
+        }
+    }
+
+    return LmStatus;
+}
+
+
+/* test data pattern */
+static LM_UINT32 pattern[4][6] = {
+    /* For 5703/04, each DFE TAP has 21-bits (low word 15, hi word 6)
+    For 5705   , each DFE TAP has 19-bits (low word 15, hi word 4)
+    For simplicity, we check only 19-bits, so we don't have to
+    distinguish which chip it is.
+    the LO word contains 15 bits, make sure pattern data is < 0x7fff
+    the HI word contains  6 bits, make sure pattern data is < 0x003f */
+    {0x00005555, 0x00000005, /* ch0, TAP 0, LO/HI pattern */
+    0x00002aaa, 0x0000000a,  /* ch0, TAP 1, LO/HI pattern */
+    0x00003456, 0x00000003}, /* ch0, TAP 2, LO/HI pattern */
+
+    {0x00002aaa, 0x0000000a, /* ch1, TAP 0, LO/HI pattern */
+    0x00003333, 0x00000003,  /* ch1, TAP 1, LO/HI pattern */
+    0x0000789a, 0x00000005}, /* ch1, TAP 2, LO/HI pattern */
+
+    {0x00005a5a, 0x00000005, /* ch2, TAP 0, LO/HI pattern */
+    0x00002a6a, 0x0000000a,  /* ch2, TAP 1, LO/HI pattern */
+    0x00001bcd, 0x00000003}, /* ch2, TAP 2, LO/HI pattern */
+
+    {0x00002a5a, 0x0000000a, /* ch3, TAP 0, LO/HI pattern */
+    0x000033c3, 0x00000003,  /* ch3, TAP 1, LO/HI pattern */
+    0x00002ef1, 0x00000005}, /* ch3, TAP 2, LO/HI pattern */
+};
+
+/********************************************************/
+/* Routine to wait for PHY Macro Command to complete    */
+/*                                                      */
+/* If PHY's Macro operation keeps stay busy, nothing we */
+/* can do anyway.  The timeout is there so we won't     */
+/* stay in this routine indefinitly.                    */
+/********************************************************/
+static LM_UINT32 LM_wait_macro_done(LM_DEVICE_BLOCK *pDevice);
+
+static LM_UINT32
+LM_wait_macro_done(LM_DEVICE_BLOCK *pDevice)
+{
+    LM_UINT32 timeout;
+    LM_UINT32 val32;
+
+    timeout = 100;
+    while (timeout--)
+    {
+        /* make sure the MACRO operation is complete */
+        LM_ReadPhy(pDevice, 0x16, &val32);
+        if ((val32 & 0x1000) == 0) break;
+    }
+
+    return( timeout > 0 );
+}
+
+/********************************************************/
+/* This routine resets the PHY on following chips:      */
+/*      5703, 04, CIOB-E and 5705                       */
+/*                                                      */
+/* This routine will issue PHY_RESET and check if       */
+/* the reset is sucessful.  If not, another PHY RESET   */
+/* will be issued, until max "retry" reaches            */
+/*                                                      */
+/* Input:                                               */
+/*      pDevice - device's context                      */
+/*      retry   - number of retries                     */
+/*      reset   - TRUE=will cause a PHY reset initially */
+/*                FALSE = will not issue a PHY reset    */
+/*                        unless TAP lockup detected    */
+/*                                                      */
+/* Output:                                              */
+/*      TRUE    - PHY Reset is done sucessfully         */
+/*      FALSE   - PHY Reset had failed, after "retry"   */
+/*                has reached                           */
+/*                                                      */
+/* Dependencies:                                        */
+/*      void LM_wait_macro_done()                       */
+/*      u32  pattern[]                                  */
+/*                                                      */
+/* Usage:                                               */
+/*      a. Before calling this routine, caller must     */
+/*         determine if the chip is a 5702/03/04 or     */
+/*         CIOB-E, and only call this routine if the    */
+/*         is one of these.                             */
+/*         or its derivatives.                          */
+/*      b. Instead of using MII register write to reset */
+/*         the PHY, call this routine instead           */
+/*      c. Upon return from this routine, check return  */
+/*         value (TRUE/FALSE) to determine if PHY reset */
+/*         is successful of not and "optionally" take   */
+/*         appropriate action (such as: event log)      */
+/*      d. Regardless of the return TRUE or FALSE,      */
+/*         proceed with PHY setup as you normally would */
+/*         after a PHY_RESET.                           */
+/*      e. It is recommended that the caller will give  */
+/*         10 "retry", however, caller can change to a  */
+/*         different number, depending on you code.     */
+/*                                                      */
+/********************************************************/
+LM_STATUS LM_ResetPhy_5703_4_5(LM_DEVICE_BLOCK *pDevice, int retry, int reset);
+
+LM_STATUS
+LM_ResetPhy_5703_4_5(LM_DEVICE_BLOCK *pDevice, int retry, int reset)
+{
+    LM_UINT32 val32, save9;
+    LM_UINT32 dataLo, dataHi;
+    int i, channel;
+    int      reset_success = LM_STATUS_FAILURE;
+    int      force_reset;
+
+    /* to actually do a PHY_RESET or not is dictated by the caller */
+    force_reset = reset;
+
+    while (retry-- && (reset_success != LM_STATUS_SUCCESS))
+    {
+        if (force_reset)
+        {
+            /* issue a phy reset, and wait for reset to complete */
+            LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+            for(i = 0; i < 100; i++)
+            {
+                MM_Wait(10);
+
+                LM_ReadPhy(pDevice, PHY_CTRL_REG, &val32);
+                if(val32 && !(val32 & PHY_CTRL_PHY_RESET))
+                {
+                    MM_Wait(20);
+                    break;
+                }
+            }
+
+            /* no more phy reset unless lockup detected */
+            force_reset = FALSE;
+        }
+
+        /* assuming reset is successful first */
+        reset_success = LM_STATUS_SUCCESS;
+
+        /* now go check the DFE TAPs to see if locked up, but
+           first, we need to set up PHY so we can read DFE TAPs */
+
+        /* Disable Transmitter and Interrupt, while we play with
+           the PHY registers, so the link partner won't see any
+           strange data and the Driver won't see any interrupts. */
+        LM_ReadPhy(pDevice, 0x10, &val32);
+        LM_WritePhy(pDevice, 0x10, val32 | 0x3000);
+
+        /* Setup Full-Duplex, 1000 mbps */
+        LM_WritePhy(pDevice, 0x0, 0x0140);
+
+        /* Set to Master mode */
+        LM_ReadPhy(pDevice, 0x9, &save9);
+        LM_WritePhy(pDevice, 0x9, 0x1800);
+
+        /* Enable SM_DSP_CLOCK & 6dB */
+        LM_WritePhy(pDevice, 0x18, 0x0c00);
+
+        /* blocks the PHY control access */
+        LM_WritePhy(pDevice, 0x17, 0x8005);
+        LM_WritePhy(pDevice, 0x15, 0x0800);
+
+        /* check TAPs for all 4 channels, as soon
+           as we see a lockup we'll stop checking */
+        for (channel=0; (channel<4) && (reset_success == LM_STATUS_SUCCESS);
+            channel++)
+        {
+            /* select channel and set TAP index to 0 */
+            LM_WritePhy(pDevice, 0x17, (channel * 0x2000) | 0x0200);
+            /* freeze filter again just to be safe */
+            LM_WritePhy(pDevice, 0x16, 0x0002);
+
+            /* write fixed pattern to the RAM, 3 TAPs for
+               each channel, each TAP have 2 WORDs (LO/HI) */
+            for (i=0; i<6; i++)
+                LM_WritePhy(pDevice, 0x15, pattern[channel][i]);
+
+            /* Activate PHY's Macro operation to write DFE TAP from RAM,
+               and wait for Macro to complete */
+            LM_WritePhy(pDevice, 0x16, 0x0202);
+            if (!LM_wait_macro_done(pDevice))
+            {
+                reset_success = LM_STATUS_FAILURE;
+                force_reset = TRUE;
+                break;
+            }
+
+            /* --- done with write phase, now begin read phase --- */
+
+            /* select channel and set TAP index to 0 */
+            LM_WritePhy(pDevice, 0x17, (channel * 0x2000) | 0x0200);
+
+            /* Active PHY's Macro operation to load DFE TAP to RAM,
+               and wait for Macro to complete */
+            LM_WritePhy(pDevice, 0x16, 0x0082);
+            if (!LM_wait_macro_done(pDevice))
+            {
+                reset_success = LM_STATUS_FAILURE;
+                force_reset = TRUE;
+                break;
+            }
+
+            /* enable "pre-fetch" */
+            LM_WritePhy(pDevice, 0x16, 0x0802);
+            if (!LM_wait_macro_done(pDevice))
+            {
+                reset_success = LM_STATUS_FAILURE;
+                force_reset = TRUE;
+                break;
+            }
+
+            /* read back the TAP values.
+               3 TAPs for each channel, each TAP have 2 WORDs (LO/HI) */
+            for (i=0; i<6; i+=2)
+            {
+                /* read Lo/Hi then wait for 'done' is faster */
+                LM_ReadPhy(pDevice, 0x15, &dataLo);
+                LM_ReadPhy(pDevice, 0x15, &dataHi);
+                if (!LM_wait_macro_done(pDevice))
+                {
+                    reset_success = LM_STATUS_FAILURE;
+                    force_reset = TRUE;
+                    break;
+                }
+
+                /* For 5703/04, each DFE TAP has 21-bits (low word 15,
+                 * hi word 6) For 5705, each DFE TAP pas 19-bits (low word 15,
+                 * hi word 4) For simplicity, we check only 19-bits, so we
+                 * don't have to distinguish which chip it is. */
+                dataLo &= 0x7fff;
+                dataHi &= 0x000f;
+            
+                /* check if what we wrote is what we read back */
+                if ( (dataLo != pattern[channel][i]) || (dataHi != pattern[channel][i+1]) )
+                {
+                    /* if failed, then the PHY is locked up,
+                       we need to do PHY reset again */
+                    reset_success = LM_STATUS_FAILURE;
+                    force_reset = TRUE;
+                    /* 04/25/2003. sb. do these writes before issueing a reset. */
+                    /* these steps will reduce the chance of back-to-back
+                     * phy lockup after reset */
+                    LM_WritePhy(pDevice, 0x17, 0x000B);
+                    LM_WritePhy(pDevice, 0x15, 0x4001);
+                    LM_WritePhy(pDevice, 0x15, 0x4005);
+                    break;
+                }
+            } /* for i */
+        } /* for channel */
+    } /* while */
+
+    /* restore dfe coeff back to zeros */
+    for (channel=0; channel<4 ; channel++)
+    {
+        LM_WritePhy(pDevice, 0x17, (channel * 0x2000) | 0x0200);
+        LM_WritePhy(pDevice, 0x16, 0x0002);
+        for (i=0; i<6; i++)
+            LM_WritePhy(pDevice, 0x15, 0x0000);
+        LM_WritePhy(pDevice, 0x16, 0x0202);
+        if (!LM_wait_macro_done(pDevice))
+        {
+            reset_success = LM_STATUS_FAILURE;
+            break;
+        }
+    }
+
+    /* remove block phy control */
+    LM_WritePhy(pDevice, 0x17, 0x8005);
+    LM_WritePhy(pDevice, 0x15, 0x0000);
+
+    /* unfreeze DFE TAP filter for all channels */
+    LM_WritePhy(pDevice, 0x17, 0x8200);
+    LM_WritePhy(pDevice, 0x16, 0x0000);
+
+    /* Restore PHY back to operating state */
+    LM_WritePhy(pDevice, 0x18, 0x0400);
+
+    /* Restore register 9 */
+    LM_WritePhy(pDevice, 0x9, save9);
+
+    /* enable transmitter and interrupt */
+    LM_ReadPhy(pDevice, 0x10, &val32);
+    LM_WritePhy(pDevice, 0x10, (val32 & ~0x3000));
+
+    return reset_success;
+}
+
+LM_VOID
+LM_ResetPhy(LM_DEVICE_BLOCK *pDevice)
+{
+    int j;
+    LM_UINT32 miireg;
+
+    if (pDevice->PhyFlags & PHY_CHECK_TAPS_AFTER_RESET)
+    {
+        LM_ResetPhy_5703_4_5(pDevice, 5, 1);
+    }
+    else
+    {
+        int wait_val = 100;
+        LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
+
+       if( pDevice->PhyFlags & PHY_IS_FIBER )
+            wait_val = 5000;
+
+        for(j = 0; j < wait_val; j++)
+        {
+            MM_Wait(10);
+
+            LM_ReadPhy(pDevice, PHY_CTRL_REG, &miireg);
+            if(miireg && !(miireg & PHY_CTRL_PHY_RESET))
+            {
+                MM_Wait(20);
+                break;
+            }
+        }
+
+        LM_PhyTapPowerMgmt(pDevice);
+    }
+    if ( (pDevice->PhyFlags & PHY_ADC_FIX) && 
+         !( pDevice->PhyFlags & PHY_IS_FIBER) )
+    {
+        LM_WritePhy(pDevice, 0x18, 0x0c00);
+        LM_WritePhy(pDevice, 0x17, 0x201f);
+        LM_WritePhy(pDevice, 0x15, 0x2aaa);
+        LM_WritePhy(pDevice, 0x17, 0x000a);
+        LM_WritePhy(pDevice, 0x15, 0x0323);
+        LM_WritePhy(pDevice, 0x18, 0x0400);
+    }
+    if ( (pDevice->PhyFlags & PHY_5705_5750_FIX) &&
+         !( pDevice->PhyFlags & PHY_IS_FIBER) )
+    {
+        LM_WritePhy(pDevice, 0x18, 0x0c00);
+        LM_WritePhy(pDevice, 0x17, 0x000a);
+        LM_WritePhy(pDevice, 0x15, 0x310b);
+        LM_WritePhy(pDevice, 0x17, 0x201f);
+        LM_WritePhy(pDevice, 0x15, 0x9506);
+        LM_WritePhy(pDevice, 0x17, 0x401f);
+        LM_WritePhy(pDevice, 0x15, 0x14e2);
+        LM_WritePhy(pDevice, 0x18, 0x0400);
+    }
+    if ( (pDevice->PhyFlags & PHY_5704_A0_FIX) &&
+         !( pDevice->PhyFlags & PHY_IS_FIBER) )
+    {
+        LM_WritePhy(pDevice, 0x1c, 0x8d68);
+        LM_WritePhy(pDevice, 0x1c, 0x8d68);
+    }
+    if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+       LM_ReadPhy(pDevice, BCM540X_EXT_CTRL_REG, &miireg);
+       miireg |= 1;         /* set tx elastic fifo */
+       LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, miireg);
+
+       LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x4c20);
+    }
+    else if (pDevice->Flags & JUMBO_CAPABLE_FLAG) 
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0007);
+        LM_ReadPhy(pDevice, BCM5401_AUX_CTRL, &miireg);
+        miireg |= 0x4000;    /* set rx extended packet length */
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, miireg);
+
+        LM_ReadPhy(pDevice, BCM540X_EXT_CTRL_REG, &miireg);
+        miireg |= 1;         /* set tx elastic fifo */
+        LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, miireg);
+
+    }
+
+    LM_SetEthWireSpeed(pDevice);
+    pDevice->PhyFlags &= ~PHY_FIBER_FALLBACK;
+}
+
+STATIC LM_VOID
+LM_SetEthWireSpeed(LM_DEVICE_BLOCK *pDevice)
+{
+    LM_UINT32 Value32;
+
+    if( pDevice->PhyFlags & PHY_IS_FIBER) 
+        return;
+
+    /* Enable Ethernet@WireSpeed. */
+    if (pDevice->PhyFlags & PHY_ETHERNET_WIRESPEED)
+    {
+        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;
+    }
+
+    LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG, &miireg);
+    pDevice->advertising1000 = miireg;
+
+    if (!(pDevice->PhyFlags & PHY_NO_GIGABIT))
+    {
+        if ((miireg & BCM540X_AN_AD_ALL_1G_SPEEDS) !=
+            BCM540X_AN_AD_ALL_1G_SPEEDS)
+        {
+            return LM_STATUS_FAILURE;
+        }
+    }else{
+        
+        if(miireg)
+        {
+            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);
+        REG_RD_BACK(pDevice, MacCtrl.MiMode);
+        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 < 200; j++)
+    {
+        MM_Wait(1);
+
+        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);
+        REG_RD_BACK(pDevice, MacCtrl.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);
+        REG_RD_BACK(pDevice, MacCtrl.MiMode);
+        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 < 200; j++)
+    {
+        MM_Wait(1);
+
+        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);
+        REG_RD_BACK(pDevice, MacCtrl.MiMode);
+        MM_Wait(40);
+    }
+} /* LM_WritePhy */
+
+STATIC void
+LM_GetPhyId(LM_DEVICE_BLOCK *pDevice)
+{
+    LM_UINT32 Value32;
+
+    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);
+
+}
+
+LM_STATUS
+LM_EnableMacLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->LoopBackMode = LM_MAC_LOOP_BACK_MODE;
+    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);
+    MM_Wait(40);    
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_DisableMacLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->LoopBackMode = 0;
+    
+    pDevice->MacMode &= ~(MAC_MODE_PORT_INTERNAL_LOOPBACK |
+            MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_MASK);
+    REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
+    MM_Wait(40); 
+    if(pDevice->PhyFlags & PHY_IS_FIBER)
+        LM_ResetPhy(pDevice);
+
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_EnablePhyLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->LoopBackMode = LM_PHY_LOOP_BACK_MODE;
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_DisablePhyLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->LoopBackMode = 0;
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_EnableExtLoopBack(PLM_DEVICE_BLOCK pDevice, LM_LINE_SPEED LineSpeed)
+{
+    pDevice->LoopBackMode = LM_EXT_LOOP_BACK_MODE;
+
+    pDevice->SavedDisableAutoNeg = pDevice->DisableAutoNeg;
+    pDevice->SavedRequestedLineSpeed = pDevice->RequestedLineSpeed;
+    pDevice->SavedRequestedDuplexMode = pDevice->RequestedDuplexMode;
+
+    pDevice->DisableAutoNeg = TRUE;
+    pDevice->RequestedLineSpeed = LineSpeed;
+    pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
+    LM_SetupPhy(pDevice);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+LM_DisableExtLoopBack(PLM_DEVICE_BLOCK pDevice)
+{
+    pDevice->LoopBackMode = 0;
+
+    pDevice->DisableAutoNeg = pDevice->SavedDisableAutoNeg;
+    pDevice->RequestedLineSpeed = pDevice->SavedRequestedLineSpeed;
+    pDevice->RequestedDuplexMode = pDevice->SavedRequestedDuplexMode;
+
+    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;
+    PLM_DEVICE_BLOCK pDevice2 = 0;
+    int j; 
+#endif
+    LM_UINT32 Value32;
+    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);
+
+        Value32 = REG_RD(pDevice, Grc.LocalCtrl);
+
+       if(T3_ASIC_5752(pDevice->ChipRevId)){
+            Value32 |= (GRC_MISC_LOCAL_CTRL_GPIO_OE3 |
+                        GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT3 | 
+                       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);
+        }
+        else
+        {
+            Value32 &= ~(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);
+        }
+
+        RAW_REG_WR(pDevice, Grc.LocalCtrl, Value32); 
+
+        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->TbiFlags & ENABLE_TBI_FLAG))
+    {
+        pDevice->RequestedLineSpeed = LM_LINE_SPEED_10MBPS;
+        LM_SetupPhy(pDevice);
+    }
+
+    /* Put the driver in the initial state, and go through the power down */
+    /* sequence. */
+    LM_DoHalt(pDevice);
+
+    if (!(pDevice->AsfFlags & ASF_ENABLED))
+    {
+        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->TbiFlags & ENABLE_TBI_FLAG))
+        {
+            LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x5a);
+            MM_Wait(40);
+        }
+
+        if (! T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId))
+        {
+            /* Let boot code deal with LED mode on shasta */
+            REG_WR(pDevice, MacCtrl.LedCtrl, pDevice->LedCtrl);
+        }
+
+        if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+        {
+            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->LedCtrl == LED_CTRL_PHY_MODE_2 ||
+                    pDevice->WolSpeed == WOL_SPEED_10MB)
+                {
+                    Value32 |= MAC_MODE_LINK_POLARITY;
+                }
+            }
+            else
+            {
+                Value32 |= MAC_MODE_LINK_POLARITY;
+            }
+        }
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+        REG_RD_BACK(pDevice, MacCtrl.Mode);
+        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;
+        }
+
+#ifdef BCM_ASF
+        if (pDevice->AsfFlags & ASF_ENABLED)
+        {
+            Value32 &= ~MAC_MODE_ACPI_POWER_ON_ENABLE;
+        }
+#endif
+        REG_WR(pDevice, MacCtrl.Mode, Value32);
+
+        /* Enable the receiver. */
+        REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_ENABLE);
+    }
+    else if (!(pDevice->AsfFlags & ASF_ENABLED))
+    {
+        if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+        {
+            REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED |
+                LED_CTRL_OVERRIDE_TRAFFIC_LED);
+        }
+        else
+        {
+            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_IS_5705_BEYOND(pDevice->ChipRevId) ) 
+            {
+                LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_LOWER_POWER_MODE);
+            }
+        }
+    }
+
+    /* Disable tx/rx clocks, and select an alternate clock. */
+    if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId)){
+        /* Do nothing */
+    }
+    else 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);
+    }
+    /* ASF on 5750 will not run properly on slow core clock */
+    else if( !(T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId)  && 
+                (pDevice->AsfFlags & ASF_ENABLED) ))   
+    { 
+        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_IS_5705_BEYOND(pDevice->ChipRevId) )
+        {
+            Value32 = T3_PCI_625_CORE_CLOCK;
+        }
+        else
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK;
+        }
+        RAW_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_IS_5705_BEYOND(pDevice->ChipRevId) )
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_625_CORE_CLOCK;
+        }
+        else if(!T3_ASIC_5714_FAMILY(pDevice->ChipRevId))
+        {
+            Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_44MHZ_CORE_CLOCK;
+        }
+
+        RAW_REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl | Value32);
+
+        if (!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+        {
+            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;
+            }
+
+            RAW_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->Flags & EEPROM_WP_FLAG))
+    {
+        LM_SwitchVaux(pDevice, pDevice2);
+    }
+
+    LM_WritePostResetSignatures(pDevice, LM_SHUTDOWN_RESET);
+
+    /* Workaround for pll instability */
+    if((T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5750_AX) ||
+        (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5750_BX)) {
+
+        Value32= REG_RD_OFFSET(pDevice, 0x7d00);
+        REG_WR_OFFSET(pDevice, 0x7d00,Value32 & ~(BIT_16 | BIT_4 | BIT_2 | BIT_1 | BIT_0)); 
+
+        if(!(pDevice->AsfFlags & ASF_ENABLED)) 
+            LM_HaltCpu(pDevice, T3_RX_CPU_ID);
+        
+    }
+
+    /* Put the the hardware in low power mode. */
+    if (!(pDevice->Flags & DISABLE_D3HOT_FLAG))
+    {
+        MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl);
+        MM_Wait(200); /* Wait 200us for state transition */
+    }
+
+    pDevice->PowerLevel = PowerLevel;
+
+#else
+    LM_WritePostResetSignatures(pDevice, LM_SHUTDOWN_RESET);
+#endif /* BCM_WOL */
+
+    return LM_STATUS_SUCCESS;
+} /* LM_SetPowerState */
+
+
+LM_VOID
+LM_SwitchVaux(PLM_DEVICE_BLOCK pDevice, PLM_DEVICE_BLOCK pDevice2)
+{
+    if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId))
+        return;
+
+    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);
+
+    /* Switch adapter to auxilliary power if WOL enabled */
+    if ((pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) ||
+        (pDevice->AsfFlags & ASF_ENABLED) ||
+        (pDevice2 && ((pDevice2->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) ||
+        (pDevice2->AsfFlags & ASF_ENABLED))))
+    {
+        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. */
+            RAW_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;
+            }
+
+            /* On NICs GPIOs are used for vaux.
+               The transition of GPIO0 from 0-1 causes vaux
+               to power up. Transition of GPIO1 from 1-0 turns vaux off.
+               GPIO2 transition from 1-0 enables a non-glitch vaux
+               transition from one state to another. 
+               On certain designs we should not output GPIO2.
+            */
+            if(pDevice->Flags & GPIO2_DONOT_OUTPUT)
+            {
+                /* GPIO0 = 0, GPIO1 = 1. */
+                RAW_REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+
+                MM_Wait(40);
+
+                /* GPIO0 = 1, GPIO1 = 1. */
+                RAW_REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OE0 |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 |
+                    GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+
+                MM_Wait(40);
+            }
+            else
+            {
+
+                /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */
+                RAW_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. */
+                RAW_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. */
+                RAW_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);
+            } /* GPIO2 OK */
+        }        /* Not 5700||5701 */
+    }                /* WOL disabled */
+    else       
+    {
+        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 */
+            RAW_REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                       GRC_MISC_LOCAL_CTRL_GPIO_OE1 |
+                         GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1);
+            MM_Wait(40);
+
+            /* GPIO1 = 0 */
+            RAW_REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl |
+                            GRC_MISC_LOCAL_CTRL_GPIO_OE1);
+            MM_Wait(40);
+
+            /* GPIO1 = 1 */
+            RAW_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)
+    {
+        if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
+            (pDevice->PhyFlags & PHY_IS_FIBER)) {
+
+            /* 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_1000XPAUSE; 
+            }
+            else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+            {
+                Value32 |= PHY_AN_AD_1000XPSE_ASYM;
+            }
+            else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)
+            {
+                Value32 |= (PHY_AN_AD_1000XPSE_ASYM |  PHY_AN_AD_1000XPAUSE);
+            }
+
+        }else{
+
+            /* 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, PhyReg18;
+    LM_UINT32 Cnt;
+
+    /* Get the interface type, line speed, and duplex mode. */
+    LineSpeed = pDevice->RequestedLineSpeed;
+    DuplexMode = pDevice->RequestedDuplexMode;
+
+    /* Exit ext. loop back, in case it was in ext. loopback mode */
+    /* Set Extended packet length bit on chips that support jumbo frames */
+    if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x4c20);
+
+        LM_ReadPhy(pDevice, BCM540X_EXT_CTRL_REG, &Value32);
+        Value32 |= 1;         /* set tx elastic fifo */
+        LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, Value32);
+
+    }
+    else
+    {
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0007);
+        LM_ReadPhy(pDevice, BCM5401_AUX_CTRL, &PhyReg18);
+        PhyReg18 &= ~0x8000;       /* clear external loop back */
+
+        if (pDevice->Flags & JUMBO_CAPABLE_FLAG)
+        {
+            PhyReg18 |= 0x4000;    /* set extended packet length */
+            LM_ReadPhy(pDevice, BCM540X_EXT_CTRL_REG, &Value32);
+            Value32 |= 1;         /* set tx elastic fifo */
+            LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, Value32);
+        }
+        LM_WritePhy(pDevice, BCM5401_AUX_CTRL, PhyReg18);
+    }
+
+#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->PhyFlags & PHY_NO_GIGABIT))
+        {
+            Value32 = BCM540X_AN_AD_ALL_1G_SPEEDS;
+
+#ifdef 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
+       {
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0);
+            pDevice->advertising1000 = 0;
+       }
+    }
+    else
+    {
+        if ((pDevice->PhyFlags & PHY_NO_GIGABIT) &&
+            (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;
+            }
+
+#ifdef INCLUDE_5701_AX_FIX
+            if ((pDevice->LoopBackMode == LM_EXT_LOOP_BACK_MODE) ||
+                (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 ||
+                pDevice->ChipRevId == T3_CHIP_ID_5701_B0))
+#else
+            if (pDevice->LoopBackMode == LM_EXT_LOOP_BACK_MODE)
+#endif
+            {
+                Value32 |= BCM540X_CONFIG_AS_MASTER |
+                    BCM540X_ENABLE_CONFIG_AS_MASTER;
+            }
+            LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32);
+            pDevice->advertising1000 = Value32;
+            if (pDevice->LoopBackMode == LM_EXT_LOOP_BACK_MODE)
+            {
+                if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+                {
+                    LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x8c20);
+                }
+                else
+                {
+                    LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0007);
+                    LM_ReadPhy(pDevice, BCM5401_AUX_CTRL, &PhyReg18);
+                    PhyReg18 |= 0x8000;    /* set loop back */
+                    LM_WritePhy(pDevice, BCM5401_AUX_CTRL, PhyReg18);
+                }
+            }
+        }
+        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;
+
+#ifdef 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);
+          REG_RD_BACK(pDevice,rxCpu.reg.PC);
+          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);
+          REG_RD_BACK(pDevice,txCpu.reg.PC);
+          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;
+    LM_STATUS status;
+
+    status = LM_STATUS_SUCCESS;
+
+    if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId) &&
+        !(cpu_number & T3_RX_CPU_ID))
+    {
+        return status;
+    }
+
+    if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701))
+    {
+        status = LM_NVRAM_AcquireLock(pDevice);
+    }
+
+    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);
+        REG_RD_BACK(pDevice,rxCpu.reg.mode);
+        MM_Wait(10);
+
+        if (i == 10000)
+            status = LM_STATUS_FAILURE;
+    }
+
+    if ((pDevice->Flags & T3_HAS_TWO_CPUS) &&
+        (cpu_number & T3_TX_CPU_ID))
+    {
+        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;
+        }
+
+        if (i == 10000)
+            status = LM_STATUS_FAILURE;
+    }
+
+    if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
+        (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701))
+    {
+        if (status != LM_STATUS_SUCCESS)
+        {
+            /*
+             * Some part of this operation failed.
+             * Just undo our own actions.
+             */
+            LM_NVRAM_ReleaseLock(pDevice);
+        }
+        else if (!(pDevice->Flags & T3_HAS_TWO_CPUS) ||
+                 cpu_number == (T3_TX_CPU_ID | T3_RX_CPU_ID))
+        {
+            /*
+             * Release our NVRAM arbitration grant along
+             * with the firmware's arbitration request bit.
+             */
+            REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1 | SW_ARB_REQ_CLR0);
+            REG_RD_BACK(pDevice, Nvram.SwArb);
+        }
+        else
+        {
+            LM_NVRAM_ReleaseLock(pDevice);
+
+            if (LM_NVRAM_AcquireLock(pDevice) == LM_STATUS_SUCCESS)
+            {
+                /* All is well. Release the arbitration and continue. */
+                LM_NVRAM_ReleaseLock(pDevice);
+            }
+            else
+            {
+                /*
+                 * We've timed out while attempting to get the
+                 * NVRAM arbitration.  Assume the cause is that
+                 * the NVRAM has requested arbitration after we
+                 * acquired arbitration the first time, but before
+                 * the CPU was actually halted.
+                 */
+
+                /*
+                 * Release our NVRAM arbitration grant along
+                 * with the firmware's arbitration request bit.
+                 */
+                REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1 | SW_ARB_REQ_CLR0);
+                REG_RD_BACK(pDevice, Nvram.SwArb);
+            }
+        }
+    }
+
+    return status;
+}
+
+
+LM_STATUS
+LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec)
+{
+       int j;
+       int ret = LM_STATUS_SUCCESS;
+
+       if(BlinkDurationSec == 0)
+       {
+               BlinkDurationSec = 1;
+        }
+       if(BlinkDurationSec > 120)
+        {
+               BlinkDurationSec = 120;
+       }
+
+       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);
+               }
+                if (MM_Sleep(pDevice, 500) != LM_STATUS_SUCCESS)/* 0.5 second */
+                {
+                    ret = LM_STATUS_FAILURE;
+                    break;
+                }
+       }
+       REG_WR(pDevice, MacCtrl.LedCtrl, pDevice->LedCtrl);
+       return ret;
+}
+
+LM_STATUS
+LM_SwitchClocks(PLM_DEVICE_BLOCK pDevice)
+{
+    LM_UINT32 ClockCtrl;
+
+    if(T3_ASIC_5714_FAMILY(pDevice->ChipRevId))
+       return LM_STATUS_SUCCESS;
+
+    ClockCtrl = REG_RD(pDevice, PciCfg.ClockCtrl);
+    pDevice->ClockCtrl = ClockCtrl & (T3_PCI_FORCE_CLKRUN |
+        T3_PCI_CLKRUN_OUTPUT_EN | 0x1f);
+    if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        if (ClockCtrl & T3_PCI_625_CORE_CLOCK)
+        {
+            /* clear ALT clock first */
+            RAW_REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl |
+                T3_PCI_625_CORE_CLOCK);
+            MM_Wait(40);  /* required delay is 27usec */
+        }
+    }
+    else
+    {
+        if (ClockCtrl & T3_PCI_44MHZ_CORE_CLOCK)
+        {
+            RAW_REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl |
+                T3_PCI_44MHZ_CORE_CLOCK | T3_PCI_SELECT_ALTERNATE_CLOCK);
+            MM_Wait(40);  /* required delay is 27usec */
+            RAW_REG_WR(pDevice, PciCfg.ClockCtrl, pDevice->ClockCtrl |
+                T3_PCI_SELECT_ALTERNATE_CLOCK);
+            MM_Wait(40);  /* required delay is 27usec */
+        }
+    }
+
+    RAW_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 = 0x00000005; /* 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_16)
+                {
+                    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_IS_5705_BEYOND(pDevice->ChipRevId))
+    {
+        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 --git a/drivers/net/bcm5700/tigon3.h b/drivers/net/bcm5700/tigon3.h
new file mode 100644 (file)
index 0000000..b8ecad5
--- /dev/null
@@ -0,0 +1,3849 @@
+/******************************************************************************/
+/*                                                                            */
+/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2005 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. */
+/******************************************************************************/
+
+#ifndef TIGON3_DEBUG
+#define TIGON3_DEBUG   0
+#endif /* TIGON3_DEBUG */
+
+/* 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 */
+
+#ifndef T3_JUMBO_RCV_ENTRY_COUNT
+#define T3_JUMBO_RCV_ENTRY_COUNT       0
+#endif /* T3_JUMBO_RCV_ENTRY_COUNT */
+
+#ifndef T3_JUMBO_RCB_ENTRY_COUNT
+#define T3_JUMBO_RCB_ENTRY_COUNT       0
+#endif /* T3_JUMBO_RCB_ENTRY_COUNT */
+
+/* Maxim number of packet descriptors used for sending packets. */
+#define MAX_TX_PACKET_DESC_COUNT            T3_SEND_RCB_ENTRY_COUNT
+#define DEFAULT_TX_PACKET_DESC_COUNT        120
+
+/* 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            T3_STD_RCV_RCB_ENTRY_COUNT
+#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_MAC_MODE            BIT_NONE
+#define T3_NIC_CFG_LED_PHY_MODE_1          BIT_2
+#define T3_NIC_CFG_LED_PHY_MODE_2          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_BOTH_PORT_100MB_WOL_CAPABLE  BIT_15
+#define T3_NIC_GPIO2_NOT_AVAILABLE          BIT_20
+
+#define T3_NIC_DATA_VER                     0x0b5c
+#define T3_NIC_DATA_VER_SHIFT               16
+
+#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_NICDRV_ALIVE2                0x0d
+
+#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_START_DONE             0x80000001
+#define T3_DRV_STATE_UNLOAD                 0x02
+#define T3_DRV_STATE_UNLOAD_DONE            0x80000002
+#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
+
+#define T3_NIC_DATA_NIC_CFG_ADDR2           0x0d38 /* bit 2-3 are same as in */
+                                                   /* 0xb58 */
+#define T3_SHASTA_EXT_LED_MODE_MASK         (BIT_15 | BIT_16)
+#define T3_SHASTA_EXT_LED_LEGACY_MODE       BIT_NONE
+#define T3_SHASTA_EXT_LED_SHARED_TRAFFIC_LINK_MODE       BIT_15
+#define T3_SHASTA_EXT_LED_MAC_MODE          BIT_16
+#define T3_SHASTA_EXT_LED_WIRELESS_COMBO_MODE       (BIT_15 | BIT_16)
+#define T3_NIC_CFG_CAPACITIVE_COUPLING            BIT_17
+#define T3_NIC_CFG_PRESERVE_PREEMPHASIS           BIT_18
+
+/******************************************************************************/
+/* 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. */
+
+#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. */
+#ifdef BCM_NAPI_RXPOLL
+#define DEFAULT_RX_COALESCING_TICKS         18
+#define DEFAULT_RX_MAX_COALESCED_FRAMES     6
+#else
+#define DEFAULT_RX_COALESCING_TICKS         60
+#define DEFAULT_RX_MAX_COALESCED_FRAMES     15
+#endif
+
+#define DEFAULT_TX_COALESCING_TICKS         200
+#define DEFAULT_TX_MAX_COALESCED_FRAMES     35
+
+#define MAX_RX_COALESCING_TICKS             500
+#define MAX_TX_COALESCING_TICKS             500
+#define MAX_RX_MAX_COALESCED_FRAMES         100
+#define MAX_TX_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         120
+#define ADAPTIVE_LO_PKT_THRESH              52000
+#define ADAPTIVE_HI_PKT_THRESH              112000
+#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES    20
+#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES    75
+
+#ifdef BCM_NAPI_RXPOLL
+#define DEFAULT_RX_COALESCING_TICKS_DURING_INT          18
+#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT      6
+#else
+#define DEFAULT_RX_COALESCING_TICKS_DURING_INT          25
+#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT      2
+#endif
+#define DEFAULT_TX_COALESCING_TICKS_DURING_INT          25
+#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
+
+/* 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_SIZE32             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. */
+/******************************************************************************/
+/* MSI ENABLE bit is located at this offset */
+#define T3_PCI_MSI_ENABLE                   0x58
+
+#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_ID_BCM5705F                  0x166E14e4
+#define T3_PCI_ID_BCM5901                   0x170D14e4
+#define T3_PCI_ID_BCM5901A2                 0x170E14e4
+#define T3_PCI_ID_BCM5751F                  0x167E14e4
+
+#define T3_PCI_ID_BCM5753                   0x16f714e4
+#define T3_PCI_ID_BCM5753M                  0x16fd14e4
+#define T3_PCI_ID_BCM5753F                  0x16fe14e4
+#define T3_PCI_ID_BCM5781                   0x16dd14e4
+
+#define T3_PCI_ID_BCM5903M                  0x16ff14e4
+
+#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
+#define T3_CHIP_ID_5705_A2                  0x3002
+#define T3_CHIP_ID_5705_A3                  0x3003
+
+#define T3_CHIP_ID_5750_A0                  0x4000
+#define T3_CHIP_ID_5750_A1                  0x4001
+#define T3_CHIP_ID_5750_A3                  0x4003
+#define T3_CHIP_ID_5750_B0                  0x4010
+#define T3_CHIP_ID_5750_C0                  0x4200
+
+#define T3_CHIP_ID_5714_A0                  0x5000
+#define T3_CHIP_ID_5752_A0                  0x6000
+#define T3_CHIP_ID_5714                     0x8000
+
+
+/* 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
+#define T3_ASIC_REV_5750                    0x04
+#define T3_ASIC_REV_5714_A0                 0x05 /*5714,5715*/
+#define T3_ASIC_REV_5752                    0x06
+#define T3_ASIC_REV_5780                    0x08 /* 5780 previously htle */
+#define T3_ASIC_REV_5714                    0x09 /*5714,5715*/
+
+#define T3_ASIC_IS_5705_BEYOND(_ChipRevId)                 \
+   ((T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5705)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5750)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714_A0)    || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5780)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5752))       
+
+#define T3_ASIC_IS_575X_PLUS(_ChipRevId)                   \
+   ((T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5750)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714_A0)    || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5780)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5752))       
+
+#define T3_ASIC_5714_FAMILY(_ChipRevId)                    \
+   ((T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714_A0)   || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5780)      || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714))
+
+#define T3_ASIC_IS_JUMBO_CAPABLE(_ChipRevId)           \
+    ((T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5700)     || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5701)      || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5703)      || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714_A0)    || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5780)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5714)       || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5704))       
+
+#define T3_ASIC_5752(_ChipRevId)  \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5752)
+
+#define T3_ASIC_5705_OR_5750(_ChipRevId)              \
+    ((T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5705) || \
+    (T3_ASIC_REV(_ChipRevId) == T3_ASIC_REV_5750))
+
+/* 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
+#define T3_CHIP_REV_5703_AX                 0x10
+#define T3_CHIP_REV_5704_AX                 0x20
+#define T3_CHIP_REV_5704_BX                 0x21
+
+#define T3_CHIP_REV_5750_AX                 0x40
+#define T3_CHIP_REV_5750_BX                 0x41
+
+/* 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
+
+#define T3_MSI_CAPABILITY_ID_REG            0x58
+#define T3_MSI_NEXT_CAPABILITY_PTR          0x59
+
+/* 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
+
+#define T3_PCIE_CAPABILITY_ID_REG           0xD0
+#define T3_PCIE_CAPABILITY_ID               0x10
+
+#define T3_PCIE_CAPABILITY_REG              0xD2
+
+/******************************************************************************/
+/* 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
+
+/* Defines for 5714 family fiber on the 546x phy*/
+
+#define PHY_AN_AD_1000XFULL                            0x20
+#define PHY_AN_AD_1000XHALF                    0x40
+#define PHY_AN_AD_1000XPAUSE                   0x80
+#define PHY_AN_AD_1000XPSE_ASYM                0x100
+#define PHY_AN_AD_1000XREM_FAULT_OFFLINE        0x2000
+#define PHY_AN_AD_1000XREM_FAULT_AN_ERROR       0x3000
+
+#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_BCM5750_PHY_ID                          0x60008180
+#define PHY_BCM8002_PHY_ID                          0x60010140
+#define PHY_BCM5714_PHY_ID                          0x60008340
+#define PHY_BCM5780_PHY_ID                          0x60008350
+#define PHY_BCM5752_PHY_ID                          0x60008100
+
+#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_BCM5750_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5714_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5780_PHY_ID) && \
+                            (((x) & PHY_ID_MASK) != PHY_BCM5752_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;
+    #define PXC_MAX_READ_BYTE_COUNT_MASK               (BIT_3 | BIT_2)
+    #define PXC_MAX_READ_BYTE_COUNT_512                        (0)
+    #define PXC_MAX_READ_BYTE_COUNT_1024               (BIT_2)
+    #define PXC_MAX_READ_BYTE_COUNT_2048               (BIT_3)
+    #define PXC_MAX_READ_BYTE_COUNT_4096               (BIT_3 | BIT_2)
+
+    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_CMD                      0x70000000
+    #define DMA_CTRL_WRITE_BOUNDARY_64_PCIE         0x10000000
+    #define DMA_CTRL_WRITE_BOUNDARY_128_PCIE        0x30000000
+    #define DMA_CTRL_WRITE_BOUNDARY_DISABLE_PCIE    0x70000000
+    #define DMA_CTRL_READ_CMD                       0x06000000
+
+    /* bits 21:19 */
+    #define DMA_CTRL_WRITE_PCIE_H20MARK_128         0x00180000 
+    #define DMA_CTRL_WRITE_PCIE_H20MARK_256         0x00380000
+
+    #define DMA_CTRL_PCIX_READ_WATERMARK_MASK       (BIT_18 | BIT_17 | BIT_16)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_64         (0)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_128        (BIT_16)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_256        (BIT_17)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_384        (BIT_17 | BIT_16)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_512        (BIT_18)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_1024       (BIT_18 | BIT_16)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_1536X      (BIT_18 | BIT_17)
+    #define DMA_CTRL_PCIX_READ_WATERMARK_1536       (BIT_18 | BIT_17 | BIT_16)
+
+    #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_128_PCIX        BIT_11
+    #define DMA_CTRL_WRITE_BOUNDARY_32              BIT_12
+    #define DMA_CTRL_WRITE_BOUNDARY_256_PCIX        BIT_12
+    #define DMA_CTRL_WRITE_BOUNDARY_64              (BIT_12 | BIT_11)
+    #define DMA_CTRL_WRITE_BOUNDARY_384_PCIX        (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
+
+    #define DMA_CTRL_READ_BOUNDARY_MASK             (BIT_10 | BIT_9 | BIT_8)
+    #define DMA_CTRL_READ_BOUNDARY_DISABLE          0
+    #define DMA_CTRL_READ_BOUNDARY_16               BIT_8
+    #define DMA_CTRL_READ_BOUNDARY_128_PCIX         BIT_8
+    #define DMA_CTRL_READ_BOUNDARY_32               BIT_9
+    #define DMA_CTRL_READ_BOUNDARY_256_PCIX         BIT_9
+    #define DMA_CTRL_READ_BOUNDARY_64               (BIT_9 | BIT_8)
+    #define DMA_CTRL_READ_BOUNDARY_384_PCIX         (BIT_9 | BIT_8)
+    #define DMA_CTRL_READ_BOUNDARY_128              BIT_10
+    #define DMA_CTRL_READ_BOUNDARY_256              (BIT_10 | BIT_8)
+    #define DMA_CTRL_READ_BOUNDARY_512              (BIT_10 | BIT_9)
+    #define DMA_CTRL_READ_BOUNDARY_1024             (BIT_10 | BIT_9 | BIT_8)
+
+    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];                      /* 0xb0-0xb7 */
+
+    T3_32BIT_REGISTER DualMacCtrl;                     /* 0xb8 */
+    #define T3_DUAL_MAC_CH_CTRL_MASK     (BIT_1 | BIT_0)
+    #define T3_DUAL_MAC_ID               BIT_2
+
+    T3_32BIT_REGISTER MacMessageExchangeOutput;                /*  0xbc  */
+    T3_32BIT_REGISTER MacMessageExchangeInput;         /*  0xc0  */
+
+    T3_32BIT_REGISTER FunctionEventMask;               /*  0xc4  */
+
+    T3_32BIT_REGISTER Unused6[4];                      /*  0xc8-0xd7  */
+
+    T3_32BIT_REGISTER DeviceCtrl;                      /*  0xd8  */
+    #define MAX_PAYLOAD_SIZE_MASK                      0x0e0
+
+    LM_UINT8 Unused7[36];
+
+} 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_SHASTA_MAC_MODE                    BIT_13
+    #define LED_CTRL_SHARED_TRAFFIC_LINK                BIT_14
+    #define LED_CTRL_WIRELESS_COMBO                     BIT_15
+    #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
+    #define MI_STATUS_10MBPS                            BIT_1
+
+    /* 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;
+    #define T3_DISABLE_LONG_BURST_READ_DYN_FIX              BIT_22
+
+    /* 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_MULTI_SPLIT_ENABLE            BIT_11
+    #define DMA_READ_MODE_MULTI_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_BD_ID_5788                         0x00010000
+    #define GRC_MISC_BD_ID_5788M                        0x00018000
+    #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_INPUT3            BIT_5
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OE3               BIT_6
+    #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT3           BIT_7
+
+    #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
+    #define NVRAM_CMD_WRITE_ENABLE                           BIT_16
+    #define NVRAM_CMD_WRITE_DISABLE                          BIT_17
+    #define NVRAM_CMD_EN_WR_SR                             BIT_18
+    #define NVRAM_CMD_DO_WR_SR                             BIT_19
+
+    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_STATUS_BITS_MASK            (BIT_4 | BIT_5 | BIT_6)
+    #define FLASH_SIZE                                  BIT_25
+    #define FLASH_COMPAT_BYPASS                         BIT_31
+    #define FLASH_VENDOR_MASK                  (BIT_25 | BIT_24 | BIT_1 | BIT_0)
+    #define FLASH_VENDOR_ATMEL_EEPROM                        BIT_25
+    #define FLASH_VENDOR_ATMEL_FLASH_BUFFERED       (BIT_25 | BIT_1 | BIT_0)
+    #define FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED          (BIT_1 | BIT_0)
+    #define FLASH_VENDOR_ST                        (BIT_25 | BIT_24 | BIT_0)
+    #define FLASH_VENDOR_SAIFUN                     (BIT_24 | BIT_1 | BIT_0)
+    #define FLASH_VENDOR_SST_SMALL                           BIT_0
+    #define FLASH_VENDOR_SST_LARGE                      (BIT_25 | BIT_0)
+
+    #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
+
+    /* Bleh!  Definitions for Baxter. */
+    #define FLASH_PART_5750_TYPEMASK \
+            (BIT_25 | BIT_24 | BIT_1 | BIT_0)
+
+    #define FLASH_PART_5752_TYPEMASK \
+            (BIT_25 | BIT_24 | BIT_23 | BIT_22 | BIT_1 | BIT_0)
+
+    #define FLASH_PART_5752_EEPROM_ATMEL_64K        BIT_NONE
+    #define FLASH_PART_5752_EEPROM_ATMEL_376K       BIT_25
+    #define FLASH_PART_5752_FLASH_ATMEL_AT45DB041   (BIT_25 | BIT_1 | BIT_0)
+    #define FLASH_PART_5752_FLASH_ATMEL_AT25F512             (BIT_1 | BIT_0)
+    #define FLASH_PART_5752_FLASH_SST_45VF010       (BIT_25 |         BIT_0)
+    #define FLASH_PART_5752_FLASH_SST_25F512                         (BIT_0)
+    #define FLASH_PART_5752_FLASH_ST_M25P10A           (BIT_25 | BIT_24 | BIT_0)
+    #define FLASH_PART_5752_FLASH_ST_M25P05A                  (BIT_24 | BIT_0)
+    #define FLASH_PART_5752_FLASH_SAIFUN_SA25F010            (BIT_22)
+    #define FLASH_PART_5752_FLASH_SAIFUN_SA25F020          (BIT_22 | BIT_1)
+    #define FLASH_PART_5752_FLASH_SAIFUN_SA25F040          (BIT_22 | BIT_0)
+    #define FLASH_PART_5752_FLASH_SST_25VF010              (BIT_24 | BIT_22)
+    #define FLASH_PART_5752_FLASH_SST_25VF020          (BIT_24 | BIT_22 | BIT_1)
+    #define FLASH_PART_5752_FLASH_SST_25VF040          (BIT_24 | BIT_22 | BIT_0)
+    #define FLASH_PART_5752_FLASH_ST_M45PE10           (BIT_25 | BIT_22)
+    #define FLASH_PART_5752_FLASH_ST_M45PE20           (BIT_25 | BIT_22 | BIT_1)
+    #define FLASH_PART_5752_FLASH_ST_M45PE40           (BIT_25 | BIT_22 | BIT_0)
+
+    #define FLASH_PART_5752_PAGEMASK \
+            (BIT_30 | BIT_29 | BIT_28)
+
+    #define FLASH_PART_5752_PAGE_SIZE_256B         BIT_NONE
+    #define FLASH_PART_5752_PAGE_SIZE_512B         BIT_28
+    #define FLASH_PART_5752_PAGE_SIZE_1K           BIT_29
+    #define FLASH_PART_5752_PAGE_SIZE_2K          (BIT_29 | BIT_28)
+    #define FLASH_PART_5752_PAGE_SIZE_4K           BIT_30
+    #define FLASH_PART_5752_PAGE_SIZE_264B        (BIT_30 | BIT_28)
+
+
+    T3_32BIT_REGISTER Config2;
+    #define NVRAM_COMMAND_MASK                             0x000000ff
+    #define NVRAM_STATUS_COMMAND(x)                        ((x) << 16)
+    #define NVRAM_ERASE_COMMAND(x)                             (x)
+
+    T3_32BIT_REGISTER Config3;
+    #define NVRAM_COMMAND_MASK                             0x000000ff
+    #define NVRAM_READ_COMMAND(x)                          ((x) << 24)
+    #define NVRAM_WRITE_UNBUFFERED_COMMAND(x)              ((x) << 8)
+    #define NVRAM_WRITE_BUFFERED_COMMAND(x)                ((x) << 16)
+    #define NVRAM_RESET_COMMAND(x)                             (x)
+
+    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
+
+    T3_32BIT_REGISTER NvmAccess;
+    #define ACCESS_EN                                   BIT_0
+    #define ACCESS_WR_EN                                BIT_1
+    #define NVRAM_ACCESS_ENABLE                         BIT_0
+    #define NVRAM_ACCESS_WRITE_ENABLE                   BIT_1
+
+    T3_32BIT_REGISTER Write1;
+    #define NVRAM_WRITE1_WRENA_CMD(x)         (x)
+    #define NVRAM_WRITE1_WRDIS_CMD(x)       ((x) << 8)
+
+    T3_32BIT_REGISTER WatchTimer;
+
+    T3_32BIT_REGISTER Config4;
+
+    /* Unused space. */
+    LM_UINT8 Unused[972];
+} 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;
+
+
+/******************************************************************************/
+/* Flash info. */
+/******************************************************************************/
+
+typedef struct {
+    LM_UINT8  jedecnum;
+    LM_UINT8  romtype;
+    #define ROM_TYPE_EEPROM  0x1
+    #define ROM_TYPE_FLASH   0x2
+    LM_BOOL   buffered;
+
+    LM_UINT32 chipsize;
+    LM_UINT32 pagesize;
+} FLASHINFO;
+
+
+#define JEDEC_ATMEL    0x1f
+#define JEDEC_ST       0x20
+#define JEDEC_SAIFUN   0x4f
+#define JEDEC_SST      0xbf
+
+#define ATMEL_AT24C64_CHIP_SIZE                   (64 * 1024)
+#define ATMEL_AT24C64_PAGE_SIZE                     (32)
+#define ATMEL_AT24C64_PAGE_MASK        (ATMEL_AT24C64_PAGE_SIZE - 1)
+
+#define ATMEL_AT24C512_CHIP_SIZE                 (512 * 1024)
+#define ATMEL_AT24C512_PAGE_SIZE                    (128)
+#define ATMEL_AT24C512_PAGE_MASK        (ATMEL_AT24C512_PAGE_SIZE - 1)
+
+#define ATMEL_AT45DB0X1B_PAGE_POS                        9
+#define ATMEL_AT45DB0X1B_PAGE_SIZE                      264
+#define ATMEL_AT45DB0X1B_PAGE_MASK                      0x1ff
+#define ATMEL_AT45DB0X1B_BUFFER_WRITE_CMD               0x83
+
+/* Currently unsupported flash type */
+#define ATMEL_AT25F512_PAGE_SIZE                        256
+#define ATMEL_AT25F512_PAGE_MASK        (ATMEL_AT25F512_PAGE_SIZE - 1)
+
+#define ST_M45PEX0_PAGE_SIZE                            256
+#define ST_M45PEX0_PAGE_MASK                (ST_M45PEX0_PAGE_SIZE - 1)
+#define ST_M45PEX0_READ_STATUS_CMD                      0x05
+#define ST_M45PEX0_PAGE_ERASE_CMD                       0xDB
+#define ST_M45PEX0_PAGE_PRGM_CMD                        0x0A
+#define ST_M45PEX0_WRENA_CMD                            0x06
+#define ST_M45PEX0_WRDIS_CMD                            0x04
+
+#define SAIFUN_SA25F0XX_PAGE_SIZE                       256
+#define SAIFUN_SA25F0XX_PAGE_MASK         (SAIFUN_SA25F0XX_PAGE_SIZE - 1)
+#define SAIFUN_SA25F0XX_READ_STATUS_CMD                 0x05
+#define SAIFUN_SA25F0XX_PAGE_ERASE_CMD                  0x81
+#define SAIFUN_SA25F0XX_PAGE_WRITE_CMD                  0x02
+#define SAIFUN_SA25F0XX_WRENA_CMD                       0x06
+
+/* Currently unsupported flash type */
+#define SST_25VF0X0_PAGE_SIZE                           4098
+#define SST_25VF0X0_PAGE_MASK                (SST_25VF0X0_PAGE_SIZE - 1)
+
+
+/******************************************************************************/
+/* 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;
+#endif
+        } Tx;
+
+        /* Receive info. */
+        struct {
+            /* This descriptor belongs to either Std, Mini, or Jumbo ring. */
+            LM_UINT16 RcvProdRing;
+            LM_UINT16 RcvRingProdIdx;
+
+            /* 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 DmaReadFifoSize;
+    LM_UINT32 GrcMode;
+
+    LM_UINT32 PowerLevel;
+
+    LM_UINT32 Flags;
+
+    #define MINI_PCI_FLAG              0x1
+    #define PCI_EXPRESS_FLAG           0x2
+    #define BCM5788_FLAG               0x4
+    #define FIBER_WOL_CAPABLE_FLAG     0x8
+    #define WOL_LIMIT_10MBPS_FLAG      0x10
+    #define ENABLE_MWI_FLAG            0x20
+    #define USE_TAGGED_STATUS_FLAG     0x40
+
+    /* NIC will not compute the pseudo header checksum.  The driver or OS */
+    /* must seed the checksum field with the pseudo checksum. */
+    #define NO_TX_PSEUDO_HDR_CSUM_FLAG 0x80
+
+    /* 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. */
+    #define NO_RX_PSEUDO_HDR_CSUM_FLAG 0x100
+
+    #define ENABLE_PCIX_FIX_FLAG       0x200
+
+    #define TX_4G_WORKAROUND_FLAG      0x400
+    #define UNDI_FIX_FLAG              0x800
+    #define FLUSH_POSTED_WRITE_FLAG    0x1000
+    #define REG_RD_BACK_FLAG           0x2000
+
+    /* Use NIC or Host based send BD. */
+    #define NIC_SEND_BD_FLAG           0x4000
+
+    /* Athlon fix. */
+    #define DELAY_PCI_GRANT_FLAG       0x8000
+
+    /* Enable OneDmaAtOnce */
+    #define ONE_DMA_AT_ONCE_FLAG       0x10000
+
+    /* Enable PCI-X multi split */
+    #define MULTI_SPLIT_ENABLE_FLAG    0x20000
+
+    #define RX_BD_LIMIT_64_FLAG        0x40000
+
+    #define DMA_WR_MODE_RX_ACCELERATE_FLAG 0x80000
+
+    /* write protect */
+    #define EEPROM_WP_FLAG             0x100000
+    #define FLASH_DETECTED_FLAG        0x200000
+
+    #define DISABLE_D3HOT_FLAG         0x400000
+
+    /* 5753 should not output gpio2 */
+    #define GPIO2_DONOT_OUTPUT         0x800000
+
+    #define USING_MSI_FLAG             0x1000000 
+    #define JUMBO_CAPABLE_FLAG         0x2000000 
+    #define PROTECTED_NVRAM_FLAG       0x4000000
+    #define T3_HAS_TWO_CPUS            0x8000000
+    #define HOST_COALESCING_BUG_FIX    0x10000000
+
+    /* 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;
+
+    LM_PACKET *RxStdRing[T3_STD_RCV_RCB_ENTRY_COUNT];
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    LM_PACKET *RxJumboRing[T3_JUMBO_RCV_RCB_ENTRY_COUNT];
+#endif
+
+    /* 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 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];
+    LM_PACKET *SendRing[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;
+
+    /* 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;
+
+    /* interrupt status tag */
+    LM_UINT32 LastTag;
+
+    /* 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;
+    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;
+
+    LM_UINT32 AutoNegJustInited;
+
+    /* 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
+
+    LM_UINT32 LedCtrl;
+
+    /* WOL Speed */
+    LM_UINT32 WolSpeed;
+    #define WOL_SPEED_10MB                              1
+    #define WOL_SPEED_100MB                             2
+
+    LM_UINT32 PhyFlags;
+    #define PHY_RESET_ON_INIT                           0x01
+    #define PHY_RESET_ON_LINKDOWN                       0x02
+    #define PHY_ADC_FIX                                 0x04
+    #define PHY_CHECK_TAPS_AFTER_RESET                  0x08
+    #define PHY_5704_A0_FIX                             0x10
+    #define PHY_ETHERNET_WIRESPEED                      0x20
+    #define PHY_5705_5750_FIX                           0x40
+    #define PHY_NO_GIGABIT                              0x80
+    #define PHY_CAPACITIVE_COUPLING                     0x100
+    #define PHY_IS_FIBER                                0x200
+    #define PHY_FIBER_FALLBACK                          0x400
+
+
+    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 LoopBackMode;
+
+#define LM_MAC_LOOP_BACK_MODE 1
+#define LM_PHY_LOOP_BACK_MODE 2
+#define LM_EXT_LOOP_BACK_MODE 3
+
+    LM_LINE_SPEED SavedRequestedLineSpeed;
+    LM_DUPLEX_MODE SavedRequestedDuplexMode;
+    LM_UINT32 SavedDisableAutoNeg;
+
+    LM_UINT32 MulticastHash[4];
+
+    LM_UINT32 AsfFlags;
+
+#define ASF_ENABLED         1
+#define ASF_NEW_HANDSHAKE   2 /* if set, this bit implies ASF enabled as well */
+
+    /* Split Mode flags */
+    LM_UINT32 SplitModeMaxReq;
+
+    #define SPLIT_MODE_5704_MAX_REQ                     3
+
+    /* 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_UINT32 MbufBase;
+    LM_UINT32 MbufSize;
+
+    LM_UINT32 NvramSize;
+
+#if INCLUDE_TBI_SUPPORT
+    /* Autoneg state info. */
+    AN_STATE_INFO AnInfo;
+
+    LM_UINT32 TbiFlags;
+    /* set if we have a SERDES PHY. */
+    #define ENABLE_TBI_FLAG            0x1
+    #define TBI_POLLING_INTR_FLAG      0x2
+    #define TBI_PURE_POLLING_FLAG      0x4
+    #define TBI_POLLING_FLAGS   (TBI_POLLING_INTR_FLAG | TBI_PURE_POLLING_FLAG)
+    #define TBI_DO_PREEMPHASIS         0x8
+
+    LM_UINT32 IgnoreTbiLinkChange;
+#endif
+#ifdef BCM_NAPI_RXPOLL
+    volatile LM_UINT32 RxPoll;
+#endif
+    char PartNo[24];
+    char BootCodeVer[16];
+    char IPMICodeVer[24];
+    char BusSpeedStr[24];
+
+    FLASHINFO flashinfo;
+    LM_UINT8  flashbuffer[256];
+} 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_RegRdBack(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)->Flags & UNDI_FIX_FLAG) ?                                      \
+        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)->Flags & UNDI_FIX_FLAG) ?                                     \
+        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_RD_BACK(pDevice, OffsetName)                                    \
+    LM_RegRdBack(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 */
+