summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package/broadcom-57xx/Makefile51
-rw-r--r--package/broadcom-57xx/src/5701rls.c46
-rw-r--r--package/broadcom-57xx/src/5701rls.h198
-rw-r--r--package/broadcom-57xx/src/Makefile17
-rw-r--r--package/broadcom-57xx/src/autoneg.c438
-rw-r--r--package/broadcom-57xx/src/autoneg.h418
-rw-r--r--package/broadcom-57xx/src/b57um.c5563
-rw-r--r--package/broadcom-57xx/src/bcmendian.h198
-rw-r--r--package/broadcom-57xx/src/bcmparams.h25
-rw-r--r--package/broadcom-57xx/src/bcmrobo.c1329
-rw-r--r--package/broadcom-57xx/src/bcmrobo.h70
-rw-r--r--package/broadcom-57xx/src/bits.h61
-rw-r--r--package/broadcom-57xx/src/fw_lso05.h289
-rw-r--r--package/broadcom-57xx/src/fw_stkoffld.h519
-rw-r--r--package/broadcom-57xx/src/hndgige.c146
-rw-r--r--package/broadcom-57xx/src/hndgige.h20
-rw-r--r--package/broadcom-57xx/src/lm.h483
-rw-r--r--package/broadcom-57xx/src/mm.h609
-rw-r--r--package/broadcom-57xx/src/proto/802.11.h1387
-rw-r--r--package/broadcom-57xx/src/proto/802.11e.h123
-rw-r--r--package/broadcom-57xx/src/proto/802.1d.h38
-rw-r--r--package/broadcom-57xx/src/proto/802.3.h20
-rw-r--r--package/broadcom-57xx/src/proto/bcmarp.h60
-rw-r--r--package/broadcom-57xx/src/proto/bcmdhcp.h36
-rw-r--r--package/broadcom-57xx/src/proto/bcmeth.h101
-rw-r--r--package/broadcom-57xx/src/proto/bcmevent.h166
-rw-r--r--package/broadcom-57xx/src/proto/bcmip.h152
-rw-r--r--package/broadcom-57xx/src/proto/bcmtcp.h68
-rw-r--r--package/broadcom-57xx/src/proto/bcmudp.h48
-rw-r--r--package/broadcom-57xx/src/proto/eap.h45
-rw-r--r--package/broadcom-57xx/src/proto/eapol.h179
-rw-r--r--package/broadcom-57xx/src/proto/ethernet.h173
-rw-r--r--package/broadcom-57xx/src/proto/vlan.h52
-rw-r--r--package/broadcom-57xx/src/proto/wpa.h158
-rw-r--r--package/broadcom-57xx/src/queue.h347
-rw-r--r--package/broadcom-57xx/src/robo_register.c111
-rw-r--r--package/broadcom-57xx/src/sbgige.h59
-rw-r--r--package/broadcom-57xx/src/tcp_seg.c106
-rw-r--r--package/broadcom-57xx/src/tigon3.c9736
-rw-r--r--package/broadcom-57xx/src/tigon3.h3882
40 files changed, 27527 insertions, 0 deletions
diff --git a/package/broadcom-57xx/Makefile b/package/broadcom-57xx/Makefile
new file mode 100644
index 0000000000..172074ca35
--- /dev/null
+++ b/package/broadcom-57xx/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 8694 2007-09-08 19:55:42Z nbd $
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=broadcom-57xx
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/brcm-57xx
+ SUBMENU:=Network Devices
+ DEPENDS:=@TARGET_brcm_2_4 +kmod-switch
+ TITLE:=Broadcom 57xx ethernet support
+ FILES:=$(PKG_BUILD_DIR)/bcm57xx.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call AutoLoad,30,bcm57xx)
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+ifeq ($(BOARD),brcm-2.4)
+ BUILDFLAGS = -DBCMDRIVER -I$(LINUX_DIR)/arch/mips/bcm947xx/include -I$(STAGING_DIR)/usr/include
+ BUILDFLAGS += -DDBG=0 -DBCM_PROC_FS=1 -DT3_JUMBO_RCV_RCB_ENTRY_COUNT=256 -DNICE_SUPPORT
+ BUILDFLAGS += -DPCIX_TARGET_WORKAROUND=1 -DINCLUDE_TBI_SUPPORT=1 -DINCLUDE_5701_AX_FIX=1
+endif
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(BUILDFLAGS)" \
+ modules
+endef
+
+define KernelPackage/brcm-57xx/install
+ $(call Package/brcm-57xx/install/Default,$(1))
+ #$(INSTALL_DIR) $(1)/etc/modules.d
+ #echo "bcm57xx activate_gpio=1" > $(1)/etc/modules.d/30-bcm57xx
+endef
+
+$(eval $(call KernelPackage,brcm-57xx))
diff --git a/package/broadcom-57xx/src/5701rls.c b/package/broadcom-57xx/src/5701rls.c
new file mode 100644
index 0000000000..6b7d49c7a8
--- /dev/null
+++ b/package/broadcom-57xx/src/5701rls.c
@@ -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/package/broadcom-57xx/src/5701rls.h b/package/broadcom-57xx/src/5701rls.h
new file mode 100644
index 0000000000..793726d287
--- /dev/null
+++ b/package/broadcom-57xx/src/5701rls.h
@@ -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/package/broadcom-57xx/src/Makefile b/package/broadcom-57xx/src/Makefile
new file mode 100644
index 0000000000..08a7914879
--- /dev/null
+++ b/package/broadcom-57xx/src/Makefile
@@ -0,0 +1,17 @@
+#
+# Broadcom BCM57XX Gigabit Ethernet driver make file.
+#
+# $Id: Makefile,v 1.1.1.4 2006/09/26 02:17:12 michael Exp $
+#
+
+O_TARGET = bcm57xx.o
+
+EXTRA_CFLAGS += -DDBG=0 -DBCM_PROC_FS=1 -DT3_JUMBO_RCV_RCB_ENTRY_COUNT=256
+EXTRA_CFLAGS += -DPCIX_TARGET_WORKAROUND=1 -DINCLUDE_TBI_SUPPORT=1 -DINCLUDE_5701_AX_FIX=1
+
+export-objs :=
+
+obj-y := b57um.o tigon3.o autoneg.o 5701rls.o tcp_seg.o hndgige.o bcmrobo.o
+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff --git a/package/broadcom-57xx/src/autoneg.c b/package/broadcom-57xx/src/autoneg.c
new file mode 100644
index 0000000000..d467f0347f
--- /dev/null
+++ b/package/broadcom-57xx/src/autoneg.c
@@ -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/package/broadcom-57xx/src/autoneg.h b/package/broadcom-57xx/src/autoneg.h
new file mode 100644
index 0000000000..5d9be8709c
--- /dev/null
+++ b/package/broadcom-57xx/src/autoneg.h
@@ -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/package/broadcom-57xx/src/b57um.c b/package/broadcom-57xx/src/b57um.c
new file mode 100644
index 0000000000..752241dd4b
--- /dev/null
+++ b/package/broadcom-57xx/src/b57um.c
@@ -0,0 +1,5563 @@
+/******************************************************************************/
+/* */
+/* 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. */
+/* */
+/******************************************************************************/
+
+/* $Id: b57um.c,v 1.32 2007/09/06 07:28:06 yogo Exp $ */
+
+char bcm5700_driver[] = "bcm57xx";
+char bcm5700_version[] = "8.3.14";
+char bcm5700_date[] = "(11/2/05)";
+
+#define B57UM
+#include "mm.h"
+#include "linux/mii.h" //@.@jack add it 2006/06/28.
+#include "typedefs.h"
+#include "osl.h"
+#include "bcmdefs.h"
+#include "bcmdevs.h"
+#include "sbconfig.h"
+#include "sbutils.h"
+#include "hndgige.h"
+#include "bcmrobo.h"
+#include "robo_register.c"
+
+#include "bcmendian.h"
+#include "bcmnvram.h"
+#include "proto/ethernet.h"
+#include "proto/vlan.h"
+#include "proto/bcmtcp.h"
+#include "proto/bcmip.h"
+#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data)
+
+/* this is needed to get good and stable performances */
+#define EXTRA_HDR BCMEXTRAHDROOM
+
+#define SIOCGREG_STATUS 0x8996 /* Read Switch register (for debug)*/
+#define SIOCSREG_STATUS 0x8997 /* Write Switch register(for debug)*/
+
+/* This structure is used in SIOCXREG_STATUS ioctl calls*/
+struct reg_ioctl_data {
+ u16 page_num;
+ u16 addr_num;
+ u16 len;
+ u16 val_in[4];
+ u16 val_out[4];
+};
+
+/* 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};
+static int activate_gpio = -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)
+
+/* Hack to hook the data path to the BCM WL dirver */
+#ifdef BCM_WL_EMULATOR
+#include "bcmnvram.h"
+#include "wl_bcm57emu.h"
+#ifdef SKB_MANAGER
+int skb_old_alloc = 0;
+#endif
+#endif /* BCM_WL_EMULATOR */
+
+/* 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);
+ }
+}
+
+
+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(msglevel, "i");
+MODULE_PARM(activate_gpio, "0-15i");
+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
+static int msglevel = 0xdeadbeef;
+int b57_msg_level;
+
+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 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);
+
+static int bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused);
+static struct notifier_block bcm5700_reboot_notifier = {
+ bcm5700_notify_reboot,
+ NULL,
+ 0
+};
+
+#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)
+
+#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,
+ BCM4785,
+ BCM5903M,
+ UNK5788
+} 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 BCM4785 10/100/1000 Integrated Controller" },
+ { "Broadcom BCM5903M Gigabit Ethernet " },
+ { "Unknown BCM5788 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, 0x471f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM4785 },
+ {0x14e4, 0x16ff, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5903M },
+ {0x173b, 0x03ed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, UNK5788 },
+ {0,}
+ };
+
+MODULE_DEVICE_TABLE(pci, bcm5700_pci_tbl);
+
+#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
+
+static int sbgige = -1;
+
+/*******************************************************************************
+ *******************************************************************************
+*/
+
+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 void robo_set_power_mode(void *h)
+{
+ //int status = 0;
+ int i;
+ //uint8 mode8;
+ //uint16 mode16;
+ uint32 flags = 0, temp32 = 0,val32 = 0, savephyaddr = 0;
+ PUM_DEVICE_BLOCK pudev = (PUM_DEVICE_BLOCK)h;
+ PLM_DEVICE_BLOCK pdev = &pudev->lm_dev;
+
+ /*Brcm,Alex,2006.7.20. Adding Phy power mode setting*/
+ BCM5700_PHY_LOCK(pudev, flags);
+ savephyaddr = pdev->PhyAddr;
+
+ for(i = 0; i < 8; i++)
+ {
+ pdev->PhyAddr = i;
+ temp32 = 0x2007;
+ LM_WritePhy(pdev, 0x18, temp32);
+ LM_ReadPhy(pdev, 0x18, &val32);
+// printk(KERN_DEBUG "Alex: port = %x, read value =%x\n",i, val32);
+ temp32 = 0xc042;
+ LM_WritePhy(pdev, 0x18, temp32);
+ /*Read back*/
+ temp32 = 0x2007;
+ val32 = 0;
+ LM_WritePhy(pdev, 0x18, temp32);
+ LM_ReadPhy(pdev, 0x18, &val32);
+// printk(KERN_ERR "Alex: read back value =%x\n",val32);
+ }
+
+ pdev->PhyAddr = savephyaddr;
+ BCM5700_PHY_UNLOCK(pudev, flags);
+
+ /*end of Brcm,Alex,2006.7.20. Adding Phy power mode setting*/
+
+}
+
+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;
+ bool rgmii = FALSE;
+ sb_t *sbh = NULL;
+ 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;
+
+ /* init core specific stuff */
+ if (pdev->device == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM471F)) {
+ sbh = sb_kattach(SB_OSH);
+ sb_gige_init(sbh, ++sbgige, &rgmii);
+ }
+
+ rc = pci_request_regions(pdev, bcm5700_driver);
+ if (rc) {
+ if (!sbh)
+ goto err_out;
+ printk(KERN_INFO "bcm5700_init_board: pci_request_regions returned error %d\n"
+ "This may be because the region is already requested by"
+ " the SMBus driver. Ignore the PCI error messages.\n", rc);
+ }
+
+ 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;
+ pUmDevice->sbh = (void *)sbh;
+ root_tigon3_dev = dev;
+
+ spin_lock_init(&pUmDevice->global_lock);
+
+ spin_lock_init(&pUmDevice->undi_lock);
+
+ spin_lock_init(&pUmDevice->phy_lock);
+
+ pDevice = &pUmDevice->lm_dev;
+ pDevice->Flags = 0;
+ pDevice->FunctNum = PCI_FUNC(pUmDevice->pdev->devfn);
+ pUmDevice->boardflags = getintvar(NULL, "boardflags");
+ if (sbh) {
+ if (pUmDevice->boardflags & BFL_ENETROBO)
+ pDevice->Flags |= ROBO_SWITCH_FLAG;
+ pDevice->Flags |= rgmii ? RGMII_MODE_FLAG : 0;
+ if (sb_chip(sbh) == BCM4785_CHIP_ID && sb_chiprev(sbh) < 2)
+ pDevice->Flags |= ONE_DMA_AT_ONCE_FLAG;
+ pDevice->Flags |= SB_CORE_FLAG;
+ if (sb_chip(sbh) == BCM4785_CHIP_ID)
+ pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
+ }
+
+#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 (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 & ROBO_SWITCH_FLAG) {
+ robo_info_t *robo;
+
+ if ((robo = bcm_robo_attach(sbh, pDevice, dev->name, NULL,
+ robo_miird, robo_miiwr)) == NULL) {
+ B57_ERR(("robo_setup: failed to attach robo switch \n"));
+ goto robo_fail;
+ }
+
+ if (bcm_robo_enable_device(robo)) {
+ B57_ERR(("robo_setup: failed to enable robo switch \n"));
+robo_fail:
+ bcm_robo_detach(robo);
+ rc = -ENODEV;
+ goto err_out_unmap;
+ }
+
+ /* 5397 power mode setting */
+ robo_set_power_mode(robo->h);
+
+ pUmDevice->robo = (void *)robo;
+ }
+
+ 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);
+ 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();
+ 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_BCM5461_PHY_ID)
+ printk("Broadcom BCM5461 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");
+
+ register_reboot_notifier(&bcm5700_reboot_notifier);
+#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_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);
+
+#ifdef BCM_WL_EMULATOR
+/* new transmit callback */
+static int bcm5700emu_start_xmit(struct sk_buff *skb, struct net_device *dev);
+/* keep track of the 2 gige devices */
+static PLM_DEVICE_BLOCK pDev1;
+static PLM_DEVICE_BLOCK pDev2;
+
+static void
+bcm5700emu_open(struct net_device *dev)
+{
+ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
+ PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
+ static int instance = 0;
+ static char *wlemu_if = NULL;
+ char *wlemu_mode = NULL;
+ //int wlemu_idx = 0;
+ static int rx_enable = 0;
+ static int tx_enable = 0;
+
+ /* which interface is the emulator ? */
+ if(instance == 0) {
+ wlemu_if = nvram_get("wlemu_if");
+ /* do we emulate rx, tx or both */
+ wlemu_mode = nvram_get("wlemu_mode");
+ if(wlemu_mode) {
+ if (!strcmp(wlemu_mode,"rx"))
+ {
+ rx_enable = 1;
+ }
+ else if (!strcmp(wlemu_mode,"tx"))
+ {
+
+ tx_enable = 1;
+
+ }
+ else if (!strcmp(wlemu_mode,"rx_tx"))
+ {
+
+ rx_enable = 1;
+ tx_enable = 1;
+ }
+ }
+ }
+
+ instance++;
+
+ /* The context is used for accessing the OSL for emulating devices */
+ pDevice->wlc = NULL;
+
+ /* determines if this device is an emulator */
+ pDevice->wl_emulate_rx = 0;
+ pDevice->wl_emulate_tx = 0;
+
+ if(wlemu_if && !strcmp(dev->name,wlemu_if))
+ {
+ /* create an emulator context. */
+ pDevice->wlc = (void *)wlcemu_wlccreate((void *)dev);
+ B57_INFO(("Using %s for wl emulation \n", dev->name));
+ if(rx_enable)
+ {
+ B57_INFO(("Enabling wl RX emulation \n"));
+ pDevice->wl_emulate_rx = 1;
+ }
+ /* re-direct transmit callback to emulator */
+ if(tx_enable)
+ {
+ pDevice->wl_emulate_tx = 1;
+ dev->hard_start_xmit = bcm5700emu_start_xmit;
+ B57_INFO(("Enabling wl TX emulation \n"));
+ }
+ }
+ /* for debug access to configured devices only */
+ if(instance == 1)
+ pDev1 = pDevice;
+ else if (instance == 2)
+ pDev2 = pDevice;
+}
+
+/* Public API to get current emulation info */
+int bcm5700emu_get_info(char *buf)
+{
+ int len = 0;
+ PLM_DEVICE_BLOCK p;
+
+ /* look for an emulating device */
+ if(pDev1->wlc) {
+ p = pDev1;
+ len += sprintf(buf+len,"emulation device : eth0\n");
+ }
+ else if (pDev2->wlc) {
+ p = pDev2;
+ len += sprintf(buf+len,"emulation device : eth1\n");
+ }
+ else {
+ len += sprintf(buf+len,"emulation not activated\n");
+ return len;
+ }
+ if(p->wl_emulate_rx)
+ len += sprintf(buf+len,"RX emulation enabled\n");
+ else
+ len += sprintf(buf+len,"RX emulation disabled\n");
+ if(p->wl_emulate_tx)
+ len += sprintf(buf+len,"TX emulation enabled\n");
+ else
+ len += sprintf(buf+len,"TX emulation disabled\n");
+ return len;
+
+}
+
+
+/* Public API to access the bcm5700_start_xmit callback */
+
+int
+bcm5700emu_forward_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ return bcm5700_start_xmit(skb, dev);
+}
+
+
+/* hook to kernel txmit callback */
+STATIC int
+bcm5700emu_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;
+ return wlcemu_start_xmit(skb,pDevice->wlc);
+}
+
+#endif /* BCM_WL_EMULATOR */
+
+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;
+ }
+
+#ifdef BCM_WL_EMULATOR
+ bcm5700emu_open(dev);
+#endif
+
+ /* 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;
+
+ /* BCM4785: Flush posted writes from GbE to host memory. */
+ if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
+ REG_RD(pDevice, HostCoalesce.Mode);
+
+ 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
+ }
+ 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 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;
+ pUmDevice->stats.tx_bytes += skb->len;
+
+ 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 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);
+ /* BCM4785: Flush posted writes from GbE to host memory. */
+ if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
+ REG_RD(pDevice, HostCoalesce.Mode);
+ 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);
+ }
+
+ /* BCM4785: Flush posted writes from GbE to host memory. */
+ if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
+ REG_RD(pDevice, HostCoalesce.Mode);
+
+ 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);
+ /* BCM4785: Flush GbE posted writes to host memory. */
+ if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
+ MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
+ 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
+ B57_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
+ {
+ /* BCM4785: Don't go to low-power state because it will power down the smbus block. */
+ if (!(pDevice->Flags & SB_CORE_FLAG))
+ 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;
+
+ return 0;
+}
+
+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);
+ /* There counters seem to be innacurate. Use byte number accumulation
+ instead.
+ 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_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
+ 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};
+
+ /* 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
+ 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_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 = 0;
+ u16 page_num =0, addr_num =0, len =0;
+ unsigned long flags;
+
+ switch(cmd) {
+ case SIOCGREG_STATUS: //Get register
+ {
+ struct reg_ioctl_data *rdata =(struct reg_ioctl_data *)rq->ifr_data;
+ robo_info_t *robo = (robo_info_t *)pUmDevice->robo;
+ page_num = rdata->page_num;
+ addr_num = rdata->addr_num;
+ len = rdata->len;
+ printk("b57um SIOCGREG_STATUS cmd page[0x%x]addr[0x%x]len[%d].\n",page_num,addr_num,len);
+ if (len == 6)
+ {
+ ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
+ printk("val[0x%04x-0x%04x-0x%04x].\n",rdata->val_out[0],rdata->val_out[1],rdata->val_out[2]);
+ }
+ else if (len == 8)
+ {
+ ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
+ printk("val[0x%04x%04x-0x%04x%04x].\n",rdata->val_out[0],rdata->val_out[1],
+ rdata->val_out[2],rdata->val_out[3]);
+ }
+ else if (len == 4)
+ {
+ ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
+ printk("val[0x%04x%04x].\n",rdata->val_out[0],rdata->val_out[1]);
+ }
+ else
+ {
+ ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
+ printk("val[0x%04x].\n",rdata->val_out[0]);
+
+ }
+ if (mm_copy_to_user(rq->ifr_data, rdata, sizeof(struct reg_ioctl_data)))
+ {
+ printk("Fail mm_copy_to_user.\n");
+ return -EFAULT;
+ }
+ return 0;
+ }
+ break;
+ case SIOCSREG_STATUS://Set register
+ {
+ struct reg_ioctl_data * wdata =(struct reg_ioctl_data *)rq->ifr_data;
+ len = wdata->len;
+ page_num = wdata->page_num;
+ addr_num = wdata->addr_num;
+ robo_info_t *robo = (robo_info_t *)pUmDevice->robo;
+ if (len == 6)
+ {
+ WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
+ //printk("val[0x%04x-0x%04x-0x%04x].\n",val48[0],val48[1],val48[2]);
+ }
+ else if (len == 8)
+ {
+ WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
+ //printk("val[0x%04x-0x%04x-0x%04x-0x%04x].\n",val64[0],val64[1],val64[2],val64[3]);
+ }
+ else if (len == 4)
+ {
+ WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
+ //printk("val[0x%08x].\n",value);
+ }
+ else
+ {
+ WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
+ //printk("len[%d] val[0x%04x].\n",len,val16);
+ }
+
+ return 0;
+ }
+ break;
+#ifdef SIOCGMIIPHY
+ case SIOCGMIIPHY: /* Get the address of the PHY in use. */
+
+ data[0] = pDevice->PhyAddr;
+ return 0;
+#endif
+
+#ifdef SIOCGMIIREG
+ case SIOCGMIIREG: /* Read the specified MII register. */
+ {
+ uint32 savephyaddr = 0;
+
+ if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+ return -EOPNOTSUPP;
+
+ /* 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 -EAGAIN;
+ }
+
+ BCM5700_PHY_LOCK(pUmDevice, flags);
+ if (data[0] != 0xffff) {
+ savephyaddr = pDevice->PhyAddr;
+ pDevice->PhyAddr = data[0];
+ }
+ LM_ReadPhy(pDevice, data[1] & 0x1f, (LM_UINT32 *)&value);
+ if (data[0] != 0xffff)
+ pDevice->PhyAddr = savephyaddr;
+ BCM5700_PHY_UNLOCK(pUmDevice, flags);
+ data[3] = value & 0xffff;
+ return 0;
+ }
+#endif
+
+#ifdef SIOCSMIIREG
+ case SIOCSMIIREG: /* Write the specified MII register */
+ {
+ uint32 savephyaddr = 0;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
+ return -EOPNOTSUPP;
+
+ BCM5700_PHY_LOCK(pUmDevice, flags);
+ if (data[0] != 0xffff) {
+ savephyaddr = pDevice->PhyAddr;
+ pDevice->PhyAddr = data[0];
+ }
+ LM_WritePhy(pDevice, data[1] & 0x1f, data[2]);
+ if (data[0] != 0xffff)
+ pDevice->PhyAddr = savephyaddr;
+ BCM5700_PHY_UNLOCK(pUmDevice, flags);
+ data[3] = 0;
+ return 0;
+ }
+#endif
+
+#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);
+ bcm_robo_set_macaddr(pUmDevice->robo, 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;
+
+ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+ while (root_tigon3_dev) {
+ pUmDevice = (PUM_DEVICE_BLOCK)root_tigon3_dev->priv;
+ 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
+bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused)
+{
+ switch (event) {
+ case SYS_HALT:
+ case SYS_POWER_OFF:
+ case SYS_RESTART:
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+
+ B57_INFO(("bcm5700 reboot notification\n"));
+ pci_unregister_driver(&bcm5700_pci_driver);
+ return NOTIFY_DONE;
+}
+
+static int __init bcm5700_init_module (void)
+{
+ int pin = 1 << 2;
+
+ if (nvram_match("disabled_5397", "1") || (activate_gpio != -1)) {
+ if ( activate_gpio != -1 ) pin = activate_gpio;
+ printk("5397 switch GPIO-Reset (pin %d)\n", pin);
+ sb_t *gpio_sbh;
+ if (!(gpio_sbh = sb_kattach(SB_OSH))) return -ENODEV;
+ sb_gpiosetcore(gpio_sbh);
+// sb_gpioreserve(gpio_sbh, 0x4, GPIO_HI_PRIORITY);
+ sb_gpioouten(gpio_sbh, 0x4, 0x4, GPIO_HI_PRIORITY);
+ sb_gpioout(gpio_sbh, 0x4, 0x4, GPIO_HI_PRIORITY);
+ sb_detach(gpio_sbh);
+ }
+
+ if (msglevel != 0xdeadbeef) {
+ b57_msg_level = msglevel;
+ printf("%s: msglevel set to 0x%x\n", __FUNCTION__, b57_msg_level);
+ } else
+ b57_msg_level = B57_ERR_VAL;
+
+ return pci_module_init(&bcm5700_pci_driver);
+}
+
+static void __exit bcm5700_cleanup_module (void)
+{
+ unregister_reboot_notifier(&bcm5700_reboot_notifier);
+ 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) {
+#ifdef BCM_WL_EMULATOR
+ skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2);
+#else
+ skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR);
+#endif
+ if (skb == 0) {
+ pUmPacket->skbuff = 0;
+ QQ_PushTail(
+ &pUmDevice->rx_out_of_buf_q.Container,
+ pPacket);
+ continue;
+ }
+ pUmPacket->skbuff = skb;
+ skb->dev = pUmDevice->dev;
+#ifndef BCM_WL_EMULATOR
+ skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
+#endif
+ }
+ 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;
+}
+
+/* From include/proto/ethernet.h */
+#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */
+
+/* From include/proto/vlan.h */
+#define VLAN_PRI_MASK 7 /* 3 bits of priority */
+#define VLAN_PRI_SHIFT 13
+
+/* Replace the priority in a vlan tag */
+#define UPD_VLANTAG_PRIO(tag, prio) do { \
+ tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); \
+ tag |= prio << VLAN_PRI_SHIFT; \
+} while (0)
+
+/* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
+ * Also updates the inplace vlan tag if requested.
+ * For debugging, it returns an indication of what it did.
+ */
+#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */
+#define PKTPRIO_VLAN 0x200 /* VLAN prio found */
+#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */
+#define PKTPRIO_DSCP 0x800 /* DSCP prio found */
+#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x))
+static uint
+pktsetprio(void *pkt, bool update_vtag)
+{
+ struct ether_header *eh;
+ struct ethervlan_header *evh;
+ uint8 *pktdata;
+ int priority = 0;
+ int rc = 0;
+
+ pktdata = (uint8 *) PKTDATA(NULL, pkt);
+ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
+
+ eh = (struct ether_header *) pktdata;
+
+ if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) {
+ uint16 vlan_tag;
+ int vlan_prio, dscp_prio = 0;
+
+ evh = (struct ethervlan_header *)eh;
+
+ vlan_tag = ntoh16(evh->vlan_tag);
+ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+
+ if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) {
+ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
+ uint8 tos_tc = IP_TOS(ip_body);
+ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+ if ((IP_VER(ip_body) == IP_VER_4) && (IPV4_PROT(ip_body) == IP_PROT_TCP)) {
+ int ip_len;
+ int src_port;
+ bool src_port_exc;
+ uint8 *tcp_hdr;
+
+ ip_len = IPV4_PAYLOAD_LEN(ip_body);
+ tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD(ip_body);
+ src_port = TCP_SRC_PORT(tcp_hdr);
+ src_port_exc = (src_port == 10110) || (src_port == 10120) ||
+ (src_port == 10130) || (src_port == 10140);
+
+ if ((ip_len == 40) && src_port_exc && TCP_IS_ACK(tcp_hdr)) {
+ dscp_prio = 7;
+ }
+ }
+ }
+
+ /* DSCP priority gets precedence over 802.1P (vlan tag) */
+ if (dscp_prio != 0) {
+ priority = dscp_prio;
+ rc |= PKTPRIO_VDSCP;
+ } else {
+ priority = vlan_prio;
+ rc |= PKTPRIO_VLAN;
+ }
+ /*
+ * If the DSCP priority is not the same as the VLAN priority,
+ * then overwrite the priority field in the vlan tag, with the
+ * DSCP priority value. This is required for Linux APs because
+ * the VLAN driver on Linux, overwrites the skb->priority field
+ * with the priority value in the vlan tag
+ */
+ if (update_vtag && (priority != vlan_prio)) {
+ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
+ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
+ evh->vlan_tag = hton16(vlan_tag);
+ rc |= PKTPRIO_UPD;
+ }
+ } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
+ uint8 *ip_body = pktdata + sizeof(struct ether_header);
+ uint8 tos_tc = IP_TOS(ip_body);
+ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+ rc |= PKTPRIO_DSCP;
+ if ((IP_VER(ip_body) == IP_VER_4) && (IPV4_PROT(ip_body) == IP_PROT_TCP)) {
+ int ip_len;
+ int src_port;
+ bool src_port_exc;
+ uint8 *tcp_hdr;
+
+ ip_len = IPV4_PAYLOAD_LEN(ip_body);
+ tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD(ip_body);
+ src_port = TCP_SRC_PORT(tcp_hdr);
+ src_port_exc = (src_port == 10110) || (src_port == 10120) ||
+ (src_port == 10130) || (src_port == 10140);
+
+ if ((ip_len == 40) && src_port_exc && TCP_IS_ACK(tcp_hdr)) {
+ priority = 7;
+ }
+ }
+ }
+
+ ASSERT(priority >= 0 && priority <= MAXPRIO);
+ PKTSETPRIO(pkt, priority);
+ return (rc | priority);
+}
+
+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;
+ uint16 dscp_prio;
+
+ 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;
+ /* Extract priority from payload and put it in skb->priority */
+ dscp_prio = 0;
+ if (pUmDevice->qos) {
+ uint rc;
+
+ rc = pktsetprio(skb, TRUE);
+ if (rc & (PKTPRIO_VDSCP | PKTPRIO_DSCP))
+ dscp_prio = rc & VLAN_PRI_MASK;
+ if (rc != 0)
+ B57_INFO(("pktsetprio returned 0x%x, skb->priority: %d\n",
+ rc, skb->priority));
+ }
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ if (size > pDevice->RxMtu) {
+ /* Make sure we have a valid VLAN tag */
+ if (htons(skb->protocol) != ETHER_TYPE_8021Q) {
+ dev_kfree_skb_irq(skb);
+ pUmDevice->rx_misc_errors++;
+ goto drop_rx;
+ }
+ }
+
+ pUmDevice->stats.rx_bytes += skb->len;
+
+ 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 BCM_VLAN
+ if (pUmDevice->vlgrp &&
+ (pPacket->Flags & RCV_BD_FLAG_VLAN_TAG)) {
+ /* Override vlan priority with dscp priority */
+ if (dscp_prio)
+ UPD_VLANTAG_PRIO(pPacket->VlanTag, dscp_prio);
+#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_WL_EMULATOR
+ if(pDevice->wl_emulate_rx) {
+ /* bcmstats("emu recv %d %d"); */
+ wlcemu_receive_skb(pDevice->wlc, skb);
+ /* bcmstats("emu recv end %d %d"); */
+ }
+ else
+#endif /* BCM_WL_EMULATOR */
+ {
+#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
+#ifdef BCM_WL_EMULATOR
+ skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2);
+#else
+ skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR);
+#endif /* BCM_WL_EMULATOR */
+ if (skb == 0) {
+ pUmPacket->skbuff = 0;
+ QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+ }
+ else {
+ pUmPacket->skbuff = skb;
+ skb->dev = pUmDevice->dev;
+#ifndef BCM_WL_EMULATOR
+ skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
+#endif
+ 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;
+ }
+#ifdef BCM_WL_EMULATOR
+ if ((skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2)) == 0)
+#else
+ if ((skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR)) == 0)
+#endif /* BCM_WL_EMULATOR */
+ {
+ QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,
+ pPacket);
+ ret = 1;
+ break;
+ }
+ pUmPacket->skbuff = skb;
+ skb->dev = pUmDevice->dev;
+#ifndef BCM_WL_EMULATOR
+ skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
+#endif
+ 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) {
+ B57_INFO(("%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name));
+ }
+ else if (Status == LM_STATUS_LINK_ACTIVE) {
+ B57_INFO(("%s: %s NIC Link is UP, ", bcm5700_driver, dev->name));
+ }
+ }
+ else {
+ if (Status == LM_STATUS_LINK_DOWN) {
+ B57_INFO(("%s: %s NIC Link is Down\n", bcm5700_driver, dev->name));
+ }
+ else if (Status == LM_STATUS_LINK_ACTIVE) {
+ B57_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;
+
+ B57_INFO(("%d Mbps ", speed));
+
+ if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
+ B57_INFO(("full duplex"));
+ else
+ B57_INFO(("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) {
+ B57_INFO((", receive "));
+ if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+ B57_INFO(("& transmit "));
+ }
+ else {
+ B57_INFO((", transmit "));
+ }
+ B57_INFO(("flow control ON"));
+ }
+ B57_INFO(("\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/package/broadcom-57xx/src/bcmendian.h b/package/broadcom-57xx/src/bcmendian.h
new file mode 100644
index 0000000000..dc26d51fff
--- /dev/null
+++ b/package/broadcom-57xx/src/bcmendian.h
@@ -0,0 +1,198 @@
+/*
+ * local version of endian.h - byte order defines
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: bcmendian.h,v 1.1.1.11 2007/05/31 08:00:41 michael Exp $
+*/
+
+#ifndef _BCMENDIAN_H_
+#define _BCMENDIAN_H_
+
+#include <typedefs.h>
+
+/* Byte swap a 16 bit value */
+#define BCMSWAP16(val) \
+ ((uint16)(\
+ (((uint16)(val) & (uint16)0x00ffU) << 8) | \
+ (((uint16)(val) & (uint16)0xff00U) >> 8)))
+
+/* Byte swap a 32 bit value */
+#define BCMSWAP32(val) \
+ ((uint32)(\
+ (((uint32)(val) & (uint32)0x000000ffUL) << 24) | \
+ (((uint32)(val) & (uint32)0x0000ff00UL) << 8) | \
+ (((uint32)(val) & (uint32)0x00ff0000UL) >> 8) | \
+ (((uint32)(val) & (uint32)0xff000000UL) >> 24)))
+
+/* 2 Byte swap a 32 bit value */
+#define BCMSWAP32BY16(val) \
+ ((uint32)(\
+ (((uint32)(val) & (uint32)0x0000ffffUL) << 16) | \
+ (((uint32)(val) & (uint32)0xffff0000UL) >> 16)))
+
+
+static INLINE uint16
+bcmswap16(uint16 val)
+{
+ return BCMSWAP16(val);
+}
+
+static INLINE uint32
+bcmswap32(uint32 val)
+{
+ return BCMSWAP32(val);
+}
+
+static INLINE uint32
+bcmswap32by16(uint32 val)
+{
+ return BCMSWAP32BY16(val);
+}
+
+/* buf - start of buffer of shorts to swap */
+/* len - byte length of buffer */
+static INLINE void
+bcmswap16_buf(uint16 *buf, uint len)
+{
+ len = len/2;
+
+ while (len--) {
+ *buf = bcmswap16(*buf);
+ buf++;
+ }
+}
+
+#ifndef hton16
+#ifndef IL_BIGENDIAN
+#define HTON16(i) BCMSWAP16(i)
+#define hton16(i) bcmswap16(i)
+#define hton32(i) bcmswap32(i)
+#define ntoh16(i) bcmswap16(i)
+#define ntoh32(i) bcmswap32(i)
+#define ltoh16(i) (i)
+#define ltoh32(i) (i)
+#define htol16(i) (i)
+#define htol32(i) (i)
+#else
+#define HTON16(i) (i)
+#define hton16(i) (i)
+#define hton32(i) (i)
+#define ntoh16(i) (i)
+#define ntoh32(i) (i)
+#define ltoh16(i) bcmswap16(i)
+#define ltoh32(i) bcmswap32(i)
+#define htol16(i) bcmswap16(i)
+#define htol32(i) bcmswap32(i)
+#endif /* IL_BIGENDIAN */
+#endif /* hton16 */
+
+#ifndef IL_BIGENDIAN
+#define ltoh16_buf(buf, i)
+#define htol16_buf(buf, i)
+#else
+#define ltoh16_buf(buf, i) bcmswap16_buf((uint16*)buf, i)
+#define htol16_buf(buf, i) bcmswap16_buf((uint16*)buf, i)
+#endif /* IL_BIGENDIAN */
+
+/*
+* store 16-bit value to unaligned little endian byte array.
+*/
+static INLINE void
+htol16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[0] = val&0xff;
+ bytes[1] = val>>8;
+}
+
+/*
+* store 32-bit value to unaligned little endian byte array.
+*/
+static INLINE void
+htol32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[0] = val&0xff;
+ bytes[1] = (val>>8)&0xff;
+ bytes[2] = (val>>16)&0xff;
+ bytes[3] = val>>24;
+}
+
+/*
+* store 16-bit value to unaligned network(big) endian byte array.
+*/
+static INLINE void
+hton16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[1] = val&0xff;
+ bytes[0] = val>>8;
+}
+
+/*
+* store 32-bit value to unaligned network(big) endian byte array.
+*/
+static INLINE void
+hton32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[3] = val&0xff;
+ bytes[2] = (val>>8)&0xff;
+ bytes[1] = (val>>16)&0xff;
+ bytes[0] = val>>24;
+}
+
+/*
+* load 16-bit value from unaligned little endian byte array.
+*/
+static INLINE uint16
+ltoh16_ua(void *bytes)
+{
+ return (((uint8*)bytes)[1]<<8)+((uint8 *)bytes)[0];
+}
+
+/*
+* load 32-bit value from unaligned little endian byte array.
+*/
+static INLINE uint32
+ltoh32_ua(void *bytes)
+{
+ return (((uint8*)bytes)[3]<<24)+(((uint8*)bytes)[2]<<16)+
+ (((uint8*)bytes)[1]<<8)+((uint8*)bytes)[0];
+}
+
+/*
+* load 16-bit value from unaligned big(network) endian byte array.
+*/
+static INLINE uint16
+ntoh16_ua(void *bytes)
+{
+ return (((uint8*)bytes)[0]<<8)+((uint8*)bytes)[1];
+}
+
+/*
+* load 32-bit value from unaligned big(network) endian byte array.
+*/
+static INLINE uint32
+ntoh32_ua(void *bytes)
+{
+ return (((uint8*)bytes)[0]<<24)+(((uint8*)bytes)[1]<<16)+
+ (((uint8*)bytes)[2]<<8)+((uint8*)bytes)[3];
+}
+
+#define ltoh_ua(ptr) (\
+ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \
+ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] : \
+ (((uint8 *)ptr)[3]<<24)+(((uint8 *)ptr)[2]<<16)+(((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] \
+)
+
+#define ntoh_ua(ptr) (\
+ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \
+ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[0]<<8)+((uint8 *)ptr)[1] : \
+ (((uint8 *)ptr)[0]<<24)+(((uint8 *)ptr)[1]<<16)+(((uint8 *)ptr)[2]<<8)+((uint8 *)ptr)[3] \
+)
+
+#endif /* _BCMENDIAN_H_ */
diff --git a/package/broadcom-57xx/src/bcmparams.h b/package/broadcom-57xx/src/bcmparams.h
new file mode 100644
index 0000000000..9445d1b0f3
--- /dev/null
+++ b/package/broadcom-57xx/src/bcmparams.h
@@ -0,0 +1,25 @@
+/*
+ * Misc system wide parameters.
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * $Id: bcmparams.h,v 1.1.1.5 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _bcmparams_h_
+#define _bcmparams_h_
+
+#define VLAN_MAXVID 15 /* Max. VLAN ID supported/allowed */
+
+#define VLAN_NUMPRIS 8 /* # of prio, start from 0 */
+
+#define DEV_NUMIFS 16 /* Max. # of devices/interfaces supported */
+
+#define WL_MAXBSSCFG 16 /* maximum number of BSS Configs we can configure */
+
+#endif
diff --git a/package/broadcom-57xx/src/bcmrobo.c b/package/broadcom-57xx/src/bcmrobo.c
new file mode 100644
index 0000000000..72824f6f62
--- /dev/null
+++ b/package/broadcom-57xx/src/bcmrobo.c
@@ -0,0 +1,1329 @@
+/*
+ * Broadcom BCM5325E/536x switch configuration module
+ *
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Based on:
+ * Broadcom 53xx RoboSwitch device driver.
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ */
+
+
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+
+#include <typedefs.h>
+#include <osl.h>
+#include <sbutils.h>
+#include <sbconfig.h>
+#include <bcmendian.h>
+#include "bcmparams.h"
+#include <bcmnvram.h>
+#include <bcmdevs.h>
+#include "bcmrobo.h"
+#include "proto/ethernet.h"
+#include <switch-core.h>
+
+#define DRIVER_NAME "bcm57xx"
+#define DRIVER_VERSION "0.1"
+
+#ifndef GPIO_PIN_NOTDEFINED
+#define GPIO_PIN_NOTDEFINED 0x20
+#endif
+
+#ifdef BCMDBG
+#define ET_ERROR(args) printk args
+#else /* BCMDBG */
+#define ET_ERROR(args)
+#endif /* BCMDBG */
+#define ET_MSG(args)
+
+/*
+ * Switch can be programmed through SPI interface, which
+ * has a rreg and a wreg functions to read from and write to
+ * registers.
+ */
+
+/* MII access registers */
+#define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
+#define REG_MII_PAGE 0x10 /* MII Page register */
+#define REG_MII_ADDR 0x11 /* MII Address register */
+#define REG_MII_DATA0 0x18 /* MII Data register 0 */
+#define REG_MII_DATA1 0x19 /* MII Data register 1 */
+#define REG_MII_DATA2 0x1a /* MII Data register 2 */
+#define REG_MII_DATA3 0x1b /* MII Data register 3 */
+
+/* Page numbers */
+#define PAGE_CTRL 0x00 /* Control page */
+#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
+#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
+#define PAGE_VLAN 0x34 /* VLAN page */
+
+/* Control page registers */
+#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */
+#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */
+#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */
+#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */
+#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */
+#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */
+#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */
+#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */
+#define REG_CTRL_MODE 0x0B /* Switch Mode register */
+#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */
+#define REG_CTRL_SRST 0x79 /* Software reset control register */
+
+#define REG_DEVICE_ID 0x30 /* 539x Device id: */
+#define DEVID5325 0x25 /* 5325 (Not really be we fake it) */
+#define DEVID5395 0x95 /* 5395 */
+#define DEVID5397 0x97 /* 5397 */
+#define DEVID5398 0x98 /* 5398 */
+
+/* VLAN page registers */
+#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
+#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
+#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
+#define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
+#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
+#define REG_VLAN_WRITE 0x08 /* VLAN Write register */
+#define REG_VLAN_READ 0x0C /* VLAN Read register */
+#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
+#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
+#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
+#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
+#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
+#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
+#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
+#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
+#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
+#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
+
+#define VLAN_NUMVLANS 16 /* # of VLANs */
+
+
+/* ARL/VLAN Table Access page registers */
+#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
+#define REG_VTBL_MINDX 0x02 /* MAC Address Index */
+#define REG_VTBL_VINDX 0x08 /* VID Table Index */
+#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
+#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
+#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
+#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
+#define REG_VTBL_SADDR 0x22 /* ARL Search Address */
+#define REG_VTBL_SRES 0x24 /* ARL Search Result */
+#define REG_VTBL_SREXT 0x2c /* ARL Search Result */
+#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
+#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
+#define REG_VTBL_PREG 0xFF /* Page Register */
+#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
+#define REG_VTBL_INDX 0x61 /* VLAN table address index register */
+#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
+#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
+#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
+#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
+
+/* SPI registers */
+#define REG_SPI_PAGE 0xff /* SPI Page register */
+
+/* Access switch registers through GPIO/SPI */
+
+/* Minimum timing constants */
+#define SCK_EDGE_TIME 2 /* clock edge duration - 2us */
+#define MOSI_SETUP_TIME 1 /* input setup duration - 1us */
+#define SS_SETUP_TIME 1 /* select setup duration - 1us */
+
+/* misc. constants */
+#define SPI_MAX_RETRY 100
+
+static int config_attach(robo_info_t *robo);
+static void config_detach(robo_info_t *robo);
+
+/* Enable GPIO access to the chip */
+static void
+gpio_enable(robo_info_t *robo)
+{
+ /* Enable GPIO outputs with SCK and MOSI low, SS high */
+ sb_gpioout(robo->sbh, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
+ sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi,
+ robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
+}
+
+/* Disable GPIO access to the chip */
+static void
+gpio_disable(robo_info_t *robo)
+{
+ /* Disable GPIO outputs with all their current values */
+ sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
+}
+
+/* Write a byte stream to the chip thru SPI */
+static int
+spi_write(robo_info_t *robo, uint8 *buf, uint len)
+{
+ uint i;
+ uint8 mask;
+
+ /* Byte bang from LSB to MSB */
+ for (i = 0; i < len; i++) {
+ /* Bit bang from MSB to LSB */
+ for (mask = 0x80; mask; mask >>= 1) {
+ /* Clock low */
+ sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
+ OSL_DELAY(SCK_EDGE_TIME);
+
+ /* Sample on rising edge */
+ if (mask & buf[i])
+ sb_gpioout(robo->sbh, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
+ else
+ sb_gpioout(robo->sbh, robo->mosi, 0, GPIO_DRV_PRIORITY);
+ OSL_DELAY(MOSI_SETUP_TIME);
+
+ /* Clock high */
+ sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
+ OSL_DELAY(SCK_EDGE_TIME);
+ }
+ }
+
+ return 0;
+}
+
+/* Read a byte stream from the chip thru SPI */
+static int
+spi_read(robo_info_t *robo, uint8 *buf, uint len)
+{
+ uint i, timeout;
+ uint8 rack, mask, byte;
+
+ /* Timeout after 100 tries without RACK */
+ for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
+ /* Bit bang from MSB to LSB */
+ for (mask = 0x80, byte = 0; mask; mask >>= 1) {
+ /* Clock low */
+ sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
+ OSL_DELAY(SCK_EDGE_TIME);
+
+ /* Sample on falling edge */
+ if (sb_gpioin(robo->sbh) & robo->miso)
+ byte |= mask;
+
+ /* Clock high */
+ sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
+ OSL_DELAY(SCK_EDGE_TIME);
+ }
+ /* RACK when bit 0 is high */
+ if (!rack) {
+ rack = (byte & 1);
+ timeout--;
+ continue;
+ }
+ /* Byte bang from LSB to MSB */
+ buf[i] = byte;
+ i++;
+ }
+
+ if (timeout == 0) {
+ ET_ERROR(("spi_read: timeout"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Enable/disable SPI access */
+static void
+spi_select(robo_info_t *robo, uint8 spi)
+{
+ if (spi) {
+ /* Enable SPI access */
+ sb_gpioout(robo->sbh, robo->ss, 0, GPIO_DRV_PRIORITY);
+ } else {
+ /* Disable SPI access */
+ sb_gpioout(robo->sbh, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
+ }
+ OSL_DELAY(SS_SETUP_TIME);
+}
+
+
+/* Select chip and page */
+static void
+spi_goto(robo_info_t *robo, uint8 page)
+{
+ uint8 reg8 = REG_SPI_PAGE; /* page select register */
+ uint8 cmd8;
+
+ /* Issue the command only when we are on a different page */
+ if (robo->page == page)
+ return;
+
+ robo->page = page;
+
+ /* Enable SPI access */
+ spi_select(robo, 1);
+
+ /* Select new page with CID 0 */
+ cmd8 = ((6 << 4) | /* normal SPI */
+ 1); /* write */
+ spi_write(robo, &cmd8, 1);
+ spi_write(robo, &reg8, 1);
+ spi_write(robo, &page, 1);
+
+ /* Disable SPI access */
+ spi_select(robo, 0);
+}
+
+/* Write register thru SPI */
+static int
+spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
+{
+ int status = 0;
+ uint8 cmd8;
+ union {
+ uint8 val8;
+ uint16 val16;
+ uint32 val32;
+ } bytes;
+
+ /* validate value length and buffer address */
+ ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
+ (len == 4 && !((int)val & 3)));
+
+ /* Select chip and page */
+ spi_goto(robo, page);
+
+ /* Enable SPI access */
+ spi_select(robo, 1);
+
+ /* Write with CID 0 */
+ cmd8 = ((6 << 4) | /* normal SPI */
+ 1); /* write */
+ spi_write(robo, &cmd8, 1);
+ spi_write(robo, &addr, 1);
+ switch (len) {
+ case 1:
+ bytes.val8 = *(uint8 *)val;
+ break;
+ case 2:
+ bytes.val16 = htol16(*(uint16 *)val);
+ break;
+ case 4:
+ bytes.val32 = htol32(*(uint32 *)val);
+ break;
+ }
+ spi_write(robo, (uint8 *)val, len);
+
+ ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
+ *(uint16 *)val, len));
+ /* Disable SPI access */
+ spi_select(robo, 0);
+ return status;
+}
+
+/* Read register thru SPI in fast SPI mode */
+static int
+spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
+{
+ int status = 0;
+ uint8 cmd8;
+ union {
+ uint8 val8;
+ uint16 val16;
+ uint32 val32;
+ } bytes;
+
+ /* validate value length and buffer address */
+ ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
+ (len == 4 && !((int)val & 3)));
+
+ /* Select chip and page */
+ spi_goto(robo, page);
+
+ /* Enable SPI access */
+ spi_select(robo, 1);
+
+ /* Fast SPI read with CID 0 and byte offset 0 */
+ cmd8 = (1 << 4); /* fast SPI */
+ spi_write(robo, &cmd8, 1);
+ spi_write(robo, &addr, 1);
+ status = spi_read(robo, (uint8 *)&bytes, len);
+ switch (len) {
+ case 1:
+ *(uint8 *)val = bytes.val8;
+ break;
+ case 2:
+ *(uint16 *)val = ltoh16(bytes.val16);
+ break;
+ case 4:
+ *(uint32 *)val = ltoh32(bytes.val32);
+ break;
+ }
+
+ ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
+ *(uint16 *)val, len));
+
+ /* Disable SPI access */
+ spi_select(robo, 0);
+ return status;
+}
+
+/* SPI/gpio interface functions */
+static dev_ops_t spigpio = {
+ gpio_enable,
+ gpio_disable,
+ spi_wreg,
+ spi_rreg,
+ "SPI (GPIO)"
+};
+
+
+/* Access switch registers through MII (MDC/MDIO) */
+
+#define MII_MAX_RETRY 100
+
+/* Write register thru MDC/MDIO */
+static int
+mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
+{
+ uint16 cmd16, val16,val48[3];
+ void *h = robo->h;
+ uint32 val64[2];
+ memset(val48,0,6);
+ memset(val64,0,8);
+ int i;
+ uint8 *ptr = (uint8 *)val;
+
+ /* validate value length and buffer address */
+ ASSERT(len == 1 || len == 6 || len == 8 ||
+ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
+
+ ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
+ *(uint16 *)val, len));
+
+ /* set page number - MII register 0x10 */
+ if (robo->page != page) {
+ cmd16 = ((page << 8) | /* page number */
+ 1); /* mdc/mdio access enable */
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
+ robo->page = page;
+ }
+
+ switch (len) {
+ case 8:
+ val16 = ptr[7];
+ val16 = ((val16 << 8) | ptr[6]);
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
+ /* FALLTHRU */
+
+ case 6:
+ val16 = ptr[5];
+ val16 = ((val16 << 8) | ptr[4]);
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
+ val16 = ptr[3];
+ val16 = ((val16 << 8) | ptr[2]);
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
+ val16 = ptr[1];
+ val16 = ((val16 << 8) | ptr[0]);
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
+ break;
+
+ case 4:
+ val16 = (uint16)((*(uint32 *)val) >> 16);
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
+ val16 = (uint16)(*(uint32 *)val);
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
+ break;
+
+ case 2:
+ val16 = *(uint16 *)val;
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
+ break;
+
+ case 1:
+ val16 = *(uint8 *)val;
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
+ break;
+ }
+
+ /* set register address - MII register 0x11 */
+ cmd16 = ((reg << 8) | /* register address */
+ 1); /* opcode write */
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
+
+ /* is operation finished? */
+ for (i = MII_MAX_RETRY; i > 0; i --) {
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
+ if ((val16 & 3) == 0)
+ break;
+ }
+
+ /* timed out */
+ if (!i) {
+ ET_ERROR(("mii_wreg: timeout"));
+ return -1;
+ }
+ return 0;
+}
+
+/* Read register thru MDC/MDIO */
+static int
+mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
+{
+ uint16 cmd16, val16;
+ void *h = robo->h;
+ int i;
+ uint8 *ptr = (uint8 *)val;
+
+ /* validate value length and buffer address */
+ ASSERT(len == 1 || len == 6 || len == 8 ||
+ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
+
+ /* set page number - MII register 0x10 */
+ if (robo->page != page) {
+ cmd16 = ((page << 8) | /* page number */
+ 1); /* mdc/mdio access enable */
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
+ robo->page = page;
+ }
+
+ /* set register address - MII register 0x11 */
+ cmd16 = ((reg << 8) | /* register address */
+ 2); /* opcode read */
+ robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
+
+ /* is operation finished? */
+ for (i = MII_MAX_RETRY; i > 0; i --) {
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
+ if ((val16 & 3) == 0)
+ break;
+ }
+ /* timed out */
+ if (!i) {
+ ET_ERROR(("mii_rreg: timeout"));
+ return -1;
+ }
+
+ ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, val16, len));
+
+ switch (len) {
+ case 8:
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
+ ptr[7] = (val16 >> 8);
+ ptr[6] = (val16 & 0xff);
+ /* FALLTHRU */
+
+ case 6:
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
+ ptr[5] = (val16 >> 8);
+ ptr[4] = (val16 & 0xff);
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
+ ptr[3] = (val16 >> 8);
+ ptr[2] = (val16 & 0xff);
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
+ ptr[1] = (val16 >> 8);
+ ptr[0] = (val16 & 0xff);
+ break;
+
+ case 4:
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
+ *(uint32 *)val = (((uint32)val16) << 16);
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
+ *(uint32 *)val |= val16;
+ break;
+
+ case 2:
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
+ *(uint16 *)val = val16;
+ break;
+ case 1:
+ val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
+ *(uint8 *)val = (uint8)(val16 & 0xff);
+ break;
+ }
+
+ return 0;
+}
+
+/* MII interface functions */
+static dev_ops_t mdcmdio = {
+ NULL,
+ NULL,
+ mii_wreg,
+ mii_rreg,
+ "MII (MDC/MDIO)"
+};
+
+/* High level switch configuration functions. */
+
+static int
+findmatch(char *string, char *name)
+{
+ uint len;
+ char *c;
+
+ len = strlen(name);
+ /* CSTYLED */
+ while ((c = strchr(string, ',')) != NULL) {
+ if (len == (uint)(c - string) && !strncmp(string, name, len))
+ return 1;
+ string = c + 1;
+ }
+
+ return (!strcmp(string, name));
+}
+
+static uint
+getgpiopin(char *vars, char *pin_name, uint def_pin)
+{
+ char name[] = "gpioXXXX";
+ char *val;
+ uint pin;
+
+ /* Go thru all possibilities till a match in pin name */
+ for (pin = 0; pin < GPIO_NUMPINS; pin ++) {
+ snprintf(name, sizeof(name), "gpio%d", pin);
+ val = getvar(vars, name);
+ if (val && findmatch(val, pin_name))
+ return pin;
+ }
+
+ if (def_pin != GPIO_PIN_NOTDEFINED) {
+ /* make sure the default pin is not used by someone else */
+ snprintf(name, sizeof(name), "gpio%d", def_pin);
+ if (getvar(vars, name)) {
+ def_pin = GPIO_PIN_NOTDEFINED;
+ }
+ }
+
+ return def_pin;
+}
+
+
+/* Port flags */
+#define FLAG_TAGGED 't' /* output tagged (external ports only) */
+#define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */
+#define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */
+
+/* port descriptor */
+typedef struct {
+ uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
+ uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
+ uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */
+ uint8 cpu; /* is this cpu port? */
+} pdesc_t;
+
+pdesc_t pdesc97[] = {
+ /* 5395/5397/5398 is 0 ~ 7. port 8 is IMP port. */
+ /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
+ /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
+ /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
+ /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
+ /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
+ /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
+ /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
+ /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
+ /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
+};
+
+pdesc_t pdesc25[] = {
+ /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
+ /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
+ /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
+ /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
+ /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
+ /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
+};
+
+
+#define to_robo(driver) ((robo_info_t *) ((switch_driver *) driver)->priv)
+#define ROBO_START(driver) \
+ do { \
+ robo_info_t *robo = to_robo(driver); \
+ if (robo->ops->enable_mgmtif) \
+ robo->ops->enable_mgmtif(robo)
+
+#define ROBO_END(driver) \
+ if (robo->ops->disable_mgmtif) \
+ robo->ops->disable_mgmtif(robo); \
+ } while (0)
+
+int
+bcm_robo_reset(robo_info_t *robo)
+{
+ int i, max_port_ind;
+ uint8 val8;
+ uint16 val16;
+ uint32 val32;
+ pdesc_t *pdesc;
+ int pdescsz;
+
+/* printk(KERN_WARNING "bcmrobo.c: bcm_robo_reset\n"); */
+
+ if (robo->ops->enable_mgmtif)
+ robo->ops->enable_mgmtif(robo);
+
+ /* setup global vlan configuration, FIXME: necessary? */
+ /* VLAN Control 0 Register (Page 0x34, Address 0) */
+ val8 = ((1 << 7) | /* enable 802.1Q VLAN */
+ (3 << 5)); /* individual VLAN learning mode */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
+
+ /* VLAN Control 1 Register (Page 0x34, Address 1) */
+ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
+ val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */
+ (1 << 3)); /* enable RSV multicast V Untagmap */
+ if (robo->devid == DEVID5325)
+ val8 |= (1 << 1); /* enable RSV multicast V Tagging */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
+
+ bcm_robo_set_macaddr(robo, NULL);
+
+ if (robo->devid == DEVID5325) {
+ /* VLAN Control 4 Register (Page 0x34, Address 4) */
+ val8 = (1 << 6); /* drop frame with VID violation */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
+
+ /* VLAN Control 5 Register (Page 0x34, Address 5) */
+ val8 = (1 << 3); /* drop frame when miss V table */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
+
+ pdesc = pdesc25;
+ pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
+ } else {
+ pdesc = pdesc97;
+ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
+ }
+
+ if (robo->devid == DEVID5325) {
+ /* setup priority mapping - applies to tagged ingress frames */
+ /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
+ /* FIXME: un-hardcode */
+ val32 = ((0 << 0) | /* 0 -> 0 */
+ (1 << 3) | /* 1 -> 1 */
+ (2 << 6) | /* 2 -> 2 */
+ (3 << 9) | /* 3 -> 3 */
+ (4 << 12) | /* 4 -> 4 */
+ (5 << 15) | /* 5 -> 5 */
+ (6 << 18) | /* 6 -> 6 */
+ (7 << 21)); /* 7 -> 7 */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
+ }
+
+ /* Set unmanaged mode */
+ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
+ val8 &= (~(1 << 0));
+ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
+
+ /* No spanning tree for unmanaged mode */
+ val8 = 0;
+ max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 : REG_CTRL_PORT4);
+ for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
+ robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
+ }
+
+ /* WAN port LED */
+ val16 = 0x1f;
+ robo->ops->write_reg(robo, PAGE_CTRL, 0x16, &val16, 2);
+
+ if (robo->ops->enable_mgmtif)
+ robo->ops->disable_mgmtif(robo);
+
+ return 0;
+}
+
+/* Get access to the RoboSwitch */
+robo_info_t *
+bcm_robo_attach(sb_t *sbh, void *h, char *name, char *vars, miird_f miird, miiwr_f miiwr)
+{
+ robo_info_t *robo;
+ uint32 reset, idx;
+ uint8 val8;
+ uint16 val16;
+
+ /* Allocate and init private state */
+ if (!(robo = MALLOC(sb_osh(sbh), sizeof(robo_info_t)))) {
+ ET_ERROR(("robo_attach: out of memory, malloced %d bytes", MALLOCED(sb_osh(sbh))));
+ return NULL;
+ }
+ bzero(robo, sizeof(robo_info_t));
+
+ robo->h = h;
+ robo->sbh = sbh;
+ robo->vars = vars;
+ robo->miird = miird;
+ robo->miiwr = miiwr;
+ robo->page = -1;
+ robo->name = name;
+
+ /* Trigger external reset by nvram variable existance */
+ if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
+ GPIO_PIN_NOTDEFINED) {
+ /*
+ * Reset sequence: RESET low(50ms)->high(20ms)
+ *
+ * We have to perform a full sequence for we don't know how long
+ * it has been from power on till now.
+ */
+ ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
+ reset = 1 << reset;
+
+ /* Keep RESET low for 50 ms */
+ sb_gpioout(robo->sbh, reset, 0, GPIO_DRV_PRIORITY);
+ sb_gpioouten(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
+ bcm_mdelay(50);
+
+ if (robo->devid == DEVID5395)
+ nvram_set("switch_type", "BCM5395");
+ else if(robo->devid == DEVID5397)
+ nvram_set("switch_type", "BCM5397");
+ else
+ nvram_set("switch_type", "unknown");
+
+ /* Keep RESET high for at least 20 ms */
+ sb_gpioout(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
+ bcm_mdelay(20);
+ } else {
+ /* In case we need it */
+ idx = sb_coreidx(robo->sbh);
+
+ if (sb_setcore(robo->sbh, SB_ROBO, 0)) {
+ /* If we have an internal robo core, reset it using sb_core_reset */
+ ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
+ sb_core_reset(robo->sbh, 0, 0);
+ }
+
+ sb_setcoreidx(robo->sbh, idx);
+ }
+
+ if (miird && miiwr) {
+ uint16 tmp;
+ int rc, retry_count = 0;
+
+ /* Read the PHY ID */
+ tmp = miird(h, PSEUDO_PHYAD, 2);
+ if (tmp != 0xffff) {
+ do {
+ rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, \
+ &robo->devid, sizeof(uint16));
+ if (rc != 0)
+ break;
+ retry_count++;
+ } while ((robo->devid == 0) && (retry_count < 10));
+
+ ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", __FUNCTION__, \
+ rc ? "un" : "", robo->devid));
+ ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
+ robo->ops = &mdcmdio;
+ if ((rc != 0) || (robo->devid == 0)) {
+ ET_MSG(("%s: error reading devid, assuming 5325e\n", __FUNCTION__));
+ robo->devid = DEVID5325;
+ }
+ ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
+ }
+ }
+
+ if ((robo->devid == DEVID5395) ||
+ (robo->devid == DEVID5397) ||
+ (robo->devid == DEVID5398)) {
+ uint8 srst_ctrl;
+
+ /* If it is a 539x switch, use the soft reset register */
+ ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
+
+ /* Reset the 539x switch core and register file */
+ srst_ctrl = 0x83;
+ mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
+
+ bcm_mdelay(500);
+
+ srst_ctrl = 0x00;
+ mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
+ }
+
+ if (!robo->ops) {
+ int mosi, miso, ss, sck;
+
+ robo->ops = &spigpio;
+ robo->devid = DEVID5325;
+
+ /* Init GPIO mapping. Default 2, 3, 4, 5 */
+ ss = getgpiopin(vars, "robo_ss", 2);
+ if (ss == GPIO_PIN_NOTDEFINED) {
+ ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
+ goto error;
+ }
+ robo->ss = 1 << ss;
+ sck = getgpiopin(vars, "robo_sck", 3);
+ if (sck == GPIO_PIN_NOTDEFINED) {
+ ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
+ goto error;
+ }
+ robo->sck = 1 << sck;
+ mosi = getgpiopin(vars, "robo_mosi", 4);
+ if (mosi == GPIO_PIN_NOTDEFINED) {
+ ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
+ goto error;
+ }
+ robo->mosi = 1 << mosi;
+ miso = getgpiopin(vars, "robo_miso", 5);
+ if (miso == GPIO_PIN_NOTDEFINED) {
+ ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
+ goto error;
+ }
+ robo->miso = 1 << miso;
+ ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
+ ss, sck, mosi, miso));
+ }
+
+ /* sanity check */
+ ASSERT(robo->ops);
+ ASSERT(robo->ops->write_reg);
+ ASSERT(robo->ops->read_reg);
+ ASSERT((robo->devid == DEVID5325) ||
+ (robo->devid == DEVID5395) ||
+ (robo->devid == DEVID5397) ||
+ (robo->devid == DEVID5398));
+
+ bcm_robo_reset(robo);
+ config_attach(robo);
+
+ return robo;
+
+error:
+ MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
+ return NULL;
+}
+
+/* Release access to the RoboSwitch */
+void
+bcm_robo_detach(robo_info_t *robo)
+{
+ config_detach(robo);
+ MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
+}
+
+/* Enable the device and set it to a known good state */
+int
+bcm_robo_enable_device(robo_info_t *robo)
+{
+ uint8 reg_offset, reg_val;
+ int ret = 0;
+
+ /* Enable management interface access */
+ if (robo->ops->enable_mgmtif)
+ robo->ops->enable_mgmtif(robo);
+
+ if (robo->devid == DEVID5398) {
+ /* Disable unused ports: port 6 and 7 */
+ for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
+ /* Set bits [1:0] to disable RX and TX */
+ reg_val = 0x03;
+ robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
+ sizeof(reg_val));
+ }
+ }
+
+ if (robo->devid == DEVID5325) {
+ /* Must put the switch into Reverse MII mode! */
+
+ /* MII port state override (page 0 register 14) */
+ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
+
+ /* Bit 4 enables reverse MII mode */
+ if (!(reg_val & (1 << 4))) {
+ /* Enable RvMII */
+ reg_val |= (1 << 4);
+ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
+ sizeof(reg_val));
+
+ /* Read back */
+ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
+ sizeof(reg_val));
+ if (!(reg_val & (1 << 4))) {
+ ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
+ ret = -1;
+ }
+ }
+ }
+
+ /* Disable management interface access */
+ if (robo->ops->disable_mgmtif)
+ robo->ops->disable_mgmtif(robo);
+
+ return ret;
+}
+
+
+void bcm_robo_set_macaddr(robo_info_t *robo, char *mac_addr)
+{
+ uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
+
+ if (mac_addr != NULL)
+ memcpy(robo->macaddr, mac_addr, 6);
+
+ mac_addr = robo->macaddr;
+
+ /* setup mac address */
+ arl_entry[0] = mac_addr[5];
+ arl_entry[1] = mac_addr[4];
+ arl_entry[2] = mac_addr[3];
+ arl_entry[3] = mac_addr[2];
+ arl_entry[4] = mac_addr[1];
+ arl_entry[5] = mac_addr[0];
+
+ if (robo->devid == DEVID5325) {
+ /* Init the entry 1 of the bin */
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
+ arl_entry1, sizeof(arl_entry1));
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
+ arl_entry1, 1);
+
+ /* Init the entry 0 of the bin */
+ arl_entry[6] = 0x8; /* Port Id: MII */
+ arl_entry[7] = 0xc0; /* Static Entry, Valid */
+
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
+ arl_entry, sizeof(arl_entry));
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
+ arl_entry, ETHER_ADDR_LEN);
+
+ } else {
+ /* Initialize the MAC Addr Index Register */
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
+ arl_entry, ETHER_ADDR_LEN);
+ }
+}
+
+static int handle_reset(void *driver, char *buf, int nr)
+{
+ ROBO_START(driver);
+ bcm_robo_reset(robo);
+ ROBO_END(driver);
+
+ return 0;
+}
+
+
+static int handle_enable_read(void *driver, char *buf, int nr)
+{
+ int ret;
+ uint8 val8;
+
+ ROBO_START(driver);
+ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
+ ret = sprintf(buf, "%d\n", !!(val8 & (1 << 1)));
+ ROBO_END(driver);
+
+ return ret;
+}
+
+static int handle_enable_write(void *driver, char *buf, int nr)
+{
+ uint8 val8;
+
+/* printk(KERN_WARNING "bcmrobo.c: handle_enable_write\n"); */
+
+ ROBO_START(driver);
+ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
+ val8 &= ~(1 << 1);
+ val8 |= ((buf[0] == '1') << 1);
+ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
+ ROBO_END(driver);
+
+ return 0;
+}
+
+static int handle_enable_vlan_read(void *driver, char *buf, int nr)
+{
+ uint8 val8;
+
+ ROBO_START(driver);
+ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
+ ROBO_END(driver);
+
+ return sprintf(buf, "%d\n", (((val8 & (1 << 7)) == (1 << 7)) ? 1 : 0));
+}
+static int handle_enable_vlan_write(void *driver, char *buf, int nr)
+{
+ int disable = ((buf[0] != '1') ? 1 : 0);
+
+ uint8 val8;
+ uint16 val16;
+ pdesc_t *pdesc;
+ int pdescsz;
+ uint16 vid;
+ uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
+
+/* printk(KERN_WARNING "bcmrobo.c: handle_enable_vlan_write\n"); */
+
+ ROBO_START(driver);
+
+ /* setup global vlan configuration */
+ /* VLAN Control 0 Register (Page 0x34, Address 0) */
+ val8 = disable ? 0 :
+ ((1 << 7) | /* enable/disable 802.1Q VLAN */
+ (3 << 5)); /* individual VLAN learning mode */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
+
+ /* VLAN Control 1 Register (Page 0x34, Address 1) */
+ val8 = disable ? 0 :
+ ((1 << 2) | /* enable/disable RSV multicast V Fwdmap */
+ (1 << 3)); /* enable/disable RSV multicast V Untagmap */
+ if (robo->devid == DEVID5325)
+ val8 |= disable ? 0 : (1 << 1); /* enable/disable RSV multicast V Tagging */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
+
+ if ( disable == 0 ) { /* FIXME: ok to stop here when disabling? */
+ arl_entry[0] = robo->macaddr[5];
+ arl_entry[1] = robo->macaddr[4];
+ arl_entry[2] = robo->macaddr[3];
+ arl_entry[3] = robo->macaddr[2];
+ arl_entry[4] = robo->macaddr[1];
+ arl_entry[5] = robo->macaddr[0];
+
+ if (robo->devid == DEVID5325) {
+ /* Init the entry 1 of the bin */
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
+ arl_entry1, sizeof(arl_entry1));
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
+ arl_entry1, 1);
+
+ /* Init the entry 0 of the bin */
+ arl_entry[6] = 0x8; /* Port Id: MII */
+ arl_entry[7] = 0xc0; /* Static Entry, Valid */
+
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
+ arl_entry, sizeof(arl_entry));
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
+ arl_entry, ETHER_ADDR_LEN);
+
+ /* VLAN Control 4 Register (Page 0x34, Address 4) */
+ val8 = (1 << 6); /* drop frame with VID violation */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
+
+ /* VLAN Control 5 Register (Page 0x34, Address 5) */
+ val8 = (1 << 3); /* drop frame when miss V table */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
+
+ pdesc = pdesc25;
+ pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
+ } else {
+ /* Initialize the MAC Addr Index Register */
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
+ arl_entry, ETHER_ADDR_LEN);
+
+ pdesc = pdesc97;
+ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
+ }
+
+ /* setup each vlan. max. 16 vlans. */
+ /* force vlan id to be equal to vlan number */
+ for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
+
+ /* Add static ARL entries */
+ if (robo->devid == DEVID5325) {
+ val8 = vid;
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, \
+ &val8, sizeof(val8));
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
+ &val8, sizeof(val8));
+
+ /* Write the entry */
+ val8 = 0x80;
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
+ &val8, sizeof(val8));
+ /* Wait for write to complete */
+ SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
+ &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
+ 100 /* usec */);
+ } else {
+ /* Set the VLAN Id in VLAN ID Index Register */
+ val8 = vid;
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
+ &val8, sizeof(val8));
+
+ /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
+ * Register.
+ */
+ arl_entry[6] = vid;
+ arl_entry[7] = 0x0;
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
+ arl_entry, sizeof(arl_entry));
+
+ /* Set the Static bit , Valid bit and Port ID fields in
+ * ARL Table Data Entry 0 Register
+ */
+ val16 = 0xc008;
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, \
+ &val16, sizeof(val16));
+
+ /* Clear the ARL_R/W bit and set the START/DONE bit in
+ * the ARL Read/Write Control Register.
+ */
+ val8 = 0x80;
+ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
+ &val8, sizeof(val8));
+ /* Wait for write to complete */
+ SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
+ &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
+ 100 /* usec */);
+ }
+ }
+ }
+
+ ROBO_END(driver);
+ return 0;
+}
+
+static int handle_vlan_port_read(void *driver, char *buf, int nr)
+{
+ /* FIXME: yeah, some work is missing here */
+ return sprintf(buf, "bcmrobo.c: handle_vlan_port_read unimplimented\n");
+}
+
+static int handle_vlan_port_write(void *driver, char *buf, int nr)
+{
+
+ switch_driver *d = (switch_driver *) driver;
+ switch_vlan_config *c = switch_parse_vlan(d, buf);
+
+ uint8 val8;
+ uint16 val16;
+ uint32 val32;
+ int j;
+ pdesc_t *pdesc;
+ int pdescsz;
+
+/* printk(KERN_WARNING "bcmrobo.c: handle_vlan_port_write, nr %d\n", nr); */
+
+ if (c == NULL)
+ return -EINVAL;
+
+ ROBO_START(driver);
+
+ if (robo->devid == DEVID5325) {
+ pdesc = pdesc25;
+ pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
+ } else {
+ pdesc = pdesc97;
+ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
+ }
+
+
+ for (j = 0; j < d->ports; j++) {
+ if ((c->untag | c->pvid) & (1 << j))
+ if ((j != d->cpuport) || (c->untag & (1 << j))) {
+
+ /* change default vlan tag */
+
+/* printk(KERN_WARNING "bcmrobo.c: set default vlan tag, port %d -> vlan %d\n", j, nr); */
+
+ val16 = ((0 << 13) | /* priority - always 0 */
+ nr); /* vlan id */
+ robo->ops->write_reg(robo, PAGE_VLAN, pdesc[j].ptagr, &val16, sizeof(val16));
+ }
+ }
+
+
+ if (robo->devid == DEVID5325) {
+ val32 = ((c->untag << 6) | /* untag enable */
+ c->port); /* vlan members */
+ val32 |= ((1 << 20) | /* valid write */
+ ((nr >> 4) << 12)); /* vlan id bit[11:4] */
+ /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
+ sizeof(val32));
+ /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
+ val16 = ((1 << 13) | /* start command */
+ (1 << 12) | /* write state */
+ nr); /* vlan id */
+ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
+ sizeof(val16));
+ } else {
+ uint8 vtble, vtbli, vtbla;
+ val32 = ((c->untag << 9) | /* untag enable */
+ c->port); /* vlan members */
+
+ if (robo->devid == DEVID5395) {
+ vtble = REG_VTBL_ENTRY_5395;
+ vtbli = REG_VTBL_INDX_5395;
+ vtbla = REG_VTBL_ACCESS_5395;
+ } else {
+ vtble = REG_VTBL_ENTRY;
+ vtbli = REG_VTBL_INDX;
+ vtbla = REG_VTBL_ACCESS;
+ }
+
+ /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
+ robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
+ sizeof(val32));
+ /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
+ val16 = nr; /* vlan id */
+ robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
+ sizeof(val16));
+
+ /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
+ val8 = ((1 << 7) | /* start command */
+ 0); /* write */
+ robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
+ sizeof(val8));
+ }
+
+ ROBO_END(driver);
+ return 0;
+}
+
+static int __init config_attach(robo_info_t *robo)
+{
+ switch_config cfg[] = {
+ {"enable", handle_enable_read, handle_enable_write},
+ {"reset", NULL, handle_reset},
+ {"enable_vlan", handle_enable_vlan_read, handle_enable_vlan_write},
+ {NULL, NULL, NULL}
+ };
+ switch_config vlan[] = {
+ {"ports", handle_vlan_port_read, handle_vlan_port_write},
+ {NULL, NULL, NULL}
+ };
+ switch_driver driver = {
+ name: DRIVER_NAME,
+ version: DRIVER_VERSION,
+ interface: robo->name,
+ cpuport: 8,
+ ports: 9,
+ vlans: 16,
+ driver_handlers: cfg,
+ port_handlers: NULL,
+ vlan_handlers: vlan,
+ };
+ if (robo->devid == DEVID5325) {
+ driver.ports = 6;
+ driver.cpuport = 5;
+ }
+ driver.priv = (void *) robo;
+
+ return switch_register_driver(&driver);
+}
+
+static void __exit config_detach(robo_info_t *robo)
+{
+ switch_unregister_driver(DRIVER_NAME);
+}
+
+
diff --git a/package/broadcom-57xx/src/bcmrobo.h b/package/broadcom-57xx/src/bcmrobo.h
new file mode 100644
index 0000000000..ce9659bba0
--- /dev/null
+++ b/package/broadcom-57xx/src/bcmrobo.h
@@ -0,0 +1,70 @@
+/*
+ * RoboSwitch setup functions
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: bcmrobo.h,v 1.1.1.6 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _bcm_robo_h_
+#define _bcm_robo_h_
+#include <switch-core.h>
+
+#define DEVID5325 0x25 /* 5325 (Not really be we fake it) */
+
+/* Forward declaration */
+typedef struct robo_info_s robo_info_t;
+
+/* Device access/config oprands */
+typedef struct {
+ /* low level routines */
+ void (*enable_mgmtif)(robo_info_t *robo); /* enable mgmt i/f, optional */
+ void (*disable_mgmtif)(robo_info_t *robo); /* disable mgmt i/f, optional */
+ int (*write_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len);
+ int (*read_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len);
+ /* description */
+ char *desc;
+} dev_ops_t;
+
+
+typedef uint16 (*miird_f)(void *h, int add, int off);
+typedef void (*miiwr_f)(void *h, int add, int off, uint16 val);
+
+/* Private state per RoboSwitch */
+struct robo_info_s {
+ sb_t *sbh; /* SiliconBackplane handle */
+ char *vars; /* nvram variables handle */
+ void *h; /* dev handle */
+ uint16 devid; /* Device id for the switch */
+ char *name; /* Linux device name */
+ char macaddr[6];
+
+ dev_ops_t *ops; /* device ops */
+ uint8 page; /* current page */
+
+ /* SPI */
+ uint32 ss, sck, mosi, miso; /* GPIO mapping */
+
+ /* MII */
+ miird_f miird;
+ miiwr_f miiwr;
+};
+
+extern robo_info_t *bcm_robo_attach(sb_t *sbh, void *h, char *name, char *vars, miird_f miird, miiwr_f miiwr);
+extern void bcm_robo_detach(robo_info_t *robo);
+extern int bcm_robo_enable_device(robo_info_t *robo);
+extern int bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr);
+extern int bcm_robo_enable_switch(robo_info_t *robo);
+extern void bcm_robo_set_macaddr(robo_info_t *robo, char *macaddr);
+
+#ifdef BCMDBG
+extern void robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b);
+#endif /* BCMDBG */
+
+#endif /* _bcm_robo_h_ */
diff --git a/package/broadcom-57xx/src/bits.h b/package/broadcom-57xx/src/bits.h
new file mode 100644
index 0000000000..cd97e84862
--- /dev/null
+++ b/package/broadcom-57xx/src/bits.h
@@ -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/package/broadcom-57xx/src/fw_lso05.h b/package/broadcom-57xx/src/fw_lso05.h
new file mode 100644
index 0000000000..cfe6a9cf2f
--- /dev/null
+++ b/package/broadcom-57xx/src/fw_lso05.h
@@ -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/package/broadcom-57xx/src/fw_stkoffld.h b/package/broadcom-57xx/src/fw_stkoffld.h
new file mode 100644
index 0000000000..119a17b341
--- /dev/null
+++ b/package/broadcom-57xx/src/fw_stkoffld.h
@@ -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/package/broadcom-57xx/src/hndgige.c b/package/broadcom-57xx/src/hndgige.c
new file mode 100644
index 0000000000..19774934a3
--- /dev/null
+++ b/package/broadcom-57xx/src/hndgige.c
@@ -0,0 +1,146 @@
+/*
+ * HND SiliconBackplane Gigabit Ethernet core software interface
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: hndgige.c,v 1.6 2007/06/01 05:59:06 michael Exp $
+ */
+
+#include <typedefs.h>
+#include <osl.h>
+#include <pcicfg.h>
+#include <sbconfig.h>
+#include <sbutils.h>
+#include "sbgige.h"
+#include <hndpci.h>
+#include "hndgige.h"
+
+uint32
+sb_base(uint32 admatch)
+{
+ uint32 base;
+ uint type;
+
+ type = admatch & SBAM_TYPE_MASK;
+ ASSERT(type < 3);
+
+ base = 0;
+
+ if (type == 0) {
+ base = admatch & SBAM_BASE0_MASK;
+ } else if (type == 1) {
+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
+ base = admatch & SBAM_BASE1_MASK;
+ } else if (type == 2) {
+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
+ base = admatch & SBAM_BASE2_MASK;
+ }
+
+ return (base);
+}
+
+/*
+ * Setup the gige core.
+ * Resetting the core will lose all settings.
+ */
+void
+sb_gige_init(sb_t *sbh, uint32 unit, bool *rgmii)
+{
+ volatile pci_config_regs *pci;
+ sbgige_pcishim_t *ocp;
+ sbconfig_t *sb;
+ osl_t *osh;
+ uint32 statelow;
+ uint32 statehigh;
+ uint32 base;
+ uint32 idx;
+ void *regs;
+
+ /* Sanity checks */
+ ASSERT(sbh);
+ ASSERT(rgmii);
+
+ idx = sb_coreidx(sbh);
+
+ /* point to the gige core registers */
+ regs = sb_setcore(sbh, SB_GIGETH, unit);
+ ASSERT(regs);
+
+ osh = sb_osh(sbh);
+
+ pci = &((sbgige_t *)regs)->pcicfg;
+ ocp = &((sbgige_t *)regs)->pcishim;
+ sb = &((sbgige_t *)regs)->sbconfig;
+
+ /* Enable the core clock and memory access */
+ if (!sb_iscoreup(sbh))
+ sb_core_reset(sbh, 0, 0);
+
+ /*
+ * Setup the 64K memory-mapped region base address through BAR0.
+ * Leave the other BAR values alone.
+ */
+ base = sb_base(R_REG(osh, &sb->sbadmatch1));
+ W_REG(osh, &pci->base[0], base);
+ W_REG(osh, &pci->base[1], 0);
+
+ /*
+ * Enable the PCI memory access anyway. Any PCI config commands
+ * issued before the core is enabled will go to the emulation
+ * only and will not go to the real PCI config registers.
+ */
+ OR_REG(osh, &pci->command, 2);
+
+ /*
+ * Enable the posted write flush scheme as follows:
+ *
+ * - Enable flush on any core register read
+ * - Enable timeout on the flush
+ * - Disable the interrupt mask when flushing
+ *
+ * This differs from the default setting only in that interrupts are
+ * not masked. Since posted writes are not flushed on interrupt, the
+ * driver must explicitly request a flush in its interrupt handling
+ * by reading a core register.
+ */
+ W_REG(osh, &ocp->FlushStatusControl, 0x68);
+
+ /*
+ * Determine whether the GbE is in GMII or RGMII mode. This is
+ * indicated in bit 16 of the SBTMStateHigh register, which is
+ * part of the core-specific flags field.
+ *
+ * For GMII, bypass the Rx/Tx DLLs, i.e. add no delay to RXC/GTXC
+ * within the core. For RGMII, do not bypass the DLLs, resulting
+ * in added delay for RXC/GTXC. The SBTMStateLow register contains
+ * the controls for doing this in the core-specific flags field:
+ *
+ * bit 24 - Enable DLL controls
+ * bit 20 - Bypass Rx DLL
+ * bit 19 - Bypass Tx DLL
+ */
+ statelow = R_REG(osh, &sb->sbtmstatelow); /* DLL controls */
+ statehigh = R_REG(osh, &sb->sbtmstatehigh); /* GMII/RGMII mode */
+ if ((statehigh & (1 << 16)) != 0) /* RGMII */
+ {
+ statelow &= ~(1 << 20); /* no Rx bypass (delay) */
+ statelow &= ~(1 << 19); /* no Tx bypass (delay) */
+ *rgmii = TRUE;
+ }
+ else /* GMII */
+ {
+ statelow |= (1 << 20); /* Rx bypass (no delay) */
+ statelow |= (1 << 19); /* Tx bypass (no delay) */
+ *rgmii = FALSE;
+ }
+ statelow |= (1 << 24); /* enable DLL controls */
+ W_REG(osh, &sb->sbtmstatelow, statelow);
+
+ sb_setcoreidx(sbh, idx);
+}
diff --git a/package/broadcom-57xx/src/hndgige.h b/package/broadcom-57xx/src/hndgige.h
new file mode 100644
index 0000000000..cdda406cf5
--- /dev/null
+++ b/package/broadcom-57xx/src/hndgige.h
@@ -0,0 +1,20 @@
+/*
+ * HND SiliconBackplane Gigabit Ethernet core software interface.
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: hndgige.h,v 1.5 2007/06/01 05:58:20 michael Exp $
+ */
+
+#ifndef _hndgige_h_
+#define _hndgige_h_
+
+extern void sb_gige_init(sb_t *sbh, uint32 unit, bool *rgmii);
+
+#endif /* _hndgige_h_ */
diff --git a/package/broadcom-57xx/src/lm.h b/package/broadcom-57xx/src/lm.h
new file mode 100644
index 0000000000..81d40f1382
--- /dev/null
+++ b/package/broadcom-57xx/src/lm.h
@@ -0,0 +1,483 @@
+/******************************************************************************/
+/* */
+/* 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);
+
+/* MII read/write functions to export to the robo support code */
+LM_UINT16 robo_miird(void *h, int phyadd, int regoff);
+void robo_miiwr(void *h, int phyadd, int regoff, LM_UINT16 value);
+
+
+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
+
+/* Debugging support */
+
+extern int b57_msg_level;
+
+#define B57_ERR_VAL 1
+#define B57_INFO_VAL 2
+
+#define B57_ERR(args) do {if (b57_msg_level & B57_ERR_VAL) printf args;} while (0)
+#define B57_INFO(args) do {if (b57_msg_level & B57_INFO_VAL) printf args;} while (0)
+
+#endif /* LM_H */
+
diff --git a/package/broadcom-57xx/src/mm.h b/package/broadcom-57xx/src/mm.h
new file mode 100644
index 0000000000..35286831f2
--- /dev/null
+++ b/package/broadcom-57xx/src/mm.h
@@ -0,0 +1,609 @@
+/******************************************************************************/
+/* */
+/* 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. */
+/* */
+/******************************************************************************/
+
+/* $Id: mm.h,v 1.6 2006/09/26 05:22:21 michael Exp $ */
+
+#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 <linux/reboot.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 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;
+
+ 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;
+ 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;
+
+ void *sbh;
+ unsigned long boardflags;
+ void *robo;
+ int qos;
+} 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
+
+#ifndef printf
+#define printf(fmt, args...) printk(KERN_WARNING fmt, ##args)
+#endif
+
+#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/package/broadcom-57xx/src/proto/802.11.h b/package/broadcom-57xx/src/proto/802.11.h
new file mode 100644
index 0000000000..ebabf730a3
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/802.11.h
@@ -0,0 +1,1387 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id: 802.11.h,v 1.1.1.25 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _802_11_H_
+#define _802_11_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+#include <proto/wpa.h>
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */
+
+/* Generic 802.11 frame constants */
+#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */
+#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */
+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */
+#define DOT11_FCS_LEN 4 /* d11 FCS length */
+#define DOT11_ICV_LEN 4 /* d11 ICV length */
+#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */
+#define DOT11_QOS_LEN 2 /* d11 QoS length */
+#define DOT11_HTC_LEN 4 /* d11 HT Control field length */
+
+#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */
+#define DOT11_IV_LEN 4 /* d11 IV length */
+#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */
+#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */
+#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */
+#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */
+
+/* Includes MIC */
+#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */
+/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */
+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ DOT11_IV_AES_CCM_LEN + \
+ DOT11_MAX_MPDU_BODY_LEN + \
+ DOT11_ICV_LEN + \
+ DOT11_FCS_LEN) /* d11 max MPDU length */
+
+#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */
+
+/* dot11RTSThreshold */
+#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */
+#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */
+
+/* dot11FragmentationThreshold */
+#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */
+#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength
+ * of the attached PHY
+ */
+#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */
+
+/* dot11BeaconPeriod */
+#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */
+
+/* dot11DTIMPeriod */
+#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */
+#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */
+
+/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */
+#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */
+#define DOT11_OUI_LEN 3 /* d11 OUI length */
+struct dot11_llc_snap_header {
+ uint8 dsap; /* always 0xAA */
+ uint8 ssap; /* always 0xAA */
+ uint8 ctl; /* always 0x03 */
+ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00
+ * Bridge-Tunnel: 0x00 0x00 0xF8
+ */
+ uint16 type; /* ethertype */
+} PACKED;
+
+/* RFC1042 header used by 802.11 per 802.1H */
+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */
+
+/* Generic 802.11 MAC header */
+/*
+ * N.B.: This struct reflects the full 4 address 802.11 MAC header.
+ * The fields are defined such that the shorter 1, 2, and 3
+ * address headers just use the first k fields.
+ */
+struct dot11_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr a1; /* address 1 */
+ struct ether_addr a2; /* address 2 */
+ struct ether_addr a3; /* address 3 */
+ uint16 seq; /* sequence control */
+ struct ether_addr a4; /* address 4 */
+} PACKED;
+
+/* Control frames */
+
+struct dot11_rts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_RTS_LEN 16 /* d11 RTS frame length */
+
+struct dot11_cts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_CTS_LEN 10 /* d11 CTS frame length */
+
+struct dot11_ack_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} PACKED;
+#define DOT11_ACK_LEN 10 /* d11 ACK frame length */
+
+struct dot11_ps_poll_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* AID */
+ struct ether_addr bssid; /* receiver address, STA in AP */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */
+
+struct dot11_cf_end_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr bssid; /* transmitter address, STA in AP */
+} PACKED;
+#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */
+
+/* BA/BAR Control parameters */
+#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */
+#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */
+#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */
+
+#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */
+#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */
+
+#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */
+#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */
+
+#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */
+#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */
+
+/* control frame header (BA/BAR) */
+struct dot11_ctl_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+} PACKED;
+#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */
+
+/* BAR frame payload */
+struct dot11_bar {
+ uint16 bar_control; /* BAR Control */
+ uint16 seqnum; /* Starting Sequence control */
+} PACKED;
+#define DOT11_BAR_LEN 4 /* BAR frame payload length */
+
+#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */
+#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */
+/* BA frame payload */
+struct dot11_ba {
+ uint16 ba_control; /* BA Control */
+ uint16 seqnum; /* Starting Sequence control */
+ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */
+} PACKED;
+#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */
+
+/* Management frame header */
+struct dot11_management_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr da; /* receiver address */
+ struct ether_addr sa; /* transmitter address */
+ struct ether_addr bssid; /* BSS ID */
+ uint16 seq; /* sequence control */
+} PACKED;
+#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */
+
+/* Management frame payloads */
+
+struct dot11_bcn_prb {
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 capability;
+} PACKED;
+#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */
+
+struct dot11_auth {
+ uint16 alg; /* algorithm */
+ uint16 seq; /* sequence control */
+ uint16 status; /* status code */
+} PACKED;
+#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge info
+ * elt
+ */
+
+struct dot11_assoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+} PACKED;
+#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */
+
+struct dot11_reassoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+ struct ether_addr ap; /* Current AP address */
+} PACKED;
+#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */
+
+struct dot11_assoc_resp {
+ uint16 capability; /* capability information */
+ uint16 status; /* status code */
+ uint16 aid; /* association ID */
+} PACKED;
+
+struct dot11_action_measure {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} PACKED;
+#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */
+
+struct dot11_action_ht_ch_width {
+ uint8 category;
+ uint8 action;
+ uint8 ch_width;
+} PACKED;
+
+struct dot11_action_ht_mimops {
+ uint8 category;
+ uint8 action;
+ uint8 control;
+} PACKED;
+
+#define SM_PWRSAVE_ENABLE 1
+#define SM_PWRSAVE_MODE 2
+
+struct dot11_action_ht_info_xchg {
+ uint8 category;
+ uint8 action;
+ uint8 info;
+} PACKED;
+
+#define DOT11_HT_INFO_XCHG_INFO_REQ 0x01
+#define DOT11_HT_INFO_XCHG_40MHZ_INTOLERANT 0x02
+#define DOT11_HT_INFO_XCHG_STA_CHAN_WIDTH 0x04
+
+
+/* ************* 802.11h related definitions. ************* */
+struct dot11_power_cnst {
+ uint8 id;
+ uint8 len;
+ uint8 power;
+} PACKED;
+typedef struct dot11_power_cnst dot11_power_cnst_t;
+
+struct dot11_power_cap {
+ uint8 min;
+ uint8 max;
+} PACKED;
+typedef struct dot11_power_cap dot11_power_cap_t;
+
+struct dot11_tpc_rep {
+ uint8 id;
+ uint8 len;
+ uint8 tx_pwr;
+ uint8 margin;
+} PACKED;
+typedef struct dot11_tpc_rep dot11_tpc_rep_t;
+#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */
+
+struct dot11_supp_channels {
+ uint8 id;
+ uint8 len;
+ uint8 first_channel;
+ uint8 num_channels;
+} PACKED;
+typedef struct dot11_supp_channels dot11_supp_channels_t;
+
+/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband
+ * offset for 40MHz operation. The possible 3 values are:
+ * 1 = above control channel
+ * 3 = below control channel
+ * 0 = no extension channel
+ */
+struct dot11_extch {
+ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */
+ uint8 len; /* IE length */
+ uint8 extch;
+} PACKED;
+typedef struct dot11_extch dot11_extch_ie_t;
+
+struct dot11_brcm_extch {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */
+ uint8 type; /* type inidicates what follows */
+ uint8 extch;
+} PACKED;
+typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t;
+
+#define BRCM_EXTCH_IE_LEN 5
+#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */
+#define DOT11_EXTCH_IE_LEN 1
+#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */
+#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */
+#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */
+#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */
+
+struct dot11_action_frmhdr {
+ uint8 category;
+ uint8 action;
+ uint8 data[1];
+} PACKED;
+
+/* CSA IE data structure */
+struct dot11_channel_switch {
+ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */
+ uint8 len; /* length of IE */
+ uint8 mode; /* mode 0 or 1 */
+ uint8 channel; /* channel switch to */
+ uint8 count; /* number of beacons before switching */
+} PACKED;
+typedef struct dot11_channel_switch dot11_chan_switch_ie_t;
+
+#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */
+/* CSA mode - 802.11h-2003 $7.3.2.20 */
+#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */
+#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */
+
+struct dot11_action_switch_channel {
+ uint8 category;
+ uint8 action;
+ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */
+ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */
+} PACKED;
+
+/* 11n Extended Channel Switch IE data structure */
+struct dot11_ext_csa {
+ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */
+ uint8 len; /* length of IE */
+ uint8 mode; /* mode 0 or 1 */
+ uint8 reg; /* regulatory class */
+ uint8 channel; /* channel switch to */
+ uint8 count; /* number of beacons before switching */
+} PACKED;
+typedef struct dot11_ext_csa dot11_ext_csa_ie_t;
+#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */
+
+struct dot11_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */
+} PACKED;
+
+/* 802.11h Measurement Request/Report IEs */
+/* Measurement Type field */
+#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */
+#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */
+#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement PRI type */
+
+/* Measurement Request Modes */
+#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */
+#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */
+#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */
+/* Measurement Report Modes */
+#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */
+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */
+#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */
+/* Basic Measurement Map bits */
+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */
+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */
+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */
+
+struct dot11_meas_req {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+} PACKED;
+typedef struct dot11_meas_req dot11_meas_req_t;
+#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */
+/* length of Measure Request IE data not including variable len */
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */
+
+struct dot11_meas_rep {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ union
+ {
+ struct {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+ } PACKED basic;
+ uint8 data[1];
+ } PACKED rep;
+} PACKED;
+typedef struct dot11_meas_rep dot11_meas_rep_t;
+
+/* length of Measure Report IE data not including variable len */
+#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */
+
+struct dot11_meas_rep_basic {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+} PACKED;
+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
+#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */
+
+struct dot11_quiet {
+ uint8 id;
+ uint8 len;
+ uint8 count; /* TBTTs until beacon interval in quiet starts */
+ uint8 period; /* Beacon intervals between periodic quiet periods ? */
+ uint16 duration; /* Length of quiet period, in TU's */
+ uint16 offset; /* TU's offset from TBTT in Count field */
+} PACKED;
+typedef struct dot11_quiet dot11_quiet_t;
+
+struct chan_map_tuple {
+ uint8 channel;
+ uint8 map;
+} PACKED;
+typedef struct chan_map_tuple chan_map_tuple_t;
+
+struct dot11_ibss_dfs {
+ uint8 id;
+ uint8 len;
+ uint8 eaddr[ETHER_ADDR_LEN];
+ uint8 interval;
+ chan_map_tuple_t map[1];
+} PACKED;
+typedef struct dot11_ibss_dfs dot11_ibss_dfs_t;
+
+/* WME Elements */
+#define WME_OUI "\x00\x50\xf2" /* WME OUI */
+#define WME_VER 1 /* WME version */
+#define WME_TYPE 2 /* WME type */
+#define WME_SUBTYPE_IE 0 /* Information Element */
+#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */
+#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */
+
+/* WME Access Category Indices (ACIs) */
+#define AC_BE 0 /* Best Effort */
+#define AC_BK 1 /* Background */
+#define AC_VI 2 /* Video */
+#define AC_VO 3 /* Voice */
+#define AC_COUNT 4 /* number of ACs */
+
+typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */
+
+#define AC_BITMAP_NONE 0x0 /* No ACs */
+#define AC_BITMAP_ALL 0xf /* All ACs */
+#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0)
+
+/* WME Information Element (IE) */
+struct wme_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+} PACKED;
+typedef struct wme_ie wme_ie_t;
+#define WME_IE_LEN 7 /* WME IE length */
+
+struct edcf_acparam {
+ uint8 ACI;
+ uint8 ECW;
+ uint16 TXOP; /* stored in network order (ls octet first) */
+} PACKED;
+typedef struct edcf_acparam edcf_acparam_t;
+
+/* WME Parameter Element (PE) */
+struct wme_param_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} PACKED;
+typedef struct wme_param_ie wme_param_ie_t;
+#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */
+
+/* QoS Info field for IE as sent from AP */
+#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */
+#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */
+#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */
+#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */
+
+/* QoS Info field for IE as sent from STA */
+#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */
+#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */
+#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */
+#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */
+#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */
+#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */
+#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */
+#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */
+#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */
+#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */
+#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */
+#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */
+
+/* ACI */
+#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */
+#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */
+#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */
+#define EDCF_ACM_MASK 0x10 /* ACM mask */
+#define EDCF_ACI_MASK 0x60 /* ACI mask */
+#define EDCF_ACI_SHIFT 5 /* ACI shift */
+
+/* ECW */
+#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */
+#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */
+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
+#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */
+#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */
+#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */
+
+/* TXOP */
+#define EDCF_TXOP_MIN 0 /* TXOP minimum value */
+#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */
+#define EDCF_TXOP2USEC(txop) ((txop) << 5)
+
+/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */
+#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */
+#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */
+#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */
+#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */
+#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */
+#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */
+#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */
+#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */
+
+/* Default EDCF parameters that AP uses; WMM draft Table 14 */
+#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */
+#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */
+#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */
+#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */
+#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */
+#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */
+#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */
+#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */
+
+struct dot11_qbss_load_ie {
+ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */
+ uint8 length;
+ uint16 station_count; /* total number of STAs associated */
+ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */
+ uint16 aac; /* available admission capacity */
+} PACKED;
+typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t;
+
+/* nom_msdu_size */
+#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */
+#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */
+
+/* surplus_bandwidth */
+/* Represented as 3 bits of integer, binary point, 13 bits fraction */
+#define INTEGER_SHIFT 13 /* integer shift */
+#define FRACTION_MASK 0x1FFF /* fraction mask */
+
+/* Management Notification Frame */
+struct dot11_management_notification {
+ uint8 category; /* DOT11_ACTION_NOTIFICATION */
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 data[1]; /* Elements */
+} PACKED;
+#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */
+
+/* WME Action Codes */
+#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */
+#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */
+#define WME_DELTS_REQUEST 2 /* WME DELTS request */
+
+/* WME Setup Response Status Codes */
+#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */
+#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */
+#define WME_ADMISSION_REFUSED 3 /* WME admission refused */
+
+/* Macro to take a pointer to a beacon or probe response
+ * body and return the char* pointer to the SSID info element
+ */
+#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN)
+
+/* Authentication frame payload constants */
+#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */
+#define DOT11_SHARED_KEY 1 /* d11 shared authentication */
+#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */
+
+/* Frame control macros */
+#define FC_PVER_MASK 0x3 /* PVER mask */
+#define FC_PVER_SHIFT 0 /* PVER shift */
+#define FC_TYPE_MASK 0xC /* type mask */
+#define FC_TYPE_SHIFT 2 /* type shift */
+#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */
+#define FC_SUBTYPE_SHIFT 4 /* subtype shift */
+#define FC_TODS 0x100 /* to DS */
+#define FC_TODS_SHIFT 8 /* to DS shift */
+#define FC_FROMDS 0x200 /* from DS */
+#define FC_FROMDS_SHIFT 9 /* from DS shift */
+#define FC_MOREFRAG 0x400 /* more frag. */
+#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */
+#define FC_RETRY 0x800 /* retry */
+#define FC_RETRY_SHIFT 11 /* retry shift */
+#define FC_PM 0x1000 /* PM */
+#define FC_PM_SHIFT 12 /* PM shift */
+#define FC_MOREDATA 0x2000 /* more data */
+#define FC_MOREDATA_SHIFT 13 /* more data shift */
+#define FC_WEP 0x4000 /* WEP */
+#define FC_WEP_SHIFT 14 /* WEP shift */
+#define FC_ORDER 0x8000 /* order */
+#define FC_ORDER_SHIFT 15 /* order shift */
+
+/* sequence control macros */
+#define SEQNUM_SHIFT 4 /* seq. number shift */
+#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */
+#define FRAGNUM_MASK 0xF /* frag. number mask */
+
+/* Frame Control type/subtype defs */
+
+/* FC Types */
+#define FC_TYPE_MNG 0 /* management type */
+#define FC_TYPE_CTL 1 /* control type */
+#define FC_TYPE_DATA 2 /* data type */
+
+/* Management Subtypes */
+#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */
+#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */
+#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */
+#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */
+#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */
+#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */
+#define FC_SUBTYPE_BEACON 8 /* beacon */
+#define FC_SUBTYPE_ATIM 9 /* ATIM */
+#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */
+#define FC_SUBTYPE_AUTH 11 /* authentication */
+#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */
+#define FC_SUBTYPE_ACTION 13 /* action */
+#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */
+
+/* Control Subtypes */
+#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */
+#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */
+#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */
+#define FC_SUBTYPE_PS_POLL 10 /* PS poll */
+#define FC_SUBTYPE_RTS 11 /* RTS */
+#define FC_SUBTYPE_CTS 12 /* CTS */
+#define FC_SUBTYPE_ACK 13 /* ACK */
+#define FC_SUBTYPE_CF_END 14 /* CF-END */
+#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */
+
+/* Data Subtypes */
+#define FC_SUBTYPE_DATA 0 /* Data */
+#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */
+#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */
+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_NULL 4 /* Null */
+#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */
+#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */
+#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */
+#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */
+#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */
+#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */
+
+/* Data Subtype Groups */
+#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0)
+#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0)
+#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0)
+#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0)
+
+/* Type/Subtype Combos */
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */
+
+#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */
+#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */
+
+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */
+#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */
+
+#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */
+#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */
+#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */
+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */
+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */
+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */
+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */
+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */
+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */
+
+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */
+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */
+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */
+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */
+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */
+
+/* QoS Control Field */
+
+/* 802.1D Priority */
+#define QOS_PRIO_SHIFT 0 /* QoS priority shift */
+#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */
+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */
+
+/* Traffic Identifier */
+#define QOS_TID_SHIFT 0 /* QoS TID shift */
+#define QOS_TID_MASK 0x000f /* QoS TID mask */
+#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */
+
+/* End of Service Period (U-APSD) */
+#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */
+#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */
+#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */
+
+/* Ack Policy */
+#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */
+#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */
+#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */
+#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */
+#define QOS_ACK_SHIFT 5 /* QoS ACK shift */
+#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */
+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */
+
+/* A-MSDU flag */
+#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */
+#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */
+
+/* Management Frames */
+
+/* Management Frame Constants */
+
+/* Fixed fields */
+#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */
+#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */
+#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */
+#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */
+#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */
+#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */
+#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */
+#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */
+#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */
+#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */
+
+/* DUR/ID field in assoc resp is 0xc000 | AID */
+#define DOT11_AID_MASK 0x3fff /* d11 AID mask */
+
+/* Reason Codes */
+#define DOT11_RC_RESERVED 0 /* d11 RC reserved */
+#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */
+#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */
+#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station
+ * is leaving (or has left) IBSS or ESS
+ */
+#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */
+#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle
+ * all currently associated stations
+ */
+#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from
+ * nonauthenticated station
+ */
+#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from
+ * nonassociated station
+ */
+#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is
+ * leaving (or has left) BSS
+ */
+#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not
+ * authenticated with responding station
+ */
+#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */
+#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */
+/* 12 is unused */
+
+/* 32-39 are QSTA specific reasons added in 11e */
+#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */
+#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */
+#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */
+#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */
+#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */
+#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */
+#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */
+#define DOT11_RC_TIMEOUT 39 /* timeout */
+
+#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */
+
+/* Status Codes */
+#define DOT11_SC_SUCCESS 0 /* Successful */
+#define DOT11_SC_FAILURE 1 /* Unspecified failure */
+#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested
+ * capabilities in the Capability
+ * Information field
+ */
+#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability
+ * to confirm that association exists
+ */
+#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason
+ * outside the scope of this standard
+ */
+#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support
+ * the specified authentication
+ * algorithm
+ */
+#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame
+ * with authentication transaction
+ * sequence number out of expected
+ * sequence
+ */
+#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of
+ * challenge failure
+ */
+#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout
+ * waiting for next frame in sequence
+ */
+#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is
+ * unable to handle additional
+ * associated stations
+ */
+#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting
+ * station not supporting all of the
+ * data rates in the BSSBasicRateSet
+ * parameter
+ */
+#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting
+ * station not supporting the Short
+ * Preamble option
+ */
+#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting
+ * station not supporting the PBCC
+ * Modulation option
+ */
+#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting
+ * station not supporting the Channel
+ * Agility option
+ */
+#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum
+ * Management capability is required.
+ */
+#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info
+ * in the Power Cap element is
+ * unacceptable.
+ */
+#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info
+ * in the Supported Channel element is
+ * unacceptable
+ */
+#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting
+ * station not supporting the Short Slot
+ * Time option
+ */
+#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting
+ * station not supporting the ER-PBCC
+ * Modulation option
+ */
+#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting
+ * station not supporting the DSS-OFDM
+ * option
+ */
+
+#define DOT11_SC_DECLINED 37 /* request declined */
+#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */
+
+/* Info Elts, length of INFORMATION portion of Info Elts */
+#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */
+#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */
+
+/* TIM Info element has 3 bytes fixed info in INFORMATION field,
+ * followed by 1 to 251 bytes of Partial Virtual Bitmap
+ */
+#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */
+#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */
+#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */
+#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */
+#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */
+
+/* TLV defines */
+#define TLV_TAG_OFF 0 /* tag offset */
+#define TLV_LEN_OFF 1 /* length offset */
+#define TLV_HDR_LEN 2 /* header length */
+#define TLV_BODY_OFF 2 /* body offset */
+
+/* Management Frame Information Element IDs */
+#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */
+#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */
+#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */
+#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */
+#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */
+#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */
+#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */
+#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */
+#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */
+#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */
+#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */
+#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */
+#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */
+#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */
+#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */
+#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */
+#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */
+#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */
+#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */
+#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */
+#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */
+#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */
+#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */
+#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */
+#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */
+#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */
+#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */
+#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */
+#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */
+#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */
+#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */
+#define DOT11_MNG_EXT_CAP 127 /* d11 mgmt ext capability */
+#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */
+#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */
+
+/* Rate element Basic flag and rate mask */
+#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */
+#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */
+
+/* ERP info element bit values */
+#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */
+#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present
+ *in the BSS
+ */
+#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for
+ *ERP-OFDM frames
+ */
+#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed,
+ * 1 == not allowed
+ */
+/* TS Delay element offset & size */
+#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */
+#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */
+
+/* Capability Information Field */
+#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */
+#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */
+#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */
+#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */
+#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */
+#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */
+#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */
+#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */
+#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */
+#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */
+#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */
+
+/* Extended Capability Information Field */
+#define DOT11_EXT_CAP_HT_IE_SUPPORT 0x01 /* support for info xchg action frame */
+
+/* Action Frame Constants */
+#define DOT11_ACTION_HDR_LEN 2 /* action frame header length */
+#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* d11 action category error mask */
+#define DOT11_ACTION_CAT_MASK 0x7F /* d11 action category mask */
+#define DOT11_ACTION_CAT_SPECT_MNG 0x00 /* d11 action category spectrum management */
+#define DOT11_ACTION_CAT_BLOCKACK 0x03 /* d11 action category block ack */
+#define DOT11_ACTION_CAT_HT 0x07 /* d11 action category for HT */
+#define DOT11_ACTION_NOTIFICATION 0x11 /* 17 */
+
+#define DOT11_ACTION_ID_M_REQ 0 /* d11 action measurement request */
+#define DOT11_ACTION_ID_M_REP 1 /* d11 action measurement response */
+#define DOT11_ACTION_ID_TPC_REQ 2 /* d11 action TPC request */
+#define DOT11_ACTION_ID_TPC_REP 3 /* d11 action TPC response */
+#define DOT11_ACTION_ID_CHANNEL_SWITCH 4 /* d11 action channel switch */
+#define DOT11_ACTION_ID_EXT_CSA 5 /* d11 extened CSA for 11n */
+
+/* HT action ids */
+#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */
+#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */
+#define DOT11_ACTION_ID_HT_INFO_XCHG 8 /* HT Information Exchange action id */
+
+/* Block Ack action types */
+#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */
+#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */
+#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */
+
+/* ADDBA action parameters */
+#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */
+#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */
+#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */
+#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */
+#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */
+#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */
+#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */
+
+#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */
+#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */
+
+struct dot11_addba_req {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba req */
+ uint8 token; /* identifier */
+ uint16 addba_param_set; /* parameter set */
+ uint16 timeout; /* timeout in seconds */
+ uint16 start_seqnum; /* starting sequence number */
+}PACKED;
+typedef struct dot11_addba_req dot11_addba_req_t;
+#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */
+
+struct dot11_addba_resp {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba resp */
+ uint8 token; /* identifier */
+ uint16 status; /* status of add request */
+ uint16 addba_param_set; /* negotiated parameter set */
+ uint16 timeout; /* negotiated timeout in seconds */
+}PACKED;
+typedef struct dot11_addba_resp dot11_addba_resp_t;
+#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */
+
+/* DELBA action parameters */
+#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */
+#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */
+#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */
+#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */
+
+struct dot11_delba {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba req */
+ uint16 delba_param_set; /* paarmeter set */
+ uint16 reason; /* reason for dellba */
+}PACKED;
+typedef struct dot11_delba dot11_delba_t;
+#define DOT11_DELBA_LEN 6 /* length of delba frame */
+
+/* MLME Enumerations */
+#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */
+#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */
+#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */
+#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */
+#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */
+
+/* 802.11 BRCM "Compromise" Pre N constants */
+#define PREN_PREAMBLE 24 /* green field preamble time */
+#define PREN_MM_EXT 8 /* extra mixed mode preamble time */
+#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */
+
+/* 802.11 N PHY constants */
+#define NPHY_RIFS_TIME 2 /* NPHY RIFS time */
+
+/* 802.11 A PHY constants */
+#define APHY_SLOT_TIME 9 /* APHY slot time */
+#define APHY_SIFS_TIME 16 /* APHY SIFS time */
+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */
+#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */
+#define APHY_SIGNAL_TIME 4 /* APHY signal time */
+#define APHY_SYMBOL_TIME 4 /* APHY symbol time */
+#define APHY_SERVICE_NBITS 16 /* APHY service nbits */
+#define APHY_TAIL_NBITS 6 /* APHY tail nbits */
+#define APHY_CWMIN 15 /* APHY cwmin */
+
+/* 802.11 B PHY constants */
+#define BPHY_SLOT_TIME 20 /* BPHY slot time */
+#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */
+#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */
+#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */
+#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */
+#define BPHY_CWMIN 31 /* BPHY cwmin */
+
+/* 802.11 G constants */
+#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */
+
+#define PHY_CWMAX 1023 /* PHY cwmax */
+
+#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */
+
+/* dot11Counters Table - 802.11 spec., Annex D */
+typedef struct d11cnt {
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+} d11cnt_t;
+
+/* BRCM OUI */
+#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */
+
+/* OUI for BRCM proprietary IE */
+#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */
+
+/* BRCM info element */
+struct brcm_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */
+ uint8 ver; /* type/ver of this IE */
+ uint8 assoc; /* # of assoc STAs */
+ uint8 flags; /* misc flags */
+ uint8 flags1; /* misc flags */
+ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */
+} PACKED;
+typedef struct brcm_ie brcm_ie_t;
+#define BRCM_IE_LEN 11 /* BRCM IE length */
+#define BRCM_IE_VER 2 /* BRCM IE version */
+#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */
+
+/* brcm_ie flags */
+#define BRF_ABCAP 0x1 /* afterburner capable */
+#define BRF_ABRQRD 0x2 /* afterburner requested */
+#define BRF_LZWDS 0x4 /* lazy wds enabled */
+#define BRF_BLOCKACK 0x8 /* BlockACK capable */
+#define BRF_ABCOUNTER_MASK 0xf0 /* afterburner wds "state" counter */
+#define BRF_ABCOUNTER_SHIFT 4 /* offset of afterburner wds "state" counter */
+
+/* brcm_ie flags1 */
+#define BRF1_AMSDU 0x1 /* A-MSDU capable */
+#define BRF1_DPT 0x2 /* DPT capable */
+
+#define AB_WDS_TIMEOUT_MAX 15 /* afterburner wds Max count indicating not
+ * locally capable
+ */
+#define AB_WDS_TIMEOUT_MIN 1 /* afterburner wds, use zero count as indicating
+ * "downrev"
+ */
+
+/* EWC definitions */
+#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */
+#define MAX_MCS_NUM (128) /* max mcs number = 128 */
+
+struct ewc_cap_ie {
+ uint16 cap;
+ uint8 params;
+ uint8 supp_mcs[MCSSET_LEN];
+ uint16 ext_htcap;
+ uint32 txbf_cap;
+ uint8 as_cap;
+} PACKED;
+typedef struct ewc_cap_ie ewc_cap_ie_t;
+
+/* CAP IE: EWC 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the capability IE is primarily used to convey this nodes abilities */
+struct ewc_prop_cap_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */
+ uint8 type; /* type inidicates what follows */
+ ewc_cap_ie_t cap_ie;
+} PACKED;
+typedef struct ewc_prop_cap_ie ewc_prop_cap_ie_t;
+#define EWC_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */
+#define EWC_CAP_IE_LEN 26
+#define EWC_CAP_IE_TYPE 51
+
+#define EWC_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */
+#define EWC_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */
+#define EWC_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */
+#define EWC_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */
+#define EWC_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */
+#define EWC_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */
+#define EWC_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */
+#define EWC_CAP_GF 0x0010 /* Greenfield preamble support */
+#define EWC_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */
+#define EWC_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */
+#define EWC_CAP_TX_STBC 0x0080 /* Tx STBC support */
+#define EWC_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */
+#define EWC_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */
+#define EWC_CAP_DELAYED_BA 0x0400 /* delayed BA support */
+#define EWC_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */
+#define EWC_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */
+#define EWC_CAP_PSMP 0x2000 /* Power Save Multi Poll support */
+#define EWC_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */
+#define EWC_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */
+
+#define EWC_CAP_RX_STBC_NO 0x0 /* no rx STBC support */
+#define EWC_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */
+#define EWC_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */
+#define EWC_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */
+
+#define EWC_MAX_AMSDU 7935 /* max amsdu size (bytes) per the EWC spec */
+#define EWC_MIN_AMSDU 3835 /* min amsdu size (bytes) per the EWC spec */
+
+#define EWC_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */
+#define EWC_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */
+#define EWC_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */
+
+/* EWC/AMPDU specific define */
+#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/8 usec units */
+#define AMPDU_MAX_RX_FACTOR 3 /* max rcv ampdu len (64kb) */
+#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */
+#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */
+
+struct ewc_add_ie {
+ uint8 ctl_ch; /* control channel number */
+ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */
+ uint16 opmode; /* operation mode */
+ uint16 misc_bits; /* misc bits */
+ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */
+} PACKED;
+typedef struct ewc_add_ie ewc_add_ie_t;
+
+/* ADD IE: EWC 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the additional IE is primarily used to convey the current BSS configuration */
+struct ewc_prop_add_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */
+ uint8 type; /* indicates what follows */
+ ewc_add_ie_t add_ie;
+} PACKED;
+typedef struct ewc_prop_add_ie ewc_prop_add_ie_t;
+
+#define EWC_ADD_IE_LEN 22
+#define EWC_ADD_IE_TYPE 52
+
+/* byte1 defn's */
+#define EWC_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */
+#define EWC_RIFS_PERMITTED 0x08 /* RIFS allowed */
+
+/* opmode defn's */
+#define EWC_OPMODE_MASK 0x0003 /* protection mode mask */
+#define EWC_OPMODE_SHIFT 0 /* protection mode shift */
+#define EWC_OPMODE_PURE 0x0000 /* protection mode PURE */
+#define EWC_OPMODE_OPTIONAL 0x0001 /* protection mode optional */
+#define EWC_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */
+#define EWC_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */
+#define EWC_OPMODE_NONGF 0x0004 /* protection mode non-GF */
+#define DOT11N_TXBURST 0x0008 /* Tx burst limit */
+#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */
+
+/* misc_bites defn's */
+#define EWC_BASIC_STBC_MCS 0x007f /* basic STBC MCS */
+#define EWC_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */
+#define EWC_SECOND_BCN 0x0100 /* Secondary beacon support */
+#define EWC_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */
+#define EWC_PCO_ACTIVE 0x0400 /* PCO active */
+#define EWC_PCO_PHASE 0x0800 /* PCO phase */
+
+/* Tx Burst Limits */
+#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */
+#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */
+
+/* Macros for opmode */
+#define GET_EWC_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \
+ >> EWC_OPMODE_SHIFT)
+#define EWC_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \
+ == EWC_OPMODE_MIXED) /* mixed mode present */
+#define EWC_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \
+ == EWC_OPMODE_HT20IN40) /* 20MHz HT present */
+#define EWC_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \
+ == EWC_OPMODE_OPTIONAL) /* Optional protection present */
+#define EWC_USE_PROTECTION(add_ie) (EWC_HT20_PRESENT((add_ie)) || \
+ EWC_MIXEDMODE_PRESENT((add_ie))) /* use protection */
+#define EWC_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_NONGF) \
+ == EWC_OPMODE_NONGF) /* non-GF present */
+#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \
+ == DOT11N_TXBURST) /* Tx Burst present */
+#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \
+ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */
+
+/* Vendor IE structure */
+struct vndr_ie {
+ uchar id;
+ uchar len;
+ uchar oui [3];
+ uchar data [1]; /* Variable size data */
+} PACKED;
+typedef struct vndr_ie vndr_ie_t;
+
+#define VNDR_IE_HDR_LEN 2 /* id + len field */
+#define VNDR_IE_MIN_LEN 3 /* size of the oui field */
+#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */
+
+/* WPA definitions */
+#define WPA_VERSION 1 /* WPA version */
+#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
+
+#define WPA2_VERSION 1 /* WPA2 version */
+#define WPA2_VERSION_LEN 2 /* WAP2 version length */
+#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */
+
+#define WPA_OUI_LEN 3 /* WPA OUI length */
+
+/* RSN authenticated key managment suite */
+#define RSN_AKM_NONE 0 /* None (IBSS) */
+#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */
+#define RSN_AKM_PSK 2 /* Pre-shared Key */
+
+/* Key related defines */
+#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */
+#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */
+#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */
+#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */
+
+#define WEP1_KEY_SIZE 5 /* max size of any WEP key */
+#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */
+#define WEP128_KEY_SIZE 13 /* max size of any WEP key */
+#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */
+#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */
+#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */
+#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */
+#define TKIP_KEY_SIZE 32 /* size of any TKIP key */
+#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */
+#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */
+#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */
+#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */
+#define AES_KEY_SIZE 16 /* size of AES key */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _802_11_H_ */
diff --git a/package/broadcom-57xx/src/proto/802.11e.h b/package/broadcom-57xx/src/proto/802.11e.h
new file mode 100644
index 0000000000..278ab9c8c5
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/802.11e.h
@@ -0,0 +1,123 @@
+/*
+ * 802.11e protocol header file
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: 802.11e.h,v 1.1.1.2 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _802_11e_H_
+#define _802_11e_H_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+#ifdef BCMDBG
+extern const char *aci_names[];
+#endif /* BCMDBG */
+
+/* WME Traffic Specification (TSPEC) element */
+#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */
+#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */
+
+#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */
+#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */
+#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */
+#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */
+
+struct tsinfo {
+ uint8 octets[3];
+} PACKED;
+
+typedef struct tsinfo tsinfo_t;
+
+/* 802.11e TSPEC IE */
+typedef struct tspec {
+ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */
+ uint8 type; /* WME_TYPE */
+ uint8 subtype; /* WME_SUBTYPE_TSPEC */
+ uint8 version; /* WME_VERSION */
+ tsinfo_t tsinfo; /* TS Info bit field */
+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */
+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */
+ uint32 min_srv_interval; /* Minimum Service Interval (us) */
+ uint32 max_srv_interval; /* Maximum Service Interval (us) */
+ uint32 inactivity_interval; /* Inactivity Interval (us) */
+ uint32 suspension_interval; /* Suspension Interval (us) */
+ uint32 srv_start_time; /* Service Start Time (us) */
+ uint32 min_data_rate; /* Minimum Data Rate (bps) */
+ uint32 mean_data_rate; /* Mean Data Rate (bps) */
+ uint32 peak_data_rate; /* Peak Data Rate (bps) */
+ uint32 max_burst_size; /* Maximum Burst Size (bytes) */
+ uint32 delay_bound; /* Delay Bound (us) */
+ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */
+ uint16 surplus_bw; /* Surplus Bandwidth Allowance Factor */
+ uint16 medium_time; /* Medium Time (32 us/s periods) */
+} PACKED tspec_t;
+
+#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */
+
+/* ts_info */
+/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */
+#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */
+#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */
+#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */
+#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */
+#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */
+#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */
+#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */
+#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */
+#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */
+#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */
+#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */
+#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */
+/* TS info. user priority mask */
+#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT)
+
+/* Macro to get/set bit(s) field in TSINFO */
+#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT)
+#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \
+ TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT)
+#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & WLC_CAC_PSB_MASK) >> WLC_CAC_PSB_SHIFT)
+#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \
+ TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT)
+
+#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \
+ ((id) << TS_INFO_TID_SHIFT))
+#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \
+ ((prio) << TS_INFO_USER_PRIO_SHIFT))
+
+/* 802.11e QBSS Load IE */
+#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */
+#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */
+
+#define CAC_ADDTS_RESP_TIMEOUT 300 /* default ADDTS response timeout in ms */
+
+/* 802.11e ADDTS status code */
+#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */
+#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */
+#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */
+
+/* 802.11e DELTS status code */
+#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */
+#define DOT11E_STATUS_END_TS 37 /* END TS */
+#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */
+#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _802_11e_CAC_H_ */
diff --git a/package/broadcom-57xx/src/proto/802.1d.h b/package/broadcom-57xx/src/proto/802.1d.h
new file mode 100644
index 0000000000..831c43bf80
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/802.1d.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * Fundamental types and constants relating to 802.1D
+ *
+ * $Id: 802.1d.h,v 1.1.1.2 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _802_1_D_
+#define _802_1_D_
+
+/* 802.1D priority defines */
+#define PRIO_8021D_NONE 2 /* None = - */
+#define PRIO_8021D_BK 1 /* BK - Background */
+#define PRIO_8021D_BE 0 /* BE - Best-effort */
+#define PRIO_8021D_EE 3 /* EE - Excellent-effort */
+#define PRIO_8021D_CL 4 /* CL - Controlled Load */
+#define PRIO_8021D_VI 5 /* Vi - Video */
+#define PRIO_8021D_VO 6 /* Vo - Voice */
+#define PRIO_8021D_NC 7 /* NC - Network Control */
+#define MAXPRIO 7 /* 0-7 */
+#define NUMPRIO (MAXPRIO + 1)
+
+#define ALLPRIO -1 /* All prioirty */
+
+/* Converts prio to precedence since the numerical value of
+ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped.
+ */
+#define PRIO2PREC(prio) \
+ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio))
+
+#endif /* _802_1_D__ */
diff --git a/package/broadcom-57xx/src/proto/802.3.h b/package/broadcom-57xx/src/proto/802.3.h
new file mode 100644
index 0000000000..493b60e3f8
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/802.3.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * Fundamental constants relating to 802.3
+ *
+ * $Id: 802.3.h,v 1.1.1.1 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _802_3_h_
+#define _802_3_h_
+
+#define SNAP_HDR_LEN 6 /* 802.3 LLC/SNAP header length */
+
+#endif /* #ifndef _802_3_h_ */
diff --git a/package/broadcom-57xx/src/proto/bcmarp.h b/package/broadcom-57xx/src/proto/bcmarp.h
new file mode 100644
index 0000000000..2e27ac1669
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/bcmarp.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * Fundamental constants relating to ARP Protocol
+ *
+ * $Id: bcmarp.h,v 1.1.1.1 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _bcmarp_h_
+#define _bcmarp_h_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+#define ARP_OPC_OFFSET 6 /* option code offset */
+#define ARP_SRC_ETH_OFFSET 8 /* src h/w address offset */
+#define ARP_SRC_IP_OFFSET 14 /* src IP address offset */
+#define ARP_TGT_ETH_OFFSET 18 /* target h/w address offset */
+#define ARP_TGT_IP_OFFSET 24 /* target IP address offset */
+
+#define ARP_OPC_REQUEST 1 /* ARP request */
+#define ARP_OPC_REPLY 2 /* ARP reply */
+
+#define ARP_DATA_LEN 28 /* ARP data length */
+
+struct bcmarp {
+ uint16 htype; /* Header type (1 = ethernet) */
+ uint16 ptype; /* Protocol type (0x800 = IP) */
+ uint8 hlen; /* Hardware address length (Eth = 6) */
+ uint8 plen; /* Protocol address length (IP = 4) */
+ uint16 oper; /* ARP_OPC_... */
+ uint8 src_eth[ETHER_ADDR_LEN]; /* Source hardware address */
+ uint8 src_ip[IPV4_ADDR_LEN]; /* Source protocol address (not aligned) */
+ uint8 dst_eth[ETHER_ADDR_LEN]; /* Destination hardware address */
+ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination protocol address */
+} PACKED;
+
+/* Ethernet header + Arp message */
+struct bcmetharp {
+ struct ether_header eh;
+ struct bcmarp arp;
+} PACKED;
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* !defined(_bcmarp_h_) */
diff --git a/package/broadcom-57xx/src/proto/bcmdhcp.h b/package/broadcom-57xx/src/proto/bcmdhcp.h
new file mode 100644
index 0000000000..f92a69b362
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/bcmdhcp.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * Fundamental constants relating to DHCP Protocol
+ *
+ * $Id: bcmdhcp.h,v 1.1.1.1 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _bcmdhcp_h_
+#define _bcmdhcp_h_
+
+/* DHCP params */
+#define DHCP_TYPE_OFFSET 0 /* DHCP type (request|reply) offset */
+#define DHCP_FLAGS_OFFSET 10 /* DHCP flags offset */
+#define DHCP_CIADDR_OFFSET 12 /* DHCP client IP address offset */
+#define DHCP_YIADDR_OFFSET 16 /* DHCP your IP address offset */
+#define DHCP_GIADDR_OFFSET 24 /* DHCP relay agent IP address offset */
+#define DHCP_CHADDR_OFFSET 28 /* DHCP client h/w address offset */
+
+#define DHCP_TYPE_REQUEST 1 /* DHCP request (discover|request) */
+#define DHCP_TYPE_REPLY 2 /* DHCP reply (offset|ack) */
+
+#define DHCP_PORT_SERVER 67 /* DHCP server UDP port */
+#define DHCP_PORT_CLIENT 68 /* DHCP client UDP port */
+
+#define DHCP_FLAG_BCAST 0x8000 /* DHCP broadcast flag */
+
+#define DHCP_FLAGS_LEN 2 /* DHCP flags field length */
+
+#endif /* #ifndef _bcmdhcp_h_ */
diff --git a/package/broadcom-57xx/src/proto/bcmeth.h b/package/broadcom-57xx/src/proto/bcmeth.h
new file mode 100644
index 0000000000..fffce6e7b5
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/bcmeth.h
@@ -0,0 +1,101 @@
+/*
+ * Broadcom Ethernettype protocol definitions
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: bcmeth.h,v 1.1.1.5 2007/05/31 08:00:41 michael Exp $
+ */
+
+/*
+ * Broadcom Ethernet protocol defines
+ */
+
+#ifndef _BCMETH_H_
+#define _BCMETH_H_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+/* ETHER_TYPE_BRCM is defined in ethernet.h */
+
+/*
+ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field
+ * in one of two formats: (only subtypes 32768-65535 are in use now)
+ *
+ * subtypes 0-32767:
+ * 8 bit subtype (0-127)
+ * 8 bit length in bytes (0-255)
+ *
+ * subtypes 32768-65535:
+ * 16 bit big-endian subtype
+ * 16 bit big-endian length in bytes (0-65535)
+ *
+ * length is the number of additional bytes beyond the 4 or 6 byte header
+ *
+ * Reserved values:
+ * 0 reserved
+ * 5-15 reserved for iLine protocol assignments
+ * 17-126 reserved, assignable
+ * 127 reserved
+ * 32768 reserved
+ * 32769-65534 reserved, assignable
+ * 65535 reserved
+ */
+
+/*
+ * While adding the subtypes and their specific processing code make sure
+ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition
+ */
+
+#define BCMILCP_SUBTYPE_RATE 1
+#define BCMILCP_SUBTYPE_LINK 2
+#define BCMILCP_SUBTYPE_CSA 3
+#define BCMILCP_SUBTYPE_LARQ 4
+#define BCMILCP_SUBTYPE_VENDOR 5
+#define BCMILCP_SUBTYPE_FLH 17
+
+#define BCMILCP_SUBTYPE_VENDOR_LONG 32769
+#define BCMILCP_SUBTYPE_CERT 32770
+#define BCMILCP_SUBTYPE_SES 32771
+
+
+#define BCMILCP_BCM_SUBTYPE_RESERVED 0
+#define BCMILCP_BCM_SUBTYPE_EVENT 1
+#define BCMILCP_BCM_SUBTYPE_SES 2
+/*
+ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded
+ * within BCMILCP_BCM_SUBTYPE_EVENT type messages
+ */
+/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */
+
+#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8
+#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0
+
+/* These fields are stored in network order */
+typedef struct bcmeth_hdr
+{
+ uint16 subtype; /* Vendor specific..32769 */
+ uint16 length;
+ uint8 version; /* Version is 0 */
+ uint8 oui[3]; /* Broadcom OUI */
+ /* user specific Data */
+ uint16 usr_subtype;
+} PACKED bcmeth_hdr_t;
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _BCMETH_H_ */
diff --git a/package/broadcom-57xx/src/proto/bcmevent.h b/package/broadcom-57xx/src/proto/bcmevent.h
new file mode 100644
index 0000000000..e862763762
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/bcmevent.h
@@ -0,0 +1,166 @@
+/*
+ * Broadcom Event protocol definitions
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ *
+ * Dependencies: proto/bcmeth.h
+ *
+ * $Id: bcmevent.h,v 1.1.1.11 2007/05/31 08:00:41 michael Exp $
+ *
+ */
+
+/*
+ * Broadcom Ethernet Events protocol defines
+ *
+ */
+
+#ifndef _BCMEVENT_H_
+#define _BCMEVENT_H_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif /* defined(__GNUC__) */
+
+#define BCM_EVENT_MSG_VERSION 1 /* wl_event_msg_t struct version */
+#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */
+
+/* flags */
+#define WLC_EVENT_MSG_LINK 0x01 /* link is up */
+#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */
+#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */
+
+/* these fields are stored in network order */
+typedef struct
+{
+ uint16 version;
+ uint16 flags; /* see flags below */
+ uint32 event_type; /* Message (see below) */
+ uint32 status; /* Status code (see below) */
+ uint32 reason; /* Reason code (if applicable) */
+ uint32 auth_type; /* WLC_E_AUTH */
+ uint32 datalen; /* data buf */
+ struct ether_addr addr; /* Station address (if applicable) */
+ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
+} PACKED wl_event_msg_t;
+
+/* used by driver msgs */
+typedef struct bcm_event {
+ struct ether_header eth;
+ bcmeth_hdr_t bcm_hdr;
+ wl_event_msg_t event;
+ /* data portion follows */
+} PACKED bcm_event_t;
+
+#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
+
+/* Event messages */
+#define WLC_E_SET_SSID 0 /* indicates status of set SSID */
+#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */
+#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */
+#define WLC_E_AUTH 3 /* 802.11 AUTH request */
+#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */
+#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */
+#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */
+#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */
+#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */
+#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */
+#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */
+#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */
+#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */
+#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */
+#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */
+#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */
+#define WLC_E_LINK 16 /* generic link indication */
+#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */
+#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */
+#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */
+#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */
+#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */
+#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */
+#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */
+#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */
+#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */
+#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */
+#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */
+#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */
+#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */
+#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */
+#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */
+#define WLC_E_ROAM_PREP 32 /* before attempting to roam */
+#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */
+#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */
+
+#ifdef EXT_STA
+#define WLC_E_RESET_COMPLETE 35
+#define WLC_E_JOIN_START 36
+#define WLC_E_ROAM_START 37
+#define WLC_E_ASSOC_START 38
+#define WLC_E_IBSS_ASSOC 39
+#define WLC_E_RADIO 40
+#define WLC_E_LAST 41 /* highest val + 1 for range checking */
+#else /* EXT_STA */
+#define WLC_E_LAST 35 /* highest val + 1 for range checking */
+#endif /* EXT_STA */
+
+/* Event status codes */
+#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */
+#define WLC_E_STATUS_FAIL 1 /* operation failed */
+#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */
+#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */
+#define WLC_E_STATUS_ABORT 4 /* operation was aborted */
+#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */
+#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */
+#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */
+#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */
+#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */
+#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */
+#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */
+#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */
+#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */
+#define WLC_E_STATUS_CCXFASTRM 14 /* scan aborted due to CCX fast roam */
+
+/* roam reason codes */
+#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */
+#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */
+#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */
+#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */
+#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */
+#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */
+#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */
+#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */
+#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */
+
+/* prune reason codes */
+#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */
+#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */
+#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */
+#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */
+#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */
+#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */
+#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */
+#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */
+#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */
+#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */
+#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */
+#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */
+#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */
+#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */
+#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif /* PACKED */
+
+#endif /* _BCMEVENT_H_ */
diff --git a/package/broadcom-57xx/src/proto/bcmip.h b/package/broadcom-57xx/src/proto/bcmip.h
new file mode 100644
index 0000000000..11f63f3208
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/bcmip.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * Fundamental constants relating to IP Protocol
+ *
+ * $Id: bcmip.h,v 1.1.1.4 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _bcmip_h_
+#define _bcmip_h_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+
+/* IPV4 and IPV6 common */
+#define IP_VER_OFFSET 0x0 /* offset to version field */
+#define IP_VER_MASK 0xf0 /* version mask */
+#define IP_VER_SHIFT 4 /* version shift */
+#define IP_VER_4 4 /* version number for IPV4 */
+#define IP_VER_6 6 /* version number for IPV6 */
+
+#define IP_VER(ip_body) \
+ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT)
+
+#define IP_PROT_ICMP 0x1 /* ICMP protocol */
+#define IP_PROT_TCP 0x6 /* TCP protocol */
+#define IP_PROT_UDP 0x11 /* UDP protocol type */
+
+/* IPV4 field offsets */
+#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */
+#define IPV4_TOS_OFFSET 1 /* type of service offset */
+#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */
+#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */
+#define IPV4_PROT_OFFSET 9 /* protocol type offset */
+#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */
+#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */
+#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */
+#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */
+
+/* IPV4 field decodes */
+#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */
+#define IPV4_VER_SHIFT 4 /* IPV4 version shift */
+
+#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */
+#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK))
+
+#define IPV4_ADDR_LEN 4 /* IPV4 address length */
+
+#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \
+ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0)
+
+#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \
+ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff)
+
+#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */
+#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */
+
+#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET])
+
+#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */
+#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */
+
+#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */
+#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */
+#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */
+
+#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET])
+
+#define IPV4_FRAG_RESV 0x8000 /* Reserved */
+#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */
+#define IPV4_FRAG_MORE 0x2000 /* More fragments */
+#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */
+
+#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */
+
+/* IPv4, no options only. */
+#define IPV4_NO_OPTIONS_HDR_LEN 20
+#define IPV4_NO_OPTIONS_PAYLOAD(ip_hdr) (&(((uint8 *)(ip_hdr))[IPV4_NO_OPTIONS_HDR_LEN]))
+
+#define IPV4_PAYLOAD_LEN(ip_body) \
+ (((int)(((uint8 *)(ip_body))[IPV4_PKTLEN_OFFSET + 0]) << 8) | \
+ ((uint8 *)(ip_body))[IPV4_PKTLEN_OFFSET + 1])
+
+/* IPV4 packet formats */
+struct ipv4_addr {
+ uint8 addr[IPV4_ADDR_LEN];
+} PACKED;
+
+struct ipv4_hdr {
+ uint8 version_ihl; /* Version and Internet Header Length */
+ uint8 tos; /* Type Of Service */
+ uint16 tot_len; /* Number of bytes in packet (max 65535) */
+ uint16 id;
+ uint16 frag; /* 3 flag bits and fragment offset */
+ uint8 ttl; /* Time To Live */
+ uint8 prot; /* Protocol */
+ uint16 hdr_chksum; /* IP header checksum */
+ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */
+ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */
+} PACKED;
+
+/* IPV6 field offsets */
+#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */
+#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */
+#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */
+#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */
+#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */
+
+/* IPV6 field decodes */
+#define IPV6_TRAFFIC_CLASS(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \
+ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4))
+
+#define IPV6_FLOW_LABEL(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \
+ (((uint8 *)(ipv6_body))[2] << 8) | \
+ (((uint8 *)(ipv6_body))[3]))
+
+#define IPV6_PAYLOAD_LEN(ipv6_body) \
+ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \
+ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1])
+
+#define IPV6_NEXT_HDR(ipv6_body) \
+ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET])
+
+#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body)
+
+#define IPV6_ADDR_LEN 16 /* IPV6 address length */
+
+/* IPV4 TOS or IPV6 Traffic Classifier or 0 */
+#define IP_TOS(ip_body) \
+ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \
+ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0)
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _bcmip_h_ */
diff --git a/package/broadcom-57xx/src/proto/bcmtcp.h b/package/broadcom-57xx/src/proto/bcmtcp.h
new file mode 100644
index 0000000000..7e834a77b9
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/bcmtcp.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * Fundamental constants relating to TCP Protocol
+ *
+ * $Id: bcmtcp.h,v 1.1.1.1 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _bcmtcp_h_
+#define _bcmtcp_h_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+#define TCP_SRC_PORT_OFFSET 0 /* TCP source port offset */
+#define TCP_DEST_PORT_OFFSET 2 /* TCP dest port offset */
+#define TCP_CHKSUM_OFFSET 16 /* TCP body checksum offset */
+
+/* These fields are stored in network order */
+struct bcmtcp_hdr
+{
+ uint16 src_port; /* Source Port Address */
+ uint16 dst_port; /* Destination Port Address */
+ uint32 seq_num; /* TCP Sequence Number */
+ uint32 ack_num; /* TCP Sequence Number */
+ uint16 hdrlen_rsvd_flags; /* Header length, reserved bits and flags */
+ uint16 tcpwin; /* TCP window */
+ uint16 chksum; /* Segment checksum with pseudoheader */
+ uint16 urg_ptr; /* Points to seq-num of byte following urg data */
+} PACKED;
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+/* Byte offset of flags in TCP header */
+#define TCP_FLAGS_OFFSET 13
+
+#define TCP_FLAGS_FIN 0x01
+#define TCP_FLAGS_SYN 0x02
+#define TCP_FLAGS_RST 0x03
+#define TCP_FLAGS_PSH 0x04
+#define TCP_FLAGS_ACK 0x10
+#define TCP_FLAGS_URG 0x20
+#define TCP_FLAGS_ECN 0x40
+#define TCP_FLAGS_CWR 0x80
+
+#define TCP_FLAGS(tcp_hdr) (((uint8 *)(tcp_hdr))[TCP_FLAGS_OFFSET])
+#define TCP_IS_ACK(tcp_hdr) (TCP_FLAGS(tcp_hdr) & TCP_FLAGS_ACK)
+
+#define TCP_SRC_PORT(tcp_hdr) (ntoh16(((struct bcmtcp_hdr*)(tcp_hdr))->src_port))
+#define TCP_DST_PORT(tcp_hdr) (ntoh16(((struct bcmtcp_hdr*)(tcp_hdr))->dst_port))
+#define TCP_SEQ_NUM(tcp_hdr) (ntoh32(((struct bcmtcp_hdr*)(tcp_hdr))->seq_num))
+#define TCP_ACK_NUM(tcp_hdr) (ntoh32(((struct bcmtcp_hdr*)(tcp_hdr))->ack_num))
+
+#endif /* #ifndef _bcmtcp_h_ */
diff --git a/package/broadcom-57xx/src/proto/bcmudp.h b/package/broadcom-57xx/src/proto/bcmudp.h
new file mode 100644
index 0000000000..782f12e219
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/bcmudp.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * Fundamental constants relating to UDP Protocol
+ *
+ * $Id: bcmudp.h,v 1.1.1.1 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _bcmudp_h_
+#define _bcmudp_h_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+/* UDP header */
+#define UDP_DEST_PORT_OFFSET 2 /* UDP dest port offset */
+#define UDP_LEN_OFFSET 4 /* UDP length offset */
+#define UDP_CHKSUM_OFFSET 6 /* UDP body checksum offset */
+
+#define UDP_HDR_LEN 8 /* UDP header length */
+#define UDP_PORT_LEN 2 /* UDP port length */
+
+/* These fields are stored in network order */
+struct bcmudp_hdr
+{
+ uint16 src_port; /* Source Port Address */
+ uint16 dst_port; /* Destination Port Address */
+ uint16 len; /* Number of bytes in datagram including header */
+ uint16 chksum; /* entire datagram checksum with pseudoheader */
+} PACKED;
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* #ifndef _bcmudp_h_ */
diff --git a/package/broadcom-57xx/src/proto/eap.h b/package/broadcom-57xx/src/proto/eap.h
new file mode 100644
index 0000000000..36ed138769
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/eap.h
@@ -0,0 +1,45 @@
+/*
+ * Extensible Authentication Protocol (EAP) definitions
+ *
+ * See
+ * RFC 2284: PPP Extensible Authentication Protocol (EAP)
+ *
+ * Copyright (C) 2002 Broadcom Corporation
+ *
+ * $Id: eap.h,v 1.2 2007/04/17 08:52:47 yogo Exp $
+ */
+
+#ifndef _eap_h_
+#define _eap_h_
+
+/* EAP packet format */
+typedef struct {
+ unsigned char code; /* EAP code */
+ unsigned char id; /* Current request ID */
+ unsigned short length; /* Length including header */
+ unsigned char type; /* EAP type (optional) */
+ unsigned char data[1]; /* Type data (optional) */
+} eap_header_t;
+
+#define EAP_HEADER_LEN 4
+
+/* EAP codes */
+#define EAP_REQUEST 1
+#define EAP_RESPONSE 2
+#define EAP_SUCCESS 3
+#define EAP_FAILURE 4
+
+/* EAP types */
+#define EAP_IDENTITY 1
+#define EAP_NOTIFICATION 2
+#define EAP_NAK 3
+#define EAP_MD5 4
+#define EAP_OTP 5
+#define EAP_GTC 6
+#define EAP_TLS 13
+#define EAP_EXPANDED 254
+#define BCM_EAP_SES 10
+#define BCM_EAP_EXP_LEN 12 /* EAP_LEN 5 + 3 bytes for SMI ID + 4 bytes for ven type */
+#define BCM_SMI_ID 0x113d
+
+#endif /* _eap_h_ */
diff --git a/package/broadcom-57xx/src/proto/eapol.h b/package/broadcom-57xx/src/proto/eapol.h
new file mode 100644
index 0000000000..36bbe8155c
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/eapol.h
@@ -0,0 +1,179 @@
+/*
+ * 802.1x EAPOL definitions
+ *
+ * See
+ * IEEE Std 802.1X-2001
+ * IEEE 802.1X RADIUS Usage Guidelines
+ *
+ * Copyright (C) 2002 Broadcom Corporation
+ *
+ * eapol.h,v 9.17 2004/12/13 22:36:09 davidm Exp
+ */
+
+#ifndef _eapol_h_
+#define _eapol_h_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+#include <bcmcrypto/aeskeywrap.h>
+
+/* EAPOL for 802.3/Ethernet */
+typedef struct {
+ struct ether_header eth; /* 802.3/Ethernet header */
+ unsigned char version; /* EAPOL protocol version */
+ unsigned char type; /* EAPOL type */
+ unsigned short length; /* Length of body */
+ unsigned char body[1]; /* Body (optional) */
+} eapol_header_t;
+
+#define EAPOL_HEADER_LEN 18
+
+/* EAPOL version */
+#define WPA2_EAPOL_VERSION 2
+#define WPA_EAPOL_VERSION 1
+#define LEAP_EAPOL_VERSION 1
+#define SES_EAPOL_VERSION 1
+
+/* EAPOL types */
+#define EAP_PACKET 0
+#define EAPOL_START 1
+#define EAPOL_LOGOFF 2
+#define EAPOL_KEY 3
+#define EAPOL_ASF 4
+
+/* EAPOL-Key types */
+#define EAPOL_RC4_KEY 1
+#ifdef BCMWPA2
+#define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */
+#endif
+#define EAPOL_WPA_KEY 254 /* WPA */
+
+/* RC4 EAPOL-Key header field sizes */
+#define EAPOL_KEY_REPLAY_LEN 8
+#define EAPOL_KEY_IV_LEN 16
+#define EAPOL_KEY_SIG_LEN 16
+
+/* RC4 EAPOL-Key */
+typedef struct {
+ unsigned char type; /* Key Descriptor Type */
+ unsigned short length; /* Key Length (unaligned) */
+ unsigned char replay[EAPOL_KEY_REPLAY_LEN]; /* Replay Counter */
+ unsigned char iv[EAPOL_KEY_IV_LEN]; /* Key IV */
+ unsigned char index; /* Key Flags & Index */
+ unsigned char signature[EAPOL_KEY_SIG_LEN]; /* Key Signature */
+ unsigned char key[1]; /* Key (optional) */
+} PACKED eapol_key_header_t;
+
+#define EAPOL_KEY_HEADER_LEN 44
+
+/* RC4 EAPOL-Key flags */
+#define EAPOL_KEY_FLAGS_MASK 0x80
+#define EAPOL_KEY_BROADCAST 0
+#define EAPOL_KEY_UNICAST 0x80
+
+/* RC4 EAPOL-Key index */
+#define EAPOL_KEY_INDEX_MASK 0x7f
+
+/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */
+#define EAPOL_WPA_KEY_REPLAY_LEN 8
+#define EAPOL_WPA_KEY_NONCE_LEN 32
+#define EAPOL_WPA_KEY_IV_LEN 16
+#define EAPOL_WPA_KEY_RSC_LEN 8
+#define EAPOL_WPA_KEY_ID_LEN 8
+#define EAPOL_WPA_KEY_MIC_LEN 16
+#define EAPOL_WPA_KEY_DATA_LEN (EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN)
+#define EAPOL_WPA_MAX_KEY_SIZE 32
+
+/* WPA EAPOL-Key */
+typedef struct {
+ unsigned char type; /* Key Descriptor Type */
+ unsigned short key_info; /* Key Information (unaligned) */
+ unsigned short key_len; /* Key Length (unaligned) */
+ unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */
+ unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */
+ unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */
+ unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */
+ unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */
+ unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */
+ unsigned short data_len; /* Key Data Length */
+ unsigned char data[EAPOL_WPA_KEY_DATA_LEN]; /* Key data */
+} PACKED eapol_wpa_key_header_t;
+
+#define EAPOL_WPA_KEY_LEN 95
+
+/* WPA/802.11i/WPA2 KEY KEY_INFO bits */
+#define WPA_KEY_DESC_V1 0x01
+#define WPA_KEY_DESC_V2 0x02
+#define WPA_KEY_PAIRWISE 0x08
+#define WPA_KEY_INSTALL 0x40
+#define WPA_KEY_ACK 0x80
+#define WPA_KEY_MIC 0x100
+#define WPA_KEY_SECURE 0x200
+#define WPA_KEY_ERROR 0x400
+#define WPA_KEY_REQ 0x800
+
+/* WPA-only KEY KEY_INFO bits */
+#define WPA_KEY_INDEX_0 0x00
+#define WPA_KEY_INDEX_1 0x10
+#define WPA_KEY_INDEX_2 0x20
+#define WPA_KEY_INDEX_3 0x30
+#define WPA_KEY_INDEX_MASK 0x30
+#define WPA_KEY_INDEX_SHIFT 0x04
+
+#ifdef BCMWPA2
+/* 802.11i/WPA2-only KEY KEY_INFO bits */
+#define WPA_KEY_ENCRYPTED_DATA 0x1000
+
+/* Key Data encapsulation */
+typedef struct {
+ uint8 type;
+ uint8 length;
+ uint8 oui[3];
+ uint8 subtype;
+ uint8 data[1];
+} PACKED eapol_wpa2_encap_data_t;
+
+#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 6
+
+#define WPA2_KEY_DATA_SUBTYPE_GTK 1
+#define WPA2_KEY_DATA_SUBTYPE_STAKEY 2
+#define WPA2_KEY_DATA_SUBTYPE_MAC 3
+#define WPA2_KEY_DATA_SUBTYPE_PMKID 4
+
+/* GTK encapsulation */
+typedef struct {
+ uint8 flags;
+ uint8 reserved;
+ uint8 gtk[EAPOL_WPA_MAX_KEY_SIZE];
+} PACKED eapol_wpa2_key_gtk_encap_t;
+
+#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 2
+
+#define WPA2_GTK_INDEX_MASK 0x03
+#define WPA2_GTK_INDEX_SHIFT 0x00
+
+#define WPA2_GTK_TRANSMIT 0x04
+
+/* STAKey encapsulation */
+typedef struct {
+ uint8 reserved[2];
+ uint8 mac[ETHER_ADDR_LEN];
+ uint8 stakey[EAPOL_WPA_MAX_KEY_SIZE];
+} PACKED eapol_wpa2_key_stakey_encap_t;
+
+#define WPA2_KEY_DATA_PAD 0xdd
+
+#endif /* BCMWPA2 */
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _eapol_h_ */
diff --git a/package/broadcom-57xx/src/proto/ethernet.h b/package/broadcom-57xx/src/proto/ethernet.h
new file mode 100644
index 0000000000..63430be5e2
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/ethernet.h
@@ -0,0 +1,173 @@
+/*
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: ethernet.h,v 1.1.1.16 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#define ETHER_ADDR_LEN 6
+
+/*
+ * The number of bytes in the type field.
+ */
+#define ETHER_TYPE_LEN 2
+
+/*
+ * The number of bytes in the trailing CRC field.
+ */
+#define ETHER_CRC_LEN 4
+
+/*
+ * The length of the combined header.
+ */
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+
+/*
+ * The minimum packet length.
+ */
+#define ETHER_MIN_LEN 64
+
+/*
+ * The minimum packet user data length.
+ */
+#define ETHER_MIN_DATA 46
+
+/*
+ * The maximum packet length.
+ */
+#define ETHER_MAX_LEN 1518
+
+/*
+ * The maximum packet user data length.
+ */
+#define ETHER_MAX_DATA 1500
+
+/* ether types */
+#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */
+#define ETHER_TYPE_IP 0x0800 /* IP */
+#define ETHER_TYPE_ARP 0x0806 /* ARP */
+#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */
+#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */
+#define ETHER_TYPE_802_1X 0x888e /* 802.1x */
+#ifdef BCMWPA2
+#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */
+#endif
+
+/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */
+#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */
+#define ETHER_BRCM_CRAM 0x1 /* Broadcom subtype cram protocol */
+
+/* ether header */
+#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */
+#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */
+#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */
+
+/*
+ * A macro to validate a length with
+ */
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+
+#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct ether_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 ether_type;
+} PACKED;
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+} PACKED;
+#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */
+
+/*
+ * Takes a pointer, set, test, clear, toggle locally admininistered
+ * address bit in the 48-bit Ethernet address.
+ */
+#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2))
+#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2)
+#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xd))
+#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2))
+
+/* Takes a pointer, marks unicast address bit in the MAC address */
+#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1))
+
+/*
+ * Takes a pointer, returns true if a 48-bit multicast address
+ * (including broadcast, since it is all ones)
+ */
+#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1)
+
+
+/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */
+#define ether_cmp(a, b) (!(((short*)a)[0] == ((short*)b)[0]) | \
+ !(((short*)a)[1] == ((short*)b)[1]) | \
+ !(((short*)a)[2] == ((short*)b)[2]))
+
+/* copy an ethernet address - assumes the pointers can be referenced as shorts */
+#define ether_copy(s, d) { \
+ ((short*)d)[0] = ((short*)s)[0]; \
+ ((short*)d)[1] = ((short*)s)[1]; \
+ ((short*)d)[2] = ((short*)s)[2]; }
+
+/*
+ * Takes a pointer, returns true if a 48-bit broadcast (all ones)
+ */
+#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \
+ ((uint8 *)(ea))[1] & \
+ ((uint8 *)(ea))[2] & \
+ ((uint8 *)(ea))[3] & \
+ ((uint8 *)(ea))[4] & \
+ ((uint8 *)(ea))[5]) == 0xff)
+
+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}};
+
+/*
+ * Takes a pointer, returns true if a 48-bit null address (all zeros)
+ */
+#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \
+ ((uint8 *)(ea))[1] | \
+ ((uint8 *)(ea))[2] | \
+ ((uint8 *)(ea))[3] | \
+ ((uint8 *)(ea))[4] | \
+ ((uint8 *)(ea))[5]) == 0)
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _NET_ETHERNET_H_ */
diff --git a/package/broadcom-57xx/src/proto/vlan.h b/package/broadcom-57xx/src/proto/vlan.h
new file mode 100644
index 0000000000..79cd5891e1
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/vlan.h
@@ -0,0 +1,52 @@
+/*
+ * 802.1Q VLAN protocol definitions
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: vlan.h,v 1.1.1.4 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _vlan_h_
+#define _vlan_h_
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */
+#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */
+#define VLAN_PRI_SHIFT 13 /* user priority */
+
+#define VLAN_PRI_MASK 7 /* 3 bits of priority */
+
+#define VLAN_TAG_LEN 4
+#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */
+
+#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */
+
+struct ethervlan_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 vlan_type; /* 0x8100 */
+ uint16 vlan_tag; /* priority, cfi and vid */
+ uint16 ether_type;
+};
+
+#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN)
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _vlan_h_ */
diff --git a/package/broadcom-57xx/src/proto/wpa.h b/package/broadcom-57xx/src/proto/wpa.h
new file mode 100644
index 0000000000..9bb6752b8f
--- /dev/null
+++ b/package/broadcom-57xx/src/proto/wpa.h
@@ -0,0 +1,158 @@
+/*
+ * Fundamental types and constants relating to WPA
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: wpa.h,v 1.1.1.6 2007/05/31 08:00:41 michael Exp $
+ */
+
+#ifndef _proto_wpa_h_
+#define _proto_wpa_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+
+/* enable structure packing */
+#if defined(__GNUC__)
+#define PACKED __attribute__((packed))
+#else
+#pragma pack(1)
+#define PACKED
+#endif
+
+/* Reason Codes */
+
+/* 13 through 23 taken from IEEE Std 802.11i-2004 */
+#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */
+#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */
+#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */
+#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */
+#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from
+ * (re-)assoc. request/probe response
+ */
+#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */
+#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */
+#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */
+#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */
+#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */
+#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */
+
+#define WPA2_PMKID_LEN 16
+
+/* WPA IE fixed portion */
+typedef struct
+{
+ uint8 tag; /* TAG */
+ uint8 length; /* TAG length */
+ uint8 oui[3]; /* IE OUI */
+ uint8 oui_type; /* OUI type */
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED version; /* IE version */
+} PACKED wpa_ie_fixed_t;
+#define WPA_IE_OUITYPE_LEN 4
+#define WPA_IE_FIXED_LEN 8
+#define WPA_IE_TAG_FIXED_LEN 6
+
+#ifdef BCMWPA2
+typedef struct {
+ uint8 tag; /* TAG */
+ uint8 length; /* TAG length */
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED version; /* IE version */
+} PACKED wpa_rsn_ie_fixed_t;
+#define WPA_RSN_IE_FIXED_LEN 4
+#define WPA_RSN_IE_TAG_FIXED_LEN 2
+typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN];
+#endif
+
+/* WPA suite/multicast suite */
+typedef struct
+{
+ uint8 oui[3];
+ uint8 type;
+} PACKED wpa_suite_t, wpa_suite_mcast_t;
+#define WPA_SUITE_LEN 4
+
+/* WPA unicast suite list/key management suite list */
+typedef struct
+{
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED count;
+ wpa_suite_t list[1];
+} PACKED wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+#define WPA_IE_SUITE_COUNT_LEN 2
+#ifdef BCMWPA2
+typedef struct
+{
+ struct {
+ uint8 low;
+ uint8 high;
+ } PACKED count;
+ wpa_pmkid_t list[1];
+} PACKED wpa_pmkid_list_t;
+#endif
+
+/* WPA cipher suites */
+#define WPA_CIPHER_NONE 0 /* None */
+#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */
+#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */
+#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */
+#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */
+#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */
+
+#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \
+ (cipher) == WPA_CIPHER_WEP_40 || \
+ (cipher) == WPA_CIPHER_WEP_104 || \
+ (cipher) == WPA_CIPHER_TKIP || \
+ (cipher) == WPA_CIPHER_AES_OCB || \
+ (cipher) == WPA_CIPHER_AES_CCM)
+
+/* WPA TKIP countermeasures parameters */
+#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */
+#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */
+
+/* RSN IE defines */
+#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */
+
+/* RSN Capabilities defined in 802.11i */
+#define RSN_CAP_PREAUTH 0x0001
+#define RSN_CAP_NOPAIRWISE 0x0002
+#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
+#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2
+#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030
+#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4
+#define RSN_CAP_1_REPLAY_CNTR 0
+#define RSN_CAP_2_REPLAY_CNTRS 1
+#define RSN_CAP_4_REPLAY_CNTRS 2
+#define RSN_CAP_16_REPLAY_CNTRS 3
+
+/* WPA capabilities defined in 802.11i */
+#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS
+#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS
+#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT
+#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK
+
+/* WPA Specific defines */
+#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */
+
+#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH
+
+
+#undef PACKED
+#if !defined(__GNUC__)
+#pragma pack()
+#endif
+
+#endif /* _proto_wpa_h_ */
diff --git a/package/broadcom-57xx/src/queue.h b/package/broadcom-57xx/src/queue.h
new file mode 100644
index 0000000000..c73be5e881
--- /dev/null
+++ b/package/broadcom-57xx/src/queue.h
@@ -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/package/broadcom-57xx/src/robo_register.c b/package/broadcom-57xx/src/robo_register.c
new file mode 100644
index 0000000000..acd385e0bf
--- /dev/null
+++ b/package/broadcom-57xx/src/robo_register.c
@@ -0,0 +1,111 @@
+
+#if 1
+#define DEBUG_REG printk
+#else
+#define DEBUG_REG
+#endif
+
+void ReadDataFromRegister(robo_info_t *robo, uint16 page_num,uint16 addr_num, uint16 len, void* data)
+{
+
+ uint32 val32 = 0,val64[2];
+ uint16 val16 =0,val48[3];//,val32[2],val64[4];
+ memset(val48,0,6);
+ memset(val64,0,8);
+ //memset(val32,0,4);
+ DEBUG_REG("Read ioctl Page[0x%02x] Addr[0x%02x] len[%d].\n", page_num, addr_num, len);
+ switch (len)
+ {
+ case 1:
+ case 2:
+ {
+ robo->ops->read_reg(robo, page_num, addr_num, &val16, len);
+ DEBUG_REG("IRead 8/16 bit Page[0x%02x]addr[0x%02x]len[%d]val[0x%04x].\n",
+ page_num, addr_num, len, val16);
+ memcpy(data,&val16,2);
+ break;
+ }
+ case 4:
+ {
+ robo->ops->read_reg(robo, page_num, addr_num, &val32, len);
+ DEBUG_REG("IRead 32bit Page[0x%02x]addr[0x%02x]len[%d]val[0x%08x].\n",
+ page_num, addr_num, len, val32);
+ memcpy(data,&val32,4);
+ break;
+ }
+ case 6:
+ {
+ robo->ops->read_reg(robo, page_num,addr_num, &val48, len);
+ DEBUG_REG("IRead 48bit Page[0x%02x]addr[0x%02x]len[%d]val[0x%04x-0x%04x-0x%04x].\n",
+ page_num, addr_num, len, val48[0], val48[1], val48[2]);
+ memcpy(data,&val48,6);
+ break;
+ }
+ case 8:
+ {
+ robo->ops->read_reg(robo, page_num, addr_num, &val64, len);
+ DEBUG_REG("IRead 64bit Page[0x%02x]addr[0x%02x]len[%d]val[0x%08x-0x%08x].\n",
+ page_num, addr_num, len, val64[0], val64[1]);
+ memcpy(data,&val64,8);
+ break;
+ }
+ }
+}
+
+
+
+void WriteDataToRegister(robo_info_t *robo,uint16 page_num,uint16 addr_num, uint16 len, void* data)
+{
+ DEBUG_REG("Write ioctl Page[0x%02x]Addr[0x%02x]len[%d].\n",page_num,addr_num,len);
+ switch (len)
+ {
+ case 1:
+ case 2:
+ {
+ DEBUG_REG("Write 2byte Page[0x%02x]addr[0x%02x]len[%d]val[0x%04x].\n",
+ page_num, addr_num, len, *((uint16 *)data));
+ robo->ops->write_reg(robo, page_num, addr_num, data, len);
+ if (page_num < 0x10 || page_num > 0x17) {
+ robo->ops->read_reg(robo, page_num, addr_num, data, len);
+ DEBUG_REG("Reload Page[0x%02x]addr[0x%02x]len[%d]val[0x%04x].\n",
+ page_num, addr_num, len, *((uint16 *)data));
+ }
+ break;
+ }
+ case 4:
+ {
+ DEBUG_REG("Write 4byte Page[0x%02x]addr[0x%02x]len[%d]val[0x%08x].\n",
+ page_num, addr_num, len, *((uint32 *)data));
+ robo->ops->write_reg(robo, page_num, addr_num, data, len);
+ if (page_num < 0x10 || page_num > 0x17) {
+ robo->ops->read_reg(robo, page_num, addr_num, data, len);
+ DEBUG_REG("Reload Page[0x%02x]addr[0x%02x]len[%d]val[0x%08x].\n",
+ page_num, addr_num, len, *((uint32 *)data));
+ }
+ break;
+ }
+ case 6:
+ {
+ DEBUG_REG("Write 6byte Page[0x%02x]addr[0x%02x]len[%d]val[0x%04x-0x%04x-0x%04x].\n",
+ page_num, addr_num, len, *((uint16 *)data),*((((uint16 *)data)+1)),
+ *(((uint16 *)data)+2));
+ robo->ops->write_reg(robo, page_num, addr_num, data, len);
+ robo->ops->read_reg(robo, page_num, addr_num, data, len);
+ DEBUG_REG("Reload Page[0x%02x]addr[0x%02x]len[%d]val[0x%04x-0x%04x-0x%04x].\n",
+ page_num, addr_num, len,*((uint16 *)data),*((((uint16 *)data)+1)),
+ *(((uint16 *)data)+2));
+ break;
+ }
+ case 8:
+ {
+ DEBUG_REG("Write 8byte Page[0x%02x]addr[0x%02x]len[%d]val[0x%08x-0x%08x].\n",
+ page_num, addr_num, len, *((uint32*)data),*(((uint32 *)data)+1));
+ robo->ops->write_reg(robo, page_num, addr_num, data, len);
+ robo->ops->read_reg(robo, page_num, addr_num, data, len);
+ DEBUG_REG("Reload Page[0x%x]addr[0x%x]len[%d]val[0x%08x-0x%08x].\n",
+ page_num, addr_num, len,*((uint32 *)data), *(((uint32 *)data)+1));
+ break;
+ }
+ }
+}
+
diff --git a/package/broadcom-57xx/src/sbgige.h b/package/broadcom-57xx/src/sbgige.h
new file mode 100644
index 0000000000..7975a7ac7e
--- /dev/null
+++ b/package/broadcom-57xx/src/sbgige.h
@@ -0,0 +1,59 @@
+/*
+ * HND SiliconBackplane Gigabit Ethernet core registers
+ *
+ * Copyright 2007, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: sbgige.h,v 1.5 2007/06/01 05:58:20 michael Exp $
+ */
+
+#ifndef _sbgige_h_
+#define _sbgige_h_
+
+#include <typedefs.h>
+#include <sbconfig.h>
+#include <pcicfg.h>
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line) pad ## line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif /* PAD */
+
+/* PCI to OCP shim registers */
+typedef volatile struct {
+ uint32 FlushStatusControl;
+ uint32 FlushReadAddr;
+ uint32 FlushTimeoutCntr;
+ uint32 BarrierReg;
+ uint32 MaocpSIControl;
+ uint32 SiocpMaControl;
+ uint8 PAD[0x02E8];
+} sbgige_pcishim_t;
+
+/* SB core registers */
+typedef volatile struct {
+ /* PCI I/O Read/Write registers */
+ uint8 pciio[0x0400];
+
+ /* Reserved */
+ uint8 reserved[0x0400];
+
+ /* PCI configuration registers */
+ pci_config_regs pcicfg;
+ uint8 PAD[0x0300];
+
+ /* PCI to OCP shim registers */
+ sbgige_pcishim_t pcishim;
+
+ /* Sonics SiliconBackplane registers */
+ sbconfig_t sbconfig;
+} sbgige_t;
+
+#endif /* _sbgige_h_ */
diff --git a/package/broadcom-57xx/src/tcp_seg.c b/package/broadcom-57xx/src/tcp_seg.c
new file mode 100644
index 0000000000..5a7c8f14a4
--- /dev/null
+++ b/package/broadcom-57xx/src/tcp_seg.c
@@ -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/package/broadcom-57xx/src/tigon3.c b/package/broadcom-57xx/src/tigon3.c
new file mode 100644
index 0000000000..159a0a7f56
--- /dev/null
+++ b/package/broadcom-57xx/src/tigon3.c
@@ -0,0 +1,9736 @@
+/******************************************************************************/
+/* */
+/* 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: */
+/******************************************************************************/
+
+/* $Id: tigon3.c,v 1.10 2007/06/01 05:58:19 michael Exp $ */
+
+#include "mm.h"
+#include "typedefs.h"
+#include "osl.h"
+#include "bcmdefs.h"
+#include "bcmdevs.h"
+#include "sbutils.h"
+#include "bcmrobo.h"
+#include "proto/ethernet.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;
+
+ /* BCM4785: Avoid all access to NVRAM & EEPROM. */
+ if (pDevice->Flags & SB_CORE_FLAG)
+ return status;
+
+ /* 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 )
+{
+ /* BCM4785: Avoid all access to NVRAM & EEPROM. */
+ if (pDevice->Flags & SB_CORE_FLAG)
+ return LM_STATUS_SUCCESS;
+
+ /* 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 )
+ {
+ B57_ERR(("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 )
+ {
+ B57_ERR(("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_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:
+ B57_ERR(("bcm57xx : 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:
+ B57_ERR(("bcm57xx : 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:
+ B57_ERR(("bcm57xx : Unknown NVRAM page size.\n"));
+ supported = FALSE;
+ }
+ }
+
+ if( supported != TRUE )
+ {
+ B57_ERR(("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;
+
+ /* BCM4785: Avoid all access to NVRAM & EEPROM. */
+ if (pDevice->Flags & SB_CORE_FLAG)
+ return;
+
+ 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;
+
+ B57_INFO(("*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;
+
+ /* BCM4785: Avoid all access to NVRAM & EEPROM. */
+ if (pDevice->Flags & SB_CORE_FLAG) {
+ *data = 0xffffffff;
+ return LM_STATUS_FAILURE;
+ }
+
+ 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_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_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 )
+{
+ /* BCM4785: Avoid all access to NVRAM & EEPROM. */
+ if (pDevice->Flags & SB_CORE_FLAG)
+ return LM_STATUS_FAILURE;
+
+ return LM_NVRAM_WriteBlock( pDevice, offset, (LM_UINT8 *)data, size * 4 );
+}
+
+#endif /* ETHTOOL_SEEPROM */
+
+
+static int
+bcm_ether_atoe(char *p, struct ether_addr *ea)
+{
+ int i = 0;
+
+ for (;;) {
+ ea->octet[i++] = (char) simple_strtoul(p, &p, 16);
+ if (!*p++ || i == 6)
+ break;
+ }
+
+ return (i == 6);
+}
+
+/******************************************************************************/
+/* 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)
+ {
+ 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 */
+ /* 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;
+
+ /* BCM4785: Use the MAC address stored in the main flash. */
+ if (pDevice->Flags & SB_CORE_FLAG) {
+ bcm_ether_atoe(getvar(NULL, "et0macaddr"), (struct ether_addr *)pDevice->NodeAddress);
+ Status = LM_STATUS_SUCCESS;
+ } else {
+ /* 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;
+ }
+ /* 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;
+ B57_ERR(("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 */
+
+ /* 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_BCM5461_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))
+ {
+ if (pDevice->Flags & ROBO_SWITCH_FLAG) {
+ B57_ERR(("PHY ID unknown, assume it is a copper PHY.\n"));
+ } else {
+ pDevice->TbiFlags |= ENABLE_TBI_FLAG;
+ B57_ERR(("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;
+ }
+
+ 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 */
+
+ /* 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
+ 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);
+
+ 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)
+ {
+ if(UNKNOWN_PHY_ID(pDevice->PhyId) && (pDevice->Flags & ROBO_SWITCH_FLAG)) {
+ pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE;
+ } else {
+ 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);
+
+ if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5461_PHY_ID)
+ LM_WritePhy(pDevice, BCM546X_1c_SHADOW_REG,
+ (BCM546X_1c_SPR_CTRL_1 | BCM546X_1c_WR_EN));
+
+ /* 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 */
+ 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);
+ }
+
+ /*
+ * BCM4785: In order to avoid repercussions from using potentially
+ * defective internal ROM, stop the Rx RISC CPU, which is not
+ * required.
+ */
+ if (pDevice->Flags & SB_CORE_FLAG) {
+ LM_DisableFW(pDevice);
+ LM_HaltCpu(pDevice, T3_RX_CPU_ID);
+ }
+
+#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);
+
+ /* BCM4785: Don't use any firmware, so don't wait */
+ if (!pDevice->Flags & SB_CORE_FLAG) {
+ /* 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)) {
+ /* 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;
+ robo_info_t *robo;
+
+ 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)
+ {
+ 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);
+ }
+ }
+ else if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5461_PHY_ID)
+ {
+ /*
+ ** Set up the 'link' LED for the 4785+5461 combo,
+ ** using the INTR/ENERGYDET pin (on the BCM4785 bringup board).
+ */
+ LM_WritePhy( pDevice,
+ BCM546X_1c_SHADOW_REG,
+ (BCM546X_1c_SPR_CTRL_2 | BCM546X_1c_WR_EN | BCM546X_1c_SP2_NRG_DET) );
+
+ /*
+ ** Set up the LINK LED mode for the 4785+5461 combo,
+ ** using the 5461 SLAVE/ANEN pin (on the BCM4785 bringup board) as
+ ** active low link status (phy ready) feedback to the 4785
+ */
+ LM_WritePhy( pDevice,
+ BCM546X_1c_SHADOW_REG,
+ (BCM546X_1c_SPR_CTRL_1 | BCM546X_1c_WR_EN | BCM546X_1c_SP1_LINK_LED) );
+ }
+
+ 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;
+
+ if(UNKNOWN_PHY_ID(pDevice->PhyId) && (pDevice->Flags & ROBO_SWITCH_FLAG)) {
+ B57_INFO(("Force to active link of 1000 MBPS and full duplex mod.\n"));
+ CurrentLinkStatus = LM_STATUS_LINK_ACTIVE;
+
+ /* Set the line speed based on the robo switch type */
+ robo = ((PUM_DEVICE_BLOCK)pDevice)->robo;
+ if (robo->devid == DEVID5325)
+ {
+ CurrentLineSpeed = LM_LINE_SPEED_100MBPS;
+ }
+ else
+ {
+ CurrentLineSpeed = LM_LINE_SPEED_1000MBPS;
+ }
+ CurrentDuplexMode = LM_DUPLEX_MODE_FULL;
+
+ /* Save line settings. */
+ pDevice->LineSpeed = CurrentLineSpeed;
+ pDevice->DuplexMode = CurrentDuplexMode;
+ } else {
+
+ /* 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;
+ /* Set line and duplex only if we don't have a Robo switch */
+ if (!(pDevice->Flags & ROBO_SWITCH_FLAG)) {
+ 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;
+ }
+
+ /* For Robo switch read PHY_CTRL_REG value as zero */
+ if (pDevice->Flags & ROBO_SWITCH_FLAG)
+ Value32 = 0;
+ else
+ 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;
+ }
+
+ /* In order for the 5750 core in BCM4785 chip to work properly
+ * in RGMII mode, the Led Control Register must be set up.
+ */
+ if (pDevice->Flags & RGMII_MODE_FLAG)
+ {
+ LM_UINT32 LedCtrl_Reg;
+
+ LedCtrl_Reg = REG_RD(pDevice, MacCtrl.LedCtrl);
+ LedCtrl_Reg &= ~(LED_CTRL_1000MBPS_LED_ON | LED_CTRL_100MBPS_LED_ON);
+
+ if(pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
+ LedCtrl_Reg |= LED_CTRL_OVERRIDE_LINK_LED;
+ else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
+ LedCtrl_Reg |= (LED_CTRL_OVERRIDE_LINK_LED | LED_CTRL_100MBPS_LED_ON);
+ else /* LM_LINE_SPEED_1000MBPS */
+ LedCtrl_Reg |= (LED_CTRL_OVERRIDE_LINK_LED | LED_CTRL_1000MBPS_LED_ON);
+
+ REG_WR(pDevice, MacCtrl.LedCtrl, LedCtrl_Reg);
+
+ MM_Wait(40);
+ }
+
+ /* 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)
+{
+ LM_UINT32 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)
+{
+ LM_UINT32 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)
+{
+ LM_UINT32 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;
+ LM_UINT32 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){
+ LM_UINT32 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)){
+ LM_UINT32 bmcr;
+
+ LM_ReadPhy(pDevice, PHY_CTRL_REG, &bmcr);
+ if (bmcr & PHY_CTRL_AUTO_NEG_ENABLE) {
+ LM_UINT32 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)) {
+ LM_UINT32 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() */
+/* LM_UINT32 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 */
+
+/* MII read/write functions to export to the robo support code */
+LM_UINT16
+robo_miird(void *h, int phyadd, int regoff)
+{
+ PLM_DEVICE_BLOCK pdev = h;
+ LM_UINT32 savephyaddr, val32;
+
+ savephyaddr = pdev->PhyAddr;
+ pdev->PhyAddr = phyadd;
+
+ LM_ReadPhy(pdev, regoff, &val32);
+
+ pdev->PhyAddr = savephyaddr;
+
+ return ((LM_UINT16)(val32 & 0xffff));
+}
+
+void
+robo_miiwr(void *h, int phyadd, int regoff, LM_UINT16 value)
+{
+ PLM_DEVICE_BLOCK pdev = h;
+ LM_UINT32 val32, savephyaddr;
+
+ savephyaddr = pdev->PhyAddr;
+ pdev->PhyAddr = phyadd;
+
+ val32 = (LM_UINT32)value;
+ LM_WritePhy(pdev, regoff, val32);
+
+ pdev->PhyAddr = savephyaddr;
+}
+
+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);
+
+ 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
+ /* 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;
+
+ /* BCM4785: Avoid all use of firmware. */
+ if (pDevice->Flags & SB_CORE_FLAG)
+ return LM_STATUS_FAILURE;
+
+#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;
+ }
+
+ /*
+ * BCM4785: There is only an Rx CPU for the 5750 derivative in
+ * the 4785. Don't go any further in this code in order to
+ * avoid access to the NVRAM arbitration register.
+ */
+ if (pDevice->Flags & SB_CORE_FLAG)
+ return status;
+
+ 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/package/broadcom-57xx/src/tigon3.h b/package/broadcom-57xx/src/tigon3.h
new file mode 100644
index 0000000000..2860ab16d6
--- /dev/null
+++ b/package/broadcom-57xx/src/tigon3.h
@@ -0,0 +1,3882 @@
+/******************************************************************************/
+/* */
+/* 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"
+#ifdef 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_BCM471F 0x471f14e4
+
+#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_BCM5461_PHY_ID 0x600080c0
+#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) && \
+ (((x) & PHY_ID_MASK) != PHY_BCM5461_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
+
+/* BCM5461 x1c Shadow Control register */
+#define BCM546X_1c_SHADOW_REG 0x1c
+
+#define BCM546X_1c_WR_EN 0x8000 /* shadow (1c) write enable bit mask */
+
+#define BCM546X_1c_SPR_CTRL_1 0x0800 /* shadow (1c) reg 00010 addr */
+#define BCM546X_1c_SP1_LINK_LED 0x0001 /* shadow (1c) reg 00010 link LED mode mask */
+
+#define BCM546X_1c_SPR_CTRL_2 0x100C /* shadow (1c) reg 00100 addr */
+#define BCM546X_1c_SP2_NRG_DET 0x0002 /* shadow (1c) reg 00100 energy detect bit mask */
+
+
+
+/******************************************************************************/
+/* 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;
+
+#if defined(PC)
+#undef PC
+#define PC pc
+#endif
+
+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
+
+ /* 5750 in BCM4785 */
+ #define SB_CORE_FLAG 0x20000000
+ /* 5750 in RGMII mode (BCM4785) */
+ #define RGMII_MODE_FLAG 0x40000000
+ /* connected to a ROBO switch */
+ #define ROBO_SWITCH_FLAG 0x80000000
+
+#ifdef BCM_WL_EMULATOR
+ LM_BOOL wl_emulate_rx;
+ LM_BOOL wl_emulate_tx;
+ void *wlc;
+#endif /*BCM_WL_EMULATOR*/
+
+ /* 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;
+
+#ifdef 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 */
+